草庐IT

java - 测试新的Java解析器

coder 2024-03-29 原文

纯粹是自学练习,我试图使用Parse::RecDescent模块在Perl中编写Java解析器。稍后我可能会使用其他工具(如Antlr,野牛等)重新实现解析器。

但是,根据Java语言规范,我如何确保我的解析器确实生成了正确的解析器?含义,它对悬挂的else的正确处理,运算符的关联性和-precedence等。

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

如果这确实是唯一的方法,那么在哪里可以找到涵盖整个Java语言规范的大量测试Java程序套件?

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

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

最佳答案

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

比较AST会很困难,因为尚无标准。每个构建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)源代码,并带有注释,但布局可能有所不同。我们验证
    解析然后美化的代码也会解析。我们重新打印解析后的 pretty-print 版本;这应该与prettyprinted版本相同,因为我们总是产生相同的布局。此测试很好地表明了我们的AST设计和实现不会丢失任何有关源代码
  • 的信息
  • 构建符号表,解决名称的含义,并根据我们的前端验证合法的Java程序进行类型检查。除了足够好(实际上已经足够好!)之外,这没有告诉您任何有关AST性质的信息。因为类型检查任务非常复杂(请检查您的本地Java标准),所以它也很漂亮脆弱的。如果您没有正确的选择,那么将其应用于大量代码时,类型检查可能会失败。同样,JDK对此进行了很好的测试。注意:没有名称和类型解析的Java解析器在实践
  • 中不是很有用
  • 产生类似于JavaDoc的交叉引用,这些交叉引用包含上述结果中的超链接源代码。这意味着很容易手动检查位代码以查看名称解析(因此AST构造)是合理的。
  • 实时显示结果,将前端​​应用于各种程序
    分析和代码转换。我们发现了偶发的问题并进行了修复。

  • 要做到这一点很难。您必须保持密切联系并持续承受测试压力,尤其是因为Java语言不断发展。
    (我们使用Java 8,而Java 9受到威胁)。底线:构建这样的解析器并检查其健全性是一项繁重的工作。

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

    [我们实际上是针对多种语言的前端进行的。您认为Java很难,请与C++一起尝试]

    关于java - 测试新的Java解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39687634/

    有关java - 测试新的Java解析器的更多相关文章

    1. Ruby 解析字符串 - 2

      我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?

    2. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

      很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

    3. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

      我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

    4. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

      使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

    5. ruby - 用逗号、双引号和编码解析 csv - 2

      我正在使用ruby​​1.9解析以下带有MacRoman字符的csv文件#encoding:ISO-8859-1#csv_parse.csvName,main-dialogue"Marceu","Giveittohimóhe,hiswife."我做了以下解析。require'csv'input_string=File.read("../csv_parse.rb").force_encoding("ISO-8859-1").encode("UTF-8")#=>"Name,main-dialogue\r\n\"Marceu\",\"Giveittohim\x97he,hiswife.\"\

    6. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

      我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

    7. ruby - Ruby 的 Hash 在比较键时使用哪种相等性测试? - 2

      我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。

    8. ruby - RSpec - 使用测试替身作为 block 参数 - 2

      我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

    9. ruby - Sinatra:运行 rspec 测试时记录噪音 - 2

      Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/

    10. java - 等价于 Java 中的 Ruby Hash - 2

      我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

    随机推荐