如何报告antlr4中的语法歧义

时间:2016-10-03 08:25:42

标签: antlr antlr4

根据antlr4书(第159页),并使用语法Ambig.g4,可以通过以下方式报告语法歧义:

grun Ambig stat -diagnostics

或等效地,以代码形式:

parser.removeErrorListeners();
parser.addErrorListener(new DiagnosticErrorListener());
parser.getInterpreter().setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);

grun命令使用 antlr-4.5.3 正确报告模糊性。但是当我使用代码表单时,我没有得到歧义报告。这是命令跟踪:

$ antlr4 Ambig.g4   # see the book's page.159 for the grammar
$ javac Ambig*.java
$ grun Ambig stat -diagnostics < in1.txt # in1.txt is as shown on page.159
    line 1:3 reportAttemptingFullContext d=0 (stat), input='f();'
    line 1:3 reportAmbiguity d=0 (stat): ambigAlts={1, 2}, input='f();'
$ javac TestA_Listener.java
$ java TestA_Listener < in1.txt   # exits silently

TestA_Listener.java代码如下:

import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.atn.*; // for PredictionMode
import java.util.*;
public class TestA_Listener {
    public static void main(String[] args) throws Exception {
        ANTLRInputStream input = new ANTLRInputStream(System.in);
        AmbigLexer lexer = new AmbigLexer(input);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        AmbigParser parser = new AmbigParser(tokens);
        parser.removeErrorListeners(); // remove ConsoleErrorListener
        parser.addErrorListener(new DiagnosticErrorListener());
        parser.getInterpreter().setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);
        parser.stat();
    }
}

有人可以指出应该如何修改上面的java代码,打印歧义报告吗?

为完整起见,这里是代码Ambig.g4:

语法Ambig;

stat: expr ';'        // expression statement
    | ID '(' ')' ';'  // function call statement
    ;

expr: ID '(' ')'
    | INT
    ;

INT :   [0-9]+ ;
ID  :   [a-zA-Z]+ ;
WS  :   [ \t\r\n]+ -> skip ;

这是输入文件in1.txt:

f();

2 个答案:

答案 0 :(得分:1)

Antlr4是一个自上而下的解析器,因此对于给定的输入,解析匹配是明确的:

stat - &gt; expr - &gt; ID - &gt; ( - &gt; ) - &gt; stat(cnt'd) - &gt; ;

第二个stat alt是多余的,从未到达,不含糊。

要解决明显的冗余问题,可以使用谓词:

stat: e=expr {isValidExpr($e)}? ';'   #exprStmt
    | ID '(' ')' ';'                  #funcStmt
    ;

isValidExpr为false时,将评估函数语句替代。

答案 1 :(得分:0)

我等了几天让其他人发布他们的答案。经过几轮试验,我找到了答案:

应从上面的代码中删除以下行。然后我们得到grun给出的相同歧义报告。

parser.removeErrorListeners(); // remove ConsoleErrorListener