Как заставить мой атом парсера завершаться внутри правила, включая необязательные пробелы?
Я могу заставить атомы разбираться по отдельности, но когда я их цепью >>
парсер не хочет покидать :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
2 ответа
Это похоже на написание кода if (consume_value || consume_expression)
, ему удастся использовать значение и никогда не пытаться использовать выражение.
Parslet постарается сопоставить ваши варианты в том порядке, в котором они определены. Если он может потреблять часть входного потока без каких-либо конфликтов, это считается успешным совпадением. Как это удалось сопоставить value
нет смысла пытаться сопоставить subexpression
,
Итак, как ваш пример выражения 1 == 1
начинается с действительного значения, и вы сказали ему сначала попробовать сопоставить со значением, ((value | bool_operation)
) он пытается и добивается успеха. Произошла ошибка (Extra Input
) означает "Я успешно согласовал ввод, но, похоже, что-то осталось".
Вам необходимо сопоставить сложный случай с простым случаем, когда один является подмножеством другого. Таким образом, сложный может потерпеть неудачу, и вы вернетесь к простому случаю.
Изменить правило на rule(:subexpression) {(bool_operation | value).repeat(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) }