[英]Generate C code for sympy expression “e1 op e2” where op is an arithmetic comparison operator
[英]Unambiguous gramar for let e1 in e2
我试图创建一个 let 语法我的想法是这样的
start : let
let : "let" ID ("=" let)? in let | atom
atom : ANYTHING | "(" let ")"
ID : /[a-z]+/
这个想法是解析这样的表达式let A = B in C
或let A in B
或两者混合let f = let x in x + 1 in f(1)
。 我还想支持括号来消除歧义,例如let A = (let b in b + 1) in A(1) + 1
我正在使用 lark,带有 LALR 解析器,但我在语法上苦苦挣扎,无法为此定义明确的语法
我试过了
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())
但我有很多减少减少错误
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('\n\n'.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>
我不知道如何定义这个语法,想法很简单let: "let" ID ("=" let)? "in" let | atom
let: "let" ID ("=" let)? "in" let | atom
let: "let" ID ("=" let)? "in" let | atom
有什么想法吗?
我认为问题是
start : expr
expr : ... | exprcont
exprcont : ... | expr
这个循环意味着你的语法不明确。
你能摆脱循环吗?
如果您想使用ANYTHING
之类的终端,请不要使用 lalr。 使用earley
。 (即使那样它仍然会产生问题)
但这实际上并不是造成这些错误的原因。 问题是expr
和exprcont
中的相互递归。 您可以删除exprcont
中的expr
:
exprcont : ANYTHING | LPAR expr RPAR
但这仍然行不通。 (除非你使用parser='earley'
和lexer='dynamic_complete'
。但这会很慢)。 您必须重新设计语法以不包含ANYTHING
终端。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.