ANTLR:如何解释这种识别Java代码后缀的语法行为?
一周前,我开始了以下项目:识别Java代码后缀的语法 我使用官方的ANTLR:如何解释这种识别Java代码后缀的语法行为?,java,antlr,grammar,Java,Antlr,Grammar,一周前,我开始了以下项目:识别Java代码后缀的语法 我使用官方的ANTLRJava语法(Java.g4)作为基准,并开始添加一些规则。然而,这些新规则也引入了左递归,我也必须处理左递归 经过几天的工作,我终于找到了工作。当我开始测试时,我注意到一些不寻常的事情,我仍然无法解释。当给定输入{}时,解析器告诉我在输入“时没有可行的替代方案,但是当我切换规则的右端的终端顺序s2,特别是如果我们将右端从v2|1 | v2|2 | v2|3…更改为v2|36 | v2|1 | v2|2…(终端v2_36
ANTLR
Java语法(Java.g4
)作为基准,并开始添加一些规则。然而,这些新规则也引入了左递归,我也必须处理左递归
经过几天的工作,我终于找到了工作。当我开始测试时,我注意到一些不寻常的事情,我仍然无法解释。当给定输入{}
时,解析器告诉我在输入“
时没有可行的替代方案,但是当我切换规则的右端的终端顺序s2
,特别是如果我们将右端从v2|1 | v2|2 | v2|3…
更改为v2|36 | v2|1 | v2|2…
(终端v2_36
移动到第一个位置),序列{}
被接受
<>我的第一个想法是,<代码> Antlr <代码>不回溯,因为我注意到,随着输入<代码> {} /代码>,解析器的第一个版本开始遵循规则<代码> V2Y3并报告没有找到任何东西,并且不尝试考虑其他选项(这就是我所想的,但可能不是真的)。就像v2\u36
一样,它给出了确切的肯定答案
但是,经过一些研究,我发现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->'{''}'
?我想你会发现它并不是以你期望的方式回溯。原因是它找到了{}
然后期望看到一个它没有找到的v2\u 181
。因为它没有回溯,所以它没有找到你想要的替代方案。替代方案是只将v2\u 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
;
我不知道你所说的“Java代码的后缀”是什么意思。如果我们有给定Java代码标记的序列
a[1..n]
,我们将后缀定义为序列a[j],a[j+1],…,a[n]
对于某些1,您使用ANTLR有什么原因吗?对于后缀解析,GLR解析器会容易得多,而且它将在大致线性时间内对LR(1)语法进行后缀解析,iirc。Grune&Jacobs中有一整章关于后缀解析(解析技术:实用指南)。谢谢你的回答。我选择ANTLR主要是因为它提供稳定的Java语法。我看了你提到的章节,注意到我定义后缀语法的方式与书中的定义相同。我也不确定是否存在LR(1)让Java应用这些算法。目前我有一个修改过的Java语法,我很确定它能识别后缀,但我很难找出错误所在。有没有错误输出?你有没有听到警告多个选项的消息?试试看:options{greedy=false;}
对于s2,这有帮助吗?