【问题标题】:ANTLR not throwing errors on invalid inputANTLR 不会在无效输入上抛出错误
【发布时间】:2016-11-16 04:35:43
【问题描述】:

我正在使用 ANTLR 解析我正在编写的 Java 工具中的逻辑表达式,但我遇到了问题,因为将无效输入字符串传递给生成的 ANTLR 词法分析器和解析器不会导致任何异常。生成的文件并没有像我期望的那样抛出 RecognitionException,而是将错误消息打印到控制台并返回,就好像没有发生错误一样,导致我的程序稍后在遇到空数据时崩溃。

我使用 ANTLRWorks 1.4.3 版来生成文件,似乎应该有某种选项让它实际抛出错误而不是打印到控制台,但我没有找到任何东西。有谁知道如何让 ANTLR 实际抛出错误消息?我看到 C# 中的同样问题是通过使用旧版本的 ANTLR 解决的,这是我需要做的吗?

编辑:在巴特指出我要找的方向后,我找到了这个页面

https://theantlrguy.atlassian.net/wiki/display/ANTLR3/Migrating+from+ANTLR+2+to+ANTLR+3

其“错误处理”部分的代码更符合我的要求。要改变 ANTLR 捕获异常的方式,可以在语法文件中这样说:

@rulecatch {
   catch (RecognitionException e) {
    throw e;
   }
}

这迫使 ANTLR 抛出异常,而不是处理和恢复。该部分还有一些关于覆盖不匹配和恢复函数以确保抛出所有可能的异常的内容。

【问题讨论】:

    标签: java exception antlr antlrworks


    【解决方案1】:

    一个简单的解决方法是覆盖您的词法分析器和解析器的 reportError(...) 并抛出您自己的异常,而不是让 ANTLR 尝试从不正确的语法/输入中恢复:

    grammar YourGrammar;
    
    // options/header/tokens
    
    @parser::members {
      @Override
      public void reportError(RecognitionException e) {
        throw new RuntimeException("I quit!\n" + e.getMessage()); 
      }
    }
    
    @lexer::members {
      @Override
      public void reportError(RecognitionException e) {
        throw new RuntimeException("I quit!\n" + e.getMessage()); 
      }
    }
    
    // lexer & parser rules
    

    有关错误报告(和恢复)的更多信息:https://theantlrguy.atlassian.net/wiki/display/ANTLR3/Error+reporting+and+recovery

    【讨论】:

    • 哦,非常感谢,我知道必须有一种简单的方法来编辑语法文件来做我想做的事,但是 ANTLR 太大了,我不知道到底是什么寻找。
    【解决方案2】:

    您应该按照in this answer的建议使用错误侦听器

    但是,为了从 antlr3 快速迁移到 antlr4 / antlr v4,您可以将其用作语法:

    @parser::members 
    {
      private final Logger log = LogManager.getLogger(this.getClass().getName());
      public java.util.HashMap<String, Double> memory = new java.util.HashMap<String, Double>();
    
      @Override
      public void notifyErrorListeners(Token offendingToken, String msg, RecognitionException ex)
      {
        throw new RuntimeException(msg); 
      }
    }
    
    @lexer::members 
    {
      @Override
      public void recover(RecognitionException ex) 
      {
        throw new RuntimeException(ex.getMessage()); 
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-14
      • 2014-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多