业余时间写了Babylon-AST的系列文章,这里是第一篇,后面还有三篇。趁着今天有空都一起发上来啦。

  最近想研究react小程序代码的,后来感觉跨度有些大,因为平时也会写一些vue的代码,而且vue小程序更接近一些,所以还是先做了一个vue小程序的PoC。可是这些都不是重点啊,重点是在这一过程中学习并使用了babylonAST。因为也是第一次接触,所以想写点笔记记录一下,也希望能给大家一点参考。

  代码是写出来的,一定一定多写多练,所以我这里还是以实例代码为主,涉及到的点也是在vue小程序中用到的,或者是转换的基础。可是也会有很多超出此范围的知识点,我们这里就先不做具体讨论啦,这里给出了一些参考资料,大家可以参考下。

涉及到的参考资料:

  1. AST explorer: https://astexplorer.net/ 神器,阅读和书写AST操作全靠它
  2. Babel Plugin Handbook https://github.com/jamiebuild... 从这里找到了一些API
  3. Babylon和babel-traverse详解 https://github.com/xtx1130/bl... 其实也称不上详解,不过看到的比较早,算是篇启蒙文章吧
  4. 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是个相对复杂的操作,通常会结合RetrieveUpdate使用。可以结合实际需要,选择阅读顺序。

  首先,构造一个空的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,所以InputOutput都没有输出,只是搭一个代码结构。

构造一个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-typesLiteral中使用的是数字类型NumericLiteral。这时就可以分别查看文档了,比如:VariableDeclaration

  这个t.variableDeclaration有两个参数kinddeclarations,第二个参数是个数组。

  根据语法树,一层层的生成代码如下:

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)

  以上,就是ASTCreate的介绍,想进一步学习的接着看后面几篇文章哦

Babylon-AST初探-代码生成(Create)相关推荐

  1. Babylon.js 第34章 合并网格

    目录 一.合并网格方法 二.详细内容 一.合并网格方法 轻松地将多个网格合并到单个网格,请使用类的MergeMeshes静态Mesh var newMesh = BABYLON.Mesh.MergeM ...

  2. Vue源码流程图(函数名与源码对应)

    这里写目录标题 概览 1. 变化侦查 1.1 Observer流程图 2. vdom虚拟DOM 2.1 创建节点createElm 2.2 更新节点patchVnode 2.3 更新子节点 updat ...

  3. Web3DGame之路,Babylonjs 和TypeScript学习笔记(二)

    先来认识一下Babylonjs,由于基于webgl来开发,所以先介绍一下基础知识. Webgl是一个html标准,他要在canvas元素上初始化. Html页面上的准备 所以我们先从html页面开始看 ...

  4. 基础的VueJS面试题(附答案)

    基础的VueJS面试题(附答案) 1.什么是MVVM框架?它适用于哪些场景? MVVM框架是一个 Model-View-View Model框架,其中 ViewModel连接模型Model)和视图(V ...

  5. 你不知道的 JavaScript 笔记——作用域和闭包

    第一章:作用域是什么 程序中变量存储在哪里,需要是怎么找到它,这就需要设计一套存储以及能方便的找到它的规则,这个规则就是作用域 编译原理 JavaScript 是一门编译语言,它与传统编译语言不同,但 ...

  6. 深入理解js系列一作用域是什么

    title: 深入理解js系列一作用域是什么? date: 2018-02-06 02:15:59 tags: 深入理解js系列 作用域 categories: JavaScript 作用域是什么? ...

  7. javascript脚本语言_10分钟快速掌握Javascript核心特性

    JavaScript的历史版本 其中ES5个人认为是使用时间最长也是最稳定的版本.基于该版本衍生出来的很多经典框架诸如ext,propertype.js,jquery,easyUI都是这个时代的杰作. ...

  8. hibernate中antlr对于hql与sql的转换源码的一些细节

    Hibernate 5.1.11Final 关于hql中的对象类转换成表名. 在from模块里对hql抽象语法树进行匹配的时候,在path()规则会还原在对hql进行语法解析的时候生成的语法树. pu ...

  9. vs 2015 C 语言,VS2015中C/C++代码分析

    VS2015中C/C++代码分析 03/31/2015 8 分钟可看完 本文内容 [原文发表时间]:2015/2/24 1:00 PM 来自 Joe Morris & Jim Springfi ...

最新文章

  1. 每天九点十分开始每半小时一次执行一个cron_趣讲 PowerJob 超强大的调度层,开始表演真正的技术了...
  2. 网站的Http请求转为Https请求
  3. Python中的一些“小坑”
  4. Zen Coding css,html缩写替换大观 快速写出html,css
  5. Linux下按日期删除文件
  6. UFLDL教程: Exercise:Self-Taught Learning
  7. RocketMQ消费者是如何获取消息的?转疯了!
  8. mysql 走索引 很慢_MySQL优化:为什么SQL走索引还那么慢?
  9. 跟着百度学PHP[4]OOP面对对象编程-16-switch逻辑就语句
  10. 前端面试:如何修改overflow:scroll 滚动条的默认样式-如背景色以及宽度
  11. tornado celery mysql_tornado中使用celery实现异步MySQL操作
  12. nosql数据库基础
  13. 处理数据spss乱码
  14. Dos命令 --复制文件(夹)
  15. 计算机如何连接iphone,iphone怎么连接到电脑的方法详解【图文】
  16. AI绘图实战(一):制作购物车图标icon | Stable Diffusion成为设计师生产力工具
  17. Oracle 存储过程 in、out、in out 参数的使用方法
  18. 发起一场GitChat是什么体验?
  19. 【2023最新】Git安装配置教程
  20. 【Oracle】SCOTT用户和HR用户

热门文章

  1. C++大师Stan Lippman:我对中国程序员的忠告
  2. 自定义session,cookie
  3. 测试计划与测试方案的区别
  4. 总结:PHP值得注意的几个问题
  5. Nokia Lumia(WP7.5) 新手入门的摸索
  6. android Tabhost 组件
  7. SilverLight客户端搭建完善聊天室 测试网址swkzy.vicp.net
  8. 使用 Visual C# .NET 通过 XPath 表达式查询 XML
  9. Transaction rolled back because it has been marked as rollback-only 原因 和解决方案
  10. Linux_异常_01_CentOS7无法ping 百度