const esprima = require('esprima')
const estraverse = require('estraverse')
const escodegen = require('escodegen')
let code = `var a = 3`
// Parse(解析)
let ast = esprima.parseScript(code);
//Transform(转换)
estraverse.traverse(ast, {
enter(node) {
console.log("enter",node.type);
},
leave(node) {
console.log("leave",node.type);
}
});
// Generate(代码生成)
const result = escodegen.generate(ast);
首先,先说明下该文章是译文,原文出自《AST for JavaScript developers》(https://itnext.io/ast-for-javascript-developers-3e79aeb08343)。很少花时间特地翻译一篇文章,咬文嚼字是件很累的事情,实在是这篇写的太棒了,所以忍不住想和大家一起分享。
该译文出自我的博客:https://github.com/CodeLittlePrince/blog/issues/19,我的博客会不定时更新各种类型文章,希望大家支持。
OK,我们直接进入正题。
如果你查看目前任何主流的项目中的 devDependencies,会发现前些年的不计其数的插件诞生。我们归纳一下有:javascript 转译、代码压缩、css 预处理器、elint、pretiier,等。有很多 js 模块我们不会在生产环境用到,但是它们在我们的开发过程中充当着重要的角色。所有的上述工具,不管怎样,都建立在了 AST 这个巨人的肩膀上。
所有的上述工具,不管怎样,都建立在了 AST 这个巨人的肩膀上。
我们定一个小目标,从解释什么是 AST 开始,然后到怎么从一般代码开始去构建它。我们将简单地接触在 AST 处理基础上,一些最流行的使用例子和工具。并且,我计划谈下我的 js2flowchart 项目,它是一个不错的利用 AST 的 demo。OK,让我们开始吧。
It is a hierarchical program representation that presents source code structure according to the grammar of a programming language, each AST node corresponds to an item of a source code.
估计很多同学会和图中的喵一样,看完这段官方的定义一脸懵逼。OK,我们来看例子:
这很简化。
实际上,正真 AST 每个节点会有更多的信息。但是,这是大体思想。从纯文纯中,我们将得到树形结构的数据。每个条目和树中的节点一一对应。
那怎么从纯文本中得到 AST 呢?哇哦,我们知道当下的编译器都做了这件事前。那我们就看看一般的编译器怎么做的就可以了。