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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/scanner/listener.dart

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

Powered by Google App Engine
This is Rietveld 408576698