从C代码构建AST

Asa*_*san 9 c gcc abstract-syntax-tree code-translation

如何从gcc C代码构建AST(抽象语法树)以进行一些修改,比如将一些int变量转换为float,然后再将代码重新生成(生成)到C语法.

实际上,目前,我真正需要的唯一功能是从包含几行的ac程序中提取变量及其类型的表...我认为有一个简单的解析器就是这样做的.

我有一些变量,如:

int  var_bss ;           
float var_f_bss;            
int var_data = 4;        
float var_f_data = 5;  
Run Code Online (Sandbox Code Playgroud)

功能:

int Foo(){          
   some local variables;            
}    
Run Code Online (Sandbox Code Playgroud)

代码位于单个c文件中.

我想向最终用户介绍所有变量,让他选择特定内存段中的源类型,例如.data中的int变量.然后用户可以将这些变量转换为浮点数.最后,我为用户生成相同的代码,但使用他选择的新变量类型.

Bas*_*tch 5

首先,这是一项艰巨的任务,因为 C 的抽象语法树比您认为的要复杂得多。有关详细信息,请阅读 C11 标准n1570,并查看网站。也看看tinyCCnwcc(至少是为了灵感)。

然后,如果您使用的是最近的 GCC(例如 4.7 或 4.8),我强烈建议自定义 GCC,例如使用MELT扩展(或您的GCC 插件)。

我不认为这是一项简单的任务,因为很可能您需要了解 GCC 内部表示的细节(至少GIMPLE

顺便说一句,MELT是(曾经)一种用于扩展 GCC 的领域特定语言,并且专为您梦寐以求的任务而设计。您将能够使用 MELT 转换内部 GCC 表示(Gimple 和 Tree-s)。在 2020 年的今天,由于缺乏资金,MELT 没有开展工作。

在 GCC 中(或在其他一些编译器中如Clang/LLVM中工作)的优点是你不必回吐一些 C 代码(这实际上比你想象的要困难得多);您只需转换内部编译器表示,也许最重要的是,您可以“免费”利用编译器总是做的许多事情:各种优化,如常量折叠、内联、公共子表达式消除等,等等。 ...

在 2020 年,您还可以考虑在最近的GCC 10 中使用libgccjit框架,并阅读这份报告草案(与Bismon相关;但另请参阅RefPerSys,与Bismon分享一些想法但没有代码 )。也可以试试Clang 静态分析器和/或Frama-C


Mor*_*sen 5

Eli Benderskypycparser是一个用 Python 编写的 C 源到源工具: https: //github.com/eliben/pycparser

它将解析 C99,并可以构建一个详细的解析树,其节点与 K&R“C 编程语言”附录 A ch 中的语法相匹配。13.《语法》。它是建立在 lex/yacc、flex/bison(无论称为 PLY)的 Python 伪实现之上的。

它有示例,而且非常容易上手。正如其他发帖者所说,将解析树缩减为最小 AST 并忽略所有不相关的细节是一项复杂的任务。

该项目也可以进行源到源的转换: https: //github.com/axw/cmonster/ CMonster 用 Python 编写并包装了 Clang API。

如果你想使用 GCC 来完成这个任务,你应该看看 MELT。还有另一个项目,脚本语言是JavaScript,但我不记得名字ATM了。

编辑:回复评论

是的,处理中间表示的框架称为TreeHydra,它已被放弃,但据我所知仍在工作。网上有一个年轻博士的视频教程。设计 TreeHydra 的家伙 - 我想我在谷歌视频中找到了它 - 解释了他选择 JS 作为界面语言是因为流行等。他看起来知识渊博且有魅力,我想这就是那个特定项目吸引我的原因:)还没有尝试过不过我自己也出来了。

我自己正在开发一个业余爱好控制流图和数据流分析工具,使用 Eli Bendersky 的框架作为构建块。在我尝试过的工具包中,Eli 的工具包确实看起来最有前途。加上来自这个特别酷的项目的灵感:Atul 的 Mini-C 编译器利用相同的 Lex/Yacc Python 端口 (PLY)。还没有做太多事情,但是比学习 libclang 更容易上手,尽管我确实认为这也是一条非常有前途的路线。

  • @creichen `pycparser` 不是 Clang 的包装器,它是基于 PLY 构建的。另一方面,“cmonster”包装了 Clang API (2认同)