测试新的Java解析器

Har*_*rry 6 java testing parsing javaparser

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

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

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

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

我查看了JavaParser,但它似乎没有详尽的测试数据集.

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

Ira*_*ter 6

要确定您是否有正确的答案,理想情况下您必须与某种标准进行比较.这对于计算机语言来说很难.

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

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

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

我们的解决方案是:

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

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

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

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