sve*_*sve 18 java grammar antlr
一周前,我开始了以下项目:一种识别Java代码后缀的语法.
我使用ANTLRJava(Java.g4)的官方语法作为基线并开始添加一些规则.但是,这些新规则还引入了左递归,我也不得不处理.
经过几天的工作,我得到了以下代码.当我开始测试时,我注意到一些不寻常的东西,我仍然无法解释.当给出输入时{ },解析器告诉我no viable alternative at input '<EOF>',但当我在规则的右侧切换终端的顺序时s2,特别是如果我们将右手侧v2_1 | v2_2 | v2_3 ...改为v2_36 | v2_1 | v2_2 ...(终端v2_36移动到第一个位置),顺序{ }被接受.
我的第一个想法是Antlr没有回溯,因为我注意到在输入{ }时,解析器的第一个版本开始遵循规则v2_3,只是报告没有找到任何东西,并且没有尝试考虑其他选项(这是我的想法,但也许不是真的)这样的确v2_36给出了肯定的答案.
但是,经过一些研究,我发现ANTLR实际上是回溯,但只有在其他一切都失败的情况下.至少对于v3.3来说也是如此(在官方ANTLR文件中阅读),但我想这也是如此v4.现在我有点困惑.在这个项目上花了这么多个小时后,如果我不能让它工作,我会觉得非常糟糕.有人可以提供某种提示吗?非常感谢,谢谢.
编辑
管理将问题隔离到
grammar Java;
@parser::members {String ruleName; }
start : compilationUnitSuf EOF;
compilationUnitSuf
: {ruleName = "typeDeclarationSuf"; } s2
;
s2: '{' '}' v2_81 | '{' '}';
v2_81 : {ruleName.equals("enumBodyDeclarationsSuf")}? t173 | t173 '}';
t173: '}' | '{'*;
LBRACKET: '{';
RBRACKET: '}';
WS : [ \t\r\n\u000C]+ -> skip
;
Run Code Online (Sandbox Code Playgroud)
那么为什么预测算法建议我遵循s2 -> v'{' '}' v2_81 -> ...而不是s2 -> '{' '}'?
我想你会发现它并没有按照你期望的方式回溯。原因是它找到了{},然后期望看到 a v2_181,但它没有找到。因为它不会回溯,因此不会找到您想要的替代方案。另一种方法是仅将其设为v2_181可选,然后就不需要回溯。像下面这样:
grammar Java;
@parser::members {String ruleName; }
start : compilationUnitSuf EOF;
compilationUnitSuf
: {ruleName = "typeDeclarationSuf"; } s2
;
s2: '{' '}' v2_81?;
v2_81 : {ruleName.equals("enumBodyDeclarationsSuf")}? t173 | t173 '}';
t173: '}' | '{'*;
LBRACKET: '{';
RBRACKET: '}';
WS : [ \t\r\n\u000C]+ -> skip
;
Run Code Online (Sandbox Code Playgroud)