• 首页
  • 关于
    • 前端行知录 photo

      前端行知录

      前端路漫漫,行知方知行

    • Email
    • Github
  • 文章
    • 所有文章
    • 所有标签
  • 作品

JavaScript AST 抽象语法树

20 Jul 2018

Reading time ~1 minute

先谈一谈背景,最近在尝试输出小程序的开发体系,对 Taro 的编译方式产生浓厚的兴趣,趁机补一补 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,那么就可以通过 AST 对代码进行分析、转换。像 webpack、babel、eslint 等涉及代码分析的工具类库,其背后都有 AST 的影子。

先看看 AST 长什么样,通过 AST Explorer 可以实时解析和查看 JavaScript 的 AST。

function printTips(tips) {
  tips.forEach((tip, i) => console.log(`Tip ${i}:` + tip));
}

对应的 AST 树部分截图如下

ast

对应的 JSON 格式原始数据部分截图如下

ast_json

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

  • Esprima
  • UglifyJS2
  • Traceur
  • acorn
  • espree eslint
  • Shift

各个 parser 的速度对比可以参见 Speed Comparison

应用

AST 的应用很广,从技术角度出发,所有涉及对代码处理的场景,AST 都有其用武之地。

编译器、代码压缩、代码混淆、代码优化,所有的 lint(不仅仅是 JavaScript),所有的打包构建工具及其插件,包括 webpack、rollup、parcel、browserify 等…

只有想不到,没有做不到,这才是应有的态度!

参考资料

  • AST Explorer
  • JavaScript 到底是解释型语言还是编译型语言?
  • Abstract Syntax Tree 抽象语法树简介
JavaScript Theory

alcat2008

Dreamer, Practitioner, Incomplete Front-ender

← requestAnimationFrame 与 requestIdleCallback 再谈前端架构/体系 →