基于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等等。

2、接着,调用对应的VisitXXX()方法,进行具体的操作;
3、最后,在遇到接下来的语句再调用对应的TraverseDecl、TraverseStmt等等,递归执行。
有人说,访问者模式比较适用于对已有功能的重构,或者说对一个项目已经完成,它的元素类型、数据结构已经定的差不多,而对数据的操作还有可能后序会改变。这样,可以使用访问者模式对原有的代码进行重构一遍。
基于Clang的Source to Source源代码转换(一)的更多相关文章
- 打造基于Clang LibTooling的iOS自动打点系统CLAS(二)
1. 配置LLVM和Clang 在这篇文章里,我们会基于上一篇所述的方案进行展开,详细讲解如何从0开始创建一个基于Clang LibTooling的编译器前端工具.在开始之前,我们假设你已经基本了解何 ...
- 数据的异构实战(一) 基于canal进行日志的订阅和转换
什么是数据的异构处理.简单说就是为了满足我们业务的扩展性,将数据从某种特定的格式转换到新的数据格式中来. 为什么会有这种需求出现呢? 传统的企业中,主要都是将数据存储在了关系型数据库中,例如说MySQ ...
- Java To CSharp源代码转换
前言 开发环境 客户端:Unity3D开发(C#) 服务器:Java (基于Java7) 日 期:2016年09月 需求说明 部分服务器的部分逻辑功能在客户端实现一遍,可以简单的理解为服务器的部分 ...
- 打造基于Clang LibTooling的iOS自动打点系统CLAS(一)
1. 手动打点的弊端 在很多ios工程师的日常工作中,不但要对接产品提出的功能性需求,还会收到产品出于数据统计分析需求目的而提出的附带的隐形需求:统计打点.大多数公司的基础框架层都会对统计打点功能做高 ...
- 打造基于Clang LibTooling的iOS自动打点系统CLAS(三)
1. 源码变换 第一章我们提到过,CLAS的本质是对源码做一次非常简单的变换(有些文章里称作变形),即Source-Source-Transformation,将打点代码精确地插入到目标函数的首部,保 ...
- SSIS 使用OLEDB/ADO NET Source 数据流source控件 连接Oracle失败
在做数据提取的时候发现一个非常奇怪的问题. Oracle客户端是安装正确并且Toad可以正常运行的,但是在新建OLEDB/ADO NET Source 数据流source控件连接Oracle的时候一直 ...
- DirectShow中写push模式的source filter流程 + 源代码(内附详细注释)
虽然网上已有很多关于DirectShow写source filter的资料,不过很多刚开始学的朋友总说讲的不是很清楚(可能其中作者省略了许多他认为简 单的过程),读者总希望看到象第一步怎么做,第二步怎 ...
- 在使用Reference Source调试.Net 源代码时如何取消optimizations(代码优化)-翻译
在使用PDB调试XAF时,发现好多变量都看不到.都被优化掉了. 下面的方法可以解决. 当你在使用Reference Source functionality in VS 2008 调试.Net 的源代 ...
- .NET Core使用Source Link提高源代码调试体验和生产效率
前言: 在我们日常开发过程中常常会使用到很多其他封装好的第三方中间件(NuGet依赖项).类库或者是.NET框架中自带的库.但是当你想要对这些类库的方法设置断点调试,然后发现无法F11(逐语句)调试进 ...
随机推荐
- Flink - NetworkEnvironment
NetworkEnvironment 是一个TaskManager对应一个,而不是一个task对应一个 其中最关键的是networkBufferPool, operator产生的中间结果,Result ...
- (。・・)ノ~个人java学习随笔记录
基本认识 1.编程思维 根据这几天的java学习,编写程序最重要的就是要有一个清晰的思路.语法上的错误可以跟随着不断的联系与学习来弥补,清晰的思维却只有自己来前期模仿,后面慢慢摸索形成一套属于自己的思 ...
- JSON与String 格式的转换
JSON 可以用 .push() 添加新数据 var json =[ { title:"1",content:"Tom" }, { title:"2& ...
- yii2 查询去重
- Selenium2学习-040-JavaScript弹出框(alert、confirm、prompt)操作演示实例
弹出框是网页自动化测试常见得操作页面元素之一,常见的JavaScript弹出框有如下三种: 1.alert(message):方法用于显示带有一条指定消息和一个 OK 按钮的警告框.DemoAlert ...
- 使用CXF框架集成Spring实现SOAP Web Service
- varnish4.1 配置文件default.vcl
varnish4.1 配置文件default.vcl # This .x VCL file vcl 4.0; backend default { .host = "127.0.0.1&quo ...
- 总结运行SSIS包的几种方式
方式一: 在BIDS里直接跑. 这个BIDS指的就是SQL Server Business Intelligence Development Studio,对于.net开发者来说它就是Visual S ...
- aix磁盘分区挂载问题
aix在进行磁盘分区挂载时,可能会报错
- 手机移动端WEB资源整合
meta基础知识 H5页面窗口自动调整到设备宽度,并禁止用户缩放页面 <meta name="viewport" content="width=device-wid ...