如何从gcc C代码构建AST(抽象语法树)以进行一些修改,例如将一些int变量转换为float,然后再将代码重新生成(生成)到C语法。
实际上,目前,我真正需要的唯一功能是从包含几行的c程序中提取变量及其类型表...我认为有一个简单的解析器就是这样做的。
我有一些变量,如:
int var_bss ;
float var_f_bss;
int var_data = 4;
float var_f_data = 5;
一个功能:
int Foo(){
some local variables;
}
代码位于单个c文件中。
我想向最终用户介绍所有变量,让他选择特定内存段中的源类型,例如.data中的int变量。然后用户可以将这些变量转换为浮点数。最后,我为用户生成了相同的代码,但是使用了他选择的新变量类型。
答案 0 :(得分:4)
首先,这是一项艰巨的任务,因为C的抽象语法树比你认为的要复杂得多。
然后,如果您使用的是最近的GCC(例如4.7或4.8),我强烈建议自定义GCC ,例如使用MELT扩展名(或某些GCC插件)。
我并不认为这是一项简单的任务,因为很可能您需要了解GCC内部表示的细节。
BTW, MELT 是一种扩展GCC的领域特定语言,专为您梦寐以求的任务而设计。您可以使用MELT转换内部GCC表示(Gimple和Tree-s)。
在GCC内部(或者在Clang / LLVM之类的其他编译器中)工作的优点是你不必吐出一些C代码(这实际上比你想象的要困难得多);你只需转换内部编译器表示,也许最重要的是,你利用“免费”编译器总是做的很多事情:所有类型的优化,如常量折叠,内联,共同子表达式消除等等,......等。
答案 1 :(得分:4)
Eli Bendersky的pycparser
是一个用Python编写的C源到源工具:https://github.com/eliben/pycparser
它将解析C99并且可以构建详细的解析树,其节点与K& R“C编程语言”附录A ch中的语法匹配。 13“语法”。它建立在lex / yacc,flex / bison的Python伪实现上,无论是什么称为PLY。
它有例子,它很容易上手。就像其他海报所说的那样,将解析树减少到最小AST并且遗漏了所有不相关的细节是一项复杂的任务。
此项目也可以进行源到源转换:https://github.com/axw/cmonster/ CMonster是用Python编写的,包含了Clang API。
如果您想使用GCC完成任务,您应该查看MELT。还有另一个项目,其中脚本语言是JavaScript,但我不记得名称ATM ..
编辑:回复评论
是的,处理中间表示的框架被称为TreeHydra并且它被放弃了,但是我仍然可以看到。有一个年轻博士在线的视频教程。设计TreeHydra的家伙 - 我认为我发现它与谷歌视频 - 解释他选择JS作为界面语言因为受欢迎等他出现了知识和魅力,我想这是特定项目卡住我的原因:)没试过不过我自己。
我自己正在使用Eli Bendersky的框架作为构建块,从事业余爱好控制流程图和数据流分析工具。在我试过的工具包中,Eli的工具包看起来真的很有前途。结合这个特别酷的项目的灵感:Atul's Mini-C Compiler使用相同的Lex / Yacc Python端口(PLY)。还没有做太多,但是比学习libclang更容易上手,尽管我也认为这是一条非常有前途的路线。
答案 2 :(得分:3)
您要求的是C源到源变换器。这样的工具很难构建,部分原因是由于C的固有复杂性,部分是因为C预处理器:AST可能包含来自系统头部等的碎片,你需要在解析时正确处理(在C再次发出C代码)结束)。
你可以试试Robert Grimm的SuperC:https://cs.nyu.edu/rgrimm/xtc/ 该特定解析器应该处理所有C(包括预处理器位)。我不知道它是否可以处理解析,但这应该相对容易(阅读:仍有很多工作要做)。