17

一周前,我开始了以下项目:一种识别 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 -> '{' '}'

4

1 回答 1

1

我认为您会发现它并没有以您期望的方式回溯。原因是它找到了{},然后期望看到 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
    ;
于 2013-10-20T13:18:01.967 回答