抽象语法树 c语言,一个简单的例子看懂抽象语法树的魔力
在计算机科学中,抽象语法树(Abstract Syntax Tree,AST),或简称语法树(Syntax tree),是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。
上面这是百度百科的定义,一如既往的让人摸不着头脑。
我们总结一下百度百科的定义:
抽象语法树是一颗树
树的每个节点都表示了源代码的一种 语法结构
上面这段总结有几个关键词:抽象语法树、树、节点、源代码、语法结构,其中语法结构是比较难理解的,那么什么是语法结构呢?
举几个简单的例子:
//变量声明
var a = 1;
复制代码
//循环
while(true){
console.log(1);
}
复制代码
//判断
if(true){
console.log(1);
}
复制代码
//函数声明
function a(){
console.log(1);
}
复制代码
以上这些例子是js的语法声明(statement),这种声明就可以看成js的语法结构! 也就是说抽象语法树的每个节点都在描述这种结构。
比如说一个节点是变量声明,那么这个节点的子节点都会去描述变量声明的具体内容:变量名是什么,变量是什么类型,变量的初始值是什么等等。
就是这样一个一个的声明,构成了抽象语法树。
代码执行的三个步骤
从js程序到机器可执行的机器码需要经历两个阶段:
语法检查
编译运行
语法检查又分为语法分析和词法分析,所以分成三个步骤就是:
词法分析
语法分析
编译运行
这里先简单介绍下每个阶段都干了什么活:
第一步:词法分析,也叫做扫描scanner。它读取我们的代码,然后把它们按照预定的规则合并成一个个的标识Tokens(type 和 value )。这个阶段,它会移除空白符,注释等。最后,整个代码将被分割进一个Tokens列表(一个一维数组)。
第二步:语法分析,也叫做解析器。它会将词法分析出来的Token数组转化成树形的表达形式。同时,验证语法,语法如果有错的话,抛出语法错误。
第三步:编译阶段,也叫编译器。这个阶段会处理AST,生成机器可执行的机械码。
词法分析
先以一个简单的例子看下token序列长什么样
var a = 1;
复制代码
他的token长这样
其实就是一个一维数组,里面有一些对象用于描述每个单词。
我整理了下常见的type:
Keyword (关键词)
Identifier (标识符)
Punctuator (标点符号)
Numberic(数字)
String (字符串)
Boolean(布尔)
Null(空值)
语法分析
词法分析由源代码生成了Token序列,语法分析则是由Token序列生成了抽象语法树。
还是看上一个例子:
var a = 1;
复制代码
他的抽象语法树长这样:
1、先看最外层的三个属性
type(表示是一段程序代码)
body(代码的具体内容)
sourceType(表示语言的种类)
2、再看body里面的具体内容,body是一个数组,这是因为程序可能有多个内容块(statement),每个内容块用一个对象表示。
3、再看每个内容块的内容
type(表示这个内容块是干什么的)
declarations(乘装变量内容的块,可以看到这个块也是一个数组,因为变量声明可能生命多个,所以一个生命对应一个对象 例如 var a=1,b=2;) kind(关键字)
4、再看declarations里面对象里面的内容
type (声明的类型是个变量)
id(表示变量名)
init(表示为这个变量设置的初值)
上面提到statement,statement有很多类型,比如说变量声明,函数定义,if语句,while循环,等都是一个statement,大家如果想看更多的类型,点击这里。
一个超级简单的例子
好了,说了这么多,终于要写代码了。
这个例子实现的功能:
将源代码中的 == 变成 ===
将源代码中的 var 变成 let
将源代码中的 console注释掉
这个例子用到的工具:
Esprima (将源代码转化为ast)
Estraverse(遍历语法树)
Escodegen(讲语法书反编译为js代码)
初始化一个项目
npm init
复制代码
安装用到的依赖包
npm install esprima estraverse escodegen --save
复制代码
新建index.js入口文件 和 originCode.js 源代码文件
在 originCode.js 中输入要转换的源代码
function fun() {
var opt = 1;
console.log(1);
if (opt == 1) {
console.log(2);
}
}
复制代码
在 index.js 中实现我们的功能
let fs = require('fs');
const esprima = require('esprima');//将JS代码转化为语法树模块
const estraverse = require('estraverse');//JS语法树遍历各节点
const escodegen = require('escodegen');//将JS语法树反编译成js代码模块
/**
* 由源代码得到抽象语法树
*/
function getAst(jsFile) {
let jsCode;
return new Promise((resolve)=>{
fs.readFile(jsFile, (error, data) => {
jsCode = data.toString();
resolve(esprima.parseScript(jsCode));
});
});
}
/**
* 设置全等
*/
function setEqual(node) {
if (node.operator === '==') {
node.operator = '===';
}
}
/**
* 删除console
*/
function delConsole(node) {
if (node.type === 'ExpressionStatement' && node.expression.type === 'CallExpression' && node.expression.callee.object.name==='console') {
node.expression.callee.object.name = '//console';
}
}
/**
* 把var变成let
*/
function setLet(node){
if(node.kind === 'var'){
node.kind = 'let';
}
}
/**
* 遍历语法树
*/
function travel(ast){
estraverse.traverse(ast, {
enter: (node) => {
setEqual(node);
setLet(node);
delConsole(node);
}
});
}
/**
* 生成文件
*/
function writeCode(file,data) {
fs.writeFile(file,data,(error)=>{
console.log(error);
});
}
/**
* 入口函数
*/
function main(){
let file = './originCode.js';
let distFile = './distCode.js';
getAst(file).then(function(jsCode) {
travel(jsCode);
// 删掉 console , 通过parseScript在生成一变ast去掉注释的内容
// let distCode = escodegen.generate( esprima.parseScript( escodegen.generate(jsCode)));
// 注释 console
let distCode = escodegen.generate(jsCode);
console.log('distcode',distCode);
writeCode(distFile,distCode);
});
}
main();
复制代码
然后运行我们的项目
node index.js
复制代码
distCode.js的内容已经变成我们想要的了
function fun() {
let opt = 1;
//console.log(1);
if (opt === 1) {
//console.log(2);
}
}
复制代码
抽象语法树 c语言,一个简单的例子看懂抽象语法树的魔力相关推荐
- 一个简单的例子看java线程机制
一个简单的例子看java线程机制 作者: zyf0808 发表日期: 2006-03-26 11:20 文章属性: 原创 复制链接 import java.util.*; public class T ...
- 抽象语法树 c语言,AST抽象语法树
AST抽象语法树 why主流项目插件的用途: javascript转译.代码压缩.css预处理.eslint.prettier等都建立在AST的基础上. whataccording to the gr ...
- SQL 引擎如何把语句转换为一个抽象语法树?
"select * from tb_user where userid > 10;"这是再简单不过的一条sql语句,从表tb_user中筛选出userid大于10的所有记录. ...
- 【编译原理】构建一个简单的解释器(Let’s Build A Simple Interpreter. Part 7.)(笔记)解释器 interpreter 解析器 parser 抽象语法树AST
[编译原理]让我们来构建一个简单的解释器(Let's Build A Simple Interpreter. Part 7.) 文章目录 python代码 插--后序遍历 C语言代码(有错误) C语言 ...
- 抽象语法树 Abstract syntax tree
什么是抽象语法树? 在计算机科学中,抽象语法和抽象语法树其实是源代码的抽象语法结构的树状表现形式 在线编辑器 我们常用的浏览器就是通过将js代码转化为抽象语法树来进行下一步的分析等其他操作.所以将js ...
- php7 ast,PHP7 的抽象语法树(AST)带来的变化
什么是抽象语法树? 抽象语法树(abstract syntax tree,AST)是源代码的抽象语法结构的树状表示,树上的每个节点都表示源代码中的一种结构,这所以说是抽象的,是因为抽象语法树并不会表示 ...
- PHP程序运行流程:语法分析(Parse)与抽象语法树(AST),PHP-Parser
什么是抽象语法树? 在 PHP5中,从 php 脚本到 Opcodes 的执行的过程是: Lexing:词法扫描分析,将源文件转换成 Token 流: Parsing:语法分析,在此阶段生成 Opco ...
- 抽象语法树mysql_抽象语法树简介(ZZ)
转载自: http://www.cnblogs.com/cxihu/p/5836744.html (一)简介 抽象语法树(abstract syntax code,AST)是源代码的抽象语法结构的树状 ...
- php ast 抽象语法树,抽象语法树(AST)
抽象语法树入门到放弃? 抽象语法树(Abstract syntax tree AST)在计算机科学中,抽象语法和抽象语法树其实是源代码的抽象语法结构的树状表现形式 为什么是抽象的? 前端工程化,离不了 ...
最新文章
- MYSQL 5.7 主从复制 -----GTID说明与限制 原创
- PostgreSQL处理xml数据初步
- 洛谷P1352 没有上司的舞会(树形DP水题)
- SAP Spartacus 和Jerry Sandbox应用Store引用的source字段类型差异
- Electron - 创建跨平台的桌面客户的应用程序
- php 制作ppt,PPT制作三个基本要素是什么?
- mfc 如何判断excel软件是否打开_如何从无到有地搭建一套完整的测试系统(上)...
- iTOP-4418/6818开发板-QtE4.7WIFI_MT6620热点
- ssh 远程锁住解锁_Linux 中锁定和解锁用户帐户的三种方法
- html 标签置底,学习笔记:让元素永久置底的几种方案(css only)
- 用 Python 发电子邮件
- python京东注册账号_玩转京东支付(python)
- Qt显示当前时间(年-月-日 时:分:秒 周几)
- 产品经理知识框架+求职面经——快手,字节跳动,
- TTL与非门多余的输入端处置办法及其优缺点
- binutils工具集——ld的用法
- 阿里3年被裁,赔偿n+3,到手30多万!感谢阿里让我人生开挂!
- 微信小程序开发者工具-使用技巧(更新中~)
- FULENT软件测试工程师头像,关于ANSYS总部测试案例3之FLUENT软件中湍流管道压降的测试报告20141230.pdf...
- c语言 不编译一段代码,为什么同一个程序.c就可以.cpp就无法编译
热门文章
- 牛腩——服务器标记格式不对
- 在圣诞节让你的macos飘雪花的小秘诀
- 思一独角兽 | 你对金融科技之都、花园城市新加坡的了解有多少?
- cnn模型训练——从环境搭建到模型部署
- 你好,CSDN,神奇的笔记分享平台
- 网友:Photoshop太贵,用不起,Adobe:拿去用,不要钱
- ASCII值的用处及其对应符号的打印方法
- vue 获取dom子元素_vue获取dom元素注意事项
- html滚动字幕鼠标悬停,一个非常好用的文字滚动的案例,鼠标悬浮可暂停[两种方案任选]...
- 【小程序websocket前后端交互】uniapp写微信小程序聊天功能功能,websocket交互功能,心跳重连【详细注释,复制即用】