代码之家  ›  专栏  ›  技术社区  ›  JSBÕ±Õ¸Õ£Õ¹

当规则失败时强制antl3立即退出

  •  1
  • JSBÕ±Õ¸Õ£Õ¹  · 技术社区  · 15 年前

    我有这样的规则:

    declaration returns [RuntimeObject obj]: 
        DECLARE label value { $obj = new RuntimeObject($label.text, $value.text); };
    

    不幸的是,它在 RuntimeObject 构造函数是因为 $label.text 是空的。检查调试输出和其他一些内容会发现与“label”的匹配实际上失败了,但是antlr运行时“帮助地”继续匹配,以便提供更有用的错误消息。( http://www.antlr.org/blog/antlr3/error.handling.tml )

    好吧,我知道这在某些情况下是如何有用的,但是我怎么能告诉安特尔停止这样做呢?这个 defaultErrorHandler=false V2的选项似乎消失了。

    3 回复  |  直到 15 年前
        1
  •  2
  •   ire_and_curses    15 年前

    我对ANTLR不太了解,所以这可能有点离谱,但是题为“错误处理”的部分 this migration page 看起来很有帮助。

    它建议你可以使用 @rulecatch { } 完全禁用错误处理,或重写 mismatch() 方法 BaseRecogniser 使用自己的不尝试恢复的实现。从您的问题描述来看,该页面上的示例似乎完全符合您的需要。

        2
  •  0
  •   Christian K.    13 年前

    您还可以重写ReportError(RecognitionException)方法,使其重新引发异常而不是打印它,如下所示:

    @parser::members {
        @Override
        public void reportError(RecognitionException e) {
            throw new RuntimeException(e);
        }
    }
    

    但是,我不确定您是否需要这样做(或者用ire_and_curses给出的解决方案),因为每次解析尝试只会得到一个错误,然后您就可以修复它,只是为了找到下一个错误。如果您尝试恢复(Antlr可以),您可以在一次尝试中获得多个错误,并修复所有错误。

        3
  •  0
  •   Brad Mace Mike King    12 年前

    您需要覆盖 mismatch recoverFromMismatchedSet 确保立即抛出异常的方法(示例是Java):

    @members {
        protected void mismatch(IntStream input, int ttype, BitSet follow) throws RecognitionException {
            throw new MismatchedTokenException(ttype, input);
        }
    
        public Object recoverFromMismatchedSet(IntStream input, RecognitionException e, BitSet follow) throws RecognitionException {
            throw e;
        }
    }
    

    然后,您需要更改解析器处理这些异常的方式,这样它们就不会被吞没:

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

    (解析器中所有规则匹配方法的主体将包含在 try 块,以此作为 catch 块)


    比较而言,默认实现 从不匹配集恢复 继承自 BaseRecognizer :

    public Object recoverFromMismatchedSet(IntStream input, RecognitionException e, BitSet follow)  throws RecognitionException {
        if (mismatchIsMissingToken(input, follow)) {
            reportError(e);
            return getMissingSymbol(input, e, Token.INVALID_TOKEN_TYPE, follow);
        }
    
        throw e;
    }
    

    以及默认的rulecatch:

    catch (RecognitionException re) {
        reportError(re);
        recover(input,re);
    }