JavaScript AST 抽象语法树
简介
AST(Abstract Syntax Tree,抽象语法树)在 Wikipedia 的定义如下:
In computer science, an abstract syntax tree (AST), or just syntax tree, is a tree representation of the abstract syntactic structure of source code written in a programming language.
指的是:源代码的抽象语法结构的树状表现形式
编译原理
先回顾下编译原理的几大过程:
**词法分析** ===> 单词与记号、正则表达式、有限自动机、从正则表达式到有限自动机的转换、词法分析器的实现
││
**语法分析** ===> 上下文无关文法、递归下降分析、LR 分析、错误处理、语法分析器自动生成
││
**语义分析** ===> 类型系统、属性文法、语法制导翻译、符号表管理、抽象语法树、线性中间表示、图中间表示
││
**中间代码生成** ===> 变量地址分配、算术表达式翻译、布尔表达式翻译、数组、结构体和字符串的翻译、控制流的翻译、函数调用的翻译
││
**目标代码优化与生成** ===> 目标体系结构、树匹配代码生成、基于动态规划的代码生成、寄存器分配、指令调度、控制流分析、数据流分析、死代码删除、常量传播、拷贝传播、静态单赋值形式
JavaScript 是一门解释型语言,但其在执行过程中仍然需要即时编译(JIT),其编译过程也遵循这些流程:
**分词/词法分析** ===> 把字符串分解成有意义的代码块,这些代码块被称为词法单元
││
**解析/语法分析** ===> 词法单元流(数组)转换成一个由元素逐级嵌套所组成的代表了程序语法结构的树,即 AST
││
**代码生成** ===> 将 AST 转换为可执行代码
总结一下:通过 Parser 把代码转化为抽象语法树(AST),该树定义了代码的结构,通过对树的处理,能实现对代码的分析、优化等操作。
JavaScript 词法解析
通过分析每行代码字符串,通过识别关键字来判断某句代码是什么表达式类型,然后把这些信息生成 AST 语法树
if (b === 1) {
a = 2;
alert(a);
}
词法分析思维抽象如图
JavaScript 语法解析
在编译过程中,代码会被映射为 AST,那么就可以通过 AST 对代码进行分析、转换。像 webpack、babel、eslint 等涉及代码分析的工具类库,其背后都有 AST 的影子。
先看看 AST 长什么样,通过 AST Explorer 或者Parser可以实时解析和查看 JavaScript 的 AST。
const a = 1;
对应的 AST
{
"type": "Program",
"body": [
{
"type": "VariableDeclaration",
"declarations": [
{
"type": "VariableDeclarator",
"id": {
"type": "Identifier",
"name": "a"
},
"init": {
"type": "Literal",
"value": 1,
"raw": "1"
}
}
],
"kind": "const"
}
],
"sourceType": "script"
}
AST 的格式每种 Parser 都有各自的标准,Esprima 的语法树结构文档 Syntax Tree Format,下面是 type 的类型列表。
type Expression =
| ThisExpression
| Identifier
| Literal
| ArrayExpression
| ObjectExpression
| FunctionExpression
| ArrowFunctionExpression
| ClassExpression
| TaggedTemplateExpression
| MemberExpression
| Super
| MetaProperty
| NewExpression
| CallExpression
| UpdateExpression
| AwaitExpression
| UnaryExpression
| BinaryExpression
| LogicalExpression
| ConditionalExpression
| YieldExpression
| AssignmentExpression
| SequenceExpression;
JavaScript Parser
介绍完 AST 树,下面列举常用的 JavaScript Parser
各个 parser 的速度对比可以参见 Speed Comparison
应用
AST 的应用很广,从技术角度出发,所有涉及对代码处理的场景,AST 都有其用武之地。
编译器、代码压缩、代码混淆、代码优化,所有的 lint(不仅仅是 JavaScript),所有的打包构建工具及其插件,包括 webpack、rollup、parcel、browserify 等…
🍻