一周前,我开始了以下项目:一种识别 Java 代码后缀的语法。
我以 Java ( ) 的官方ANTLR
语法为Java.g4
基准,开始添加一些规则。然而,这些新规则也引入了我也必须处理的左递归。
经过几天的工作,我得到了以下代码。当我开始测试时,我发现了一些我仍然无法解释的异常情况。当给定输入时{ }
,解析器告诉我no viable alternative at input '<EOF>'
,但是当我在规则的右手边切换终端的顺序时s2
,特别是如果我们将右手边从v2_1 | v2_2 | v2_3 ...
to v2_36 | v2_1 | v2_2 ...
(终端v2_36
移动到第一个位置),序列{ }
被接受。
我的第一个想法是Antlr
不会回溯,因为我注意到随着输入{ }
,解析器的第一个版本开始遵循规则v2_3
,只是报告没有找到任何东西并且不尝试考虑其他选项(这就是我的想法,但也许不是true) 就像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
;
那么为什么预测算法建议我遵循s2 -> v'{' '}' v2_81 -> ...
而不是s2 -> '{' '}'
?