AST 在前端的应用

240 阅读4分钟

什么是 AST

在计算机科学中,抽象语法树(Abstract Syntax Tree,AST),或简称**语法树**(Syntax tree),是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。(百度百科)

所以它本质上是一棵树🌲,这样我们就能通过特定的一些算法,对树进行遍历和更改。

image.png

如何生成 AST

image.png

typescript 编译器:www.youtube.com/watch?v=X8k…

词法分析

词法分析(lexical analysis)是计算机科学中将字符序列转换为单词(Token)序列的过程。进行词法分析的程序或者函数叫作词法分析器(Lexical analyzer,简称Lexer),也叫扫描器(Scanner)。词法分析器一般以函数的形式存在,供语法分析器调用

逐个字符读取代码,生成一个一个 token。使用 acorn 解析源代码

image.png

语法分析

语法分析器(Parser),它的作用是进行语法检查、并构建由输入的 token 组成的数据结构(一般是语法分析树抽象语法树等层次化的数据结构)。语法分析器通常使用一个独立的词法分析器从输入字符流中分离出一个个的“token”,并将 token 流作为其输入。

调用词法分析器,根据生成的 token,生成抽象语法树。使用 acorn 解析源代码

image.png

常用的解析器

  1. acorn(功能比较基础,很多解析器都是基于它进行开发的,webapck 底层也是用的 acorn)

  2. @babel/parser (babel 自带解析器)

  3. Espree (Esling 默认解析器)

  4. @babel/eslint-parser (使用了实验性语法时,eslint 可以使用这个解析器)

  5. @typescript-eslint/parser

    1. @typescript-eslint/typescript-estree(将 typescript 的 ast 转换为符合 ESTree 标准的 ast)
  6. vue-eslint-parser

    1. @vue/compiler-dom (vue 自带编译器)
    2. Vue template 部分的 node 类型
  7. typescript

可以看到解析器的类型多种多样,不同的工具或者框架都可以基于自己的需求进行定制化,但最终针对抽象语法树的实现,都需要遵循 ESTree、typescript-estree 的规范。

swc(Rust 版 Babel),EsBuild(go 语言打包器)

ESTree 标准

就像 ES 标准一样,对于 javascript,抽象语法树也有一套标准叫 ESTree,它定义了抽象语法树所有的节点类型,以及每个节点类型应该包含的属性。

关于 typescript AST 标准: 目前 typescript 没有披露相应的标准,只能通过解析器查看其相应的节点类型

操作 AST

我们需要对节点进行一系列的操作,常见的有以下这些场景:

  1. 查找某一类、某一个节点
  2. 寻找祖先、孩子节点
  3. 对节点进行删除、替换、更新的操作

通常情况下,操作的频率很高,如果每一次都需要遍历一遍 AST,会导致时间复杂度较高,所以需要对操作过程进行优化,可以通过社区的一些工具来辅助:

  1. @babel/traverse
  2. acorn-walk

操作 AST 通常会涉及到一些概念:

Scope

即 javascript 的作用域,作用域大致分为 global、function、block 这三种类型,每一个 ast 节点都会归属于某一个作用域,并且能通过 scope 找到所有的子 scope 和父 scope。scope 中存储了这个作用域里的所有信息,包括:

  • 声明了哪些变量,哪些变量是当前作用域声明的,哪些变量是引用外部的,如果是引用外部变量,那么引用的这个外部变量的位置在哪里
  • 子作用域
  • 父作用域

reference

引用,通过它,可以找到一个变量被在哪些地方被引用。如果是引用方,也能找到定义该变量的节点。

举例🌰

babeljs.io/docs/en/bab…

应用

代码降级

对代码做降级处理,例如 babel、swc

模块打包器

依赖分析

Typescript

Typescript 实现了自己的一套编译器,将 ts 代码编译成 ast 最终生成符合 ESTree 结构的 AST,然后再将其转换为 code

V8

image.png

参考资料

  1. ESTree

  2. babel-handlebok

  3. eslint rule

  4. typescript Architectural Overview

AstExplorer:astexplorer.net/