Parsing 测试(自动)解析器的更好方法?
我最近正在编写一种小型编程语言,并且已经完成了它的解析器的编写。我想为解析器编写一个自动测试(其结果是一个抽象语法树),但我不确定哪种方法更好 首先,我尝试将AST序列化为S表达式文本,并将其与我手工编写的预期输出文本进行比较,但它存在一些问题:Parsing 测试(自动)解析器的更好方法?,parsing,testing,abstract-syntax-tree,Parsing,Testing,Abstract Syntax Tree,我最近正在编写一种小型编程语言,并且已经完成了它的解析器的编写。我想为解析器编写一个自动测试(其结果是一个抽象语法树),但我不确定哪种方法更好 首先,我尝试将AST序列化为S表达式文本,并将其与我手工编写的预期输出文本进行比较,但它存在一些问题: 序列化文本与预期输出(如空格)之间存在细微的无意义差异。例如,以下各项之间没有区别: (attribute (symbol str) (symbol length)) (已序列化)和: (那是我亲手写的)在它们的意义上,但是字符串比较当然会区分它们
- 序列化文本与预期输出(如空格)之间存在细微的无意义差异。例如,以下各项之间没有区别:
(已序列化)和: (那是我亲手写的)在它们的意义上,但是字符串比较当然会区分它们。好的,我可以通过正常化来解决它(attribute (symbol str) (symbol length))
- 当测试失败时,它不会简洁地显示实际树和预期树之间的差异。我只想显示一个差异节点,而不是整个树
()
(a)
((((((((((a))))))))))
((((((((((a)))))))))
(a (a (a (a (a (a (b)))))))
(((((((b) a) a) a) a) a) a)
(((((((b a) a) a) a) a) a)
((a)(a)(a)(a))
((a)(a a)(a))
(())
(()())
((()())(()())(()()))
((()())()()(()()))
...
如果您正在为解析器寻找一个完全自动化和可扩展的单元测试框架,我建议您采用以下方法: 输入错误 创建一组错误输入的样本。然后将它们分别输入到解析器中,确保解析器拒绝它们。我最好为每个定义预期输出的测试用例提供元数据——解析器应该产生的特定错误代码/消息 正确输入 与前一种情况一样,创建一组表示各种正确输入的样本。除了解析器接受所有输入的简单验证之外,还存在验证实际抽象语法树是否有意义的问题 为了解决这个问题,我将做以下工作:用一些众所周知的格式描述每个测试用例的预期AST,这些格式可以被认为没有bug的第三方解析器安全地解析(反序列化为实际的内存中AST结构)(针对您的情况)。自然的选择是XML,因为大多数语言/编程框架都支持XML,并提供相应的(反)序列化功能。最好的解决方案是直接反序列化为AST节点类型。由于存在方便的XML可视化编辑工具,因此构建大型测试用例也是可行的 然后,我将使用将两个AST配对并比较每对中的两个节点是否相等来构造一个AST比较器。但是,相等是一个每AST节点类型特定的操作
注:
- 这种方法适用于大多数单元测试框架,如JUnit
- AST到XML序列化是调试编译器的受欢迎工具
- 访问者模式实现可以很容易地作为编译器中多个处理阶段的主干
- 有一些编译器测试套件免费提供,可以为您的项目提供一些启发-例如,请参见Ada编程语言的示例,尽管此测试套件处理更高级别的测试,而不仅仅是解析器测试
()
(a)
((((((((((a))))))))))
((((((((((a)))))))))
(a (a (a (a (a (a (b)))))))
(((((((b) a) a) a) a) a) a)
(((((((b a) a) a) a) a) a)
((a)(a)(a)(a))
((a)(a a)(a))
(())
(()())
((()())(()())(()()))
((()())()()(()()))
...