简介
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.
指的是:源代码的抽象语法结构的树状表现形式
编译原理
先回顾下编译原理的几大过程:
1**词法分析** ===> 单词与记号、正则表达式、有限自动机、从正则表达式到有限自动机的转换、词法分析器的实现2 ││3 **语法分析** ===> 上下文无关文法、递归下降分析、LR 分析、错误处理、语法分析器自动生成4 ││5 **语义分析** ===> 类型系统、属性文法、语法制导翻译、符号表管理、抽象语法树、线性中间表示、图中间表示6 ││7 **中间代码生成** ===> 变量地址分配、算术表达式翻译、布尔表达式翻译、数组、结构体和字符串的翻译、控制流的翻译、函数调用的翻译8 ││9**目标代码优化与生成** ===> 目标体系结构、树匹配代码生成、基于动态规划的代码生成、寄存器分配、指令调度、控制流分析、数据流分析、死代码删除、常量传播、拷贝传播、静态单赋值形式
JavaScript 是一门解释型语言,但其在执行过程中仍然需要即时编译(JIT),其编译过程也遵循这些流程:
1**分词/词法分析** ===> 把字符串分解成有意义的代码块,这些代码块被称为词法单元2 ││3**解析/语法分析** ===> 词法单元流(数组)转换成一个由元素逐级嵌套所组成的代表了程序语法结构的树,即 AST4 ││5 **代码生成** ===> 将 AST 转换为可执行代码
总结一下:通过 Parser 把代码转化为抽象语法树(AST),该树定义了代码的结构,通过对树的处理,能实现对代码的分析、优化等操作。
JavaScript 词法解析
通过分析每行代码字符串,通过识别关键字来判断某句代码是什么表达式类型,然后把这些信息生成 AST 语法树
1if (b === 1) {2 a = 2;3 alert(a);4}
词法分析思维抽象如图
JavaScript 语法解析
在编译过程中,代码会被映射为 AST,那么就可以通过 AST 对代码进行分析、转换。像 webpack、babel、eslint 等涉及代码分析的工具类库,其背后都有 AST 的影子。
先看看 AST 长什么样,通过 AST Explorer 或者Parser可以实时解析和查看 JavaScript 的 AST。
1const a = 1;
对应的 AST
1{2 "type": "Program",3 "body": [4 {5 "type": "VariableDeclaration",6 "declarations": [7 {8 "type": "VariableDeclarator",9 "id": {10 "type": "Identifier",11 "name": "a"12 },13 "init": {14 "type": "Literal",15 "value": 1,16 "raw": "1"17 }18 }19 ],20 "kind": "const"21 }22 ],23 "sourceType": "script"24}
AST 的格式每种 Parser 都有各自的标准,Esprima 的语法树结构文档 Syntax Tree Format,下面是 type 的类型列表。
1type Expression =2 | ThisExpression3 | Identifier4 | Literal5 | ArrayExpression6 | ObjectExpression7 | FunctionExpression8 | ArrowFunctionExpression9 | ClassExpression10 | TaggedTemplateExpression11 | MemberExpression12 | Super13 | MetaProperty14 | NewExpression15 | CallExpression16 | UpdateExpression17 | AwaitExpression18 | UnaryExpression19 | BinaryExpression20 | LogicalExpression21 | ConditionalExpression22 | YieldExpression23 | AssignmentExpression24 | SequenceExpression;
JavaScript Parser
介绍完 AST 树,下面列举常用的 JavaScript Parser
各个 parser 的速度对比可以参见 Speed Comparison
应用
AST 的应用很广,从技术角度出发,所有涉及对代码处理的场景,AST 都有其用武之地。
编译器、代码压缩、代码混淆、代码优化,所有的 lint(不仅仅是 JavaScript),所有的打包构建工具及其插件,包括 webpack、rollup、parcel、browserify 等…
🍻