52

有哪些好的工具可以快速开始解析和分析 C/C++ 代码?

特别是,我正在寻找处理 C/C++ 预处理器和语言的开源工具。这些工具最好使用 lex/yacc(或 flex/bison)作为语法,不要太复杂。他们应该处理最新的 ANSI C/C++ 定义。

这是我到目前为止发现的,但还没有详细研究它们(想法?):

  • CScope - 老式 C 分析器。不过,似乎没有进行完整的解析。被描述为用于查找 C 函数的美化“grep”。
  • GCC - 每个人都喜欢的开源编译器。非常复杂,但似乎可以做到这一切。有一个用于创建 GCC 扩展的相关项目称为GEM,但自 GCC 4.1 (2006) 以来尚未更新。
  • PUMA - 纯机械手。(来自页面:“该项目的目的是提供一个类库,用于分析和操作 C/C++ 源。为此,PUMA 提供了用于扫描、解析和操作 C/C++ 源的类。”) . 这看起来很有希望,但自 2001 年以来一直没有更新。显然 PUMA 已被合并到AspectC++中,但即使是这个项目自 2006 年以来也没有更新过。
  • 各种 C/C++ 原始语法。你可以得到c-c++-grammars-1.2.tar.gz,但它自 1997 年以来一直无人维护。谷歌搜索一下就可以找到其他可以作为起点的基本 lex/yacc 语法。
  • 还有其他人吗?

我希望以此为起点,将 C/C++ 源代码翻译成新的玩具语言。

谢谢!-马特

(添加 2/9):只是澄清一下:除了 C/C++ 代码本身之外,我还想从预处理器中提取语义信息。我不希望“#define foo 42”消失在整数“42”中,但仍与名称“foo”相关联。不幸的是,这排除了几个首先运行预处理器并且只提供 C/C++ 解析树的解决方案)

4

14 回答 14

35

解析 C++ 非常困难,因为语法是不可判定的。引用Yossi Kreinin 的话:

异常复杂的语法

“杰出”应该按字面解释,因为所有流行语言都有上下文无关(或“几乎”上下文无关)的语法,而 C++ 有不可判定的语法。如果你喜欢编译器和解析器,你可能知道这意味着什么。如果你不喜欢这种事情,有一个简单的例子来说明解析 C++ 的问题:是AA BB(CC);对象定义还是函数声明?事实证明,答案很大程度上取决于语句之前的代码——“上下文”。这表明(在直观的层面上)C++ 语法对上下文非常敏感。

于 2009-02-09T01:38:25.173 回答
21

您可以查看使用 llvm 进行解析的clang 。

现在完全支持 C++链接

于 2009-02-09T10:04:52.990 回答
17

ANTLR解析器生成器具有C/C++语法以及预处理器。我从来没有使用过它,所以我不能说它对 C++ 的解析有多完整。ANTLR 本身在一些场合对我来说是一个有用的工具,用于解析更简单的语言。

于 2009-02-09T03:05:44.760 回答
16

根据您的问题,GCCXML可能是您的答案。基本上,它使用 GCC 解析源代码,然后为您提供易于理解的解析树 XML。使用 GCCXML,您可以一劳永逸地完成。

于 2009-02-09T01:25:52.130 回答
14

pycparser是一个用 Python 编写的完整的 C (C99) 解析器。它有一个完全可配置的 AST 后端,因此它被用作您可能需要的任何类型的语言处理的基础。

不过不支持C++。当然,这C 难多了。


更新(2012 年):毫无疑问,此时的答案是Clang - 它是模块化的,支持完整的 C++(具有许多 C++-11 特性)并且具有相对友好的代码库。它还有一个用于绑定高级语言(即Python)的 C API。

于 2009-03-14T06:38:01.230 回答
8

看看doxygen是如何工作的,完整的源代码可用并且它是基于 flex 的。

一个误导性的候选者是GOLD,它是一个免费的基于 Windows 的解析器工具包,专门用于创建翻译器。他们支持的语言列表是指可以实现解析器的语言,而不是支持的解析语法列表。

他们只有 C 和 C# 的语法,没有 C++。

于 2009-02-09T01:03:38.220 回答
7

解析 C++ 是一项非常复杂的挑战

有 Boost/Spirit 框架,几年前他们确实有过实现 C++ 解析器的想法,但还远未完成

完全正确地解析 ISO C++ 绝非易事,实际上有很多相关的努力。但它本身就是一项复杂的工作,如果不重写理解所有 C++预处理器的完整编译器前端,就不容易完成。Spirit 人员提供了一个称为“wave”的预处理器实现。

也就是说,您可能想看看猪肉/oink(基于 elsa),这是一个 C++ 解析器工具包,专门用于源代码转换目的,Mozilla 项目正在使用它来进行大规模静态源代码分析和自动代码重写,最有趣的部分是它不仅支持大部分C++,还支持预处理器本身!

另一方面,确实有一个可用的专有解决方案:EDG 前端,它几乎可以用于所有与 C++ 相关的工作。

就个人而言,我会查看 Mozilla 使用的基于 elsa 的猪肉/oink 套件,除此之外,FSF 现在已经批准使用运行时库许可证对gcc 插件的工作,因此我认为事情会发生变化很快,一旦人们可以使用二进制插件轻松利用基于 gcc 的 C++ 解析器来实现此类目的。

所以,简而言之:如果你有钱:EDG,如果你现在需要一些免费/开源的东西:else/oink 是相当有前途的,如果你有时间,你可能想在你的项目中使用 gcc。

另一个仅适用于 C 代码的选项是cscout

于 2009-03-13T20:02:29.840 回答
6

C++ 的语法是出了名的多毛。Lambda上有一个关于它的好帖子,但要点是 C++ 语法可能需要任意多的前瞻。

对于我想你可能会做的那种事情,我会考虑破解 Gnu CC 或Splint。特别是 Gnu CC 确实非常彻底地分离了语言生成部分,因此您最好构建一个新的 g++ 后端。

于 2009-02-09T00:55:24.077 回答
4

实际上,PUMA 和 AspectC++ 仍然在积极维护和更新。我正在研究使用 AspectC++ 并且想知道自己缺乏更新。我给作者发了电子邮件,他说 AspectC++ 和 PUMA 仍在开发中。您可以通过 SVN https://svn.aspectc.org/repos/获得源代码,或者您可以在http://akut.aspectc.org获得常规的二进制构建。和现在很多优秀的c++项目一样,作者没有时间跟上网页维护。如果你有一份全职工作和生活,这是有道理的。

于 2010-08-30T20:46:48.490 回答
3

Elsa在 C++ 解析方面胜过我所知道的一切,即使它不是 100% 兼容的。我是一个粉丝。有一个打印出 C++ 的模块,因此这可能是您的玩具项目的一个很好的起点。

于 2009-02-09T10:02:22.730 回答
3

请参阅我们的C++ 前端 ,了解功能齐全的 C++ 解析器:构建 AST、符号表、进行名称和类型解析。您甚至可以解析和保留预处理器指令。C++ 前端构建在我们的DMS 软件再工程工具包之上,它允许您使用该信息通过源到源的转换来执行任意源代码更改。

DMS 是实现此类转换器的理想引擎。

话虽如此,我认为您想象的任务没有多大意义。我认为尝试替换 C++ 没有多大价值,而且您会发现构建一个完整的翻译器需要大量工作,尤其是当您的目标是“玩具”语言时。如果它的唯一目的是生成一个更易于解析的同构版本的 C++(等等,我们已经假设了一个健壮的 C++!),那么使用健壮的解析器解析 C++ 可能没有什么意义。

2012 年 5 月编辑:DMS 的 C++ 前端现在处理 GCC3/GCC4/C++11、Microsoft VisualC 2005/2010。稳健。

编辑 2015 年 2 月:现在处理 GCC 和 MS 方言中的 C++14。

编辑 2015 年 8 月:现在在统一的树中解析和捕获代码和预处理器指令。

编辑 2020 年 5 月:过去几年一直在做 C++17。C++20 正在进行中。

于 2009-06-17T15:06:23.397 回答
2

像tiny-CSmall C这样更容易理解的东西怎么样?

于 2009-02-09T00:59:41.443 回答
1

不久前,我尝试编写一个工具来自动为 c 文件生成单元测试。

为了进行预处理,我将文件通过 GCC。输出很难看,但您可以轻松地从预处理文件中追踪原始代码的位置。但为了您的需要,您可能需要其他东西。

我使用Meter作为 C 解析器的基础。它是开源的,使用 lex 和 yacc。这使得无需完全了解 lex 和 yacc 即可在短时间内轻松启动和运行。

我还编写了一个 C 应用程序,因为 lex 和 yacc 解决方案无法帮助我跨函数跟踪功能并一次性解析整个函数的结构。它在短时间内变得无法维护并被放弃。

于 2009-02-09T09:55:21.390 回答
1

使用像 GNU 的CFlow这样可以分析代码并生成调用图图表的工具怎么样,这就是opengroup(手册页)对 cflow 的看法。GNU版cflow自带源码,开源也...

希望这会有所帮助,最好的问候,汤姆。

于 2010-01-24T12:00:15.293 回答