0

アトムを個別に解析することはできますが、パーサーを使用してそれらを連鎖させると、ルール>>を離れたくないようです。:integer

次のエラーが表示されます。

Extra input after last repetition at line 1 char 2.
`- Expected one of [VALUE, BOOL_OPERATION] at line 1 char 2.
   |- Expected at least 1 of [0-9] at line 1 char 2.
   |  `- Failed to match [0-9] at line 1 char 2.
   `- Failed to match sequence (VALUE BOOL_COMPARISON VALUE) at line 1 char 2.
      `- Expected at least 1 of [0-9] at line 1 char 2.
         `- Failed to match [0-9] at line 1 char 2.

次のコードを実行する場合:

require 'minitest/autorun'
require 'parslet'
require 'parslet/convenience'

class ExpressionParser < Parslet::Parser
  # Single chars
  rule(:space) { match('\s').repeat(1) }
  rule(:space?) { space.maybe }

  # Values
  rule(:integer) { match('[0-9]').repeat(1).as(:integer) } 
  rule(:value) { integer }

  # Operators
  rule(:equals) { str('=').repeat(1,2).as(:equals) }     
  rule(:bool_comparison) { space? >> equals >> space?}

  # Grammar  
  rule(:bool_operation) { value >> bool_comparison >> value }      
  rule(:subexpression) {(value | bool_operation).repeat(1)}

  root(:subexpression)
end

class TestExpressions < Minitest::Unit::TestCase
  def setup
    @parser = ExpressionParser.new
  end

  def test_equals
    assert @parser.value.parse("1")
    assert @parser.bool_comparison.parse("==")
    assert @parser.parse_with_debug("1 == 1")
  end
end
4

2 に答える 2

1

ルールは、に移動する前に、まずルールとsubexpressionの一致を試みる必要があります。bool_operationvalue

rule(:subexpression) {(bool_operation | value).repeat(1)}

また、誤ってマージされないように、valueにタグを付ける必要があります。bool_operation

rule(:bool_operation) { value.as(:first) >> bool_comparison >> value.as(:second) }
于 2014-11-23T23:02:17.743 に答える
1

コードを書くようなものif (consume_value || consume_expression)で、値を消費することに成功し、式を消費しようとはしません。

Parslet は、定義されている順序でオプションを照合しようとします。競合することなく入力ストリームの一部を消費できる場合、一致は成功したと見なされます。マッチングに成功したので、マッチングvalueを試みる理由はありませんsubexpression

したがって、式の例1 == 1は有効な「値」で始まり、最初に値との照合を試みるように指示しているため、 ( (value | bool_operation)) 試行して成功します。生成されたエラー ( Extra Input) は、「入力は正常に一致しましたが、何かが残っているようです」という意味です。

一方が他方のサブセットである場合、単純なケースの前に複雑なケースを一致させる必要があります。そうすれば、複雑なものが失敗する可能性があり、単純なケースに戻ります。

ルールを に変更しrule(:subexpression) {(bool_operation | value).repeat(1)}ます。

于 2014-11-24T00:40:07.680 に答える