抽象语法树 AST 与 编译器 Compiler

the-super-tiny-compiler / 超级微小的编译器

此部分 the-super-tiny-compiler / 超级微小的编译器 内容,均摘取自 the-super-tiny-compiler-CN,先看完 the-super-tiny-compiler-CN 才有看后续的意义。

概要

大部分编译器的工作可以被分解为三个主要阶段:解析(Parsing),转化(Transformation)以及 代码生成(Code Generation)

  1. 解析 将源代码转换为一个更抽象的形式。
  2. 转换 接受解析产生的抽象形式并且操纵这些抽象形式做任何编译器想让它们做的事。
  3. 代码生成 基于转换后的代码表现形式(code representation)生成目标代码。

解析

  1. 词法分析 —— tokenizer 通过一个叫做tokenizer(词素生成器,也叫lexer)的工具将源代码分解成一个个词素。(词素是描述编程语言语法的对象。它可以描述数字,标识符,标点符号,运算符等等。)
  2. 语法分析 —— parser 接收词素并将它们组合成一个描述了源代码各部分之间关系的中间表达形式:抽象语法树。(抽象语法树是一个深度嵌套的对象,这个对象以一种既能够简单地操作又提供很多关于源代码信息的形式,来展现代码。)

转换

编译器的下一个阶段是转换阶段。再回顾一遍,这个过程接收解析生成的抽象语法树并对它做出改动。转换阶段可以改变抽象语法树使代码保持在同一个语言(例如Babel,Babel接收的是JS代码生成的也是JS代码),或者编译成另外一门语言。

traverser函数,这个函数接收抽象语法树以及一个访问者对象

transformer -> traverser(ast, visitor)

接收创造的抽象语法树并将它和一个访问者对象传给 traverser 函数。然后创造一个新的抽象语法树

代码生成

codeGenerator 生成新的代码

babel 是如何工作的?

  1. 解析 —— @babel/parser(包含 上方提到的 tokenizerparser),根据 es2015, es2016… 标准,生成 AST
  2. 转换 —— @babel/traverse + plugins (visitor)
  3. 代码生成 —— @babel/generator

AST 定义

  1. SpiderMonkey in MDN
  2. The ESTree Spec
  3. babel AST 针对 ESTree 的调整
  4. jsx-AST

AST 生成工具 (parser)

  1. esprima —— 老牌解析器
  2. acorn —— esprima 后的轮子,目前使用最多。webpack 也使用此工具
  3. astexplorer —— 在线生成工具
  4. espree —— 最初从 esprima fork 出来,来自 eslint,用于 eslint
  5. babel-parser —— 原 babylon,最初 从 acorn fork 出来
  6. UglifyJS2 —— 自带 parser
  7. shift-parser-js —— 自己定义了一套 AST 规范 shift-spec

其他 AST 转换工具 (transformer)

  1. estraverse

代码生成工具 (codeGenerator)

  1. escodegen

其他编译工具

  1. traceur-compiler

基于 AST 的工具

如上所描述:

  1. eslint
  2. webpack
  3. UglifyJS 代码压缩
  4. prettier —— 使用 @babel/parserangular-estree-parser… etc.
  5. typescript —— 自带 parser、transformer、codeGenerator
  6. 代码重构
    1. recast
    2. jscodeshift
    3. react-codemod
  7. 其他,例如:IDE 错误提示、格式化、高亮、自动补全 等

参考

  1. the-super-tiny-compiler-CN
  2. JS AST 原理揭秘
  3. JavaScript基础——JS编译器你都做了啥?
  4. 平庸前端码农之蜕变 — AST
  5. 代码重构利器 —— jscodeshift
  6. 利用 AST 对项目代码进行迁移
  7. jscodeshift 入门指南
  8. ACORN.JS:原理与应⽤
  9. 使用 Acorn 来解析 JavaScript
  10. Speed Comparison
  11. es6-tools