我在StackOverflow上已经阅读了很多关于LL(k)解析器中相互左递归问题的问题。我找到了删除左递归的通用算法:
A : Aa | b ;
变为
A : bR ;
R : (aA)? ;
然而,我无法弄清楚如何将它应用于我的情况。我有
left_exp: IDENT | exp DOT IDENT ;
exp : handful
| of
| other rules
| left_exp ;
其他一些规则"都包含常规递归,例如exp : exp PLUS exp
等,并且没有问题。问题在于left_exp
和exp
是相互递归的。
我考虑过将IDENT
和exp DOT IDENT
添加到exp
规则中,但在某些情况下,其他有效exp
规则不适用,其中{{ 1}}是有效的。
编辑
我还有以下规则,它要求左表达式后跟赋值。
left_exp
由于正则表达式只是一个左表达式,如果后面跟着DOT IDENT,似乎我不能只添加
assign_statement: left_exp ( COLON IDENT )? EQUAL exp SEMI ;
到我的表达式定义,因为然后赋值将接受左侧的任何其他有效表达式,而不是仅接受其中一个。
答案 0 :(得分:1)
我申请的方法通常是这样的:
A: Aa | b;
变为:
A: b (a)*;
或者一般而言:所有没有左递归的alts后跟所有具有无限发生的(移除的)左递归的alts(通过kleene运算符表示)。例如:
A: Aa | Ab | c | d | Ae;
变为:
A:(c | d)(a | b | e)*;
您可以通过不断替换A:
来轻松检查A: Aa | b;
A: (Aa | b)a | b;
A: Aaa | ba | b;
A: (Aa | b)aa | ba | b;
A: Aaaa | baa | ba | b;
等
在你的例子中,你有一个间接的左递归(通过2个规则)。这是ANTLR不接受的。解决方案是将alts从left_exp
移动到exp
规则,然后应用我上面描述的算法。