Я пытаюсь написать парсер для простого языка:
parser = Lark("""
?start: arithmetic_expr | boolean_expr
// relational operation
?rel_op : arithmetic_expr ("<" | ">" | "==" | "!=") arithmetic_expr
// boolean expression
?boolean_expr: bool_term
| boolean_expr "or" bool_term
?bool_term: bool_atom
| bool_term "and" bool_atom
?bool_atom: "true"
| "false"
| "!" bool_atom
| rel_op
| ID
| "(" boolean_expr ")"
// arithmetic expression
?arithmetic_expr: product
| arithmetic_expr "+" product
| arithmetic_expr "-" product
?product: atom
| product "*" atom
| product "/" atom
?atom: NUMBER
| "-" atom
| ID
| "(" arithmetic_expr ")"
%import common.CNAME -> ID
%import common.NUMBER
""", parser='lalr', start='start')
Когда я его запускаю, я получаю следующую ошибку:
lark.exceptions.GrammarError: Reduce/Reduce collision in Terminal('RPAR') between the following rules:
- <bool_atom : ID>
- <atom : ID>
Я понимаю, что это Это происходит потому, что если мы представим, что анализатор был построен без ошибки, а затем записали parser.parse('foo')
, то и arithmetic_expr
, и boolean_expr
были бы "правильными" производными. Кроме того, как вы можете видеть, я использую LALR, который является строго детерминированным c алгоритмом и не может обрабатывать неоднозначности.
Итак, мой вопрос, как я могу сделать эту грамматику однозначной? Я не могу найти решение.