ANTLR未报告的语法歧义 [英] Ambiguity in grammar not reported by ANTLR

查看:13
本文介绍了ANTLR未报告的语法歧义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

谁能帮我理解ANTLR为什么不报告此语法中的歧义问题?

https://github.com/NASA-SW-VnV/fret/blob/master/fret-electron/support/NuSMVParser/NuSMV.g4#L61-L78

simpleExprltlExpr中的规则以这样一种方式重复,即始终有两个替代路径来构建任何内容,并对其应用andorxorimpliesequivnot运算符或一些带括号的表达式。

当我对它运行ANTLR时,我预计会看到一条警告,但我什么也得不到(这意味着生成了一个解析器和一个词法分析器)。

推荐答案

由于ANTLR以先到先得的方式匹配解析器规则,因此第一个匹配的规则获胜(解析器不关心是否可以以多种方式解析某些输入)。

若要显示模糊性,您可以附加一个自定义错误侦听器并覆盖其reportAmbiguity方法,并将预测模式设置为PredictionMode.LL_EXACT_AMBIG_DETECTION

如果statement中的print_statement_1print_statement_2替换项不明确,请使用以下语法:

grammar T;

parse
 : statement* EOF
 ;

statement
 : print_statement_1
 | print_statement_2
 ;

print_statement_1
 : 'print' expr
 ;

print_statement_2
 : 'print' expr
 ;

expr
 : INT
 ;

INT
 : [0-9]+
 ;

SPACE
 : [ 	
] -> skip
 ;

ANY
 : .
 ;

如果您运行以下代码:

public static void main(String[] args) {
    
  String source= "print 42";
  TLexer lexer = new TLexer(CharStreams.fromString(source));
  TParser parser = new TParser(new CommonTokenStream(lexer));

  parser.getInterpreter().setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);

  parser.addErrorListener(new BaseErrorListener() {
    // The code below is from org.antlr.v4.runtime.DiagnosticErrorListener
    @Override
    public void reportAmbiguity(Parser recognizer, DFA dfa, int startIndex, int stopIndex, boolean exact, BitSet ambigAlts, ATNConfigSet configs) {
      if (exact) {
        String format = "reportAmbiguity d=%s: ambigAlts=%s, input='%s'";
        String decision = this.getDecisionDescription(recognizer, dfa);
        BitSet conflictingAlts = this.getConflictingAlts(ambigAlts, configs);
        String text = recognizer.getTokenStream().getText(Interval.of(startIndex, stopIndex));
        String message = String.format(format, decision, conflictingAlts, text);
        recognizer.notifyErrorListeners(message);
      }
    }

    protected String getDecisionDescription(Parser recognizer, DFA dfa) {
      int decision = dfa.decision;
      int ruleIndex = dfa.atnStartState.ruleIndex;
      String[] ruleNames = recognizer.getRuleNames();
      if (ruleIndex >= 0 && ruleIndex < ruleNames.length) {
        String ruleName = ruleNames[ruleIndex];
        return ruleName != null && !ruleName.isEmpty() ? String.format("%d (%s)", decision, ruleName) : String.valueOf(decision);
      } else {
        return String.valueOf(decision);
      }
    }

    protected BitSet getConflictingAlts(BitSet reportedAlts, ATNConfigSet configs) {
      if (reportedAlts != null) {
        return reportedAlts;
      } else {
        BitSet result = new BitSet();
        Iterator i$ = configs.iterator();

        while(i$.hasNext()) {
          ATNConfig config = (ATNConfig)i$.next();
          result.set(config.alt);
        }

        return result;
      }
    }
  });

  ParseTree root = parser.parse();
}

将打印以下内容:

line 1:8 reportAmbiguity d=1 (statement): ambigAlts={1, 2}, input='print42'

这篇关于ANTLR未报告的语法歧义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆