测试新的Java解析器

时间:2016-09-25 13:57:33

标签: java parsing testing javaparser

纯粹作为一种自学练习,我尝试使用Parse::RecDescent模块在​​Perl中编写Java解析器。我稍后可能会使用其他工具重新实现解析器,例如 Antlr bison 等。

但是,根据Java语言规范,我如何确保我的解析器确实生成了正确的解析?意义,正确处理悬空else,操作员关联性和 - 优先级等。

一种方法是将我的解析器与已知的无错误解析器进行比较,让两个解析器为大量测试Java程序生成AST,然后比较两组AST。

如果这确实是唯一的方法,我在哪里可以找到一整套完整的Java语言规范测试Java程序?

我看过JavaParser,但它似乎没有详尽的测试数据集。

另一种方法当然是自己手工编写成千上万个测试Java程序,这对我来说是非常不切实际的,不仅在时间方面,而且在确保其详尽无遗!

2 个答案:

答案 0 :(得分:6)

要确定您是否有正确的答案,您最好必须与某种标准进行比较。这对于计算机语言来说很难。

比较AST很难,因为没有这样的标准。构建AST的每个解析器构建一个AST,其结构由编码解析器的人设计。

这意味着如果您构建一个产生AST的解析器,并且您获得了其他人的AST生成解析器,您将发现您选择的AST节点与其他AST不匹配。现在你必须构建从AST到另一个的映射(你怎么知道映射是有效的?)。您可以尝试让解析器从另一个解析器生成AST,但您将发现的是您生成的AST受您使用的解析技术的影响。

我们公司生产的Java前端存在类似问题(如果您想了解更多信息,请参阅bio)。我们的目标是测试答案是自洽然后我们对大部分代码进行了大量的长期体验测试。

我们的解决方案是:

  • (使用我们可以获得的最强大的解析技术(GLR)构建解析器。这意味着我们可以识别其他解析技术(LL,LR,...)不易识别的某些构造,从而生成AST节点其他解析器将很难生成。请参阅下面的注释以获取重要的示例。即便如此,we produce AST nodes in way that avoids completely our having to hand-code AST node construction也是大多数其他解析技术所要求的;这往往会产生与手动编码不同的AST。)
  • 解析大量Java代码(生成AST)以确保我们没有解析错误。 [JDK是一个非常好的大小示例,很容易获得]
  • 我们的工具可以采用AST并重新生成(prettyprint)源代码,完成注释但可能有些不同的布局。我们验证了 parsed-then-prettyprinted代码也解析。我们重新打印解析的漂亮版本;这应该与prettyprinted版本相同,因为我们总是生成相同的布局。这个测试很好地表明我们的AST设计和实现并没有丢失任何关于源代码的信息
  • 构建符号表,解析名称的含义,并根据我们的前端验证合法的Java程序是否进行类型检查。这并没有告诉你任何关于AST的本质,除了它足够好(事实上,这已经足够了!)因为类型检查任务非常复杂(去检查你的本地Java标准),它是也很脆弱。如果你没有把一切都搞定,那么在应用大量代码时,类型检查可能会失败。同样,JDK对此非常好。 注意:没有名称和类型解析的Java解析器在实践中非常有用
  • 生成JavaDoc,就像包含来自上述结果的超链接源代码的交叉引用一样。这意味着手动检查位代码很容易看到名称解析(因此AST构造)是理智的。
  • 与结果一起生活,将前端应用于各种程序 代码分析和转换。我们偶尔发现问题并修复它。

很难做到这一点;你必须接近并持续保持测试压力,特别是因为Java语言不断发展。 (我们在Java 8,Java 9受到威胁)。结论:构建这样一个解析器并检查它的完整性是很多

我们喜欢有一套独立的测试,但我们还没有在野外看到过。我希望那些测试存在(我认为Oracle和IBM有它们)真的不会直接测试解析名称解析,而是测试一些代码编译并运行产生已知结果。由于我们没有构建编译器,如果我们拥有它们,我们将无法运行这样的测试。我们可以进行名称解析和类型一致性检查,这将有所帮助。

[我们实际上是为了许多语言前端而做到这一点。你认为Java很难,用C ++试试吧

答案 1 :(得分:1)

我同意@ ira-baxter所写的内容。

简而言之,很容易验证您的解析器可以解析所有有效的源代码(只需抛出很多代码:我们这样做是为了测试JavaParser,我们只是没有在存储库中放入几百兆字节的代码源代码)。

很难验证您生成的AST是否具有正确的形状,因为您可以使用许多不同的方法来解析相同的代码并构建不同但同样有效的AST。有些形状会更容易与其他人合作,但没有“真理”可以坚持。

如果你的工具产生的AST与另一个解析器生成的AST不同,那么它并不一定意味着两个解析器中的任何一个都是错误的,它可能只是一个设计选择。