OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |