【问题标题】:Where can I find standard BNF or YACC grammar for C++ language?在哪里可以找到 C++ 语言的标准 BNF 或 YACC 语法?
【发布时间】:2009-03-05 03:24:22
【问题描述】:

我正在尝试开发一种代码生成器,以帮助对遗留的 C/C++ 混合项目进行单元测试。我没有发现任何一种独立的工具可以从声明中生成存根代码。所以我决定建一个,应该不会那么难。

拜托,任何人都可以给我一个标准的语法链接,用 yacc 语言更好地描述。

希望我不是在重新发明轮子,在这种情况下请帮助我。

最好的问候, 凯文

【问题讨论】:

  • 要从声明中生成存根代码,首先您必须解析声明。这实际上意味着一个完整的 C++ 解析器。你真的不想这样做。

标签: c++ yacc bnf


【解决方案1】:

来自C++ FAQ Lite

38.11 Is there a yacc-able C++ grammar?

您需要的主要 yacc 语法 来自埃德·威林克。埃德相信他的 语法完全符合the ISO/ANSI C++ standard,但是他 不保证:“语法有 不是,”他说,“被用于愤怒。” 您可以获得the grammar without action routinesthe grammar with dummy action routines。你 也可以得到the corresponding lexer。对于那些 对他如何取得成就感兴趣 上下文无关解析器(通过推送所有 歧义加上少量 解析后稍后进行修复 已完成),您可能想阅读 his thesis 的第 4 章。

还有一个很老的yacc语法 不支持模板, 异常,也不是命名空间;加上它 偏离核心语言 一些微妙的方式。你可以得到那个 语法herehere

【讨论】:

  • 如果您需要真正解析 C++,您需要真正有效的机器。 “不用于愤怒”意味着它不适用于真正的 C++ 代码。 (考虑到这个答案完全无效,我不明白为什么这个答案被喜欢/赞成这么多次)。
  • @Ira:我猜测为什么它被赞成是真的没有比这更好的了。解析 C++ 很困难。
  • 艾拉是对的。你很可能最终会浪费你的时间。如果你想做的是学习,我完全赞成建立你自己的,然后跳进兔子洞。但是,如果您想完成一项工作,建议您获得开箱即用的东西。 DMS 工具还有其他优势,因为它涵盖了多种语言,并且具有您可能会在项目中发现有用的附加功能。如果您的时间物有所值(即您不是为了好玩而这样做),那么价格是合理的。
  • 请注意,Willink 语法的链接已经失效,但目前可以在edwillink.plus.com/projects/fog/CxxGrammar.y找到语法
【解决方案2】:

我最近发现了一些 C++ 语法文件(C++ 1998:ISO/IEC 14882:1998 和 C++ 2008:ISO/IEC SC22/WG21 N2723=08-0233强>) 在grammarware website。语法以 Enahnced BNF、DMS BNF、BGF、SDF 和 Rascal 表示法表示。遗憾的是,C++ 语法似乎没有得到更新(没有 C++2003 或 C++11)。

【讨论】:

    【解决方案3】:

    Jared 的链接是您可以获得的最接近上下文无关语法的东西。某些事情确实需要延迟到以后,但这是通过一些比 C++ 的上下文敏感语法更好的论点。

    更糟糕的是,C++1x 将显着复杂化语法。为了达到对 C++ 的完美解析,解析器需要实现足够多的标准来正确执行重载解析,包括模板参数推导,这反过来又需要概念机制、lambdas,实际上几乎所有的语言,除了两阶段名称查找和异常规范,如果我没记错的话,不需要实际实现来成功解析程序。

    实际上,如果你能解析 C++,你就已经完成了编译器的一半。

    【讨论】:

    • 如果您不能完全进行名称解析,那么您离 C++ 编译器还差得很远。解析比名称解析容易得多。
    • 否,因为解析需要名称解析;这就是我的观点。 C++ 的语法就是这么糟糕。
    • 如果您使用 GLR 解析器,C++ 解析不需要名称解析。事实上,这非常简单,我们每天都使用我们的 DMS 工具来完成 (www.semanticdesigns.com/Products/FrontEnds/CppFrontEnd.html)。如果您坚持使用不能容忍本地歧义的 LALR(1) 解析器,那么您必须在解析时命名 resolve,我同意这是一团糟,但是您有理由不这样做方式。即使存在局部歧义,为 C++ 进行名称解析仍然非常困难,我承认,但并不像与解析器纠缠在一起时那样令人讨厌。
    • ... 我们的 C++ 前端也完成了所有的名称解析。你离 C++ 编译器还差得很远:你仍然需要流分析、优化转换、低级代码生成、寄存器分配、优化……
    【解决方案4】:

    对于另一种方法,您可以考虑搭载现有编译器。

    GCC-XML 会将 C++“编译”成包含大量有用信息的 XML 文件;对于您的目的来说,这可能就足够了。

    不幸的是,GCC-XML 只维护了 1/4,让它工作起来可能……很有趣。祝你好运,如果你走这条路。

    【讨论】:

      【解决方案5】:

      我最近找到了this one。我还没有尝试过,所以不确定它是否有效。您能否提供有关您正在尝试开发的工具的更多信息?我下载了这个语法,因为我正在开发一个检测工具,所以我可以为我的unit test framework 添加覆盖信息。

      重新阅读您的评论后...

      我认为this tool 完全符合您的需求。

      【讨论】:

      • 我实际上是在做一些实际上属于单元测试框架的东西。要测试单个翻译单元,需要提供外部参考来生成可运行的二进制文件,因此我尝试解析源代码以查找声明并生成存根定义。
      【解决方案6】:

      我们的 DMS 软件再造工具包可以通过强大的、 功能齐全的 C++ 解析器。看 http://www.semanticdesigns.com/Products/FrontEnds/CppFrontEnd.html 这会构建 AST 和符号表,并且可以推断任何表达式的类型。 DMS 使人们能够进行任意分析和转换 在 C++ 代码上。

      一个“简单”的转换是检测代码以收集测试覆盖率 数据;我们将其作为 COTS 工具提供。请参阅本文以了解 DMS 是如何做到的: http://www.semanticdesigns.com/Company/Publications/TestCoverage.pdf

      编辑 2013 年 9 月(这个答案有点陈旧):DMS 的 C++ 解析器/名称解析/控制流分析处理完整的 C++11, 在 ISO-、GNU- 和 Microsoft 变体中。它还将解析(并保留) 包含大多数预处理器条件的源代码。它有一个明确的语法 与 GCC 或 Clang 不同,驱动解析过程。

      【讨论】:

      • 虽然 stackoverflow 不直接支持或反对开源和/或免费解决方案,但通常放置一个不直接指向解决方案的复杂链接是一个坏主意。如果你真的想推广你的工具,至少要指向一个页面,其中包含一些示例代码和依赖项,无需阅读公司简介和隔离下载链接即可使用。
      • OP 说他想要一个语法,但他真正的问题是解析 C++ 以提取信息以生成存根。我的回答显示了如何通过跳过他获得有效语法的不切实际的想法(对于传统的解析器生成器来说几乎不存在)然后在不解决名称解析问题的情况下以某种方式进行解析(这是一个巨大的数量)来解决他的真正问题工作)。这个“复杂的链接”直接指向一个实用的答案。
      • 如果您认为某个问题不切实际,则无需发表意见。让其他更有资格回答这个问题的人回答它,或者让这个问题无人回答并被证明是正确的。其次,我确实访问了该页面,但看不到任何答案,但有一些关于前端的营销宣传,没有任何示例,也没有下载链接。如果有实际答案,请编辑答案并在此处添加,以防网站出现故障。
      • @Adnan:有时候我认为我实际上有资格回答这个问题。如果有疑问,请阅读我的简历。关于“营销宣传”:我想你错过了它明确表示它产生控制和数据流信息的部分,这是 OP 得到答案的必要条件。
      • 这不是个人评论,只能在问题的上下文中进行。我会将您的答案是否合格的判断留给您自己的个人评估。祝你有美好的一天。
      猜你喜欢
      • 1970-01-01
      • 2016-12-30
      • 1970-01-01
      • 2010-12-06
      • 1970-01-01
      • 2011-06-05
      • 2011-04-22
      • 2015-10-15
      • 1970-01-01
      相关资源
      最近更新 更多