Parsing AntlrGrammar.g4:::以下规则集是相互左递归的[子查询]

Parsing AntlrGrammar.g4:::以下规则集是相互左递归的[子查询],parsing,recursion,antlr4,context-free-grammar,top-down,Parsing,Recursion,Antlr4,Context Free Grammar,Top Down,在Antlr4中,据说支持直接左递归。我可以用下面给出的语法中的[expr]-规则来验证这一点。无论如何,ANTLR4的语法分析为[subquery]-规则抛出了错误,这是该语法中的第二个直接递归规则: AntlrGrammar.g4::: The following sets of rules are mutually left-recursive [subquery] 子查询规则也是左递归的。没有间接递归 grammar GrammarSubspace; DIGIT: [0-9]; IN

在Antlr4中,据说支持直接左递归。我可以用下面给出的语法中的[expr]-规则来验证这一点。无论如何,ANTLR4的语法分析为[subquery]-规则抛出了错误,这是该语法中的第二个直接递归规则:

AntlrGrammar.g4::: The following sets of rules are mutually left-recursive [subquery]
子查询规则也是左递归的。没有间接递归

grammar GrammarSubspace;

DIGIT: [0-9];
INT:  DIGIT ( DIGIT )*;
LETTER : [a-zA-Z_] ;
ID :  LETTER (LETTER|[0-9]|'_');

expr: expr '*' expr // precedence 4
| expr '+' expr // precedence 3
| INT // primary (precedence 2)
| ID // primary (precedence 1)
;

rowsetoperator: ( UNION (ALL)? | INTERSECT | MINUS );

subquery:
( 
    TERMINALVARIANT  
  | (subquery rowsetoperator subquery)+
  |  '('  subquery  ')'
) 
;

    TERMINALVARIANT: T E R M I N A L V A R I A N T; // Placeholder for another UNTERMINAL that resolves into all terminals without indirect recurrence to subquery

fragment A: [aA];    fragment B: [bB];    fragment C: [cC];    fragment D: [dD];
fragment E: [eE];    fragment F: [fF];    fragment G: [gG];    fragment H: [hH];
fragment I: [iI];    fragment J: [jJ];    fragment K: [kK];    fragment L: [lL];
fragment M: [mM];    fragment N: [nN];    fragment O: [oO];    fragment P: [pP];
fragment Q: [qQ];    fragment R: [rR];    fragment S: [sS];    fragment T: [tT];
fragment U: [uU];    fragment V: [vV];    fragment W: [wW];    fragment X: [xX];
fragment Y: [yY];    fragment Z: [zZ];
不同子查询代码的法律语法输入行为:

TERMINALVARIANT 
(TERMINALVARIANT) 
TERMINALVARIANT INTERSECT TERMINALVARIANT 
TERMINALVARIANT UNION ALL TERMINALVARIANT 
TERMINALVARIANT UNION TERMINALVARIANT 
TERMINALVARIANT MINUS TERMINALVARIANT 
(TERMINALVARIANT INTERSECT TERMINALVARIANT) 
(((((TERMINALVARIANT INTERSECT TERMINALVARIANT)))))
等等

递归具有TERMINALVARIANT并给出一个exit子句,因此递归是/可以是有限的。
为什么会出现这个错误?如何重写语法以避免它?

虽然这会很奇怪,但您是否尝试过删除
子查询中所有子规则的括号?也许在构建过程中,这会被转换成它自己的子规则,从而创建相互的左递归…谢谢你的想法。我测试了这个。实际上是之前的分支导致了错误。注释掉子句后,这将正确编译。子查询:(TERMINALVARIANT//|(子查询rowsetoperator子查询)+|'(“子查询”);好的,删除该规则中的
+
怎么样?因为由于左递归,无论如何都不需要它……这不是一个解决方案。这会改变语法。实际上,这是SQL语法的简化版本。在那里,您可以分类无限数量的子查询,例如使用UNION ALL。实际上,我解决了这个问题,但重写了语法,以减少一级左递归。实际上,Antrl4将行(子查询rowsetoperator subquery)+重写为两个独立的子规则,并在后面为其自身的间接左递归bann进行斗争。所以Antrl4中的直接左递归支持并不是在所有情况下都成立。是的,这是正确的。。。但是我很确定,如果您删除
+
,它不会改变语法。。。你试过了吗?唯一需要改变的是解析树,但您仍然可以正确解析相同的输入(在我看来,“新”的解析树实际上是输入的更好表示)