纯粹作为一种自学练习,我尝试使用Parse::RecDescent
模块在Perl中编写Java解析器。我稍后可能会使用其他工具重新实现解析器,例如 Antlr , bison 等。
但是,根据Java语言规范,我如何确保我的解析器确实生成了正确的解析?意义,正确处理悬空else
,操作员关联性和 - 优先级等。
一种方法是将我的解析器与已知的无错误解析器进行比较,让两个解析器为大量测试Java程序生成AST,然后比较两组AST。
如果这确实是唯一的方法,我在哪里可以找到一整套完整的Java语言规范测试Java程序?
我看过JavaParser,但它似乎没有详尽的测试数据集。
另一种方法当然是自己手工编写成千上万个测试Java程序,这对我来说是非常不切实际的,不仅在时间方面,而且在确保其详尽无遗!
答案 0 :(得分:6)
要确定您是否有正确的答案,您最好必须与某种标准进行比较。这对于计算机语言来说很难。
比较AST很难,因为没有这样的标准。构建AST的每个解析器构建一个AST,其结构由编码解析器的人设计。
这意味着如果您构建一个产生AST的解析器,并且您获得了其他人的AST生成解析器,您将发现您选择的AST节点与其他AST不匹配。现在你必须构建从AST到另一个的映射(你怎么知道映射是有效的?)。您可以尝试让解析器从另一个解析器生成AST,但您将发现的是您生成的AST受您使用的解析技术的影响。
我们公司生产的Java前端存在类似问题(如果您想了解更多信息,请参阅bio)。我们的目标是测试答案是自洽然后我们对大部分代码进行了大量的长期体验测试。
我们的解决方案是:
很难做到这一点;你必须接近并持续保持测试压力,特别是因为Java语言不断发展。 (我们在Java 8,Java 9受到威胁)。结论:构建这样一个解析器并检查它的完整性是很多。
我们喜欢有一套独立的测试,但我们还没有在野外看到过。我希望那些测试存在(我认为Oracle和IBM有它们)真的不会直接测试解析和名称解析,而是测试一些代码编译并运行产生已知结果。由于我们没有构建编译器,如果我们拥有它们,我们将无法运行这样的测试。我们可以进行名称解析和类型一致性检查,这将有所帮助。
[我们实际上是为了许多语言前端而做到这一点。你认为Java很难,用C ++试试吧
答案 1 :(得分:1)
我同意@ ira-baxter所写的内容。
简而言之,很容易验证您的解析器可以解析所有有效的源代码(只需抛出很多代码:我们这样做是为了测试JavaParser,我们只是没有在存储库中放入几百兆字节的代码源代码)。
很难验证您生成的AST是否具有正确的形状,因为您可以使用许多不同的方法来解析相同的代码并构建不同但同样有效的AST。有些形状会更容易与其他人合作,但没有“真理”可以坚持。
如果你的工具产生的AST与另一个解析器生成的AST不同,那么它并不一定意味着两个解析器中的任何一个都是错误的,它可能只是一个设计选择。