介绍

babelJavascript 的编译语法器,确切来说是源码到源码的编译器,通常也叫做“转换编译器(transpiler)。意思是说你为 Babel 提供一些 JavaScript 代码,Babel 更改这些代码,然后返回给你新生成的代码。

抽象语法数(AST)

这个处理过程中的每一步都涉及到创建或是操作抽象语法树,亦称 AST。

1
2
3
function square(n) {
return n * n;
}

这个程序可以被表示成如下的一棵树:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- FunctionDeclaration:
- id:
- Identifier:
- name: square
- params [1]
- Identifier
- name: n
- body:
- BlockStatement
- body [1]
- ReturnStatement
- argument
- BinaryExpression
- operator: *
- left
- Identifier
- name: n
- right
- Identifier
- name: n

或是如下所示的 JavaScript Object(对象):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
type: "FunctionDeclaration",
id: {
type: "Identifier",
name: "square"
},
params: [{
type: "Identifier",
name: "n"
}],
body: {
type: "BlockStatement",
body: [{
type: "ReturnStatement",
argument: {
type: "BinaryExpression",
operator: "*",
left: {
type: "Identifier",
name: "n"
},
right: {
type: "Identifier",
name: "n"
}
}
}]
}
}

你会留意到 AST 的每一层都拥有相同的结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
type: "FunctionDeclaration",
id: {...},
params: [...],
body: {...}
}

{
type: "Identifier",
name: ...
}

{
type: "BinaryExpression",
operator: ...,
left: {...},
right: {...}
}

注意:出于简化的目的移除了某些属性

这样的每一层结构也被叫做 节点(Node)。 一个 AST 可以由单一的节点或是成百上千个节点构成。

Babel 的处理步骤

Babel 的三个主要处理步骤分别是: 解析(parse)转换(transform)生成(generate)

解析

解析步骤接收代码并输出 AST。 这个步骤分为两个阶段:**词法分析(Lexical Analysis) **和 语法分析(Syntactic Analysis)。

词法分析

词法分析阶段把字符串形式的代码转换为 令牌(tokens) 流。
你可以把令牌看作是一个扁平的语法片段数组:

1
n * n;
1
2
3
4
5
6
[
{ type: { ... }, value: "n", start: 0, end: 1, loc: { ... } },
{ type: { ... }, value: "*", start: 2, end: 3, loc: { ... } },
{ type: { ... }, value: "n", start: 4, end: 5, loc: { ... } },
...
]

每一个 type 有一组属性来描述该令牌:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
type: {
label: 'name',
keyword: undefined,
beforeExpr: false,
startsExpr: true,
rightAssociative: false,
isLoop: false,
isAssign: false,
prefix: false,
postfix: false,
binop: null,
updateContext: null
},
...
}

和 AST 节点一样它们也有 start,end,loc 属性。

语法分析

语法分析阶段会把一个令牌流转换成 AST 的形式。 这个阶段会使用令牌中的信息把它们转换成一个 AST 的表述结构,这样更易于后续的操作。

转换

转换步骤接收 AST 并对其遍历,在此过程对节点进行添加、更新、删除等操作。这个是 Babel 编译器 中最复杂的过程,也是插件将来要介入工作的部分。

生成

代码生成步骤把最终(经过一系列转换后)的 AST 转成字符串形式的代码,同时还会创建 源码映射
代码生成其实很简单:深度优先遍历整个 AST,然后构建可以表示转换后代码的字符串。

遍历

想要转换 AST 你需要进行递归的树形遍历。