Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I was trying to create an let grammar my idea was somthing like this

start : let
let : "let" ID ("=" let)? in let | atom
atom : ANYTHING | "(" let ")"
ID : /[a-z]+/

The idea is to parse expressions like this let A = B in C or let A in B or both mixed let f = let x in x + 1 in f(1). I also want to support parenthesis to disambiguate like let A = (let b in b + 1) in A(1) + 1

I'm using lark, whith LALR parser, but I was struggling with the grammar, and can't define an unambiguous grammar for this

I tried


from lark import Lark, Transformer as LarkTransformer


grammar = """
    start : expr
    expr : LET ID (EQUAL exprcont)? IN exprcont | exprcont
    exprcont : ANYTHING | LPAR expr RPAR | expr
    ANYTHING.0 : /.+/
    LET : "let"
    IN : "in"
    ID : /[a-z_][a-z0-9_]*/
    EQUAL : "="
    LPAR.10 : "("
    RPAR.10 : ")"

    %import common.WS
    %ignore WS
"""

let_parser = Lark(grammar, parser="lalr")

print(let_parser.parse("let a = 1 in let b = 2 in a + b").pretty())

But I got lot's of reduce reduce errors

Traceback (most recent call last):
  File "/Users/gecko/code/lampycode/letparser.py", line 55, in <module>
    let_parser = Lark(grammar, parser="lalr")
  File "/Users/gecko/.pyenv/versions/lampy/lib/python3.9/site-packages/lark/lark.py", line 339, in __init__
    self.parser = self._build_parser()
  File "/Users/gecko/.pyenv/versions/lampy/lib/python3.9/site-packages/lark/lark.py", line 373, in _build_parser
    return self.parser_class(self.lexer_conf, parser_conf, options=self.options)
  File "/Users/gecko/.pyenv/versions/lampy/lib/python3.9/site-packages/lark/parser_frontends.py", line 145, in __init__
    self.parser = LALR_Parser(parser_conf, debug=debug)
  File "/Users/gecko/.pyenv/versions/lampy/lib/python3.9/site-packages/lark/parsers/lalr_parser.py", line 17, in __init__
    analysis.compute_lalr()
  File "/Users/gecko/.pyenv/versions/lampy/lib/python3.9/site-packages/lark/parsers/lalr_analysis.py", line 304, in compute_lalr
    self.compute_lalr1_states()
  File "/Users/gecko/.pyenv/versions/lampy/lib/python3.9/site-packages/lark/parsers/lalr_analysis.py", line 279, in compute_lalr1_states
    raise GrammarError('

'.join(msgs))
lark.exceptions.GrammarError: Reduce/Reduce collision in Terminal('$END') between the following rules: 
    - <exprcont : expr>
    - <start : expr>

Reduce/Reduce collision in Terminal('IN') between the following rules: 
    - <expr : exprcont>
    - <expr : LET ID IN exprcont>

Reduce/Reduce collision in Terminal('RPAR') between the following rules: 
    - <expr : exprcont>
    - <expr : LET ID IN exprcont>

Reduce/Reduce collision in Terminal('$END') between the following rules: 
    - <expr : exprcont>
    - <expr : LET ID IN exprcont>

Reduce/Reduce collision in Terminal('IN') between the following rules: 
    - <expr : exprcont>
    - <expr : LET ID EQUAL exprcont IN exprcont>

Reduce/Reduce collision in Terminal('RPAR') between the following rules: 
    - <expr : exprcont>
    - <expr : LET ID EQUAL exprcont IN exprcont>

Reduce/Reduce collision in Terminal('$END') between the following rules: 
    - <expr : exprcont>

I have no idea how to define this grammar, the idea is so simple let : "let" ID ("=" let)? "in" let | atom any ideas?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
263 views
Welcome To Ask or Share your Answers For Others

1 Answer

I think the problem is

start : expr
    expr : ... | exprcont
    exprcont : ... | expr

This loop means that your grammar is ambiguous.

Can you get rid of the loop?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...