简体   繁体   English

ANTLR4 互左递归文法

[英]ANTLR4 mutual left recursion grammar

I have read many questions here on StackOverflow about mutual left-recursion issues in LL(k) parsers.我在 StackOverflow 上阅读了很多关于 LL(k) 解析器中相互左递归问题的问题。 I found the general algorithm for removing left-recursion:我找到了去除左递归的通用算法:

A : Aa | b ;

becomes变成

A : bR ;
R : (aA)? ;

However, I cannot figure out how to apply it to my situation.但是,我无法弄清楚如何将其应用于我的情况。 I have我有

left_exp: IDENT | exp DOT IDENT ;
exp     : handful
        | of
        | other rules
        | left_exp ;  

The "handful of other rules" all contain regular recursion, such as exp : exp PLUS exp , etc. and have no issues. “少数其他规则”都包含常规递归,例如exp : exp PLUS exp等,没有问题。 The issue is with left_exp and exp being mutually recursive.问题在于left_expexp是相互递归的。

I thought about just adding IDENT and exp DOT IDENT to the exp rules, but there are some situations where the other valid exp rules do not apply, where left_exp would be valid.我想过将IDENTexp DOT IDENT添加到exp规则中,但在某些情况下,其他有效的exp规则不适用,而left_exp将有效。

EDIT编辑

I also have the following rule, which calls for a left expression followed by assignment.我还有以下规则,它要求左表达式后跟赋值。

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

Since a regular expression is only a left expression if it is followed by DOT IDENT, it seems that I can't just add由于正则表达式如果后跟 DOT IDENT 则只是左表达式,因此似乎我不能只添加

| IDENT
| exp DOT IDENT

to my expression definition, because then assignment would accept any other valid expression on the left side, rather than only one of those two.到我的表达式定义,因为然后赋值将接受左侧的任何其他有效表达式,而不仅仅是这两个表达式中的一个。

The approach I apply usually goes like this:我应用的方法通常是这样的:

A: Aa | b;

becomes:变成:

A: b (a)*;

Or in general: all alts without left recursion followed by all alts with a (removed) left recursion with unlimited occurences (expressed via the kleene operator).或者一般来说:所有没有左递归的alts,然后是所有具有(删除)左递归的alts,出现次数不受限制(通过kleene算子表示)。 Example:例子:

A: Aa | Ab | c | d | Ae;

becomes:变成:

A: (c | d) (a | b | e)*; A: (c | d) (a | b | e)*;

You can check this easily by continuosly replacing A:您可以通过不断替换 A 来轻松检查这一点:

A: Aa | b;
A: (Aa | b)a | b;
A: Aaa | ba | b;
A: (Aa | b)aa | ba | b;
A: Aaaa | baa | ba | b;

etc.等等。

In your example however you have an indirect left recursion (via 2 rules).但是,在您的示例中,您有一个间接左递归(通过 2 个规则)。 This is not accepted by ANTLR.这不被 ANTLR 接受。 A solution is to move the alts from left_exp to the exp rule and then apply the algorithm I described above.一个解决方案是将 alts 从left_exp移动到exp规则,然后应用我上面描述的算法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM