Unittest 中的 ANTLR4 Python:如何中止任何错误

ANTLR4 Python in Unittest: how to abort on any error

我想在 Python 单元测试中测试我的 lexer/parser。为此,我希望 antlr 每次出现异常时都以异常失败。实现此目的最优雅的方法是什么?

我读过 ANTLR Mega Tutorial,他们写了一个 ErrorListener 覆盖 syntaxError() 来保存最后一个违规符号,然后最后,他们检查是否有任何违规符号遇到了。

我看到有不同的 ErrorStrategy classes and BailErrorStrategy sounds like this is what I need. But then I read How can I fail on first syntax error in a python ANTLR generated parser while keeping the error message? 说这个策略并不总是抛出异常。

到目前为止我最好的想法是在 ErrorListener.syntxError() 中抛出一个异常:

import unittest
from antlr4 import *
from antlr.myLexer import myLexer
from antlr.myParser import myParser
from antlr4.error.ErrorListener import ErrorListener


class MyErrorListener(ErrorListener):
    def syntaxError(self, recognizer, offendingSymbol, line, column, msg, e):
        raise Exception("ERROR: when parsing line %d column %d: %s\n" % \
                        (line, column, msg))


class TestMyParser(unittest.TestCase):
    def test_with_testfile(self):
        error_listener = MyErrorListener()
        input_stream = FileStream("testfile")
        lexer = myLexer(input_stream)
        lexer.removeErrorListeners()
        lexer.addErrorListener(error_listener)
        stream = CommonTokenStream(lexer)
        parser = myParser(stream)
        parser.removeErrorListeners()
        parser.addErrorListener(error_listener)
        tree = parser.startrule()


if __name__ == '__main__':
    unittest.main()

您最好的选择是 BailErrorStategy。它使用了一个在 ANTLR4 运行time 的任何地方都没有捕获到的异常,因此直接冒泡到您自己的代码中。

如果您使用普通错误 handler/default 策略,它将始终尝试从语法错误中恢复以允许继续解析 运行。

但即使 BailErrorStrategy 到位,您也可以有一个错误侦听器来获取出现的第一个(也是唯一一个)错误。对于错误消息,我建议附加您自己的错误侦听器 class 以生成您自己的错误消息版本,就像我所做的那样 in this C++ code