compiler-construction - ANTLR if-else 歧义错误

标签 compiler-construction antlr grammar antlr4

我正在尝试为一种简单的编程语言创建 ANTLR 语法。

它有类似 C 语言的 if 语句:

program
    : statement* EOF
    ;

statement
    : block                                                                 # blockStatement
    | SEMI                                                                  # emptyStatement
    | assignment                                                            # assignmentStatement
    | declaration                                                           # variableDeclarationStatement
    | 'if' parExpression ifBody=statement ('else' elseBody=statement)?      # ifStatement
    ..........
    ;

block
    : '{' statement* '}'
    ;

expression
    : literal                                                           # literalExpression
    | Identifier                                                        # variableReference
    ..........
    ;

parExpression : '(' expression ')';

assignment : Identifier assignmentOp expression SEMI;

SEMI : ';';

Identifier : (LETTER | '_') (LETTER | DIGIT | '_')* ;

它似乎工作正常但是当我使用 DiagnosticErrorListener 运行时我得到错误

reportAttemptingFullContext d=1 (statement), input='else', Line 3:0
reportContextSensitivity d=1 (statement), input='else', Line 3:0
reportAttemptingFullContext d=1 (statement), input='else', Line 5:0
reportContextSensitivity d=1 (statement), input='else', Line 5:0

像这样的代码

if (flag1)
    x = 42;
else if (flag2)
    x = 43;
else
    x = 44;

我不确定我是否理解这里有什么问题,但正如我在其他情况下的理解(例如 if (a) if (b) ... else ...)这个语法可能是模棱两可的。

我该如何解决?

最佳答案

这就是所谓的悬空问题。 解析文本:

      if (flag1)
         if (flag2) x=2;
            else x=3;

可以通过两种方式匹配你的语法:

      if (flag1)
         if (flag2) x=2;
         else x=3; // belongs to if (flag2)

      if (flag1)
         if (flag2) x=2;
      else x=3; // belongs to if (flag1)

因为您将 else 子句设为可选匹配项。这意味着语法规则提供了有歧义的匹配,这是您从 ANTLR 收到的投诉。

你想要的是强制 else 匹配最近的未闭合 if 语句;这是大多数编程语言中 if ... else 的解释。

必须修改语句解析规则:

statement
    : non_if_statement
    | if_statement
;

if_statement
    : 'if' parExpression 
         ifBody= ( non_if_statement 'else' elseBody=statement
                   | if_statement )
;  

non_if_statement
    :block                                                                 
    | SEMI
    | assignment 
    | declaration
    ..........
;

这写起来有点笨拙,但应该可以。

许多解析器生成器允许您在遇到标记时“强制转换”。如果您强制改变原始语法中的 else 关键字,您将获得相同的效果。如果确实可以的话,我不知道如何为 ANTLR 说这些。

[Lischke 说如果你忽略这个错误,你仍然可以用你原来的语法得到正确的结果。我认为他是对的;那是因为解析器生成器被迫选择两种解释之一作为它接受的解释。]

关于compiler-construction - ANTLR if-else 歧义错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41585107/

相关文章:

sql - 为什么 SQL 对子句顺序严格?

java - 插入 Java 编译器

c++ - 同时使用参数重载和返回类型重载

optimization - LLVM中Loop的getSmallConstantTripCount方法的使用

java - 使用 ANTLR 将非贪婪序列作为字符串获取

c - 有没有办法对 C 代码进行句法/语义差异?

java - 为什么不摆脱 JVM?

python - ANTLR 语法后缀

具有冲突标记的 ANTLR 行为

parsing - 如何使用 perl6 语法创建解析树?