ANTLR4相互左递归语法

时间:2017-01-22 06:44:55

标签: recursion antlr grammar antlr4

我在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_expexp是相互递归的。

我考虑过将IDENTexp DOT IDENT添加到exp规则中,但在某些情况下,其他有效exp规则不适用,其中{{ 1}}是有效的。

编辑

我还有以下规则,它要求左表达式后跟赋值。

left_exp

由于正则表达式只是一个左表达式,如果后面跟着DOT IDENT,似乎我不能只添加

assign_statement: left_exp ( COLON IDENT )? EQUAL exp SEMI ;

到我的表达式定义,因为然后赋值将接受左侧的任何其他有效表达式,而不是仅接受其中一个。

1 个答案:

答案 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规则,然后应用我上面描述的算法。