强制antlr3在规则失败时立即退出

时间:2009-09-08 16:38:35

标签: error-handling antlr antlr3

我有这样的规则:

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)。

好的,我可以看到这对某些情况有用,但我怎么能告诉Antlr停止这样做呢?来自v2的defaultErrorHandler=false选项似乎已经消失。

3 个答案:

答案 0 :(得分:2)

我对Antlr了解不多,所以这可能偏离基础,但this migration page上标题为“错误处理”的部分看起来很有帮助。

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

答案 1 :(得分:0)

您还可以覆盖reportError(RecognitionException)方法,使其重新抛出异常而不是打印它,如下所示:

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

但是,我不确定你想要这个(或ire_and_curses的解决方案),因为每次解析尝试只会出现一个错误,然后你可以修复,只是为了找到下一个错误。如果你试图恢复(ANTLR没问题)你可以一次尝试多个错误,并修复所有错误。

答案 2 :(得分:0)

您需要覆盖mismatchrecoverFromMismatchedSet方法以确保立即抛出异常(示例适用于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块。)


为了进行比较,recoverFromMismatchedSet的默认实现继承自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);
}