OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 final bool VERBOSE = false; | |
6 | |
7 class Listener { | |
8 void beginArguments(Token token) { | |
9 } | |
10 | |
11 void endArguments(int count, Token beginToken, Token endToken) { | |
12 } | |
13 | |
14 void beginBlock(Token token) { | |
15 } | |
16 | |
17 void endBlock(int count, Token beginToken, Token endToken) { | |
18 } | |
19 | |
20 void beginClassBody(Token token) { | |
21 } | |
22 | |
23 void endClassBody(int memberCount, Token beginToken, Token endToken) { | |
24 } | |
25 | |
26 void beginClassDeclaration(Token token) { | |
27 } | |
28 | |
29 void endClassDeclaration(int interfacesCount, Token beginToken, | |
30 Token extendsKeyword, Token implementsKeyword, | |
31 Token endToken) { | |
32 } | |
33 | |
34 void beginDoWhileStatement(Token token) { | |
35 } | |
36 | |
37 void endDoWhileStatement(Token doKeyword, Token whileKeyword, | |
38 Token endToken) { | |
39 } | |
40 | |
41 void beginExpressionStatement(Token token) { | |
42 } | |
43 | |
44 void endExpressionStatement(Token token) { | |
45 } | |
46 | |
47 void beginDefaultClause(Token token) { | |
48 } | |
49 | |
50 void handleNoDefaultClause(Token token) { | |
51 } | |
52 | |
53 void endDefaultClause(Token defaultKeyword) { | |
54 } | |
55 | |
56 void beginFactoryMethod(Token token) { | |
57 } | |
58 | |
59 void endFactoryMethod(Token factoryKeyword, Token periodBeforeName, | |
60 Token endToken) { | |
61 } | |
62 | |
63 void beginFormalParameter(Token token) { | |
64 } | |
65 | |
66 void endFormalParameter(Token token, Token thisKeyword) { | |
67 } | |
68 | |
69 void beginFormalParameters(Token token) { | |
70 } | |
71 | |
72 void endFormalParameters(int count, Token beginToken, Token endToken) { | |
73 } | |
74 | |
75 void endFields(int count, Token beginToken, Token endToken) { | |
76 } | |
77 | |
78 void beginForStatement(Token token) { | |
79 } | |
80 | |
81 void endForStatement(int updateExpressionCount, | |
82 Token beginToken, Token endToken) { | |
83 } | |
84 | |
85 void endForInStatement(Token beginToken, Token inKeyword, Token endToken) { | |
86 } | |
87 | |
88 void beginFunction(Token token) { | |
89 } | |
90 | |
91 void endFunction(Token getOrSet, Token endToken) { | |
92 } | |
93 | |
94 void beginFunctionDeclaration(Token token) { | |
95 } | |
96 | |
97 void endFunctionDeclaration(Token token) { | |
98 } | |
99 | |
100 void beginFunctionBody(Token token) { | |
101 } | |
102 | |
103 void endFunctionBody(int count, Token beginToken, Token endToken) { | |
104 } | |
105 | |
106 void handleNoFunctionBody(Token token) { | |
107 } | |
108 | |
109 void beginFunctionName(Token token) { | |
110 } | |
111 | |
112 void endFunctionName(Token token) { | |
113 } | |
114 | |
115 void beginFunctionTypeAlias(Token token) { | |
116 } | |
117 | |
118 void endFunctionTypeAlias(Token typedefKeyword, Token endToken) { | |
119 } | |
120 | |
121 void beginIfStatement(Token token) { | |
122 } | |
123 | |
124 void endIfStatement(Token ifToken, Token elseToken) { | |
125 } | |
126 | |
127 void beginInitializedIdentifier(Token token) { | |
128 } | |
129 | |
130 void endInitializedIdentifier() { | |
131 } | |
132 | |
133 void beginInitializer(Token token) { | |
134 } | |
135 | |
136 void endInitializer(Token assignmentOperator) { | |
137 } | |
138 | |
139 void beginInitializers(Token token) { | |
140 } | |
141 | |
142 void endInitializers(int count, Token beginToken, Token endToken) { | |
143 } | |
144 | |
145 void handleNoInitializers() { | |
146 } | |
147 | |
148 void beginInterface(Token token) { | |
149 } | |
150 | |
151 void endInterface(int supertypeCount, Token interfaceKeyword, | |
152 Token extendsKeyword, Token endToken) { | |
153 } | |
154 | |
155 void beginLabeledStatement(Token token) { | |
156 } | |
157 | |
158 void endLabeledStatement(Token colon) { | |
159 } | |
160 | |
161 void beginLiteralMapEntry(Token token) { | |
162 } | |
163 | |
164 void endLiteralMapEntry(Token colon, Token endToken) { | |
165 } | |
166 | |
167 void beginLiteralString(Token token) { | |
168 } | |
169 | |
170 void endLiteralString(int interpolationCount) { | |
171 } | |
172 | |
173 void handleStringJuxtaposition(int literalCount) { | |
174 } | |
175 | |
176 void beginMember(Token token) { | |
177 } | |
178 | |
179 void endMethod(Token getOrSet, Token beginToken, Token endToken) { | |
180 } | |
181 | |
182 void beginOptionalFormalParameters(Token token) { | |
183 } | |
184 | |
185 void endOptionalFormalParameters(int count, | |
186 Token beginToken, Token endToken) { | |
187 } | |
188 | |
189 void beginReturnStatement(Token token) { | |
190 } | |
191 | |
192 void endReturnStatement(bool hasExpression, | |
193 Token beginToken, Token endToken) { | |
194 } | |
195 | |
196 void beginScriptTag(Token token) { | |
197 } | |
198 | |
199 void endScriptTag(bool hasPrefix, Token beginToken, Token endToken) { | |
200 } | |
201 | |
202 void beginSend(Token token) { | |
203 } | |
204 | |
205 void endSend(Token token) { | |
206 } | |
207 | |
208 void beginSwitchStatement(Token token) { | |
209 } | |
210 | |
211 void endSwitchStatement(Token switchKeyword, Token endToken) { | |
212 } | |
213 | |
214 void beginSwitchBlock(Token token) { | |
215 } | |
216 | |
217 void endSwitchBlock(int caseCount, Token beginToken, Token endToken) { | |
218 } | |
219 | |
220 void beginThrowStatement(Token token) { | |
221 } | |
222 | |
223 void endThrowStatement(Token throwToken, Token endToken) { | |
224 } | |
225 | |
226 void endRethrowStatement(Token throwToken, Token endToken) { | |
227 } | |
228 | |
229 void beginTopLevelMember(Token token) { | |
230 } | |
231 | |
232 void endTopLevelFields(int count, Token beginToken, Token endToken) { | |
233 } | |
234 | |
235 void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) { | |
236 } | |
237 | |
238 void beginTryStatement(Token token) { | |
239 } | |
240 | |
241 void handleCatchBlock(Token catchKeyword) { | |
242 } | |
243 | |
244 void handleFinallyBlock(Token finallyKeyword) { | |
245 } | |
246 | |
247 void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) { | |
248 } | |
249 | |
250 void endType(Token beginToken, Token endToken) { | |
251 } | |
252 | |
253 void beginTypeArguments(Token token) { | |
254 } | |
255 | |
256 void endTypeArguments(int count, Token beginToken, Token endToken) { | |
257 } | |
258 | |
259 void handleNoTypeArguments(Token token) { | |
260 } | |
261 | |
262 void beginTypeVariable(Token token) { | |
263 } | |
264 | |
265 void endTypeVariable(Token token) { | |
266 } | |
267 | |
268 void beginTypeVariables(Token token) { | |
269 } | |
270 | |
271 void endTypeVariables(int count, Token beginToken, Token endToken) { | |
272 } | |
273 | |
274 void beginUnamedFunction(Token token) { | |
275 } | |
276 | |
277 void endUnamedFunction(Token token) { | |
278 } | |
279 | |
280 void beginVariablesDeclaration(Token token) { | |
281 } | |
282 | |
283 void endVariablesDeclaration(int count, Token endToken) { | |
284 } | |
285 | |
286 void beginWhileStatement(Token token) { | |
287 } | |
288 | |
289 void endWhileStatement(Token whileKeyword, Token endToken) { | |
290 } | |
291 | |
292 void handleAssignmentExpression(Token token) { | |
293 } | |
294 | |
295 void handleBinaryExpression(Token token) { | |
296 } | |
297 | |
298 void handleConditionalExpression(Token question, Token colon) { | |
299 } | |
300 | |
301 void handleConstExpression(Token token, bool named) { | |
302 } | |
303 | |
304 void handleFunctionTypedFormalParameter(Token token) { | |
305 } | |
306 | |
307 void handleIdentifier(Token token) { | |
308 } | |
309 | |
310 void handleIndexedExpression(Token openCurlyBracket, | |
311 Token closeCurlyBracket) { | |
312 } | |
313 | |
314 void handleIsOperator(Token operathor, Token not, Token endToken) { | |
315 // TODO(ahe): Rename [operathor] to "operator" when VM bug is fixed. | |
316 } | |
317 | |
318 void handleLiteralBool(Token token) { | |
319 } | |
320 | |
321 void handleBreakStatement(bool hasTarget, | |
322 Token breakKeyword, Token endToken) { | |
323 } | |
324 | |
325 void handleContinueStatement(bool hasTarget, | |
326 Token continueKeyword, Token endToken) { | |
327 } | |
328 | |
329 void handleEmptyStatement(Token token) { | |
330 } | |
331 | |
332 /** Called with either the token containing a double literal, or | |
333 * an immediately preceding "unary plus" token. | |
334 */ | |
335 void handleLiteralDouble(Token token) { | |
336 } | |
337 | |
338 /** Called with either the token containing an integer literal, | |
339 * or an immediately preceding "unary plus" token. | |
340 */ | |
341 void handleLiteralInt(Token token) { | |
342 } | |
343 | |
344 void handleLiteralList(int count, Token beginToken, Token constKeyword, | |
345 Token endToken) { | |
346 } | |
347 | |
348 void handleLiteralMap(int count, Token beginToken, Token constKeyword, | |
349 Token endToken) { | |
350 } | |
351 | |
352 void handleLiteralNull(Token token) { | |
353 } | |
354 | |
355 void handleModifier(Token token) { | |
356 } | |
357 | |
358 void handleModifiers(int count) { | |
359 } | |
360 | |
361 void handleNamedArgument(Token colon) { | |
362 } | |
363 | |
364 void handleNewExpression(Token token, bool named) { | |
365 } | |
366 | |
367 void handleNoArguments(Token token) { | |
368 } | |
369 | |
370 void handleNoExpression(Token token) { | |
371 } | |
372 | |
373 void handleNoType(Token token) { | |
374 } | |
375 | |
376 void handleNoTypeVariables(Token token) { | |
377 } | |
378 | |
379 void handleOperatorName(Token operatorKeyword, Token token) { | |
380 } | |
381 | |
382 void handleParenthesizedExpression(BeginGroupToken token) { | |
383 } | |
384 | |
385 void handleQualified(Token period) { | |
386 } | |
387 | |
388 void handleStringPart(Token token) { | |
389 } | |
390 | |
391 void handleSuperExpression(Token token) { | |
392 } | |
393 | |
394 void handleSwitchCase(Token labelToken, int expressionCount, | |
395 Token defaultKeyword, int statementCount, | |
396 Token firstToken, Token endToken) { | |
397 } | |
398 | |
399 void handleThisExpression(Token token) { | |
400 } | |
401 | |
402 void handleUnaryPostfixAssignmentExpression(Token token) { | |
403 } | |
404 | |
405 void handleUnaryPrefixExpression(Token token) { | |
406 } | |
407 | |
408 void handleUnaryPrefixAssignmentExpression(Token token) { | |
409 } | |
410 | |
411 void handleValuedFormalParameter(Token equals, Token token) { | |
412 } | |
413 | |
414 void handleVoidKeyword(Token token) { | |
415 } | |
416 | |
417 Token expected(String string, Token token) { | |
418 error("expected '$string', but got '${token.slowToString()}'", token); | |
419 return skipToEof(token); | |
420 } | |
421 | |
422 void expectedIdentifier(Token token) { | |
423 error("expected identifier, but got '${token.slowToString()}'", token); | |
424 } | |
425 | |
426 Token expectedType(Token token) { | |
427 error("expected a type, but got '${token.slowToString()}'", token); | |
428 return skipToEof(token); | |
429 } | |
430 | |
431 Token expectedExpression(Token token) { | |
432 error("expected an expression, but got '${token.slowToString()}'", token); | |
433 return skipToEof(token); | |
434 } | |
435 | |
436 Token unexpected(Token token) { | |
437 error("unexpected token '${token.slowToString()}'", token); | |
438 return skipToEof(token); | |
439 } | |
440 | |
441 Token expectedBlockToSkip(Token token) { | |
442 error("expected a block, but got '${token.slowToString()}'", token); | |
443 return skipToEof(token); | |
444 } | |
445 | |
446 Token expectedFunctionBody(Token token) { | |
447 error("expected a function body, but got '${token.slowToString()}'", token); | |
448 return skipToEof(token); | |
449 } | |
450 | |
451 Token expectedClassBody(Token token) { | |
452 error("expected a class body, but got '${token.slowToString()}'", token); | |
453 return skipToEof(token); | |
454 } | |
455 | |
456 Token expectedClassBodyToSkip(Token token) { | |
457 error("expected a class body, but got '${token.slowToString()}'", token); | |
458 return skipToEof(token); | |
459 } | |
460 | |
461 skipToEof(Token token) { | |
462 while (token.info !== EOF_INFO) { | |
463 token = token.next; | |
464 } | |
465 return token; | |
466 } | |
467 | |
468 void recoverableError(String message, [Token token, Node node]) { | |
469 if (token === null && node !== null) { | |
470 token = node.getBeginToken(); | |
471 } | |
472 error(message, token); | |
473 } | |
474 | |
475 void error(String message, Token token) { | |
476 throw new ParserError("$message @ ${token.charOffset}"); | |
477 } | |
478 } | |
479 | |
480 class ParserError { | |
481 final String reason; | |
482 ParserError(this.reason); | |
483 toString() => reason; | |
484 } | |
485 | |
486 /** | |
487 * A listener for parser events. | |
488 */ | |
489 class ElementListener extends Listener { | |
490 final DiagnosticListener listener; | |
491 final CompilationUnitElement compilationUnitElement; | |
492 final StringValidator stringValidator; | |
493 Link<StringQuoting> interpolationScope; | |
494 | |
495 Link<Node> nodes = const EmptyLink<Node>(); | |
496 | |
497 ElementListener(DiagnosticListener listener, | |
498 CompilationUnitElement this.compilationUnitElement) | |
499 : this.listener = listener, | |
500 stringValidator = new StringValidator(listener), | |
501 interpolationScope = const EmptyLink<StringQuoting>(); | |
502 | |
503 void pushQuoting(StringQuoting quoting) { | |
504 interpolationScope = interpolationScope.prepend(quoting); | |
505 } | |
506 | |
507 StringQuoting popQuoting() { | |
508 StringQuoting result = interpolationScope.head; | |
509 interpolationScope = interpolationScope.tail; | |
510 return result; | |
511 } | |
512 | |
513 LiteralString popLiteralString() { | |
514 StringNode node = popNode(); | |
515 // TODO(lrn): Handle interpolations in script tags. | |
516 if (node.isInterpolation) { | |
517 listener.cancel("String interpolation not supported in library tags", | |
518 node: node); | |
519 return null; | |
520 } | |
521 return node; | |
522 } | |
523 | |
524 void endScriptTag(bool hasPrefix, Token beginToken, Token endToken) { | |
525 StringNode prefix = null; | |
526 Identifier argumentName = null; | |
527 if (hasPrefix) { | |
528 prefix = popLiteralString(); | |
529 argumentName = popNode(); | |
530 } | |
531 StringNode firstArgument = popLiteralString(); | |
532 Identifier tag = popNode(); | |
533 compilationUnitElement.addTag(new ScriptTag(tag, firstArgument, | |
534 argumentName, prefix, | |
535 beginToken, endToken), | |
536 listener); | |
537 } | |
538 | |
539 void endClassDeclaration(int interfacesCount, Token beginToken, | |
540 Token extendsKeyword, Token implementsKeyword, | |
541 Token endToken) { | |
542 SourceString nativeName = native.checkForNativeClass(this); | |
543 NodeList interfaces = | |
544 makeNodeList(interfacesCount, implementsKeyword, null, ","); | |
545 TypeAnnotation supertype = popNode(); | |
546 NodeList typeParameters = popNode(); | |
547 Identifier name = popNode(); | |
548 ClassElement element = new PartialClassElement( | |
549 name.source, beginToken, endToken, compilationUnitElement); | |
550 element.nativeName = nativeName; | |
551 pushElement(element); | |
552 } | |
553 | |
554 void endDefaultClause(Token defaultKeyword) { | |
555 NodeList typeParameters = popNode(); | |
556 Node name = popNode(); | |
557 pushNode(new TypeAnnotation(name, typeParameters)); | |
558 } | |
559 | |
560 void handleNoDefaultClause(Token token) { | |
561 pushNode(null); | |
562 } | |
563 | |
564 void endInterface(int supertypeCount, Token interfaceKeyword, | |
565 Token extendsKeyword, Token endToken) { | |
566 // TODO(ahe): Record the defaultClause. | |
567 Node defaultClause = popNode(); | |
568 NodeList supertypes = | |
569 makeNodeList(supertypeCount, extendsKeyword, null, ","); | |
570 NodeList typeParameters = popNode(); | |
571 Identifier name = popNode(); | |
572 pushElement(new PartialClassElement(name.source, interfaceKeyword, | |
573 endToken, | |
574 compilationUnitElement)); | |
575 } | |
576 | |
577 void endFunctionTypeAlias(Token typedefKeyword, Token endToken) { | |
578 NodeList typeVariables = popNode(); // TOOD(karlklose): do not throw away. | |
579 Identifier name = popNode(); | |
580 TypeAnnotation returnType = popNode(); | |
581 pushElement(new TypedefElement(name.source, compilationUnitElement, | |
582 typedefKeyword)); | |
583 } | |
584 | |
585 void handleVoidKeyword(Token token) { | |
586 pushNode(new TypeAnnotation(new Identifier(token), null)); | |
587 } | |
588 | |
589 void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) { | |
590 Identifier name = popNode(); | |
591 Modifiers modifiers = popNode(); | |
592 ElementKind kind; | |
593 if (getOrSet === null) { | |
594 kind = ElementKind.FUNCTION; | |
595 } else if (getOrSet.stringValue === 'get') { | |
596 kind = ElementKind.GETTER; | |
597 } else if (getOrSet.stringValue === 'set') { | |
598 kind = ElementKind.SETTER; | |
599 } | |
600 pushElement(new PartialFunctionElement(name.source, beginToken, getOrSet, | |
601 endToken, kind, | |
602 modifiers, compilationUnitElement)); | |
603 } | |
604 | |
605 void endTopLevelFields(int count, Token beginToken, Token endToken) { | |
606 void buildFieldElement(SourceString name, Element fields) { | |
607 pushElement(new VariableElement( | |
608 name, fields, ElementKind.FIELD, compilationUnitElement)); | |
609 } | |
610 NodeList variables = makeNodeList(count, null, null, ","); | |
611 Modifiers modifiers = popNode(); | |
612 buildFieldElements(modifiers, variables, compilationUnitElement, | |
613 buildFieldElement, | |
614 beginToken, endToken); | |
615 } | |
616 | |
617 void buildFieldElements(Modifiers modifiers, | |
618 NodeList variables, | |
619 ContainerElement enclosingElement, | |
620 void buildFieldElement(SourceString name, | |
621 Element fields), | |
622 Token beginToken, Token endToken) { | |
623 Element fields = new PartialFieldListElement(beginToken, | |
624 endToken, | |
625 modifiers, | |
626 enclosingElement); | |
627 for (Link<Node> nodes = variables.nodes; !nodes.isEmpty(); | |
628 nodes = nodes.tail) { | |
629 Expression initializedIdentifier = nodes.head; | |
630 Identifier identifier = initializedIdentifier.asIdentifier(); | |
631 if (identifier === null) { | |
632 identifier = initializedIdentifier.asSendSet().selector.asIdentifier(); | |
633 } | |
634 SourceString name = identifier.source; | |
635 buildFieldElement(name, fields); | |
636 } | |
637 } | |
638 | |
639 void handleIdentifier(Token token) { | |
640 pushNode(new Identifier(token)); | |
641 } | |
642 | |
643 void handleQualified(Token period) { | |
644 Identifier last = popNode(); | |
645 Identifier first = popNode(); | |
646 pushNode(new Send(first, last)); | |
647 } | |
648 | |
649 void handleNoType(Token token) { | |
650 pushNode(null); | |
651 } | |
652 | |
653 void endTypeVariable(Token token) { | |
654 TypeAnnotation bound = popNode(); | |
655 Identifier name = popNode(); | |
656 pushNode(new TypeVariable(name, bound)); | |
657 } | |
658 | |
659 void endTypeVariables(int count, Token beginToken, Token endToken) { | |
660 pushNode(makeNodeList(count, beginToken, endToken, ',')); | |
661 } | |
662 | |
663 void handleNoTypeVariables(token) { | |
664 pushNode(null); | |
665 } | |
666 | |
667 void endTypeArguments(int count, Token beginToken, Token endToken) { | |
668 pushNode(makeNodeList(count, beginToken, endToken, ',')); | |
669 } | |
670 | |
671 void handleNoTypeArguments(Token token) { | |
672 pushNode(null); | |
673 } | |
674 | |
675 void endType(Token beginToken, Token endToken) { | |
676 NodeList typeArguments = popNode(); | |
677 Expression typeName = popNode(); | |
678 pushNode(new TypeAnnotation(typeName, typeArguments)); | |
679 } | |
680 | |
681 void handleParenthesizedExpression(BeginGroupToken token) { | |
682 Expression expression = popNode(); | |
683 pushNode(new ParenthesizedExpression(expression, token)); | |
684 } | |
685 | |
686 void handleModifier(Token token) { | |
687 pushNode(new Identifier(token)); | |
688 } | |
689 | |
690 void handleModifiers(int count) { | |
691 NodeList nodes = makeNodeList(count, null, null, null); | |
692 pushNode(new Modifiers(nodes)); | |
693 } | |
694 | |
695 Token expected(String string, Token token) { | |
696 listener.cancel("expected '$string', but got '${token.slowToString()}'", | |
697 token: token); | |
698 return skipToEof(token); | |
699 } | |
700 | |
701 void expectedIdentifier(Token token) { | |
702 listener.cancel("expected identifier, but got '${token.slowToString()}'", | |
703 token: token); | |
704 pushNode(null); | |
705 } | |
706 | |
707 Token expectedType(Token token) { | |
708 listener.cancel("expected a type, but got '${token.slowToString()}'", | |
709 token: token); | |
710 pushNode(null); | |
711 return skipToEof(token); | |
712 } | |
713 | |
714 Token expectedExpression(Token token) { | |
715 listener.cancel("expected an expression, but got '${token.slowToString()}'", | |
716 token: token); | |
717 pushNode(null); | |
718 return skipToEof(token); | |
719 } | |
720 | |
721 Token unexpected(Token token) { | |
722 listener.cancel("unexpected token '${token.slowToString()}'", token: token); | |
723 return skipToEof(token); | |
724 } | |
725 | |
726 Token expectedBlockToSkip(Token token) { | |
727 if (token.stringValue === 'native') { | |
728 return native.handleNativeBlockToSkip(this, token); | |
729 } else { | |
730 return unexpected(token); | |
731 } | |
732 } | |
733 | |
734 Token expectedFunctionBody(Token token) { | |
735 String printString = token.slowToString(); | |
736 listener.cancel("expected a function body, but got '$printString'", | |
737 token: token); | |
738 return skipToEof(token); | |
739 } | |
740 | |
741 Token expectedClassBody(Token token) { | |
742 listener.cancel("expected a class body, but got '${token.slowToString()}'", | |
743 token: token); | |
744 return skipToEof(token); | |
745 } | |
746 | |
747 Token expectedClassBodyToSkip(Token token) { | |
748 if (token.stringValue === 'native') { | |
749 return native.handleNativeClassBodyToSkip(this, token); | |
750 } else { | |
751 return unexpected(token); | |
752 } | |
753 } | |
754 | |
755 void recoverableError(String message, [Token token, Node node]) { | |
756 listener.cancel(message, token: token, node: node); | |
757 } | |
758 | |
759 void pushElement(Element element) { | |
760 compilationUnitElement.addMember(element, listener); | |
761 } | |
762 | |
763 void pushNode(Node node) { | |
764 nodes = nodes.prepend(node); | |
765 if (VERBOSE) log("push $nodes"); | |
766 } | |
767 | |
768 Node popNode() { | |
769 assert(!nodes.isEmpty()); | |
770 Node node = nodes.head; | |
771 nodes = nodes.tail; | |
772 if (VERBOSE) log("pop $nodes"); | |
773 return node; | |
774 } | |
775 | |
776 Node peekNode() { | |
777 assert(!nodes.isEmpty()); | |
778 Node node = nodes.head; | |
779 if (VERBOSE) log("peek $node"); | |
780 return node; | |
781 } | |
782 | |
783 void log(message) { | |
784 print(message); | |
785 } | |
786 | |
787 NodeList makeNodeList(int count, Token beginToken, Token endToken, | |
788 String delimiter) { | |
789 Link<Node> nodes = const EmptyLink<Node>(); | |
790 for (; count > 0; --count) { | |
791 // This effectively reverses the order of nodes so they end up | |
792 // in correct (source) order. | |
793 nodes = nodes.prepend(popNode()); | |
794 } | |
795 SourceString sourceDelimiter = | |
796 (delimiter === null) ? null : new SourceString(delimiter); | |
797 return new NodeList(beginToken, nodes, endToken, sourceDelimiter); | |
798 } | |
799 | |
800 void beginLiteralString(Token token) { | |
801 SourceString source = token.value; | |
802 StringQuoting quoting = StringValidator.quotingFromString(source); | |
803 pushQuoting(quoting); | |
804 // Just wrap the token for now. At the end of the interpolation, | |
805 // when we know how many there are, go back and validate the tokens. | |
806 pushNode(new LiteralString(token, null)); | |
807 } | |
808 | |
809 void handleStringPart(Token token) { | |
810 // Just push an unvalidated token now, and replace it when we know the | |
811 // end of the interpolation. | |
812 pushNode(new LiteralString(token, null)); | |
813 } | |
814 | |
815 void endLiteralString(int count) { | |
816 StringQuoting quoting = popQuoting(); | |
817 | |
818 Link<StringInterpolationPart> parts = | |
819 const EmptyLink<StringInterpolationPart>(); | |
820 // Parts of the string interpolation are popped in reverse order, | |
821 // starting with the last literal string part. | |
822 bool isLast = true; | |
823 for (int i = 0; i < count; i++) { | |
824 LiteralString string = popNode(); | |
825 DartString validation = | |
826 stringValidator.validateInterpolationPart(string.token, quoting, | |
827 isFirst: false, | |
828 isLast: isLast); | |
829 // Replace the unvalidated LiteralString with a new LiteralString | |
830 // object that has the validation result included. | |
831 string = new LiteralString(string.token, validation); | |
832 Expression expression = popNode(); | |
833 parts = parts.prepend(new StringInterpolationPart(expression, string)); | |
834 isLast = false; | |
835 } | |
836 | |
837 LiteralString string = popNode(); | |
838 DartString validation = | |
839 stringValidator.validateInterpolationPart(string.token, quoting, | |
840 isFirst: true, | |
841 isLast: isLast); | |
842 string = new LiteralString(string.token, validation); | |
843 if (isLast) { | |
844 pushNode(string); | |
845 } else { | |
846 NodeList nodes = new NodeList(null, parts, null, null); | |
847 pushNode(new StringInterpolation(string, nodes)); | |
848 } | |
849 } | |
850 | |
851 void handleStringJuxtaposition(int stringCount) { | |
852 assert(stringCount != 0); | |
853 Expression accumulator = popNode(); | |
854 stringCount--; | |
855 while (stringCount > 0) { | |
856 Expression expression = popNode(); | |
857 accumulator = new StringJuxtaposition(expression, accumulator); | |
858 stringCount--; | |
859 } | |
860 pushNode(accumulator); | |
861 } | |
862 } | |
863 | |
864 class NodeListener extends ElementListener { | |
865 NodeListener(DiagnosticListener listener, CompilationUnitElement element) | |
866 : super(listener, element); | |
867 | |
868 void endClassDeclaration(int interfacesCount, Token beginToken, | |
869 Token extendsKeyword, Token implementsKeyword, | |
870 Token endToken) { | |
871 NodeList body = popNode(); | |
872 NodeList interfaces = | |
873 makeNodeList(interfacesCount, implementsKeyword, null, ","); | |
874 TypeAnnotation supertype = popNode(); | |
875 NodeList typeParameters = popNode(); | |
876 Identifier name = popNode(); | |
877 pushNode(new ClassNode(name, typeParameters, supertype, interfaces, null, | |
878 beginToken, extendsKeyword, endToken)); | |
879 } | |
880 | |
881 void endFunctionTypeAlias(Token typedefKeyword, Token endToken) { | |
882 NodeList formals = popNode(); | |
883 NodeList typeParameters = null; // TODO(ahe): Don't discard these. | |
884 Identifier name = popNode(); | |
885 TypeAnnotation returnType = popNode(); | |
886 pushNode(new Typedef(returnType, name, typeParameters, formals, | |
887 typedefKeyword, endToken)); | |
888 } | |
889 | |
890 void endInterface(int supertypeCount, Token interfaceKeyword, | |
891 Token extendsKeyword, Token endToken) { | |
892 NodeList body = popNode(); | |
893 TypeAnnotation defaultClause = popNode(); | |
894 NodeList supertypes = makeNodeList(supertypeCount, extendsKeyword, | |
895 null, ','); | |
896 NodeList typeParameters = popNode(); | |
897 Identifier name = popNode(); | |
898 pushNode(new ClassNode(name, typeParameters, null, supertypes, | |
899 defaultClause, interfaceKeyword, null, endToken)); | |
900 } | |
901 | |
902 void endClassBody(int memberCount, Token beginToken, Token endToken) { | |
903 pushNode(makeNodeList(memberCount, beginToken, endToken, null)); | |
904 } | |
905 | |
906 void endTopLevelFields(int count, Token beginToken, Token endToken) { | |
907 NodeList variables = makeNodeList(count, null, null, ","); | |
908 Modifiers modifiers = popNode(); | |
909 pushNode(new VariableDefinitions(null, modifiers, variables, endToken)); | |
910 } | |
911 | |
912 void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) { | |
913 Statement body = popNode(); | |
914 NodeList formalParameters = popNode(); | |
915 Identifier name = popNode(); | |
916 Modifiers modifiers = popNode(); | |
917 ElementKind kind; | |
918 if (getOrSet === null) { | |
919 kind = ElementKind.FUNCTION; | |
920 } else if (getOrSet.stringValue === 'get') { | |
921 kind = ElementKind.GETTER; | |
922 } else if (getOrSet.stringValue === 'set') { | |
923 kind = ElementKind.SETTER; | |
924 } | |
925 pushElement(new PartialFunctionElement(name.source, beginToken, getOrSet, | |
926 endToken, kind, | |
927 modifiers, compilationUnitElement)); | |
928 } | |
929 | |
930 void endFormalParameter(Token token, Token thisKeyword) { | |
931 Expression name = popNode(); | |
932 if (thisKeyword !== null) { | |
933 Identifier thisIdentifier = new Identifier(thisKeyword); | |
934 if (name.asSend() === null) { | |
935 name = new Send(thisIdentifier, name); | |
936 } else { | |
937 name = name.asSend().copyWithReceiver(thisIdentifier); | |
938 } | |
939 } | |
940 TypeAnnotation type = popNode(); | |
941 Modifiers modifiers = popNode(); | |
942 pushNode(new VariableDefinitions(type, modifiers, | |
943 new NodeList.singleton(name), token)); | |
944 } | |
945 | |
946 void endFormalParameters(int count, Token beginToken, Token endToken) { | |
947 pushNode(makeNodeList(count, beginToken, endToken, ",")); | |
948 } | |
949 | |
950 void endArguments(int count, Token beginToken, Token endToken) { | |
951 pushNode(makeNodeList(count, beginToken, endToken, ",")); | |
952 } | |
953 | |
954 void handleNoArguments(Token token) { | |
955 pushNode(null); | |
956 } | |
957 | |
958 void endReturnStatement(bool hasExpression, | |
959 Token beginToken, Token endToken) { | |
960 Expression expression = hasExpression ? popNode() : null; | |
961 pushNode(new Return(beginToken, endToken, expression)); | |
962 } | |
963 | |
964 void endExpressionStatement(Token token) { | |
965 pushNode(new ExpressionStatement(popNode(), token)); | |
966 } | |
967 | |
968 void handleOnError(Token token, var error) { | |
969 listener.cancel("internal error: '${token.value}': ${error}", token: token); | |
970 } | |
971 | |
972 Token expectedFunctionBody(Token token) { | |
973 if (token.stringValue === 'native') { | |
974 return native.handleNativeFunctionBody(this, token); | |
975 } else { | |
976 listener.cancel( | |
977 "expected a function body, but got '${token.slowToString()}'", | |
978 token: token); | |
979 return skipToEof(token); | |
980 } | |
981 } | |
982 | |
983 Token expectedClassBody(Token token) { | |
984 if (token.stringValue === 'native') { | |
985 return native.handleNativeClassBody(this, token); | |
986 } else { | |
987 listener.cancel( | |
988 "expected a class body, but got '${token.slowToString()}'", | |
989 token: token); | |
990 return skipToEof(token); | |
991 } | |
992 } | |
993 | |
994 void handleLiteralInt(Token token) { | |
995 pushNode(new LiteralInt(token, (t, e) => handleOnError(t, e))); | |
996 } | |
997 | |
998 void handleLiteralDouble(Token token) { | |
999 pushNode(new LiteralDouble(token, (t, e) => handleOnError(t, e))); | |
1000 } | |
1001 | |
1002 void handleLiteralBool(Token token) { | |
1003 pushNode(new LiteralBool(token, (t, e) => handleOnError(t, e))); | |
1004 } | |
1005 | |
1006 void handleLiteralNull(Token token) { | |
1007 pushNode(new LiteralNull(token)); | |
1008 } | |
1009 | |
1010 void handleBinaryExpression(Token token) { | |
1011 Node argument = popNode(); | |
1012 Node receiver = popNode(); | |
1013 if (token.stringValue === '.') { | |
1014 if (argument is !Send) internalError(node: argument); | |
1015 if (argument.asSend().receiver !== null) internalError(node: argument); | |
1016 if (argument is SendSet) internalError(node: argument); | |
1017 pushNode(argument.asSend().copyWithReceiver(receiver)); | |
1018 } else { | |
1019 NodeList arguments = new NodeList.singleton(argument); | |
1020 pushNode(new Send(receiver, new Operator(token), arguments)); | |
1021 } | |
1022 } | |
1023 | |
1024 void handleAssignmentExpression(Token token) { | |
1025 Node arg = popNode(); | |
1026 Node node = popNode(); | |
1027 Send send = node.asSend(); | |
1028 if (send === null) internalError(node: node); | |
1029 if (!(send.isPropertyAccess || send.isIndex)) internalError(node: send); | |
1030 if (send.asSendSet() !== null) internalError(node: send); | |
1031 NodeList arguments; | |
1032 if (send.isIndex) { | |
1033 Link<Node> link = new Link<Node>(arg); | |
1034 link = link.prepend(send.arguments.head); | |
1035 arguments = new NodeList(null, link); | |
1036 } else { | |
1037 arguments = new NodeList.singleton(arg); | |
1038 } | |
1039 Operator op = new Operator(token); | |
1040 pushNode(new SendSet(send.receiver, send.selector, op, arguments)); | |
1041 } | |
1042 | |
1043 void handleConditionalExpression(Token question, Token colon) { | |
1044 Node elseExpression = popNode(); | |
1045 Node thenExpression = popNode(); | |
1046 Node condition = popNode(); | |
1047 pushNode(new Conditional( | |
1048 condition, thenExpression, elseExpression, question, colon)); | |
1049 } | |
1050 | |
1051 void endSend(Token token) { | |
1052 NodeList arguments = popNode(); | |
1053 Node selector = popNode(); | |
1054 // TODO(ahe): Handle receiver. | |
1055 pushNode(new Send(null, selector, arguments)); | |
1056 } | |
1057 | |
1058 void endFunctionBody(int count, Token beginToken, Token endToken) { | |
1059 pushNode(new Block(makeNodeList(count, beginToken, endToken, null))); | |
1060 } | |
1061 | |
1062 void handleNoFunctionBody(Token token) { | |
1063 pushNode(null); | |
1064 } | |
1065 | |
1066 void endFunction(Token getOrSet, Token endToken) { | |
1067 Statement body = popNode(); | |
1068 NodeList initializers = popNode(); | |
1069 NodeList formals = popNode(); | |
1070 // The name can be an identifier or a send in case of named constructors. | |
1071 Expression name = popNode(); | |
1072 TypeAnnotation type = popNode(); | |
1073 Modifiers modifiers = popNode(); | |
1074 pushNode(new FunctionExpression(name, formals, body, type, | |
1075 modifiers, initializers, getOrSet)); | |
1076 } | |
1077 | |
1078 void endFunctionDeclaration(Token endToken) { | |
1079 pushNode(new FunctionDeclaration(popNode())); | |
1080 } | |
1081 | |
1082 void endVariablesDeclaration(int count, Token endToken) { | |
1083 // TODO(ahe): Pick one name for this concept, either | |
1084 // VariablesDeclaration or VariableDefinitions. | |
1085 NodeList variables = makeNodeList(count, null, null, ","); | |
1086 TypeAnnotation type = popNode(); | |
1087 Modifiers modifiers = popNode(); | |
1088 pushNode(new VariableDefinitions(type, modifiers, variables, endToken)); | |
1089 } | |
1090 | |
1091 void endInitializer(Token assignmentOperator) { | |
1092 Expression initializer = popNode(); | |
1093 NodeList arguments = new NodeList.singleton(initializer); | |
1094 Expression name = popNode(); | |
1095 Operator op = new Operator(assignmentOperator); | |
1096 pushNode(new SendSet(null, name, op, arguments)); | |
1097 } | |
1098 | |
1099 void endIfStatement(Token ifToken, Token elseToken) { | |
1100 Statement elsePart = (elseToken === null) ? null : popNode(); | |
1101 Statement thenPart = popNode(); | |
1102 ParenthesizedExpression condition = popNode(); | |
1103 pushNode(new If(condition, thenPart, elsePart, ifToken, elseToken)); | |
1104 } | |
1105 | |
1106 void endForStatement(int updateExpressionCount, | |
1107 Token beginToken, Token endToken) { | |
1108 Statement body = popNode(); | |
1109 NodeList updates = makeNodeList(updateExpressionCount, null, null, ','); | |
1110 Statement condition = popNode(); | |
1111 Node initializer = popNode(); | |
1112 pushNode(new For(initializer, condition, updates, body, beginToken)); | |
1113 } | |
1114 | |
1115 void handleNoExpression(Token token) { | |
1116 pushNode(null); | |
1117 } | |
1118 | |
1119 void endDoWhileStatement(Token doKeyword, Token whileKeyword, | |
1120 Token endToken) { | |
1121 Expression condition = popNode(); | |
1122 Statement body = popNode(); | |
1123 pushNode(new DoWhile(body, condition, doKeyword, whileKeyword, endToken)); | |
1124 } | |
1125 | |
1126 void endWhileStatement(Token whileKeyword, Token endToken) { | |
1127 Statement body = popNode(); | |
1128 Expression condition = popNode(); | |
1129 pushNode(new While(condition, body, whileKeyword)); | |
1130 } | |
1131 | |
1132 void endBlock(int count, Token beginToken, Token endToken) { | |
1133 pushNode(new Block(makeNodeList(count, beginToken, endToken, null))); | |
1134 } | |
1135 | |
1136 void endThrowStatement(Token throwToken, Token endToken) { | |
1137 Expression expression = popNode(); | |
1138 pushNode(new Throw(expression, throwToken, endToken)); | |
1139 } | |
1140 | |
1141 void endRethrowStatement(Token throwToken, Token endToken) { | |
1142 pushNode(new Throw(null, throwToken, endToken)); | |
1143 } | |
1144 | |
1145 void handleUnaryPrefixExpression(Token token) { | |
1146 pushNode(new Send.prefix(popNode(), new Operator(token))); | |
1147 } | |
1148 | |
1149 void handleSuperExpression(Token token) { | |
1150 pushNode(new Identifier(token)); | |
1151 } | |
1152 | |
1153 void handleThisExpression(Token token) { | |
1154 pushNode(new Identifier(token)); | |
1155 } | |
1156 | |
1157 void handleUnaryAssignmentExpression(Token token, bool isPrefix) { | |
1158 Node node = popNode(); | |
1159 Send send = node.asSend(); | |
1160 if (send === null) internalError(node: node); | |
1161 if (!(send.isPropertyAccess || send.isIndex)) internalError(node: send); | |
1162 if (send.asSendSet() !== null) internalError(node: send); | |
1163 Node argument = null; | |
1164 if (send.isIndex) argument = send.arguments.head; | |
1165 Operator op = new Operator(token); | |
1166 | |
1167 if (isPrefix) { | |
1168 pushNode(new SendSet.prefix(send.receiver, send.selector, op, argument)); | |
1169 } else { | |
1170 pushNode(new SendSet.postfix(send.receiver, send.selector, op, argument)); | |
1171 } | |
1172 } | |
1173 | |
1174 void handleUnaryPostfixAssignmentExpression(Token token) { | |
1175 handleUnaryAssignmentExpression(token, false); | |
1176 } | |
1177 | |
1178 void handleUnaryPrefixAssignmentExpression(Token token) { | |
1179 handleUnaryAssignmentExpression(token, true); | |
1180 } | |
1181 | |
1182 void endInitializers(int count, Token beginToken, Token endToken) { | |
1183 pushNode(makeNodeList(count, beginToken, null, ',')); | |
1184 } | |
1185 | |
1186 void handleNoInitializers() { | |
1187 pushNode(null); | |
1188 } | |
1189 | |
1190 void endFields(int count, Token beginToken, Token endToken) { | |
1191 NodeList variables = makeNodeList(count, null, null, ","); | |
1192 Modifiers modifiers = popNode(); | |
1193 pushNode(new VariableDefinitions(null, modifiers, variables, endToken)); | |
1194 } | |
1195 | |
1196 void endMethod(Token getOrSet, Token beginToken, Token endToken) { | |
1197 Statement body = popNode(); | |
1198 NodeList initializers = popNode(); | |
1199 NodeList formalParameters = popNode(); | |
1200 Expression name = popNode(); | |
1201 Modifiers modifiers = popNode(); | |
1202 pushNode(new FunctionExpression(name, formalParameters, body, null, | |
1203 modifiers, initializers, getOrSet)); | |
1204 } | |
1205 | |
1206 void handleLiteralMap(int count, Token beginToken, Token constKeyword, | |
1207 Token endToken) { | |
1208 NodeList entries = makeNodeList(count, beginToken, endToken, ','); | |
1209 NodeList typeArguments = popNode(); | |
1210 pushNode(new LiteralMap(typeArguments, entries)); | |
1211 } | |
1212 | |
1213 void endLiteralMapEntry(Token colon, Token endToken) { | |
1214 Expression value = popNode(); | |
1215 Expression key = popNode(); | |
1216 if (key.asLiteralString() === null) { | |
1217 recoverableError('expected a constant string', node: key); | |
1218 } | |
1219 pushNode(new LiteralMapEntry(key, colon, value)); | |
1220 } | |
1221 | |
1222 void handleLiteralList(int count, Token beginToken, Token constKeyword, | |
1223 Token endToken) { | |
1224 NodeList elements = makeNodeList(count, beginToken, endToken, ','); | |
1225 NodeList typeArguments = popNode(); | |
1226 // TODO(ahe): Type arguments are discarded. | |
1227 pushNode(new LiteralList(null, elements, constKeyword)); | |
1228 } | |
1229 | |
1230 void handleIndexedExpression(Token openSquareBracket, | |
1231 Token closeSquareBracket) { | |
1232 NodeList arguments = | |
1233 makeNodeList(1, openSquareBracket, closeSquareBracket, null); | |
1234 Node receiver = popNode(); | |
1235 Token token = | |
1236 new StringToken(INDEX_INFO, '[]', openSquareBracket.charOffset); | |
1237 Node selector = new Operator(token); | |
1238 pushNode(new Send(receiver, selector, arguments)); | |
1239 } | |
1240 | |
1241 void handleNewExpression(Token token, bool named) { | |
1242 NodeList arguments = popNode(); | |
1243 Node name = popNode(); | |
1244 if (named) { | |
1245 TypeAnnotation type = popNode(); | |
1246 name = new Send(type, name); | |
1247 } | |
1248 pushNode(new NewExpression(token, new Send(null, name, arguments))); | |
1249 } | |
1250 | |
1251 void handleConstExpression(Token token, bool named) { | |
1252 NodeList arguments = popNode(); | |
1253 if (named) { | |
1254 Identifier name = popNode(); | |
1255 } | |
1256 TypeAnnotation type = popNode(); | |
1257 pushNode(new NewExpression(token, new Send(null, type, arguments))); | |
1258 } | |
1259 | |
1260 void handleOperatorName(Token operatorKeyword, Token token) { | |
1261 Operator op = new Operator(token); | |
1262 pushNode(new Send(new Identifier(operatorKeyword), op, null)); | |
1263 } | |
1264 | |
1265 void handleNamedArgument(Token colon) { | |
1266 Expression expression = popNode(); | |
1267 Identifier name = popNode(); | |
1268 pushNode(new NamedArgument(name, colon, expression)); | |
1269 } | |
1270 | |
1271 void endOptionalFormalParameters(int count, | |
1272 Token beginToken, Token endToken) { | |
1273 pushNode(makeNodeList(count, beginToken, endToken, ',')); | |
1274 } | |
1275 | |
1276 void handleFunctionTypedFormalParameter(Token endToken) { | |
1277 NodeList formals = popNode(); | |
1278 Identifier name = popNode(); | |
1279 TypeAnnotation returnType = popNode(); | |
1280 pushNode(null); // Signal "no type" to endFormalParameter. | |
1281 pushNode(new FunctionExpression(name, formals, null, returnType, | |
1282 null, null, null)); | |
1283 } | |
1284 | |
1285 void handleValuedFormalParameter(Token equals, Token token) { | |
1286 Expression defaultValue = popNode(); | |
1287 Expression parameterName = popNode(); | |
1288 pushNode(new SendSet(null, parameterName, new Operator(equals), | |
1289 new NodeList.singleton(defaultValue))); | |
1290 } | |
1291 | |
1292 void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) { | |
1293 Block finallyBlock = null; | |
1294 if (finallyKeyword !== null) { | |
1295 finallyBlock = popNode(); | |
1296 } | |
1297 NodeList catchBlocks = makeNodeList(catchCount, null, null, null); | |
1298 Block tryBlock = popNode(); | |
1299 pushNode(new TryStatement(tryBlock, catchBlocks, finallyBlock, | |
1300 tryKeyword, finallyKeyword)); | |
1301 } | |
1302 | |
1303 void handleCatchBlock(Token catchKeyword) { | |
1304 Block block = popNode(); | |
1305 NodeList formals = popNode(); | |
1306 pushNode(new CatchBlock(formals, block, catchKeyword)); | |
1307 } | |
1308 | |
1309 void endSwitchStatement(Token switchKeyword, Token endToken) { | |
1310 NodeList cases = popNode(); | |
1311 ParenthesizedExpression expression = popNode(); | |
1312 pushNode(new SwitchStatement(expression, cases, switchKeyword)); | |
1313 } | |
1314 | |
1315 void endSwitchBlock(int caseCount, Token beginToken, Token endToken) { | |
1316 Link<Node> nodes = const EmptyLink<Node>(); | |
1317 while (caseCount > 0) { | |
1318 SwitchCase switchCase = popNode(); | |
1319 nodes = nodes.prepend(switchCase); | |
1320 caseCount--; | |
1321 } | |
1322 pushNode(new NodeList(beginToken, nodes, endToken, null)); | |
1323 } | |
1324 | |
1325 void handleSwitchCase(Token labelToken, int expressionCount, | |
1326 Token defaultKeyword, int statementCount, | |
1327 Token firstToken, Token endToken) { | |
1328 NodeList statements = makeNodeList(statementCount, null, null, null); | |
1329 NodeList expressions = makeNodeList(expressionCount, null, null, null); | |
1330 Identifier label = null; | |
1331 if (labelToken !== null) { | |
1332 label = popNode(); | |
1333 } | |
1334 pushNode(new SwitchCase(label, expressions, defaultKeyword, statements, | |
1335 firstToken)); | |
1336 } | |
1337 | |
1338 void handleBreakStatement(bool hasTarget, | |
1339 Token breakKeyword, Token endToken) { | |
1340 Identifier target = null; | |
1341 if (hasTarget) { | |
1342 target = popNode(); | |
1343 } | |
1344 pushNode(new BreakStatement(target, breakKeyword, endToken)); | |
1345 } | |
1346 | |
1347 void handleContinueStatement(bool hasTarget, | |
1348 Token continueKeyword, Token endToken) { | |
1349 Identifier target = null; | |
1350 if (hasTarget) { | |
1351 target = popNode(); | |
1352 } | |
1353 pushNode(new ContinueStatement(target, continueKeyword, endToken)); | |
1354 } | |
1355 | |
1356 void handleEmptyStatement(Token token) { | |
1357 pushNode(new EmptyStatement(token)); | |
1358 } | |
1359 | |
1360 void endFactoryMethod(Token factoryKeyword, Token periodBeforeName, | |
1361 Token endToken) { | |
1362 Statement body = popNode(); | |
1363 NodeList formals = popNode(); | |
1364 NodeList typeParameters = popNode(); // TODO(karlklose): don't throw away. | |
1365 Node name = popNode(); | |
1366 if (periodBeforeName !== null) { | |
1367 // A library prefix was handled in [handleQualified]. | |
1368 name = new Send(popNode(), name); | |
1369 } | |
1370 handleModifier(factoryKeyword); | |
1371 handleModifiers(1); | |
1372 Modifiers modifiers = popNode(); | |
1373 pushNode(new FunctionExpression(name, formals, body, null, | |
1374 modifiers, null, null)); | |
1375 } | |
1376 | |
1377 void endForInStatement(Token beginToken, Token inKeyword, Token endToken) { | |
1378 Statement body = popNode(); | |
1379 Expression expression = popNode(); | |
1380 Node declaredIdentifier = popNode(); | |
1381 pushNode(new ForInStatement(declaredIdentifier, expression, body, | |
1382 beginToken, inKeyword)); | |
1383 } | |
1384 | |
1385 void endUnamedFunction(Token token) { | |
1386 Statement body = popNode(); | |
1387 NodeList formals = popNode(); | |
1388 pushNode(new FunctionExpression(null, formals, body, null, | |
1389 null, null, null)); | |
1390 } | |
1391 | |
1392 void handleIsOperator(Token operathor, Token not, Token endToken) { | |
1393 TypeAnnotation type = popNode(); | |
1394 Expression expression = popNode(); | |
1395 Node argument; | |
1396 if (not != null) { | |
1397 argument = new Send.prefix(type, new Operator(not)); | |
1398 } else { | |
1399 argument = type; | |
1400 } | |
1401 | |
1402 NodeList arguments = new NodeList.singleton(argument); | |
1403 pushNode(new Send(expression, new Operator(operathor), arguments)); | |
1404 } | |
1405 | |
1406 void endLabeledStatement(Token colon) { | |
1407 Statement statement = popNode(); | |
1408 Identifier label = popNode(); | |
1409 pushNode(new LabeledStatement(label, colon, statement)); | |
1410 } | |
1411 | |
1412 void log(message) { | |
1413 listener.log(message); | |
1414 } | |
1415 | |
1416 void internalError([Token token, Node node]) { | |
1417 listener.cancel('internal error', token: token, node: node); | |
1418 throw 'internal error'; | |
1419 } | |
1420 } | |
1421 | |
1422 class PartialFunctionElement extends FunctionElement { | |
1423 final Token beginToken; | |
1424 final Token getOrSet; | |
1425 final Token endToken; | |
1426 | |
1427 PartialFunctionElement(SourceString name, | |
1428 Token this.beginToken, | |
1429 Token this.getOrSet, | |
1430 Token this.endToken, | |
1431 ElementKind kind, | |
1432 Modifiers modifiers, | |
1433 Element enclosing) | |
1434 : super(name, kind, modifiers, enclosing); | |
1435 | |
1436 FunctionExpression parseNode(DiagnosticListener listener) { | |
1437 if (cachedNode != null) return cachedNode; | |
1438 cachedNode = parse(listener, | |
1439 getCompilationUnit(), | |
1440 (p) => p.parseFunction(beginToken, getOrSet)); | |
1441 return cachedNode; | |
1442 } | |
1443 | |
1444 Token position() => findMyName(beginToken); | |
1445 } | |
1446 | |
1447 class PartialFieldListElement extends VariableListElement { | |
1448 final Token beginToken; | |
1449 final Token endToken; | |
1450 | |
1451 PartialFieldListElement(Token this.beginToken, | |
1452 Token this.endToken, | |
1453 Modifiers modifiers, | |
1454 Element enclosing) | |
1455 : super(ElementKind.VARIABLE_LIST, modifiers, enclosing); | |
1456 | |
1457 VariableDefinitions parseNode(DiagnosticListener listener) { | |
1458 if (cachedNode != null) return cachedNode; | |
1459 cachedNode = parse(listener, | |
1460 getCompilationUnit(), | |
1461 (p) => p.parseVariablesDeclaration(beginToken)); | |
1462 return cachedNode; | |
1463 } | |
1464 | |
1465 Token position() => beginToken; // findMyName doesn't work. I'm nameless. | |
1466 } | |
1467 | |
1468 Node parse(DiagnosticListener diagnosticListener, | |
1469 CompilationUnitElement element, | |
1470 doParse(Parser parser)) { | |
1471 NodeListener listener = new NodeListener(diagnosticListener, element); | |
1472 doParse(new Parser(listener)); | |
1473 Node node = listener.popNode(); | |
1474 assert(listener.nodes.isEmpty()); | |
1475 return node; | |
1476 } | |
OLD | NEW |