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

这就像写一些代码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 回答
1

subexpression规则应首先尝试匹配该bool_operation规则,然后再移动到value.

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

此外,您需要标记values,bool_operation以免它们被错误地合并。

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