Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
ANTLR:如何解释这种识别Java代码后缀的语法行为?_Java_Antlr_Grammar - Fatal编程技术网

ANTLR:如何解释这种识别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

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

我使用官方的
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,这有帮助吗?