1 | var types = require("../lib/types");
|
2 | var Type = types.Type;
|
3 | var def = Type.def;
|
4 | var or = Type.or;
|
5 | var shared = require("../lib/shared");
|
6 | var defaults = shared.defaults;
|
7 | var geq = shared.geq;
|
8 |
|
9 |
|
10 |
|
11 | def("Printable")
|
12 | .field("loc", or(
|
13 | def("SourceLocation"),
|
14 | null
|
15 | ), defaults["null"], true);
|
16 |
|
17 | def("Node")
|
18 | .bases("Printable")
|
19 | .field("type", String)
|
20 | .field("comments", or(
|
21 | [def("Comment")],
|
22 | null
|
23 | ), defaults["null"], true);
|
24 |
|
25 | def("SourceLocation")
|
26 | .build("start", "end", "source")
|
27 | .field("start", def("Position"))
|
28 | .field("end", def("Position"))
|
29 | .field("source", or(String, null), defaults["null"]);
|
30 |
|
31 | def("Position")
|
32 | .build("line", "column")
|
33 | .field("line", geq(1))
|
34 | .field("column", geq(0));
|
35 |
|
36 | def("File")
|
37 | .bases("Node")
|
38 | .build("program")
|
39 | .field("program", def("Program"));
|
40 |
|
41 | def("Program")
|
42 | .bases("Node")
|
43 | .build("body")
|
44 | .field("body", [def("Statement")]);
|
45 |
|
46 | def("Function")
|
47 | .bases("Node")
|
48 | .field("id", or(def("Identifier"), null), defaults["null"])
|
49 | .field("params", [def("Pattern")])
|
50 | .field("body", def("BlockStatement"));
|
51 |
|
52 | def("Statement").bases("Node");
|
53 |
|
54 |
|
55 |
|
56 | def("EmptyStatement").bases("Statement").build();
|
57 |
|
58 | def("BlockStatement")
|
59 | .bases("Statement")
|
60 | .build("body")
|
61 | .field("body", [def("Statement")]);
|
62 |
|
63 |
|
64 |
|
65 | def("ExpressionStatement")
|
66 | .bases("Statement")
|
67 | .build("expression")
|
68 | .field("expression", def("Expression"));
|
69 |
|
70 | def("IfStatement")
|
71 | .bases("Statement")
|
72 | .build("test", "consequent", "alternate")
|
73 | .field("test", def("Expression"))
|
74 | .field("consequent", def("Statement"))
|
75 | .field("alternate", or(def("Statement"), null), defaults["null"]);
|
76 |
|
77 | def("LabeledStatement")
|
78 | .bases("Statement")
|
79 | .build("label", "body")
|
80 | .field("label", def("Identifier"))
|
81 | .field("body", def("Statement"));
|
82 |
|
83 | def("BreakStatement")
|
84 | .bases("Statement")
|
85 | .build("label")
|
86 | .field("label", or(def("Identifier"), null), defaults["null"]);
|
87 |
|
88 | def("ContinueStatement")
|
89 | .bases("Statement")
|
90 | .build("label")
|
91 | .field("label", or(def("Identifier"), null), defaults["null"]);
|
92 |
|
93 | def("WithStatement")
|
94 | .bases("Statement")
|
95 | .build("object", "body")
|
96 | .field("object", def("Expression"))
|
97 | .field("body", def("Statement"));
|
98 |
|
99 | def("SwitchStatement")
|
100 | .bases("Statement")
|
101 | .build("discriminant", "cases", "lexical")
|
102 | .field("discriminant", def("Expression"))
|
103 | .field("cases", [def("SwitchCase")])
|
104 | .field("lexical", Boolean, defaults["false"]);
|
105 |
|
106 | def("ReturnStatement")
|
107 | .bases("Statement")
|
108 | .build("argument")
|
109 | .field("argument", or(def("Expression"), null));
|
110 |
|
111 | def("ThrowStatement")
|
112 | .bases("Statement")
|
113 | .build("argument")
|
114 | .field("argument", def("Expression"));
|
115 |
|
116 | def("TryStatement")
|
117 | .bases("Statement")
|
118 | .build("block", "handler", "finalizer")
|
119 | .field("block", def("BlockStatement"))
|
120 | .field("handler", or(def("CatchClause"), null), function() {
|
121 | return this.handlers && this.handlers[0] || null;
|
122 | })
|
123 | .field("handlers", [def("CatchClause")], function() {
|
124 | return this.handler ? [this.handler] : [];
|
125 | }, true)
|
126 | .field("guardedHandlers", [def("CatchClause")], defaults.emptyArray)
|
127 | .field("finalizer", or(def("BlockStatement"), null), defaults["null"]);
|
128 |
|
129 | def("CatchClause")
|
130 | .bases("Node")
|
131 | .build("param", "guard", "body")
|
132 | .field("param", def("Pattern"))
|
133 | .field("guard", or(def("Expression"), null), defaults["null"])
|
134 | .field("body", def("BlockStatement"));
|
135 |
|
136 | def("WhileStatement")
|
137 | .bases("Statement")
|
138 | .build("test", "body")
|
139 | .field("test", def("Expression"))
|
140 | .field("body", def("Statement"));
|
141 |
|
142 | def("DoWhileStatement")
|
143 | .bases("Statement")
|
144 | .build("body", "test")
|
145 | .field("body", def("Statement"))
|
146 | .field("test", def("Expression"));
|
147 |
|
148 | def("ForStatement")
|
149 | .bases("Statement")
|
150 | .build("init", "test", "update", "body")
|
151 | .field("init", or(
|
152 | def("VariableDeclaration"),
|
153 | def("Expression"),
|
154 | null))
|
155 | .field("test", or(def("Expression"), null))
|
156 | .field("update", or(def("Expression"), null))
|
157 | .field("body", def("Statement"));
|
158 |
|
159 | def("ForInStatement")
|
160 | .bases("Statement")
|
161 | .build("left", "right", "body")
|
162 | .field("left", or(
|
163 | def("VariableDeclaration"),
|
164 | def("Expression")))
|
165 | .field("right", def("Expression"))
|
166 | .field("body", def("Statement"));
|
167 |
|
168 | def("DebuggerStatement").bases("Statement").build();
|
169 |
|
170 | def("Declaration").bases("Statement");
|
171 |
|
172 | def("FunctionDeclaration")
|
173 | .bases("Function", "Declaration")
|
174 | .build("id", "params", "body")
|
175 | .field("id", def("Identifier"));
|
176 |
|
177 | def("FunctionExpression")
|
178 | .bases("Function", "Expression")
|
179 | .build("id", "params", "body");
|
180 |
|
181 | def("VariableDeclaration")
|
182 | .bases("Declaration")
|
183 | .build("kind", "declarations")
|
184 | .field("kind", or("var", "let", "const"))
|
185 | .field("declarations", [def("VariableDeclarator")]);
|
186 |
|
187 | def("VariableDeclarator")
|
188 | .bases("Node")
|
189 | .build("id", "init")
|
190 | .field("id", def("Pattern"))
|
191 | .field("init", or(def("Expression"), null));
|
192 |
|
193 |
|
194 | def("Expression").bases("Node", "Pattern");
|
195 |
|
196 | def("ThisExpression").bases("Expression").build();
|
197 |
|
198 | def("ArrayExpression")
|
199 | .bases("Expression")
|
200 | .build("elements")
|
201 | .field("elements", [or(def("Expression"), null)]);
|
202 |
|
203 | def("ObjectExpression")
|
204 | .bases("Expression")
|
205 | .build("properties")
|
206 | .field("properties", [def("Property")]);
|
207 |
|
208 |
|
209 | def("Property")
|
210 | .bases("Node")
|
211 | .build("kind", "key", "value")
|
212 | .field("kind", or("init", "get", "set"))
|
213 | .field("key", or(def("Literal"), def("Identifier")))
|
214 | .field("value", def("Expression"));
|
215 |
|
216 | def("SequenceExpression")
|
217 | .bases("Expression")
|
218 | .build("expressions")
|
219 | .field("expressions", [def("Expression")]);
|
220 |
|
221 | var UnaryOperator = or(
|
222 | "-", "+", "!", "~",
|
223 | "typeof", "void", "delete");
|
224 |
|
225 | def("UnaryExpression")
|
226 | .bases("Expression")
|
227 | .build("operator", "argument", "prefix")
|
228 | .field("operator", UnaryOperator)
|
229 | .field("argument", def("Expression"))
|
230 |
|
231 |
|
232 | .field("prefix", Boolean, defaults["true"]);
|
233 |
|
234 | var BinaryOperator = or(
|
235 | "==", "!=", "===", "!==",
|
236 | "<", "<=", ">", ">=",
|
237 | "<<", ">>", ">>>",
|
238 | "+", "-", "*", "/", "%",
|
239 | "&",
|
240 | "|", "^", "in",
|
241 | "instanceof", "..");
|
242 |
|
243 | def("BinaryExpression")
|
244 | .bases("Expression")
|
245 | .build("operator", "left", "right")
|
246 | .field("operator", BinaryOperator)
|
247 | .field("left", def("Expression"))
|
248 | .field("right", def("Expression"));
|
249 |
|
250 | var AssignmentOperator = or(
|
251 | "=", "+=", "-=", "*=", "/=", "%=",
|
252 | "<<=", ">>=", ">>>=",
|
253 | "|=", "^=", "&=");
|
254 |
|
255 | def("AssignmentExpression")
|
256 | .bases("Expression")
|
257 | .build("operator", "left", "right")
|
258 | .field("operator", AssignmentOperator)
|
259 | .field("left", def("Pattern"))
|
260 | .field("right", def("Expression"));
|
261 |
|
262 | var UpdateOperator = or("++", "--");
|
263 |
|
264 | def("UpdateExpression")
|
265 | .bases("Expression")
|
266 | .build("operator", "argument", "prefix")
|
267 | .field("operator", UpdateOperator)
|
268 | .field("argument", def("Expression"))
|
269 | .field("prefix", Boolean);
|
270 |
|
271 | var LogicalOperator = or("||", "&&");
|
272 |
|
273 | def("LogicalExpression")
|
274 | .bases("Expression")
|
275 | .build("operator", "left", "right")
|
276 | .field("operator", LogicalOperator)
|
277 | .field("left", def("Expression"))
|
278 | .field("right", def("Expression"));
|
279 |
|
280 | def("ConditionalExpression")
|
281 | .bases("Expression")
|
282 | .build("test", "consequent", "alternate")
|
283 | .field("test", def("Expression"))
|
284 | .field("consequent", def("Expression"))
|
285 | .field("alternate", def("Expression"));
|
286 |
|
287 | def("NewExpression")
|
288 | .bases("Expression")
|
289 | .build("callee", "arguments")
|
290 | .field("callee", def("Expression"))
|
291 |
|
292 |
|
293 |
|
294 | .field("arguments", [def("Expression")]);
|
295 |
|
296 | def("CallExpression")
|
297 | .bases("Expression")
|
298 | .build("callee", "arguments")
|
299 | .field("callee", def("Expression"))
|
300 |
|
301 | .field("arguments", [def("Expression")]);
|
302 |
|
303 | def("MemberExpression")
|
304 | .bases("Expression")
|
305 | .build("object", "property", "computed")
|
306 | .field("object", def("Expression"))
|
307 | .field("property", or(def("Identifier"), def("Expression")))
|
308 | .field("computed", Boolean, function(){
|
309 | var type = this.property.type;
|
310 | if (type === 'Literal' ||
|
311 | type === 'MemberExpression' ||
|
312 | type === 'BinaryExpression') {
|
313 | return true;
|
314 | }
|
315 | return false;
|
316 | });
|
317 |
|
318 | def("Pattern").bases("Node");
|
319 |
|
320 | def("SwitchCase")
|
321 | .bases("Node")
|
322 | .build("test", "consequent")
|
323 | .field("test", or(def("Expression"), null))
|
324 | .field("consequent", [def("Statement")]);
|
325 |
|
326 | def("Identifier")
|
327 |
|
328 | .bases("Node", "Expression", "Pattern")
|
329 | .build("name")
|
330 | .field("name", String);
|
331 |
|
332 | def("Literal")
|
333 |
|
334 | .bases("Node", "Expression")
|
335 | .build("value")
|
336 | .field("value", or(String, Boolean, null, Number, RegExp))
|
337 | .field("regex", or({
|
338 | pattern: String,
|
339 | flags: String
|
340 | }, null), function() {
|
341 | if (this.value instanceof RegExp) {
|
342 | var flags = "";
|
343 |
|
344 | if (this.value.ignoreCase) flags += "i";
|
345 | if (this.value.multiline) flags += "m";
|
346 | if (this.value.global) flags += "g";
|
347 |
|
348 | return {
|
349 | pattern: this.value.source,
|
350 | flags: flags
|
351 | };
|
352 | }
|
353 |
|
354 | return null;
|
355 | });
|
356 |
|
357 |
|
358 | def("Comment")
|
359 | .bases("Printable")
|
360 | .field("value", String)
|
361 |
|
362 |
|
363 |
|
364 |
|
365 |
|
366 | .field("leading", Boolean, defaults["true"])
|
367 | .field("trailing", Boolean, defaults["false"]);
|