I'm trying to write a parser for a simple language:
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')
When I run it, I get the following error:
lark.exceptions.GrammarError: Reduce/Reduce collision in Terminal('RPAR') between the following rules:
- <bool_atom : ID>
- <atom : ID>
I understand that this is happening because, if we imagine that the parser was built without an error, and then wrote parser.parse('foo')
, both arithmetic_expr
and boolean_expr
would be "correct" derivations. Also, as you can see I'm using LALR which is a strictly deterministic algorithm and can't handle ambiguities.
So my question is, how can I make this grammar unambiguous? I can't seem to find the solution.