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

发布于 2024-08-04 08:35:04 字数 573 浏览 4 评论 0原文

我有这样的规则:

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

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

好的,我知道这在某些情况下会有什么用处,但我怎样才能告诉 Antlr 停止这样做呢? v2 中的 defaultErrorHandler=false 选项似乎消失了。

I've got a rule like this:

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

Unfortunately, it throws an exception in the RuntimeObject constructor because $label.text is null. Examining the debug output and some other things reveals that the match against "label" actually failed, but the Antlr runtime "helpfully" continues with the match for the purpose of giving a more helpful error message (http://www.antlr.org/blog/antlr3/error.handling.tml).

Okay, I can see how this would be useful for some situations, but how can I tell Antlr to stop doing that? The defaultErrorHandler=false option from v2 seems to be gone.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

请恋爱 2024-08-11 08:35:04

我对 Antlr 不太了解,所以这可能有点偏离基础,但是 此迁移页面看起来很有帮助。

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

I don't know much about Antlr, so this may be way off base, but the section entitled "Error Handling" on this migration page looks helpful.

It suggests you can either use @rulecatch { } to disable error handling entirely, or override the mismatch() method of the BaseRecogniser with your own implementation that doesn't attempt to recover. From your problem description, the example on that page seems like it does exactly what you want.

你穿错了嫁妆 2024-08-11 08:35:04

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

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

但是,我不确定您想要这个(或 ire_and_curses 的解决方案),因为您只会收到一个错误每次解析尝试,然后您可以修复它,只是为了找到下一个错误。如果您尝试恢复(ANTLR 可以),您可能会在一次尝试中遇到多个错误,然后修复所有错误。

You could also override the reportError(RecognitionException) method, to make it rethrow the exception instead of print it, like so:

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

However, I'm not sure you want this (or the solution by ire_and_curses), because you will only get one error per parse attempt, which you can then fix, just to find the next error. If you try to recover (ANTLR does it okay) you can get multiple errors in one try, and fix all of them.

梦在深巷 2024-08-11 08:35:04

您需要重写 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 块。)


用于比较,从 BaseRecognizer 继承的 recoverFromMismatchedSet 的默认实现:

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);
}

You need to override the mismatch and recoverFromMismatchedSet methods to ensure an exception is thrown immediately (examples are for 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;
    }
}

then you need to change how the parser deals with those exceptions so they're not swallowed:

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

(The bodies of all the rule-matching methods in your parser will be enclosed in try blocks, with this as the catch block.)


For comparison, the default implementation of recoverFromMismatchedSet inherited from 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;
}

and the default rulecatch:

catch (RecognitionException re) {
    reportError(re);
    recover(input,re);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文