首页 > 解决方案 > Unittest中的ANTLR4 Python:如何中止任何错误

问题描述

我想在 Python Unittest 中测试我的词法分析器/解析器。为此,我希望 antlr 每次出现异常时都会失败。实现这一目标的最优雅的方法是什么?

我已经阅读了ANTLR Mega Tutorial,他们在那里编写了一个ErrorListener覆盖syntaxError()以保存最后一个违规符号,然后最后,他们检查是否遇到任何违规符号。

我看到有不同的ErrorStrategy类,BailErrorStrategy听起来这就是我需要的。但是后来我阅读了如何在 python ANTLR 生成的解析器中出现第一个语法错误时失败,同时保留错误消息?这表示这种策略并不总是抛出异常。

到目前为止,我最好的想法是抛出一个异常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()

标签: pythonantlr4python-unittest

解决方案


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

如果您使用正常的错误处理程序/默认策略,它将始终尝试从语法错误中恢复以允许继续解析运行。

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


推荐阅读