我该在哪里找到C++语言的标准BNF或YACC语法?

23

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

请问有人能够指出一个标准语法链接,最好用yacc语言描述的?

希望我没有重复造轮子,在那种情况下请帮助我。

此致, Kevin


要从声明中生成存根代码,首先必须解析该声明。在实践中,这意味着需要一个完整的C++解析器。你真的不想这样做。 - Ira Baxter
6个回答

25

来自C++ FAQ Lite

38.11 是否有可用于yacc的C++语法?

您需要的主要yacc语法来自Ed Willink。Ed认为他的语法完全符合ISO / ANSI C ++标准,但他不保证:“他说”语法尚未“被愤怒地使用。您可以获取没有操作例程的语法或带有虚拟操作例程的语法。你也可以获得相应的词法分析器。对于那些对他如何实现无上下文解析器(通过将所有歧义加上少量修复推到后面进行解析完成)感兴趣的人,您可能想阅读{{link1:他的论文}}第4章。还有一个非常古老的yacc语法,不支持模板、异常和命名空间;此外,它在某些微妙的方式中偏离了核心语言。您可以在{{link2:这里}}或{{link3:这里}}获取该语法。

2
如果你想真正解析C++,你需要使用真正可靠的机制。如果一个工具被称为“Not used in anger”,意味着它无法处理真正的C++代码。(我不理解为什么这个答案会受到那么多喜爱/点赞,因为这个答案是完全无效的)。 - Ira Baxter
1
@Ira:我猜它被点赞的原因是没有更好的选择。解析C++很难。 - David Thornley
1
Ira是对的。你很可能最终只会浪费时间。如果你想要学习,我完全支持自己构建并深入探究其中的奥秘。但如果你想完成一项任务,最好选择一个开箱即用的工具。DMS工具在其他方面也有优势,它涵盖了许多语言,并且具有你在项目中可能会发现有用的额外功能。如果你的时间就是金钱(即你不是出于兴趣而进行),那么价格是合理的。 - Andre Artus
请注意,Willink语法的链接已失效,但该语法目前可以在http://www.edwillink.plus.com/projects/fog/CxxGrammar.y找到。 - Michael Gaskill

4

我最近在grammarware网站上找到了一些C++语法文件(C++ 1998: ISO/IEC 14882:1998和C++ 2008: ISO/IEC SC22/WG21 N2723=08-0233)。这些语法使用增强型BNF、DMS BNF、BGF、SDF和Rascal符号表示。不过遗憾的是,C++语法似乎没有得到更新(没有C++2003或C++11版本)。


3
Jared的链接是最接近无上下文语法的东西。某些事情确实需要延迟到后面,但这比C++的上下文敏感语法更好,这是某些争论的观点。
更糟糕的是,C++1x将显著复杂化语法。为了达到对C++的完美解析,解析器将需要实现足够的标准来正确执行重载分辨率,包括模板参数推导,这又需要概念机制、lambda和实际上几乎所有的语言,除了两阶段名称查找和异常说明外,如果我记得正确的话,这些不需要实际实现就能成功解析程序。
实际上,如果您可以解析C++,那么您已经完成了编译器的一半。

如果你无法完全进行名称解析,那么你离C++编译器还有很远的路要走。相比名称解析,语法分析要容易得多。 - Ira Baxter
1
不行,因为解析需要名称解析;这就是我的观点。C++的语法太糟糕了。 - coppro
如果您使用GLR解析器,则C++解析不需要名称解析。实际上,这很容易,我们每天都使用我们的DMS工具进行解析(www.semanticdesigns.com/Products/FrontEnds/CppFrontEnd.html)。如果您坚持使用无法容忍局部歧义的LALR(1)解析器,那么在解析时必须进行名称解析,我同意这是一种混乱的方式,但这就是您不采用该方法的原因。即使存在局部歧义,对于C ++进行名称解析仍然相当困难,我会承认,但与解析器纠缠在一起时并不像那么讨厌。 - Ira Baxter
我们的C++前端也执行所有名称解析。但你仍然远离一个C++编译器:你仍然需要流分析、优化转换、低级代码生成、寄存器分配、优化等等。 - Ira Baxter

2

还有另一种方法,您可以考虑依托现有的编译器。

GCC-XML会将C++代码编译成带有大量有用信息的XML文件;对于您的需求可能已经足够了。

不幸的是,GCC-XML只有1/4进行维护,并且让它正常工作可能有些棘手。如果您选择这条路线,祝你好运。


2
我最近发现了这个工具。我没有试过它,所以不确定它是否有效。你能否提供更多有关你正在开发的工具的信息?我下载了这个语法,因为我正在开发一个仪器工具,以便为我的单元测试框架添加覆盖率信息。

经过重新阅读您的评论...

我认为这个工具完全符合您的需求。


我正在开发一个单元测试框架,需要提供外部引用来生成可运行的二进制文件以测试单个翻译单元。因此,我正在尝试解析源代码以查找声明并生成存根定义。 - Kevin Yu

1

我们的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和微软变体。它还会解析(并保留)包含大多数预处理条件指令的源代码。它具有驱动解析过程的显式语法,与GCC或Clang不同。


虽然stackoverflow并不直接支持或反对开源和/或免费解决方案,但通常将一个复杂的链接放在那里而不是直接指向解决方案是一个坏主意。如果你真的想推广你的工具,至少要指向一个页面,其中包含一些示例代码和依赖项,可以在不阅读公司介绍和有壁垒的下载链接的情况下使用。 - Adnan Y
OP说他想要一个语法,但他真正的问题是解析C++以提取信息以生成存根。我的答案展示了如何通过跳过他不切实际的获取工作语法的想法(对于传统的解析器生成器来说,它们几乎不存在),然后在不解决名称解析问题的情况下进行解析(这是大量工作)。这个“复杂的链接”直接指向一个实用的答案。 - Ira Baxter
如果你认为一个问题不切实际,那就别发表意见。让更有资格回答这个问题的人来回答,或者干脆不回答,证明你是正确的。其次,我确实访问了那个页面,但是除了一些关于前端的营销宣传之外,我没有看到任何答案,也没有例子或下载链接。如果有真正的答案,请编辑答案,并在这里添加,以防网站崩溃。 - Adnan Y
@Adnan:有时候我真的觉得我有资格回答这个问题。如果你不确定的话,请阅读我的个人简历。关于“市场宣传语”的问题:我想你可能错过了其中明确说明它可以产生控制和数据流信息的部分,这是 OP 得到他答案所必需的条件。 - Ira Baxter
这不是个人评论,只应与问题的背景联系起来考虑。我会让你自己评估你的答案是否合格。祝你有美好的一天。 - Adnan Y

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接