# AST解析
1、在线网站ast生成网站 (opens new window)
# 1、简介
抽象语法树(Abstract Syntax Tree,AST),是源代码语法结构的一种抽象表示,它以树状的形式表示编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。AST运用广泛,比如:
- 高级语言的编译、机器码的生成
- 一些高级编辑器的错误提示、代码高亮、代码自动补全;
- 前端工具,例如eslint、pretiier,对代码错误或风格的检查,babel、typescript对代码的编译处理等。
# 2、AST转换流程
# 1、ast生成流程
- 词法分析:也叫扫描(scanner),将整个代码字符串转换为令牌(tokens)流,令牌(tokens)看作是一个扁平的语法片段数组
- 语法分析:把一个令牌流转换为AST,使用令牌中的信息把它们转换成一个 AST 的表述结构,这样更易于后续的操作
//代码:const ast = "this is tree";
//tokens:扁平化数组
[
{
"type": "Keyword",
"value": "const"
},
{
"type": "Identifier",
"value": "ast"
},
{
"type": "Punctuator",
"value": "="
},
{
"type": "String",
"value": "\"this is tree\""
},
{
"type": "Punctuator",
"value": ";"
}
]
//ast:acorn解析器
//type为节点类型,每一种类型的节点定义了一些附加属性来进一步描述该节点类型,eg:start、end
{
"type": "Program",
"start": 0,
"end": 27,
"body": [
{
"type": "VariableDeclaration",
"start": 0,
"end": 27,
"declarations": [
{
"type": "VariableDeclarator",
"start": 6,
"end": 26,
"id": {
"type": "Identifier",
"start": 6,
"end": 9,
"name": "ast"
},
"init": {
"type": "Literal",
"start": 12,
"end": 26,
"value": "this is tree",
"raw": "\"this is tree\""
}
}
],
"kind": "const"
}
],
"sourceType": "module"
}
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# 2、ast的主要type类型
Ast常用的类型如下:
- Program:程序主体,整段代码的主体
- VariableDeclaration:变量声明,例如var、let、const
- FunctionDeclaration:函数声明,例如function
- Identifier:标识符,例如申明变量时var i = 5 中的i
- Literal:字面量,通常指字符串型的字面量
- BinaryExpression:二进制表达式,例如1+1
- BlockStatement:块语句,包裹在{}块内的代码
- ReturnStatement:返回语句,通常指return
- CallExpression:调用表达式,通常指调用一个函数
- MemberExpression:成员表达式,通常指调用对象的成员,例如console对象到的log成员
# 3、ast使用流程
代码转换的三个步骤:parse、traverse、generator,ast的生成、遍历和代码转换
- 使用scanner解析器对源代码进行解析,生成令牌流tokens
- 使用parser将tokens生成ast树
- traverse对ast树进行深度优先遍历,进行增删改查,生成新的ast树
- 使用generator对新的ast树转换为代码
# 3、解析器
解析器将js转换为ast,目前的js解析器都遵循ESTree规范,常见的js解析器:
- esprima:解析器始祖,第一个用JavaScript编写的符合EsTree规范的JavaScript的解析器
- acorn:webpack解析器
- espree:eslint解析器
- babel-parser:babel解析器,基于babylon实现
- uglify-js:单独的解析器
const acorn = require("acorn") //js解析器
const estraverse = require("estraverse") //ast遍历器
const escodegen = require("escodegen") //代码生成器generator
const str = "const ast = 'this is tree';"
const tokens = [...acorn.tokenizer(str)]
const ast = acorn.parse(str)
console.log(JSON.stringify(tokens))
console.log(JSON.stringify(ast))
estraverse.traverse(ast,{
enter(node){
console.log('悄悄的我来了'+node.type)
if(node.type === 'Literal')
node.value = "this is newTree"
},
leave(node){
console.log('悄悄的我又走了'+node.type)
}
})
const result = escodegen.generate(ast)
console.log(result) //const ast = 'this is newTree';
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24