在if语句的ANTLR抛出错误中的Context Free Grammar

时间:2014-04-10 03:02:20

标签: parsing programming-languages antlr grammar lexical-analysis

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

if_statement
    :   'if' expression
        (statement | '{' statement+ '}')
        ('elif' expression (statement | '{' statement+ '}'))*
        ('else' (statement | '{' statement+ '}'))?
    ;

我已经实施了#34;声明"和"表达"正确,但if_statement给了我以下错误:

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"和"否则"块。 基本上,我们可以有0或更多" elif"块,所以我用*包裹它们 我们也可以有0或1"否则"块,所以我用它包裹它。?

什么似乎导致错误?



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

我还将"表达式"的实现放在一起。和#34;陈述":

statement
    :   assignment_statement
    |   if_statement
    |   while_statement
    |   for_statement
    |   function_call_statement
    ;


term
    :   IDENTIFIER
    |   '(' expression ')'
    |   INTEGER
    |   STRING_LITERAL
    |   CHAR_LITERAL
    |   IDENTIFIER '(' actualParameters ')'
    ;

negation
    :   'not'* term
    ;

unary
    :   ('+' | '-')* negation
    ;

mult
    :   unary (('*' | '/' | 'mod') unary)*
    ;

add
    :   mult (('+' | '-') mult)*
    ;

relation
    :   add (('=' | '/=' | '<' | '<=' | '>=' | '>') add)*
    ;

expression
    :   relation (('and' | 'or') relation)*
    ;

actualParameters
    :   expression (',' expression)*
    ;

1 个答案:

答案 0 :(得分:1)

因为你的语法允许语句块而不是按{...}分组,所以你自己有一个经典的dangling else歧义。

简短说明。输入:

if expr1 if expr2 ... else ...

可以解析为:

解析1

if expr1
    if expr2
        ...
    else
        ...

但也是这样:

解析2

if expr1
    if expr2
        ...
else
    ...

要消除歧义,可以改变:

(statement | '{' statement+ '}')

成:

'{' statement+ '}'
// or
'{' statement* '}'

通过查看if else所属的大括号,或添加a predicate以强制解析器选择解析1 ,这一点很清楚:

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

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