ANTLR:如何解释这种识别Java代码后缀的语法的行为?

2022-09-03 03:04:58

一周前,我开始了以下项目:一个识别Java代码后缀的语法。

我使用Java()的官方语法作为基线,并开始添加一些规则。但是,这些新规则也引入了左递归,我也必须处理。ANTLRJava.g4

经过几天的工作,我有了以下代码。当我开始测试时,我注意到一些我仍然无法解释的不寻常的事情。当给定解析器告诉我的输入时,但是当我在规则的右手侧切换终端的顺序时,特别是如果我们将右手侧从更改为(终端移动到第一个位置),序列被接受。{ }no viable alternative at input '<EOF>'s2v2_1 | v2_2 | v2_3 ...v2_36 | v2_1 | v2_2 ...v2_36{ }

我的第一个想法是不会回溯,因为我注意到通过输入,解析器的第一个版本开始遵循规则,只是报告没有找到任何东西,并且不尝试考虑其他选项(这是我认为的,但也许不是真的),就像给出确切的肯定答案一样。Antlr{ }v2_3v2_36

但是,经过一些研究,我发现这实际上确实会回溯,但前提是其他一切都失败了。至少对于v3.3来说是正确的(在官方文件中阅读),但我想对于.现在我有点困惑。在这个项目上花了这么多时间之后,如果我不让它工作,我会感到非常可怕。有人可以给一些提示或其他东西吗?将不胜感激,谢谢。ANTLRANTLRv4

编辑

设法将问题隔离到

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 -> '{' '}'


答案 1

我认为你会发现它没有以你期望的方式回溯。原因是它找到了,然后期望看到一个,它找不到。因为它不会回溯,它不会找到你想要的替代方案。另一种方法是将可选的设置为可选,然后您不需要回溯。如下所示:{}v2_181v2_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
    ;

答案 2

推荐