一周前,我启动了以下项目:识别Java代码后缀的语法。
我使用了官方的ANTLR
语法(Java.g4
)作为基准,并开始添加一些规则。然而,这些新规则也引入了左递归,这也是我不得不处理的。
经过几天的工作,我有了following code。当我开始测试的时候,我注意到了一些不寻常的东西,我仍然无法解释。当给定输入{ }
时,解析器告诉我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
;
那么为什么预测算法建议我遵循s2 -> v'{' '}' v2_81 -> ...
而不是s2 -> '{' '}'
呢
发布于 2013-10-20 21:18:02
我想你会发现它并不是以你所期望的方式倒退。原因是它找到了{}
,然后希望看到一个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
;
https://stackoverflow.com/questions/18496826
复制相似问题