基于Clang的Source to Source源代码转换(一)

Clang中包含了非常多的关于抽象语法树(AST)的访问和操作的类和接口。我们程序开发人员可以直接通过继承其中的某些类,重写其中的关键成员方法,从而形成我们自己的对抽象语法树的操作。

那么,首先我们简要介绍几个概念:

抽象语法树(AST):抽象语法树是源代码的抽象语法结构的树状表现形式。树上的每个节点都表示源代码中的一种结构。之所以说语法是“抽象”的,是因为这里的语法并不会表示出真实语法中出现的每个细节。一般的,在源代码的翻译和编译过程中,语法分析之后会创建出抽象语法树。一旦AST被创建出来,在后续的处理过程中,比如语义分析阶段,会添加很多语义信息帮助进行后续的语义翻译工作。AST其实就是一个程序的静态模型,它抽象出了一个程序在静态时结构状态,我们可以通过对AST的分析从而了解一个程序的相关静态信息。

Source to Source转换:我所理解的源到源的转换可以简单的当做是从一种源代码的形式转换到另一种源代码的形式。这其中,形式的定义很宽泛,包括了最简单的源代码风格、变量函数的命名到不同的编程语言。这些的转换都可以成为source to source transformation。

那么,如果要进行源到源的转换,最直接的思路和方式就是通过获得一个程序代码片段的抽象语法树(AST),然后通过修改AST的若干子树或若干结点,然后将AST转换成源代码,从而完成源到源的转换。

既然,我们已经明白了我们的目标和途径,那么接下来就介绍一下Clang中的基于AST的操作以及它们的设计模式。

Clang中的AST部分操作和表示的设计和实现比较类似于设计模式中的访问者模式。

Stmt

Stmt是表示程序语言语法成分的最原始的抽象基类接口,而我们的其他各种语法类型则是继承Stmt,如IfStmt,NullStmt,DeclStmt等等。它们相当于是访问者模式中的Element和ConcreteElement。元素类和抽象元素类。
RecursiveASTVisitor
RecursiveASTVisitor类似于访问者模式中的访问者。
我们在实现自己的操作AST的方法时需要继承自RecursiveASTVisitor类,并重写其中的多个方法,一般为bool VisitXXX(Stmt* stmt)方法。每一个VisitXXX方法都是访问某个具体对应类型的Stmt结点并对它进行操作的函数。
所以RecursiveASTVisitor和我们写的Visitor类就相当于抽象访问者类和访问者类。
ASTConsumer
ASTConsumer类的主要功能是提供一种自顶向下的对抽象语法树进行访问的入口。因为AST中包含了各种各样的Stmt,所以也可以认为ASTConsumer类似于提供了访问这个包含多种类型Stmt的容器的入口。因此我们可以将它对应到访问者模式中的ObjectStructure和Client。在这其中有多种方法来遍历当前程序生成的抽象语法树AST,从而获得各种各样类型的AST Node。因此,我们需要自己实现一个继承自ASTConsumer得类,并重写其中的遍历AST的方法,如:HandleTopLevelDecl,HandleTranslationUnit等等。

最后,我们还可以加入了FrontendAction等类,让我们绑定相关的编译器CompilerInstance信息等等,这些具体的部分我们放在下一篇文章中进行分析。

因此,我们在使用Clang进行AST操作时的主要流程是:分别继承RecursiveASTVisitor类和ASTConsumer类并重写其中对应的方法,如图中红色标识的类。

整个过程的表示如下:

根据我们设定好的前序或后序深度优先的访问方式,对于一个已经构建好的AST,完成以下工作:

1、从抽象语法树的根节点开始,当遇到一个 AST节点时,根据它的类型调用对应的TraverseXXX()方法;
2、接着,调用对应的VisitXXX()方法,进行具体的操作;
3、最后,在遇到接下来的语句再调用对应的TraverseDecl、TraverseStmt等等,递归执行。

因为基于C++语言的基本的语法类型已经不会怎么变动了(如if语句、class声明语句、循环语句等等),而对于每一个AST结点的操作确实需要随时按需求修改的,需要将数据结构的抽象和对数据结构的操作进行分离,所以比较满足了访问者模式的基本要求。

有人说,访问者模式比较适用于对已有功能的重构,或者说对一个项目已经完成,它的元素类型、数据结构已经定的差不多,而对数据的操作还有可能后序会改变。这样,可以使用访问者模式对原有的代码进行重构一遍。

时间: 2024-12-28 14:06:23

基于Clang的Source to Source源代码转换(一)的相关文章

让source insight的源代码文件显示字体变大

让source insight的源代码文件显示字体变大source insight version 4.00.0084 options->file type options->screen font->选中,然后键入yes.这样,所有的文件的字体大小都改变了. 原文地址:https://www.cnblogs.com/praiseslow/p/11478611.html

[转]基于clang插件的一种iOS包大小瘦身方案

转自:http://mp.weixin.qq.com/s?__biz=MzA3ODg4MDk0Ng==&mid=2651112856&idx=1&sn=b2c74c62a10b4c9a4e7538d1ad7eb739 iOS包瘦身,对于一般团队来说并不是优化的首要目标,但是对于一些安装包已经超限的团队来说非常关键.微信和阿里移动安全都分享过相关的内容,后者采用的是去除无用代码的思路,感兴趣的同学可以阅读: iOS瘦身之删除无用的mach-O文件 而本文则将这个思路发挥到了极致,欢迎

在使用Reference Source调试.Net 源代码时如何取消optimizations(代码优化)-翻译

在使用PDB调试XAF时,发现好多变量都看不到.都被优化掉了. 下面的方法可以解决. 当你在使用Reference Source functionality in VS 2008 调试.Net 的源代码的时候,你会发现很多变量没法再调试时查看. 这是因为源代码服务器上提供的代码默认是为最终销售优化过的(optimized ).这些值虽然你没法查看,但不会阻断单步执行,大部分情况下你可能不需要查看. 但如果你真的需要查看,这里还是有一个办法的. 你需要靠诉CLR不要加载pre-JIT(也加NGEN

DirectShow中写push模式的source filter流程 + 源代码(内附详细注释)

虽然网上已有很多关于DirectShow写source filter的资料,不过很多刚开始学的朋友总说讲的不是很清楚(可能其中作者省略了许多他认为简 单的过程),读者总希望看到象第一步怎么做,第二步怎么做....这样的demo.其实写你的第一个filter是有一定难度的,只要过了这关以后 就容易多了.由于最近需要自己写一个push推模式的source filter,加上刚激活了Blog,不好意思Blog上没有一篇文章,所以将写这个filter的过程写下来 ,为了照顾刚开始学的朋友,我采用第一步第

基于CentOS 6.8平台最新源代码包MariaDB数据库企业版安装

安装环境 系统:CentOS 6.8 x86_64 MariaDB:enterprise 10.1.16 资源获取 MariaDB企业版下载,访问地址 https://mariadb.com/my_portal/download/mariadb-enterprise 这里需要登录帐号才能下载,可以免费注册. 登录成功后进入MariaDB企业版产品下载页面,这里提供了二进制与源代码等多种安装包.根据实际需求选择版本10.1.16GA,源代码包下载. 确定tar.gz包下载 得到下载地址,复制到Ce

基于ANYCAD的DXF文件读取与转换

写这篇文章的目的是我这段时间关于ANYCAD的一些学习感悟,并且附上具体的操作,使新手少走一些弯路. 本人是C#的新手,从来没接触过编程,暑期跟着老师做学习,第一个任务就是用C#打开DXF文件,我以为任务很简单,BUT 在网上搜索一大堆,都是没用的(对于我这个新手来讲),偶然一次看到一篇<基于AnyCAD.net 三维图形平台快速搭建DXF文件的读取.显示.转换成JPG, PNG,以及PDF>,了解了这个ANYCAD这个控件,但是这篇文章在我把代码输进去操作的时候发现对于我这个新手来说没太大用

基于单细胞测序数据构建细胞状态转换轨迹(cell trajectory)方法总结

细胞状态转换轨迹构建示意图(Trapnell et al. Nature Biotechnology, 2014) 在各种生物系统中,细胞都会展现出一系列的不同状态(如基因表达的动态变化等),这些状态(state)之间会按照一定的时间顺序转换.最典型的比如细胞的分化过程,从不成熟的细胞逐渐分化为成熟细胞.此外,细胞在受到外界刺激或扰动时,细胞内基因的表达也可能发生一系列的变化,从而呈现出一系列状态的转换. 这些特别提一下,细胞状态(cell state)和细胞亚型(cell subtype)是两

基于CentOS 6.8平台最新源代码包编译安装LNMP环境搭建(Nginx+MySQL+PHP)

部署环境 系统:CentOS 6.8 x86_64 Nginx:1.11.3 MySQL:5.7.14 PHP:7.0.10 pcre:8.39 zlib:1.2.8 openssl:1.0.1t freetype:2.6.5 libmcrypt:2.5.8 boost:1.59.0 cmake:3.6.1 部署准备 使用客户机浏览器访问freetype官网 https://www.freetype.org/ 下载页面选取一个下载地址 下载目前最新发行版本,右击-复制下载链接. 在CentOS服

基于CentOS 6.8平台最新源代码包LAMP环境搭建(Apache+MySQL+PHP)

部署环境 系统:CentOS6.8 x86_64 Apache:2.4.23 MySQL:5.7.14 PHP:7.0.10 apr:1.5.2 apr-util:1.5.4 boost:1.59.0 cmake:3.6.1 pcre:8.39 软件包准备 这里CentOS6.8系统(无需图形环境)的安装过程略,使用个人电脑(Windows系统)的浏览器访问Apache官方网站 http://www.apache.org/ 点击下载页面标签 点击建议的镜像下载站点 找到apr目录 这里下载最新版