Antlr4 说我的规则是相互递归的

Antlr4 saying my rule is mutually left recursive with itself

我正在做一个任务,我们为一种简单的语言制作一个编译器,我们正在为 Java 使用 ANTLR4。在终于让我的语法工作之后,我不得不向语言解析器添加一些 Java 代码来构建 AST。这就是我感到困惑的地方。如果规则相互递归,Antlr 应该会抛出错误,据我所知,当一条规则引用另一条规则而第二条规则引用第一条规则时,就会发生这种情况。我不明白的是为什么 antlr 告诉我我的规则是相互递归的?这是我不断收到的错误消息:error(119): PrevParser.g4::: The following sets of rules are mutually left-recursive [expr]。我环顾四周,似乎没有人遇到这个问题。我确实发现有人说互左递归规则的共同点是它们的第一个标记是另一个规则,所以我尝试在规则标记之前放置一个常规 . 标记,现在它神奇地编译了。当规则仅引用自身时,为什么要这样做?这是导致问题的部分代码:

expr returns [AstExpr ast] 
     : (VOID_CONST {$ast = new AstAtomExpr(loc($VOID_CONST), AstAtomExpr.Type.VOID, $VOID_CONST.text);}) 
     | (INT_CONST {$ast = new AstAtomExpr(loc($INT_CONST), AstAtomExpr.Type.INT, $INT_CONST.text);}) 
     | (CHAR_CONST {$ast = new AstAtomExpr(loc($CHAR_CONST), AstAtomExpr.Type.CHAR, $CHAR_CONST.text);}) 
     | (POINT_CONST {$ast = new AstAtomExpr(loc($POINT_CONST), AstAtomExpr.Type.POINTER, $POINT_CONST.text);}) 
     | (STRING_CONST {$ast = new AstAtomExpr(loc($STRING_CONST), AstAtomExpr.Type.STRING, $STRING_CONST.text);}) 
     | (BOOL_CONST {$ast = new AstAtomExpr(loc($BOOL_CONST), AstAtomExpr.Type.BOOL, $BOOL_CONST.text);}) 
     | (IDENTIFIER {$ast = new AstNameExpr(loc($IDENTIFIER), $IDENTIFIER.text);}) 
     | ( e1=expr O_OKLEPAJ e2=expr O_ZAKLEPAJ {$ast = new AstArrExpr(loc($e1.ast, $O_ZAKLEPAJ), $e1.ast, $e2.ast);} ) 
;

错误出现在规则 expr 将自身引用为 e1=expr 的最后一行。 如果我将规则更改为如下所示: ( DOT e1=expr O_OKLEPAJ e2=expr O_ZAKLEPAJ {$ast = new AstArrExpr(loc($e1.ast, $O_ZAKLEPAJ), $e1.ast, $e2.ast);} ) 整个过程都会正常编译。有谁知道我该如何解决这个问题?感谢任何帮助。

我以前在 Whosebug 上看过这个(但现在找不到了)。这似乎是 left-recursive expr 之前的括号引起的错误。只需删除括号(无论如何都是多余的)。

所以不是:

expr returns [AstExpr ast] 
 : ...
 | ( e1=expr O_OKLEPAJ e2=expr O_ZAKLEPAJ {$ast = new AstArrExpr(loc($e1.ast, $O_ZAKLEPAJ), $e1.ast, $e2.ast);} )
 ;

而是这个:

expr returns [AstExpr ast] 
 : ...
 | e1=expr O_OKLEPAJ e2=expr O_ZAKLEPAJ {$ast = new AstArrExpr(loc($e1.ast, $O_ZAKLEPAJ), $e1.ast, $e2.ast);}
 ;