-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathparser.js
258 lines (225 loc) · 6.91 KB
/
parser.js
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
import {
Program,
ArrowFunctionExpression,
VariableDeclaration,
Identifier,
BlockStatement,
ReturnStatement,
Literal,
tokenTypeMap,
} from './specs';
class Parser {
constructor(tokens) {
if (!Array.isArray(tokens)) {
throw new Error('Parse tokens must be an array');
}
this.tokens = tokens;
this.curToken = null;
this.stashStack = [];
this.index = -1;
}
getTreeNode = () => {
return this.nextStatement() || this.nextExpression();
}
getAST = () => {
const ast = new Program();
while (this.index < this.tokens.length - 1) {
const treeNode = this.getTreeNode();
if (!treeNode) {
break;
}
ast.body.push(treeNode);
}
return ast;
}
/**
* 读取并返回下一个语句
*/
nextStatement = () => {
this.stash();
this.setNextToken();
if (this.curToken.type === tokenTypeMap.brace.type && this.curToken.value === '{') {
const blockStatement = new BlockStatement();
while (this.index < this.tokens.length - 1) {
this.stash();
this.setNextToken();
if (this.curToken.type === tokenTypeMap.brace.type && this.curToken.value === '}') {
// `{` 紧接着就是 `}`,说明是空的语句块
this.commit();
break;
}
// 处理 return 语句的情况
if (
this.curToken.type === tokenTypeMap.identifier.type
&& this.curToken.value === 'return'
) {
const returnStatement = new ReturnStatement();
const returnStatementArgument = returnStatement.argument;
while (this.index < this.tokens.length - 1) {
this.stash();
this.setNextToken();
if (this.curToken.type === tokenTypeMap.identifier.type) {
if (returnStatementArgument.left && !returnStatementArgument.right) {
this.rewind();
returnStatementArgument.right = this.getTreeNode();
}
if (!returnStatementArgument.left) {
this.rewind();
returnStatementArgument.left = this.getTreeNode();
}
continue;
}
if (this.curToken.type === tokenTypeMap.operator.type) {
returnStatementArgument.operator = this.curToken.value;
continue;
}
// 处理 `;` 结束的情况
if (this.curToken.type === tokenTypeMap.colon.type) {
this.commit();
break;
}
}
blockStatement.body.push(returnStatement);
continue;
}
}
return blockStatement;
}
// 没有找到语句块,回到处理之前的位置
this.rewind();
}
/**
* 读取并返回下一个表达式
*/
nextExpression = () => {
this.stash();
this.setNextToken();
if (
this.curToken.type === tokenTypeMap.identifier.type
&& (this.curToken.value === 'const' || this.curToken.value === 'let')
) {
const declaration = new VariableDeclaration({
kind: this.curToken.value,
});
const declarator = declaration.declarations[0]; // 暂时只处理每行只定义一个变量的情况
while (this.index < this.tokens.length - 1) {
this.stash();
this.setNextToken();
// 解析变量名
if (this.curToken.type === tokenTypeMap.identifier.type) {
if (!declarator.id) {
declarator.id = new Identifier({
name: this.curToken.value,
});
}
continue;
}
// 碰到 `=` 继续往前解析
if (this.curToken.type === tokenTypeMap.equal.type) {
continue;
}
// 解析赋于变量的值
if (
this.curToken.type === tokenTypeMap.string.type
|| this.curToken.type === tokenTypeMap.number.type
) {
let value = this.curToken.value;
if (this.curToken.type === tokenTypeMap.number.type) {
value = Number(value);
}
declarator.init = new Literal({ value });
}
else if (
tokenTypeMap.parens.chars.includes(this.curToken.value)
&& this.curToken.value === '('
) {
this.rewind(); // 处理 `(a, b)` 这种函数调用,或者函数定义的情况
declarator.init = this.getTreeNode();
}
// 解析冒号结尾
if (this.curToken.type == tokenTypeMap.colon.type) {
// 解析完成
this.commit();
break;
}
}
return declaration;
}
// 碰到 `(` 的情况,先只假设是箭头函数的情况
if (
this.curToken.type === tokenTypeMap.parens.type
&& this.curToken.value === '('
) {
const arrowFunction = new ArrowFunctionExpression();
while (this.index < this.tokens.length - 1) {
this.stash();
this.setNextToken();
// 处理 `)` 结束符的情况,继续解析
if (this.curToken.type === tokenTypeMap.parens.type && this.curToken.value === ')') {
continue;
}
// 处理函数的变量
if (this.curToken.type === tokenTypeMap.identifier.type) {
this.rewind(); // 回退一步,处理函数的变量
arrowFunction.params.push(this.getTreeNode());
continue;
}
// 处理逗号的情况
if (this.curToken.type === tokenTypeMap.comma.type) {
continue;
}
// 处理 => 箭头函数符号的问题
if (this.curToken.type === tokenTypeMap.arrow.type) {
continue;
}
// 处理函数体的情况
if (this.curToken.type === tokenTypeMap.brace.type && this.curToken.value === '{') {
this.rewind(); // 需要回退一步,处理函数体的情况
const treeNode = this.getTreeNode();
arrowFunction.body = treeNode;
continue;
}
// 解析冒号结尾
if (this.curToken.type == tokenTypeMap.colon.type) {
this.commit();
break;
}
}
return arrowFunction;
}
// 处理字符串变量的情况
if (this.curToken.type === tokenTypeMap.identifier.type) {
return new Identifier({
name: this.curToken.value,
});
}
// 没有找到表达式块,回到处理之前的位置
this.rewind();
}
/**
* 读取下一个语法单元(或称符号),赋值给 curToken
*/
setNextToken = () => {
this.index = this.index += 1;
this.curToken = this.tokens[this.index];
}
/**
* 暂存当前读取符号的位置,方便在需要的时候返回
*/
stash = () => {
this.stashStack.push(this.index);
}
/**
* 返回到上一个暂存点
*/
rewind = () => {
this.index = this.stashStack.pop();
}
/**
* 上一个暂存点不再被需要,其将被销毁
*/
commit = () => {
this.stashStack.pop();
}
}
export default Parser;