Parsing ANTLR中的上下文无关语法为if语句抛出错误

Parsing ANTLR中的上下文无关语法为if语句抛出错误,parsing,programming-languages,antlr,grammar,lexical-analysis,Parsing,Programming Languages,Antlr,Grammar,Lexical Analysis,我用ANTLR为类似Java的if语句编写了语法,如下所示: if_statement : 'if' expression (statement | '{' statement+ '}') ('elif' expression (statement | '{' statement+ '}'))* ('else' (statement | '{' statement+ '}'))? ; 我已经正确地实现了“语句”和“表达式”,但

我用ANTLR为类似Java的if语句编写了语法,如下所示:

if_statement
    :   'if' expression
        (statement | '{' statement+ '}')
        ('elif' expression (statement | '{' statement+ '}'))*
        ('else' (statement | '{' statement+ '}'))?
    ;
我已经正确地实现了“语句”和“表达式”,但是if_语句给了我以下错误:

Decision can match input such as "'elif'" using multiple alternatives: 1, 2
As a result, alternative(s) 2 were disabled for that input
 |---> ('elif' expression (statement | '{' statement+ '}'))*

warning(200): /OptDB/src/OptDB/XL.g:38:9: 
Decision can match input such as "'else'" using multiple alternatives: 1, 2
As a result, alternative(s) 2 were disabled for that input
 |---> ('else' (statement | '{' statement+ '}'))?
“elif”和“else”块似乎有问题。 基本上,我们可以有0个或更多的“elif”块,所以我用* 我们也可以有0或1个“else”块,所以我用?来包装它

是什么导致了这个错误



========================================================================

我还将介绍“表达式”和“语句”的实现:

语句
:赋值语句
|if_语句
|while_语句
|FORU声明
|函数调用语句
;
学期
:标识符
|“(“表达式”)”
|整数
|字符串文字
|字符文字
|标识符“(“actualParameters”)”
;
否定
:“不是”*术语
;
一元
:(“+”|“-”)*否定
;
骡子
:一元((“*”|“/”|“mod”)一元)*
;
添加
:mult((“+”|“-”)mult)*
;
关系
:添加((“=”|“/=”|“)添加)*
;
表达
:关系((‘and’|‘or’)关系)*
;
实际参数
:表达式(“,”表达式)*
;

因为您的语法允许语句块,而不必按
{…}
分组,所以您有一个典型的歧义

简短的解释。输入:

if expr1 if expr2 ... else ...
可以解析为:

解析1 但也同样如此:

解析2 要消除歧义,请更改:

(statement | '{' statement+ '}')
进入:

通过查看
if
else所属的大括号,或添加以强制解析器选择Parse 1,可以清楚地看到:

if_statement
 : 'if' expression statement_block
   (('elif')=> 'elif' expression statement_block)*
   (('else')=> 'else' statement_block)?
 ;

statement_block
 : '{' statement* '}'
 | statement
 ;

+1:经典问题,经典解决方案,优秀答案,包括规范参考。我希望我能添加一些东西。第三种解决方案是使用Java语言规范中的
NoShortIf
规则,如图所示(搜索以
NoShortIf
结尾的规则)。
if expr1
    if expr2
        ...
else
    ...
(statement | '{' statement+ '}')
'{' statement+ '}'
// or
'{' statement* '}'
if_statement
 : 'if' expression statement_block
   (('elif')=> 'elif' expression statement_block)*
   (('else')=> 'else' statement_block)?
 ;

statement_block
 : '{' statement* '}'
 | statement
 ;