Babylon-AST初探-代码生成(Create)
业余时间写了Babylon-AST的系列文章,这里是第一篇,后面还有三篇。趁着今天有空都一起发上来啦。
最近想研究react
转小程序
代码的,后来感觉跨度有些大,因为平时也会写一些vue
的代码,而且vue
和小程序
更接近一些,所以还是先做了一个vue
转小程序
的PoC。可是这些都不是重点啊,重点是在这一过程中学习并使用了babylon
的AST
。因为也是第一次接触,所以想写点笔记记录一下,也希望能给大家一点参考。
代码是写出来的,一定一定多写多练,所以我这里还是以实例代码为主,涉及到的点也是在vue
转小程序
中用到的,或者是转换的基础。可是也会有很多超出此范围的知识点,我们这里就先不做具体讨论啦,这里给出了一些参考资料,大家可以参考下。
涉及到的参考资料:
- AST explorer: https://astexplorer.net/ 神器,阅读和书写
AST
操作全靠它 - Babel Plugin Handbook https://github.com/jamiebuild... 从这里找到了一些
API
- Babylon和babel-traverse详解 https://github.com/xtx1130/bl... 其实也称不上详解,不过看到的比较早,算是篇启蒙文章吧
- Babel types https://babeljs.io/docs/core-... 生成代码时会大量用到
AST explorer查看代码
首先打开 https://astexplorer.net/ ,直接在代码里输入1
,查看基本效果。
我们要做的只是代码的转换,这里只需关心program.body
部分即可(是否可以操作tokens来更改代码,还没有研究)。
如上图,程序代码里只有一个表达式ExpressionStatement
。点击+
展开,可以看到内部的细节,如下图:
内部结构只有一个Literal
,非常简单。更复杂的代码,我们在后面再来解释。
AST 的CRUD(Create-Retrieve-Update-Delete)
1. Create
实际上,Create
是个相对复杂的操作,通常会结合Retrieve
和Update
使用。可以结合实际需要,选择阅读顺序。
首先,构造一个空的node
工程,后续会基于该项目一步步拓展。
npm install babylon @babel/types @babel/generator @babel/traverse
测试代码
const babylon = require('babylon')
const t = require('@babel/types')
const generate = require('@babel/generator').default
const traverse = require('@babel/traverse').defaultconst code = ''
const ast = babylon.parse(code)
// manipulate ast
const output = generate(ast, {}, code)
console.log('Input \n', code)
console.log('Output \n', output.code)
因为这里是空的code
,所以Input
和Output
都没有输出,只是搭一个代码结构。
构造一个1
的代码
根据上面的两个图,只有1
代码由一个ExpressionStatement
内嵌一个Literal
组成。直接代码如下,可以参考下注释。
const code = ''
const ast = babylon.parse(code)// 生成literal
const literal = t.numericLiteral(1)
// 生成expressionStatement
const exp = t.expressionStatement(literal)
// 将表达式放入body中
ast.program.body.push(exp)const output = generate(ast, {}, code)
console.log('Input \n', code)
console.log('Output \n', output.code)
运行输出
InputOutput1;
这个例子中首先用到了t
(babel-types)。可以在 https://babeljs.io/docs/core-... 查看文档。t
里面有类型判断和生成实例等方法。
如t.expressionStatement(literal)
就是生成一个ExpressionStatement
,这个函数要用到的参数在文档中(https://babeljs.io/docs/core-... 有描述,可是文档真心不好看,大家还是根据AST explorer中查找对应的方法,然后在文档看个参数就好了:
构造const a = 1
的代码
上述1
的代码过于简单,我们来生成const a = 1
的代码。将const a = 1
输入到AST explorer中,查看语法树信息如下图:
在这段代码中涉及了VariableDeclaration
, VariableDeclarator
, Identifier
, Literal
几个babel-types
,Literal
中使用的是数字类型NumericLiteral
。这时就可以分别查看文档了,比如:VariableDeclaration
这个t.variableDeclaration
有两个参数kind
和declarations
,第二个参数是个数组。
根据语法树,一层层的生成代码如下:
const code = ''
const ast = babylon.parse(code)// 生成 VariableDeclarator
const id = t.identifier('a')
const literal = t.numericLiteral(1)
const declarator = t.variableDeclarator(id, literal)// 生成 VariableDeclaration
const declaration = t.variableDeclaration('const', [declarator])// 将表达式放入body中
ast.program.body.push(declaration)const output = generate(ast, {}, code)
console.log('Input \n', code)
console.log('Output \n', output.code)
执行结果如下:
InputOutputconst a = 1;
Create
总结
根据AST explorer可以完美生成代码,常见的异常是参数没有填对,特别是数组什么的,一定要注意。多结合API文档和从小的代码片段做起能够规避这类错误。
最后,生成一个稍复杂一点的代码。
function add(a, b) {return a + b
}
AST树如下
感兴趣的同学可以先尝试根据语法树提示写一写,再看下面的对照代码,如果上面看懂了其实写这个真心不是很难了。
const code = ''
const ast = babylon.parse(code)// BinaryExpression a + b
const binaryExp = t.binaryExpression('+', t.identifier('a'), t.identifier('b'))
const returnStatement = t.returnStatement(binaryExp)// function body
const fnBody = t.blockStatement([returnStatement])
const params = [t.identifier('a'), t.identifier('b')]const fnDeclaraton = t.functionDeclaration(t.identifier('add'), params, fnBody)
ast.program.body.push(fnDeclaraton)const output = generate(ast, {}, code)
console.log('Input \n', code)
console.log('Output \n', output.code)
以上,就是AST
的Create
的介绍,想进一步学习的接着看后面几篇文章哦
Babylon-AST初探-代码生成(Create)相关推荐
- Babylon.js 第34章 合并网格
目录 一.合并网格方法 二.详细内容 一.合并网格方法 轻松地将多个网格合并到单个网格,请使用类的MergeMeshes静态Mesh var newMesh = BABYLON.Mesh.MergeM ...
- Vue源码流程图(函数名与源码对应)
这里写目录标题 概览 1. 变化侦查 1.1 Observer流程图 2. vdom虚拟DOM 2.1 创建节点createElm 2.2 更新节点patchVnode 2.3 更新子节点 updat ...
- Web3DGame之路,Babylonjs 和TypeScript学习笔记(二)
先来认识一下Babylonjs,由于基于webgl来开发,所以先介绍一下基础知识. Webgl是一个html标准,他要在canvas元素上初始化. Html页面上的准备 所以我们先从html页面开始看 ...
- 基础的VueJS面试题(附答案)
基础的VueJS面试题(附答案) 1.什么是MVVM框架?它适用于哪些场景? MVVM框架是一个 Model-View-View Model框架,其中 ViewModel连接模型Model)和视图(V ...
- 你不知道的 JavaScript 笔记——作用域和闭包
第一章:作用域是什么 程序中变量存储在哪里,需要是怎么找到它,这就需要设计一套存储以及能方便的找到它的规则,这个规则就是作用域 编译原理 JavaScript 是一门编译语言,它与传统编译语言不同,但 ...
- 深入理解js系列一作用域是什么
title: 深入理解js系列一作用域是什么? date: 2018-02-06 02:15:59 tags: 深入理解js系列 作用域 categories: JavaScript 作用域是什么? ...
- javascript脚本语言_10分钟快速掌握Javascript核心特性
JavaScript的历史版本 其中ES5个人认为是使用时间最长也是最稳定的版本.基于该版本衍生出来的很多经典框架诸如ext,propertype.js,jquery,easyUI都是这个时代的杰作. ...
- hibernate中antlr对于hql与sql的转换源码的一些细节
Hibernate 5.1.11Final 关于hql中的对象类转换成表名. 在from模块里对hql抽象语法树进行匹配的时候,在path()规则会还原在对hql进行语法解析的时候生成的语法树. pu ...
- vs 2015 C 语言,VS2015中C/C++代码分析
VS2015中C/C++代码分析 03/31/2015 8 分钟可看完 本文内容 [原文发表时间]:2015/2/24 1:00 PM 来自 Joe Morris & Jim Springfi ...
最新文章
- 每天九点十分开始每半小时一次执行一个cron_趣讲 PowerJob 超强大的调度层,开始表演真正的技术了...
- 网站的Http请求转为Https请求
- Python中的一些“小坑”
- Zen Coding css,html缩写替换大观 快速写出html,css
- Linux下按日期删除文件
- UFLDL教程: Exercise:Self-Taught Learning
- RocketMQ消费者是如何获取消息的?转疯了!
- mysql 走索引 很慢_MySQL优化:为什么SQL走索引还那么慢?
- 跟着百度学PHP[4]OOP面对对象编程-16-switch逻辑就语句
- 前端面试:如何修改overflow:scroll 滚动条的默认样式-如背景色以及宽度
- tornado celery mysql_tornado中使用celery实现异步MySQL操作
- nosql数据库基础
- 处理数据spss乱码
- Dos命令 --复制文件(夹)
- 计算机如何连接iphone,iphone怎么连接到电脑的方法详解【图文】
- AI绘图实战(一):制作购物车图标icon | Stable Diffusion成为设计师生产力工具
- Oracle 存储过程 in、out、in out 参数的使用方法
- 发起一场GitChat是什么体验?
- 【2023最新】Git安装配置教程
- 【Oracle】SCOTT用户和HR用户
热门文章
- C++大师Stan Lippman:我对中国程序员的忠告
- 自定义session,cookie
- 测试计划与测试方案的区别
- 总结:PHP值得注意的几个问题
- Nokia Lumia(WP7.5) 新手入门的摸索
- android Tabhost 组件
- SilverLight客户端搭建完善聊天室 测试网址swkzy.vicp.net
- 使用 Visual C# .NET 通过 XPath 表达式查询 XML
- Transaction rolled back because it has been marked as rollback-only 原因 和解决方案
- Linux_异常_01_CentOS7无法ping 百度