我可以单独解析原子,但是当我使用>>
链接它们时,解析器似乎不想离开: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
答案 0 :(得分:1)
subexpression
规则应首先尝试匹配bool_operation
规则,然后再转到value
。
rule(:subexpression) {(bool_operation | value).repeat(1)}
此外,您需要在value
中标记bool_operation
,以便它们不会被错误地合并。
rule(:bool_operation) { value.as(:first) >> bool_comparison >> value.as(:second) }
答案 1 :(得分:1)
就像编写一些代码if (consume_value || consume_expression)
一样,它会成功使用该值,并且永远不会尝试使用该表达式。
Parslet会尝试按照定义的顺序匹配您的选项。如果它可以消耗一些输入流而没有任何冲突,那么它被认为是成功的匹配。在成功匹配value
后,它没有理由尝试匹配subexpression
。
因此,您的示例表达式1 == 1
以有效的&#34;值&#34;开头。并且你告诉它首先尝试匹配值,((value | bool_operation)
)它尝试并成功。生成的错误(Extra Input
)表示&#34;我成功匹配输入,但似乎还有剩余的东西。&#34;
在简单情况之前,当一个是另一个的子集时,您需要匹配复杂的情况。这样复杂的一个可能会失败,你回到简单的情况。
将规则更改为rule(:subexpression) {(bool_operation | value).repeat(1)}
。