Antlr4 ANTLRv4在发生错误后重置lexer和解析器

Antlr4 ANTLRv4在发生错误后重置lexer和解析器,antlr4,Antlr4,我试图重用lexer/parser来顺序解析短文本块。为了确保前一次跑步不会留下任何痕迹,我总是这样做 mLexer.reset(); mLexer.setInputStream(new ANTLRInputStream(data)); mParser.reset(); mParser.setTokenStream(new CommonTokenStream(mLexer)); 认为这将完全重置lexer和parser,不管之前发生了什么。不幸的是,在解析无效

我试图重用lexer/parser来顺序解析短文本块。为了确保前一次跑步不会留下任何痕迹,我总是这样做

    mLexer.reset();
    mLexer.setInputStream(new ANTLRInputStream(data));

    mParser.reset();
    mParser.setTokenStream(new CommonTokenStream(mLexer));
认为这将完全重置lexer和parser,不管之前发生了什么。不幸的是,在解析无效模式时,仍然存在一些问题

我的lexer无法恢复:

      @Override
        public void recover(final LexerNoViableAltException e) {
            throw new RuntimeException(e);
        }
我的解析器也不会:

private class HexParserErrorStrategy extends org.antlr.v4.runtime.DefaultErrorStrategy {
    @Override
    public void recover(final Parser recognizer, final RecognitionException e) {
        throw new RuntimeException(e);
    }

    @Override
    public Token recoverInline(final Parser recognizer) throws RecognitionException {
        throw new RuntimeException();
    }

    @Override
    public void reportUnwantedToken(final Parser recognizer) {
        throw new RuntimeException();
    }
}
当我解析一个像“123456”这样的字符串时,它工作得很好。之后,我解析了一个无效的模式,这给了我一个RE。如果我再次尝试解析“123456”,结果与第一次运行的结果不同

那么,如何相应地重置解析器/词法分析器?

与第一次运行的结果有什么不同

以下是一些一般提示:

  • 使用
    BailErrorStrategy
    而不是创建自己的策略。它已经包含在ANTLR运行时中,并将抛出一个
    ParseCanceledException
    ,而不仅仅是
    RuntimeException
    。它还将所有相关解析树节点的
    exception
    字段设置为正确的值

  • 您可以创建一个新的lexer/parser实例,而不是重用以前的实例


  • 似乎setXXStream和reset的顺序很重要。当颠倒顺序时,它会按预期工作:

    mLexer.setInputStream(new ANTLRInputStream(data));
    mLexer.reset();
    
    mParser.setTokenStream(new CommonTokenStream(mLexer));
    mParser.reset();
    

    可能是给医生的。最初,我希望在设置新流时重置lexer/解析器。

    在无效运行期间,我的流中有未知字符。这是正确检测到的。在第三次运行时,我仍然得到一个错误,即一些字符无法正确识别。关于使用新的解析器。到目前为止,这是我的解决办法。我只是想,随着时间的推移,解析器会学习并变得更快;DFA是一种共享结构,因此新的解析器实例会自动重用以前的解析器实例的结果。