Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(75)

Side by Side Diff: pkg/compiler/lib/src/parser/partial_elements.dart

Issue 1311783012: Split parser/listener.dart, parser/class_element_listener.dart and tokens/token.dart into smaller l… (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dart2js.parser.listener; 5 library dart2js.parser.partial_elements;
6 6
7 import '../compiler.dart' show 7 import '../compiler.dart' show
8 Compiler; 8 Compiler;
9 import '../dart_types.dart' show DynamicType; 9 import '../dart_types.dart' show DynamicType;
10 import '../diagnostics/diagnostic_listener.dart'; 10 import '../diagnostics/diagnostic_listener.dart';
11 import '../diagnostics/invariant.dart' show 11 import '../diagnostics/invariant.dart' show
12 invariant; 12 invariant;
13 import '../diagnostics/messages.dart'; 13 import '../diagnostics/messages.dart';
14 import '../diagnostics/spannable.dart' show
15 Spannable,
16 SpannableAssertionFailure;
17 import '../elements/elements.dart' show 14 import '../elements/elements.dart' show
18 CompilationUnitElement, 15 CompilationUnitElement,
19 ConstructorElement, 16 ConstructorElement,
20 Element, 17 Element,
21 ElementKind, 18 ElementKind,
22 GetterElement, 19 GetterElement,
23 LibraryElement, 20 LibraryElement,
24 MetadataAnnotation, 21 MetadataAnnotation,
25 MethodElement, 22 MethodElement,
26 SetterElement; 23 SetterElement,
24 STATE_NOT_STARTED,
25 STATE_DONE;
27 import '../elements/modelx.dart' show 26 import '../elements/modelx.dart' show
28 BaseFunctionElementX, 27 BaseFunctionElementX,
28 ClassElementX,
29 ConstructorElementX, 29 ConstructorElementX,
30 CompilationUnitElementX,
31 DeclarationSite, 30 DeclarationSite,
32 ElementX, 31 ElementX,
33 EnumClassElementX,
34 FieldElementX, 32 FieldElementX,
35 GetterElementX, 33 GetterElementX,
36 LibraryElementX,
37 MetadataAnnotationX, 34 MetadataAnnotationX,
38 MethodElementX, 35 MethodElementX,
39 MixinApplicationElementX,
40 SetterElementX, 36 SetterElementX,
41 TypedefElementX, 37 TypedefElementX,
42 VariableList; 38 VariableList;
43 import '../native/native.dart' as native; 39 import '../elements/visitor.dart' show
44 import '../string_validator.dart' show 40 ElementVisitor;
45 StringValidator;
46 import '../tokens/keyword.dart' show
47 Keyword;
48 import '../tokens/token.dart' show 41 import '../tokens/token.dart' show
49 BAD_INPUT_INFO,
50 BadInputToken, 42 BadInputToken,
51 BeginGroupToken, 43 BeginGroupToken,
52 EOF_INFO,
53 EOF_TOKEN,
54 ErrorToken, 44 ErrorToken,
55 IDENTIFIER_INFO,
56 INDEX_INFO,
57 KeywordToken, 45 KeywordToken,
58 StringToken, 46 StringToken,
59 Token, 47 Token,
60 UnmatchedToken, 48 UnmatchedToken,
61 UnterminatedToken; 49 UnterminatedToken;
50 import '../tokens/token_constants.dart' as Tokens show
51 EOF_TOKEN;
62 import '../tree/tree.dart'; 52 import '../tree/tree.dart';
63 import '../util/util.dart' show
64 Link;
65 53
66 import 'class_element_parser.dart' show 54 import 'class_element_parser.dart' show
67 PartialClassElement; 55 ClassElementParser;
68 import 'parser.dart' show 56 import 'parser.dart' show
69 Parser; 57 Parser;
70 58 import 'listener.dart' show
71 const bool VERBOSE = false; 59 ParserError;
72 60 import 'member_listener.dart' show
73 /** 61 MemberListener;
74 * A parser event listener that does nothing except throw exceptions 62 import 'node_listener.dart' show
75 * on parser errors. 63 NodeListener;
76 */
77 class Listener {
78 set suppressParseErrors(bool value) {
79 }
80
81 void beginArguments(Token token) {
82 }
83
84 void endArguments(int count, Token beginToken, Token endToken) {
85 }
86
87 /// Handle async modifiers `async`, `async*`, `sync`.
88 void handleAsyncModifier(Token asyncToken, Token startToken) {
89 }
90
91 void beginAwaitExpression(Token token) {
92 }
93
94 void endAwaitExpression(Token beginToken, Token endToken) {
95 }
96
97 void beginBlock(Token token) {
98 }
99
100 void endBlock(int count, Token beginToken, Token endToken) {
101 }
102
103 void beginCascade(Token token) {
104 }
105
106 void endCascade() {
107 }
108
109 void beginClassBody(Token token) {
110 }
111
112 void endClassBody(int memberCount, Token beginToken, Token endToken) {
113 }
114
115 void beginClassDeclaration(Token token) {
116 }
117
118 void endClassDeclaration(int interfacesCount, Token beginToken,
119 Token extendsKeyword, Token implementsKeyword,
120 Token endToken) {
121 }
122
123 void beginCombinators(Token token) {
124 }
125
126 void endCombinators(int count) {
127 }
128
129 void beginCompilationUnit(Token token) {
130 }
131
132 void endCompilationUnit(int count, Token token) {
133 }
134
135 void beginConstructorReference(Token start) {
136 }
137
138 void endConstructorReference(Token start, Token periodBeforeName,
139 Token endToken) {
140 }
141
142 void beginDoWhileStatement(Token token) {
143 }
144
145 void endDoWhileStatement(Token doKeyword, Token whileKeyword,
146 Token endToken) {
147 }
148
149 void beginEnum(Token enumKeyword) {
150 }
151
152 void endEnum(Token enumKeyword, Token endBrace, int count) {
153 }
154
155 void beginExport(Token token) {
156 }
157
158 void endExport(Token exportKeyword, Token semicolon) {
159 }
160
161 void beginExpressionStatement(Token token) {
162 }
163
164 void endExpressionStatement(Token token) {
165 }
166
167 void beginFactoryMethod(Token token) {
168 }
169
170 void endFactoryMethod(Token beginToken, Token endToken) {
171 }
172
173 void beginFormalParameter(Token token) {
174 }
175
176 void endFormalParameter(Token thisKeyword) {
177 }
178
179 void handleNoFormalParameters(Token token) {
180 }
181
182 void beginFormalParameters(Token token) {
183 }
184
185 void endFormalParameters(int count, Token beginToken, Token endToken) {
186 }
187
188 void endFields(int count, Token beginToken, Token endToken) {
189 }
190
191 void beginForStatement(Token token) {
192 }
193
194 void endForStatement(int updateExpressionCount,
195 Token beginToken, Token endToken) {
196 }
197
198 void endForIn(Token awaitToken, Token forToken,
199 Token inKeyword, Token endToken) {
200 }
201
202 void beginFunction(Token token) {
203 }
204
205 void endFunction(Token getOrSet, Token endToken) {
206 }
207
208 void beginFunctionDeclaration(Token token) {
209 }
210
211 void endFunctionDeclaration(Token token) {
212 }
213
214 void beginFunctionBody(Token token) {
215 }
216
217 void endFunctionBody(int count, Token beginToken, Token endToken) {
218 }
219
220 void handleNoFunctionBody(Token token) {
221 }
222
223 void skippedFunctionBody(Token token) {
224 }
225
226 void beginFunctionName(Token token) {
227 }
228
229 void endFunctionName(Token token) {
230 }
231
232 void beginFunctionTypeAlias(Token token) {
233 }
234
235 void endFunctionTypeAlias(Token typedefKeyword, Token endToken) {
236 }
237
238 void beginMixinApplication(Token token) {
239 }
240
241 void endMixinApplication() {
242 }
243
244 void beginNamedMixinApplication(Token token) {
245 }
246
247 void endNamedMixinApplication(Token classKeyword,
248 Token implementsKeyword,
249 Token endToken) {
250 }
251
252 void beginHide(Token hideKeyword) {
253 }
254
255 void endHide(Token hideKeyword) {
256 }
257
258 void beginIdentifierList(Token token) {
259 }
260
261 void endIdentifierList(int count) {
262 }
263
264 void beginTypeList(Token token) {
265 }
266
267 void endTypeList(int count) {
268 }
269
270 void beginIfStatement(Token token) {
271 }
272
273 void endIfStatement(Token ifToken, Token elseToken) {
274 }
275
276 void beginImport(Token importKeyword) {
277 }
278
279 void endImport(Token importKeyword, Token DeferredKeyword,
280 Token asKeyword, Token semicolon) {
281 }
282
283 void beginInitializedIdentifier(Token token) {
284 }
285
286 void endInitializedIdentifier() {
287 }
288
289 void beginInitializer(Token token) {
290 }
291
292 void endInitializer(Token assignmentOperator) {
293 }
294
295 void beginInitializers(Token token) {
296 }
297
298 void endInitializers(int count, Token beginToken, Token endToken) {
299 }
300
301 void handleNoInitializers() {
302 }
303
304 void handleLabel(Token token) {
305 }
306
307 void beginLabeledStatement(Token token, int labelCount) {
308 }
309
310 void endLabeledStatement(int labelCount) {
311 }
312
313 void beginLibraryName(Token token) {
314 }
315
316 void endLibraryName(Token libraryKeyword, Token semicolon) {
317 }
318
319 void beginLiteralMapEntry(Token token) {
320 }
321
322 void endLiteralMapEntry(Token colon, Token endToken) {
323 }
324
325 void beginLiteralString(Token token) {
326 }
327
328 void endLiteralString(int interpolationCount) {
329 }
330
331 void handleStringJuxtaposition(int literalCount) {
332 }
333
334 void beginMember(Token token) {
335 }
336
337 void endMethod(Token getOrSet, Token beginToken, Token endToken) {
338 }
339
340 void beginMetadataStar(Token token) {
341 }
342
343 void endMetadataStar(int count, bool forParameter) {
344 }
345
346 void beginMetadata(Token token) {
347 }
348
349 void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
350 }
351
352 void beginOptionalFormalParameters(Token token) {
353 }
354
355 void endOptionalFormalParameters(int count,
356 Token beginToken, Token endToken) {
357 }
358
359 void beginPart(Token token) {
360 }
361
362 void endPart(Token partKeyword, Token semicolon) {
363 }
364
365 void beginPartOf(Token token) {
366 }
367
368 void endPartOf(Token partKeyword, Token semicolon) {
369 }
370
371 void beginRedirectingFactoryBody(Token token) {
372 }
373
374 void endRedirectingFactoryBody(Token beginToken, Token endToken) {
375 }
376
377 void beginReturnStatement(Token token) {
378 }
379
380 void endReturnStatement(bool hasExpression,
381 Token beginToken, Token endToken) {
382 }
383
384 void beginSend(Token token) {
385 }
386
387 void endSend(Token token) {
388 }
389
390 void beginShow(Token showKeyword) {
391 }
392
393 void endShow(Token showKeyword) {
394 }
395
396 void beginSwitchStatement(Token token) {
397 }
398
399 void endSwitchStatement(Token switchKeyword, Token endToken) {
400 }
401
402 void beginSwitchBlock(Token token) {
403 }
404
405 void endSwitchBlock(int caseCount, Token beginToken, Token endToken) {
406 }
407
408 void beginLiteralSymbol(Token token) {
409 }
410
411 void endLiteralSymbol(Token hashToken, int identifierCount) {
412 }
413
414 void beginThrowExpression(Token token) {
415 }
416
417 void endThrowExpression(Token throwToken, Token endToken) {
418 }
419
420 void beginRethrowStatement(Token token) {
421 }
422
423 void endRethrowStatement(Token throwToken, Token endToken) {
424 }
425
426 void endTopLevelDeclaration(Token token) {
427 }
428
429 void beginTopLevelMember(Token token) {
430 }
431
432 void endTopLevelFields(int count, Token beginToken, Token endToken) {
433 }
434
435 void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
436 }
437
438 void beginTryStatement(Token token) {
439 }
440
441 void handleCaseMatch(Token caseKeyword, Token colon) {
442 }
443
444 void handleCatchBlock(Token onKeyword, Token catchKeyword) {
445 }
446
447 void handleFinallyBlock(Token finallyKeyword) {
448 }
449
450 void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
451 }
452
453 void endType(Token beginToken, Token endToken) {
454 }
455
456 void beginTypeArguments(Token token) {
457 }
458
459 void endTypeArguments(int count, Token beginToken, Token endToken) {
460 }
461
462 void handleNoTypeArguments(Token token) {
463 }
464
465 void beginTypeVariable(Token token) {
466 }
467
468 void endTypeVariable(Token token) {
469 }
470
471 void beginTypeVariables(Token token) {
472 }
473
474 void endTypeVariables(int count, Token beginToken, Token endToken) {
475 }
476
477 void beginUnnamedFunction(Token token) {
478 }
479
480 void endUnnamedFunction(Token token) {
481 }
482
483 void beginVariablesDeclaration(Token token) {
484 }
485
486 void endVariablesDeclaration(int count, Token endToken) {
487 }
488
489 void beginWhileStatement(Token token) {
490 }
491
492 void endWhileStatement(Token whileKeyword, Token endToken) {
493 }
494
495 void handleAsOperator(Token operathor, Token endToken) {
496 // TODO(ahe): Rename [operathor] to "operator" when VM bug is fixed.
497 }
498
499 void handleAssignmentExpression(Token token) {
500 }
501
502 void handleBinaryExpression(Token token) {
503 }
504
505 void handleConditionalExpression(Token question, Token colon) {
506 }
507
508 void handleConstExpression(Token token) {
509 }
510
511 void handleFunctionTypedFormalParameter(Token token) {
512 }
513
514 void handleIdentifier(Token token) {
515 }
516
517 void handleIndexedExpression(Token openCurlyBracket,
518 Token closeCurlyBracket) {
519 }
520
521 void handleIsOperator(Token operathor, Token not, Token endToken) {
522 // TODO(ahe): Rename [operathor] to "operator" when VM bug is fixed.
523 }
524
525 void handleLiteralBool(Token token) {
526 }
527
528 void handleBreakStatement(bool hasTarget,
529 Token breakKeyword, Token endToken) {
530 }
531
532 void handleContinueStatement(bool hasTarget,
533 Token continueKeyword, Token endToken) {
534 }
535
536 void handleEmptyStatement(Token token) {
537 }
538
539 void handleAssertStatement(Token assertKeyword, Token semicolonToken) {
540 }
541
542 /** Called with either the token containing a double literal, or
543 * an immediately preceding "unary plus" token.
544 */
545 void handleLiteralDouble(Token token) {
546 }
547
548 /** Called with either the token containing an integer literal,
549 * or an immediately preceding "unary plus" token.
550 */
551 void handleLiteralInt(Token token) {
552 }
553
554 void handleLiteralList(int count, Token beginToken, Token constKeyword,
555 Token endToken) {
556 }
557
558 void handleLiteralMap(int count, Token beginToken, Token constKeyword,
559 Token endToken) {
560 }
561
562 void handleLiteralNull(Token token) {
563 }
564
565 void handleModifier(Token token) {
566 }
567
568 void handleModifiers(int count) {
569 }
570
571 void handleNamedArgument(Token colon) {
572 }
573
574 void handleNewExpression(Token token) {
575 }
576
577 void handleNoArguments(Token token) {
578 }
579
580 void handleNoExpression(Token token) {
581 }
582
583 void handleNoType(Token token) {
584 }
585
586 void handleNoTypeVariables(Token token) {
587 }
588
589 void handleOperator(Token token) {
590 }
591
592 void handleOperatorName(Token operatorKeyword, Token token) {
593 }
594
595 void handleParenthesizedExpression(BeginGroupToken token) {
596 }
597
598 void handleQualified(Token period) {
599 }
600
601 void handleStringPart(Token token) {
602 }
603
604 void handleSuperExpression(Token token) {
605 }
606
607 void handleSwitchCase(int labelCount, int expressionCount,
608 Token defaultKeyword, int statementCount,
609 Token firstToken, Token endToken) {
610 }
611
612 void handleThisExpression(Token token) {
613 }
614
615 void handleUnaryPostfixAssignmentExpression(Token token) {
616 }
617
618 void handleUnaryPrefixExpression(Token token) {
619 }
620
621 void handleUnaryPrefixAssignmentExpression(Token token) {
622 }
623
624 void handleValuedFormalParameter(Token equals, Token token) {
625 }
626
627 void handleVoidKeyword(Token token) {
628 }
629
630 void beginYieldStatement(Token token) {
631 }
632
633 void endYieldStatement(Token yieldToken, Token starToken, Token endToken) {
634 }
635
636 Token expected(String string, Token token) {
637 if (token is ErrorToken) {
638 reportErrorToken(token);
639 } else {
640 error("expected '$string', but got '${token.value}'", token);
641 }
642 return skipToEof(token);
643 }
644
645 Token synthesizeIdentifier(Token token) {
646 Token synthesizedToken =
647 new StringToken.fromString(IDENTIFIER_INFO, '?', token.charOffset);
648 synthesizedToken.next = token.next;
649 return synthesizedToken;
650 }
651
652 Token expectedIdentifier(Token token) {
653 if (token is ErrorToken) {
654 reportErrorToken(token);
655 } else {
656 error("expected identifier, but got '${token.value}'", token);
657 }
658 return skipToEof(token);
659 }
660
661 Token expectedType(Token token) {
662 if (token is ErrorToken) {
663 reportErrorToken(token);
664 } else {
665 error("expected a type, but got '${token.value}'", token);
666 }
667 return skipToEof(token);
668 }
669
670 Token expectedExpression(Token token) {
671 if (token is ErrorToken) {
672 reportErrorToken(token);
673 } else {
674 error("expected an expression, but got '${token.value}'", token);
675 }
676 return skipToEof(token);
677 }
678
679 Token unexpected(Token token) {
680 if (token is ErrorToken) {
681 reportErrorToken(token);
682 } else {
683 error("unexpected token '${token.value}'", token);
684 }
685 return skipToEof(token);
686 }
687
688 Token expectedBlockToSkip(Token token) {
689 if (token is ErrorToken) {
690 reportErrorToken(token);
691 } else {
692 error("expected a block, but got '${token.value}'", token);
693 }
694 return skipToEof(token);
695 }
696
697 Token expectedFunctionBody(Token token) {
698 if (token is ErrorToken) {
699 reportErrorToken(token);
700 } else {
701 error("expected a function body, but got '${token.value}'", token);
702 }
703 return skipToEof(token);
704 }
705
706 Token expectedClassBody(Token token) {
707 if (token is ErrorToken) {
708 reportErrorToken(token);
709 } else {
710 error("expected a class body, but got '${token.value}'", token);
711 }
712 return skipToEof(token);
713 }
714
715 Token expectedClassBodyToSkip(Token token) {
716 if (token is ErrorToken) {
717 reportErrorToken(token);
718 } else {
719 error("expected a class body, but got '${token.value}'", token);
720 }
721 return skipToEof(token);
722 }
723
724 Token expectedDeclaration(Token token) {
725 if (token is ErrorToken) {
726 reportErrorToken(token);
727 } else {
728 error("expected a declaration, but got '${token.value}'", token);
729 }
730 return skipToEof(token);
731 }
732
733 Token unmatched(Token token) {
734 if (token is ErrorToken) {
735 reportErrorToken(token);
736 } else {
737 error("unmatched '${token.value}'", token);
738 }
739 return skipToEof(token);
740 }
741
742 skipToEof(Token token) {
743 while (!identical(token.info, EOF_INFO)) {
744 token = token.next;
745 }
746 return token;
747 }
748
749 void recoverableError(Token token, String message) {
750 error(message, token);
751 }
752
753 void error(String message, Token token) {
754 throw new ParserError("$message @ ${token.charOffset}");
755 }
756
757 void reportError(Spannable spannable,
758 MessageKind messageKind,
759 [Map arguments = const {}]) {
760 MessageTemplate template = MessageTemplate.TEMPLATES[messageKind];
761 String message = template.message(arguments, true).toString();
762 Token token;
763 if (spannable is Token) {
764 token = spannable;
765 } else if (spannable is Node) {
766 token = spannable.getBeginToken();
767 } else {
768 throw new ParserError(message);
769 }
770 recoverableError(token, message);
771 }
772
773 void reportErrorToken(ErrorToken token) {
774 if (token is BadInputToken) {
775 String hex = token.character.toRadixString(16);
776 if (hex.length < 4) {
777 String padding = "0000".substring(hex.length);
778 hex = "$padding$hex";
779 }
780 reportError(
781 token, MessageKind.BAD_INPUT_CHARACTER, {'characterHex': hex});
782 } else if (token is UnterminatedToken) {
783 MessageKind kind;
784 var arguments = const {};
785 switch (token.start) {
786 case '1e':
787 kind = MessageKind.EXPONENT_MISSING;
788 break;
789 case '"':
790 case "'":
791 case '"""':
792 case "'''":
793 case 'r"':
794 case "r'":
795 case 'r"""':
796 case "r'''":
797 kind = MessageKind.UNTERMINATED_STRING;
798 arguments = {'quote': token.start};
799 break;
800 case '0x':
801 kind = MessageKind.HEX_DIGIT_EXPECTED;
802 break;
803 case r'$':
804 kind = MessageKind.MALFORMED_STRING_LITERAL;
805 break;
806 case '/*':
807 kind = MessageKind.UNTERMINATED_COMMENT;
808 break;
809 default:
810 kind = MessageKind.UNTERMINATED_TOKEN;
811 break;
812 }
813 reportError(token, kind, arguments);
814 } else if (token is UnmatchedToken) {
815 String begin = token.begin.value;
816 String end = closeBraceFor(begin);
817 reportError(
818 token, MessageKind.UNMATCHED_TOKEN, {'begin': begin, 'end': end});
819 } else {
820 throw new SpannableAssertionFailure(token, token.assertionMessage);
821 }
822 }
823 }
824
825 String closeBraceFor(String openBrace) {
826 return const {
827 '(': ')',
828 '[': ']',
829 '{': '}',
830 '<': '>',
831 r'${': '}',
832 }[openBrace];
833 }
834
835 class ParserError {
836 final String reason;
837 ParserError(this.reason);
838 toString() => reason;
839 }
840
841 typedef int IdGenerator();
842
843 /**
844 * A parser event listener designed to work with [PartialParser]. It
845 * builds elements representing the top-level declarations found in
846 * the parsed compilation unit and records them in
847 * [compilationUnitElement].
848 */
849 class ElementListener extends Listener {
850 final IdGenerator idGenerator;
851 final DiagnosticListener listener;
852 final CompilationUnitElementX compilationUnitElement;
853 final StringValidator stringValidator;
854 Link<StringQuoting> interpolationScope;
855
856 Link<Node> nodes = const Link<Node>();
857
858 Link<MetadataAnnotation> metadata = const Link<MetadataAnnotation>();
859
860 /// Records a stack of booleans for each member parsed (a stack is used to
861 /// support nested members which isn't currently possible, but it also serves
862 /// as a simple way to tell we're currently parsing a member). In this case,
863 /// member refers to members of a library or a class (but currently, classes
864 /// themselves are not considered members). If the top of the stack
865 /// (memberErrors.head) is true, the current member has already reported at
866 /// least one parse error.
867 Link<bool> memberErrors = const Link<bool>();
868
869 bool suppressParseErrors = false;
870
871 ElementListener(
872 DiagnosticListener listener,
873 this.compilationUnitElement,
874 this.idGenerator)
875 : this.listener = listener,
876 stringValidator = new StringValidator(listener),
877 interpolationScope = const Link<StringQuoting>();
878
879 bool get currentMemberHasParseError {
880 return !memberErrors.isEmpty && memberErrors.head;
881 }
882
883 void pushQuoting(StringQuoting quoting) {
884 interpolationScope = interpolationScope.prepend(quoting);
885 }
886
887 StringQuoting popQuoting() {
888 StringQuoting result = interpolationScope.head;
889 interpolationScope = interpolationScope.tail;
890 return result;
891 }
892
893 StringNode popLiteralString() {
894 StringNode node = popNode();
895 // TODO(lrn): Handle interpolations in script tags.
896 if (node.isInterpolation) {
897 listener.internalError(node,
898 "String interpolation not supported in library tags.");
899 return null;
900 }
901 return node;
902 }
903
904 bool allowLibraryTags() {
905 // Library tags are only allowed in the library file itself, not
906 // in sourced files.
907 LibraryElement library = compilationUnitElement.implementationLibrary;
908 return !compilationUnitElement.hasMembers &&
909 library.entryCompilationUnit == compilationUnitElement;
910 }
911
912 void endLibraryName(Token libraryKeyword, Token semicolon) {
913 Expression name = popNode();
914 addLibraryTag(new LibraryName(libraryKeyword, name,
915 popMetadata(compilationUnitElement)));
916 }
917
918 void endImport(Token importKeyword, Token deferredKeyword, Token asKeyword,
919 Token semicolon) {
920 NodeList combinators = popNode();
921 bool isDeferred = deferredKeyword != null;
922 Identifier prefix;
923 if (asKeyword != null) {
924 prefix = popNode();
925 }
926 StringNode uri = popLiteralString();
927 addLibraryTag(new Import(importKeyword, uri, prefix, combinators,
928 popMetadata(compilationUnitElement),
929 isDeferred: isDeferred));
930 }
931
932 void endEnum(Token enumKeyword, Token endBrace, int count) {
933 NodeList names = makeNodeList(count, enumKeyword.next.next, endBrace, ",");
934 Identifier name = popNode();
935
936 int id = idGenerator();
937 Element enclosing = compilationUnitElement;
938 pushElement(new EnumClassElementX(name.source, enclosing, id,
939 new Enum(enumKeyword, name, names)));
940 rejectBuiltInIdentifier(name);
941 }
942
943 void endExport(Token exportKeyword, Token semicolon) {
944 NodeList combinators = popNode();
945 StringNode uri = popNode();
946 addLibraryTag(new Export(exportKeyword, uri, combinators,
947 popMetadata(compilationUnitElement)));
948 }
949
950 void endCombinators(int count) {
951 if (0 == count) {
952 pushNode(null);
953 } else {
954 pushNode(makeNodeList(count, null, null, " "));
955 }
956 }
957
958 void endHide(Token hideKeyword) => pushCombinator(hideKeyword);
959
960 void endShow(Token showKeyword) => pushCombinator(showKeyword);
961
962 void pushCombinator(Token keywordToken) {
963 NodeList identifiers = popNode();
964 pushNode(new Combinator(identifiers, keywordToken));
965 }
966
967 void endIdentifierList(int count) {
968 pushNode(makeNodeList(count, null, null, ","));
969 }
970
971 void endTypeList(int count) {
972 pushNode(makeNodeList(count, null, null, ","));
973 }
974
975 void endPart(Token partKeyword, Token semicolon) {
976 StringNode uri = popLiteralString();
977 addLibraryTag(new Part(partKeyword, uri,
978 popMetadata(compilationUnitElement)));
979 }
980
981 void endPartOf(Token partKeyword, Token semicolon) {
982 Expression name = popNode();
983 addPartOfTag(new PartOf(partKeyword, name,
984 popMetadata(compilationUnitElement)));
985 }
986
987 void addPartOfTag(PartOf tag) {
988 compilationUnitElement.setPartOf(tag, listener);
989 }
990
991 void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
992 if (periodBeforeName != null) {
993 popNode(); // Discard name.
994 }
995 popNode(); // Discard node (Send or Identifier).
996 pushMetadata(new PartialMetadataAnnotation(beginToken, endToken));
997 }
998
999 void endTopLevelDeclaration(Token token) {
1000 if (!metadata.isEmpty) {
1001 recoverableError(metadata.head.beginToken,
1002 'Metadata not supported here.');
1003 metadata = const Link<MetadataAnnotation>();
1004 }
1005 }
1006
1007 void endClassDeclaration(int interfacesCount, Token beginToken,
1008 Token extendsKeyword, Token implementsKeyword,
1009 Token endToken) {
1010 makeNodeList(interfacesCount, implementsKeyword, null, ","); // interfaces
1011 popNode(); // superType
1012 popNode(); // typeParameters
1013 Identifier name = popNode();
1014 int id = idGenerator();
1015 PartialClassElement element = new PartialClassElement(
1016 name.source, beginToken, endToken, compilationUnitElement, id);
1017 pushElement(element);
1018 rejectBuiltInIdentifier(name);
1019 }
1020
1021 void rejectBuiltInIdentifier(Identifier name) {
1022 if (name.token is KeywordToken) {
1023 Keyword keyword = (name.token as KeywordToken).keyword;
1024 if (!keyword.isPseudo) {
1025 recoverableError(name, "Illegal name '${keyword.syntax}'.");
1026 }
1027 }
1028 }
1029
1030 void endFunctionTypeAlias(Token typedefKeyword, Token endToken) {
1031 popNode(); // TODO(karlklose): do not throw away typeVariables.
1032 Identifier name = popNode();
1033 popNode(); // returnType
1034 pushElement(
1035 new PartialTypedefElement(
1036 name.source, compilationUnitElement, typedefKeyword, endToken));
1037 rejectBuiltInIdentifier(name);
1038 }
1039
1040 void endNamedMixinApplication(Token classKeyword,
1041 Token implementsKeyword,
1042 Token endToken) {
1043 NodeList interfaces = (implementsKeyword != null) ? popNode() : null;
1044 MixinApplication mixinApplication = popNode();
1045 Modifiers modifiers = popNode();
1046 NodeList typeParameters = popNode();
1047 Identifier name = popNode();
1048 NamedMixinApplication namedMixinApplication = new NamedMixinApplication(
1049 name, typeParameters, modifiers, mixinApplication, interfaces,
1050 classKeyword, endToken);
1051
1052 int id = idGenerator();
1053 Element enclosing = compilationUnitElement;
1054 pushElement(new MixinApplicationElementX(name.source, enclosing, id,
1055 namedMixinApplication,
1056 modifiers));
1057 rejectBuiltInIdentifier(name);
1058 }
1059
1060 void endMixinApplication() {
1061 NodeList mixins = popNode();
1062 TypeAnnotation superclass = popNode();
1063 pushNode(new MixinApplication(superclass, mixins));
1064 }
1065
1066 void handleVoidKeyword(Token token) {
1067 pushNode(new TypeAnnotation(new Identifier(token), null));
1068 }
1069
1070 void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
1071 bool hasParseError = currentMemberHasParseError;
1072 memberErrors = memberErrors.tail;
1073 Identifier name = popNode();
1074 popNode(); // type
1075 Modifiers modifiers = popNode();
1076 PartialFunctionElement element = new PartialFunctionElement(
1077 name.source, beginToken, getOrSet, endToken,
1078 modifiers, compilationUnitElement);
1079 element.hasParseError = hasParseError;
1080 pushElement(element);
1081 }
1082
1083 void endTopLevelFields(int count, Token beginToken, Token endToken) {
1084 bool hasParseError = currentMemberHasParseError;
1085 memberErrors = memberErrors.tail;
1086 void buildFieldElement(Identifier name, VariableList fields) {
1087 pushElement(
1088 new FieldElementX(name, compilationUnitElement, fields));
1089 }
1090 NodeList variables = makeNodeList(count, null, null, ",");
1091 popNode(); // type
1092 Modifiers modifiers = popNode();
1093 buildFieldElements(modifiers, variables, compilationUnitElement,
1094 buildFieldElement,
1095 beginToken, endToken, hasParseError);
1096 }
1097
1098 void buildFieldElements(Modifiers modifiers,
1099 NodeList variables,
1100 Element enclosingElement,
1101 void buildFieldElement(Identifier name,
1102 VariableList fields),
1103 Token beginToken, Token endToken,
1104 bool hasParseError) {
1105 VariableList fields =
1106 new PartialFieldList(beginToken, endToken, modifiers, hasParseError);
1107 for (Link<Node> variableNodes = variables.nodes;
1108 !variableNodes.isEmpty;
1109 variableNodes = variableNodes.tail) {
1110 Expression initializedIdentifier = variableNodes.head;
1111 Identifier identifier = initializedIdentifier.asIdentifier();
1112 if (identifier == null) {
1113 identifier = initializedIdentifier.asSendSet().selector.asIdentifier();
1114 }
1115 buildFieldElement(identifier, fields);
1116 }
1117 }
1118
1119 void handleIdentifier(Token token) {
1120 pushNode(new Identifier(token));
1121 }
1122
1123 void handleQualified(Token period) {
1124 Identifier last = popNode();
1125 Expression first = popNode();
1126 pushNode(new Send(first, last));
1127 }
1128
1129 void handleNoType(Token token) {
1130 pushNode(null);
1131 }
1132
1133 void endTypeVariable(Token token) {
1134 TypeAnnotation bound = popNode();
1135 Identifier name = popNode();
1136 pushNode(new TypeVariable(name, bound));
1137 rejectBuiltInIdentifier(name);
1138 }
1139
1140 void endTypeVariables(int count, Token beginToken, Token endToken) {
1141 pushNode(makeNodeList(count, beginToken, endToken, ','));
1142 }
1143
1144 void handleNoTypeVariables(token) {
1145 pushNode(null);
1146 }
1147
1148 void endTypeArguments(int count, Token beginToken, Token endToken) {
1149 pushNode(makeNodeList(count, beginToken, endToken, ','));
1150 }
1151
1152 void handleNoTypeArguments(Token token) {
1153 pushNode(null);
1154 }
1155
1156 void endType(Token beginToken, Token endToken) {
1157 NodeList typeArguments = popNode();
1158 Expression typeName = popNode();
1159 pushNode(new TypeAnnotation(typeName, typeArguments));
1160 }
1161
1162 void handleParenthesizedExpression(BeginGroupToken token) {
1163 Expression expression = popNode();
1164 pushNode(new ParenthesizedExpression(expression, token));
1165 }
1166
1167 void handleModifier(Token token) {
1168 pushNode(new Identifier(token));
1169 }
1170
1171 void handleModifiers(int count) {
1172 if (count == 0) {
1173 pushNode(Modifiers.EMPTY);
1174 } else {
1175 NodeList modifierNodes = makeNodeList(count, null, null, ' ');
1176 pushNode(new Modifiers(modifierNodes));
1177 }
1178 }
1179
1180 Token expected(String string, Token token) {
1181 if (token is ErrorToken) {
1182 reportErrorToken(token);
1183 } else if (identical(';', string)) {
1184 // When a semicolon is missing, it often leads to an error on the
1185 // following line. So we try to find the token preceding the semicolon
1186 // and report that something is missing *after* it.
1187 Token preceding = findPrecedingToken(token);
1188 if (preceding == token) {
1189 reportError(
1190 token, MessageKind.MISSING_TOKEN_BEFORE_THIS, {'token': string});
1191 } else {
1192 reportError(
1193 preceding, MessageKind.MISSING_TOKEN_AFTER_THIS, {'token': string});
1194 }
1195 return token;
1196 } else {
1197 reportFatalError(
1198 token,
1199 MessageTemplate.TEMPLATES[MessageKind.MISSING_TOKEN_BEFORE_THIS]
1200 .message({'token': string}, true).toString());
1201 }
1202 return skipToEof(token);
1203 }
1204
1205 /// Finds the preceding token via the begin token of the last AST node pushed
1206 /// on the [nodes] stack.
1207 Token findPrecedingToken(Token token) {
1208 Token result;
1209 Link<Node> nodes = this.nodes;
1210 while (!nodes.isEmpty) {
1211 result = findPrecedingTokenFromNode(nodes.head, token);
1212 if (result != null) {
1213 return result;
1214 }
1215 nodes = nodes.tail;
1216 }
1217 if (compilationUnitElement != null) {
1218 if (compilationUnitElement is CompilationUnitElementX) {
1219 CompilationUnitElementX unit = compilationUnitElement;
1220 Link<Element> members = unit.localMembers;
1221 while (!members.isEmpty) {
1222 ElementX member = members.head;
1223 DeclarationSite site = member.declarationSite;
1224 if (site is PartialElement) {
1225 result = findPrecedingTokenFromToken(site.endToken, token);
1226 if (result != null) {
1227 return result;
1228 }
1229 }
1230 members = members.tail;
1231 }
1232 result =
1233 findPrecedingTokenFromNode(compilationUnitElement.partTag, token);
1234 if (result != null) {
1235 return result;
1236 }
1237 }
1238 }
1239 return token;
1240 }
1241
1242 Token findPrecedingTokenFromNode(Node node, Token token) {
1243 if (node != null) {
1244 return findPrecedingTokenFromToken(node.getBeginToken(), token);
1245 }
1246 return null;
1247 }
1248
1249 Token findPrecedingTokenFromToken(Token start, Token token) {
1250 if (start != null) {
1251 Token current = start;
1252 while (current.kind != EOF_TOKEN && current.next != token) {
1253 current = current.next;
1254 }
1255 if (current.kind != EOF_TOKEN) {
1256 return current;
1257 }
1258 }
1259 return null;
1260 }
1261
1262 Token expectedIdentifier(Token token) {
1263 if (token is KeywordToken) {
1264 reportError(
1265 token, MessageKind.EXPECTED_IDENTIFIER_NOT_RESERVED_WORD,
1266 {'keyword': token.value});
1267 } else if (token is ErrorToken) {
1268 reportErrorToken(token);
1269 return synthesizeIdentifier(token);
1270 } else {
1271 reportFatalError(token,
1272 "Expected identifier, but got '${token.value}'.");
1273 }
1274 return token;
1275 }
1276
1277 Token expectedType(Token token) {
1278 pushNode(null);
1279 if (token is ErrorToken) {
1280 reportErrorToken(token);
1281 return synthesizeIdentifier(token);
1282 } else {
1283 reportFatalError(
1284 token, "Expected a type, but got '${token.value}'.");
1285 return skipToEof(token);
1286 }
1287 }
1288
1289 Token expectedExpression(Token token) {
1290 if (token is ErrorToken) {
1291 reportErrorToken(token);
1292 pushNode(new ErrorExpression(token));
1293 return token.next;
1294 } else {
1295 reportFatalError(token,
1296 "Expected an expression, but got '${token.value}'.");
1297 pushNode(null);
1298 return skipToEof(token);
1299 }
1300 }
1301
1302 Token unexpected(Token token) {
1303 if (token is ErrorToken) {
1304 reportErrorToken(token);
1305 } else {
1306 String message = "Unexpected token '${token.value}'.";
1307 if (token.info == BAD_INPUT_INFO) {
1308 message = token.value;
1309 }
1310 reportFatalError(token, message);
1311 }
1312 return skipToEof(token);
1313 }
1314
1315 Token expectedBlockToSkip(Token token) {
1316 if (identical(token.stringValue, 'native')) {
1317 return native.handleNativeBlockToSkip(this, token);
1318 } else {
1319 return unexpected(token);
1320 }
1321 }
1322
1323 Token expectedFunctionBody(Token token) {
1324 if (token is ErrorToken) {
1325 reportErrorToken(token);
1326 } else {
1327 String printString = token.value;
1328 reportFatalError(token,
1329 "Expected a function body, but got '$printString'.");
1330 }
1331 return skipToEof(token);
1332 }
1333
1334 Token expectedClassBody(Token token) {
1335 if (token is ErrorToken) {
1336 reportErrorToken(token);
1337 } else {
1338 reportFatalError(token,
1339 "Expected a class body, but got '${token.value}'.");
1340 }
1341 return skipToEof(token);
1342 }
1343
1344 Token expectedClassBodyToSkip(Token token) {
1345 return unexpected(token);
1346 }
1347
1348 Token expectedDeclaration(Token token) {
1349 if (token is ErrorToken) {
1350 reportErrorToken(token);
1351 } else {
1352 reportFatalError(token,
1353 "Expected a declaration, but got '${token.value}'.");
1354 }
1355 return skipToEof(token);
1356 }
1357
1358 Token unmatched(Token token) {
1359 if (token is ErrorToken) {
1360 reportErrorToken(token);
1361 } else {
1362 String begin = token.value;
1363 String end = closeBraceFor(begin);
1364 reportError(
1365 token, MessageKind.UNMATCHED_TOKEN, {'begin': begin, 'end': end});
1366 }
1367 Token next = token.next;
1368 while (next is ErrorToken) {
1369 next = next.next;
1370 }
1371 return next;
1372 }
1373
1374 void recoverableError(Spannable node, String message) {
1375 // TODO(johnniwinther): Make recoverable errors non-fatal.
1376 reportFatalError(node, message);
1377 }
1378
1379 void pushElement(Element element) {
1380 popMetadata(element);
1381 compilationUnitElement.addMember(element, listener);
1382 }
1383
1384 Link<MetadataAnnotation> popMetadata(ElementX element) {
1385 var result = const Link<MetadataAnnotation>();
1386 for (Link link = metadata; !link.isEmpty; link = link.tail) {
1387 element.addMetadata(link.head);
1388 // Reverse the list as is implicitly done by addMetadata.
1389 result = result.prepend(link.head);
1390 }
1391 metadata = const Link<MetadataAnnotation>();
1392 return result;
1393 }
1394
1395 void pushMetadata(MetadataAnnotation annotation) {
1396 metadata = metadata.prepend(annotation);
1397 }
1398
1399 void addLibraryTag(LibraryTag tag) {
1400 if (!allowLibraryTags()) {
1401 recoverableError(tag, 'Library tags not allowed here.');
1402 }
1403 LibraryElementX implementationLibrary =
1404 compilationUnitElement.implementationLibrary;
1405 implementationLibrary.addTag(tag, listener);
1406 }
1407
1408 void pushNode(Node node) {
1409 nodes = nodes.prepend(node);
1410 if (VERBOSE) log("push $nodes");
1411 }
1412
1413 Node popNode() {
1414 assert(!nodes.isEmpty);
1415 Node node = nodes.head;
1416 nodes = nodes.tail;
1417 if (VERBOSE) log("pop $nodes");
1418 return node;
1419 }
1420
1421 void log(message) {
1422 print(message);
1423 }
1424
1425 NodeList makeNodeList(int count, Token beginToken, Token endToken,
1426 String delimiter) {
1427 Link<Node> poppedNodes = const Link<Node>();
1428 for (; count > 0; --count) {
1429 // This effectively reverses the order of nodes so they end up
1430 // in correct (source) order.
1431 poppedNodes = poppedNodes.prepend(popNode());
1432 }
1433 return new NodeList(beginToken, poppedNodes, endToken, delimiter);
1434 }
1435
1436 void beginLiteralString(Token token) {
1437 String source = token.value;
1438 StringQuoting quoting = StringValidator.quotingFromString(source);
1439 pushQuoting(quoting);
1440 // Just wrap the token for now. At the end of the interpolation,
1441 // when we know how many there are, go back and validate the tokens.
1442 pushNode(new LiteralString(token, null));
1443 }
1444
1445 void handleStringPart(Token token) {
1446 // Just push an unvalidated token now, and replace it when we know the
1447 // end of the interpolation.
1448 pushNode(new LiteralString(token, null));
1449 }
1450
1451 void endLiteralString(int count) {
1452 StringQuoting quoting = popQuoting();
1453
1454 Link<StringInterpolationPart> parts =
1455 const Link<StringInterpolationPart>();
1456 // Parts of the string interpolation are popped in reverse order,
1457 // starting with the last literal string part.
1458 bool isLast = true;
1459 for (int i = 0; i < count; i++) {
1460 LiteralString string = popNode();
1461 DartString validation =
1462 stringValidator.validateInterpolationPart(string.token, quoting,
1463 isFirst: false,
1464 isLast: isLast);
1465 // Replace the unvalidated LiteralString with a new LiteralString
1466 // object that has the validation result included.
1467 string = new LiteralString(string.token, validation);
1468 Expression expression = popNode();
1469 parts = parts.prepend(new StringInterpolationPart(expression, string));
1470 isLast = false;
1471 }
1472
1473 LiteralString string = popNode();
1474 DartString validation =
1475 stringValidator.validateInterpolationPart(string.token, quoting,
1476 isFirst: true,
1477 isLast: isLast);
1478 string = new LiteralString(string.token, validation);
1479 if (isLast) {
1480 pushNode(string);
1481 } else {
1482 NodeList partNodes = new NodeList(null, parts, null, "");
1483 pushNode(new StringInterpolation(string, partNodes));
1484 }
1485 }
1486
1487 void handleStringJuxtaposition(int stringCount) {
1488 assert(stringCount != 0);
1489 Expression accumulator = popNode();
1490 stringCount--;
1491 while (stringCount > 0) {
1492 Expression expression = popNode();
1493 accumulator = new StringJuxtaposition(expression, accumulator);
1494 stringCount--;
1495 }
1496 pushNode(accumulator);
1497 }
1498
1499 void beginMember(Token token) {
1500 memberErrors = memberErrors.prepend(false);
1501 }
1502
1503 void beginTopLevelMember(Token token) {
1504 beginMember(token);
1505 }
1506
1507 void endFields(fieldCount, start, token) {
1508 memberErrors = memberErrors.tail;
1509 }
1510
1511 void endMethod(getOrSet, start, token) {
1512 memberErrors = memberErrors.tail;
1513 }
1514
1515 void beginFactoryMethod(Token token) {
1516 memberErrors = memberErrors.prepend(false);
1517 }
1518
1519 void endFactoryMethod(Token beginToken, Token endToken) {
1520 memberErrors = memberErrors.tail;
1521 }
1522
1523 /// Don't call this method. Should only be used as a last resort when there
1524 /// is no feasible way to recover from a parser error.
1525 void reportFatalError(Spannable spannable, String message) {
1526 reportError(spannable, MessageKind.GENERIC, {'text': message});
1527 // Some parse errors are infeasible to recover from, so we throw an error.
1528 throw new ParserError(message);
1529 }
1530
1531 void reportError(Spannable spannable,
1532 MessageKind errorCode,
1533 [Map arguments = const {}]) {
1534 if (currentMemberHasParseError) return; // Error already reported.
1535 if (suppressParseErrors) return;
1536 if (!memberErrors.isEmpty) {
1537 memberErrors = memberErrors.tail.prepend(true);
1538 }
1539 listener.reportError(spannable, errorCode, arguments);
1540 }
1541 }
1542
1543 class NodeListener extends ElementListener {
1544 NodeListener(
1545 DiagnosticListener listener,
1546 CompilationUnitElement element)
1547 : super(listener, element, null);
1548
1549 void addLibraryTag(LibraryTag tag) {
1550 pushNode(tag);
1551 }
1552
1553 void addPartOfTag(PartOf tag) {
1554 pushNode(tag);
1555 }
1556
1557 void endClassDeclaration(int interfacesCount, Token beginToken,
1558 Token extendsKeyword, Token implementsKeyword,
1559 Token endToken) {
1560 NodeList body = popNode();
1561 NodeList interfaces =
1562 makeNodeList(interfacesCount, implementsKeyword, null, ",");
1563 Node supertype = popNode();
1564 NodeList typeParameters = popNode();
1565 Identifier name = popNode();
1566 Modifiers modifiers = popNode();
1567 pushNode(new ClassNode(modifiers, name, typeParameters, supertype,
1568 interfaces, beginToken, extendsKeyword, body,
1569 endToken));
1570 }
1571
1572 void endCompilationUnit(int count, Token token) {
1573 pushNode(makeNodeList(count, null, null, '\n'));
1574 }
1575
1576 void endFunctionTypeAlias(Token typedefKeyword, Token endToken) {
1577 NodeList formals = popNode();
1578 NodeList typeParameters = popNode();
1579 Identifier name = popNode();
1580 TypeAnnotation returnType = popNode();
1581 pushNode(new Typedef(returnType, name, typeParameters, formals,
1582 typedefKeyword, endToken));
1583 }
1584
1585 void endNamedMixinApplication(Token classKeyword,
1586 Token implementsKeyword,
1587 Token endToken) {
1588 NodeList interfaces = (implementsKeyword != null) ? popNode() : null;
1589 Node mixinApplication = popNode();
1590 Modifiers modifiers = popNode();
1591 NodeList typeParameters = popNode();
1592 Identifier name = popNode();
1593 pushNode(new NamedMixinApplication(name, typeParameters,
1594 modifiers, mixinApplication,
1595 interfaces,
1596 classKeyword, endToken));
1597 }
1598
1599 void endEnum(Token enumKeyword, Token endBrace, int count) {
1600 NodeList names = makeNodeList(count, enumKeyword.next.next, endBrace, ",");
1601 Identifier name = popNode();
1602 pushNode(new Enum(enumKeyword, name, names));
1603 }
1604
1605 void endClassBody(int memberCount, Token beginToken, Token endToken) {
1606 pushNode(makeNodeList(memberCount, beginToken, endToken, null));
1607 }
1608
1609 void endTopLevelFields(int count, Token beginToken, Token endToken) {
1610 NodeList variables = makeNodeList(count, null, endToken, ",");
1611 TypeAnnotation type = popNode();
1612 Modifiers modifiers = popNode();
1613 pushNode(new VariableDefinitions(type, modifiers, variables));
1614 }
1615
1616 void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
1617 popNode(); // body
1618 popNode(); // formalParameters
1619 Identifier name = popNode();
1620 popNode(); // type
1621 Modifiers modifiers = popNode();
1622 PartialFunctionElement element = new PartialFunctionElement(
1623 name.source, beginToken, getOrSet, endToken,
1624 modifiers, compilationUnitElement);
1625 pushElement(element);
1626 }
1627
1628 void endFormalParameter(Token thisKeyword) {
1629 Expression name = popNode();
1630 if (thisKeyword != null) {
1631 Identifier thisIdentifier = new Identifier(thisKeyword);
1632 if (name.asSend() == null) {
1633 name = new Send(thisIdentifier, name);
1634 } else {
1635 name = name.asSend().copyWithReceiver(thisIdentifier, false);
1636 }
1637 }
1638 TypeAnnotation type = popNode();
1639 Modifiers modifiers = popNode();
1640 NodeList metadata = popNode();
1641 pushNode(new VariableDefinitions.forParameter(
1642 metadata, type, modifiers, new NodeList.singleton(name)));
1643 }
1644
1645 void endFormalParameters(int count, Token beginToken, Token endToken) {
1646 pushNode(makeNodeList(count, beginToken, endToken, ","));
1647 }
1648
1649 void handleNoFormalParameters(Token token) {
1650 pushNode(null);
1651 }
1652
1653 void endArguments(int count, Token beginToken, Token endToken) {
1654 pushNode(makeNodeList(count, beginToken, endToken, ","));
1655 }
1656
1657 void handleNoArguments(Token token) {
1658 pushNode(null);
1659 }
1660
1661 void endConstructorReference(Token start, Token periodBeforeName,
1662 Token endToken) {
1663 Identifier name = null;
1664 if (periodBeforeName != null) {
1665 name = popNode();
1666 }
1667 NodeList typeArguments = popNode();
1668 Node classReference = popNode();
1669 if (typeArguments != null) {
1670 classReference = new TypeAnnotation(classReference, typeArguments);
1671 } else {
1672 Identifier identifier = classReference.asIdentifier();
1673 Send send = classReference.asSend();
1674 if (identifier != null) {
1675 // TODO(ahe): Should be:
1676 // classReference = new Send(null, identifier);
1677 classReference = identifier;
1678 } else if (send != null) {
1679 classReference = send;
1680 } else {
1681 internalError(node: classReference);
1682 }
1683 }
1684 Node constructor = classReference;
1685 if (name != null) {
1686 // Either typeName<args>.name or x.y.name.
1687 constructor = new Send(classReference, name);
1688 }
1689 pushNode(constructor);
1690 }
1691
1692 void endRedirectingFactoryBody(Token beginToken,
1693 Token endToken) {
1694 pushNode(new RedirectingFactoryBody(beginToken, endToken, popNode()));
1695 }
1696
1697 void endReturnStatement(bool hasExpression,
1698 Token beginToken, Token endToken) {
1699 Expression expression = hasExpression ? popNode() : null;
1700 pushNode(new Return(beginToken, endToken, expression));
1701 }
1702
1703 void endYieldStatement(Token yieldToken, Token starToken, Token endToken) {
1704 Expression expression = popNode();
1705 pushNode(new Yield(yieldToken, starToken, expression, endToken));
1706 }
1707
1708 void endExpressionStatement(Token token) {
1709 pushNode(new ExpressionStatement(popNode(), token));
1710 }
1711
1712 void handleOnError(Token token, var errorInformation) {
1713 listener.internalError(token, "'${token.value}': ${errorInformation}");
1714 }
1715
1716 Token expectedFunctionBody(Token token) {
1717 if (identical(token.stringValue, 'native')) {
1718 return native.handleNativeFunctionBody(this, token);
1719 } else if (token is ErrorToken) {
1720 pushNode(null);
1721 reportErrorToken(token);
1722 } else {
1723 reportFatalError(token,
1724 "Expected a function body, but got '${token.value}'.");
1725 }
1726 return skipToEof(token);
1727 }
1728
1729 Token expectedClassBody(Token token) {
1730 if (token is ErrorToken) {
1731 reportErrorToken(token);
1732 return skipToEof(token);
1733 } else {
1734 reportFatalError(token,
1735 "Expected a class body, but got '${token.value}'.");
1736 return skipToEof(token);
1737 }
1738 }
1739
1740 void handleLiteralInt(Token token) {
1741 pushNode(new LiteralInt(token, (t, e) => handleOnError(t, e)));
1742 }
1743
1744 void handleLiteralDouble(Token token) {
1745 pushNode(new LiteralDouble(token, (t, e) => handleOnError(t, e)));
1746 }
1747
1748 void handleLiteralBool(Token token) {
1749 pushNode(new LiteralBool(token, (t, e) => handleOnError(t, e)));
1750 }
1751
1752 void handleLiteralNull(Token token) {
1753 pushNode(new LiteralNull(token));
1754 }
1755
1756 void endLiteralSymbol(Token hashToken, int identifierCount) {
1757 NodeList identifiers = makeNodeList(identifierCount, null, null, '.');
1758 pushNode(new LiteralSymbol(hashToken, identifiers));
1759 }
1760
1761 void handleBinaryExpression(Token token) {
1762 Node argument = popNode();
1763 Node receiver = popNode();
1764 String tokenString = token.stringValue;
1765 if (identical(tokenString, '.') ||
1766 identical(tokenString, '..') ||
1767 identical(tokenString, '?.')) {
1768 Send argumentSend = argument.asSend();
1769 if (argumentSend == null) {
1770 // TODO(ahe): The parser should diagnose this problem, not
1771 // this listener.
1772 reportFatalError(argument,
1773 'Expected an identifier.');
1774 }
1775 if (argumentSend.receiver != null) internalError(node: argument);
1776 if (argument is SendSet) internalError(node: argument);
1777 pushNode(argument.asSend().copyWithReceiver(receiver,
1778 identical(tokenString, '?.')));
1779 } else {
1780 NodeList arguments = new NodeList.singleton(argument);
1781 pushNode(new Send(receiver, new Operator(token), arguments));
1782 }
1783 if (identical(tokenString, '===')) {
1784 listener.reportError(token, MessageKind.UNSUPPORTED_EQ_EQ_EQ,
1785 {'lhs': receiver, 'rhs': argument});
1786 }
1787 if (identical(tokenString, '!==')) {
1788 listener.reportError(token, MessageKind.UNSUPPORTED_BANG_EQ_EQ,
1789 {'lhs': receiver, 'rhs': argument});
1790 }
1791 }
1792
1793 void beginCascade(Token token) {
1794 pushNode(new CascadeReceiver(popNode(), token));
1795 }
1796
1797 void endCascade() {
1798 pushNode(new Cascade(popNode()));
1799 }
1800
1801 void handleAsOperator(Token operathor, Token endToken) {
1802 TypeAnnotation type = popNode();
1803 Expression expression = popNode();
1804 NodeList arguments = new NodeList.singleton(type);
1805 pushNode(new Send(expression, new Operator(operathor), arguments));
1806 }
1807
1808 void handleAssignmentExpression(Token token) {
1809 Node arg = popNode();
1810 Node node = popNode();
1811 Send send = node.asSend();
1812 if (send == null || !(send.isPropertyAccess || send.isIndex)) {
1813 reportNotAssignable(node);
1814 }
1815 if (send.asSendSet() != null) internalError(node: send);
1816 NodeList arguments;
1817 if (send.isIndex) {
1818 Link<Node> link = const Link<Node>().prepend(arg);
1819 link = link.prepend(send.arguments.head);
1820 arguments = new NodeList(null, link);
1821 } else {
1822 arguments = new NodeList.singleton(arg);
1823 }
1824 Operator op = new Operator(token);
1825 pushNode(new SendSet(send.receiver, send.selector, op, arguments,
1826 send.isConditional));
1827 }
1828
1829 void reportNotAssignable(Node node) {
1830 // TODO(ahe): The parser should diagnose this problem, not this
1831 // listener.
1832 reportFatalError(node,
1833 'Not assignable.');
1834 }
1835
1836 void handleConditionalExpression(Token question, Token colon) {
1837 Node elseExpression = popNode();
1838 Node thenExpression = popNode();
1839 Node condition = popNode();
1840 pushNode(new Conditional(
1841 condition, thenExpression, elseExpression, question, colon));
1842 }
1843
1844 void endSend(Token token) {
1845 NodeList arguments = popNode();
1846 Node selector = popNode();
1847 // TODO(ahe): Handle receiver.
1848 pushNode(new Send(null, selector, arguments));
1849 }
1850
1851 void endFunctionBody(int count, Token beginToken, Token endToken) {
1852 if (count == 0 && beginToken == null) {
1853 pushNode(new EmptyStatement(endToken));
1854 } else {
1855 pushNode(new Block(makeNodeList(count, beginToken, endToken, null)));
1856 }
1857 }
1858
1859 void handleAsyncModifier(Token asyncToken, Token starToken) {
1860 if (asyncToken != null) {
1861 pushNode(new AsyncModifier(asyncToken, starToken));
1862 } else {
1863 pushNode(null);
1864 }
1865 }
1866
1867 void skippedFunctionBody(Token token) {
1868 pushNode(new Block(new NodeList.empty()));
1869 }
1870
1871 void handleNoFunctionBody(Token token) {
1872 pushNode(new EmptyStatement(token));
1873 }
1874
1875 void endFunction(Token getOrSet, Token endToken) {
1876 Statement body = popNode();
1877 AsyncModifier asyncModifier = popNode();
1878 NodeList initializers = popNode();
1879 NodeList formals = popNode();
1880 // The name can be an identifier or a send in case of named constructors.
1881 Expression name = popNode();
1882 TypeAnnotation type = popNode();
1883 Modifiers modifiers = popNode();
1884 pushNode(new FunctionExpression(name, formals, body, type,
1885 modifiers, initializers, getOrSet,
1886 asyncModifier));
1887 }
1888
1889 void endFunctionDeclaration(Token endToken) {
1890 pushNode(new FunctionDeclaration(popNode()));
1891 }
1892
1893 void endVariablesDeclaration(int count, Token endToken) {
1894 // TODO(ahe): Pick one name for this concept, either
1895 // VariablesDeclaration or VariableDefinitions.
1896 NodeList variables = makeNodeList(count, null, endToken, ",");
1897 TypeAnnotation type = popNode();
1898 Modifiers modifiers = popNode();
1899 pushNode(new VariableDefinitions(type, modifiers, variables));
1900 }
1901
1902 void endInitializer(Token assignmentOperator) {
1903 Expression initializer = popNode();
1904 NodeList arguments =
1905 initializer == null ? null : new NodeList.singleton(initializer);
1906 Expression name = popNode();
1907 Operator op = new Operator(assignmentOperator);
1908 pushNode(new SendSet(null, name, op, arguments));
1909 }
1910
1911 void endIfStatement(Token ifToken, Token elseToken) {
1912 Statement elsePart = (elseToken == null) ? null : popNode();
1913 Statement thenPart = popNode();
1914 ParenthesizedExpression condition = popNode();
1915 pushNode(new If(condition, thenPart, elsePart, ifToken, elseToken));
1916 }
1917
1918 void endForStatement(int updateExpressionCount,
1919 Token beginToken, Token endToken) {
1920 Statement body = popNode();
1921 NodeList updates = makeNodeList(updateExpressionCount, null, null, ',');
1922 Statement condition = popNode();
1923 Node initializer = popNode();
1924 pushNode(new For(initializer, condition, updates, body, beginToken));
1925 }
1926
1927 void handleNoExpression(Token token) {
1928 pushNode(null);
1929 }
1930
1931 void endDoWhileStatement(Token doKeyword, Token whileKeyword,
1932 Token endToken) {
1933 Expression condition = popNode();
1934 Statement body = popNode();
1935 pushNode(new DoWhile(body, condition, doKeyword, whileKeyword, endToken));
1936 }
1937
1938 void endWhileStatement(Token whileKeyword, Token endToken) {
1939 Statement body = popNode();
1940 Expression condition = popNode();
1941 pushNode(new While(condition, body, whileKeyword));
1942 }
1943
1944 void endBlock(int count, Token beginToken, Token endToken) {
1945 pushNode(new Block(makeNodeList(count, beginToken, endToken, null)));
1946 }
1947
1948 void endThrowExpression(Token throwToken, Token endToken) {
1949 Expression expression = popNode();
1950 pushNode(new Throw(expression, throwToken, endToken));
1951 }
1952
1953 void endAwaitExpression(Token awaitToken, Token endToken) {
1954 Expression expression = popNode();
1955 pushNode(new Await(awaitToken, expression));
1956 }
1957
1958 void endRethrowStatement(Token throwToken, Token endToken) {
1959 pushNode(new Rethrow(throwToken, endToken));
1960 if (identical(throwToken.stringValue, 'throw')) {
1961 listener.reportError(throwToken,
1962 MessageKind.UNSUPPORTED_THROW_WITHOUT_EXP);
1963 }
1964 }
1965
1966 void handleUnaryPrefixExpression(Token token) {
1967 pushNode(new Send.prefix(popNode(), new Operator(token)));
1968 }
1969
1970 void handleSuperExpression(Token token) {
1971 pushNode(new Identifier(token));
1972 }
1973
1974 void handleThisExpression(Token token) {
1975 pushNode(new Identifier(token));
1976 }
1977
1978 void handleUnaryAssignmentExpression(Token token, bool isPrefix) {
1979 Node node = popNode();
1980 Send send = node.asSend();
1981 if (send == null) {
1982 reportNotAssignable(node);
1983 }
1984 if (!(send.isPropertyAccess || send.isIndex)) {
1985 reportNotAssignable(node);
1986 }
1987 if (send.asSendSet() != null) internalError(node: send);
1988 Node argument = null;
1989 if (send.isIndex) argument = send.arguments.head;
1990 Operator op = new Operator(token);
1991
1992 if (isPrefix) {
1993 pushNode(new SendSet.prefix(send.receiver, send.selector, op, argument,
1994 send.isConditional));
1995 } else {
1996 pushNode(new SendSet.postfix(send.receiver, send.selector, op, argument,
1997 send.isConditional));
1998 }
1999 }
2000
2001 void handleUnaryPostfixAssignmentExpression(Token token) {
2002 handleUnaryAssignmentExpression(token, false);
2003 }
2004
2005 void handleUnaryPrefixAssignmentExpression(Token token) {
2006 handleUnaryAssignmentExpression(token, true);
2007 }
2008
2009 void endInitializers(int count, Token beginToken, Token endToken) {
2010 pushNode(makeNodeList(count, beginToken, null, ','));
2011 }
2012
2013 void handleNoInitializers() {
2014 pushNode(null);
2015 }
2016
2017 void endFields(int count, Token beginToken, Token endToken) {
2018 NodeList variables = makeNodeList(count, null, endToken, ",");
2019 TypeAnnotation type = popNode();
2020 Modifiers modifiers = popNode();
2021 pushNode(new VariableDefinitions(type, modifiers, variables));
2022 }
2023
2024 void endMethod(Token getOrSet, Token beginToken, Token endToken) {
2025 Statement body = popNode();
2026 AsyncModifier asyncModifier = popNode();
2027 NodeList initializers = popNode();
2028 NodeList formalParameters = popNode();
2029 Expression name = popNode();
2030 TypeAnnotation returnType = popNode();
2031 Modifiers modifiers = popNode();
2032 pushNode(new FunctionExpression(name, formalParameters, body, returnType,
2033 modifiers, initializers, getOrSet,
2034 asyncModifier));
2035 }
2036
2037 void handleLiteralMap(int count, Token beginToken, Token constKeyword,
2038 Token endToken) {
2039 NodeList entries = makeNodeList(count, beginToken, endToken, ',');
2040 NodeList typeArguments = popNode();
2041 pushNode(new LiteralMap(typeArguments, entries, constKeyword));
2042 }
2043
2044 void endLiteralMapEntry(Token colon, Token endToken) {
2045 Expression value = popNode();
2046 Expression key = popNode();
2047 pushNode(new LiteralMapEntry(key, colon, value));
2048 }
2049
2050 void handleLiteralList(int count, Token beginToken, Token constKeyword,
2051 Token endToken) {
2052 NodeList elements = makeNodeList(count, beginToken, endToken, ',');
2053 pushNode(new LiteralList(popNode(), elements, constKeyword));
2054 }
2055
2056 void handleIndexedExpression(Token openSquareBracket,
2057 Token closeSquareBracket) {
2058 NodeList arguments =
2059 makeNodeList(1, openSquareBracket, closeSquareBracket, null);
2060 Node receiver = popNode();
2061 Token token = new StringToken.fromString(INDEX_INFO, '[]',
2062 openSquareBracket.charOffset);
2063 Node selector = new Operator(token);
2064 pushNode(new Send(receiver, selector, arguments));
2065 }
2066
2067 void handleNewExpression(Token token) {
2068 NodeList arguments = popNode();
2069 Node name = popNode();
2070 pushNode(new NewExpression(token, new Send(null, name, arguments)));
2071 }
2072
2073 void handleConstExpression(Token token) {
2074 // [token] carries the 'const' information.
2075 handleNewExpression(token);
2076 }
2077
2078 void handleOperator(Token token) {
2079 pushNode(new Operator(token));
2080 }
2081
2082 void handleOperatorName(Token operatorKeyword, Token token) {
2083 Operator op = new Operator(token);
2084 pushNode(new Send(new Identifier(operatorKeyword), op, null));
2085 }
2086
2087 void handleNamedArgument(Token colon) {
2088 Expression expression = popNode();
2089 Identifier name = popNode();
2090 pushNode(new NamedArgument(name, colon, expression));
2091 }
2092
2093 void endOptionalFormalParameters(int count,
2094 Token beginToken, Token endToken) {
2095 pushNode(makeNodeList(count, beginToken, endToken, ','));
2096 }
2097
2098 void handleFunctionTypedFormalParameter(Token endToken) {
2099 NodeList formals = popNode();
2100 Identifier name = popNode();
2101 TypeAnnotation returnType = popNode();
2102 pushNode(null); // Signal "no type" to endFormalParameter.
2103 pushNode(new FunctionExpression(name, formals, null, returnType,
2104 Modifiers.EMPTY, null, null, null));
2105 }
2106
2107 void handleValuedFormalParameter(Token equals, Token token) {
2108 Expression defaultValue = popNode();
2109 Expression parameterName = popNode();
2110 pushNode(new SendSet(null, parameterName, new Operator(equals),
2111 new NodeList.singleton(defaultValue)));
2112 }
2113
2114 void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
2115 Block finallyBlock = null;
2116 if (finallyKeyword != null) {
2117 finallyBlock = popNode();
2118 }
2119 NodeList catchBlocks = makeNodeList(catchCount, null, null, null);
2120 Block tryBlock = popNode();
2121 pushNode(new TryStatement(tryBlock, catchBlocks, finallyBlock,
2122 tryKeyword, finallyKeyword));
2123 }
2124
2125 void handleCaseMatch(Token caseKeyword, Token colon) {
2126 pushNode(new CaseMatch(caseKeyword, popNode(), colon));
2127 }
2128
2129 void handleCatchBlock(Token onKeyword, Token catchKeyword) {
2130 Block block = popNode();
2131 NodeList formals = catchKeyword != null? popNode(): null;
2132 TypeAnnotation type = onKeyword != null ? popNode() : null;
2133 pushNode(new CatchBlock(type, formals, block, onKeyword, catchKeyword));
2134 }
2135
2136 void endSwitchStatement(Token switchKeyword, Token endToken) {
2137 NodeList cases = popNode();
2138 ParenthesizedExpression expression = popNode();
2139 pushNode(new SwitchStatement(expression, cases, switchKeyword));
2140 }
2141
2142 void endSwitchBlock(int caseCount, Token beginToken, Token endToken) {
2143 Link<Node> caseNodes = const Link<Node>();
2144 while (caseCount > 0) {
2145 SwitchCase switchCase = popNode();
2146 caseNodes = caseNodes.prepend(switchCase);
2147 caseCount--;
2148 }
2149 pushNode(new NodeList(beginToken, caseNodes, endToken, null));
2150 }
2151
2152 void handleSwitchCase(int labelCount, int caseCount,
2153 Token defaultKeyword, int statementCount,
2154 Token firstToken, Token endToken) {
2155 NodeList statements = makeNodeList(statementCount, null, null, null);
2156 NodeList labelsAndCases =
2157 makeNodeList(labelCount + caseCount, null, null, null);
2158 pushNode(new SwitchCase(labelsAndCases, defaultKeyword, statements,
2159 firstToken));
2160 }
2161
2162 void handleBreakStatement(bool hasTarget,
2163 Token breakKeyword, Token endToken) {
2164 Identifier target = null;
2165 if (hasTarget) {
2166 target = popNode();
2167 }
2168 pushNode(new BreakStatement(target, breakKeyword, endToken));
2169 }
2170
2171 void handleContinueStatement(bool hasTarget,
2172 Token continueKeyword, Token endToken) {
2173 Identifier target = null;
2174 if (hasTarget) {
2175 target = popNode();
2176 }
2177 pushNode(new ContinueStatement(target, continueKeyword, endToken));
2178 }
2179
2180 void handleEmptyStatement(Token token) {
2181 pushNode(new EmptyStatement(token));
2182 }
2183
2184 void endFactoryMethod(Token beginToken, Token endToken) {
2185 super.endFactoryMethod(beginToken, endToken);
2186 Statement body = popNode();
2187 AsyncModifier asyncModifier = popNode();
2188 NodeList formals = popNode();
2189 Node name = popNode();
2190
2191 // TODO(ahe): Move this parsing to the parser.
2192 int modifierCount = 0;
2193 Token modifier = beginToken;
2194 if (modifier.stringValue == "external") {
2195 handleModifier(modifier);
2196 modifierCount++;
2197 modifier = modifier.next;
2198 }
2199 if (modifier.stringValue == "const") {
2200 handleModifier(modifier);
2201 modifierCount++;
2202 modifier = modifier.next;
2203 }
2204 assert(modifier.stringValue == "factory");
2205 handleModifier(modifier);
2206 modifierCount++;
2207 handleModifiers(modifierCount);
2208 Modifiers modifiers = popNode();
2209
2210 pushNode(new FunctionExpression(name, formals, body, null,
2211 modifiers, null, null, asyncModifier));
2212 }
2213
2214 void endForIn(Token awaitToken, Token forToken,
2215 Token inKeyword, Token endToken) {
2216 Statement body = popNode();
2217 Expression expression = popNode();
2218 Node declaredIdentifier = popNode();
2219 if (awaitToken == null) {
2220 pushNode(new SyncForIn(declaredIdentifier, expression, body,
2221 forToken, inKeyword));
2222 } else {
2223 pushNode(new AsyncForIn(declaredIdentifier, expression, body, awaitToken,
2224 forToken, inKeyword));
2225 }
2226 }
2227
2228 void endMetadataStar(int count, bool forParameter) {
2229 // TODO(johnniwinther): Handle metadata for all node kinds.
2230 if (forParameter) {
2231 if (0 == count) {
2232 pushNode(null);
2233 } else {
2234 pushNode(makeNodeList(count, null, null, ' '));
2235 }
2236 }
2237 }
2238
2239 void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
2240 NodeList arguments = popNode();
2241 if (arguments == null) {
2242 // This is a constant expression.
2243 Identifier name;
2244 if (periodBeforeName != null) {
2245 name = popNode();
2246 }
2247 NodeList typeArguments = popNode();
2248 Node receiver = popNode();
2249 if (typeArguments != null) {
2250 receiver = new TypeAnnotation(receiver, typeArguments);
2251 recoverableError(typeArguments,
2252 'Type arguments are not allowed here.');
2253 } else {
2254 Identifier identifier = receiver.asIdentifier();
2255 Send send = receiver.asSend();
2256 if (identifier != null) {
2257 receiver = new Send(null, identifier);
2258 } else if (send == null) {
2259 internalError(node: receiver);
2260 }
2261 }
2262 Send send = receiver;
2263 if (name != null) {
2264 send = new Send(receiver, name);
2265 }
2266 pushNode(new Metadata(beginToken, send));
2267 } else {
2268 // This is a const constructor call.
2269 endConstructorReference(beginToken, periodBeforeName, endToken);
2270 Node constructor = popNode();
2271 pushNode(new Metadata(beginToken,
2272 new NewExpression(null,
2273 new Send(null, constructor, arguments))));
2274 }
2275 }
2276
2277 void handleAssertStatement(Token assertKeyword, Token semicolonToken) {
2278 NodeList arguments = popNode();
2279 Node selector = new Identifier(assertKeyword);
2280 Node send = new Send(null, selector, arguments);
2281 pushNode(new ExpressionStatement(send, semicolonToken));
2282 }
2283
2284 void endUnnamedFunction(Token token) {
2285 Statement body = popNode();
2286 AsyncModifier asyncModifier = popNode();
2287 NodeList formals = popNode();
2288 pushNode(new FunctionExpression(null, formals, body, null,
2289 Modifiers.EMPTY, null, null,
2290 asyncModifier));
2291 }
2292
2293 void handleIsOperator(Token operathor, Token not, Token endToken) {
2294 TypeAnnotation type = popNode();
2295 Expression expression = popNode();
2296 Node argument;
2297 if (not != null) {
2298 argument = new Send.prefix(type, new Operator(not));
2299 } else {
2300 argument = type;
2301 }
2302
2303 NodeList arguments = new NodeList.singleton(argument);
2304 pushNode(new Send(expression, new Operator(operathor), arguments));
2305 }
2306
2307 void handleLabel(Token colon) {
2308 Identifier name = popNode();
2309 pushNode(new Label(name, colon));
2310 }
2311
2312 void endLabeledStatement(int labelCount) {
2313 Statement statement = popNode();
2314 NodeList labels = makeNodeList(labelCount, null, null, null);
2315 pushNode(new LabeledStatement(labels, statement));
2316 }
2317
2318 void log(message) {
2319 listener.log(message);
2320 }
2321
2322 void internalError({Token token, Node node}) {
2323 // TODO(ahe): This should call listener.internalError.
2324 Spannable spannable = (token == null) ? node : token;
2325 throw new SpannableAssertionFailure(spannable, 'Internal error in parser.');
2326 }
2327 }
2328 64
2329 abstract class PartialElement implements DeclarationSite { 65 abstract class PartialElement implements DeclarationSite {
2330 Token beginToken; 66 Token beginToken;
2331 Token endToken; 67 Token endToken;
2332 68
2333 bool hasParseError = false; 69 bool hasParseError = false;
2334 70
2335 bool get isErroneous => hasParseError; 71 bool get isErroneous => hasParseError;
2336 72
2337 DeclarationSite get declarationSite => this; 73 DeclarationSite get declarationSite => this;
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
2608 bool hasParseError = false; 344 bool hasParseError = false;
2609 345
2610 PartialMetadataAnnotation(this.beginToken, this.tokenAfterEndToken); 346 PartialMetadataAnnotation(this.beginToken, this.tokenAfterEndToken);
2611 347
2612 bool get isErroneous => hasParseError; 348 bool get isErroneous => hasParseError;
2613 349
2614 DeclarationSite get declarationSite => this; 350 DeclarationSite get declarationSite => this;
2615 351
2616 Token get endToken { 352 Token get endToken {
2617 Token token = beginToken; 353 Token token = beginToken;
2618 while (token.kind != EOF_TOKEN) { 354 while (token.kind != Tokens.EOF_TOKEN) {
2619 if (identical(token.next, tokenAfterEndToken)) break; 355 if (identical(token.next, tokenAfterEndToken)) break;
2620 token = token.next; 356 token = token.next;
2621 } 357 }
2622 assert(token != null); 358 assert(token != null);
2623 return token; 359 return token;
2624 } 360 }
2625 361
2626 void set endToken(_) { 362 void set endToken(_) {
2627 throw new UnsupportedError("endToken="); 363 throw new UnsupportedError("endToken=");
2628 } 364 }
(...skipping 14 matching lines...) Expand all
2643 } 379 }
2644 380
2645 bool get hasNode => cachedNode != null; 381 bool get hasNode => cachedNode != null;
2646 382
2647 Node get node { 383 Node get node {
2648 assert(invariant(this, hasNode)); 384 assert(invariant(this, hasNode));
2649 return cachedNode; 385 return cachedNode;
2650 } 386 }
2651 } 387 }
2652 388
389 class PartialClassElement extends ClassElementX with PartialElement {
Johnni Winther 2015/09/02 13:14:41 Moved from class_element_parser.dart
390 ClassNode cachedNode;
391
392 PartialClassElement(String name,
393 Token beginToken,
394 Token endToken,
395 Element enclosing,
396 int id)
397 : super(name, enclosing, id, STATE_NOT_STARTED) {
398 this.beginToken = beginToken;
399 this.endToken = endToken;
400 }
401
402 void set supertypeLoadState(int state) {
403 assert(state == STATE_NOT_STARTED || state == supertypeLoadState + 1);
404 assert(state <= STATE_DONE);
405 super.supertypeLoadState = state;
406 }
407
408 void set resolutionState(int state) {
409 assert(state == STATE_NOT_STARTED || state == resolutionState + 1);
410 assert(state <= STATE_DONE);
411 super.resolutionState = state;
412 }
413
414 bool get hasNode => cachedNode != null;
415
416 ClassNode get node {
417 assert(invariant(this, cachedNode != null,
418 message: "Node has not been computed for $this."));
419 return cachedNode;
420 }
421
422 ClassNode parseNode(Compiler compiler) {
423 if (cachedNode != null) return cachedNode;
424 compiler.withCurrentElement(this, () {
425 compiler.parser.measure(() {
426 MemberListener listener = new MemberListener(compiler, this);
427 Parser parser = new ClassElementParser(listener);
428 try {
429 Token token = parser.parseTopLevelDeclaration(beginToken);
430 assert(identical(token, endToken.next));
431 cachedNode = listener.popNode();
432 assert(
433 invariant(
434 beginToken, listener.nodes.isEmpty,
435 message: "Non-empty listener stack: ${listener.nodes}"));
436 } on ParserError {
437 // TODO(ahe): Often, a ParserError is thrown while parsing the class
438 // body. This means that the stack actually contains most of the
439 // information synthesized below. Consider rewriting the parser so
440 // endClassDeclaration is called before parsing the class body.
441 Identifier name = new Identifier(findMyName(beginToken));
442 NodeList typeParameters = null;
443 Node supertype = null;
444 NodeList interfaces = listener.makeNodeList(0, null, null, ",");
445 Token extendsKeyword = null;
446 NodeList body = listener.makeNodeList(0, beginToken, endToken, null);
447 cachedNode = new ClassNode(
448 Modifiers.EMPTY, name, typeParameters, supertype, interfaces,
449 beginToken, extendsKeyword, body, endToken);
450 hasParseError = true;
451 }
452 });
453 compiler.patchParser.measure(() {
454 if (isPatched) {
455 // TODO(lrn): Perhaps extract functionality so it doesn't
456 // need compiler.
457 compiler.patchParser.parsePatchClassNode(patch);
458 }
459 });
460 });
461 return cachedNode;
462 }
463
464 Token get position => beginToken;
465
466 // TODO(johnniwinther): Ensure that modifiers are always available.
467 Modifiers get modifiers =>
468 cachedNode != null ? cachedNode.modifiers : Modifiers.EMPTY;
469
470 accept(ElementVisitor visitor, arg) {
471 return visitor.visitClassElement(this, arg);
472 }
473
474 PartialClassElement copyWithEnclosing(CompilationUnitElement enclosing) {
475 return new PartialClassElement(name, beginToken, endToken, enclosing, id);
476 }
477 }
478
2653 Node parse( 479 Node parse(
2654 DiagnosticListener diagnosticListener, 480 DiagnosticListener diagnosticListener,
2655 ElementX element, 481 ElementX element,
2656 PartialElement partial, 482 PartialElement partial,
2657 doParse(Parser parser)) { 483 doParse(Parser parser)) {
2658 CompilationUnitElement unit = element.compilationUnit; 484 CompilationUnitElement unit = element.compilationUnit;
2659 NodeListener listener = new NodeListener(diagnosticListener, unit); 485 NodeListener listener = new NodeListener(diagnosticListener, unit);
2660 listener.memberErrors = listener.memberErrors.prepend(false); 486 listener.memberErrors = listener.memberErrors.prepend(false);
2661 try { 487 try {
2662 if (partial.hasParseError) { 488 if (partial.hasParseError) {
2663 listener.suppressParseErrors = true; 489 listener.suppressParseErrors = true;
2664 } 490 }
2665 doParse(new Parser(listener)); 491 doParse(new Parser(listener));
2666 } on ParserError catch (e) { 492 } on ParserError catch (e) {
2667 partial.hasParseError = true; 493 partial.hasParseError = true;
2668 return new ErrorNode(element.position, e.reason); 494 return new ErrorNode(element.position, e.reason);
2669 } 495 }
2670 Node node = listener.popNode(); 496 Node node = listener.popNode();
2671 assert(listener.nodes.isEmpty); 497 assert(listener.nodes.isEmpty);
2672 return node; 498 return node;
2673 } 499 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698