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

Side by Side Diff: observatory_pub_packages/analyzer/src/generated/parser.dart

Issue 816693004: Add observatory_pub_packages snapshot to third_party (Closed) Base URL: http://dart.googlecode.com/svn/third_party/
Patch Set: Created 6 years 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) 2014, 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 // This code was auto-generated, is not intended to be edited, and is subject to
6 // significant change. Please see the README file for more information.
7
8 library engine.parser;
9
10 import 'dart:collection';
11 import 'java_core.dart';
12 import 'java_engine.dart';
13 import 'instrumentation.dart';
14 import 'error.dart';
15 import 'source.dart';
16 import 'scanner.dart';
17 import 'ast.dart';
18 import 'utilities_dart.dart';
19 import 'engine.dart' show AnalysisEngine, AnalysisOptionsImpl;
20 import 'utilities_collection.dart' show TokenMap;
21
22 /**
23 * Instances of the class `CommentAndMetadata` implement a simple data-holder fo r a method
24 * that needs to return multiple values.
25 */
26 class CommentAndMetadata {
27 /**
28 * The documentation comment that was parsed, or `null` if none was given.
29 */
30 final Comment comment;
31
32 /**
33 * The metadata that was parsed.
34 */
35 final List<Annotation> metadata;
36
37 /**
38 * Initialize a newly created holder with the given data.
39 *
40 * @param comment the documentation comment that was parsed
41 * @param metadata the metadata that was parsed
42 */
43 CommentAndMetadata(this.comment, this.metadata);
44 }
45
46 /**
47 * Instances of the class `FinalConstVarOrType` implement a simple data-holder f or a method
48 * that needs to return multiple values.
49 */
50 class FinalConstVarOrType {
51 /**
52 * The 'final', 'const' or 'var' keyword, or `null` if none was given.
53 */
54 final Token keyword;
55
56 /**
57 * The type, of `null` if no type was specified.
58 */
59 final TypeName type;
60
61 /**
62 * Initialize a newly created holder with the given data.
63 *
64 * @param keyword the 'final', 'const' or 'var' keyword
65 * @param type the type
66 */
67 FinalConstVarOrType(this.keyword, this.type);
68 }
69
70 /**
71 * Instances of the class `IncrementalParseDispatcher` implement a dispatcher th at will invoke
72 * the right parse method when re-parsing a specified child of the visited node. All of the methods
73 * in this class assume that the parser is positioned to parse the replacement f or the node. All of
74 * the methods will throw an [IncrementalParseException] if the node could not b e parsed for
75 * some reason.
76 */
77 class IncrementalParseDispatcher implements AstVisitor<AstNode> {
78 /**
79 * The parser used to parse the replacement for the node.
80 */
81 final Parser _parser;
82
83 /**
84 * The node that is to be replaced.
85 */
86 final AstNode _oldNode;
87
88 /**
89 * Initialize a newly created dispatcher to parse a single node that will repl ace the given node.
90 *
91 * @param parser the parser used to parse the replacement for the node
92 * @param oldNode the node that is to be replaced
93 */
94 IncrementalParseDispatcher(this._parser, this._oldNode);
95
96 @override
97 AstNode visitAdjacentStrings(AdjacentStrings node) {
98 if (node.strings.contains(_oldNode)) {
99 return _parser.parseStringLiteral();
100 }
101 return _notAChild(node);
102 }
103
104 @override
105 AstNode visitAnnotation(Annotation node) {
106 if (identical(_oldNode, node.name)) {
107 throw new InsufficientContextException();
108 } else if (identical(_oldNode, node.constructorName)) {
109 throw new InsufficientContextException();
110 } else if (identical(_oldNode, node.arguments)) {
111 return _parser.parseArgumentList();
112 }
113 return _notAChild(node);
114 }
115
116 @override
117 AstNode visitArgumentList(ArgumentList node) {
118 if (node.arguments.contains(_oldNode)) {
119 return _parser.parseArgument();
120 }
121 return _notAChild(node);
122 }
123
124 @override
125 AstNode visitAsExpression(AsExpression node) {
126 if (identical(_oldNode, node.expression)) {
127 return _parser.parseBitwiseOrExpression();
128 } else if (identical(_oldNode, node.type)) {
129 return _parser.parseTypeName();
130 }
131 return _notAChild(node);
132 }
133
134 @override
135 AstNode visitAssertStatement(AssertStatement node) {
136 if (identical(_oldNode, node.condition)) {
137 return _parser.parseExpression2();
138 }
139 return _notAChild(node);
140 }
141
142 @override
143 AstNode visitAssignmentExpression(AssignmentExpression node) {
144 if (identical(_oldNode, node.leftHandSide)) {
145 // TODO(brianwilkerson) If the assignment is part of a cascade section, th en we don't have a
146 // single parse method that will work. Otherwise, we can parse a condition al expression, but
147 // need to ensure that the resulting expression is assignable.
148 // return parser.parseConditionalExpression();
149 throw new InsufficientContextException();
150 } else if (identical(_oldNode, node.rightHandSide)) {
151 if (_isCascadeAllowedInAssignment(node)) {
152 return _parser.parseExpression2();
153 }
154 return _parser.parseExpressionWithoutCascade();
155 }
156 return _notAChild(node);
157 }
158
159 @override
160 AstNode visitAwaitExpression(AwaitExpression node) {
161 if (identical(_oldNode, node.expression)) {
162 // TODO(brianwilkerson) Depending on precedence, this might not be suffici ent.
163 return _parser.parseExpression2();
164 }
165 return _notAChild(node);
166 }
167
168 @override
169 AstNode visitBinaryExpression(BinaryExpression node) {
170 if (identical(_oldNode, node.leftOperand)) {
171 throw new InsufficientContextException();
172 } else if (identical(_oldNode, node.rightOperand)) {
173 throw new InsufficientContextException();
174 }
175 return _notAChild(node);
176 }
177
178 @override
179 AstNode visitBlock(Block node) {
180 if (node.statements.contains(_oldNode)) {
181 return _parser.parseStatement2();
182 }
183 return _notAChild(node);
184 }
185
186 @override
187 AstNode visitBlockFunctionBody(BlockFunctionBody node) {
188 if (identical(_oldNode, node.block)) {
189 return _parser.parseBlock();
190 }
191 return _notAChild(node);
192 }
193
194 @override
195 AstNode visitBooleanLiteral(BooleanLiteral node) => _notAChild(node);
196
197 @override
198 AstNode visitBreakStatement(BreakStatement node) {
199 if (identical(_oldNode, node.label)) {
200 return _parser.parseSimpleIdentifier();
201 }
202 return _notAChild(node);
203 }
204
205 @override
206 AstNode visitCascadeExpression(CascadeExpression node) {
207 if (identical(_oldNode, node.target)) {
208 return _parser.parseConditionalExpression();
209 } else if (node.cascadeSections.contains(_oldNode)) {
210 throw new InsufficientContextException();
211 }
212 return _notAChild(node);
213 }
214
215 @override
216 AstNode visitCatchClause(CatchClause node) {
217 if (identical(_oldNode, node.exceptionType)) {
218 return _parser.parseTypeName();
219 } else if (identical(_oldNode, node.exceptionParameter)) {
220 return _parser.parseSimpleIdentifier();
221 } else if (identical(_oldNode, node.stackTraceParameter)) {
222 return _parser.parseSimpleIdentifier();
223 } else if (identical(_oldNode, node.body)) {
224 return _parser.parseBlock();
225 }
226 return _notAChild(node);
227 }
228
229 @override
230 AstNode visitClassDeclaration(ClassDeclaration node) {
231 if (identical(_oldNode, node.documentationComment)) {
232 throw new InsufficientContextException();
233 } else if (node.metadata.contains(_oldNode)) {
234 return _parser.parseAnnotation();
235 } else if (identical(_oldNode, node.name)) {
236 return _parser.parseSimpleIdentifier();
237 } else if (identical(_oldNode, node.typeParameters)) {
238 return _parser.parseTypeParameterList();
239 } else if (identical(_oldNode, node.extendsClause)) {
240 return _parser.parseExtendsClause();
241 } else if (identical(_oldNode, node.withClause)) {
242 return _parser.parseWithClause();
243 } else if (identical(_oldNode, node.implementsClause)) {
244 return _parser.parseImplementsClause();
245 } else if (node.members.contains(_oldNode)) {
246 ClassMember member = _parser.parseClassMember(node.name.name);
247 if (member == null) {
248 throw new InsufficientContextException();
249 }
250 return member;
251 }
252 return _notAChild(node);
253 }
254
255 @override
256 AstNode visitClassTypeAlias(ClassTypeAlias node) {
257 if (identical(_oldNode, node.documentationComment)) {
258 throw new InsufficientContextException();
259 } else if (node.metadata.contains(_oldNode)) {
260 return _parser.parseAnnotation();
261 } else if (identical(_oldNode, node.name)) {
262 return _parser.parseSimpleIdentifier();
263 } else if (identical(_oldNode, node.typeParameters)) {
264 return _parser.parseTypeParameterList();
265 } else if (identical(_oldNode, node.superclass)) {
266 return _parser.parseTypeName();
267 } else if (identical(_oldNode, node.withClause)) {
268 return _parser.parseWithClause();
269 } else if (identical(_oldNode, node.implementsClause)) {
270 return _parser.parseImplementsClause();
271 }
272 return _notAChild(node);
273 }
274
275 @override
276 AstNode visitComment(Comment node) {
277 throw new InsufficientContextException();
278 }
279
280 @override
281 AstNode visitCommentReference(CommentReference node) {
282 if (identical(_oldNode, node.identifier)) {
283 return _parser.parsePrefixedIdentifier();
284 }
285 return _notAChild(node);
286 }
287
288 @override
289 AstNode visitCompilationUnit(CompilationUnit node) {
290 throw new InsufficientContextException();
291 }
292
293 @override
294 AstNode visitConditionalExpression(ConditionalExpression node) {
295 if (identical(_oldNode, node.condition)) {
296 return _parser.parseLogicalOrExpression();
297 } else if (identical(_oldNode, node.thenExpression)) {
298 return _parser.parseExpressionWithoutCascade();
299 } else if (identical(_oldNode, node.elseExpression)) {
300 return _parser.parseExpressionWithoutCascade();
301 }
302 return _notAChild(node);
303 }
304
305 @override
306 AstNode visitConstructorDeclaration(ConstructorDeclaration node) {
307 if (identical(_oldNode, node.documentationComment)) {
308 throw new InsufficientContextException();
309 } else if (node.metadata.contains(_oldNode)) {
310 return _parser.parseAnnotation();
311 } else if (identical(_oldNode, node.returnType)) {
312 throw new InsufficientContextException();
313 } else if (identical(_oldNode, node.name)) {
314 throw new InsufficientContextException();
315 } else if (identical(_oldNode, node.parameters)) {
316 return _parser.parseFormalParameterList();
317 } else if (identical(_oldNode, node.redirectedConstructor)) {
318 throw new InsufficientContextException();
319 } else if (node.initializers.contains(_oldNode)) {
320 throw new InsufficientContextException();
321 } else if (identical(_oldNode, node.body)) {
322 throw new InsufficientContextException();
323 }
324 return _notAChild(node);
325 }
326
327 @override
328 AstNode visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
329 if (identical(_oldNode, node.fieldName)) {
330 return _parser.parseSimpleIdentifier();
331 } else if (identical(_oldNode, node.expression)) {
332 throw new InsufficientContextException();
333 }
334 return _notAChild(node);
335 }
336
337 @override
338 AstNode visitConstructorName(ConstructorName node) {
339 if (identical(_oldNode, node.type)) {
340 return _parser.parseTypeName();
341 } else if (identical(_oldNode, node.name)) {
342 return _parser.parseSimpleIdentifier();
343 }
344 return _notAChild(node);
345 }
346
347 @override
348 AstNode visitContinueStatement(ContinueStatement node) {
349 if (identical(_oldNode, node.label)) {
350 return _parser.parseSimpleIdentifier();
351 }
352 return _notAChild(node);
353 }
354
355 @override
356 AstNode visitDeclaredIdentifier(DeclaredIdentifier node) {
357 if (identical(_oldNode, node.documentationComment)) {
358 throw new InsufficientContextException();
359 } else if (node.metadata.contains(_oldNode)) {
360 return _parser.parseAnnotation();
361 } else if (identical(_oldNode, node.type)) {
362 throw new InsufficientContextException();
363 } else if (identical(_oldNode, node.identifier)) {
364 return _parser.parseSimpleIdentifier();
365 }
366 return _notAChild(node);
367 }
368
369 @override
370 AstNode visitDefaultFormalParameter(DefaultFormalParameter node) {
371 if (identical(_oldNode, node.parameter)) {
372 return _parser.parseNormalFormalParameter();
373 } else if (identical(_oldNode, node.defaultValue)) {
374 return _parser.parseExpression2();
375 }
376 return _notAChild(node);
377 }
378
379 @override
380 AstNode visitDoStatement(DoStatement node) {
381 if (identical(_oldNode, node.body)) {
382 return _parser.parseStatement2();
383 } else if (identical(_oldNode, node.condition)) {
384 return _parser.parseExpression2();
385 }
386 return _notAChild(node);
387 }
388
389 @override
390 AstNode visitDoubleLiteral(DoubleLiteral node) => _notAChild(node);
391
392 @override
393 AstNode visitEmptyFunctionBody(EmptyFunctionBody node) => _notAChild(node);
394
395 @override
396 AstNode visitEmptyStatement(EmptyStatement node) => _notAChild(node);
397
398 @override
399 AstNode visitEnumConstantDeclaration(EnumConstantDeclaration node) {
400 if (identical(_oldNode, node.documentationComment)) {
401 throw new InsufficientContextException();
402 } else if (node.metadata.contains(_oldNode)) {
403 return _parser.parseAnnotation();
404 } else if (identical(_oldNode, node.name)) {
405 return _parser.parseSimpleIdentifier();
406 }
407 return _notAChild(node);
408 }
409
410 @override
411 AstNode visitEnumDeclaration(EnumDeclaration node) {
412 if (identical(_oldNode, node.documentationComment)) {
413 throw new InsufficientContextException();
414 } else if (node.metadata.contains(_oldNode)) {
415 return _parser.parseAnnotation();
416 } else if (identical(_oldNode, node.name)) {
417 return _parser.parseSimpleIdentifier();
418 } else if (node.constants.contains(_oldNode)) {
419 throw new InsufficientContextException();
420 }
421 return _notAChild(node);
422 }
423
424 @override
425 AstNode visitExportDirective(ExportDirective node) {
426 if (identical(_oldNode, node.documentationComment)) {
427 throw new InsufficientContextException();
428 } else if (node.metadata.contains(_oldNode)) {
429 return _parser.parseAnnotation();
430 } else if (identical(_oldNode, node.uri)) {
431 return _parser.parseStringLiteral();
432 } else if (node.combinators.contains(_oldNode)) {
433 throw new IncrementalParseException();
434 }
435 return _notAChild(node);
436 }
437
438 @override
439 AstNode visitExpressionFunctionBody(ExpressionFunctionBody node) {
440 if (identical(_oldNode, node.expression)) {
441 return _parser.parseExpression2();
442 }
443 return _notAChild(node);
444 }
445
446 @override
447 AstNode visitExpressionStatement(ExpressionStatement node) {
448 if (identical(_oldNode, node.expression)) {
449 return _parser.parseExpression2();
450 }
451 return _notAChild(node);
452 }
453
454 @override
455 AstNode visitExtendsClause(ExtendsClause node) {
456 if (identical(_oldNode, node.superclass)) {
457 return _parser.parseTypeName();
458 }
459 return _notAChild(node);
460 }
461
462 @override
463 AstNode visitFieldDeclaration(FieldDeclaration node) {
464 if (identical(_oldNode, node.documentationComment)) {
465 throw new InsufficientContextException();
466 } else if (node.metadata.contains(_oldNode)) {
467 return _parser.parseAnnotation();
468 } else if (identical(_oldNode, node.fields)) {
469 throw new InsufficientContextException();
470 }
471 return _notAChild(node);
472 }
473
474 @override
475 AstNode visitFieldFormalParameter(FieldFormalParameter node) {
476 if (identical(_oldNode, node.documentationComment)) {
477 throw new InsufficientContextException();
478 } else if (node.metadata.contains(_oldNode)) {
479 return _parser.parseAnnotation();
480 } else if (identical(_oldNode, node.type)) {
481 return _parser.parseTypeName();
482 } else if (identical(_oldNode, node.identifier)) {
483 return _parser.parseSimpleIdentifier();
484 } else if (identical(_oldNode, node.parameters)) {
485 return _parser.parseFormalParameterList();
486 }
487 return _notAChild(node);
488 }
489
490 @override
491 AstNode visitForEachStatement(ForEachStatement node) {
492 if (identical(_oldNode, node.loopVariable)) {
493 throw new InsufficientContextException();
494 } else if (identical(_oldNode, node.identifier)) {
495 return _parser.parseSimpleIdentifier();
496 } else if (identical(_oldNode, node.body)) {
497 return _parser.parseStatement2();
498 }
499 return _notAChild(node);
500 }
501
502 @override
503 AstNode visitFormalParameterList(FormalParameterList node) {
504 // We don't know which kind of parameter to parse.
505 throw new InsufficientContextException();
506 }
507
508 @override
509 AstNode visitForStatement(ForStatement node) {
510 if (identical(_oldNode, node.variables)) {
511 throw new InsufficientContextException();
512 } else if (identical(_oldNode, node.initialization)) {
513 throw new InsufficientContextException();
514 } else if (identical(_oldNode, node.condition)) {
515 return _parser.parseExpression2();
516 } else if (node.updaters.contains(_oldNode)) {
517 return _parser.parseExpression2();
518 } else if (identical(_oldNode, node.body)) {
519 return _parser.parseStatement2();
520 }
521 return _notAChild(node);
522 }
523
524 @override
525 AstNode visitFunctionDeclaration(FunctionDeclaration node) {
526 if (identical(_oldNode, node.documentationComment)) {
527 throw new InsufficientContextException();
528 } else if (node.metadata.contains(_oldNode)) {
529 return _parser.parseAnnotation();
530 } else if (identical(_oldNode, node.returnType)) {
531 return _parser.parseReturnType();
532 } else if (identical(_oldNode, node.name)) {
533 return _parser.parseSimpleIdentifier();
534 } else if (identical(_oldNode, node.functionExpression)) {
535 throw new InsufficientContextException();
536 }
537 return _notAChild(node);
538 }
539
540 @override
541 AstNode visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
542 if (identical(_oldNode, node.functionDeclaration)) {
543 throw new InsufficientContextException();
544 }
545 return _notAChild(node);
546 }
547
548 @override
549 AstNode visitFunctionExpression(FunctionExpression node) {
550 if (identical(_oldNode, node.parameters)) {
551 return _parser.parseFormalParameterList();
552 } else if (identical(_oldNode, node.body)) {
553 throw new InsufficientContextException();
554 }
555 return _notAChild(node);
556 }
557
558 @override
559 AstNode visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
560 if (identical(_oldNode, node.function)) {
561 throw new InsufficientContextException();
562 } else if (identical(_oldNode, node.argumentList)) {
563 return _parser.parseArgumentList();
564 }
565 return _notAChild(node);
566 }
567
568 @override
569 AstNode visitFunctionTypeAlias(FunctionTypeAlias node) {
570 if (identical(_oldNode, node.documentationComment)) {
571 throw new InsufficientContextException();
572 } else if (node.metadata.contains(_oldNode)) {
573 return _parser.parseAnnotation();
574 } else if (identical(_oldNode, node.returnType)) {
575 return _parser.parseReturnType();
576 } else if (identical(_oldNode, node.name)) {
577 return _parser.parseSimpleIdentifier();
578 } else if (identical(_oldNode, node.typeParameters)) {
579 return _parser.parseTypeParameterList();
580 } else if (identical(_oldNode, node.parameters)) {
581 return _parser.parseFormalParameterList();
582 }
583 return _notAChild(node);
584 }
585
586 @override
587 AstNode visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
588 if (identical(_oldNode, node.documentationComment)) {
589 throw new InsufficientContextException();
590 } else if (node.metadata.contains(_oldNode)) {
591 return _parser.parseAnnotation();
592 } else if (identical(_oldNode, node.returnType)) {
593 return _parser.parseReturnType();
594 } else if (identical(_oldNode, node.identifier)) {
595 return _parser.parseSimpleIdentifier();
596 } else if (identical(_oldNode, node.parameters)) {
597 return _parser.parseFormalParameterList();
598 }
599 return _notAChild(node);
600 }
601
602 @override
603 AstNode visitHideCombinator(HideCombinator node) {
604 if (node.hiddenNames.contains(_oldNode)) {
605 return _parser.parseSimpleIdentifier();
606 }
607 return _notAChild(node);
608 }
609
610 @override
611 AstNode visitIfStatement(IfStatement node) {
612 if (identical(_oldNode, node.condition)) {
613 return _parser.parseExpression2();
614 } else if (identical(_oldNode, node.thenStatement)) {
615 return _parser.parseStatement2();
616 } else if (identical(_oldNode, node.elseStatement)) {
617 return _parser.parseStatement2();
618 }
619 return _notAChild(node);
620 }
621
622 @override
623 AstNode visitImplementsClause(ImplementsClause node) {
624 if (node.interfaces.contains(node)) {
625 return _parser.parseTypeName();
626 }
627 return _notAChild(node);
628 }
629
630 @override
631 AstNode visitImportDirective(ImportDirective node) {
632 if (identical(_oldNode, node.documentationComment)) {
633 throw new InsufficientContextException();
634 } else if (node.metadata.contains(_oldNode)) {
635 return _parser.parseAnnotation();
636 } else if (identical(_oldNode, node.uri)) {
637 return _parser.parseStringLiteral();
638 } else if (identical(_oldNode, node.prefix)) {
639 return _parser.parseSimpleIdentifier();
640 } else if (node.combinators.contains(_oldNode)) {
641 throw new IncrementalParseException();
642 }
643 return _notAChild(node);
644 }
645
646 @override
647 AstNode visitIndexExpression(IndexExpression node) {
648 if (identical(_oldNode, node.target)) {
649 throw new InsufficientContextException();
650 } else if (identical(_oldNode, node.index)) {
651 return _parser.parseExpression2();
652 }
653 return _notAChild(node);
654 }
655
656 @override
657 AstNode visitInstanceCreationExpression(InstanceCreationExpression node) {
658 if (identical(_oldNode, node.constructorName)) {
659 return _parser.parseConstructorName();
660 } else if (identical(_oldNode, node.argumentList)) {
661 return _parser.parseArgumentList();
662 }
663 return _notAChild(node);
664 }
665
666 @override
667 AstNode visitIntegerLiteral(IntegerLiteral node) => _notAChild(node);
668
669 @override
670 AstNode visitInterpolationExpression(InterpolationExpression node) {
671 if (identical(_oldNode, node.expression)) {
672 if (node.leftBracket == null) {
673 throw new InsufficientContextException();
674 }
675 return _parser.parseExpression2();
676 }
677 return _notAChild(node);
678 }
679
680 @override
681 AstNode visitInterpolationString(InterpolationString node) {
682 throw new InsufficientContextException();
683 }
684
685 @override
686 AstNode visitIsExpression(IsExpression node) {
687 if (identical(_oldNode, node.expression)) {
688 return _parser.parseBitwiseOrExpression();
689 } else if (identical(_oldNode, node.type)) {
690 return _parser.parseTypeName();
691 }
692 return _notAChild(node);
693 }
694
695 @override
696 AstNode visitLabel(Label node) {
697 if (identical(_oldNode, node.label)) {
698 return _parser.parseSimpleIdentifier();
699 }
700 return _notAChild(node);
701 }
702
703 @override
704 AstNode visitLabeledStatement(LabeledStatement node) {
705 if (node.labels.contains(_oldNode)) {
706 return _parser.parseLabel();
707 } else if (identical(_oldNode, node.statement)) {
708 return _parser.parseStatement2();
709 }
710 return _notAChild(node);
711 }
712
713 @override
714 AstNode visitLibraryDirective(LibraryDirective node) {
715 if (identical(_oldNode, node.documentationComment)) {
716 throw new InsufficientContextException();
717 } else if (node.metadata.contains(_oldNode)) {
718 return _parser.parseAnnotation();
719 } else if (identical(_oldNode, node.name)) {
720 return _parser.parseLibraryIdentifier();
721 }
722 return _notAChild(node);
723 }
724
725 @override
726 AstNode visitLibraryIdentifier(LibraryIdentifier node) {
727 if (node.components.contains(_oldNode)) {
728 return _parser.parseSimpleIdentifier();
729 }
730 return _notAChild(node);
731 }
732
733 @override
734 AstNode visitListLiteral(ListLiteral node) {
735 if (identical(_oldNode, node.typeArguments)) {
736 return _parser.parseTypeArgumentList();
737 } else if (node.elements.contains(_oldNode)) {
738 return _parser.parseExpression2();
739 }
740 return _notAChild(node);
741 }
742
743 @override
744 AstNode visitMapLiteral(MapLiteral node) {
745 if (identical(_oldNode, node.typeArguments)) {
746 return _parser.parseTypeArgumentList();
747 } else if (node.entries.contains(_oldNode)) {
748 return _parser.parseMapLiteralEntry();
749 }
750 return _notAChild(node);
751 }
752
753 @override
754 AstNode visitMapLiteralEntry(MapLiteralEntry node) {
755 if (identical(_oldNode, node.key)) {
756 return _parser.parseExpression2();
757 } else if (identical(_oldNode, node.value)) {
758 return _parser.parseExpression2();
759 }
760 return _notAChild(node);
761 }
762
763 @override
764 AstNode visitMethodDeclaration(MethodDeclaration node) {
765 if (identical(_oldNode, node.documentationComment)) {
766 throw new InsufficientContextException();
767 } else if (node.metadata.contains(_oldNode)) {
768 return _parser.parseAnnotation();
769 } else if (identical(_oldNode, node.returnType)) {
770 throw new InsufficientContextException();
771 } else if (identical(_oldNode, node.name)) {
772 if (node.operatorKeyword != null) {
773 throw new InsufficientContextException();
774 }
775 return _parser.parseSimpleIdentifier();
776 } else if (identical(_oldNode, node.body)) {
777 //return parser.parseFunctionBody();
778 throw new InsufficientContextException();
779 }
780 return _notAChild(node);
781 }
782
783 @override
784 AstNode visitMethodInvocation(MethodInvocation node) {
785 if (identical(_oldNode, node.target)) {
786 throw new IncrementalParseException();
787 } else if (identical(_oldNode, node.methodName)) {
788 return _parser.parseSimpleIdentifier();
789 } else if (identical(_oldNode, node.argumentList)) {
790 return _parser.parseArgumentList();
791 }
792 return _notAChild(node);
793 }
794
795 @override
796 AstNode visitNamedExpression(NamedExpression node) {
797 if (identical(_oldNode, node.name)) {
798 return _parser.parseLabel();
799 } else if (identical(_oldNode, node.expression)) {
800 return _parser.parseExpression2();
801 }
802 return _notAChild(node);
803 }
804
805 @override
806 AstNode visitNativeClause(NativeClause node) {
807 if (identical(_oldNode, node.name)) {
808 return _parser.parseStringLiteral();
809 }
810 return _notAChild(node);
811 }
812
813 @override
814 AstNode visitNativeFunctionBody(NativeFunctionBody node) {
815 if (identical(_oldNode, node.stringLiteral)) {
816 return _parser.parseStringLiteral();
817 }
818 return _notAChild(node);
819 }
820
821 @override
822 AstNode visitNullLiteral(NullLiteral node) => _notAChild(node);
823
824 @override
825 AstNode visitParenthesizedExpression(ParenthesizedExpression node) {
826 if (identical(_oldNode, node.expression)) {
827 return _parser.parseExpression2();
828 }
829 return _notAChild(node);
830 }
831
832 @override
833 AstNode visitPartDirective(PartDirective node) {
834 if (identical(_oldNode, node.documentationComment)) {
835 throw new InsufficientContextException();
836 } else if (node.metadata.contains(_oldNode)) {
837 return _parser.parseAnnotation();
838 } else if (identical(_oldNode, node.uri)) {
839 return _parser.parseStringLiteral();
840 }
841 return _notAChild(node);
842 }
843
844 @override
845 AstNode visitPartOfDirective(PartOfDirective node) {
846 if (identical(_oldNode, node.documentationComment)) {
847 throw new InsufficientContextException();
848 } else if (node.metadata.contains(_oldNode)) {
849 return _parser.parseAnnotation();
850 } else if (identical(_oldNode, node.libraryName)) {
851 return _parser.parseLibraryIdentifier();
852 }
853 return _notAChild(node);
854 }
855
856 @override
857 AstNode visitPostfixExpression(PostfixExpression node) {
858 if (identical(_oldNode, node.operand)) {
859 throw new InsufficientContextException();
860 }
861 return _notAChild(node);
862 }
863
864 @override
865 AstNode visitPrefixedIdentifier(PrefixedIdentifier node) {
866 if (identical(_oldNode, node.prefix)) {
867 return _parser.parseSimpleIdentifier();
868 } else if (identical(_oldNode, node.identifier)) {
869 return _parser.parseSimpleIdentifier();
870 }
871 return _notAChild(node);
872 }
873
874 @override
875 AstNode visitPrefixExpression(PrefixExpression node) {
876 if (identical(_oldNode, node.operand)) {
877 throw new InsufficientContextException();
878 }
879 return _notAChild(node);
880 }
881
882 @override
883 AstNode visitPropertyAccess(PropertyAccess node) {
884 if (identical(_oldNode, node.target)) {
885 throw new InsufficientContextException();
886 } else if (identical(_oldNode, node.propertyName)) {
887 return _parser.parseSimpleIdentifier();
888 }
889 return _notAChild(node);
890 }
891
892 @override
893 AstNode visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
894 if (identical(_oldNode, node.constructorName)) {
895 return _parser.parseSimpleIdentifier();
896 } else if (identical(_oldNode, node.argumentList)) {
897 return _parser.parseArgumentList();
898 }
899 return _notAChild(node);
900 }
901
902 @override
903 AstNode visitRethrowExpression(RethrowExpression node) => _notAChild(node);
904
905 @override
906 AstNode visitReturnStatement(ReturnStatement node) {
907 if (identical(_oldNode, node.expression)) {
908 return _parser.parseExpression2();
909 }
910 return _notAChild(node);
911 }
912
913 @override
914 AstNode visitScriptTag(ScriptTag node) => _notAChild(node);
915
916 @override
917 AstNode visitShowCombinator(ShowCombinator node) {
918 if (node.shownNames.contains(_oldNode)) {
919 return _parser.parseSimpleIdentifier();
920 }
921 return _notAChild(node);
922 }
923
924 @override
925 AstNode visitSimpleFormalParameter(SimpleFormalParameter node) {
926 if (identical(_oldNode, node.documentationComment)) {
927 throw new InsufficientContextException();
928 } else if (node.metadata.contains(_oldNode)) {
929 return _parser.parseAnnotation();
930 } else if (identical(_oldNode, node.type)) {
931 throw new InsufficientContextException();
932 } else if (identical(_oldNode, node.identifier)) {
933 throw new InsufficientContextException();
934 }
935 return _notAChild(node);
936 }
937
938 @override
939 AstNode visitSimpleIdentifier(SimpleIdentifier node) => _notAChild(node);
940
941 @override
942 AstNode visitSimpleStringLiteral(SimpleStringLiteral node) => _notAChild(node) ;
943
944 @override
945 AstNode visitStringInterpolation(StringInterpolation node) {
946 if (node.elements.contains(_oldNode)) {
947 throw new InsufficientContextException();
948 }
949 return _notAChild(node);
950 }
951
952 @override
953 AstNode visitSuperConstructorInvocation(SuperConstructorInvocation node) {
954 if (identical(_oldNode, node.constructorName)) {
955 return _parser.parseSimpleIdentifier();
956 } else if (identical(_oldNode, node.argumentList)) {
957 return _parser.parseArgumentList();
958 }
959 return _notAChild(node);
960 }
961
962 @override
963 AstNode visitSuperExpression(SuperExpression node) => _notAChild(node);
964
965 @override
966 AstNode visitSwitchCase(SwitchCase node) {
967 if (node.labels.contains(_oldNode)) {
968 return _parser.parseLabel();
969 } else if (identical(_oldNode, node.expression)) {
970 return _parser.parseExpression2();
971 } else if (node.statements.contains(_oldNode)) {
972 return _parser.parseStatement2();
973 }
974 return _notAChild(node);
975 }
976
977 @override
978 AstNode visitSwitchDefault(SwitchDefault node) {
979 if (node.labels.contains(_oldNode)) {
980 return _parser.parseLabel();
981 } else if (node.statements.contains(_oldNode)) {
982 return _parser.parseStatement2();
983 }
984 return _notAChild(node);
985 }
986
987 @override
988 AstNode visitSwitchStatement(SwitchStatement node) {
989 if (identical(_oldNode, node.expression)) {
990 return _parser.parseExpression2();
991 } else if (node.members.contains(_oldNode)) {
992 throw new InsufficientContextException();
993 }
994 return _notAChild(node);
995 }
996
997 @override
998 AstNode visitSymbolLiteral(SymbolLiteral node) => _notAChild(node);
999
1000 @override
1001 AstNode visitThisExpression(ThisExpression node) => _notAChild(node);
1002
1003 @override
1004 AstNode visitThrowExpression(ThrowExpression node) {
1005 if (identical(_oldNode, node.expression)) {
1006 if (_isCascadeAllowedInThrow(node)) {
1007 return _parser.parseExpression2();
1008 }
1009 return _parser.parseExpressionWithoutCascade();
1010 }
1011 return _notAChild(node);
1012 }
1013
1014 @override
1015 AstNode visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
1016 if (identical(_oldNode, node.documentationComment)) {
1017 throw new InsufficientContextException();
1018 } else if (node.metadata.contains(_oldNode)) {
1019 return _parser.parseAnnotation();
1020 } else if (identical(_oldNode, node.variables)) {
1021 throw new InsufficientContextException();
1022 }
1023 return _notAChild(node);
1024 }
1025
1026 @override
1027 AstNode visitTryStatement(TryStatement node) {
1028 if (identical(_oldNode, node.body)) {
1029 return _parser.parseBlock();
1030 } else if (node.catchClauses.contains(_oldNode)) {
1031 throw new InsufficientContextException();
1032 } else if (identical(_oldNode, node.finallyBlock)) {
1033 throw new InsufficientContextException();
1034 }
1035 return _notAChild(node);
1036 }
1037
1038 @override
1039 AstNode visitTypeArgumentList(TypeArgumentList node) {
1040 if (node.arguments.contains(_oldNode)) {
1041 return _parser.parseTypeName();
1042 }
1043 return _notAChild(node);
1044 }
1045
1046 @override
1047 AstNode visitTypeName(TypeName node) {
1048 if (identical(_oldNode, node.name)) {
1049 return _parser.parsePrefixedIdentifier();
1050 } else if (identical(_oldNode, node.typeArguments)) {
1051 return _parser.parseTypeArgumentList();
1052 }
1053 return _notAChild(node);
1054 }
1055
1056 @override
1057 AstNode visitTypeParameter(TypeParameter node) {
1058 if (identical(_oldNode, node.documentationComment)) {
1059 throw new InsufficientContextException();
1060 } else if (node.metadata.contains(_oldNode)) {
1061 return _parser.parseAnnotation();
1062 } else if (identical(_oldNode, node.name)) {
1063 return _parser.parseSimpleIdentifier();
1064 } else if (identical(_oldNode, node.bound)) {
1065 return _parser.parseTypeName();
1066 }
1067 return _notAChild(node);
1068 }
1069
1070 @override
1071 AstNode visitTypeParameterList(TypeParameterList node) {
1072 if (node.typeParameters.contains(node)) {
1073 return _parser.parseTypeParameter();
1074 }
1075 return _notAChild(node);
1076 }
1077
1078 @override
1079 AstNode visitVariableDeclaration(VariableDeclaration node) {
1080 if (identical(_oldNode, node.documentationComment)) {
1081 throw new InsufficientContextException();
1082 } else if (node.metadata.contains(_oldNode)) {
1083 return _parser.parseAnnotation();
1084 } else if (identical(_oldNode, node.name)) {
1085 throw new InsufficientContextException();
1086 } else if (identical(_oldNode, node.initializer)) {
1087 throw new InsufficientContextException();
1088 }
1089 return _notAChild(node);
1090 }
1091
1092 @override
1093 AstNode visitVariableDeclarationList(VariableDeclarationList node) {
1094 if (identical(_oldNode, node.documentationComment)) {
1095 throw new InsufficientContextException();
1096 } else if (node.metadata.contains(_oldNode)) {
1097 return _parser.parseAnnotation();
1098 } else if (node.variables.contains(_oldNode)) {
1099 throw new InsufficientContextException();
1100 }
1101 return _notAChild(node);
1102 }
1103
1104 @override
1105 AstNode visitVariableDeclarationStatement(VariableDeclarationStatement node) {
1106 if (identical(_oldNode, node.variables)) {
1107 throw new InsufficientContextException();
1108 }
1109 return _notAChild(node);
1110 }
1111
1112 @override
1113 AstNode visitWhileStatement(WhileStatement node) {
1114 if (identical(_oldNode, node.condition)) {
1115 return _parser.parseExpression2();
1116 } else if (identical(_oldNode, node.body)) {
1117 return _parser.parseStatement2();
1118 }
1119 return _notAChild(node);
1120 }
1121
1122 @override
1123 AstNode visitWithClause(WithClause node) {
1124 if (node.mixinTypes.contains(node)) {
1125 return _parser.parseTypeName();
1126 }
1127 return _notAChild(node);
1128 }
1129
1130 @override
1131 AstNode visitYieldStatement(YieldStatement node) {
1132 if (identical(_oldNode, node.expression)) {
1133 return _parser.parseExpression2();
1134 }
1135 return _notAChild(node);
1136 }
1137
1138 /**
1139 * Return `true` if the given assignment expression can have a cascade express ion on the
1140 * right-hand side.
1141 *
1142 * @param node the assignment expression being tested
1143 * @return `true` if the right-hand side can be a cascade expression
1144 */
1145 bool _isCascadeAllowedInAssignment(AssignmentExpression node) {
1146 // TODO(brianwilkerson) Implement this method.
1147 throw new InsufficientContextException();
1148 }
1149
1150 /**
1151 * Return `true` if the given throw expression can have a cascade expression.
1152 *
1153 * @param node the throw expression being tested
1154 * @return `true` if the expression can be a cascade expression
1155 */
1156 bool _isCascadeAllowedInThrow(ThrowExpression node) {
1157 // TODO(brianwilkerson) Implement this method.
1158 throw new InsufficientContextException();
1159 }
1160
1161 /**
1162 * Throw an exception indicating that the visited node was not the parent of t he node to be
1163 * replaced.
1164 *
1165 * @param visitedNode the visited node that should have been the parent of the node to be replaced
1166 */
1167 AstNode _notAChild(AstNode visitedNode) {
1168 throw new IncrementalParseException.con1("Internal error: the visited node ( a ${visitedNode.runtimeType.toString()}) was not the parent of the node to be re placed (a ${_oldNode.runtimeType.toString()})");
1169 }
1170 }
1171
1172 /**
1173 * Instances of the class `IncrementalParseException` represent an exception tha t occurred
1174 * while attempting to parse a replacement for a specified node in an existing A ST structure.
1175 */
1176 class IncrementalParseException extends RuntimeException {
1177 /**
1178 * Initialize a newly created exception to have no message and to be its own c ause.
1179 */
1180 IncrementalParseException() : super();
1181
1182 /**
1183 * Initialize a newly created exception to have the given message and to be it s own cause.
1184 *
1185 * @param message the message describing the reason for the exception
1186 */
1187 IncrementalParseException.con1(String message) : super(message: message);
1188
1189 /**
1190 * Initialize a newly created exception to have no message and to have the giv en cause.
1191 *
1192 * @param cause the exception that caused this exception
1193 */
1194 IncrementalParseException.con2(Exception cause) : super(cause: cause);
1195 }
1196
1197 /**
1198 * Instances of the class `IncrementalParser` re-parse a single AST structure wi thin a larger
1199 * AST structure.
1200 */
1201 class IncrementalParser {
1202 /**
1203 * The source being parsed.
1204 */
1205 final Source _source;
1206
1207 /**
1208 * A map from old tokens to new tokens used during the cloning process.
1209 */
1210 final TokenMap _tokenMap;
1211
1212 /**
1213 * The error listener that will be informed of any errors that are found durin g the parse.
1214 */
1215 final AnalysisErrorListener _errorListener;
1216
1217 /**
1218 * The node in the AST structure that contains the revised content.
1219 */
1220 AstNode _updatedNode;
1221
1222 /**
1223 * Initialize a newly created incremental parser to parse a portion of the con tent of the given
1224 * source.
1225 *
1226 * @param source the source being parsed
1227 * @param tokenMap a map from old tokens to new tokens used during the cloning process
1228 * @param errorListener the error listener that will be informed of any errors that are found
1229 * during the parse
1230 */
1231 IncrementalParser(this._source, this._tokenMap, this._errorListener);
1232
1233 /**
1234 * Return the node in the AST structure that contains the revised content.
1235 *
1236 * @return the updated node
1237 */
1238 AstNode get updatedNode => _updatedNode;
1239
1240 /**
1241 * Given a range of tokens that were re-scanned, re-parse the minimum number o f tokens to produce
1242 * a consistent AST structure. The range is represented by the first and last tokens in the range.
1243 * The tokens are assumed to be contained in the same token stream.
1244 *
1245 * @param leftToken the token in the new token stream immediately to the left of the range of
1246 * tokens that were inserted
1247 * @param rightToken the token in the new token stream immediately to the righ t of the range of
1248 * tokens that were inserted
1249 * @param originalStart the offset in the original source of the first charact er that was modified
1250 * @param originalEnd the offset in the original source of the last character that was modified
1251 */
1252 AstNode reparse(AstNode originalStructure, Token leftToken, Token rightToken, int originalStart, int originalEnd) {
1253 AstNode oldNode = null;
1254 AstNode newNode = null;
1255 //
1256 // Find the first token that needs to be re-parsed.
1257 //
1258 Token firstToken = leftToken.next;
1259 if (identical(firstToken, rightToken)) {
1260 // If there are no new tokens, then we need to include at least one copied node in the range.
1261 firstToken = leftToken;
1262 }
1263 //
1264 // Find the smallest AST node that encompasses the range of re-scanned token s.
1265 //
1266 if (originalEnd < originalStart) {
1267 oldNode = new NodeLocator.con1(originalStart).searchWithin(originalStructu re);
1268 } else {
1269 oldNode = new NodeLocator.con2(originalStart, originalEnd).searchWithin(or iginalStructure);
1270 }
1271 //
1272 // Find the token at which parsing is to begin.
1273 //
1274 int originalOffset = oldNode.offset;
1275 Token parseToken = _findTokenAt(firstToken, originalOffset);
1276 if (parseToken == null) {
1277 return null;
1278 }
1279 //
1280 // Parse the appropriate AST structure starting at the appropriate place.
1281 //
1282 Parser parser = new Parser(_source, _errorListener);
1283 parser.currentToken = parseToken;
1284 while (newNode == null) {
1285 AstNode parent = oldNode.parent;
1286 if (parent == null) {
1287 parseToken = _findFirstToken(parseToken);
1288 parser.currentToken = parseToken;
1289 return parser.parseCompilationUnit2();
1290 }
1291 bool advanceToParent = false;
1292 try {
1293 IncrementalParseDispatcher dispatcher = new IncrementalParseDispatcher(p arser, oldNode);
1294 newNode = parent.accept(dispatcher);
1295 //
1296 // Validate that the new node can replace the old node.
1297 //
1298 Token mappedToken = _tokenMap.get(oldNode.endToken.next);
1299 if (mappedToken == null || mappedToken.offset != newNode.endToken.next.o ffset || newNode.offset != oldNode.offset) {
1300 advanceToParent = true;
1301 }
1302 } on InsufficientContextException catch (exception) {
1303 advanceToParent = true;
1304 } catch (exception) {
1305 return null;
1306 }
1307 if (advanceToParent) {
1308 newNode = null;
1309 oldNode = parent;
1310 originalOffset = oldNode.offset;
1311 parseToken = _findTokenAt(parseToken, originalOffset);
1312 parser.currentToken = parseToken;
1313 }
1314 }
1315 _updatedNode = newNode;
1316 //
1317 // Replace the old node with the new node in a copy of the original AST stru cture.
1318 //
1319 if (identical(oldNode, originalStructure)) {
1320 // We ended up re-parsing the whole structure, so there's no need for a co py.
1321 ResolutionCopier.copyResolutionData(oldNode, newNode);
1322 return newNode;
1323 }
1324 ResolutionCopier.copyResolutionData(oldNode, newNode);
1325 IncrementalAstCloner cloner = new IncrementalAstCloner(oldNode, newNode, _to kenMap);
1326 return originalStructure.accept(cloner) as AstNode;
1327 }
1328
1329 /**
1330 * Return the first (non-EOF) token in the token stream containing the given t oken.
1331 *
1332 * @param firstToken the token from which the search is to begin
1333 * @return the first token in the token stream containing the given token
1334 */
1335 Token _findFirstToken(Token firstToken) {
1336 while (firstToken.type != TokenType.EOF) {
1337 firstToken = firstToken.previous;
1338 }
1339 return firstToken.next;
1340 }
1341
1342 /**
1343 * Find the token at or before the given token with the given offset, or `null ` if there is
1344 * no such token.
1345 *
1346 * @param firstToken the token from which the search is to begin
1347 * @param offset the offset of the token to be returned
1348 * @return the token with the given offset
1349 */
1350 Token _findTokenAt(Token firstToken, int offset) {
1351 while (firstToken.offset > offset && firstToken.type != TokenType.EOF) {
1352 firstToken = firstToken.previous;
1353 }
1354 return firstToken;
1355 }
1356 }
1357
1358 /**
1359 * Instances of the class `InsufficientContextException` represent a situation i n which an AST
1360 * node cannot be re-parsed because there is not enough context to know how to r e-parse the node.
1361 * Clients can attempt to re-parse the parent of the node.
1362 */
1363 class InsufficientContextException extends IncrementalParseException {
1364 /**
1365 * Initialize a newly created exception to have no message and to be its own c ause.
1366 */
1367 InsufficientContextException() : super();
1368
1369 /**
1370 * Initialize a newly created exception to have the given message and to be it s own cause.
1371 *
1372 * @param message the message describing the reason for the exception
1373 */
1374 InsufficientContextException.con1(String message) : super.con1(message);
1375
1376 /**
1377 * Initialize a newly created exception to have no message and to have the giv en cause.
1378 *
1379 * @param cause the exception that caused this exception
1380 */
1381 InsufficientContextException.con2(Exception cause) : super.con2(cause);
1382 }
1383
1384 /**
1385 * Instances of the class `Modifiers` implement a simple data-holder for a metho d that needs
1386 * to return multiple values.
1387 */
1388 class Modifiers {
1389 /**
1390 * The token representing the keyword 'abstract', or `null` if the keyword was not found.
1391 */
1392 Token abstractKeyword;
1393
1394 /**
1395 * The token representing the keyword 'const', or `null` if the keyword was no t found.
1396 */
1397 Token constKeyword;
1398
1399 /**
1400 * The token representing the keyword 'external', or `null` if the keyword was not found.
1401 */
1402 Token externalKeyword;
1403
1404 /**
1405 * The token representing the keyword 'factory', or `null` if the keyword was not found.
1406 */
1407 Token factoryKeyword;
1408
1409 /**
1410 * The token representing the keyword 'final', or `null` if the keyword was no t found.
1411 */
1412 Token finalKeyword;
1413
1414 /**
1415 * The token representing the keyword 'static', or `null` if the keyword was n ot found.
1416 */
1417 Token staticKeyword;
1418
1419 /**
1420 * The token representing the keyword 'var', or `null` if the keyword was not found.
1421 */
1422 Token varKeyword;
1423
1424 @override
1425 String toString() {
1426 JavaStringBuilder builder = new JavaStringBuilder();
1427 bool needsSpace = _appendKeyword(builder, false, abstractKeyword);
1428 needsSpace = _appendKeyword(builder, needsSpace, constKeyword);
1429 needsSpace = _appendKeyword(builder, needsSpace, externalKeyword);
1430 needsSpace = _appendKeyword(builder, needsSpace, factoryKeyword);
1431 needsSpace = _appendKeyword(builder, needsSpace, finalKeyword);
1432 needsSpace = _appendKeyword(builder, needsSpace, staticKeyword);
1433 _appendKeyword(builder, needsSpace, varKeyword);
1434 return builder.toString();
1435 }
1436
1437 /**
1438 * If the given keyword is not `null`, append it to the given builder, prefixi ng it with a
1439 * space if needed.
1440 *
1441 * @param builder the builder to which the keyword will be appended
1442 * @param needsSpace `true` if the keyword needs to be prefixed with a space
1443 * @param keyword the keyword to be appended
1444 * @return `true` if subsequent keywords need to be prefixed with a space
1445 */
1446 bool _appendKeyword(JavaStringBuilder builder, bool needsSpace, Token keyword) {
1447 if (keyword != null) {
1448 if (needsSpace) {
1449 builder.appendChar(0x20);
1450 }
1451 builder.append(keyword.lexeme);
1452 return true;
1453 }
1454 return needsSpace;
1455 }
1456 }
1457
1458 /**
1459 * Instances of the class `Parser` are used to parse tokens into an AST structur e.
1460 */
1461 class Parser {
1462 /**
1463 * The source being parsed.
1464 */
1465 final Source _source;
1466
1467 /**
1468 * The error listener that will be informed of any errors that are found durin g the parse.
1469 */
1470 final AnalysisErrorListener _errorListener;
1471
1472 /**
1473 * An [errorListener] lock, if more than `0`, then errors are not reported.
1474 */
1475 int _errorListenerLock = 0;
1476
1477 /**
1478 * A flag indicating whether parser is to parse function bodies.
1479 */
1480 bool _parseFunctionBodies = true;
1481
1482 /**
1483 * A flag indicating whether the parser is to parse the async support.
1484 */
1485 bool _parseAsync = AnalysisOptionsImpl.DEFAULT_ENABLE_ASYNC;
1486
1487 /**
1488 * A flag indicating whether the parser is to parse deferred libraries.
1489 */
1490 bool _parseDeferredLibraries = AnalysisOptionsImpl.DEFAULT_ENABLE_DEFERRED_LOA DING;
1491
1492 /**
1493 * A flag indicating whether the parser is to parse enum declarations.
1494 */
1495 bool _parseEnum = AnalysisOptionsImpl.DEFAULT_ENABLE_ENUM;
1496
1497 /**
1498 * The next token to be parsed.
1499 */
1500 Token _currentToken;
1501
1502 /**
1503 * A flag indicating whether the parser is currently in a function body marked as being 'async'.
1504 */
1505 bool _inAsync = false;
1506
1507 /**
1508 * A flag indicating whether the parser is currently in the body of a loop.
1509 */
1510 bool _inLoop = false;
1511
1512 /**
1513 * A flag indicating whether the parser is currently in a switch statement.
1514 */
1515 bool _inSwitch = false;
1516
1517 /**
1518 * A flag indicating whether the parser is currently in a constructor field in itializer, with no
1519 * intervening parens, braces, or brackets.
1520 */
1521 bool _inInitializer = false;
1522
1523 static String ASYNC = "async";
1524
1525 static String _AWAIT = "await";
1526
1527 static String _HIDE = "hide";
1528
1529 static String _OF = "of";
1530
1531 static String _ON = "on";
1532
1533 static String _NATIVE = "native";
1534
1535 static String _SHOW = "show";
1536
1537 static String SYNC = "sync";
1538
1539 static String _YIELD = "yield";
1540
1541 /**
1542 * Initialize a newly created parser.
1543 *
1544 * @param source the source being parsed
1545 * @param errorListener the error listener that will be informed of any errors that are found
1546 * during the parse
1547 */
1548 Parser(this._source, this._errorListener);
1549
1550 /**
1551 * Parse a compilation unit, starting with the given token.
1552 *
1553 * @param token the first token of the compilation unit
1554 * @return the compilation unit that was parsed
1555 */
1556 CompilationUnit parseCompilationUnit(Token token) {
1557 InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engi ne.Parser.parseCompilationUnit");
1558 try {
1559 _currentToken = token;
1560 return parseCompilationUnit2();
1561 } finally {
1562 instrumentation.log2(2);
1563 }
1564 }
1565
1566 /**
1567 * Parse the script tag and directives in a compilation unit, starting with th e given token, until
1568 * the first non-directive is encountered. The remainder of the compilation un it will not be
1569 * parsed. Specifically, if there are directives later in the file, they will not be parsed.
1570 *
1571 * @param token the first token of the compilation unit
1572 * @return the compilation unit that was parsed
1573 */
1574 CompilationUnit parseDirectives(Token token) {
1575 InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engi ne.Parser.parseDirectives");
1576 try {
1577 _currentToken = token;
1578 return _parseDirectives();
1579 } finally {
1580 instrumentation.log2(2);
1581 }
1582 }
1583
1584 /**
1585 * Parse an expression, starting with the given token.
1586 *
1587 * @param token the first token of the expression
1588 * @return the expression that was parsed, or `null` if the tokens do not repr esent a
1589 * recognizable expression
1590 */
1591 Expression parseExpression(Token token) {
1592 InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engi ne.Parser.parseExpression");
1593 try {
1594 _currentToken = token;
1595 return parseExpression2();
1596 } finally {
1597 instrumentation.log();
1598 }
1599 }
1600
1601 /**
1602 * Parse a statement, starting with the given token.
1603 *
1604 * @param token the first token of the statement
1605 * @return the statement that was parsed, or `null` if the tokens do not repre sent a
1606 * recognizable statement
1607 */
1608 Statement parseStatement(Token token) {
1609 InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engi ne.Parser.parseStatement");
1610 try {
1611 _currentToken = token;
1612 return parseStatement2();
1613 } finally {
1614 instrumentation.log();
1615 }
1616 }
1617
1618 /**
1619 * Parse a sequence of statements, starting with the given token.
1620 *
1621 * @param token the first token of the sequence of statement
1622 * @return the statements that were parsed, or `null` if the tokens do not rep resent a
1623 * recognizable sequence of statements
1624 */
1625 List<Statement> parseStatements(Token token) {
1626 InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engi ne.Parser.parseStatements");
1627 try {
1628 _currentToken = token;
1629 return _parseStatementList();
1630 } finally {
1631 instrumentation.log();
1632 }
1633 }
1634
1635 /**
1636 * Set whether the parser is to parse the async support.
1637 *
1638 * @param parseAsync `true` if the parser is to parse the async support
1639 */
1640 void set parseAsync(bool parseAsync) {
1641 this._parseAsync = parseAsync;
1642 }
1643
1644 /**
1645 * Set whether the parser is to parse deferred libraries.
1646 *
1647 * @param parseDeferredLibraries `true` if the parser is to parse deferred lib raries
1648 */
1649 void set parseDeferredLibraries(bool parseDeferredLibraries) {
1650 this._parseDeferredLibraries = parseDeferredLibraries;
1651 }
1652
1653 /**
1654 * Set whether the parser is to parse enum declarations.
1655 *
1656 * @param parseEnum `true` if the parser is to parse enum declarations
1657 */
1658 void set parseEnum(bool parseEnum) {
1659 this._parseEnum = parseEnum;
1660 }
1661
1662 /**
1663 * Set whether parser is to parse function bodies.
1664 *
1665 * @param parseFunctionBodies `true` if parser is to parse function bodies
1666 */
1667 void set parseFunctionBodies(bool parseFunctionBodies) {
1668 this._parseFunctionBodies = parseFunctionBodies;
1669 }
1670
1671 /**
1672 * Parse an annotation.
1673 *
1674 * <pre>
1675 * annotation ::=
1676 * '@' qualified ('.' identifier)? arguments?
1677 * </pre>
1678 *
1679 * @return the annotation that was parsed
1680 */
1681 Annotation parseAnnotation() {
1682 Token atSign = _expect(TokenType.AT);
1683 Identifier name = parsePrefixedIdentifier();
1684 Token period = null;
1685 SimpleIdentifier constructorName = null;
1686 if (_matches(TokenType.PERIOD)) {
1687 period = andAdvance;
1688 constructorName = parseSimpleIdentifier();
1689 }
1690 ArgumentList arguments = null;
1691 if (_matches(TokenType.OPEN_PAREN)) {
1692 arguments = parseArgumentList();
1693 }
1694 return new Annotation(atSign, name, period, constructorName, arguments);
1695 }
1696
1697 /**
1698 * Parse an argument.
1699 *
1700 * <pre>
1701 * argument ::=
1702 * namedArgument
1703 * | expression
1704 *
1705 * namedArgument ::=
1706 * label expression
1707 * </pre>
1708 *
1709 * @return the argument that was parsed
1710 */
1711 Expression parseArgument() {
1712 //
1713 // Both namedArgument and expression can start with an identifier, but only namedArgument can
1714 // have an identifier followed by a colon.
1715 //
1716 if (_matchesIdentifier() && _tokenMatches(_peek(), TokenType.COLON)) {
1717 return new NamedExpression(parseLabel(), parseExpression2());
1718 } else {
1719 return parseExpression2();
1720 }
1721 }
1722
1723 /**
1724 * Parse a list of arguments.
1725 *
1726 * <pre>
1727 * arguments ::=
1728 * '(' argumentList? ')'
1729 *
1730 * argumentList ::=
1731 * namedArgument (',' namedArgument)*
1732 * | expressionList (',' namedArgument)*
1733 * </pre>
1734 *
1735 * @return the argument list that was parsed
1736 */
1737 ArgumentList parseArgumentList() {
1738 Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
1739 List<Expression> arguments = new List<Expression>();
1740 if (_matches(TokenType.CLOSE_PAREN)) {
1741 return new ArgumentList(leftParenthesis, arguments, andAdvance);
1742 }
1743 //
1744 // Even though unnamed arguments must all appear before any named arguments, we allow them to
1745 // appear in any order so that we can recover faster.
1746 //
1747 bool wasInInitializer = _inInitializer;
1748 _inInitializer = false;
1749 try {
1750 Expression argument = parseArgument();
1751 arguments.add(argument);
1752 bool foundNamedArgument = argument is NamedExpression;
1753 bool generatedError = false;
1754 while (_optional(TokenType.COMMA)) {
1755 argument = parseArgument();
1756 arguments.add(argument);
1757 if (foundNamedArgument) {
1758 if (!generatedError && argument is! NamedExpression) {
1759 // Report the error, once, but allow the arguments to be in any orde r in the AST.
1760 _reportErrorForCurrentToken(ParserErrorCode.POSITIONAL_AFTER_NAMED_A RGUMENT, []);
1761 generatedError = true;
1762 }
1763 } else if (argument is NamedExpression) {
1764 foundNamedArgument = true;
1765 }
1766 }
1767 // TODO(brianwilkerson) Recovery: Look at the left parenthesis to see whet her there is a
1768 // matching right parenthesis. If there is, then we're more likely missing a comma and should
1769 // go back to parsing arguments.
1770 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
1771 return new ArgumentList(leftParenthesis, arguments, rightParenthesis);
1772 } finally {
1773 _inInitializer = wasInInitializer;
1774 }
1775 }
1776
1777 /**
1778 * Parse a bitwise or expression.
1779 *
1780 * <pre>
1781 * bitwiseOrExpression ::=
1782 * bitwiseXorExpression ('|' bitwiseXorExpression)*
1783 * | 'super' ('|' bitwiseXorExpression)+
1784 * </pre>
1785 *
1786 * @return the bitwise or expression that was parsed
1787 */
1788 Expression parseBitwiseOrExpression() {
1789 Expression expression;
1790 if (_matchesKeyword(Keyword.SUPER) && _tokenMatches(_peek(), TokenType.BAR)) {
1791 expression = new SuperExpression(andAdvance);
1792 } else {
1793 expression = _parseBitwiseXorExpression();
1794 }
1795 while (_matches(TokenType.BAR)) {
1796 Token operator = andAdvance;
1797 expression = new BinaryExpression(expression, operator, _parseBitwiseXorEx pression());
1798 }
1799 return expression;
1800 }
1801
1802 /**
1803 * Parse a block.
1804 *
1805 * <pre>
1806 * block ::=
1807 * '{' statements '}'
1808 * </pre>
1809 *
1810 * @return the block that was parsed
1811 */
1812 Block parseBlock() {
1813 Token leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET);
1814 List<Statement> statements = new List<Statement>();
1815 Token statementStart = _currentToken;
1816 while (!_matches(TokenType.EOF) && !_matches(TokenType.CLOSE_CURLY_BRACKET)) {
1817 Statement statement = parseStatement2();
1818 if (statement != null) {
1819 statements.add(statement);
1820 }
1821 if (identical(_currentToken, statementStart)) {
1822 // Ensure that we are making progress and report an error if we're not.
1823 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_ currentToken.lexeme]);
1824 _advance();
1825 }
1826 statementStart = _currentToken;
1827 }
1828 Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
1829 return new Block(leftBracket, statements, rightBracket);
1830 }
1831
1832 /**
1833 * Parse a class member.
1834 *
1835 * <pre>
1836 * classMemberDefinition ::=
1837 * declaration ';'
1838 * | methodSignature functionBody
1839 * </pre>
1840 *
1841 * @param className the name of the class containing the member being parsed
1842 * @return the class member that was parsed, or `null` if what was found was n ot a valid
1843 * class member
1844 */
1845 ClassMember parseClassMember(String className) {
1846 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
1847 Modifiers modifiers = _parseModifiers();
1848 if (_matchesKeyword(Keyword.VOID)) {
1849 TypeName returnType = parseReturnType();
1850 if (_matchesKeyword(Keyword.GET) && _tokenMatchesIdentifier(_peek())) {
1851 _validateModifiersForGetterOrSetterOrMethod(modifiers);
1852 return _parseGetter(commentAndMetadata, modifiers.externalKeyword, modif iers.staticKeyword, returnType);
1853 } else if (_matchesKeyword(Keyword.SET) && _tokenMatchesIdentifier(_peek() )) {
1854 _validateModifiersForGetterOrSetterOrMethod(modifiers);
1855 return _parseSetter(commentAndMetadata, modifiers.externalKeyword, modif iers.staticKeyword, returnType);
1856 } else if (_matchesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) {
1857 _validateModifiersForOperator(modifiers);
1858 return _parseOperator(commentAndMetadata, modifiers.externalKeyword, ret urnType);
1859 } else if (_matchesIdentifier() && _peek().matchesAny([
1860 TokenType.OPEN_PAREN,
1861 TokenType.OPEN_CURLY_BRACKET,
1862 TokenType.FUNCTION])) {
1863 _validateModifiersForGetterOrSetterOrMethod(modifiers);
1864 return _parseMethodDeclarationAfterReturnType(commentAndMetadata, modifi ers.externalKeyword, modifiers.staticKeyword, returnType);
1865 } else {
1866 //
1867 // We have found an error of some kind. Try to recover.
1868 //
1869 if (_matchesIdentifier()) {
1870 if (_peek().matchesAny([TokenType.EQ, TokenType.COMMA, TokenType.SEMIC OLON])) {
1871 //
1872 // We appear to have a variable declaration with a type of "void".
1873 //
1874 _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType, []);
1875 return _parseInitializedIdentifierList(commentAndMetadata, modifiers .staticKeyword, _validateModifiersForField(modifiers), returnType);
1876 }
1877 }
1878 if (_isOperator(_currentToken)) {
1879 //
1880 // We appear to have found an operator declaration without the 'operat or' keyword.
1881 //
1882 _validateModifiersForOperator(modifiers);
1883 return _parseOperator(commentAndMetadata, modifiers.externalKeyword, r eturnType);
1884 }
1885 _reportErrorForToken(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken, []);
1886 return null;
1887 }
1888 } else if (_matchesKeyword(Keyword.GET) && _tokenMatchesIdentifier(_peek())) {
1889 _validateModifiersForGetterOrSetterOrMethod(modifiers);
1890 return _parseGetter(commentAndMetadata, modifiers.externalKeyword, modifie rs.staticKeyword, null);
1891 } else if (_matchesKeyword(Keyword.SET) && _tokenMatchesIdentifier(_peek())) {
1892 _validateModifiersForGetterOrSetterOrMethod(modifiers);
1893 return _parseSetter(commentAndMetadata, modifiers.externalKeyword, modifie rs.staticKeyword, null);
1894 } else if (_matchesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) {
1895 _validateModifiersForOperator(modifiers);
1896 return _parseOperator(commentAndMetadata, modifiers.externalKeyword, null) ;
1897 } else if (!_matchesIdentifier()) {
1898 if (_isOperator(_currentToken)) {
1899 //
1900 // We appear to have found an operator declaration without the 'operator ' keyword.
1901 //
1902 _validateModifiersForOperator(modifiers);
1903 return _parseOperator(commentAndMetadata, modifiers.externalKeyword, nul l);
1904 }
1905 Token keyword = modifiers.varKeyword;
1906 if (keyword == null) {
1907 keyword = modifiers.finalKeyword;
1908 }
1909 if (keyword == null) {
1910 keyword = modifiers.constKeyword;
1911 }
1912 if (keyword != null) {
1913 //
1914 // We appear to have found an incomplete field declaration.
1915 //
1916 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER, []);
1917 List<VariableDeclaration> variables = new List<VariableDeclaration>();
1918 variables.add(new VariableDeclaration(null, null, _createSyntheticIdenti fier(), null, null));
1919 return new FieldDeclaration(commentAndMetadata.comment, commentAndMetada ta.metadata, null, new VariableDeclarationList(null, null, keyword, null, variab les), _expectSemicolon());
1920 }
1921 _reportErrorForToken(ParserErrorCode.EXPECTED_CLASS_MEMBER, _currentToken, []);
1922 if (commentAndMetadata.comment != null || !commentAndMetadata.metadata.isE mpty) {
1923 //
1924 // We appear to have found an incomplete declaration at the end of the c lass. At this point
1925 // it consists of a metadata, which we don't want to loose, so we'll tre at it as a method
1926 // declaration with a missing name, parameters and empty body.
1927 //
1928 return new MethodDeclaration(commentAndMetadata.comment, commentAndMetad ata.metadata, null, null, null, null, null, _createSyntheticIdentifier(), new Fo rmalParameterList(null, new List<FormalParameter>(), null, null, null), new Empt yFunctionBody(_createSyntheticToken(TokenType.SEMICOLON)));
1929 }
1930 return null;
1931 } else if (_tokenMatches(_peek(), TokenType.PERIOD) && _tokenMatchesIdentifi er(_peekAt(2)) && _tokenMatches(_peekAt(3), TokenType.OPEN_PAREN)) {
1932 return _parseConstructor(commentAndMetadata, modifiers.externalKeyword, _v alidateModifiersForConstructor(modifiers), modifiers.factoryKeyword, parseSimple Identifier(), andAdvance, parseSimpleIdentifier(), parseFormalParameterList());
1933 } else if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
1934 SimpleIdentifier methodName = parseSimpleIdentifier();
1935 FormalParameterList parameters = parseFormalParameterList();
1936 if (_matches(TokenType.COLON) || modifiers.factoryKeyword != null || metho dName.name == className) {
1937 return _parseConstructor(commentAndMetadata, modifiers.externalKeyword, _validateModifiersForConstructor(modifiers), modifiers.factoryKeyword, methodNam e, null, null, parameters);
1938 }
1939 _validateModifiersForGetterOrSetterOrMethod(modifiers);
1940 _validateFormalParameterList(parameters);
1941 return _parseMethodDeclarationAfterParameters(commentAndMetadata, modifier s.externalKeyword, modifiers.staticKeyword, null, methodName, parameters);
1942 } else if (_peek().matchesAny([TokenType.EQ, TokenType.COMMA, TokenType.SEMI COLON])) {
1943 if (modifiers.constKeyword == null && modifiers.finalKeyword == null && mo difiers.varKeyword == null) {
1944 _reportErrorForCurrentToken(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_T YPE, []);
1945 }
1946 return _parseInitializedIdentifierList(commentAndMetadata, modifiers.stati cKeyword, _validateModifiersForField(modifiers), null);
1947 }
1948 TypeName type = parseTypeName();
1949 if (_matchesKeyword(Keyword.GET) && _tokenMatchesIdentifier(_peek())) {
1950 _validateModifiersForGetterOrSetterOrMethod(modifiers);
1951 return _parseGetter(commentAndMetadata, modifiers.externalKeyword, modifie rs.staticKeyword, type);
1952 } else if (_matchesKeyword(Keyword.SET) && _tokenMatchesIdentifier(_peek())) {
1953 _validateModifiersForGetterOrSetterOrMethod(modifiers);
1954 return _parseSetter(commentAndMetadata, modifiers.externalKeyword, modifie rs.staticKeyword, type);
1955 } else if (_matchesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) {
1956 _validateModifiersForOperator(modifiers);
1957 return _parseOperator(commentAndMetadata, modifiers.externalKeyword, type) ;
1958 } else if (!_matchesIdentifier()) {
1959 if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
1960 //
1961 // We appear to have found an incomplete declaration at the end of the c lass. At this point
1962 // it consists of a type name, so we'll treat it as a field declaration with a missing
1963 // field name and semicolon.
1964 //
1965 return _parseInitializedIdentifierList(commentAndMetadata, modifiers.sta ticKeyword, _validateModifiersForField(modifiers), type);
1966 }
1967 if (_isOperator(_currentToken)) {
1968 //
1969 // We appear to have found an operator declaration without the 'operator ' keyword.
1970 //
1971 _validateModifiersForOperator(modifiers);
1972 return _parseOperator(commentAndMetadata, modifiers.externalKeyword, typ e);
1973 }
1974 //
1975 // We appear to have found an incomplete declaration before another declar ation.
1976 // At this point it consists of a type name, so we'll treat it as a field declaration
1977 // with a missing field name and semicolon.
1978 //
1979 _reportErrorForToken(ParserErrorCode.EXPECTED_CLASS_MEMBER, _currentToken, []);
1980 try {
1981 _lockErrorListener();
1982 return _parseInitializedIdentifierList(commentAndMetadata, modifiers.sta ticKeyword, _validateModifiersForField(modifiers), type);
1983 } finally {
1984 _unlockErrorListener();
1985 }
1986 } else if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
1987 SimpleIdentifier methodName = parseSimpleIdentifier();
1988 FormalParameterList parameters = parseFormalParameterList();
1989 if (methodName.name == className) {
1990 _reportErrorForNode(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, type, []);
1991 return _parseConstructor(commentAndMetadata, modifiers.externalKeyword, _validateModifiersForConstructor(modifiers), modifiers.factoryKeyword, methodNam e, null, null, parameters);
1992 }
1993 _validateModifiersForGetterOrSetterOrMethod(modifiers);
1994 _validateFormalParameterList(parameters);
1995 return _parseMethodDeclarationAfterParameters(commentAndMetadata, modifier s.externalKeyword, modifiers.staticKeyword, type, methodName, parameters);
1996 } else if (_tokenMatches(_peek(), TokenType.OPEN_CURLY_BRACKET)) {
1997 // We have found "TypeName identifier {", and are guessing that this is a getter without the
1998 // keyword 'get'.
1999 _validateModifiersForGetterOrSetterOrMethod(modifiers);
2000 _reportErrorForCurrentToken(ParserErrorCode.MISSING_GET, []);
2001 _currentToken = _injectToken(new Parser_SyntheticKeywordToken(Keyword.GET, _currentToken.offset));
2002 return _parseGetter(commentAndMetadata, modifiers.externalKeyword, modifie rs.staticKeyword, type);
2003 }
2004 return _parseInitializedIdentifierList(commentAndMetadata, modifiers.staticK eyword, _validateModifiersForField(modifiers), type);
2005 }
2006
2007 /**
2008 * Parse a compilation unit.
2009 *
2010 * Specified:
2011 *
2012 * <pre>
2013 * compilationUnit ::=
2014 * scriptTag? directive* topLevelDeclaration*
2015 * </pre>
2016 * Actual:
2017 *
2018 * <pre>
2019 * compilationUnit ::=
2020 * scriptTag? topLevelElement*
2021 *
2022 * topLevelElement ::=
2023 * directive
2024 * | topLevelDeclaration
2025 * </pre>
2026 *
2027 * @return the compilation unit that was parsed
2028 */
2029 CompilationUnit parseCompilationUnit2() {
2030 Token firstToken = _currentToken;
2031 ScriptTag scriptTag = null;
2032 if (_matches(TokenType.SCRIPT_TAG)) {
2033 scriptTag = new ScriptTag(andAdvance);
2034 }
2035 //
2036 // Even though all directives must appear before declarations and must occur in a given order,
2037 // we allow directives and declarations to occur in any order so that we can recover better.
2038 //
2039 bool libraryDirectiveFound = false;
2040 bool partOfDirectiveFound = false;
2041 bool partDirectiveFound = false;
2042 bool directiveFoundAfterDeclaration = false;
2043 List<Directive> directives = new List<Directive>();
2044 List<CompilationUnitMember> declarations = new List<CompilationUnitMember>() ;
2045 Token memberStart = _currentToken;
2046 while (!_matches(TokenType.EOF)) {
2047 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
2048 if ((_matchesKeyword(Keyword.IMPORT) || _matchesKeyword(Keyword.EXPORT) || _matchesKeyword(Keyword.LIBRARY) || _matchesKeyword(Keyword.PART)) && !_tokenMa tches(_peek(), TokenType.PERIOD) && !_tokenMatches(_peek(), TokenType.LT) && !_t okenMatches(_peek(), TokenType.OPEN_PAREN)) {
2049 Directive directive = _parseDirective(commentAndMetadata);
2050 if (declarations.length > 0 && !directiveFoundAfterDeclaration) {
2051 _reportErrorForCurrentToken(ParserErrorCode.DIRECTIVE_AFTER_DECLARATIO N, []);
2052 directiveFoundAfterDeclaration = true;
2053 }
2054 if (directive is LibraryDirective) {
2055 if (libraryDirectiveFound) {
2056 _reportErrorForCurrentToken(ParserErrorCode.MULTIPLE_LIBRARY_DIRECTI VES, []);
2057 } else {
2058 if (directives.length > 0) {
2059 _reportErrorForToken(ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST, directive.libraryToken, []);
2060 }
2061 libraryDirectiveFound = true;
2062 }
2063 } else if (directive is PartDirective) {
2064 partDirectiveFound = true;
2065 } else if (partDirectiveFound) {
2066 if (directive is ExportDirective) {
2067 _reportErrorForToken(ParserErrorCode.EXPORT_DIRECTIVE_AFTER_PART_DIR ECTIVE, directive.keyword, []);
2068 } else if (directive is ImportDirective) {
2069 _reportErrorForToken(ParserErrorCode.IMPORT_DIRECTIVE_AFTER_PART_DIR ECTIVE, directive.keyword, []);
2070 }
2071 }
2072 if (directive is PartOfDirective) {
2073 if (partOfDirectiveFound) {
2074 _reportErrorForCurrentToken(ParserErrorCode.MULTIPLE_PART_OF_DIRECTI VES, []);
2075 } else {
2076 int directiveCount = directives.length;
2077 for (int i = 0; i < directiveCount; i++) {
2078 _reportErrorForToken(ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART , directives[i].keyword, []);
2079 }
2080 partOfDirectiveFound = true;
2081 }
2082 } else {
2083 if (partOfDirectiveFound) {
2084 _reportErrorForToken(ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART, directive.keyword, []);
2085 }
2086 }
2087 directives.add(directive);
2088 } else if (_matches(TokenType.SEMICOLON)) {
2089 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_ currentToken.lexeme]);
2090 _advance();
2091 } else {
2092 CompilationUnitMember member = _parseCompilationUnitMember(commentAndMet adata);
2093 if (member != null) {
2094 declarations.add(member);
2095 }
2096 }
2097 if (identical(_currentToken, memberStart)) {
2098 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_ currentToken.lexeme]);
2099 _advance();
2100 while (!_matches(TokenType.EOF) && !_couldBeStartOfCompilationUnitMember ()) {
2101 _advance();
2102 }
2103 }
2104 memberStart = _currentToken;
2105 }
2106 return new CompilationUnit(firstToken, scriptTag, directives, declarations, _currentToken);
2107 }
2108
2109 /**
2110 * Parse a conditional expression.
2111 *
2112 * <pre>
2113 * conditionalExpression ::=
2114 * logicalOrExpression ('?' expressionWithoutCascade ':' expressionWithout Cascade)?
2115 * </pre>
2116 *
2117 * @return the conditional expression that was parsed
2118 */
2119 Expression parseConditionalExpression() {
2120 Expression condition = parseLogicalOrExpression();
2121 if (!_matches(TokenType.QUESTION)) {
2122 return condition;
2123 }
2124 Token question = andAdvance;
2125 Expression thenExpression = parseExpressionWithoutCascade();
2126 Token colon = _expect(TokenType.COLON);
2127 Expression elseExpression = parseExpressionWithoutCascade();
2128 return new ConditionalExpression(condition, question, thenExpression, colon, elseExpression);
2129 }
2130
2131 /**
2132 * Parse the name of a constructor.
2133 *
2134 * <pre>
2135 * constructorName:
2136 * type ('.' identifier)?
2137 * </pre>
2138 *
2139 * @return the constructor name that was parsed
2140 */
2141 ConstructorName parseConstructorName() {
2142 TypeName type = parseTypeName();
2143 Token period = null;
2144 SimpleIdentifier name = null;
2145 if (_matches(TokenType.PERIOD)) {
2146 period = andAdvance;
2147 name = parseSimpleIdentifier();
2148 }
2149 return new ConstructorName(type, period, name);
2150 }
2151
2152 /**
2153 * Parse an expression that might contain a cascade.
2154 *
2155 * <pre>
2156 * expression ::=
2157 * assignableExpression assignmentOperator expression
2158 * | conditionalExpression cascadeSection*
2159 * | throwExpression
2160 * </pre>
2161 *
2162 * @return the expression that was parsed
2163 */
2164 Expression parseExpression2() {
2165 if (_matchesKeyword(Keyword.THROW)) {
2166 return _parseThrowExpression();
2167 } else if (_matchesKeyword(Keyword.RETHROW)) {
2168 // TODO(brianwilkerson) Rethrow is a statement again.
2169 return _parseRethrowExpression();
2170 }
2171 //
2172 // assignableExpression is a subset of conditionalExpression, so we can pars e a conditional
2173 // expression and then determine whether it is followed by an assignmentOper ator, checking for
2174 // conformance to the restricted grammar after making that determination.
2175 //
2176 Expression expression = parseConditionalExpression();
2177 TokenType tokenType = _currentToken.type;
2178 if (tokenType == TokenType.PERIOD_PERIOD) {
2179 List<Expression> cascadeSections = new List<Expression>();
2180 while (tokenType == TokenType.PERIOD_PERIOD) {
2181 Expression section = _parseCascadeSection();
2182 if (section != null) {
2183 cascadeSections.add(section);
2184 }
2185 tokenType = _currentToken.type;
2186 }
2187 return new CascadeExpression(expression, cascadeSections);
2188 } else if (tokenType.isAssignmentOperator) {
2189 Token operator = andAdvance;
2190 _ensureAssignable(expression);
2191 return new AssignmentExpression(expression, operator, parseExpression2());
2192 }
2193 return expression;
2194 }
2195
2196 /**
2197 * Parse an expression that does not contain any cascades.
2198 *
2199 * <pre>
2200 * expressionWithoutCascade ::=
2201 * assignableExpression assignmentOperator expressionWithoutCascade
2202 * | conditionalExpression
2203 * | throwExpressionWithoutCascade
2204 * </pre>
2205 *
2206 * @return the expression that was parsed
2207 */
2208 Expression parseExpressionWithoutCascade() {
2209 if (_matchesKeyword(Keyword.THROW)) {
2210 return _parseThrowExpressionWithoutCascade();
2211 } else if (_matchesKeyword(Keyword.RETHROW)) {
2212 return _parseRethrowExpression();
2213 }
2214 //
2215 // assignableExpression is a subset of conditionalExpression, so we can pars e a conditional
2216 // expression and then determine whether it is followed by an assignmentOper ator, checking for
2217 // conformance to the restricted grammar after making that determination.
2218 //
2219 Expression expression = parseConditionalExpression();
2220 if (_currentToken.type.isAssignmentOperator) {
2221 Token operator = andAdvance;
2222 _ensureAssignable(expression);
2223 expression = new AssignmentExpression(expression, operator, parseExpressio nWithoutCascade());
2224 }
2225 return expression;
2226 }
2227
2228 /**
2229 * Parse a class extends clause.
2230 *
2231 * <pre>
2232 * classExtendsClause ::=
2233 * 'extends' type
2234 * </pre>
2235 *
2236 * @return the class extends clause that was parsed
2237 */
2238 ExtendsClause parseExtendsClause() {
2239 Token keyword = _expectKeyword(Keyword.EXTENDS);
2240 TypeName superclass = parseTypeName();
2241 return new ExtendsClause(keyword, superclass);
2242 }
2243
2244 /**
2245 * Parse a list of formal parameters.
2246 *
2247 * <pre>
2248 * formalParameterList ::=
2249 * '(' ')'
2250 * | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
2251 * | '(' optionalFormalParameters ')'
2252 *
2253 * normalFormalParameters ::=
2254 * normalFormalParameter (',' normalFormalParameter)*
2255 *
2256 * optionalFormalParameters ::=
2257 * optionalPositionalFormalParameters
2258 * | namedFormalParameters
2259 *
2260 * optionalPositionalFormalParameters ::=
2261 * '[' defaultFormalParameter (',' defaultFormalParameter)* ']'
2262 *
2263 * namedFormalParameters ::=
2264 * '{' defaultNamedParameter (',' defaultNamedParameter)* '}'
2265 * </pre>
2266 *
2267 * @return the formal parameters that were parsed
2268 */
2269 FormalParameterList parseFormalParameterList() {
2270 Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
2271 if (_matches(TokenType.CLOSE_PAREN)) {
2272 return new FormalParameterList(leftParenthesis, null, null, null, andAdvan ce);
2273 }
2274 //
2275 // Even though it is invalid to have default parameters outside of brackets, required parameters
2276 // inside of brackets, or multiple groups of default and named parameters, w e allow all of these
2277 // cases so that we can recover better.
2278 //
2279 List<FormalParameter> parameters = new List<FormalParameter>();
2280 List<FormalParameter> normalParameters = new List<FormalParameter>();
2281 List<FormalParameter> positionalParameters = new List<FormalParameter>();
2282 List<FormalParameter> namedParameters = new List<FormalParameter>();
2283 List<FormalParameter> currentParameters = normalParameters;
2284 Token leftSquareBracket = null;
2285 Token rightSquareBracket = null;
2286 Token leftCurlyBracket = null;
2287 Token rightCurlyBracket = null;
2288 ParameterKind kind = ParameterKind.REQUIRED;
2289 bool firstParameter = true;
2290 bool reportedMuliplePositionalGroups = false;
2291 bool reportedMulipleNamedGroups = false;
2292 bool reportedMixedGroups = false;
2293 bool wasOptionalParameter = false;
2294 Token initialToken = null;
2295 do {
2296 if (firstParameter) {
2297 firstParameter = false;
2298 } else if (!_optional(TokenType.COMMA)) {
2299 // TODO(brianwilkerson) The token is wrong, we need to recover from this case.
2300 if (_getEndToken(leftParenthesis) != null) {
2301 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TOKEN, [TokenType .COMMA.lexeme]);
2302 } else {
2303 _reportErrorForToken(ParserErrorCode.MISSING_CLOSING_PARENTHESIS, _cur rentToken.previous, []);
2304 break;
2305 }
2306 }
2307 initialToken = _currentToken;
2308 //
2309 // Handle the beginning of parameter groups.
2310 //
2311 if (_matches(TokenType.OPEN_SQUARE_BRACKET)) {
2312 wasOptionalParameter = true;
2313 if (leftSquareBracket != null && !reportedMuliplePositionalGroups) {
2314 _reportErrorForCurrentToken(ParserErrorCode.MULTIPLE_POSITIONAL_PARAME TER_GROUPS, []);
2315 reportedMuliplePositionalGroups = true;
2316 }
2317 if (leftCurlyBracket != null && !reportedMixedGroups) {
2318 _reportErrorForCurrentToken(ParserErrorCode.MIXED_PARAMETER_GROUPS, [] );
2319 reportedMixedGroups = true;
2320 }
2321 leftSquareBracket = andAdvance;
2322 currentParameters = positionalParameters;
2323 kind = ParameterKind.POSITIONAL;
2324 } else if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
2325 wasOptionalParameter = true;
2326 if (leftCurlyBracket != null && !reportedMulipleNamedGroups) {
2327 _reportErrorForCurrentToken(ParserErrorCode.MULTIPLE_NAMED_PARAMETER_G ROUPS, []);
2328 reportedMulipleNamedGroups = true;
2329 }
2330 if (leftSquareBracket != null && !reportedMixedGroups) {
2331 _reportErrorForCurrentToken(ParserErrorCode.MIXED_PARAMETER_GROUPS, [] );
2332 reportedMixedGroups = true;
2333 }
2334 leftCurlyBracket = andAdvance;
2335 currentParameters = namedParameters;
2336 kind = ParameterKind.NAMED;
2337 }
2338 //
2339 // Parse and record the parameter.
2340 //
2341 FormalParameter parameter = _parseFormalParameter(kind);
2342 parameters.add(parameter);
2343 currentParameters.add(parameter);
2344 if (kind == ParameterKind.REQUIRED && wasOptionalParameter) {
2345 _reportErrorForNode(ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS, p arameter, []);
2346 }
2347 //
2348 // Handle the end of parameter groups.
2349 //
2350 // TODO(brianwilkerson) Improve the detection and reporting of missing and mismatched delimiters.
2351 if (_matches(TokenType.CLOSE_SQUARE_BRACKET)) {
2352 rightSquareBracket = andAdvance;
2353 currentParameters = normalParameters;
2354 if (leftSquareBracket == null) {
2355 if (leftCurlyBracket != null) {
2356 _reportErrorForCurrentToken(ParserErrorCode.WRONG_TERMINATOR_FOR_PAR AMETER_GROUP, ["}"]);
2357 rightCurlyBracket = rightSquareBracket;
2358 rightSquareBracket = null;
2359 } else {
2360 _reportErrorForCurrentToken(ParserErrorCode.UNEXPECTED_TERMINATOR_FO R_PARAMETER_GROUP, ["["]);
2361 }
2362 }
2363 kind = ParameterKind.REQUIRED;
2364 } else if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
2365 rightCurlyBracket = andAdvance;
2366 currentParameters = normalParameters;
2367 if (leftCurlyBracket == null) {
2368 if (leftSquareBracket != null) {
2369 _reportErrorForCurrentToken(ParserErrorCode.WRONG_TERMINATOR_FOR_PAR AMETER_GROUP, ["]"]);
2370 rightSquareBracket = rightCurlyBracket;
2371 rightCurlyBracket = null;
2372 } else {
2373 _reportErrorForCurrentToken(ParserErrorCode.UNEXPECTED_TERMINATOR_FO R_PARAMETER_GROUP, ["{"]);
2374 }
2375 }
2376 kind = ParameterKind.REQUIRED;
2377 }
2378 } while (!_matches(TokenType.CLOSE_PAREN) && !identical(initialToken, _curre ntToken));
2379 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
2380 //
2381 // Check that the groups were closed correctly.
2382 //
2383 if (leftSquareBracket != null && rightSquareBracket == null) {
2384 _reportErrorForCurrentToken(ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMET ER_GROUP, ["]"]);
2385 }
2386 if (leftCurlyBracket != null && rightCurlyBracket == null) {
2387 _reportErrorForCurrentToken(ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMET ER_GROUP, ["}"]);
2388 }
2389 //
2390 // Build the parameter list.
2391 //
2392 if (leftSquareBracket == null) {
2393 leftSquareBracket = leftCurlyBracket;
2394 }
2395 if (rightSquareBracket == null) {
2396 rightSquareBracket = rightCurlyBracket;
2397 }
2398 return new FormalParameterList(leftParenthesis, parameters, leftSquareBracke t, rightSquareBracket, rightParenthesis);
2399 }
2400
2401 /**
2402 * Parse a function expression.
2403 *
2404 * <pre>
2405 * functionExpression ::=
2406 * formalParameterList functionExpressionBody
2407 * </pre>
2408 *
2409 * @return the function expression that was parsed
2410 */
2411 FunctionExpression parseFunctionExpression() {
2412 FormalParameterList parameters = parseFormalParameterList();
2413 _validateFormalParameterList(parameters);
2414 FunctionBody body = _parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTI ON_BODY, true);
2415 return new FunctionExpression(parameters, body);
2416 }
2417
2418 /**
2419 * Parse an implements clause.
2420 *
2421 * <pre>
2422 * implementsClause ::=
2423 * 'implements' type (',' type)*
2424 * </pre>
2425 *
2426 * @return the implements clause that was parsed
2427 */
2428 ImplementsClause parseImplementsClause() {
2429 Token keyword = _expectKeyword(Keyword.IMPLEMENTS);
2430 List<TypeName> interfaces = new List<TypeName>();
2431 interfaces.add(parseTypeName());
2432 while (_optional(TokenType.COMMA)) {
2433 interfaces.add(parseTypeName());
2434 }
2435 return new ImplementsClause(keyword, interfaces);
2436 }
2437
2438 /**
2439 * Parse a label.
2440 *
2441 * <pre>
2442 * label ::=
2443 * identifier ':'
2444 * </pre>
2445 *
2446 * @return the label that was parsed
2447 */
2448 Label parseLabel() {
2449 SimpleIdentifier label = parseSimpleIdentifier();
2450 Token colon = _expect(TokenType.COLON);
2451 return new Label(label, colon);
2452 }
2453
2454 /**
2455 * Parse a library identifier.
2456 *
2457 * <pre>
2458 * libraryIdentifier ::=
2459 * identifier ('.' identifier)*
2460 * </pre>
2461 *
2462 * @return the library identifier that was parsed
2463 */
2464 LibraryIdentifier parseLibraryIdentifier() {
2465 List<SimpleIdentifier> components = new List<SimpleIdentifier>();
2466 components.add(parseSimpleIdentifier());
2467 while (_matches(TokenType.PERIOD)) {
2468 _advance();
2469 components.add(parseSimpleIdentifier());
2470 }
2471 return new LibraryIdentifier(components);
2472 }
2473
2474 /**
2475 * Parse a logical or expression.
2476 *
2477 * <pre>
2478 * logicalOrExpression ::=
2479 * logicalAndExpression ('||' logicalAndExpression)*
2480 * </pre>
2481 *
2482 * @return the logical or expression that was parsed
2483 */
2484 Expression parseLogicalOrExpression() {
2485 Expression expression = _parseLogicalAndExpression();
2486 while (_matches(TokenType.BAR_BAR)) {
2487 Token operator = andAdvance;
2488 expression = new BinaryExpression(expression, operator, _parseLogicalAndEx pression());
2489 }
2490 return expression;
2491 }
2492
2493 /**
2494 * Parse a map literal entry.
2495 *
2496 * <pre>
2497 * mapLiteralEntry ::=
2498 * expression ':' expression
2499 * </pre>
2500 *
2501 * @return the map literal entry that was parsed
2502 */
2503 MapLiteralEntry parseMapLiteralEntry() {
2504 Expression key = parseExpression2();
2505 Token separator = _expect(TokenType.COLON);
2506 Expression value = parseExpression2();
2507 return new MapLiteralEntry(key, separator, value);
2508 }
2509
2510 /**
2511 * Parse a normal formal parameter.
2512 *
2513 * <pre>
2514 * normalFormalParameter ::=
2515 * functionSignature
2516 * | fieldFormalParameter
2517 * | simpleFormalParameter
2518 *
2519 * functionSignature:
2520 * metadata returnType? identifier formalParameterList
2521 *
2522 * fieldFormalParameter ::=
2523 * metadata finalConstVarOrType? 'this' '.' identifier
2524 *
2525 * simpleFormalParameter ::=
2526 * declaredIdentifier
2527 * | metadata identifier
2528 * </pre>
2529 *
2530 * @return the normal formal parameter that was parsed
2531 */
2532 NormalFormalParameter parseNormalFormalParameter() {
2533 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
2534 FinalConstVarOrType holder = _parseFinalConstVarOrType(true);
2535 Token thisKeyword = null;
2536 Token period = null;
2537 if (_matchesKeyword(Keyword.THIS)) {
2538 thisKeyword = andAdvance;
2539 period = _expect(TokenType.PERIOD);
2540 }
2541 SimpleIdentifier identifier = parseSimpleIdentifier();
2542 if (_matches(TokenType.OPEN_PAREN)) {
2543 FormalParameterList parameters = parseFormalParameterList();
2544 if (thisKeyword == null) {
2545 if (holder.keyword != null) {
2546 _reportErrorForToken(ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, hol der.keyword, []);
2547 }
2548 return new FunctionTypedFormalParameter(commentAndMetadata.comment, comm entAndMetadata.metadata, holder.type, identifier, parameters);
2549 } else {
2550 return new FieldFormalParameter(commentAndMetadata.comment, commentAndMe tadata.metadata, holder.keyword, holder.type, thisKeyword, period, identifier, p arameters);
2551 }
2552 }
2553 TypeName type = holder.type;
2554 if (type != null) {
2555 if (_tokenMatchesKeyword(type.name.beginToken, Keyword.VOID)) {
2556 _reportErrorForToken(ParserErrorCode.VOID_PARAMETER, type.name.beginToke n, []);
2557 } else if (holder.keyword != null && _tokenMatchesKeyword(holder.keyword, Keyword.VAR)) {
2558 _reportErrorForToken(ParserErrorCode.VAR_AND_TYPE, holder.keyword, []);
2559 }
2560 }
2561 if (thisKeyword != null) {
2562 return new FieldFormalParameter(commentAndMetadata.comment, commentAndMeta data.metadata, holder.keyword, holder.type, thisKeyword, period, identifier, nul l);
2563 }
2564 return new SimpleFormalParameter(commentAndMetadata.comment, commentAndMetad ata.metadata, holder.keyword, holder.type, identifier);
2565 }
2566
2567 /**
2568 * Parse a prefixed identifier.
2569 *
2570 * <pre>
2571 * prefixedIdentifier ::=
2572 * identifier ('.' identifier)?
2573 * </pre>
2574 *
2575 * @return the prefixed identifier that was parsed
2576 */
2577 Identifier parsePrefixedIdentifier() {
2578 SimpleIdentifier qualifier = parseSimpleIdentifier();
2579 if (!_matches(TokenType.PERIOD)) {
2580 return qualifier;
2581 }
2582 Token period = andAdvance;
2583 SimpleIdentifier qualified = parseSimpleIdentifier();
2584 return new PrefixedIdentifier(qualifier, period, qualified);
2585 }
2586
2587 /**
2588 * Parse a return type.
2589 *
2590 * <pre>
2591 * returnType ::=
2592 * 'void'
2593 * | type
2594 * </pre>
2595 *
2596 * @return the return type that was parsed
2597 */
2598 TypeName parseReturnType() {
2599 if (_matchesKeyword(Keyword.VOID)) {
2600 return new TypeName(new SimpleIdentifier(andAdvance), null);
2601 } else {
2602 return parseTypeName();
2603 }
2604 }
2605
2606 /**
2607 * Parse a simple identifier.
2608 *
2609 * <pre>
2610 * identifier ::=
2611 * IDENTIFIER
2612 * </pre>
2613 *
2614 * @return the simple identifier that was parsed
2615 */
2616 SimpleIdentifier parseSimpleIdentifier() {
2617 if (_matchesIdentifier()) {
2618 return new SimpleIdentifier(andAdvance);
2619 }
2620 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER, []);
2621 return _createSyntheticIdentifier();
2622 }
2623
2624 /**
2625 * Parse a statement.
2626 *
2627 * <pre>
2628 * statement ::=
2629 * label* nonLabeledStatement
2630 * </pre>
2631 *
2632 * @return the statement that was parsed
2633 */
2634 Statement parseStatement2() {
2635 List<Label> labels = new List<Label>();
2636 while (_matchesIdentifier() && _tokenMatches(_peek(), TokenType.COLON)) {
2637 labels.add(parseLabel());
2638 }
2639 Statement statement = _parseNonLabeledStatement();
2640 if (labels.isEmpty) {
2641 return statement;
2642 }
2643 return new LabeledStatement(labels, statement);
2644 }
2645
2646 /**
2647 * Parse a string literal.
2648 *
2649 * <pre>
2650 * stringLiteral ::=
2651 * MULTI_LINE_STRING+
2652 * | SINGLE_LINE_STRING+
2653 * </pre>
2654 *
2655 * @return the string literal that was parsed
2656 */
2657 StringLiteral parseStringLiteral() {
2658 List<StringLiteral> strings = new List<StringLiteral>();
2659 while (_matches(TokenType.STRING)) {
2660 Token string = andAdvance;
2661 if (_matches(TokenType.STRING_INTERPOLATION_EXPRESSION) || _matches(TokenT ype.STRING_INTERPOLATION_IDENTIFIER)) {
2662 strings.add(_parseStringInterpolation(string));
2663 } else {
2664 strings.add(new SimpleStringLiteral(string, _computeStringValue(string.l exeme, true, true)));
2665 }
2666 }
2667 if (strings.length < 1) {
2668 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_STRING_LITERAL, []);
2669 return _createSyntheticStringLiteral();
2670 } else if (strings.length == 1) {
2671 return strings[0];
2672 } else {
2673 return new AdjacentStrings(strings);
2674 }
2675 }
2676
2677 /**
2678 * Parse a list of type arguments.
2679 *
2680 * <pre>
2681 * typeArguments ::=
2682 * '<' typeList '>'
2683 *
2684 * typeList ::=
2685 * type (',' type)*
2686 * </pre>
2687 *
2688 * @return the type argument list that was parsed
2689 */
2690 TypeArgumentList parseTypeArgumentList() {
2691 Token leftBracket = _expect(TokenType.LT);
2692 List<TypeName> arguments = new List<TypeName>();
2693 arguments.add(parseTypeName());
2694 while (_optional(TokenType.COMMA)) {
2695 arguments.add(parseTypeName());
2696 }
2697 Token rightBracket = _expectGt();
2698 return new TypeArgumentList(leftBracket, arguments, rightBracket);
2699 }
2700
2701 /**
2702 * Parse a type name.
2703 *
2704 * <pre>
2705 * type ::=
2706 * qualified typeArguments?
2707 * </pre>
2708 *
2709 * @return the type name that was parsed
2710 */
2711 TypeName parseTypeName() {
2712 Identifier typeName;
2713 if (_matchesKeyword(Keyword.VAR)) {
2714 _reportErrorForCurrentToken(ParserErrorCode.VAR_AS_TYPE_NAME, []);
2715 typeName = new SimpleIdentifier(andAdvance);
2716 } else if (_matchesIdentifier()) {
2717 typeName = parsePrefixedIdentifier();
2718 } else {
2719 typeName = _createSyntheticIdentifier();
2720 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TYPE_NAME, []);
2721 }
2722 TypeArgumentList typeArguments = null;
2723 if (_matches(TokenType.LT)) {
2724 typeArguments = parseTypeArgumentList();
2725 }
2726 return new TypeName(typeName, typeArguments);
2727 }
2728
2729 /**
2730 * Parse a type parameter.
2731 *
2732 * <pre>
2733 * typeParameter ::=
2734 * metadata name ('extends' bound)?
2735 * </pre>
2736 *
2737 * @return the type parameter that was parsed
2738 */
2739 TypeParameter parseTypeParameter() {
2740 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
2741 SimpleIdentifier name = parseSimpleIdentifier();
2742 if (_matchesKeyword(Keyword.EXTENDS)) {
2743 Token keyword = andAdvance;
2744 TypeName bound = parseTypeName();
2745 return new TypeParameter(commentAndMetadata.comment, commentAndMetadata.me tadata, name, keyword, bound);
2746 }
2747 return new TypeParameter(commentAndMetadata.comment, commentAndMetadata.meta data, name, null, null);
2748 }
2749
2750 /**
2751 * Parse a list of type parameters.
2752 *
2753 * <pre>
2754 * typeParameterList ::=
2755 * '<' typeParameter (',' typeParameter)* '>'
2756 * </pre>
2757 *
2758 * @return the list of type parameters that were parsed
2759 */
2760 TypeParameterList parseTypeParameterList() {
2761 Token leftBracket = _expect(TokenType.LT);
2762 List<TypeParameter> typeParameters = new List<TypeParameter>();
2763 typeParameters.add(parseTypeParameter());
2764 while (_optional(TokenType.COMMA)) {
2765 typeParameters.add(parseTypeParameter());
2766 }
2767 Token rightBracket = _expectGt();
2768 return new TypeParameterList(leftBracket, typeParameters, rightBracket);
2769 }
2770
2771 /**
2772 * Parse a with clause.
2773 *
2774 * <pre>
2775 * withClause ::=
2776 * 'with' typeName (',' typeName)*
2777 * </pre>
2778 *
2779 * @return the with clause that was parsed
2780 */
2781 WithClause parseWithClause() {
2782 Token with2 = _expectKeyword(Keyword.WITH);
2783 List<TypeName> types = new List<TypeName>();
2784 types.add(parseTypeName());
2785 while (_optional(TokenType.COMMA)) {
2786 types.add(parseTypeName());
2787 }
2788 return new WithClause(with2, types);
2789 }
2790
2791 void set currentToken(Token currentToken) {
2792 this._currentToken = currentToken;
2793 }
2794
2795 /**
2796 * Advance to the next token in the token stream.
2797 */
2798 void _advance() {
2799 _currentToken = _currentToken.next;
2800 }
2801
2802 /**
2803 * Append the character equivalent of the given scalar value to the given buil der. Use the start
2804 * and end indices to report an error, and don't append anything to the builde r, if the scalar
2805 * value is invalid.
2806 *
2807 * @param builder the builder to which the scalar value is to be appended
2808 * @param escapeSequence the escape sequence that was parsed to produce the sc alar value
2809 * @param scalarValue the value to be appended
2810 * @param startIndex the index of the first character representing the scalar value
2811 * @param endIndex the index of the last character representing the scalar val ue
2812 */
2813 void _appendScalarValue(JavaStringBuilder builder, String escapeSequence, int scalarValue, int startIndex, int endIndex) {
2814 if (scalarValue < 0 || scalarValue > Character.MAX_CODE_POINT || (scalarValu e >= 0xD800 && scalarValue <= 0xDFFF)) {
2815 _reportErrorForCurrentToken(ParserErrorCode.INVALID_CODE_POINT, [escapeSeq uence]);
2816 return;
2817 }
2818 if (scalarValue < Character.MAX_VALUE) {
2819 builder.appendChar(scalarValue);
2820 } else {
2821 builder.append(Character.toChars(scalarValue));
2822 }
2823 }
2824
2825 /**
2826 * Compute the content of a string with the given literal representation.
2827 *
2828 * @param lexeme the literal representation of the string
2829 * @param first `true` if this is the first token in a string literal
2830 * @param last `true` if this is the last token in a string literal
2831 * @return the actual value of the string
2832 */
2833 String _computeStringValue(String lexeme, bool first, bool last) {
2834 bool isRaw = false;
2835 int start = 0;
2836 if (first) {
2837 if (StringUtilities.startsWith4(lexeme, 0, 0x72, 0x22, 0x22, 0x22) || Stri ngUtilities.startsWith4(lexeme, 0, 0x72, 0x27, 0x27, 0x27)) {
2838 isRaw = true;
2839 start += 4;
2840 } else if (StringUtilities.startsWith2(lexeme, 0, 0x72, 0x22) || StringUti lities.startsWith2(lexeme, 0, 0x72, 0x27)) {
2841 isRaw = true;
2842 start += 2;
2843 } else if (StringUtilities.startsWith3(lexeme, 0, 0x22, 0x22, 0x22) || Str ingUtilities.startsWith3(lexeme, 0, 0x27, 0x27, 0x27)) {
2844 start += 3;
2845 } else if (StringUtilities.startsWithChar(lexeme, 0x22) || StringUtilities .startsWithChar(lexeme, 0x27)) {
2846 start += 1;
2847 }
2848 }
2849 int end = lexeme.length;
2850 if (last) {
2851 if (StringUtilities.endsWith3(lexeme, 0x22, 0x22, 0x22) || StringUtilities .endsWith3(lexeme, 0x27, 0x27, 0x27)) {
2852 end -= 3;
2853 } else if (StringUtilities.endsWithChar(lexeme, 0x22) || StringUtilities.e ndsWithChar(lexeme, 0x27)) {
2854 end -= 1;
2855 }
2856 }
2857 if (end - start + 1 < 0) {
2858 AnalysisEngine.instance.logger.logError("Internal error: computeStringValu e(${lexeme}, ${first}, ${last})");
2859 return "";
2860 }
2861 if (isRaw) {
2862 return lexeme.substring(start, end);
2863 }
2864 JavaStringBuilder builder = new JavaStringBuilder();
2865 int index = start;
2866 while (index < end) {
2867 index = _translateCharacter(builder, lexeme, index);
2868 }
2869 return builder.toString();
2870 }
2871
2872 /**
2873 * Convert the given method declaration into the nearest valid top-level funct ion declaration.
2874 *
2875 * @param method the method to be converted
2876 * @return the function declaration that most closely captures the components of the given method
2877 * declaration
2878 */
2879 FunctionDeclaration _convertToFunctionDeclaration(MethodDeclaration method) => new FunctionDeclaration(method.documentationComment, method.metadata, method.ex ternalKeyword, method.returnType, method.propertyKeyword, method.name, new Funct ionExpression(method.parameters, method.body));
2880
2881 /**
2882 * Return `true` if the current token could be the start of a compilation unit member. This
2883 * method is used for recovery purposes to decide when to stop skipping tokens after finding an
2884 * error while parsing a compilation unit member.
2885 *
2886 * @return `true` if the current token could be the start of a compilation uni t member
2887 */
2888 bool _couldBeStartOfCompilationUnitMember() {
2889 if ((_matchesKeyword(Keyword.IMPORT) || _matchesKeyword(Keyword.EXPORT) || _ matchesKeyword(Keyword.LIBRARY) || _matchesKeyword(Keyword.PART)) && !_tokenMatc hes(_peek(), TokenType.PERIOD) && !_tokenMatches(_peek(), TokenType.LT)) {
2890 // This looks like the start of a directive
2891 return true;
2892 } else if (_matchesKeyword(Keyword.CLASS)) {
2893 // This looks like the start of a class definition
2894 return true;
2895 } else if (_matchesKeyword(Keyword.TYPEDEF) && !_tokenMatches(_peek(), Token Type.PERIOD) && !_tokenMatches(_peek(), TokenType.LT)) {
2896 // This looks like the start of a typedef
2897 return true;
2898 } else if (_matchesKeyword(Keyword.VOID) || ((_matchesKeyword(Keyword.GET) | | _matchesKeyword(Keyword.SET)) && _tokenMatchesIdentifier(_peek())) || (_matche sKeyword(Keyword.OPERATOR) && _isOperator(_peek()))) {
2899 // This looks like the start of a function
2900 return true;
2901 } else if (_matchesIdentifier()) {
2902 if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
2903 // This looks like the start of a function
2904 return true;
2905 }
2906 Token token = _skipReturnType(_currentToken);
2907 if (token == null) {
2908 return false;
2909 }
2910 if (_matchesKeyword(Keyword.GET) || _matchesKeyword(Keyword.SET) || (_matc hesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) || _matchesIdentifier()) {
2911 return true;
2912 }
2913 }
2914 return false;
2915 }
2916
2917 /**
2918 * Create a synthetic identifier.
2919 *
2920 * @return the synthetic identifier that was created
2921 */
2922 SimpleIdentifier _createSyntheticIdentifier() {
2923 Token syntheticToken;
2924 if (_currentToken.type == TokenType.KEYWORD) {
2925 // Consider current keyword token as an identifier.
2926 // It is not always true, e.g. "^is T" where "^" is place the place for sy nthetic identifier.
2927 // By creating SyntheticStringToken we can distinguish a real identifier f rom synthetic.
2928 // In the code completion behavior will depend on a cursor position - befo re or on "is".
2929 syntheticToken = _injectToken(new SyntheticStringToken(TokenType.IDENTIFIE R, _currentToken.lexeme, _currentToken.offset));
2930 } else {
2931 syntheticToken = _createSyntheticToken(TokenType.IDENTIFIER);
2932 }
2933 return new SimpleIdentifier(syntheticToken);
2934 }
2935
2936 /**
2937 * Create a synthetic token representing the given keyword.
2938 *
2939 * @return the synthetic token that was created
2940 */
2941 Token _createSyntheticKeyword(Keyword keyword) => _injectToken(new Parser_Synt heticKeywordToken(keyword, _currentToken.offset));
2942
2943 /**
2944 * Create a synthetic string literal.
2945 *
2946 * @return the synthetic string literal that was created
2947 */
2948 SimpleStringLiteral _createSyntheticStringLiteral() => new SimpleStringLiteral (_createSyntheticToken(TokenType.STRING), "");
2949
2950 /**
2951 * Create a synthetic token with the given type.
2952 *
2953 * @return the synthetic token that was created
2954 */
2955 Token _createSyntheticToken(TokenType type) => _injectToken(new StringToken(ty pe, "", _currentToken.offset));
2956
2957 /**
2958 * Check that the given expression is assignable and report an error if it isn 't.
2959 *
2960 * <pre>
2961 * assignableExpression ::=
2962 * primary (arguments* assignableSelector)+
2963 * | 'super' assignableSelector
2964 * | identifier
2965 *
2966 * assignableSelector ::=
2967 * '[' expression ']'
2968 * | '.' identifier
2969 * </pre>
2970 *
2971 * @param expression the expression being checked
2972 */
2973 void _ensureAssignable(Expression expression) {
2974 if (expression != null && !expression.isAssignable) {
2975 _reportErrorForCurrentToken(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSI GNABLE, []);
2976 }
2977 }
2978
2979 /**
2980 * If the current token has the expected type, return it after advancing to th e next token.
2981 * Otherwise report an error and return the current token without advancing. N ote that the method
2982 * [expectGt] should be used if the argument to this method would be [TokenTyp e#GT]
2983 * .
2984 *
2985 * @param type the type of token that is expected
2986 * @return the token that matched the given type
2987 */
2988 Token _expect(TokenType type) {
2989 if (_matches(type)) {
2990 return andAdvance;
2991 }
2992 // Remove uses of this method in favor of matches?
2993 // Pass in the error code to use to report the error?
2994 if (type == TokenType.SEMICOLON) {
2995 _reportErrorForToken(ParserErrorCode.EXPECTED_TOKEN, _currentToken.previou s, [type.lexeme]);
2996 } else {
2997 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TOKEN, [type.lexeme]) ;
2998 }
2999 return _currentToken;
3000 }
3001
3002 /**
3003 * If the current token has the type [TokenType#GT], return it after advancing to the next
3004 * token. Otherwise report an error and return the current token without advan cing.
3005 *
3006 * @return the token that matched the given type
3007 */
3008 Token _expectGt() {
3009 if (_matchesGt()) {
3010 return andAdvance;
3011 }
3012 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TOKEN, [TokenType.GT.le xeme]);
3013 return _currentToken;
3014 }
3015
3016 /**
3017 * If the current token is a keyword matching the given string, return it afte r advancing to the
3018 * next token. Otherwise report an error and return the current token without advancing.
3019 *
3020 * @param keyword the keyword that is expected
3021 * @return the token that matched the given type
3022 */
3023 Token _expectKeyword(Keyword keyword) {
3024 if (_matchesKeyword(keyword)) {
3025 return andAdvance;
3026 }
3027 // Remove uses of this method in favor of matches?
3028 // Pass in the error code to use to report the error?
3029 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TOKEN, [keyword.syntax] );
3030 return _currentToken;
3031 }
3032
3033 /**
3034 * If [currentToken] is a semicolon, returns it; otherwise reports error and c reates a
3035 * synthetic one.
3036 *
3037 * TODO(scheglov) consider pushing this into [expect]
3038 */
3039 Token _expectSemicolon() {
3040 if (_matches(TokenType.SEMICOLON)) {
3041 return andAdvance;
3042 } else {
3043 _reportErrorForToken(ParserErrorCode.EXPECTED_TOKEN, _currentToken.previou s, [";"]);
3044 return _createSyntheticToken(TokenType.SEMICOLON);
3045 }
3046 }
3047
3048 /**
3049 * Search the given list of ranges for a range that contains the given index. Return the range
3050 * that was found, or `null` if none of the ranges contain the index.
3051 *
3052 * @param ranges the ranges to be searched
3053 * @param index the index contained in the returned range
3054 * @return the range that was found
3055 */
3056 List<int> _findRange(List<List<int>> ranges, int index) {
3057 int rangeCount = ranges.length;
3058 for (int i = 0; i < rangeCount; i++) {
3059 List<int> range = ranges[i];
3060 if (range[0] <= index && index <= range[1]) {
3061 return range;
3062 } else if (index < range[0]) {
3063 return null;
3064 }
3065 }
3066 return null;
3067 }
3068
3069 /**
3070 * Advance to the next token in the token stream, making it the new current to ken.
3071 *
3072 * @return the token that was current before this method was invoked
3073 */
3074 Token get andAdvance {
3075 Token token = _currentToken;
3076 _advance();
3077 return token;
3078 }
3079
3080 /**
3081 * Return a list of the ranges of characters in the given comment string that should be treated as
3082 * code blocks.
3083 *
3084 * @param comment the comment being processed
3085 * @return the ranges of characters that should be treated as code blocks
3086 */
3087 List<List<int>> _getCodeBlockRanges(String comment) {
3088 List<List<int>> ranges = new List<List<int>>();
3089 int length = comment.length;
3090 if (length < 3) {
3091 return ranges;
3092 }
3093 int index = 0;
3094 int firstChar = comment.codeUnitAt(0);
3095 if (firstChar == 0x2F) {
3096 int secondChar = comment.codeUnitAt(1);
3097 int thirdChar = comment.codeUnitAt(2);
3098 if ((secondChar == 0x2A && thirdChar == 0x2A) || (secondChar == 0x2F && th irdChar == 0x2F)) {
3099 index = 3;
3100 }
3101 }
3102 while (index < length) {
3103 int currentChar = comment.codeUnitAt(index);
3104 if (currentChar == 0xD || currentChar == 0xA) {
3105 index = index + 1;
3106 while (index < length && Character.isWhitespace(comment.codeUnitAt(index ))) {
3107 index = index + 1;
3108 }
3109 if (StringUtilities.startsWith6(comment, index, 0x2A, 0x20, 0x20, 0x20, 0x20, 0x20)) {
3110 int end = index + 6;
3111 while (end < length && comment.codeUnitAt(end) != 0xD && comment.codeU nitAt(end) != 0xA) {
3112 end = end + 1;
3113 }
3114 ranges.add(<int> [index, end]);
3115 index = end;
3116 }
3117 } else if (index + 1 < length && currentChar == 0x5B && comment.codeUnitAt (index + 1) == 0x3A) {
3118 int end = StringUtilities.indexOf2(comment, index + 2, 0x3A, 0x5D);
3119 if (end < 0) {
3120 end = length;
3121 }
3122 ranges.add(<int> [index, end]);
3123 index = end + 1;
3124 } else {
3125 index = index + 1;
3126 }
3127 }
3128 return ranges;
3129 }
3130
3131 /**
3132 * Return the end token associated with the given begin token, or `null` if ei ther the given
3133 * token is not a begin token or it does not have an end token associated with it.
3134 *
3135 * @param beginToken the token that is expected to have an end token associate d with it
3136 * @return the end token associated with the begin token
3137 */
3138 Token _getEndToken(Token beginToken) {
3139 if (beginToken is BeginToken) {
3140 return beginToken.endToken;
3141 }
3142 return null;
3143 }
3144
3145 /**
3146 * Return `true` if the current token is the first token of a return type that is followed
3147 * by an identifier, possibly followed by a list of type parameters, followed by a
3148 * left-parenthesis. This is used by parseTypeAlias to determine whether or no t to parse a return
3149 * type.
3150 *
3151 * @return `true` if we can successfully parse the rest of a type alias if we first parse a
3152 * return type.
3153 */
3154 bool get hasReturnTypeInTypeAlias {
3155 Token next = _skipReturnType(_currentToken);
3156 if (next == null) {
3157 return false;
3158 }
3159 return _tokenMatchesIdentifier(next);
3160 }
3161
3162 /**
3163 * Inject the given token into the token stream immediately before the current token.
3164 *
3165 * @param token the token to be added to the token stream
3166 * @return the token that was just added to the token stream
3167 */
3168 Token _injectToken(Token token) {
3169 Token previous = _currentToken.previous;
3170 token.setNext(_currentToken);
3171 previous.setNext(token);
3172 return token;
3173 }
3174
3175 /**
3176 * Return `true` if the current token appears to be the beginning of a functio n declaration.
3177 *
3178 * @return `true` if the current token appears to be the beginning of a functi on declaration
3179 */
3180 bool _isFunctionDeclaration() {
3181 if (_matchesKeyword(Keyword.VOID)) {
3182 return true;
3183 }
3184 Token afterReturnType = _skipTypeName(_currentToken);
3185 if (afterReturnType == null) {
3186 // There was no return type, but it is optional, so go back to where we st arted.
3187 afterReturnType = _currentToken;
3188 }
3189 Token afterIdentifier = _skipSimpleIdentifier(afterReturnType);
3190 if (afterIdentifier == null) {
3191 // It's possible that we parsed the function name as if it were a type nam e, so see whether
3192 // it makes sense if we assume that there is no type.
3193 afterIdentifier = _skipSimpleIdentifier(_currentToken);
3194 }
3195 if (afterIdentifier == null) {
3196 return false;
3197 }
3198 if (_isFunctionExpression(afterIdentifier)) {
3199 return true;
3200 }
3201 // It's possible that we have found a getter. While this isn't valid at this point we test for
3202 // it in order to recover better.
3203 if (_matchesKeyword(Keyword.GET)) {
3204 Token afterName = _skipSimpleIdentifier(_currentToken.next);
3205 if (afterName == null) {
3206 return false;
3207 }
3208 return _tokenMatches(afterName, TokenType.FUNCTION) || _tokenMatches(after Name, TokenType.OPEN_CURLY_BRACKET);
3209 }
3210 return false;
3211 }
3212
3213 /**
3214 * Return `true` if the given token appears to be the beginning of a function expression.
3215 *
3216 * @param startToken the token that might be the start of a function expressio n
3217 * @return `true` if the given token appears to be the beginning of a function expression
3218 */
3219 bool _isFunctionExpression(Token startToken) {
3220 // Function expressions aren't allowed in initializer lists.
3221 if (_inInitializer) {
3222 return false;
3223 }
3224 Token afterParameters = _skipFormalParameterList(startToken);
3225 if (afterParameters == null) {
3226 return false;
3227 }
3228 if (afterParameters.matchesAny([TokenType.OPEN_CURLY_BRACKET, TokenType.FUNC TION])) {
3229 return true;
3230 }
3231 if (_parseAsync) {
3232 String lexeme = afterParameters.lexeme;
3233 return lexeme == ASYNC || lexeme == SYNC;
3234 }
3235 return false;
3236 }
3237
3238 /**
3239 * Return `true` if the given character is a valid hexadecimal digit.
3240 *
3241 * @param character the character being tested
3242 * @return `true` if the character is a valid hexadecimal digit
3243 */
3244 bool _isHexDigit(int character) => (0x30 <= character && character <= 0x39) || (0x41 <= character && character <= 0x46) || (0x61 <= character && character <= 0x66);
3245
3246 /**
3247 * Return `true` if the current token is the first token in an initialized var iable
3248 * declaration rather than an expression. This method assumes that we have alr eady skipped past
3249 * any metadata that might be associated with the declaration.
3250 *
3251 * <pre>
3252 * initializedVariableDeclaration ::=
3253 * declaredIdentifier ('=' expression)? (',' initializedIdentifier)*
3254 *
3255 * declaredIdentifier ::=
3256 * metadata finalConstVarOrType identifier
3257 *
3258 * finalConstVarOrType ::=
3259 * 'final' type?
3260 * | 'const' type?
3261 * | 'var'
3262 * | type
3263 *
3264 * type ::=
3265 * qualified typeArguments?
3266 *
3267 * initializedIdentifier ::=
3268 * identifier ('=' expression)?
3269 * </pre>
3270 *
3271 * @return `true` if the current token is the first token in an initialized va riable
3272 * declaration
3273 */
3274 bool _isInitializedVariableDeclaration() {
3275 if (_matchesKeyword(Keyword.FINAL) || _matchesKeyword(Keyword.VAR)) {
3276 // An expression cannot start with a keyword other than 'const', 'rethrow' , or 'throw'.
3277 return true;
3278 }
3279 if (_matchesKeyword(Keyword.CONST)) {
3280 // Look to see whether we might be at the start of a list or map literal, otherwise this
3281 // should be the start of a variable declaration.
3282 return !_peek().matchesAny([
3283 TokenType.LT,
3284 TokenType.OPEN_CURLY_BRACKET,
3285 TokenType.OPEN_SQUARE_BRACKET,
3286 TokenType.INDEX]);
3287 }
3288 // We know that we have an identifier, and need to see whether it might be a type name.
3289 Token token = _skipTypeName(_currentToken);
3290 if (token == null) {
3291 // There was no type name, so this can't be a declaration.
3292 return false;
3293 }
3294 token = _skipSimpleIdentifier(token);
3295 if (token == null) {
3296 return false;
3297 }
3298 TokenType type = token.type;
3299 return type == TokenType.EQ || type == TokenType.COMMA || type == TokenType. SEMICOLON || _tokenMatchesKeyword(token, Keyword.IN);
3300 }
3301
3302 /**
3303 * Given that we have just found bracketed text within a comment, look to see whether that text is
3304 * (a) followed by a parenthesized link address, (b) followed by a colon, or ( c) followed by
3305 * optional whitespace and another square bracket.
3306 *
3307 * This method uses the syntax described by the <a
3308 * href="http://daringfireball.net/projects/markdown/syntax">markdown</a> proj ect.
3309 *
3310 * @param comment the comment text in which the bracketed text was found
3311 * @param rightIndex the index of the right bracket
3312 * @return `true` if the bracketed text is followed by a link address
3313 */
3314 bool _isLinkText(String comment, int rightIndex) {
3315 int length = comment.length;
3316 int index = rightIndex + 1;
3317 if (index >= length) {
3318 return false;
3319 }
3320 int nextChar = comment.codeUnitAt(index);
3321 if (nextChar == 0x28 || nextChar == 0x3A) {
3322 return true;
3323 }
3324 while (Character.isWhitespace(nextChar)) {
3325 index = index + 1;
3326 if (index >= length) {
3327 return false;
3328 }
3329 nextChar = comment.codeUnitAt(index);
3330 }
3331 return nextChar == 0x5B;
3332 }
3333
3334 /**
3335 * Return `true` if the given token appears to be the beginning of an operator declaration.
3336 *
3337 * @param startToken the token that might be the start of an operator declarat ion
3338 * @return `true` if the given token appears to be the beginning of an operato r declaration
3339 */
3340 bool _isOperator(Token startToken) {
3341 // Accept any operator here, even if it is not user definable.
3342 if (!startToken.isOperator) {
3343 return false;
3344 }
3345 // Token "=" means that it is actually field initializer.
3346 if (startToken.type == TokenType.EQ) {
3347 return false;
3348 }
3349 // Consume all operator tokens.
3350 Token token = startToken.next;
3351 while (token.isOperator) {
3352 token = token.next;
3353 }
3354 // Formal parameter list is expect now.
3355 return _tokenMatches(token, TokenType.OPEN_PAREN);
3356 }
3357
3358 /**
3359 * Return `true` if the current token appears to be the beginning of a switch member.
3360 *
3361 * @return `true` if the current token appears to be the beginning of a switch member
3362 */
3363 bool _isSwitchMember() {
3364 Token token = _currentToken;
3365 while (_tokenMatches(token, TokenType.IDENTIFIER) && _tokenMatches(token.nex t, TokenType.COLON)) {
3366 token = token.next.next;
3367 }
3368 if (token.type == TokenType.KEYWORD) {
3369 Keyword keyword = (token as KeywordToken).keyword;
3370 return keyword == Keyword.CASE || keyword == Keyword.DEFAULT;
3371 }
3372 return false;
3373 }
3374
3375 /**
3376 * Return `true` if the given token appears to be the first token of a type na me that is
3377 * followed by a variable or field formal parameter.
3378 *
3379 * @param startToken the first token of the sequence being checked
3380 * @return `true` if there is a type name and variable starting at the given t oken
3381 */
3382 bool _isTypedIdentifier(Token startToken) {
3383 Token token = _skipReturnType(startToken);
3384 if (token == null) {
3385 return false;
3386 } else if (_tokenMatchesIdentifier(token)) {
3387 return true;
3388 } else if (_tokenMatchesKeyword(token, Keyword.THIS) && _tokenMatches(token. next, TokenType.PERIOD) && _tokenMatchesIdentifier(token.next.next)) {
3389 return true;
3390 }
3391 return false;
3392 }
3393
3394 /**
3395 * Compare the given tokens to find the token that appears first in the source being parsed. That
3396 * is, return the left-most of all of the tokens. The arguments are allowed to be `null`.
3397 * Return the token with the smallest offset, or `null` if there are no argume nts or if all
3398 * of the arguments are `null`.
3399 *
3400 * @param tokens the tokens being compared
3401 * @return the token with the smallest offset
3402 */
3403 Token _lexicallyFirst(List<Token> tokens) {
3404 Token first = null;
3405 int firstOffset = 2147483647;
3406 for (Token token in tokens) {
3407 if (token != null) {
3408 int offset = token.offset;
3409 if (offset < firstOffset) {
3410 first = token;
3411 firstOffset = offset;
3412 }
3413 }
3414 }
3415 return first;
3416 }
3417
3418 /**
3419 * Increments the error reporting lock level. If level is more than `0`, then
3420 * [reportError] wont report any error.
3421 */
3422 void _lockErrorListener() {
3423 _errorListenerLock++;
3424 }
3425
3426 /**
3427 * Return `true` if the current token has the given type. Note that the method
3428 * [matchesGt] should be used if the argument to this method would be
3429 * [TokenType#GT].
3430 *
3431 * @param type the type of token that can optionally appear in the current loc ation
3432 * @return `true` if the current token has the given type
3433 */
3434 bool _matches(TokenType type) => _currentToken.type == type;
3435
3436 /**
3437 * Return `true` if the current token has a type of [TokenType#GT]. Note that this
3438 * method, unlike other variants, will modify the token stream if possible to match desired type.
3439 * In particular, if the next token is either a '>>' or '>>>', the token strea m will be re-written
3440 * and `true` will be returned.
3441 *
3442 * @return `true` if the current token has a type of [TokenType#GT]
3443 */
3444 bool _matchesGt() {
3445 TokenType currentType = _currentToken.type;
3446 if (currentType == TokenType.GT) {
3447 return true;
3448 } else if (currentType == TokenType.GT_GT) {
3449 int offset = _currentToken.offset;
3450 Token first = new Token(TokenType.GT, offset);
3451 Token second = new Token(TokenType.GT, offset + 1);
3452 second.setNext(_currentToken.next);
3453 first.setNext(second);
3454 _currentToken.previous.setNext(first);
3455 _currentToken = first;
3456 return true;
3457 } else if (currentType == TokenType.GT_EQ) {
3458 int offset = _currentToken.offset;
3459 Token first = new Token(TokenType.GT, offset);
3460 Token second = new Token(TokenType.EQ, offset + 1);
3461 second.setNext(_currentToken.next);
3462 first.setNext(second);
3463 _currentToken.previous.setNext(first);
3464 _currentToken = first;
3465 return true;
3466 } else if (currentType == TokenType.GT_GT_EQ) {
3467 int offset = _currentToken.offset;
3468 Token first = new Token(TokenType.GT, offset);
3469 Token second = new Token(TokenType.GT, offset + 1);
3470 Token third = new Token(TokenType.EQ, offset + 2);
3471 third.setNext(_currentToken.next);
3472 second.setNext(third);
3473 first.setNext(second);
3474 _currentToken.previous.setNext(first);
3475 _currentToken = first;
3476 return true;
3477 }
3478 return false;
3479 }
3480
3481 /**
3482 * Return `true` if the current token is a valid identifier. Valid identifiers include
3483 * built-in identifiers (pseudo-keywords).
3484 *
3485 * @return `true` if the current token is a valid identifier
3486 */
3487 bool _matchesIdentifier() => _tokenMatchesIdentifier(_currentToken);
3488
3489 /**
3490 * Return `true` if the current token matches the given keyword.
3491 *
3492 * @param keyword the keyword that can optionally appear in the current locati on
3493 * @return `true` if the current token matches the given keyword
3494 */
3495 bool _matchesKeyword(Keyword keyword) => _tokenMatchesKeyword(_currentToken, k eyword);
3496
3497 /**
3498 * Return `true` if the current token matches the given identifier.
3499 *
3500 * @param identifier the identifier that can optionally appear in the current location
3501 * @return `true` if the current token matches the given identifier
3502 */
3503 bool _matchesString(String identifier) => _currentToken.type == TokenType.IDEN TIFIER && _currentToken.lexeme == identifier;
3504
3505 /**
3506 * If the current token has the given type, then advance to the next token and return `true`
3507 * . Otherwise, return `false` without advancing. This method should not be in voked with an
3508 * argument value of [TokenType#GT].
3509 *
3510 * @param type the type of token that can optionally appear in the current loc ation
3511 * @return `true` if the current token has the given type
3512 */
3513 bool _optional(TokenType type) {
3514 if (_matches(type)) {
3515 _advance();
3516 return true;
3517 }
3518 return false;
3519 }
3520
3521 /**
3522 * Parse an additive expression.
3523 *
3524 * <pre>
3525 * additiveExpression ::=
3526 * multiplicativeExpression (additiveOperator multiplicativeExpression)*
3527 * | 'super' (additiveOperator multiplicativeExpression)+
3528 * </pre>
3529 *
3530 * @return the additive expression that was parsed
3531 */
3532 Expression _parseAdditiveExpression() {
3533 Expression expression;
3534 if (_matchesKeyword(Keyword.SUPER) && _currentToken.next.type.isAdditiveOper ator) {
3535 expression = new SuperExpression(andAdvance);
3536 } else {
3537 expression = _parseMultiplicativeExpression();
3538 }
3539 while (_currentToken.type.isAdditiveOperator) {
3540 Token operator = andAdvance;
3541 expression = new BinaryExpression(expression, operator, _parseMultiplicati veExpression());
3542 }
3543 return expression;
3544 }
3545
3546 /**
3547 * Parse an assert statement.
3548 *
3549 * <pre>
3550 * assertStatement ::=
3551 * 'assert' '(' conditionalExpression ')' ';'
3552 * </pre>
3553 *
3554 * @return the assert statement
3555 */
3556 AssertStatement _parseAssertStatement() {
3557 Token keyword = _expectKeyword(Keyword.ASSERT);
3558 Token leftParen = _expect(TokenType.OPEN_PAREN);
3559 Expression expression = parseExpression2();
3560 if (expression is AssignmentExpression) {
3561 _reportErrorForNode(ParserErrorCode.ASSERT_DOES_NOT_TAKE_ASSIGNMENT, expre ssion, []);
3562 } else if (expression is CascadeExpression) {
3563 _reportErrorForNode(ParserErrorCode.ASSERT_DOES_NOT_TAKE_CASCADE, expressi on, []);
3564 } else if (expression is ThrowExpression) {
3565 _reportErrorForNode(ParserErrorCode.ASSERT_DOES_NOT_TAKE_THROW, expression , []);
3566 } else if (expression is RethrowExpression) {
3567 _reportErrorForNode(ParserErrorCode.ASSERT_DOES_NOT_TAKE_RETHROW, expressi on, []);
3568 }
3569 Token rightParen = _expect(TokenType.CLOSE_PAREN);
3570 Token semicolon = _expect(TokenType.SEMICOLON);
3571 return new AssertStatement(keyword, leftParen, expression, rightParen, semic olon);
3572 }
3573
3574 /**
3575 * Parse an assignable expression.
3576 *
3577 * <pre>
3578 * assignableExpression ::=
3579 * primary (arguments* assignableSelector)+
3580 * | 'super' assignableSelector
3581 * | identifier
3582 * </pre>
3583 *
3584 * @param primaryAllowed `true` if the expression is allowed to be a primary w ithout any
3585 * assignable selector
3586 * @return the assignable expression that was parsed
3587 */
3588 Expression _parseAssignableExpression(bool primaryAllowed) {
3589 if (_matchesKeyword(Keyword.SUPER)) {
3590 return _parseAssignableSelector(new SuperExpression(andAdvance), false);
3591 }
3592 //
3593 // A primary expression can start with an identifier. We resolve the ambigui ty by determining
3594 // whether the primary consists of anything other than an identifier and/or is followed by an
3595 // assignableSelector.
3596 //
3597 Expression expression = _parsePrimaryExpression();
3598 bool isOptional = primaryAllowed || expression is SimpleIdentifier;
3599 while (true) {
3600 while (_matches(TokenType.OPEN_PAREN)) {
3601 ArgumentList argumentList = parseArgumentList();
3602 if (expression is SimpleIdentifier) {
3603 expression = new MethodInvocation(null, null, expression as SimpleIden tifier, argumentList);
3604 } else if (expression is PrefixedIdentifier) {
3605 PrefixedIdentifier identifier = expression as PrefixedIdentifier;
3606 expression = new MethodInvocation(identifier.prefix, identifier.period , identifier.identifier, argumentList);
3607 } else if (expression is PropertyAccess) {
3608 PropertyAccess access = expression as PropertyAccess;
3609 expression = new MethodInvocation(access.target, access.operator, acce ss.propertyName, argumentList);
3610 } else {
3611 expression = new FunctionExpressionInvocation(expression, argumentList );
3612 }
3613 if (!primaryAllowed) {
3614 isOptional = false;
3615 }
3616 }
3617 Expression selectorExpression = _parseAssignableSelector(expression, isOpt ional || (expression is PrefixedIdentifier));
3618 if (identical(selectorExpression, expression)) {
3619 if (!isOptional && (expression is PrefixedIdentifier)) {
3620 PrefixedIdentifier identifier = expression as PrefixedIdentifier;
3621 expression = new PropertyAccess(identifier.prefix, identifier.period, identifier.identifier);
3622 }
3623 return expression;
3624 }
3625 expression = selectorExpression;
3626 isOptional = true;
3627 }
3628 }
3629
3630 /**
3631 * Parse an assignable selector.
3632 *
3633 * <pre>
3634 * assignableSelector ::=
3635 * '[' expression ']'
3636 * | '.' identifier
3637 * </pre>
3638 *
3639 * @param prefix the expression preceding the selector
3640 * @param optional `true` if the selector is optional
3641 * @return the assignable selector that was parsed, or the original prefix if there was no
3642 * assignable selector
3643 */
3644 Expression _parseAssignableSelector(Expression prefix, bool optional) {
3645 if (_matches(TokenType.OPEN_SQUARE_BRACKET)) {
3646 Token leftBracket = andAdvance;
3647 bool wasInInitializer = _inInitializer;
3648 _inInitializer = false;
3649 try {
3650 Expression index = parseExpression2();
3651 Token rightBracket = _expect(TokenType.CLOSE_SQUARE_BRACKET);
3652 return new IndexExpression.forTarget(prefix, leftBracket, index, rightBr acket);
3653 } finally {
3654 _inInitializer = wasInInitializer;
3655 }
3656 } else if (_matches(TokenType.PERIOD)) {
3657 Token period = andAdvance;
3658 return new PropertyAccess(prefix, period, parseSimpleIdentifier());
3659 } else {
3660 if (!optional) {
3661 // Report the missing selector.
3662 _reportErrorForCurrentToken(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, []);
3663 }
3664 return prefix;
3665 }
3666 }
3667
3668 /**
3669 * Parse a await expression.
3670 *
3671 * <pre>
3672 * awaitExpression ::=
3673 * 'await' unaryExpression
3674 * </pre>
3675 *
3676 * @return the await expression that was parsed
3677 */
3678 AwaitExpression _parseAwaitExpression() {
3679 Token awaitToken = andAdvance;
3680 Expression expression = _parseUnaryExpression();
3681 return new AwaitExpression(awaitToken, expression);
3682 }
3683
3684 /**
3685 * Parse a bitwise and expression.
3686 *
3687 * <pre>
3688 * bitwiseAndExpression ::=
3689 * shiftExpression ('&' shiftExpression)*
3690 * | 'super' ('&' shiftExpression)+
3691 * </pre>
3692 *
3693 * @return the bitwise and expression that was parsed
3694 */
3695 Expression _parseBitwiseAndExpression() {
3696 Expression expression;
3697 if (_matchesKeyword(Keyword.SUPER) && _tokenMatches(_peek(), TokenType.AMPER SAND)) {
3698 expression = new SuperExpression(andAdvance);
3699 } else {
3700 expression = _parseShiftExpression();
3701 }
3702 while (_matches(TokenType.AMPERSAND)) {
3703 Token operator = andAdvance;
3704 expression = new BinaryExpression(expression, operator, _parseShiftExpress ion());
3705 }
3706 return expression;
3707 }
3708
3709 /**
3710 * Parse a bitwise exclusive-or expression.
3711 *
3712 * <pre>
3713 * bitwiseXorExpression ::=
3714 * bitwiseAndExpression ('^' bitwiseAndExpression)*
3715 * | 'super' ('^' bitwiseAndExpression)+
3716 * </pre>
3717 *
3718 * @return the bitwise exclusive-or expression that was parsed
3719 */
3720 Expression _parseBitwiseXorExpression() {
3721 Expression expression;
3722 if (_matchesKeyword(Keyword.SUPER) && _tokenMatches(_peek(), TokenType.CARET )) {
3723 expression = new SuperExpression(andAdvance);
3724 } else {
3725 expression = _parseBitwiseAndExpression();
3726 }
3727 while (_matches(TokenType.CARET)) {
3728 Token operator = andAdvance;
3729 expression = new BinaryExpression(expression, operator, _parseBitwiseAndEx pression());
3730 }
3731 return expression;
3732 }
3733
3734 /**
3735 * Parse a break statement.
3736 *
3737 * <pre>
3738 * breakStatement ::=
3739 * 'break' identifier? ';'
3740 * </pre>
3741 *
3742 * @return the break statement that was parsed
3743 */
3744 Statement _parseBreakStatement() {
3745 Token breakKeyword = _expectKeyword(Keyword.BREAK);
3746 SimpleIdentifier label = null;
3747 if (_matchesIdentifier()) {
3748 label = parseSimpleIdentifier();
3749 }
3750 if (!_inLoop && !_inSwitch && label == null) {
3751 _reportErrorForToken(ParserErrorCode.BREAK_OUTSIDE_OF_LOOP, breakKeyword, []);
3752 }
3753 Token semicolon = _expect(TokenType.SEMICOLON);
3754 return new BreakStatement(breakKeyword, label, semicolon);
3755 }
3756
3757 /**
3758 * Parse a cascade section.
3759 *
3760 * <pre>
3761 * cascadeSection ::=
3762 * '..' (cascadeSelector arguments*) (assignableSelector arguments*)* casc adeAssignment?
3763 *
3764 * cascadeSelector ::=
3765 * '[' expression ']'
3766 * | identifier
3767 *
3768 * cascadeAssignment ::=
3769 * assignmentOperator expressionWithoutCascade
3770 * </pre>
3771 *
3772 * @return the expression representing the cascaded method invocation
3773 */
3774 Expression _parseCascadeSection() {
3775 Token period = _expect(TokenType.PERIOD_PERIOD);
3776 Expression expression = null;
3777 SimpleIdentifier functionName = null;
3778 if (_matchesIdentifier()) {
3779 functionName = parseSimpleIdentifier();
3780 } else if (_currentToken.type == TokenType.OPEN_SQUARE_BRACKET) {
3781 Token leftBracket = andAdvance;
3782 bool wasInInitializer = _inInitializer;
3783 _inInitializer = false;
3784 try {
3785 Expression index = parseExpression2();
3786 Token rightBracket = _expect(TokenType.CLOSE_SQUARE_BRACKET);
3787 expression = new IndexExpression.forCascade(period, leftBracket, index, rightBracket);
3788 period = null;
3789 } finally {
3790 _inInitializer = wasInInitializer;
3791 }
3792 } else {
3793 _reportErrorForToken(ParserErrorCode.MISSING_IDENTIFIER, _currentToken, [_ currentToken.lexeme]);
3794 functionName = _createSyntheticIdentifier();
3795 }
3796 assert((expression == null && functionName != null) || (expression != null & & functionName == null));
3797 if (_currentToken.type == TokenType.OPEN_PAREN) {
3798 while (_currentToken.type == TokenType.OPEN_PAREN) {
3799 if (functionName != null) {
3800 expression = new MethodInvocation(expression, period, functionName, pa rseArgumentList());
3801 period = null;
3802 functionName = null;
3803 } else if (expression == null) {
3804 // It should not be possible to get here.
3805 expression = new MethodInvocation(expression, period, _createSynthetic Identifier(), parseArgumentList());
3806 } else {
3807 expression = new FunctionExpressionInvocation(expression, parseArgumen tList());
3808 }
3809 }
3810 } else if (functionName != null) {
3811 expression = new PropertyAccess(expression, period, functionName);
3812 period = null;
3813 }
3814 assert(expression != null);
3815 bool progress = true;
3816 while (progress) {
3817 progress = false;
3818 Expression selector = _parseAssignableSelector(expression, true);
3819 if (!identical(selector, expression)) {
3820 expression = selector;
3821 progress = true;
3822 while (_currentToken.type == TokenType.OPEN_PAREN) {
3823 if (expression is PropertyAccess) {
3824 PropertyAccess propertyAccess = expression as PropertyAccess;
3825 expression = new MethodInvocation(propertyAccess.target, propertyAcc ess.operator, propertyAccess.propertyName, parseArgumentList());
3826 } else {
3827 expression = new FunctionExpressionInvocation(expression, parseArgum entList());
3828 }
3829 }
3830 }
3831 }
3832 if (_currentToken.type.isAssignmentOperator) {
3833 Token operator = andAdvance;
3834 _ensureAssignable(expression);
3835 expression = new AssignmentExpression(expression, operator, parseExpressio nWithoutCascade());
3836 }
3837 return expression;
3838 }
3839
3840 /**
3841 * Parse a class declaration.
3842 *
3843 * <pre>
3844 * classDeclaration ::=
3845 * metadata 'abstract'? 'class' name typeParameterList? (extendsClause wit hClause?)? implementsClause? '{' classMembers '}' |
3846 * metadata 'abstract'? 'class' mixinApplicationClass
3847 * </pre>
3848 *
3849 * @param commentAndMetadata the metadata to be associated with the member
3850 * @param abstractKeyword the token for the keyword 'abstract', or `null` if t he keyword was
3851 * not given
3852 * @return the class declaration that was parsed
3853 */
3854 CompilationUnitMember _parseClassDeclaration(CommentAndMetadata commentAndMeta data, Token abstractKeyword) {
3855 Token keyword = _expectKeyword(Keyword.CLASS);
3856 if (_matchesIdentifier()) {
3857 Token next = _peek();
3858 if (_tokenMatches(next, TokenType.LT)) {
3859 next = _skipTypeParameterList(next);
3860 if (next != null && _tokenMatches(next, TokenType.EQ)) {
3861 return _parseClassTypeAlias(commentAndMetadata, abstractKeyword, keywo rd);
3862 }
3863 } else if (_tokenMatches(next, TokenType.EQ)) {
3864 return _parseClassTypeAlias(commentAndMetadata, abstractKeyword, keyword );
3865 }
3866 }
3867 SimpleIdentifier name = parseSimpleIdentifier();
3868 String className = name.name;
3869 TypeParameterList typeParameters = null;
3870 if (_matches(TokenType.LT)) {
3871 typeParameters = parseTypeParameterList();
3872 }
3873 //
3874 // Parse the clauses. The parser accepts clauses in any order, but will gene rate errors if they
3875 // are not in the order required by the specification.
3876 //
3877 ExtendsClause extendsClause = null;
3878 WithClause withClause = null;
3879 ImplementsClause implementsClause = null;
3880 bool foundClause = true;
3881 while (foundClause) {
3882 if (_matchesKeyword(Keyword.EXTENDS)) {
3883 if (extendsClause == null) {
3884 extendsClause = parseExtendsClause();
3885 if (withClause != null) {
3886 _reportErrorForToken(ParserErrorCode.WITH_BEFORE_EXTENDS, withClause .withKeyword, []);
3887 } else if (implementsClause != null) {
3888 _reportErrorForToken(ParserErrorCode.IMPLEMENTS_BEFORE_EXTENDS, impl ementsClause.keyword, []);
3889 }
3890 } else {
3891 _reportErrorForToken(ParserErrorCode.MULTIPLE_EXTENDS_CLAUSES, extends Clause.keyword, []);
3892 parseExtendsClause();
3893 }
3894 } else if (_matchesKeyword(Keyword.WITH)) {
3895 if (withClause == null) {
3896 withClause = parseWithClause();
3897 if (implementsClause != null) {
3898 _reportErrorForToken(ParserErrorCode.IMPLEMENTS_BEFORE_WITH, impleme ntsClause.keyword, []);
3899 }
3900 } else {
3901 _reportErrorForToken(ParserErrorCode.MULTIPLE_WITH_CLAUSES, withClause .withKeyword, []);
3902 parseWithClause();
3903 }
3904 } else if (_matchesKeyword(Keyword.IMPLEMENTS)) {
3905 if (implementsClause == null) {
3906 implementsClause = parseImplementsClause();
3907 } else {
3908 _reportErrorForToken(ParserErrorCode.MULTIPLE_IMPLEMENTS_CLAUSES, impl ementsClause.keyword, []);
3909 parseImplementsClause();
3910 }
3911 } else {
3912 foundClause = false;
3913 }
3914 }
3915 if (withClause != null && extendsClause == null) {
3916 _reportErrorForToken(ParserErrorCode.WITH_WITHOUT_EXTENDS, withClause.with Keyword, []);
3917 }
3918 //
3919 // Look for and skip over the extra-lingual 'native' specification.
3920 //
3921 NativeClause nativeClause = null;
3922 if (_matchesString(_NATIVE) && _tokenMatches(_peek(), TokenType.STRING)) {
3923 nativeClause = _parseNativeClause();
3924 }
3925 //
3926 // Parse the body of the class.
3927 //
3928 Token leftBracket = null;
3929 List<ClassMember> members = null;
3930 Token rightBracket = null;
3931 if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
3932 leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET);
3933 members = _parseClassMembers(className, _getEndToken(leftBracket));
3934 rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
3935 } else {
3936 leftBracket = _createSyntheticToken(TokenType.OPEN_CURLY_BRACKET);
3937 rightBracket = _createSyntheticToken(TokenType.CLOSE_CURLY_BRACKET);
3938 _reportErrorForCurrentToken(ParserErrorCode.MISSING_CLASS_BODY, []);
3939 }
3940 ClassDeclaration classDeclaration = new ClassDeclaration(commentAndMetadata. comment, commentAndMetadata.metadata, abstractKeyword, keyword, name, typeParame ters, extendsClause, withClause, implementsClause, leftBracket, members, rightBr acket);
3941 classDeclaration.nativeClause = nativeClause;
3942 return classDeclaration;
3943 }
3944
3945 /**
3946 * Parse a list of class members.
3947 *
3948 * <pre>
3949 * classMembers ::=
3950 * (metadata memberDefinition)*
3951 * </pre>
3952 *
3953 * @param className the name of the class whose members are being parsed
3954 * @param closingBracket the closing bracket for the class, or `null` if the c losing bracket
3955 * is missing
3956 * @return the list of class members that were parsed
3957 */
3958 List<ClassMember> _parseClassMembers(String className, Token closingBracket) {
3959 List<ClassMember> members = new List<ClassMember>();
3960 Token memberStart = _currentToken;
3961 while (!_matches(TokenType.EOF) && !_matches(TokenType.CLOSE_CURLY_BRACKET) && (closingBracket != null || (!_matchesKeyword(Keyword.CLASS) && !_matchesKeywo rd(Keyword.TYPEDEF)))) {
3962 if (_matches(TokenType.SEMICOLON)) {
3963 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_ currentToken.lexeme]);
3964 _advance();
3965 } else {
3966 ClassMember member = parseClassMember(className);
3967 if (member != null) {
3968 members.add(member);
3969 }
3970 }
3971 if (identical(_currentToken, memberStart)) {
3972 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_ currentToken.lexeme]);
3973 _advance();
3974 }
3975 memberStart = _currentToken;
3976 }
3977 return members;
3978 }
3979
3980 /**
3981 * Parse a class type alias.
3982 *
3983 * <pre>
3984 * classTypeAlias ::=
3985 * identifier typeParameters? '=' 'abstract'? mixinApplication
3986 *
3987 * mixinApplication ::=
3988 * type withClause implementsClause? ';'
3989 * </pre>
3990 *
3991 * @param commentAndMetadata the metadata to be associated with the member
3992 * @param abstractKeyword the token representing the 'abstract' keyword
3993 * @param classKeyword the token representing the 'class' keyword
3994 * @return the class type alias that was parsed
3995 */
3996 ClassTypeAlias _parseClassTypeAlias(CommentAndMetadata commentAndMetadata, Tok en abstractKeyword, Token classKeyword) {
3997 SimpleIdentifier className = parseSimpleIdentifier();
3998 TypeParameterList typeParameters = null;
3999 if (_matches(TokenType.LT)) {
4000 typeParameters = parseTypeParameterList();
4001 }
4002 Token equals = _expect(TokenType.EQ);
4003 TypeName superclass = parseTypeName();
4004 WithClause withClause = null;
4005 if (_matchesKeyword(Keyword.WITH)) {
4006 withClause = parseWithClause();
4007 } else {
4008 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TOKEN, [Keyword.WITH. syntax]);
4009 }
4010 ImplementsClause implementsClause = null;
4011 if (_matchesKeyword(Keyword.IMPLEMENTS)) {
4012 implementsClause = parseImplementsClause();
4013 }
4014 Token semicolon;
4015 if (_matches(TokenType.SEMICOLON)) {
4016 semicolon = andAdvance;
4017 } else {
4018 if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
4019 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TOKEN, [TokenType.S EMICOLON.lexeme]);
4020 Token leftBracket = andAdvance;
4021 _parseClassMembers(className.name, _getEndToken(leftBracket));
4022 _expect(TokenType.CLOSE_CURLY_BRACKET);
4023 } else {
4024 _reportErrorForToken(ParserErrorCode.EXPECTED_TOKEN, _currentToken.previ ous, [TokenType.SEMICOLON.lexeme]);
4025 }
4026 semicolon = _createSyntheticToken(TokenType.SEMICOLON);
4027 }
4028 return new ClassTypeAlias(commentAndMetadata.comment, commentAndMetadata.met adata, classKeyword, className, typeParameters, equals, abstractKeyword, supercl ass, withClause, implementsClause, semicolon);
4029 }
4030
4031 /**
4032 * Parse a list of combinators in a directive.
4033 *
4034 * <pre>
4035 * combinator ::=
4036 * 'show' identifier (',' identifier)*
4037 * | 'hide' identifier (',' identifier)*
4038 * </pre>
4039 *
4040 * @return the combinators that were parsed
4041 */
4042 List<Combinator> _parseCombinators() {
4043 List<Combinator> combinators = new List<Combinator>();
4044 while (_matchesString(_SHOW) || _matchesString(_HIDE)) {
4045 Token keyword = _expect(TokenType.IDENTIFIER);
4046 if (keyword.lexeme == _SHOW) {
4047 List<SimpleIdentifier> shownNames = _parseIdentifierList();
4048 combinators.add(new ShowCombinator(keyword, shownNames));
4049 } else {
4050 List<SimpleIdentifier> hiddenNames = _parseIdentifierList();
4051 combinators.add(new HideCombinator(keyword, hiddenNames));
4052 }
4053 }
4054 return combinators;
4055 }
4056
4057 /**
4058 * Parse the documentation comment and metadata preceding a declaration. This method allows any
4059 * number of documentation comments to occur before, after or between the meta data, but only
4060 * returns the last (right-most) documentation comment that is found.
4061 *
4062 * <pre>
4063 * metadata ::=
4064 * annotation*
4065 * </pre>
4066 *
4067 * @return the documentation comment and metadata that were parsed
4068 */
4069 CommentAndMetadata _parseCommentAndMetadata() {
4070 Comment comment = _parseDocumentationComment();
4071 List<Annotation> metadata = new List<Annotation>();
4072 while (_matches(TokenType.AT)) {
4073 metadata.add(parseAnnotation());
4074 Comment optionalComment = _parseDocumentationComment();
4075 if (optionalComment != null) {
4076 comment = optionalComment;
4077 }
4078 }
4079 return new CommentAndMetadata(comment, metadata);
4080 }
4081
4082 /**
4083 * Parse a comment reference from the source between square brackets.
4084 *
4085 * <pre>
4086 * commentReference ::=
4087 * 'new'? prefixedIdentifier
4088 * </pre>
4089 *
4090 * @param referenceSource the source occurring between the square brackets wit hin a documentation
4091 * comment
4092 * @param sourceOffset the offset of the first character of the reference sour ce
4093 * @return the comment reference that was parsed, or `null` if no reference co uld be found
4094 */
4095 CommentReference _parseCommentReference(String referenceSource, int sourceOffs et) {
4096 // TODO(brianwilkerson) The errors are not getting the right offset/length a nd are being duplicated.
4097 if (referenceSource.length == 0) {
4098 Token syntheticToken = new SyntheticStringToken(TokenType.IDENTIFIER, "", sourceOffset);
4099 return new CommentReference(null, new SimpleIdentifier(syntheticToken));
4100 }
4101 try {
4102 BooleanErrorListener listener = new BooleanErrorListener();
4103 Scanner scanner = new Scanner(null, new SubSequenceReader(referenceSource, sourceOffset), listener);
4104 scanner.setSourceStart(1, 1);
4105 Token firstToken = scanner.tokenize();
4106 if (listener.errorReported) {
4107 return null;
4108 }
4109 Token newKeyword = null;
4110 if (_tokenMatchesKeyword(firstToken, Keyword.NEW)) {
4111 newKeyword = firstToken;
4112 firstToken = firstToken.next;
4113 }
4114 if (_tokenMatchesIdentifier(firstToken)) {
4115 Token secondToken = firstToken.next;
4116 Token thirdToken = secondToken.next;
4117 Token nextToken;
4118 Identifier identifier;
4119 if (_tokenMatches(secondToken, TokenType.PERIOD) && _tokenMatchesIdentif ier(thirdToken)) {
4120 identifier = new PrefixedIdentifier(new SimpleIdentifier(firstToken), secondToken, new SimpleIdentifier(thirdToken));
4121 nextToken = thirdToken.next;
4122 } else {
4123 identifier = new SimpleIdentifier(firstToken);
4124 nextToken = firstToken.next;
4125 }
4126 if (nextToken.type != TokenType.EOF) {
4127 return null;
4128 }
4129 return new CommentReference(newKeyword, identifier);
4130 } else if (_tokenMatchesKeyword(firstToken, Keyword.THIS) || _tokenMatches Keyword(firstToken, Keyword.NULL) || _tokenMatchesKeyword(firstToken, Keyword.TR UE) || _tokenMatchesKeyword(firstToken, Keyword.FALSE)) {
4131 // TODO(brianwilkerson) If we want to support this we will need to exten d the definition
4132 // of CommentReference to take an expression rather than an identifier. For now we just
4133 // ignore it to reduce the number of errors produced, but that's probabl y not a valid
4134 // long term approach.
4135 return null;
4136 }
4137 } catch (exception) {
4138 }
4139 return null;
4140 }
4141
4142 /**
4143 * Parse all of the comment references occurring in the given array of documen tation comments.
4144 *
4145 * <pre>
4146 * commentReference ::=
4147 * '[' 'new'? qualified ']' libraryReference?
4148 *
4149 * libraryReference ::=
4150 * '(' stringLiteral ')'
4151 * </pre>
4152 *
4153 * @param tokens the comment tokens representing the documentation comments to be parsed
4154 * @return the comment references that were parsed
4155 */
4156 List<CommentReference> _parseCommentReferences(List<Token> tokens) {
4157 List<CommentReference> references = new List<CommentReference>();
4158 for (Token token in tokens) {
4159 String comment = token.lexeme;
4160 int length = comment.length;
4161 List<List<int>> codeBlockRanges = _getCodeBlockRanges(comment);
4162 int leftIndex = comment.indexOf('[');
4163 while (leftIndex >= 0 && leftIndex + 1 < length) {
4164 List<int> range = _findRange(codeBlockRanges, leftIndex);
4165 if (range == null) {
4166 int nameOffset = token.offset + leftIndex + 1;
4167 int rightIndex = JavaString.indexOf(comment, ']', leftIndex);
4168 if (rightIndex >= 0) {
4169 int firstChar = comment.codeUnitAt(leftIndex + 1);
4170 if (firstChar != 0x27 && firstChar != 0x22) {
4171 if (_isLinkText(comment, rightIndex)) {
4172 } else {
4173 CommentReference reference = _parseCommentReference(comment.subs tring(leftIndex + 1, rightIndex), nameOffset);
4174 if (reference != null) {
4175 references.add(reference);
4176 }
4177 }
4178 }
4179 } else {
4180 // terminating ']' is not typed yet
4181 int charAfterLeft = comment.codeUnitAt(leftIndex + 1);
4182 if (Character.isLetterOrDigit(charAfterLeft)) {
4183 int nameEnd = StringUtilities.indexOfFirstNotLetterDigit(comment, leftIndex + 1);
4184 String name = comment.substring(leftIndex + 1, nameEnd);
4185 Token nameToken = new StringToken(TokenType.IDENTIFIER, name, name Offset);
4186 references.add(new CommentReference(null, new SimpleIdentifier(nam eToken)));
4187 } else {
4188 Token nameToken = new SyntheticStringToken(TokenType.IDENTIFIER, " ", nameOffset);
4189 references.add(new CommentReference(null, new SimpleIdentifier(nam eToken)));
4190 }
4191 // next character
4192 rightIndex = leftIndex + 1;
4193 }
4194 leftIndex = JavaString.indexOf(comment, '[', rightIndex);
4195 } else {
4196 leftIndex = JavaString.indexOf(comment, '[', range[1] + 1);
4197 }
4198 }
4199 }
4200 return references;
4201 }
4202
4203 /**
4204 * Parse a compilation unit member.
4205 *
4206 * <pre>
4207 * compilationUnitMember ::=
4208 * classDefinition
4209 * | functionTypeAlias
4210 * | external functionSignature
4211 * | external getterSignature
4212 * | external setterSignature
4213 * | functionSignature functionBody
4214 * | returnType? getOrSet identifier formalParameterList functionBody
4215 * | (final | const) type? staticFinalDeclarationList ';'
4216 * | variableDeclaration ';'
4217 * </pre>
4218 *
4219 * @param commentAndMetadata the metadata to be associated with the member
4220 * @return the compilation unit member that was parsed, or `null` if what was parsed could
4221 * not be represented as a compilation unit member
4222 */
4223 CompilationUnitMember _parseCompilationUnitMember(CommentAndMetadata commentAn dMetadata) {
4224 Modifiers modifiers = _parseModifiers();
4225 if (_matchesKeyword(Keyword.CLASS)) {
4226 return _parseClassDeclaration(commentAndMetadata, _validateModifiersForCla ss(modifiers));
4227 } else if (_matchesKeyword(Keyword.TYPEDEF) && !_tokenMatches(_peek(), Token Type.PERIOD) && !_tokenMatches(_peek(), TokenType.LT) && !_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
4228 _validateModifiersForTypedef(modifiers);
4229 return _parseTypeAlias(commentAndMetadata);
4230 } else if (_parseEnum && _matchesKeyword(Keyword.ENUM)) {
4231 _validateModifiersForEnum(modifiers);
4232 return _parseEnumDeclaration(commentAndMetadata);
4233 }
4234 if (_matchesKeyword(Keyword.VOID)) {
4235 TypeName returnType = parseReturnType();
4236 if ((_matchesKeyword(Keyword.GET) || _matchesKeyword(Keyword.SET)) && _tok enMatchesIdentifier(_peek())) {
4237 _validateModifiersForTopLevelFunction(modifiers);
4238 return _parseFunctionDeclaration(commentAndMetadata, modifiers.externalK eyword, returnType);
4239 } else if (_matchesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) {
4240 _reportErrorForToken(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken, []);
4241 return _convertToFunctionDeclaration(_parseOperator(commentAndMetadata, modifiers.externalKeyword, returnType));
4242 } else if (_matchesIdentifier() && _peek().matchesAny([
4243 TokenType.OPEN_PAREN,
4244 TokenType.OPEN_CURLY_BRACKET,
4245 TokenType.FUNCTION])) {
4246 _validateModifiersForTopLevelFunction(modifiers);
4247 return _parseFunctionDeclaration(commentAndMetadata, modifiers.externalK eyword, returnType);
4248 } else {
4249 //
4250 // We have found an error of some kind. Try to recover.
4251 //
4252 if (_matchesIdentifier()) {
4253 if (_peek().matchesAny([TokenType.EQ, TokenType.COMMA, TokenType.SEMIC OLON])) {
4254 //
4255 // We appear to have a variable declaration with a type of "void".
4256 //
4257 _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType, []);
4258 return new TopLevelVariableDeclaration(commentAndMetadata.comment, c ommentAndMetadata.metadata, _parseVariableDeclarationListAfterType(null, _valida teModifiersForTopLevelVariable(modifiers), null), _expect(TokenType.SEMICOLON));
4259 }
4260 }
4261 _reportErrorForToken(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken, []);
4262 return null;
4263 }
4264 } else if ((_matchesKeyword(Keyword.GET) || _matchesKeyword(Keyword.SET)) && _tokenMatchesIdentifier(_peek())) {
4265 _validateModifiersForTopLevelFunction(modifiers);
4266 return _parseFunctionDeclaration(commentAndMetadata, modifiers.externalKey word, null);
4267 } else if (_matchesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) {
4268 _reportErrorForToken(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken, [] );
4269 return _convertToFunctionDeclaration(_parseOperator(commentAndMetadata, mo difiers.externalKeyword, null));
4270 } else if (!_matchesIdentifier()) {
4271 Token keyword = modifiers.varKeyword;
4272 if (keyword == null) {
4273 keyword = modifiers.finalKeyword;
4274 }
4275 if (keyword == null) {
4276 keyword = modifiers.constKeyword;
4277 }
4278 if (keyword != null) {
4279 //
4280 // We appear to have found an incomplete top-level variable declaration.
4281 //
4282 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER, []);
4283 List<VariableDeclaration> variables = new List<VariableDeclaration>();
4284 variables.add(new VariableDeclaration(null, null, _createSyntheticIdenti fier(), null, null));
4285 return new TopLevelVariableDeclaration(commentAndMetadata.comment, comme ntAndMetadata.metadata, new VariableDeclarationList(null, null, keyword, null, v ariables), _expectSemicolon());
4286 }
4287 _reportErrorForToken(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken, [ ]);
4288 return null;
4289 } else if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
4290 _validateModifiersForTopLevelFunction(modifiers);
4291 return _parseFunctionDeclaration(commentAndMetadata, modifiers.externalKey word, null);
4292 } else if (_peek().matchesAny([TokenType.EQ, TokenType.COMMA, TokenType.SEMI COLON])) {
4293 if (modifiers.constKeyword == null && modifiers.finalKeyword == null && mo difiers.varKeyword == null) {
4294 _reportErrorForCurrentToken(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_T YPE, []);
4295 }
4296 return new TopLevelVariableDeclaration(commentAndMetadata.comment, comment AndMetadata.metadata, _parseVariableDeclarationListAfterType(null, _validateModi fiersForTopLevelVariable(modifiers), null), _expect(TokenType.SEMICOLON));
4297 }
4298 TypeName returnType = parseReturnType();
4299 if ((_matchesKeyword(Keyword.GET) || _matchesKeyword(Keyword.SET)) && _token MatchesIdentifier(_peek())) {
4300 _validateModifiersForTopLevelFunction(modifiers);
4301 return _parseFunctionDeclaration(commentAndMetadata, modifiers.externalKey word, returnType);
4302 } else if (_matchesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) {
4303 _reportErrorForToken(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken, [] );
4304 return _convertToFunctionDeclaration(_parseOperator(commentAndMetadata, mo difiers.externalKeyword, returnType));
4305 } else if (_matches(TokenType.AT)) {
4306 return new TopLevelVariableDeclaration(commentAndMetadata.comment, comment AndMetadata.metadata, _parseVariableDeclarationListAfterType(null, _validateModi fiersForTopLevelVariable(modifiers), returnType), _expect(TokenType.SEMICOLON));
4307 } else if (!_matchesIdentifier()) {
4308 // TODO(brianwilkerson) Generalize this error. We could also be parsing a top-level variable at this point.
4309 _reportErrorForToken(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken, [ ]);
4310 Token semicolon;
4311 if (_matches(TokenType.SEMICOLON)) {
4312 semicolon = andAdvance;
4313 } else {
4314 semicolon = _createSyntheticToken(TokenType.SEMICOLON);
4315 }
4316 List<VariableDeclaration> variables = new List<VariableDeclaration>();
4317 variables.add(new VariableDeclaration(null, null, _createSyntheticIdentifi er(), null, null));
4318 return new TopLevelVariableDeclaration(commentAndMetadata.comment, comment AndMetadata.metadata, new VariableDeclarationList(null, null, null, returnType, variables), semicolon);
4319 }
4320 if (_peek().matchesAny([
4321 TokenType.OPEN_PAREN,
4322 TokenType.FUNCTION,
4323 TokenType.OPEN_CURLY_BRACKET])) {
4324 _validateModifiersForTopLevelFunction(modifiers);
4325 return _parseFunctionDeclaration(commentAndMetadata, modifiers.externalKey word, returnType);
4326 }
4327 return new TopLevelVariableDeclaration(commentAndMetadata.comment, commentAn dMetadata.metadata, _parseVariableDeclarationListAfterType(null, _validateModifi ersForTopLevelVariable(modifiers), returnType), _expect(TokenType.SEMICOLON));
4328 }
4329
4330 /**
4331 * Parse a const expression.
4332 *
4333 * <pre>
4334 * constExpression ::=
4335 * instanceCreationExpression
4336 * | listLiteral
4337 * | mapLiteral
4338 * </pre>
4339 *
4340 * @return the const expression that was parsed
4341 */
4342 Expression _parseConstExpression() {
4343 Token keyword = _expectKeyword(Keyword.CONST);
4344 if (_matches(TokenType.OPEN_SQUARE_BRACKET) || _matches(TokenType.INDEX)) {
4345 return _parseListLiteral(keyword, null);
4346 } else if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
4347 return _parseMapLiteral(keyword, null);
4348 } else if (_matches(TokenType.LT)) {
4349 return _parseListOrMapLiteral(keyword);
4350 }
4351 return _parseInstanceCreationExpression(keyword);
4352 }
4353
4354 ConstructorDeclaration _parseConstructor(CommentAndMetadata commentAndMetadata , Token externalKeyword, Token constKeyword, Token factoryKeyword, SimpleIdentif ier returnType, Token period, SimpleIdentifier name, FormalParameterList paramet ers) {
4355 bool bodyAllowed = externalKeyword == null;
4356 Token separator = null;
4357 List<ConstructorInitializer> initializers = null;
4358 if (_matches(TokenType.COLON)) {
4359 separator = andAdvance;
4360 initializers = new List<ConstructorInitializer>();
4361 do {
4362 if (_matchesKeyword(Keyword.THIS)) {
4363 if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
4364 bodyAllowed = false;
4365 initializers.add(_parseRedirectingConstructorInvocation());
4366 } else if (_tokenMatches(_peek(), TokenType.PERIOD) && _tokenMatches(_ peekAt(3), TokenType.OPEN_PAREN)) {
4367 bodyAllowed = false;
4368 initializers.add(_parseRedirectingConstructorInvocation());
4369 } else {
4370 initializers.add(_parseConstructorFieldInitializer());
4371 }
4372 } else if (_matchesKeyword(Keyword.SUPER)) {
4373 initializers.add(_parseSuperConstructorInvocation());
4374 } else {
4375 initializers.add(_parseConstructorFieldInitializer());
4376 }
4377 } while (_optional(TokenType.COMMA));
4378 }
4379 ConstructorName redirectedConstructor = null;
4380 FunctionBody body;
4381 if (_matches(TokenType.EQ)) {
4382 separator = andAdvance;
4383 redirectedConstructor = parseConstructorName();
4384 body = new EmptyFunctionBody(_expect(TokenType.SEMICOLON));
4385 if (factoryKeyword == null) {
4386 _reportErrorForNode(ParserErrorCode.REDIRECTION_IN_NON_FACTORY_CONSTRUCT OR, redirectedConstructor, []);
4387 }
4388 } else {
4389 body = _parseFunctionBody(true, ParserErrorCode.MISSING_FUNCTION_BODY, fal se);
4390 if (constKeyword != null && factoryKeyword != null && externalKeyword == n ull) {
4391 _reportErrorForToken(ParserErrorCode.CONST_FACTORY, factoryKeyword, []);
4392 } else if (body is EmptyFunctionBody) {
4393 if (factoryKeyword != null && externalKeyword == null) {
4394 _reportErrorForToken(ParserErrorCode.FACTORY_WITHOUT_BODY, factoryKeyw ord, []);
4395 }
4396 } else {
4397 if (constKeyword != null) {
4398 _reportErrorForNode(ParserErrorCode.CONST_CONSTRUCTOR_WITH_BODY, body, []);
4399 } else if (!bodyAllowed) {
4400 _reportErrorForNode(ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_BODY, bo dy, []);
4401 }
4402 }
4403 }
4404 return new ConstructorDeclaration(commentAndMetadata.comment, commentAndMeta data.metadata, externalKeyword, constKeyword, factoryKeyword, returnType, period , name, parameters, separator, initializers, redirectedConstructor, body);
4405 }
4406
4407 /**
4408 * Parse a field initializer within a constructor.
4409 *
4410 * <pre>
4411 * fieldInitializer:
4412 * ('this' '.')? identifier '=' conditionalExpression cascadeSection*
4413 * </pre>
4414 *
4415 * @return the field initializer that was parsed
4416 */
4417 ConstructorFieldInitializer _parseConstructorFieldInitializer() {
4418 Token keyword = null;
4419 Token period = null;
4420 if (_matchesKeyword(Keyword.THIS)) {
4421 keyword = andAdvance;
4422 period = _expect(TokenType.PERIOD);
4423 }
4424 SimpleIdentifier fieldName = parseSimpleIdentifier();
4425 Token equals = _expect(TokenType.EQ);
4426 bool wasInInitializer = _inInitializer;
4427 _inInitializer = true;
4428 try {
4429 Expression expression = parseConditionalExpression();
4430 TokenType tokenType = _currentToken.type;
4431 if (tokenType == TokenType.PERIOD_PERIOD) {
4432 List<Expression> cascadeSections = new List<Expression>();
4433 while (tokenType == TokenType.PERIOD_PERIOD) {
4434 Expression section = _parseCascadeSection();
4435 if (section != null) {
4436 cascadeSections.add(section);
4437 }
4438 tokenType = _currentToken.type;
4439 }
4440 expression = new CascadeExpression(expression, cascadeSections);
4441 }
4442 return new ConstructorFieldInitializer(keyword, period, fieldName, equals, expression);
4443 } finally {
4444 _inInitializer = wasInInitializer;
4445 }
4446 }
4447
4448 /**
4449 * Parse a continue statement.
4450 *
4451 * <pre>
4452 * continueStatement ::=
4453 * 'continue' identifier? ';'
4454 * </pre>
4455 *
4456 * @return the continue statement that was parsed
4457 */
4458 Statement _parseContinueStatement() {
4459 Token continueKeyword = _expectKeyword(Keyword.CONTINUE);
4460 if (!_inLoop && !_inSwitch) {
4461 _reportErrorForToken(ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP, continueKey word, []);
4462 }
4463 SimpleIdentifier label = null;
4464 if (_matchesIdentifier()) {
4465 label = parseSimpleIdentifier();
4466 }
4467 if (_inSwitch && !_inLoop && label == null) {
4468 _reportErrorForToken(ParserErrorCode.CONTINUE_WITHOUT_LABEL_IN_CASE, conti nueKeyword, []);
4469 }
4470 Token semicolon = _expect(TokenType.SEMICOLON);
4471 return new ContinueStatement(continueKeyword, label, semicolon);
4472 }
4473
4474 /**
4475 * Parse a directive.
4476 *
4477 * <pre>
4478 * directive ::=
4479 * exportDirective
4480 * | libraryDirective
4481 * | importDirective
4482 * | partDirective
4483 * </pre>
4484 *
4485 * @param commentAndMetadata the metadata to be associated with the directive
4486 * @return the directive that was parsed
4487 */
4488 Directive _parseDirective(CommentAndMetadata commentAndMetadata) {
4489 if (_matchesKeyword(Keyword.IMPORT)) {
4490 return _parseImportDirective(commentAndMetadata);
4491 } else if (_matchesKeyword(Keyword.EXPORT)) {
4492 return _parseExportDirective(commentAndMetadata);
4493 } else if (_matchesKeyword(Keyword.LIBRARY)) {
4494 return _parseLibraryDirective(commentAndMetadata);
4495 } else if (_matchesKeyword(Keyword.PART)) {
4496 return _parsePartDirective(commentAndMetadata);
4497 } else {
4498 // Internal error: this method should not have been invoked if the current token was something
4499 // other than one of the above.
4500 throw new IllegalStateException("parseDirective invoked in an invalid stat e; currentToken = ${_currentToken}");
4501 }
4502 }
4503
4504 /**
4505 * Parse the script tag and directives in a compilation unit until the first n on-directive is
4506 * encountered.
4507 *
4508 *
4509 * <pre>
4510 * compilationUnit ::=
4511 * scriptTag? directive*
4512 * </pre>
4513 *
4514 * @return the compilation unit that was parsed
4515 */
4516 CompilationUnit _parseDirectives() {
4517 Token firstToken = _currentToken;
4518 ScriptTag scriptTag = null;
4519 if (_matches(TokenType.SCRIPT_TAG)) {
4520 scriptTag = new ScriptTag(andAdvance);
4521 }
4522 List<Directive> directives = new List<Directive>();
4523 while (!_matches(TokenType.EOF)) {
4524 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
4525 if ((_matchesKeyword(Keyword.IMPORT) || _matchesKeyword(Keyword.EXPORT) || _matchesKeyword(Keyword.LIBRARY) || _matchesKeyword(Keyword.PART)) && !_tokenMa tches(_peek(), TokenType.PERIOD) && !_tokenMatches(_peek(), TokenType.LT) && !_t okenMatches(_peek(), TokenType.OPEN_PAREN)) {
4526 directives.add(_parseDirective(commentAndMetadata));
4527 } else if (_matches(TokenType.SEMICOLON)) {
4528 _advance();
4529 } else {
4530 while (!_matches(TokenType.EOF)) {
4531 _advance();
4532 }
4533 return new CompilationUnit(firstToken, scriptTag, directives, new List<C ompilationUnitMember>(), _currentToken);
4534 }
4535 }
4536 return new CompilationUnit(firstToken, scriptTag, directives, new List<Compi lationUnitMember>(), _currentToken);
4537 }
4538
4539 /**
4540 * Parse a documentation comment.
4541 *
4542 * <pre>
4543 * documentationComment ::=
4544 * multiLineComment?
4545 * | singleLineComment*
4546 * </pre>
4547 *
4548 * @return the documentation comment that was parsed, or `null` if there was n o comment
4549 */
4550 Comment _parseDocumentationComment() {
4551 List<Token> commentTokens = new List<Token>();
4552 Token commentToken = _currentToken.precedingComments;
4553 while (commentToken != null) {
4554 if (commentToken.type == TokenType.SINGLE_LINE_COMMENT) {
4555 if (StringUtilities.startsWith3(commentToken.lexeme, 0, 0x2F, 0x2F, 0x2F )) {
4556 if (commentTokens.length == 1 && StringUtilities.startsWith3(commentTo kens[0].lexeme, 0, 0x2F, 0x2A, 0x2A)) {
4557 commentTokens.clear();
4558 }
4559 commentTokens.add(commentToken);
4560 }
4561 } else {
4562 if (StringUtilities.startsWith3(commentToken.lexeme, 0, 0x2F, 0x2A, 0x2A )) {
4563 commentTokens.clear();
4564 commentTokens.add(commentToken);
4565 }
4566 }
4567 commentToken = commentToken.next;
4568 }
4569 if (commentTokens.isEmpty) {
4570 return null;
4571 }
4572 List<Token> tokens = new List.from(commentTokens);
4573 List<CommentReference> references = _parseCommentReferences(tokens);
4574 return Comment.createDocumentationCommentWithReferences(tokens, references);
4575 }
4576
4577 /**
4578 * Parse a do statement.
4579 *
4580 * <pre>
4581 * doStatement ::=
4582 * 'do' statement 'while' '(' expression ')' ';'
4583 * </pre>
4584 *
4585 * @return the do statement that was parsed
4586 */
4587 Statement _parseDoStatement() {
4588 bool wasInLoop = _inLoop;
4589 _inLoop = true;
4590 try {
4591 Token doKeyword = _expectKeyword(Keyword.DO);
4592 Statement body = parseStatement2();
4593 Token whileKeyword = _expectKeyword(Keyword.WHILE);
4594 Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
4595 Expression condition = parseExpression2();
4596 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
4597 Token semicolon = _expect(TokenType.SEMICOLON);
4598 return new DoStatement(doKeyword, body, whileKeyword, leftParenthesis, con dition, rightParenthesis, semicolon);
4599 } finally {
4600 _inLoop = wasInLoop;
4601 }
4602 }
4603
4604 /**
4605 * Parse an empty statement.
4606 *
4607 * <pre>
4608 * emptyStatement ::=
4609 * ';'
4610 * </pre>
4611 *
4612 * @return the empty statement that was parsed
4613 */
4614 Statement _parseEmptyStatement() => new EmptyStatement(andAdvance);
4615
4616 EnumConstantDeclaration _parseEnumConstantDeclaration() {
4617 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
4618 SimpleIdentifier name;
4619 if (_matchesIdentifier()) {
4620 name = parseSimpleIdentifier();
4621 } else {
4622 name = _createSyntheticIdentifier();
4623 }
4624 return new EnumConstantDeclaration(commentAndMetadata.comment, commentAndMet adata.metadata, name);
4625 }
4626
4627 /**
4628 * Parse an enum declaration.
4629 *
4630 * <pre>
4631 * enumType ::=
4632 * metadata 'enum' id '{' id (',' id)* (',')? '}'
4633 * </pre>
4634 *
4635 * @param commentAndMetadata the metadata to be associated with the member
4636 * @return the enum declaration that was parsed
4637 */
4638 EnumDeclaration _parseEnumDeclaration(CommentAndMetadata commentAndMetadata) {
4639 Token keyword = _expectKeyword(Keyword.ENUM);
4640 SimpleIdentifier name = parseSimpleIdentifier();
4641 Token leftBracket = null;
4642 List<EnumConstantDeclaration> constants = new List<EnumConstantDeclaration>( );
4643 Token rightBracket = null;
4644 if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
4645 leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET);
4646 if (_matchesIdentifier()) {
4647 constants.add(_parseEnumConstantDeclaration());
4648 } else if (_matches(TokenType.COMMA) && _tokenMatchesIdentifier(_peek())) {
4649 constants.add(_parseEnumConstantDeclaration());
4650 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER, []);
4651 } else {
4652 constants.add(_parseEnumConstantDeclaration());
4653 _reportErrorForCurrentToken(ParserErrorCode.EMPTY_ENUM_BODY, []);
4654 }
4655 while (_optional(TokenType.COMMA)) {
4656 if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
4657 break;
4658 }
4659 constants.add(_parseEnumConstantDeclaration());
4660 }
4661 rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
4662 } else {
4663 leftBracket = _createSyntheticToken(TokenType.OPEN_CURLY_BRACKET);
4664 rightBracket = _createSyntheticToken(TokenType.CLOSE_CURLY_BRACKET);
4665 _reportErrorForCurrentToken(ParserErrorCode.MISSING_ENUM_BODY, []);
4666 }
4667 return new EnumDeclaration(commentAndMetadata.comment, commentAndMetadata.me tadata, keyword, name, leftBracket, constants, rightBracket);
4668 }
4669
4670 /**
4671 * Parse an equality expression.
4672 *
4673 * <pre>
4674 * equalityExpression ::=
4675 * relationalExpression (equalityOperator relationalExpression)?
4676 * | 'super' equalityOperator relationalExpression
4677 * </pre>
4678 *
4679 * @return the equality expression that was parsed
4680 */
4681 Expression _parseEqualityExpression() {
4682 Expression expression;
4683 if (_matchesKeyword(Keyword.SUPER) && _currentToken.next.type.isEqualityOper ator) {
4684 expression = new SuperExpression(andAdvance);
4685 } else {
4686 expression = _parseRelationalExpression();
4687 }
4688 bool leftEqualityExpression = false;
4689 while (_currentToken.type.isEqualityOperator) {
4690 Token operator = andAdvance;
4691 if (leftEqualityExpression) {
4692 _reportErrorForNode(ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND, expression, []);
4693 }
4694 expression = new BinaryExpression(expression, operator, _parseRelationalEx pression());
4695 leftEqualityExpression = true;
4696 }
4697 return expression;
4698 }
4699
4700 /**
4701 * Parse an export directive.
4702 *
4703 * <pre>
4704 * exportDirective ::=
4705 * metadata 'export' stringLiteral combinator*';'
4706 * </pre>
4707 *
4708 * @param commentAndMetadata the metadata to be associated with the directive
4709 * @return the export directive that was parsed
4710 */
4711 ExportDirective _parseExportDirective(CommentAndMetadata commentAndMetadata) {
4712 Token exportKeyword = _expectKeyword(Keyword.EXPORT);
4713 StringLiteral libraryUri = parseStringLiteral();
4714 List<Combinator> combinators = _parseCombinators();
4715 Token semicolon = _expectSemicolon();
4716 return new ExportDirective(commentAndMetadata.comment, commentAndMetadata.me tadata, exportKeyword, libraryUri, combinators, semicolon);
4717 }
4718
4719 /**
4720 * Parse a list of expressions.
4721 *
4722 * <pre>
4723 * expressionList ::=
4724 * expression (',' expression)*
4725 * </pre>
4726 *
4727 * @return the expression that was parsed
4728 */
4729 List<Expression> _parseExpressionList() {
4730 List<Expression> expressions = new List<Expression>();
4731 expressions.add(parseExpression2());
4732 while (_optional(TokenType.COMMA)) {
4733 expressions.add(parseExpression2());
4734 }
4735 return expressions;
4736 }
4737
4738 /**
4739 * Parse the 'final', 'const', 'var' or type preceding a variable declaration.
4740 *
4741 * <pre>
4742 * finalConstVarOrType ::=
4743 * | 'final' type?
4744 * | 'const' type?
4745 * | 'var'
4746 * | type
4747 * </pre>
4748 *
4749 * @param optional `true` if the keyword and type are optional
4750 * @return the 'final', 'const', 'var' or type that was parsed
4751 */
4752 FinalConstVarOrType _parseFinalConstVarOrType(bool optional) {
4753 Token keyword = null;
4754 TypeName type = null;
4755 if (_matchesKeyword(Keyword.FINAL) || _matchesKeyword(Keyword.CONST)) {
4756 keyword = andAdvance;
4757 if (_isTypedIdentifier(_currentToken)) {
4758 type = parseTypeName();
4759 }
4760 } else if (_matchesKeyword(Keyword.VAR)) {
4761 keyword = andAdvance;
4762 } else {
4763 if (_isTypedIdentifier(_currentToken)) {
4764 type = parseReturnType();
4765 } else if (!optional) {
4766 _reportErrorForCurrentToken(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_T YPE, []);
4767 }
4768 }
4769 return new FinalConstVarOrType(keyword, type);
4770 }
4771
4772 /**
4773 * Parse a formal parameter. At most one of `isOptional` and `isNamed` can be
4774 * `true`.
4775 *
4776 * <pre>
4777 * defaultFormalParameter ::=
4778 * normalFormalParameter ('=' expression)?
4779 *
4780 * defaultNamedParameter ::=
4781 * normalFormalParameter (':' expression)?
4782 * </pre>
4783 *
4784 * @param kind the kind of parameter being expected based on the presence or a bsence of group
4785 * delimiters
4786 * @return the formal parameter that was parsed
4787 */
4788 FormalParameter _parseFormalParameter(ParameterKind kind) {
4789 NormalFormalParameter parameter = parseNormalFormalParameter();
4790 if (_matches(TokenType.EQ)) {
4791 Token seperator = andAdvance;
4792 Expression defaultValue = parseExpression2();
4793 if (kind == ParameterKind.NAMED) {
4794 _reportErrorForToken(ParserErrorCode.WRONG_SEPARATOR_FOR_NAMED_PARAMETER , seperator, []);
4795 } else if (kind == ParameterKind.REQUIRED) {
4796 _reportErrorForNode(ParserErrorCode.POSITIONAL_PARAMETER_OUTSIDE_GROUP, parameter, []);
4797 }
4798 return new DefaultFormalParameter(parameter, kind, seperator, defaultValue );
4799 } else if (_matches(TokenType.COLON)) {
4800 Token seperator = andAdvance;
4801 Expression defaultValue = parseExpression2();
4802 if (kind == ParameterKind.POSITIONAL) {
4803 _reportErrorForToken(ParserErrorCode.WRONG_SEPARATOR_FOR_POSITIONAL_PARA METER, seperator, []);
4804 } else if (kind == ParameterKind.REQUIRED) {
4805 _reportErrorForNode(ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP, param eter, []);
4806 }
4807 return new DefaultFormalParameter(parameter, kind, seperator, defaultValue );
4808 } else if (kind != ParameterKind.REQUIRED) {
4809 return new DefaultFormalParameter(parameter, kind, null, null);
4810 }
4811 return parameter;
4812 }
4813
4814 /**
4815 * Parse a for statement.
4816 *
4817 * <pre>
4818 * forStatement ::=
4819 * 'for' '(' forLoopParts ')' statement
4820 *
4821 * forLoopParts ::=
4822 * forInitializerStatement expression? ';' expressionList?
4823 * | declaredIdentifier 'in' expression
4824 * | identifier 'in' expression
4825 *
4826 * forInitializerStatement ::=
4827 * localVariableDeclaration ';'
4828 * | expression? ';'
4829 * </pre>
4830 *
4831 * @return the for statement that was parsed
4832 */
4833 Statement _parseForStatement() {
4834 bool wasInLoop = _inLoop;
4835 _inLoop = true;
4836 try {
4837 Token awaitKeyword = null;
4838 if (_matchesString(_AWAIT)) {
4839 awaitKeyword = andAdvance;
4840 }
4841 Token forKeyword = _expectKeyword(Keyword.FOR);
4842 Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
4843 VariableDeclarationList variableList = null;
4844 Expression initialization = null;
4845 if (!_matches(TokenType.SEMICOLON)) {
4846 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
4847 if (_matchesIdentifier() && _tokenMatchesKeyword(_peek(), Keyword.IN)) {
4848 List<VariableDeclaration> variables = new List<VariableDeclaration>();
4849 SimpleIdentifier variableName = parseSimpleIdentifier();
4850 variables.add(new VariableDeclaration(null, null, variableName, null, null));
4851 variableList = new VariableDeclarationList(commentAndMetadata.comment, commentAndMetadata.metadata, null, null, variables);
4852 } else if (_isInitializedVariableDeclaration()) {
4853 variableList = _parseVariableDeclarationListAfterMetadata(commentAndMe tadata);
4854 } else {
4855 initialization = parseExpression2();
4856 }
4857 if (_matchesKeyword(Keyword.IN)) {
4858 DeclaredIdentifier loopVariable = null;
4859 SimpleIdentifier identifier = null;
4860 if (variableList == null) {
4861 // We found: <expression> 'in'
4862 _reportErrorForCurrentToken(ParserErrorCode.MISSING_VARIABLE_IN_FOR_ EACH, []);
4863 } else {
4864 NodeList<VariableDeclaration> variables = variableList.variables;
4865 if (variables.length > 1) {
4866 _reportErrorForCurrentToken(ParserErrorCode.MULTIPLE_VARIABLES_IN_ FOR_EACH, [variables.length.toString()]);
4867 }
4868 VariableDeclaration variable = variables[0];
4869 if (variable.initializer != null) {
4870 _reportErrorForCurrentToken(ParserErrorCode.INITIALIZED_VARIABLE_I N_FOR_EACH, []);
4871 }
4872 Token keyword = variableList.keyword;
4873 TypeName type = variableList.type;
4874 if (keyword != null || type != null) {
4875 loopVariable = new DeclaredIdentifier(commentAndMetadata.comment, commentAndMetadata.metadata, keyword, type, variable.name);
4876 } else {
4877 if (!commentAndMetadata.metadata.isEmpty) {
4878 }
4879 identifier = variable.name;
4880 }
4881 }
4882 Token inKeyword = _expectKeyword(Keyword.IN);
4883 Expression iterator = parseExpression2();
4884 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
4885 Statement body = parseStatement2();
4886 if (loopVariable == null) {
4887 return new ForEachStatement.con2(awaitKeyword, forKeyword, leftParen thesis, identifier, inKeyword, iterator, rightParenthesis, body);
4888 }
4889 return new ForEachStatement.con1(awaitKeyword, forKeyword, leftParenth esis, loopVariable, inKeyword, iterator, rightParenthesis, body);
4890 }
4891 }
4892 if (awaitKeyword != null) {
4893 _reportErrorForToken(ParserErrorCode.INVALID_AWAIT_IN_FOR, awaitKeyword, []);
4894 }
4895 Token leftSeparator = _expect(TokenType.SEMICOLON);
4896 Expression condition = null;
4897 if (!_matches(TokenType.SEMICOLON)) {
4898 condition = parseExpression2();
4899 }
4900 Token rightSeparator = _expect(TokenType.SEMICOLON);
4901 List<Expression> updaters = null;
4902 if (!_matches(TokenType.CLOSE_PAREN)) {
4903 updaters = _parseExpressionList();
4904 }
4905 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
4906 Statement body = parseStatement2();
4907 return new ForStatement(forKeyword, leftParenthesis, variableList, initial ization, leftSeparator, condition, rightSeparator, updaters, rightParenthesis, b ody);
4908 } finally {
4909 _inLoop = wasInLoop;
4910 }
4911 }
4912
4913 /**
4914 * Parse a function body.
4915 *
4916 * <pre>
4917 * functionBody ::=
4918 * '=>' expression ';'
4919 * | block
4920 *
4921 * functionExpressionBody ::=
4922 * '=>' expression
4923 * | block
4924 * </pre>
4925 *
4926 * @param mayBeEmpty `true` if the function body is allowed to be empty
4927 * @param emptyErrorCode the error code to report if function body expected, b ut not found
4928 * @param inExpression `true` if the function body is being parsed as part of an expression
4929 * and therefore does not have a terminating semicolon
4930 * @return the function body that was parsed
4931 */
4932 FunctionBody _parseFunctionBody(bool mayBeEmpty, ParserErrorCode emptyErrorCod e, bool inExpression) {
4933 bool wasInAsync = _inAsync;
4934 bool wasInLoop = _inLoop;
4935 bool wasInSwitch = _inSwitch;
4936 _inAsync = false;
4937 _inLoop = false;
4938 _inSwitch = false;
4939 try {
4940 if (_matches(TokenType.SEMICOLON)) {
4941 if (!mayBeEmpty) {
4942 _reportErrorForCurrentToken(emptyErrorCode, []);
4943 }
4944 return new EmptyFunctionBody(andAdvance);
4945 } else if (_matchesString(_NATIVE)) {
4946 Token nativeToken = andAdvance;
4947 StringLiteral stringLiteral = null;
4948 if (_matches(TokenType.STRING)) {
4949 stringLiteral = parseStringLiteral();
4950 }
4951 return new NativeFunctionBody(nativeToken, stringLiteral, _expect(TokenT ype.SEMICOLON));
4952 }
4953 Token keyword = null;
4954 Token star = null;
4955 if (_parseAsync) {
4956 if (_matchesString(ASYNC)) {
4957 keyword = andAdvance;
4958 if (_matches(TokenType.STAR)) {
4959 star = andAdvance;
4960 }
4961 _inAsync = true;
4962 } else if (_matchesString(SYNC)) {
4963 keyword = andAdvance;
4964 if (_matches(TokenType.STAR)) {
4965 star = andAdvance;
4966 }
4967 }
4968 }
4969 if (_matches(TokenType.FUNCTION)) {
4970 if (keyword != null) {
4971 if (!_tokenMatchesString(keyword, ASYNC)) {
4972 _reportErrorForToken(ParserErrorCode.INVALID_SYNC, keyword, []);
4973 keyword = null;
4974 } else if (star != null) {
4975 _reportErrorForToken(ParserErrorCode.INVALID_STAR_AFTER_ASYNC, star, []);
4976 }
4977 }
4978 Token functionDefinition = andAdvance;
4979 Expression expression = parseExpression2();
4980 Token semicolon = null;
4981 if (!inExpression) {
4982 semicolon = _expect(TokenType.SEMICOLON);
4983 }
4984 if (!_parseFunctionBodies) {
4985 return new EmptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON ));
4986 }
4987 return new ExpressionFunctionBody(keyword, functionDefinition, expressio n, semicolon);
4988 } else if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
4989 if (keyword != null) {
4990 if (_tokenMatchesString(keyword, SYNC) && star == null) {
4991 _reportErrorForToken(ParserErrorCode.MISSING_STAR_AFTER_SYNC, keywor d, []);
4992 }
4993 }
4994 if (!_parseFunctionBodies) {
4995 _skipBlock();
4996 return new EmptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON ));
4997 }
4998 return new BlockFunctionBody(keyword, star, parseBlock());
4999 } else {
5000 // Invalid function body
5001 _reportErrorForCurrentToken(emptyErrorCode, []);
5002 return new EmptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON)) ;
5003 }
5004 } finally {
5005 _inAsync = wasInAsync;
5006 _inLoop = wasInLoop;
5007 _inSwitch = wasInSwitch;
5008 }
5009 }
5010
5011 /**
5012 * Parse a function declaration.
5013 *
5014 * <pre>
5015 * functionDeclaration ::=
5016 * functionSignature functionBody
5017 * | returnType? getOrSet identifier formalParameterList functionBody
5018 * </pre>
5019 *
5020 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
5021 * declaration
5022 * @param externalKeyword the 'external' keyword, or `null` if the function is not external
5023 * @param returnType the return type, or `null` if there is no return type
5024 * @param isStatement `true` if the function declaration is being parsed as a statement
5025 * @return the function declaration that was parsed
5026 */
5027 FunctionDeclaration _parseFunctionDeclaration(CommentAndMetadata commentAndMet adata, Token externalKeyword, TypeName returnType) {
5028 Token keyword = null;
5029 bool isGetter = false;
5030 if (_matchesKeyword(Keyword.GET) && !_tokenMatches(_peek(), TokenType.OPEN_P AREN)) {
5031 keyword = andAdvance;
5032 isGetter = true;
5033 } else if (_matchesKeyword(Keyword.SET) && !_tokenMatches(_peek(), TokenType .OPEN_PAREN)) {
5034 keyword = andAdvance;
5035 }
5036 SimpleIdentifier name = parseSimpleIdentifier();
5037 FormalParameterList parameters = null;
5038 if (!isGetter) {
5039 if (_matches(TokenType.OPEN_PAREN)) {
5040 parameters = parseFormalParameterList();
5041 _validateFormalParameterList(parameters);
5042 } else {
5043 _reportErrorForCurrentToken(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, []);
5044 }
5045 } else if (_matches(TokenType.OPEN_PAREN)) {
5046 _reportErrorForCurrentToken(ParserErrorCode.GETTER_WITH_PARAMETERS, []);
5047 parseFormalParameterList();
5048 }
5049 FunctionBody body;
5050 if (externalKeyword == null) {
5051 body = _parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTION_BODY, fa lse);
5052 } else {
5053 body = new EmptyFunctionBody(_expect(TokenType.SEMICOLON));
5054 }
5055 // if (!isStatement && matches(TokenType.SEMICOLON)) {
5056 // // TODO(brianwilkerson) Improve this error message.
5057 // reportError(ParserErrorCode.UNEXPECTED_TOKEN, currentToken.getLexeme ());
5058 // advance();
5059 // }
5060 return new FunctionDeclaration(commentAndMetadata.comment, commentAndMetadat a.metadata, externalKeyword, returnType, keyword, name, new FunctionExpression(p arameters, body));
5061 }
5062
5063 /**
5064 * Parse a function declaration statement.
5065 *
5066 * <pre>
5067 * functionDeclarationStatement ::=
5068 * functionSignature functionBody
5069 * </pre>
5070 *
5071 * @return the function declaration statement that was parsed
5072 */
5073 Statement _parseFunctionDeclarationStatement() {
5074 Modifiers modifiers = _parseModifiers();
5075 _validateModifiersForFunctionDeclarationStatement(modifiers);
5076 return _parseFunctionDeclarationStatementAfterReturnType(_parseCommentAndMet adata(), _parseOptionalReturnType());
5077 }
5078
5079 /**
5080 * Parse a function declaration statement.
5081 *
5082 * <pre>
5083 * functionDeclarationStatement ::=
5084 * functionSignature functionBody
5085 * </pre>
5086 *
5087 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
5088 * declaration
5089 * @param returnType the return type, or `null` if there is no return type
5090 * @return the function declaration statement that was parsed
5091 */
5092 Statement _parseFunctionDeclarationStatementAfterReturnType(CommentAndMetadata commentAndMetadata, TypeName returnType) {
5093 FunctionDeclaration declaration = _parseFunctionDeclaration(commentAndMetada ta, null, returnType);
5094 Token propertyKeyword = declaration.propertyKeyword;
5095 if (propertyKeyword != null) {
5096 if ((propertyKeyword as KeywordToken).keyword == Keyword.GET) {
5097 _reportErrorForToken(ParserErrorCode.GETTER_IN_FUNCTION, propertyKeyword , []);
5098 } else {
5099 _reportErrorForToken(ParserErrorCode.SETTER_IN_FUNCTION, propertyKeyword , []);
5100 }
5101 }
5102 return new FunctionDeclarationStatement(declaration);
5103 }
5104
5105 /**
5106 * Parse a function type alias.
5107 *
5108 * <pre>
5109 * functionTypeAlias ::=
5110 * functionPrefix typeParameterList? formalParameterList ';'
5111 *
5112 * functionPrefix ::=
5113 * returnType? name
5114 * </pre>
5115 *
5116 * @param commentAndMetadata the metadata to be associated with the member
5117 * @param keyword the token representing the 'typedef' keyword
5118 * @return the function type alias that was parsed
5119 */
5120 FunctionTypeAlias _parseFunctionTypeAlias(CommentAndMetadata commentAndMetadat a, Token keyword) {
5121 TypeName returnType = null;
5122 if (hasReturnTypeInTypeAlias) {
5123 returnType = parseReturnType();
5124 }
5125 SimpleIdentifier name = parseSimpleIdentifier();
5126 TypeParameterList typeParameters = null;
5127 if (_matches(TokenType.LT)) {
5128 typeParameters = parseTypeParameterList();
5129 }
5130 if (_matches(TokenType.SEMICOLON) || _matches(TokenType.EOF)) {
5131 _reportErrorForCurrentToken(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, [] );
5132 FormalParameterList parameters = new FormalParameterList(_createSyntheticT oken(TokenType.OPEN_PAREN), null, null, null, _createSyntheticToken(TokenType.CL OSE_PAREN));
5133 Token semicolon = _expect(TokenType.SEMICOLON);
5134 return new FunctionTypeAlias(commentAndMetadata.comment, commentAndMetadat a.metadata, keyword, returnType, name, typeParameters, parameters, semicolon);
5135 } else if (!_matches(TokenType.OPEN_PAREN)) {
5136 _reportErrorForCurrentToken(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, [] );
5137 // TODO(brianwilkerson) Recover from this error. At the very least we shou ld skip to the start
5138 // of the next valid compilation unit member, allowing for the possibility of finding the
5139 // typedef parameters before that point.
5140 return new FunctionTypeAlias(commentAndMetadata.comment, commentAndMetadat a.metadata, keyword, returnType, name, typeParameters, new FormalParameterList(_ createSyntheticToken(TokenType.OPEN_PAREN), null, null, null, _createSyntheticTo ken(TokenType.CLOSE_PAREN)), _createSyntheticToken(TokenType.SEMICOLON));
5141 }
5142 FormalParameterList parameters = parseFormalParameterList();
5143 _validateFormalParameterList(parameters);
5144 Token semicolon = _expect(TokenType.SEMICOLON);
5145 return new FunctionTypeAlias(commentAndMetadata.comment, commentAndMetadata. metadata, keyword, returnType, name, typeParameters, parameters, semicolon);
5146 }
5147
5148 /**
5149 * Parse a getter.
5150 *
5151 * <pre>
5152 * getter ::=
5153 * getterSignature functionBody?
5154 *
5155 * getterSignature ::=
5156 * 'external'? 'static'? returnType? 'get' identifier
5157 * </pre>
5158 *
5159 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
5160 * declaration
5161 * @param externalKeyword the 'external' token
5162 * @param staticKeyword the static keyword, or `null` if the getter is not sta tic
5163 * @param the return type that has already been parsed, or `null` if there was no return
5164 * type
5165 * @return the getter that was parsed
5166 */
5167 MethodDeclaration _parseGetter(CommentAndMetadata commentAndMetadata, Token ex ternalKeyword, Token staticKeyword, TypeName returnType) {
5168 Token propertyKeyword = _expectKeyword(Keyword.GET);
5169 SimpleIdentifier name = parseSimpleIdentifier();
5170 if (_matches(TokenType.OPEN_PAREN) && _tokenMatches(_peek(), TokenType.CLOSE _PAREN)) {
5171 _reportErrorForCurrentToken(ParserErrorCode.GETTER_WITH_PARAMETERS, []);
5172 _advance();
5173 _advance();
5174 }
5175 FunctionBody body = _parseFunctionBody(externalKeyword != null || staticKeyw ord == null, ParserErrorCode.STATIC_GETTER_WITHOUT_BODY, false);
5176 if (externalKeyword != null && body is! EmptyFunctionBody) {
5177 _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_GETTER_WITH_BODY, []) ;
5178 }
5179 return new MethodDeclaration(commentAndMetadata.comment, commentAndMetadata. metadata, externalKeyword, staticKeyword, returnType, propertyKeyword, null, nam e, null, body);
5180 }
5181
5182 /**
5183 * Parse a list of identifiers.
5184 *
5185 * <pre>
5186 * identifierList ::=
5187 * identifier (',' identifier)*
5188 * </pre>
5189 *
5190 * @return the list of identifiers that were parsed
5191 */
5192 List<SimpleIdentifier> _parseIdentifierList() {
5193 List<SimpleIdentifier> identifiers = new List<SimpleIdentifier>();
5194 identifiers.add(parseSimpleIdentifier());
5195 while (_matches(TokenType.COMMA)) {
5196 _advance();
5197 identifiers.add(parseSimpleIdentifier());
5198 }
5199 return identifiers;
5200 }
5201
5202 /**
5203 * Parse an if statement.
5204 *
5205 * <pre>
5206 * ifStatement ::=
5207 * 'if' '(' expression ')' statement ('else' statement)?
5208 * </pre>
5209 *
5210 * @return the if statement that was parsed
5211 */
5212 Statement _parseIfStatement() {
5213 Token ifKeyword = _expectKeyword(Keyword.IF);
5214 Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
5215 Expression condition = parseExpression2();
5216 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
5217 Statement thenStatement = parseStatement2();
5218 Token elseKeyword = null;
5219 Statement elseStatement = null;
5220 if (_matchesKeyword(Keyword.ELSE)) {
5221 elseKeyword = andAdvance;
5222 elseStatement = parseStatement2();
5223 }
5224 return new IfStatement(ifKeyword, leftParenthesis, condition, rightParenthes is, thenStatement, elseKeyword, elseStatement);
5225 }
5226
5227 /**
5228 * Parse an import directive.
5229 *
5230 * <pre>
5231 * importDirective ::=
5232 * metadata 'import' stringLiteral ('as' identifier)? combinator*';'
5233 * </pre>
5234 *
5235 * @param commentAndMetadata the metadata to be associated with the directive
5236 * @return the import directive that was parsed
5237 */
5238 ImportDirective _parseImportDirective(CommentAndMetadata commentAndMetadata) {
5239 Token importKeyword = _expectKeyword(Keyword.IMPORT);
5240 StringLiteral libraryUri = parseStringLiteral();
5241 Token deferredToken = null;
5242 Token asToken = null;
5243 SimpleIdentifier prefix = null;
5244 if (_matchesKeyword(Keyword.DEFERRED)) {
5245 if (_parseDeferredLibraries) {
5246 deferredToken = andAdvance;
5247 } else {
5248 _reportErrorForCurrentToken(ParserErrorCode.DEFERRED_IMPORTS_NOT_SUPPORT ED, []);
5249 _advance();
5250 }
5251 }
5252 if (_matchesKeyword(Keyword.AS)) {
5253 asToken = andAdvance;
5254 prefix = parseSimpleIdentifier();
5255 } else if (deferredToken != null) {
5256 _reportErrorForCurrentToken(ParserErrorCode.MISSING_PREFIX_IN_DEFERRED_IMP ORT, []);
5257 }
5258 List<Combinator> combinators = _parseCombinators();
5259 Token semicolon = _expectSemicolon();
5260 return new ImportDirective(commentAndMetadata.comment, commentAndMetadata.me tadata, importKeyword, libraryUri, deferredToken, asToken, prefix, combinators, semicolon);
5261 }
5262
5263 /**
5264 * Parse a list of initialized identifiers.
5265 *
5266 * <pre>
5267 * ?? ::=
5268 * 'static'? ('var' | type) initializedIdentifierList ';'
5269 * | 'final' type? initializedIdentifierList ';'
5270 *
5271 * initializedIdentifierList ::=
5272 * initializedIdentifier (',' initializedIdentifier)*
5273 *
5274 * initializedIdentifier ::=
5275 * identifier ('=' expression)?
5276 * </pre>
5277 *
5278 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
5279 * declaration
5280 * @param staticKeyword the static keyword, or `null` if the getter is not sta tic
5281 * @param keyword the token representing the 'final', 'const' or 'var' keyword , or `null` if
5282 * there is no keyword
5283 * @param type the type that has already been parsed, or `null` if 'var' was p rovided
5284 * @return the getter that was parsed
5285 */
5286 FieldDeclaration _parseInitializedIdentifierList(CommentAndMetadata commentAnd Metadata, Token staticKeyword, Token keyword, TypeName type) {
5287 VariableDeclarationList fieldList = _parseVariableDeclarationListAfterType(n ull, keyword, type);
5288 return new FieldDeclaration(commentAndMetadata.comment, commentAndMetadata.m etadata, staticKeyword, fieldList, _expect(TokenType.SEMICOLON));
5289 }
5290
5291 /**
5292 * Parse an instance creation expression.
5293 *
5294 * <pre>
5295 * instanceCreationExpression ::=
5296 * ('new' | 'const') type ('.' identifier)? argumentList
5297 * </pre>
5298 *
5299 * @param keyword the 'new' or 'const' keyword that introduces the expression
5300 * @return the instance creation expression that was parsed
5301 */
5302 InstanceCreationExpression _parseInstanceCreationExpression(Token keyword) {
5303 ConstructorName constructorName = parseConstructorName();
5304 ArgumentList argumentList = parseArgumentList();
5305 return new InstanceCreationExpression(keyword, constructorName, argumentList );
5306 }
5307
5308 /**
5309 * Parse a library directive.
5310 *
5311 * <pre>
5312 * libraryDirective ::=
5313 * metadata 'library' identifier ';'
5314 * </pre>
5315 *
5316 * @param commentAndMetadata the metadata to be associated with the directive
5317 * @return the library directive that was parsed
5318 */
5319 LibraryDirective _parseLibraryDirective(CommentAndMetadata commentAndMetadata) {
5320 Token keyword = _expectKeyword(Keyword.LIBRARY);
5321 LibraryIdentifier libraryName = _parseLibraryName(ParserErrorCode.MISSING_NA ME_IN_LIBRARY_DIRECTIVE, keyword);
5322 Token semicolon = _expect(TokenType.SEMICOLON);
5323 return new LibraryDirective(commentAndMetadata.comment, commentAndMetadata.m etadata, keyword, libraryName, semicolon);
5324 }
5325
5326 /**
5327 * Parse a library name.
5328 *
5329 * <pre>
5330 * libraryName ::=
5331 * libraryIdentifier
5332 * </pre>
5333 *
5334 * @param missingNameError the error code to be used if the library name is mi ssing
5335 * @param missingNameToken the token associated with the error produced if the library name is
5336 * missing
5337 * @return the library name that was parsed
5338 */
5339 LibraryIdentifier _parseLibraryName(ParserErrorCode missingNameError, Token mi ssingNameToken) {
5340 if (_matchesIdentifier()) {
5341 return parseLibraryIdentifier();
5342 } else if (_matches(TokenType.STRING)) {
5343 // TODO(brianwilkerson) Recovery: This should be extended to handle arbitr ary tokens until we
5344 // can find a token that can start a compilation unit member.
5345 StringLiteral string = parseStringLiteral();
5346 _reportErrorForNode(ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME, string, [ ]);
5347 } else {
5348 _reportErrorForToken(missingNameError, missingNameToken, []);
5349 }
5350 List<SimpleIdentifier> components = new List<SimpleIdentifier>();
5351 components.add(_createSyntheticIdentifier());
5352 return new LibraryIdentifier(components);
5353 }
5354
5355 /**
5356 * Parse a list literal.
5357 *
5358 * <pre>
5359 * listLiteral ::=
5360 * 'const'? typeArguments? '[' (expressionList ','?)? ']'
5361 * </pre>
5362 *
5363 * @param modifier the 'const' modifier appearing before the literal, or `null ` if there is
5364 * no modifier
5365 * @param typeArguments the type arguments appearing before the literal, or `n ull` if there
5366 * are no type arguments
5367 * @return the list literal that was parsed
5368 */
5369 ListLiteral _parseListLiteral(Token modifier, TypeArgumentList typeArguments) {
5370 // may be empty list literal
5371 if (_matches(TokenType.INDEX)) {
5372 BeginToken leftBracket = new BeginToken(TokenType.OPEN_SQUARE_BRACKET, _cu rrentToken.offset);
5373 Token rightBracket = new Token(TokenType.CLOSE_SQUARE_BRACKET, _currentTok en.offset + 1);
5374 leftBracket.endToken = rightBracket;
5375 rightBracket.setNext(_currentToken.next);
5376 leftBracket.setNext(rightBracket);
5377 _currentToken.previous.setNext(leftBracket);
5378 _currentToken = _currentToken.next;
5379 return new ListLiteral(modifier, typeArguments, leftBracket, null, rightBr acket);
5380 }
5381 // open
5382 Token leftBracket = _expect(TokenType.OPEN_SQUARE_BRACKET);
5383 if (_matches(TokenType.CLOSE_SQUARE_BRACKET)) {
5384 return new ListLiteral(modifier, typeArguments, leftBracket, null, andAdva nce);
5385 }
5386 bool wasInInitializer = _inInitializer;
5387 _inInitializer = false;
5388 try {
5389 List<Expression> elements = new List<Expression>();
5390 elements.add(parseExpression2());
5391 while (_optional(TokenType.COMMA)) {
5392 if (_matches(TokenType.CLOSE_SQUARE_BRACKET)) {
5393 return new ListLiteral(modifier, typeArguments, leftBracket, elements, andAdvance);
5394 }
5395 elements.add(parseExpression2());
5396 }
5397 Token rightBracket = _expect(TokenType.CLOSE_SQUARE_BRACKET);
5398 return new ListLiteral(modifier, typeArguments, leftBracket, elements, rig htBracket);
5399 } finally {
5400 _inInitializer = wasInInitializer;
5401 }
5402 }
5403
5404 /**
5405 * Parse a list or map literal.
5406 *
5407 * <pre>
5408 * listOrMapLiteral ::=
5409 * listLiteral
5410 * | mapLiteral
5411 * </pre>
5412 *
5413 * @param modifier the 'const' modifier appearing before the literal, or `null ` if there is
5414 * no modifier
5415 * @return the list or map literal that was parsed
5416 */
5417 TypedLiteral _parseListOrMapLiteral(Token modifier) {
5418 TypeArgumentList typeArguments = null;
5419 if (_matches(TokenType.LT)) {
5420 typeArguments = parseTypeArgumentList();
5421 }
5422 if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
5423 return _parseMapLiteral(modifier, typeArguments);
5424 } else if (_matches(TokenType.OPEN_SQUARE_BRACKET) || _matches(TokenType.IND EX)) {
5425 return _parseListLiteral(modifier, typeArguments);
5426 }
5427 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL, [] );
5428 return new ListLiteral(modifier, typeArguments, _createSyntheticToken(TokenT ype.OPEN_SQUARE_BRACKET), null, _createSyntheticToken(TokenType.CLOSE_SQUARE_BRA CKET));
5429 }
5430
5431 /**
5432 * Parse a logical and expression.
5433 *
5434 * <pre>
5435 * logicalAndExpression ::=
5436 * equalityExpression ('&&' equalityExpression)*
5437 * </pre>
5438 *
5439 * @return the logical and expression that was parsed
5440 */
5441 Expression _parseLogicalAndExpression() {
5442 Expression expression = _parseEqualityExpression();
5443 while (_matches(TokenType.AMPERSAND_AMPERSAND)) {
5444 Token operator = andAdvance;
5445 expression = new BinaryExpression(expression, operator, _parseEqualityExpr ession());
5446 }
5447 return expression;
5448 }
5449
5450 /**
5451 * Parse a map literal.
5452 *
5453 * <pre>
5454 * mapLiteral ::=
5455 * 'const'? typeArguments? '{' (mapLiteralEntry (',' mapLiteralEntry)* ',' ?)? '}'
5456 * </pre>
5457 *
5458 * @param modifier the 'const' modifier appearing before the literal, or `null ` if there is
5459 * no modifier
5460 * @param typeArguments the type arguments that were declared, or `null` if th ere are no
5461 * type arguments
5462 * @return the map literal that was parsed
5463 */
5464 MapLiteral _parseMapLiteral(Token modifier, TypeArgumentList typeArguments) {
5465 Token leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET);
5466 List<MapLiteralEntry> entries = new List<MapLiteralEntry>();
5467 if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
5468 return new MapLiteral(modifier, typeArguments, leftBracket, entries, andAd vance);
5469 }
5470 bool wasInInitializer = _inInitializer;
5471 _inInitializer = false;
5472 try {
5473 entries.add(parseMapLiteralEntry());
5474 while (_optional(TokenType.COMMA)) {
5475 if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
5476 return new MapLiteral(modifier, typeArguments, leftBracket, entries, a ndAdvance);
5477 }
5478 entries.add(parseMapLiteralEntry());
5479 }
5480 Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
5481 return new MapLiteral(modifier, typeArguments, leftBracket, entries, right Bracket);
5482 } finally {
5483 _inInitializer = wasInInitializer;
5484 }
5485 }
5486
5487 /**
5488 * Parse a method declaration.
5489 *
5490 * <pre>
5491 * functionDeclaration ::=
5492 * ('external' 'static'?)? functionSignature functionBody
5493 * | 'external'? functionSignature ';'
5494 * </pre>
5495 *
5496 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
5497 * declaration
5498 * @param externalKeyword the 'external' token
5499 * @param staticKeyword the static keyword, or `null` if the getter is not sta tic
5500 * @param returnType the return type of the method
5501 * @param name the name of the method
5502 * @param parameters the parameters to the method
5503 * @return the method declaration that was parsed
5504 */
5505 MethodDeclaration _parseMethodDeclarationAfterParameters(CommentAndMetadata co mmentAndMetadata, Token externalKeyword, Token staticKeyword, TypeName returnTyp e, SimpleIdentifier name, FormalParameterList parameters) {
5506 FunctionBody body = _parseFunctionBody(externalKeyword != null || staticKeyw ord == null, ParserErrorCode.MISSING_FUNCTION_BODY, false);
5507 if (externalKeyword != null) {
5508 if (body is! EmptyFunctionBody) {
5509 _reportErrorForNode(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, body, []) ;
5510 }
5511 } else if (staticKeyword != null) {
5512 if (body is EmptyFunctionBody) {
5513 _reportErrorForNode(ParserErrorCode.ABSTRACT_STATIC_METHOD, body, []);
5514 }
5515 }
5516 return new MethodDeclaration(commentAndMetadata.comment, commentAndMetadata. metadata, externalKeyword, staticKeyword, returnType, null, null, name, paramete rs, body);
5517 }
5518
5519 /**
5520 * Parse a method declaration.
5521 *
5522 * <pre>
5523 * functionDeclaration ::=
5524 * 'external'? 'static'? functionSignature functionBody
5525 * | 'external'? functionSignature ';'
5526 * </pre>
5527 *
5528 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
5529 * declaration
5530 * @param externalKeyword the 'external' token
5531 * @param staticKeyword the static keyword, or `null` if the getter is not sta tic
5532 * @param returnType the return type of the method
5533 * @return the method declaration that was parsed
5534 */
5535 MethodDeclaration _parseMethodDeclarationAfterReturnType(CommentAndMetadata co mmentAndMetadata, Token externalKeyword, Token staticKeyword, TypeName returnTyp e) {
5536 SimpleIdentifier methodName = parseSimpleIdentifier();
5537 FormalParameterList parameters = parseFormalParameterList();
5538 _validateFormalParameterList(parameters);
5539 return _parseMethodDeclarationAfterParameters(commentAndMetadata, externalKe yword, staticKeyword, returnType, methodName, parameters);
5540 }
5541
5542 /**
5543 * Parse the modifiers preceding a declaration. This method allows the modifie rs to appear in any
5544 * order but does generate errors for duplicated modifiers. Checks for other p roblems, such as
5545 * having the modifiers appear in the wrong order or specifying both 'const' a nd 'final', are
5546 * reported in one of the methods whose name is prefixed with `validateModifie rsFor`.
5547 *
5548 * <pre>
5549 * modifiers ::=
5550 * ('abstract' | 'const' | 'external' | 'factory' | 'final' | 'static' | ' var')*
5551 * </pre>
5552 *
5553 * @return the modifiers that were parsed
5554 */
5555 Modifiers _parseModifiers() {
5556 Modifiers modifiers = new Modifiers();
5557 bool progress = true;
5558 while (progress) {
5559 if (_tokenMatches(_peek(), TokenType.PERIOD) || _tokenMatches(_peek(), Tok enType.LT) || _tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
5560 return modifiers;
5561 }
5562 if (_matchesKeyword(Keyword.ABSTRACT)) {
5563 if (modifiers.abstractKeyword != null) {
5564 _reportErrorForCurrentToken(ParserErrorCode.DUPLICATED_MODIFIER, [_cur rentToken.lexeme]);
5565 _advance();
5566 } else {
5567 modifiers.abstractKeyword = andAdvance;
5568 }
5569 } else if (_matchesKeyword(Keyword.CONST)) {
5570 if (modifiers.constKeyword != null) {
5571 _reportErrorForCurrentToken(ParserErrorCode.DUPLICATED_MODIFIER, [_cur rentToken.lexeme]);
5572 _advance();
5573 } else {
5574 modifiers.constKeyword = andAdvance;
5575 }
5576 } else if (_matchesKeyword(Keyword.EXTERNAL) && !_tokenMatches(_peek(), To kenType.PERIOD) && !_tokenMatches(_peek(), TokenType.LT)) {
5577 if (modifiers.externalKeyword != null) {
5578 _reportErrorForCurrentToken(ParserErrorCode.DUPLICATED_MODIFIER, [_cur rentToken.lexeme]);
5579 _advance();
5580 } else {
5581 modifiers.externalKeyword = andAdvance;
5582 }
5583 } else if (_matchesKeyword(Keyword.FACTORY) && !_tokenMatches(_peek(), Tok enType.PERIOD) && !_tokenMatches(_peek(), TokenType.LT)) {
5584 if (modifiers.factoryKeyword != null) {
5585 _reportErrorForCurrentToken(ParserErrorCode.DUPLICATED_MODIFIER, [_cur rentToken.lexeme]);
5586 _advance();
5587 } else {
5588 modifiers.factoryKeyword = andAdvance;
5589 }
5590 } else if (_matchesKeyword(Keyword.FINAL)) {
5591 if (modifiers.finalKeyword != null) {
5592 _reportErrorForCurrentToken(ParserErrorCode.DUPLICATED_MODIFIER, [_cur rentToken.lexeme]);
5593 _advance();
5594 } else {
5595 modifiers.finalKeyword = andAdvance;
5596 }
5597 } else if (_matchesKeyword(Keyword.STATIC) && !_tokenMatches(_peek(), Toke nType.PERIOD) && !_tokenMatches(_peek(), TokenType.LT)) {
5598 if (modifiers.staticKeyword != null) {
5599 _reportErrorForCurrentToken(ParserErrorCode.DUPLICATED_MODIFIER, [_cur rentToken.lexeme]);
5600 _advance();
5601 } else {
5602 modifiers.staticKeyword = andAdvance;
5603 }
5604 } else if (_matchesKeyword(Keyword.VAR)) {
5605 if (modifiers.varKeyword != null) {
5606 _reportErrorForCurrentToken(ParserErrorCode.DUPLICATED_MODIFIER, [_cur rentToken.lexeme]);
5607 _advance();
5608 } else {
5609 modifiers.varKeyword = andAdvance;
5610 }
5611 } else {
5612 progress = false;
5613 }
5614 }
5615 return modifiers;
5616 }
5617
5618 /**
5619 * Parse a multiplicative expression.
5620 *
5621 * <pre>
5622 * multiplicativeExpression ::=
5623 * unaryExpression (multiplicativeOperator unaryExpression)*
5624 * | 'super' (multiplicativeOperator unaryExpression)+
5625 * </pre>
5626 *
5627 * @return the multiplicative expression that was parsed
5628 */
5629 Expression _parseMultiplicativeExpression() {
5630 Expression expression;
5631 if (_matchesKeyword(Keyword.SUPER) && _currentToken.next.type.isMultiplicati veOperator) {
5632 expression = new SuperExpression(andAdvance);
5633 } else {
5634 expression = _parseUnaryExpression();
5635 }
5636 while (_currentToken.type.isMultiplicativeOperator) {
5637 Token operator = andAdvance;
5638 expression = new BinaryExpression(expression, operator, _parseUnaryExpress ion());
5639 }
5640 return expression;
5641 }
5642
5643 /**
5644 * Parse a class native clause.
5645 *
5646 * <pre>
5647 * classNativeClause ::=
5648 * 'native' name
5649 * </pre>
5650 *
5651 * @return the class native clause that was parsed
5652 */
5653 NativeClause _parseNativeClause() {
5654 Token keyword = andAdvance;
5655 StringLiteral name = parseStringLiteral();
5656 return new NativeClause(keyword, name);
5657 }
5658
5659 /**
5660 * Parse a new expression.
5661 *
5662 * <pre>
5663 * newExpression ::=
5664 * instanceCreationExpression
5665 * </pre>
5666 *
5667 * @return the new expression that was parsed
5668 */
5669 InstanceCreationExpression _parseNewExpression() => _parseInstanceCreationExpr ession(_expectKeyword(Keyword.NEW));
5670
5671 /**
5672 * Parse a non-labeled statement.
5673 *
5674 * <pre>
5675 * nonLabeledStatement ::=
5676 * block
5677 * | assertStatement
5678 * | breakStatement
5679 * | continueStatement
5680 * | doStatement
5681 * | forStatement
5682 * | ifStatement
5683 * | returnStatement
5684 * | switchStatement
5685 * | tryStatement
5686 * | whileStatement
5687 * | variableDeclarationList ';'
5688 * | expressionStatement
5689 * | functionSignature functionBody
5690 * </pre>
5691 *
5692 * @return the non-labeled statement that was parsed
5693 */
5694 Statement _parseNonLabeledStatement() {
5695 // TODO(brianwilkerson) Pass the comment and metadata on where appropriate.
5696 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
5697 if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
5698 if (_tokenMatches(_peek(), TokenType.STRING)) {
5699 Token afterString = _skipStringLiteral(_currentToken.next);
5700 if (afterString != null && afterString.type == TokenType.COLON) {
5701 return new ExpressionStatement(parseExpression2(), _expect(TokenType.S EMICOLON));
5702 }
5703 }
5704 return parseBlock();
5705 } else if (_matches(TokenType.KEYWORD) && !(_currentToken as KeywordToken).k eyword.isPseudoKeyword) {
5706 Keyword keyword = (_currentToken as KeywordToken).keyword;
5707 // TODO(jwren) compute some metrics to figure out a better order for this if-then sequence to optimize performance
5708 if (keyword == Keyword.ASSERT) {
5709 return _parseAssertStatement();
5710 } else if (keyword == Keyword.BREAK) {
5711 return _parseBreakStatement();
5712 } else if (keyword == Keyword.CONTINUE) {
5713 return _parseContinueStatement();
5714 } else if (keyword == Keyword.DO) {
5715 return _parseDoStatement();
5716 } else if (keyword == Keyword.FOR) {
5717 return _parseForStatement();
5718 } else if (keyword == Keyword.IF) {
5719 return _parseIfStatement();
5720 } else if (keyword == Keyword.RETHROW) {
5721 return new ExpressionStatement(_parseRethrowExpression(), _expect(TokenT ype.SEMICOLON));
5722 } else if (keyword == Keyword.RETURN) {
5723 return _parseReturnStatement();
5724 } else if (keyword == Keyword.SWITCH) {
5725 return _parseSwitchStatement();
5726 } else if (keyword == Keyword.THROW) {
5727 return new ExpressionStatement(_parseThrowExpression(), _expect(TokenTyp e.SEMICOLON));
5728 } else if (keyword == Keyword.TRY) {
5729 return _parseTryStatement();
5730 } else if (keyword == Keyword.WHILE) {
5731 return _parseWhileStatement();
5732 } else if (keyword == Keyword.VAR || keyword == Keyword.FINAL) {
5733 return _parseVariableDeclarationStatementAfterMetadata(commentAndMetadat a);
5734 } else if (keyword == Keyword.VOID) {
5735 TypeName returnType = parseReturnType();
5736 if (_matchesIdentifier() && _peek().matchesAny([
5737 TokenType.OPEN_PAREN,
5738 TokenType.OPEN_CURLY_BRACKET,
5739 TokenType.FUNCTION])) {
5740 return _parseFunctionDeclarationStatementAfterReturnType(commentAndMet adata, returnType);
5741 } else {
5742 //
5743 // We have found an error of some kind. Try to recover.
5744 //
5745 if (_matchesIdentifier()) {
5746 if (_peek().matchesAny([TokenType.EQ, TokenType.COMMA, TokenType.SEM ICOLON])) {
5747 //
5748 // We appear to have a variable declaration with a type of "void".
5749 //
5750 _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType, []) ;
5751 return _parseVariableDeclarationStatementAfterMetadata(commentAndM etadata);
5752 }
5753 } else if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
5754 //
5755 // We appear to have found an incomplete statement at the end of a b lock. Parse it as a
5756 // variable declaration.
5757 //
5758 return _parseVariableDeclarationStatementAfterType(commentAndMetadat a, null, returnType);
5759 }
5760 _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT, []);
5761 // TODO(brianwilkerson) Recover from this error.
5762 return new EmptyStatement(_createSyntheticToken(TokenType.SEMICOLON));
5763 }
5764 } else if (keyword == Keyword.CONST) {
5765 if (_peek().matchesAny([
5766 TokenType.LT,
5767 TokenType.OPEN_CURLY_BRACKET,
5768 TokenType.OPEN_SQUARE_BRACKET,
5769 TokenType.INDEX])) {
5770 return new ExpressionStatement(parseExpression2(), _expect(TokenType.S EMICOLON));
5771 } else if (_tokenMatches(_peek(), TokenType.IDENTIFIER)) {
5772 Token afterType = _skipTypeName(_peek());
5773 if (afterType != null) {
5774 if (_tokenMatches(afterType, TokenType.OPEN_PAREN) || (_tokenMatches (afterType, TokenType.PERIOD) && _tokenMatches(afterType.next, TokenType.IDENTIF IER) && _tokenMatches(afterType.next.next, TokenType.OPEN_PAREN))) {
5775 return new ExpressionStatement(parseExpression2(), _expect(TokenTy pe.SEMICOLON));
5776 }
5777 }
5778 }
5779 return _parseVariableDeclarationStatementAfterMetadata(commentAndMetadat a);
5780 } else if (keyword == Keyword.NEW || keyword == Keyword.TRUE || keyword == Keyword.FALSE || keyword == Keyword.NULL || keyword == Keyword.SUPER || keyword == Keyword.THIS) {
5781 return new ExpressionStatement(parseExpression2(), _expect(TokenType.SEM ICOLON));
5782 } else {
5783 //
5784 // We have found an error of some kind. Try to recover.
5785 //
5786 _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT, []);
5787 return new EmptyStatement(_createSyntheticToken(TokenType.SEMICOLON));
5788 }
5789 } else if (_inAsync && _matchesString(_YIELD)) {
5790 return _parseYieldStatement();
5791 } else if (_inAsync && _matchesString(_AWAIT)) {
5792 if (_tokenMatchesKeyword(_peek(), Keyword.FOR)) {
5793 return _parseForStatement();
5794 }
5795 return new ExpressionStatement(parseExpression2(), _expect(TokenType.SEMIC OLON));
5796 } else if (_matches(TokenType.SEMICOLON)) {
5797 return _parseEmptyStatement();
5798 } else if (_isInitializedVariableDeclaration()) {
5799 return _parseVariableDeclarationStatementAfterMetadata(commentAndMetadata) ;
5800 } else if (_isFunctionDeclaration()) {
5801 return _parseFunctionDeclarationStatement();
5802 } else if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
5803 _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT, []);
5804 return new EmptyStatement(_createSyntheticToken(TokenType.SEMICOLON));
5805 } else {
5806 return new ExpressionStatement(parseExpression2(), _expect(TokenType.SEMIC OLON));
5807 }
5808 }
5809
5810 /**
5811 * Parse an operator declaration.
5812 *
5813 * <pre>
5814 * operatorDeclaration ::=
5815 * operatorSignature (';' | functionBody)
5816 *
5817 * operatorSignature ::=
5818 * 'external'? returnType? 'operator' operator formalParameterList
5819 * </pre>
5820 *
5821 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
5822 * declaration
5823 * @param externalKeyword the 'external' token
5824 * @param the return type that has already been parsed, or `null` if there was no return
5825 * type
5826 * @return the operator declaration that was parsed
5827 */
5828 MethodDeclaration _parseOperator(CommentAndMetadata commentAndMetadata, Token externalKeyword, TypeName returnType) {
5829 Token operatorKeyword;
5830 if (_matchesKeyword(Keyword.OPERATOR)) {
5831 operatorKeyword = andAdvance;
5832 } else {
5833 _reportErrorForToken(ParserErrorCode.MISSING_KEYWORD_OPERATOR, _currentTok en, []);
5834 operatorKeyword = _createSyntheticKeyword(Keyword.OPERATOR);
5835 }
5836 if (!_currentToken.isUserDefinableOperator) {
5837 _reportErrorForCurrentToken(ParserErrorCode.NON_USER_DEFINABLE_OPERATOR, [ _currentToken.lexeme]);
5838 }
5839 SimpleIdentifier name = new SimpleIdentifier(andAdvance);
5840 if (_matches(TokenType.EQ)) {
5841 Token previous = _currentToken.previous;
5842 if ((_tokenMatches(previous, TokenType.EQ_EQ) || _tokenMatches(previous, T okenType.BANG_EQ)) && _currentToken.offset == previous.offset + 2) {
5843 _reportErrorForCurrentToken(ParserErrorCode.INVALID_OPERATOR, ["${previo us.lexeme}${_currentToken.lexeme}"]);
5844 _advance();
5845 }
5846 }
5847 FormalParameterList parameters = parseFormalParameterList();
5848 _validateFormalParameterList(parameters);
5849 FunctionBody body = _parseFunctionBody(true, ParserErrorCode.MISSING_FUNCTIO N_BODY, false);
5850 if (externalKeyword != null && body is! EmptyFunctionBody) {
5851 _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_OPERATOR_WITH_BODY, [ ]);
5852 }
5853 return new MethodDeclaration(commentAndMetadata.comment, commentAndMetadata. metadata, externalKeyword, null, returnType, null, operatorKeyword, name, parame ters, body);
5854 }
5855
5856 /**
5857 * Parse a return type if one is given, otherwise return `null` without advanc ing.
5858 *
5859 * @return the return type that was parsed
5860 */
5861 TypeName _parseOptionalReturnType() {
5862 if (_matchesKeyword(Keyword.VOID)) {
5863 return parseReturnType();
5864 } else if (_matchesIdentifier() && !_matchesKeyword(Keyword.GET) && !_matche sKeyword(Keyword.SET) && !_matchesKeyword(Keyword.OPERATOR) && (_tokenMatchesIde ntifier(_peek()) || _tokenMatches(_peek(), TokenType.LT))) {
5865 return parseReturnType();
5866 } else if (_matchesIdentifier() && _tokenMatches(_peek(), TokenType.PERIOD) && _tokenMatchesIdentifier(_peekAt(2)) && (_tokenMatchesIdentifier(_peekAt(3)) | | _tokenMatches(_peekAt(3), TokenType.LT))) {
5867 return parseReturnType();
5868 }
5869 return null;
5870 }
5871
5872 /**
5873 * Parse a part or part-of directive.
5874 *
5875 * <pre>
5876 * partDirective ::=
5877 * metadata 'part' stringLiteral ';'
5878 *
5879 * partOfDirective ::=
5880 * metadata 'part' 'of' identifier ';'
5881 * </pre>
5882 *
5883 * @param commentAndMetadata the metadata to be associated with the directive
5884 * @return the part or part-of directive that was parsed
5885 */
5886 Directive _parsePartDirective(CommentAndMetadata commentAndMetadata) {
5887 Token partKeyword = _expectKeyword(Keyword.PART);
5888 if (_matchesString(_OF)) {
5889 Token ofKeyword = andAdvance;
5890 LibraryIdentifier libraryName = _parseLibraryName(ParserErrorCode.MISSING_ NAME_IN_PART_OF_DIRECTIVE, ofKeyword);
5891 Token semicolon = _expect(TokenType.SEMICOLON);
5892 return new PartOfDirective(commentAndMetadata.comment, commentAndMetadata. metadata, partKeyword, ofKeyword, libraryName, semicolon);
5893 }
5894 StringLiteral partUri = parseStringLiteral();
5895 Token semicolon = _expect(TokenType.SEMICOLON);
5896 return new PartDirective(commentAndMetadata.comment, commentAndMetadata.meta data, partKeyword, partUri, semicolon);
5897 }
5898
5899 /**
5900 * Parse a postfix expression.
5901 *
5902 * <pre>
5903 * postfixExpression ::=
5904 * assignableExpression postfixOperator
5905 * | primary selector*
5906 *
5907 * selector ::=
5908 * assignableSelector
5909 * | argumentList
5910 * </pre>
5911 *
5912 * @return the postfix expression that was parsed
5913 */
5914 Expression _parsePostfixExpression() {
5915 Expression operand = _parseAssignableExpression(true);
5916 if (_matches(TokenType.OPEN_SQUARE_BRACKET) || _matches(TokenType.PERIOD) || _matches(TokenType.OPEN_PAREN)) {
5917 do {
5918 if (_matches(TokenType.OPEN_PAREN)) {
5919 ArgumentList argumentList = parseArgumentList();
5920 if (operand is PropertyAccess) {
5921 PropertyAccess access = operand as PropertyAccess;
5922 operand = new MethodInvocation(access.target, access.operator, acces s.propertyName, argumentList);
5923 } else {
5924 operand = new FunctionExpressionInvocation(operand, argumentList);
5925 }
5926 } else {
5927 operand = _parseAssignableSelector(operand, true);
5928 }
5929 } while (_matches(TokenType.OPEN_SQUARE_BRACKET) || _matches(TokenType.PER IOD) || _matches(TokenType.OPEN_PAREN));
5930 return operand;
5931 }
5932 if (!_currentToken.type.isIncrementOperator) {
5933 return operand;
5934 }
5935 _ensureAssignable(operand);
5936 Token operator = andAdvance;
5937 return new PostfixExpression(operand, operator);
5938 }
5939
5940 /**
5941 * Parse a primary expression.
5942 *
5943 * <pre>
5944 * primary ::=
5945 * thisExpression
5946 * | 'super' assignableSelector
5947 * | functionExpression
5948 * | literal
5949 * | identifier
5950 * | newExpression
5951 * | constObjectExpression
5952 * | '(' expression ')'
5953 * | argumentDefinitionTest
5954 *
5955 * literal ::=
5956 * nullLiteral
5957 * | booleanLiteral
5958 * | numericLiteral
5959 * | stringLiteral
5960 * | symbolLiteral
5961 * | mapLiteral
5962 * | listLiteral
5963 * </pre>
5964 *
5965 * @return the primary expression that was parsed
5966 */
5967 Expression _parsePrimaryExpression() {
5968 if (_matchesKeyword(Keyword.THIS)) {
5969 return new ThisExpression(andAdvance);
5970 } else if (_matchesKeyword(Keyword.SUPER)) {
5971 return _parseAssignableSelector(new SuperExpression(andAdvance), false);
5972 } else if (_matchesKeyword(Keyword.NULL)) {
5973 return new NullLiteral(andAdvance);
5974 } else if (_matchesKeyword(Keyword.FALSE)) {
5975 return new BooleanLiteral(andAdvance, false);
5976 } else if (_matchesKeyword(Keyword.TRUE)) {
5977 return new BooleanLiteral(andAdvance, true);
5978 } else if (_matches(TokenType.DOUBLE)) {
5979 Token token = andAdvance;
5980 double value = 0.0;
5981 try {
5982 value = double.parse(token.lexeme);
5983 } on FormatException catch (exception) {
5984 }
5985 return new DoubleLiteral(token, value);
5986 } else if (_matches(TokenType.HEXADECIMAL)) {
5987 Token token = andAdvance;
5988 int value = null;
5989 try {
5990 value = int.parse(token.lexeme.substring(2), radix: 16);
5991 } on FormatException catch (exception) {
5992 }
5993 return new IntegerLiteral(token, value);
5994 } else if (_matches(TokenType.INT)) {
5995 Token token = andAdvance;
5996 int value = null;
5997 try {
5998 value = int.parse(token.lexeme);
5999 } on FormatException catch (exception) {
6000 }
6001 return new IntegerLiteral(token, value);
6002 } else if (_matches(TokenType.STRING)) {
6003 return parseStringLiteral();
6004 } else if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
6005 return _parseMapLiteral(null, null);
6006 } else if (_matches(TokenType.OPEN_SQUARE_BRACKET) || _matches(TokenType.IND EX)) {
6007 return _parseListLiteral(null, null);
6008 } else if (_matchesIdentifier()) {
6009 // TODO(brianwilkerson) The code below was an attempt to recover from an e rror case, but it
6010 // needs to be applied as a recovery only after we know that parsing it as an identifier
6011 // doesn't work. Leaving the code as a reminder of how to recover.
6012 // if (isFunctionExpression(peek())) {
6013 // //
6014 // // Function expressions were allowed to have names at one point, but this is now illegal.
6015 // //
6016 // reportError(ParserErrorCode.NAMED_FUNCTION_EXPRESSION, getAndAdv ance());
6017 // return parseFunctionExpression();
6018 // }
6019 return parsePrefixedIdentifier();
6020 } else if (_matchesKeyword(Keyword.NEW)) {
6021 return _parseNewExpression();
6022 } else if (_matchesKeyword(Keyword.CONST)) {
6023 return _parseConstExpression();
6024 } else if (_matches(TokenType.OPEN_PAREN)) {
6025 if (_isFunctionExpression(_currentToken)) {
6026 return parseFunctionExpression();
6027 }
6028 Token leftParenthesis = andAdvance;
6029 bool wasInInitializer = _inInitializer;
6030 _inInitializer = false;
6031 try {
6032 Expression expression = parseExpression2();
6033 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
6034 return new ParenthesizedExpression(leftParenthesis, expression, rightPar enthesis);
6035 } finally {
6036 _inInitializer = wasInInitializer;
6037 }
6038 } else if (_matches(TokenType.LT)) {
6039 return _parseListOrMapLiteral(null);
6040 } else if (_matches(TokenType.QUESTION) && _tokenMatches(_peek(), TokenType. IDENTIFIER)) {
6041 _reportErrorForCurrentToken(ParserErrorCode.UNEXPECTED_TOKEN, [_currentTok en.lexeme]);
6042 _advance();
6043 return _parsePrimaryExpression();
6044 } else if (_matchesKeyword(Keyword.VOID)) {
6045 //
6046 // Recover from having a return type of "void" where a return type is not expected.
6047 //
6048 // TODO(brianwilkerson) Improve this error message.
6049 _reportErrorForCurrentToken(ParserErrorCode.UNEXPECTED_TOKEN, [_currentTok en.lexeme]);
6050 _advance();
6051 return _parsePrimaryExpression();
6052 } else if (_matches(TokenType.HASH)) {
6053 return _parseSymbolLiteral();
6054 } else {
6055 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER, []);
6056 return _createSyntheticIdentifier();
6057 }
6058 }
6059
6060 /**
6061 * Parse a redirecting constructor invocation.
6062 *
6063 * <pre>
6064 * redirectingConstructorInvocation ::=
6065 * 'this' ('.' identifier)? arguments
6066 * </pre>
6067 *
6068 * @return the redirecting constructor invocation that was parsed
6069 */
6070 RedirectingConstructorInvocation _parseRedirectingConstructorInvocation() {
6071 Token keyword = _expectKeyword(Keyword.THIS);
6072 Token period = null;
6073 SimpleIdentifier constructorName = null;
6074 if (_matches(TokenType.PERIOD)) {
6075 period = andAdvance;
6076 constructorName = parseSimpleIdentifier();
6077 }
6078 ArgumentList argumentList = parseArgumentList();
6079 return new RedirectingConstructorInvocation(keyword, period, constructorName , argumentList);
6080 }
6081
6082 /**
6083 * Parse a relational expression.
6084 *
6085 * <pre>
6086 * relationalExpression ::=
6087 * bitwiseOrExpression ('is' '!'? type | 'as' type | relationalOperator bi twiseOrExpression)?
6088 * | 'super' relationalOperator bitwiseOrExpression
6089 * </pre>
6090 *
6091 * @return the relational expression that was parsed
6092 */
6093 Expression _parseRelationalExpression() {
6094 if (_matchesKeyword(Keyword.SUPER) && _currentToken.next.type.isRelationalOp erator) {
6095 Expression expression = new SuperExpression(andAdvance);
6096 Token operator = andAdvance;
6097 expression = new BinaryExpression(expression, operator, parseBitwiseOrExpr ession());
6098 return expression;
6099 }
6100 Expression expression = parseBitwiseOrExpression();
6101 if (_matchesKeyword(Keyword.AS)) {
6102 Token asOperator = andAdvance;
6103 expression = new AsExpression(expression, asOperator, parseTypeName());
6104 } else if (_matchesKeyword(Keyword.IS)) {
6105 Token isOperator = andAdvance;
6106 Token notOperator = null;
6107 if (_matches(TokenType.BANG)) {
6108 notOperator = andAdvance;
6109 }
6110 expression = new IsExpression(expression, isOperator, notOperator, parseTy peName());
6111 } else if (_currentToken.type.isRelationalOperator) {
6112 Token operator = andAdvance;
6113 expression = new BinaryExpression(expression, operator, parseBitwiseOrExpr ession());
6114 }
6115 return expression;
6116 }
6117
6118 /**
6119 * Parse a rethrow expression.
6120 *
6121 * <pre>
6122 * rethrowExpression ::=
6123 * 'rethrow'
6124 * </pre>
6125 *
6126 * @return the rethrow expression that was parsed
6127 */
6128 Expression _parseRethrowExpression() => new RethrowExpression(_expectKeyword(K eyword.RETHROW));
6129
6130 /**
6131 * Parse a return statement.
6132 *
6133 * <pre>
6134 * returnStatement ::=
6135 * 'return' expression? ';'
6136 * </pre>
6137 *
6138 * @return the return statement that was parsed
6139 */
6140 Statement _parseReturnStatement() {
6141 Token returnKeyword = _expectKeyword(Keyword.RETURN);
6142 if (_matches(TokenType.SEMICOLON)) {
6143 return new ReturnStatement(returnKeyword, null, andAdvance);
6144 }
6145 Expression expression = parseExpression2();
6146 Token semicolon = _expect(TokenType.SEMICOLON);
6147 return new ReturnStatement(returnKeyword, expression, semicolon);
6148 }
6149
6150 /**
6151 * Parse a setter.
6152 *
6153 * <pre>
6154 * setter ::=
6155 * setterSignature functionBody?
6156 *
6157 * setterSignature ::=
6158 * 'external'? 'static'? returnType? 'set' identifier formalParameterList
6159 * </pre>
6160 *
6161 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
6162 * declaration
6163 * @param externalKeyword the 'external' token
6164 * @param staticKeyword the static keyword, or `null` if the setter is not sta tic
6165 * @param the return type that has already been parsed, or `null` if there was no return
6166 * type
6167 * @return the setter that was parsed
6168 */
6169 MethodDeclaration _parseSetter(CommentAndMetadata commentAndMetadata, Token ex ternalKeyword, Token staticKeyword, TypeName returnType) {
6170 Token propertyKeyword = _expectKeyword(Keyword.SET);
6171 SimpleIdentifier name = parseSimpleIdentifier();
6172 FormalParameterList parameters = parseFormalParameterList();
6173 _validateFormalParameterList(parameters);
6174 FunctionBody body = _parseFunctionBody(externalKeyword != null || staticKeyw ord == null, ParserErrorCode.STATIC_SETTER_WITHOUT_BODY, false);
6175 if (externalKeyword != null && body is! EmptyFunctionBody) {
6176 _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_SETTER_WITH_BODY, []) ;
6177 }
6178 return new MethodDeclaration(commentAndMetadata.comment, commentAndMetadata. metadata, externalKeyword, staticKeyword, returnType, propertyKeyword, null, nam e, parameters, body);
6179 }
6180
6181 /**
6182 * Parse a shift expression.
6183 *
6184 * <pre>
6185 * shiftExpression ::=
6186 * additiveExpression (shiftOperator additiveExpression)*
6187 * | 'super' (shiftOperator additiveExpression)+
6188 * </pre>
6189 *
6190 * @return the shift expression that was parsed
6191 */
6192 Expression _parseShiftExpression() {
6193 Expression expression;
6194 if (_matchesKeyword(Keyword.SUPER) && _currentToken.next.type.isShiftOperato r) {
6195 expression = new SuperExpression(andAdvance);
6196 } else {
6197 expression = _parseAdditiveExpression();
6198 }
6199 while (_currentToken.type.isShiftOperator) {
6200 Token operator = andAdvance;
6201 expression = new BinaryExpression(expression, operator, _parseAdditiveExpr ession());
6202 }
6203 return expression;
6204 }
6205
6206 /**
6207 * Parse a list of statements within a switch statement.
6208 *
6209 * <pre>
6210 * statements ::=
6211 * statement*
6212 * </pre>
6213 *
6214 * @return the statements that were parsed
6215 */
6216 List<Statement> _parseStatementList() {
6217 List<Statement> statements = new List<Statement>();
6218 Token statementStart = _currentToken;
6219 while (!_matches(TokenType.EOF) && !_matches(TokenType.CLOSE_CURLY_BRACKET) && !_isSwitchMember()) {
6220 statements.add(parseStatement2());
6221 if (identical(_currentToken, statementStart)) {
6222 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_ currentToken.lexeme]);
6223 _advance();
6224 }
6225 statementStart = _currentToken;
6226 }
6227 return statements;
6228 }
6229
6230 /**
6231 * Parse a string literal that contains interpolations.
6232 *
6233 * @return the string literal that was parsed
6234 */
6235 StringInterpolation _parseStringInterpolation(Token string) {
6236 List<InterpolationElement> elements = new List<InterpolationElement>();
6237 bool hasMore = _matches(TokenType.STRING_INTERPOLATION_EXPRESSION) || _match es(TokenType.STRING_INTERPOLATION_IDENTIFIER);
6238 elements.add(new InterpolationString(string, _computeStringValue(string.lexe me, true, !hasMore)));
6239 while (hasMore) {
6240 if (_matches(TokenType.STRING_INTERPOLATION_EXPRESSION)) {
6241 Token openToken = andAdvance;
6242 bool wasInInitializer = _inInitializer;
6243 _inInitializer = false;
6244 try {
6245 Expression expression = parseExpression2();
6246 Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
6247 elements.add(new InterpolationExpression(openToken, expression, rightB racket));
6248 } finally {
6249 _inInitializer = wasInInitializer;
6250 }
6251 } else {
6252 Token openToken = andAdvance;
6253 Expression expression = null;
6254 if (_matchesKeyword(Keyword.THIS)) {
6255 expression = new ThisExpression(andAdvance);
6256 } else {
6257 expression = parseSimpleIdentifier();
6258 }
6259 elements.add(new InterpolationExpression(openToken, expression, null));
6260 }
6261 if (_matches(TokenType.STRING)) {
6262 string = andAdvance;
6263 hasMore = _matches(TokenType.STRING_INTERPOLATION_EXPRESSION) || _matche s(TokenType.STRING_INTERPOLATION_IDENTIFIER);
6264 elements.add(new InterpolationString(string, _computeStringValue(string. lexeme, false, !hasMore)));
6265 } else {
6266 hasMore = false;
6267 }
6268 }
6269 return new StringInterpolation(elements);
6270 }
6271
6272 /**
6273 * Parse a super constructor invocation.
6274 *
6275 * <pre>
6276 * superConstructorInvocation ::=
6277 * 'super' ('.' identifier)? arguments
6278 * </pre>
6279 *
6280 * @return the super constructor invocation that was parsed
6281 */
6282 SuperConstructorInvocation _parseSuperConstructorInvocation() {
6283 Token keyword = _expectKeyword(Keyword.SUPER);
6284 Token period = null;
6285 SimpleIdentifier constructorName = null;
6286 if (_matches(TokenType.PERIOD)) {
6287 period = andAdvance;
6288 constructorName = parseSimpleIdentifier();
6289 }
6290 ArgumentList argumentList = parseArgumentList();
6291 return new SuperConstructorInvocation(keyword, period, constructorName, argu mentList);
6292 }
6293
6294 /**
6295 * Parse a switch statement.
6296 *
6297 * <pre>
6298 * switchStatement ::=
6299 * 'switch' '(' expression ')' '{' switchCase* defaultCase? '}'
6300 *
6301 * switchCase ::=
6302 * label* ('case' expression ':') statements
6303 *
6304 * defaultCase ::=
6305 * label* 'default' ':' statements
6306 * </pre>
6307 *
6308 * @return the switch statement that was parsed
6309 */
6310 SwitchStatement _parseSwitchStatement() {
6311 bool wasInSwitch = _inSwitch;
6312 _inSwitch = true;
6313 try {
6314 HashSet<String> definedLabels = new HashSet<String>();
6315 Token keyword = _expectKeyword(Keyword.SWITCH);
6316 Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
6317 Expression expression = parseExpression2();
6318 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
6319 Token leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET);
6320 Token defaultKeyword = null;
6321 List<SwitchMember> members = new List<SwitchMember>();
6322 while (!_matches(TokenType.EOF) && !_matches(TokenType.CLOSE_CURLY_BRACKET )) {
6323 List<Label> labels = new List<Label>();
6324 while (_matchesIdentifier() && _tokenMatches(_peek(), TokenType.COLON)) {
6325 SimpleIdentifier identifier = parseSimpleIdentifier();
6326 String label = identifier.token.lexeme;
6327 if (definedLabels.contains(label)) {
6328 _reportErrorForToken(ParserErrorCode.DUPLICATE_LABEL_IN_SWITCH_STATE MENT, identifier.token, [label]);
6329 } else {
6330 definedLabels.add(label);
6331 }
6332 Token colon = _expect(TokenType.COLON);
6333 labels.add(new Label(identifier, colon));
6334 }
6335 if (_matchesKeyword(Keyword.CASE)) {
6336 Token caseKeyword = andAdvance;
6337 Expression caseExpression = parseExpression2();
6338 Token colon = _expect(TokenType.COLON);
6339 members.add(new SwitchCase(labels, caseKeyword, caseExpression, colon, _parseStatementList()));
6340 if (defaultKeyword != null) {
6341 _reportErrorForToken(ParserErrorCode.SWITCH_HAS_CASE_AFTER_DEFAULT_C ASE, caseKeyword, []);
6342 }
6343 } else if (_matchesKeyword(Keyword.DEFAULT)) {
6344 if (defaultKeyword != null) {
6345 _reportErrorForToken(ParserErrorCode.SWITCH_HAS_MULTIPLE_DEFAULT_CAS ES, _peek(), []);
6346 }
6347 defaultKeyword = andAdvance;
6348 Token colon = _expect(TokenType.COLON);
6349 members.add(new SwitchDefault(labels, defaultKeyword, colon, _parseSta tementList()));
6350 } else {
6351 // We need to advance, otherwise we could end up in an infinite loop, but this could be a
6352 // lot smarter about recovering from the error.
6353 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_CASE_OR_DEFAULT, []);
6354 while (!_matches(TokenType.EOF) && !_matches(TokenType.CLOSE_CURLY_BRA CKET) && !_matchesKeyword(Keyword.CASE) && !_matchesKeyword(Keyword.DEFAULT)) {
6355 _advance();
6356 }
6357 }
6358 }
6359 Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
6360 return new SwitchStatement(keyword, leftParenthesis, expression, rightPare nthesis, leftBracket, members, rightBracket);
6361 } finally {
6362 _inSwitch = wasInSwitch;
6363 }
6364 }
6365
6366 /**
6367 * Parse a symbol literal.
6368 *
6369 * <pre>
6370 * symbolLiteral ::=
6371 * '#' identifier ('.' identifier)*
6372 * </pre>
6373 *
6374 * @return the symbol literal that was parsed
6375 */
6376 SymbolLiteral _parseSymbolLiteral() {
6377 Token poundSign = andAdvance;
6378 List<Token> components = new List<Token>();
6379 if (_matchesIdentifier()) {
6380 components.add(andAdvance);
6381 while (_matches(TokenType.PERIOD)) {
6382 _advance();
6383 if (_matchesIdentifier()) {
6384 components.add(andAdvance);
6385 } else {
6386 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER, []);
6387 components.add(_createSyntheticToken(TokenType.IDENTIFIER));
6388 break;
6389 }
6390 }
6391 } else if (_currentToken.isOperator) {
6392 components.add(andAdvance);
6393 } else if (_tokenMatchesKeyword(_currentToken, Keyword.VOID)) {
6394 components.add(andAdvance);
6395 } else {
6396 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER, []);
6397 components.add(_createSyntheticToken(TokenType.IDENTIFIER));
6398 }
6399 return new SymbolLiteral(poundSign, new List.from(components));
6400 }
6401
6402 /**
6403 * Parse a throw expression.
6404 *
6405 * <pre>
6406 * throwExpression ::=
6407 * 'throw' expression
6408 * </pre>
6409 *
6410 * @return the throw expression that was parsed
6411 */
6412 Expression _parseThrowExpression() {
6413 Token keyword = _expectKeyword(Keyword.THROW);
6414 if (_matches(TokenType.SEMICOLON) || _matches(TokenType.CLOSE_PAREN)) {
6415 _reportErrorForToken(ParserErrorCode.MISSING_EXPRESSION_IN_THROW, _current Token, []);
6416 return new ThrowExpression(keyword, _createSyntheticIdentifier());
6417 }
6418 Expression expression = parseExpression2();
6419 return new ThrowExpression(keyword, expression);
6420 }
6421
6422 /**
6423 * Parse a throw expression.
6424 *
6425 * <pre>
6426 * throwExpressionWithoutCascade ::=
6427 * 'throw' expressionWithoutCascade
6428 * </pre>
6429 *
6430 * @return the throw expression that was parsed
6431 */
6432 Expression _parseThrowExpressionWithoutCascade() {
6433 Token keyword = _expectKeyword(Keyword.THROW);
6434 if (_matches(TokenType.SEMICOLON) || _matches(TokenType.CLOSE_PAREN)) {
6435 _reportErrorForToken(ParserErrorCode.MISSING_EXPRESSION_IN_THROW, _current Token, []);
6436 return new ThrowExpression(keyword, _createSyntheticIdentifier());
6437 }
6438 Expression expression = parseExpressionWithoutCascade();
6439 return new ThrowExpression(keyword, expression);
6440 }
6441
6442 /**
6443 * Parse a try statement.
6444 *
6445 * <pre>
6446 * tryStatement ::=
6447 * 'try' block (onPart+ finallyPart? | finallyPart)
6448 *
6449 * onPart ::=
6450 * catchPart block
6451 * | 'on' type catchPart? block
6452 *
6453 * catchPart ::=
6454 * 'catch' '(' identifier (',' identifier)? ')'
6455 *
6456 * finallyPart ::=
6457 * 'finally' block
6458 * </pre>
6459 *
6460 * @return the try statement that was parsed
6461 */
6462 Statement _parseTryStatement() {
6463 Token tryKeyword = _expectKeyword(Keyword.TRY);
6464 Block body = parseBlock();
6465 List<CatchClause> catchClauses = new List<CatchClause>();
6466 Block finallyClause = null;
6467 while (_matchesString(_ON) || _matchesKeyword(Keyword.CATCH)) {
6468 Token onKeyword = null;
6469 TypeName exceptionType = null;
6470 if (_matchesString(_ON)) {
6471 onKeyword = andAdvance;
6472 exceptionType = parseTypeName();
6473 }
6474 Token catchKeyword = null;
6475 Token leftParenthesis = null;
6476 SimpleIdentifier exceptionParameter = null;
6477 Token comma = null;
6478 SimpleIdentifier stackTraceParameter = null;
6479 Token rightParenthesis = null;
6480 if (_matchesKeyword(Keyword.CATCH)) {
6481 catchKeyword = andAdvance;
6482 leftParenthesis = _expect(TokenType.OPEN_PAREN);
6483 exceptionParameter = parseSimpleIdentifier();
6484 if (_matches(TokenType.COMMA)) {
6485 comma = andAdvance;
6486 stackTraceParameter = parseSimpleIdentifier();
6487 }
6488 rightParenthesis = _expect(TokenType.CLOSE_PAREN);
6489 }
6490 Block catchBody = parseBlock();
6491 catchClauses.add(new CatchClause(onKeyword, exceptionType, catchKeyword, l eftParenthesis, exceptionParameter, comma, stackTraceParameter, rightParenthesis , catchBody));
6492 }
6493 Token finallyKeyword = null;
6494 if (_matchesKeyword(Keyword.FINALLY)) {
6495 finallyKeyword = andAdvance;
6496 finallyClause = parseBlock();
6497 } else {
6498 if (catchClauses.isEmpty) {
6499 _reportErrorForCurrentToken(ParserErrorCode.MISSING_CATCH_OR_FINALLY, [] );
6500 }
6501 }
6502 return new TryStatement(tryKeyword, body, catchClauses, finallyKeyword, fina llyClause);
6503 }
6504
6505 /**
6506 * Parse a type alias.
6507 *
6508 * <pre>
6509 * typeAlias ::=
6510 * 'typedef' typeAliasBody
6511 *
6512 * typeAliasBody ::=
6513 * classTypeAlias
6514 * | functionTypeAlias
6515 *
6516 * classTypeAlias ::=
6517 * identifier typeParameters? '=' 'abstract'? mixinApplication
6518 *
6519 * mixinApplication ::=
6520 * qualified withClause implementsClause? ';'
6521 *
6522 * functionTypeAlias ::=
6523 * functionPrefix typeParameterList? formalParameterList ';'
6524 *
6525 * functionPrefix ::=
6526 * returnType? name
6527 * </pre>
6528 *
6529 * @param commentAndMetadata the metadata to be associated with the member
6530 * @return the type alias that was parsed
6531 */
6532 TypeAlias _parseTypeAlias(CommentAndMetadata commentAndMetadata) {
6533 Token keyword = _expectKeyword(Keyword.TYPEDEF);
6534 if (_matchesIdentifier()) {
6535 Token next = _peek();
6536 if (_tokenMatches(next, TokenType.LT)) {
6537 next = _skipTypeParameterList(next);
6538 if (next != null && _tokenMatches(next, TokenType.EQ)) {
6539 TypeAlias typeAlias = _parseClassTypeAlias(commentAndMetadata, null, k eyword);
6540 _reportErrorForToken(ParserErrorCode.DEPRECATED_CLASS_TYPE_ALIAS, keyw ord, []);
6541 return typeAlias;
6542 }
6543 } else if (_tokenMatches(next, TokenType.EQ)) {
6544 TypeAlias typeAlias = _parseClassTypeAlias(commentAndMetadata, null, key word);
6545 _reportErrorForToken(ParserErrorCode.DEPRECATED_CLASS_TYPE_ALIAS, keywor d, []);
6546 return typeAlias;
6547 }
6548 }
6549 return _parseFunctionTypeAlias(commentAndMetadata, keyword);
6550 }
6551
6552 /**
6553 * Parse a unary expression.
6554 *
6555 * <pre>
6556 * unaryExpression ::=
6557 * prefixOperator unaryExpression
6558 * | awaitExpression
6559 * | postfixExpression
6560 * | unaryOperator 'super'
6561 * | '-' 'super'
6562 * | incrementOperator assignableExpression
6563 * </pre>
6564 *
6565 * @return the unary expression that was parsed
6566 */
6567 Expression _parseUnaryExpression() {
6568 if (_matches(TokenType.MINUS) || _matches(TokenType.BANG) || _matches(TokenT ype.TILDE)) {
6569 Token operator = andAdvance;
6570 if (_matchesKeyword(Keyword.SUPER)) {
6571 if (_tokenMatches(_peek(), TokenType.OPEN_SQUARE_BRACKET) || _tokenMatch es(_peek(), TokenType.PERIOD)) {
6572 // "prefixOperator unaryExpression"
6573 // --> "prefixOperator postfixExpression"
6574 // --> "prefixOperator primary selector*"
6575 // --> "prefixOperator 'super' assignableSelector selector*"
6576 return new PrefixExpression(operator, _parseUnaryExpression());
6577 }
6578 return new PrefixExpression(operator, new SuperExpression(andAdvance));
6579 }
6580 return new PrefixExpression(operator, _parseUnaryExpression());
6581 } else if (_currentToken.type.isIncrementOperator) {
6582 Token operator = andAdvance;
6583 if (_matchesKeyword(Keyword.SUPER)) {
6584 if (_tokenMatches(_peek(), TokenType.OPEN_SQUARE_BRACKET) || _tokenMatch es(_peek(), TokenType.PERIOD)) {
6585 // --> "prefixOperator 'super' assignableSelector selector*"
6586 return new PrefixExpression(operator, _parseUnaryExpression());
6587 }
6588 //
6589 // Even though it is not valid to use an incrementing operator ('++' or '--') before 'super',
6590 // we can (and therefore must) interpret "--super" as semantically equiv alent to "-(-super)".
6591 // Unfortunately, we cannot do the same for "++super" because "+super" i s also not valid.
6592 //
6593 if (operator.type == TokenType.MINUS_MINUS) {
6594 int offset = operator.offset;
6595 Token firstOperator = new Token(TokenType.MINUS, offset);
6596 Token secondOperator = new Token(TokenType.MINUS, offset + 1);
6597 secondOperator.setNext(_currentToken);
6598 firstOperator.setNext(secondOperator);
6599 operator.previous.setNext(firstOperator);
6600 return new PrefixExpression(firstOperator, new PrefixExpression(second Operator, new SuperExpression(andAdvance)));
6601 } else {
6602 // Invalid operator before 'super'
6603 _reportErrorForCurrentToken(ParserErrorCode.INVALID_OPERATOR_FOR_SUPER , [operator.lexeme]);
6604 return new PrefixExpression(operator, new SuperExpression(andAdvance)) ;
6605 }
6606 }
6607 return new PrefixExpression(operator, _parseAssignableExpression(false));
6608 } else if (_matches(TokenType.PLUS)) {
6609 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER, []);
6610 return _createSyntheticIdentifier();
6611 } else if (_inAsync && _matchesString(_AWAIT)) {
6612 return _parseAwaitExpression();
6613 }
6614 return _parsePostfixExpression();
6615 }
6616
6617 /**
6618 * Parse a variable declaration.
6619 *
6620 * <pre>
6621 * variableDeclaration ::=
6622 * identifier ('=' expression)?
6623 * </pre>
6624 *
6625 * @return the variable declaration that was parsed
6626 */
6627 VariableDeclaration _parseVariableDeclaration() {
6628 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
6629 SimpleIdentifier name = parseSimpleIdentifier();
6630 Token equals = null;
6631 Expression initializer = null;
6632 if (_matches(TokenType.EQ)) {
6633 equals = andAdvance;
6634 initializer = parseExpression2();
6635 }
6636 return new VariableDeclaration(commentAndMetadata.comment, commentAndMetadat a.metadata, name, equals, initializer);
6637 }
6638
6639 /**
6640 * Parse a variable declaration list.
6641 *
6642 * <pre>
6643 * variableDeclarationList ::=
6644 * finalConstVarOrType variableDeclaration (',' variableDeclaration)*
6645 * </pre>
6646 *
6647 * @param commentAndMetadata the metadata to be associated with the variable d eclaration list
6648 * @return the variable declaration list that was parsed
6649 */
6650 VariableDeclarationList _parseVariableDeclarationListAfterMetadata(CommentAndM etadata commentAndMetadata) {
6651 FinalConstVarOrType holder = _parseFinalConstVarOrType(false);
6652 return _parseVariableDeclarationListAfterType(commentAndMetadata, holder.key word, holder.type);
6653 }
6654
6655 /**
6656 * Parse a variable declaration list.
6657 *
6658 * <pre>
6659 * variableDeclarationList ::=
6660 * finalConstVarOrType variableDeclaration (',' variableDeclaration)*
6661 * </pre>
6662 *
6663 * @param commentAndMetadata the metadata to be associated with the variable d eclaration list, or
6664 * `null` if there is no attempt at parsing the comment and metadata
6665 * @param keyword the token representing the 'final', 'const' or 'var' keyword , or `null` if
6666 * there is no keyword
6667 * @param type the type of the variables in the list
6668 * @return the variable declaration list that was parsed
6669 */
6670 VariableDeclarationList _parseVariableDeclarationListAfterType(CommentAndMetad ata commentAndMetadata, Token keyword, TypeName type) {
6671 if (type != null && keyword != null && _tokenMatchesKeyword(keyword, Keyword .VAR)) {
6672 _reportErrorForToken(ParserErrorCode.VAR_AND_TYPE, keyword, []);
6673 }
6674 List<VariableDeclaration> variables = new List<VariableDeclaration>();
6675 variables.add(_parseVariableDeclaration());
6676 while (_matches(TokenType.COMMA)) {
6677 _advance();
6678 variables.add(_parseVariableDeclaration());
6679 }
6680 return new VariableDeclarationList(commentAndMetadata != null ? commentAndMe tadata.comment : null, commentAndMetadata != null ? commentAndMetadata.metadata : null, keyword, type, variables);
6681 }
6682
6683 /**
6684 * Parse a variable declaration statement.
6685 *
6686 * <pre>
6687 * variableDeclarationStatement ::=
6688 * variableDeclarationList ';'
6689 * </pre>
6690 *
6691 * @param commentAndMetadata the metadata to be associated with the variable d eclaration
6692 * statement, or `null` if there is no attempt at parsing the comment and metadata
6693 * @return the variable declaration statement that was parsed
6694 */
6695 VariableDeclarationStatement _parseVariableDeclarationStatementAfterMetadata(C ommentAndMetadata commentAndMetadata) {
6696 // Token startToken = currentToken;
6697 VariableDeclarationList variableList = _parseVariableDeclarationListAfterMet adata(commentAndMetadata);
6698 // if (!matches(TokenType.SEMICOLON)) {
6699 // if (matches(startToken, Keyword.VAR) && isTypedIdentifier(startToken .getNext())) {
6700 // // TODO(brianwilkerson) This appears to be of the form "var type v ariable". We should do
6701 // // a better job of recovering in this case.
6702 // }
6703 // }
6704 Token semicolon = _expect(TokenType.SEMICOLON);
6705 return new VariableDeclarationStatement(variableList, semicolon);
6706 }
6707
6708 /**
6709 * Parse a variable declaration statement.
6710 *
6711 * <pre>
6712 * variableDeclarationStatement ::=
6713 * variableDeclarationList ';'
6714 * </pre>
6715 *
6716 * @param commentAndMetadata the metadata to be associated with the variable d eclaration
6717 * statement, or `null` if there is no attempt at parsing the comment and metadata
6718 * @param keyword the token representing the 'final', 'const' or 'var' keyword , or `null` if
6719 * there is no keyword
6720 * @param type the type of the variables in the list
6721 * @return the variable declaration statement that was parsed
6722 */
6723 VariableDeclarationStatement _parseVariableDeclarationStatementAfterType(Comme ntAndMetadata commentAndMetadata, Token keyword, TypeName type) {
6724 VariableDeclarationList variableList = _parseVariableDeclarationListAfterTyp e(commentAndMetadata, keyword, type);
6725 Token semicolon = _expect(TokenType.SEMICOLON);
6726 return new VariableDeclarationStatement(variableList, semicolon);
6727 }
6728
6729 /**
6730 * Parse a while statement.
6731 *
6732 * <pre>
6733 * whileStatement ::=
6734 * 'while' '(' expression ')' statement
6735 * </pre>
6736 *
6737 * @return the while statement that was parsed
6738 */
6739 Statement _parseWhileStatement() {
6740 bool wasInLoop = _inLoop;
6741 _inLoop = true;
6742 try {
6743 Token keyword = _expectKeyword(Keyword.WHILE);
6744 Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
6745 Expression condition = parseExpression2();
6746 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
6747 Statement body = parseStatement2();
6748 return new WhileStatement(keyword, leftParenthesis, condition, rightParent hesis, body);
6749 } finally {
6750 _inLoop = wasInLoop;
6751 }
6752 }
6753
6754 /**
6755 * Parse a yield statement.
6756 *
6757 * <pre>
6758 * yieldStatement ::=
6759 * 'yield' '*'? expression ';'
6760 * </pre>
6761 *
6762 * @return the yield statement that was parsed
6763 */
6764 YieldStatement _parseYieldStatement() {
6765 Token yieldToken = andAdvance;
6766 Token star = null;
6767 if (_matches(TokenType.STAR)) {
6768 star = andAdvance;
6769 }
6770 Expression expression = parseExpression2();
6771 Token semicolon = _expect(TokenType.SEMICOLON);
6772 return new YieldStatement(yieldToken, star, expression, semicolon);
6773 }
6774
6775 /**
6776 * Return the token that is immediately after the current token. This is equiv alent to
6777 * [peekAt].
6778 *
6779 * @return the token that is immediately after the current token
6780 */
6781 Token _peek() => _currentToken.next;
6782
6783 /**
6784 * Return the token that is the given distance after the current token.
6785 *
6786 * @param distance the number of tokens to look ahead, where `0` is the curren t token,
6787 * `1` is the next token, etc.
6788 * @return the token that is the given distance after the current token
6789 */
6790 Token _peekAt(int distance) {
6791 Token token = _currentToken;
6792 for (int i = 0; i < distance; i++) {
6793 token = token.next;
6794 }
6795 return token;
6796 }
6797
6798 /**
6799 * Report the given [AnalysisError].
6800 *
6801 * @param error the error to be reported
6802 */
6803 void _reportError(AnalysisError error) {
6804 if (_errorListenerLock != 0) {
6805 return;
6806 }
6807 _errorListener.onError(error);
6808 }
6809
6810 /**
6811 * Report an error with the given error code and arguments.
6812 *
6813 * @param errorCode the error code of the error to be reported
6814 * @param arguments the arguments to the error, used to compose the error mess age
6815 */
6816 void _reportErrorForCurrentToken(ParserErrorCode errorCode, List<Object> argum ents) {
6817 _reportErrorForToken(errorCode, _currentToken, arguments);
6818 }
6819
6820 /**
6821 * Report an error with the given error code and arguments.
6822 *
6823 * @param errorCode the error code of the error to be reported
6824 * @param node the node specifying the location of the error
6825 * @param arguments the arguments to the error, used to compose the error mess age
6826 */
6827 void _reportErrorForNode(ParserErrorCode errorCode, AstNode node, List<Object> arguments) {
6828 _reportError(new AnalysisError.con2(_source, node.offset, node.length, error Code, arguments));
6829 }
6830
6831 /**
6832 * Report an error with the given error code and arguments.
6833 *
6834 * @param errorCode the error code of the error to be reported
6835 * @param token the token specifying the location of the error
6836 * @param arguments the arguments to the error, used to compose the error mess age
6837 */
6838 void _reportErrorForToken(ParserErrorCode errorCode, Token token, List<Object> arguments) {
6839 if (token.type == TokenType.EOF) {
6840 token = token.previous;
6841 }
6842 _reportError(new AnalysisError.con2(_source, token.offset, Math.max(token.le ngth, 1), errorCode, arguments));
6843 }
6844
6845 /**
6846 * Skips a block with all containing blocks.
6847 */
6848 void _skipBlock() {
6849 Token endToken = (_currentToken as BeginToken).endToken;
6850 if (endToken == null) {
6851 endToken = _currentToken.next;
6852 while (!identical(endToken, _currentToken)) {
6853 _currentToken = endToken;
6854 endToken = _currentToken.next;
6855 }
6856 _reportErrorForToken(ParserErrorCode.EXPECTED_TOKEN, _currentToken.previou s, ["}"]);
6857 } else {
6858 _currentToken = endToken.next;
6859 }
6860 }
6861
6862 /**
6863 * Parse the 'final', 'const', 'var' or type preceding a variable declaration, starting at the
6864 * given token, without actually creating a type or changing the current token . Return the token
6865 * following the type that was parsed, or `null` if the given token is not the first token
6866 * in a valid type.
6867 *
6868 * <pre>
6869 * finalConstVarOrType ::=
6870 * | 'final' type?
6871 * | 'const' type?
6872 * | 'var'
6873 * | type
6874 * </pre>
6875 *
6876 * @param startToken the token at which parsing is to begin
6877 * @return the token following the type that was parsed
6878 */
6879 Token _skipFinalConstVarOrType(Token startToken) {
6880 if (_tokenMatchesKeyword(startToken, Keyword.FINAL) || _tokenMatchesKeyword( startToken, Keyword.CONST)) {
6881 Token next = startToken.next;
6882 if (_tokenMatchesIdentifier(next)) {
6883 Token next2 = next.next;
6884 // "Type parameter" or "Type<" or "prefix.Type"
6885 if (_tokenMatchesIdentifier(next2) || _tokenMatches(next2, TokenType.LT) || _tokenMatches(next2, TokenType.PERIOD)) {
6886 return _skipTypeName(next);
6887 }
6888 // "parameter"
6889 return next;
6890 }
6891 } else if (_tokenMatchesKeyword(startToken, Keyword.VAR)) {
6892 return startToken.next;
6893 } else if (_tokenMatchesIdentifier(startToken)) {
6894 Token next = startToken.next;
6895 if (_tokenMatchesIdentifier(next) || _tokenMatches(next, TokenType.LT) || _tokenMatchesKeyword(next, Keyword.THIS) || (_tokenMatches(next, TokenType.PERIO D) && _tokenMatchesIdentifier(next.next) && (_tokenMatchesIdentifier(next.next.n ext) || _tokenMatches(next.next.next, TokenType.LT) || _tokenMatchesKeyword(next .next.next, Keyword.THIS)))) {
6896 return _skipReturnType(startToken);
6897 }
6898 }
6899 return null;
6900 }
6901
6902 /**
6903 * Parse a list of formal parameters, starting at the given token, without act ually creating a
6904 * formal parameter list or changing the current token. Return the token follo wing the formal
6905 * parameter list that was parsed, or `null` if the given token is not the fir st token in a
6906 * valid list of formal parameter.
6907 *
6908 * Note that unlike other skip methods, this method uses a heuristic. In the w orst case, the
6909 * parameters could be prefixed by metadata, which would require us to be able to skip arbitrary
6910 * expressions. Rather than duplicate the logic of most of the parse methods w e simply look for
6911 * something that is likely to be a list of parameters and then skip to return ing the token after
6912 * the closing parenthesis.
6913 *
6914 * This method must be kept in sync with [parseFormalParameterList].
6915 *
6916 * <pre>
6917 * formalParameterList ::=
6918 * '(' ')'
6919 * | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
6920 * | '(' optionalFormalParameters ')'
6921 *
6922 * normalFormalParameters ::=
6923 * normalFormalParameter (',' normalFormalParameter)*
6924 *
6925 * optionalFormalParameters ::=
6926 * optionalPositionalFormalParameters
6927 * | namedFormalParameters
6928 *
6929 * optionalPositionalFormalParameters ::=
6930 * '[' defaultFormalParameter (',' defaultFormalParameter)* ']'
6931 *
6932 * namedFormalParameters ::=
6933 * '{' defaultNamedParameter (',' defaultNamedParameter)* '}'
6934 * </pre>
6935 *
6936 * @param startToken the token at which parsing is to begin
6937 * @return the token following the formal parameter list that was parsed
6938 */
6939 Token _skipFormalParameterList(Token startToken) {
6940 if (!_tokenMatches(startToken, TokenType.OPEN_PAREN)) {
6941 return null;
6942 }
6943 Token next = startToken.next;
6944 if (_tokenMatches(next, TokenType.CLOSE_PAREN)) {
6945 return next.next;
6946 }
6947 //
6948 // Look to see whether the token after the open parenthesis is something tha t should only occur
6949 // at the beginning of a parameter list.
6950 //
6951 if (next.matchesAny([
6952 TokenType.AT,
6953 TokenType.OPEN_SQUARE_BRACKET,
6954 TokenType.OPEN_CURLY_BRACKET]) || _tokenMatchesKeyword(next, Keyword.VOI D) || (_tokenMatchesIdentifier(next) && (next.next.matchesAny([TokenType.COMMA, TokenType.CLOSE_PAREN])))) {
6955 return _skipPastMatchingToken(startToken);
6956 }
6957 //
6958 // Look to see whether the first parameter is a function typed parameter wit hout a return type.
6959 //
6960 if (_tokenMatchesIdentifier(next) && _tokenMatches(next.next, TokenType.OPEN _PAREN)) {
6961 Token afterParameters = _skipFormalParameterList(next.next);
6962 if (afterParameters != null && (afterParameters.matchesAny([TokenType.COMM A, TokenType.CLOSE_PAREN]))) {
6963 return _skipPastMatchingToken(startToken);
6964 }
6965 }
6966 //
6967 // Look to see whether the first parameter has a type or is a function typed parameter with a
6968 // return type.
6969 //
6970 Token afterType = _skipFinalConstVarOrType(next);
6971 if (afterType == null) {
6972 return null;
6973 }
6974 if (_skipSimpleIdentifier(afterType) == null) {
6975 return null;
6976 }
6977 return _skipPastMatchingToken(startToken);
6978 }
6979
6980 /**
6981 * If the given token is a begin token with an associated end token, then retu rn the token
6982 * following the end token. Otherwise, return `null`.
6983 *
6984 * @param startToken the token that is assumed to be a being token
6985 * @return the token following the matching end token
6986 */
6987 Token _skipPastMatchingToken(Token startToken) {
6988 if (startToken is! BeginToken) {
6989 return null;
6990 }
6991 Token closeParen = (startToken as BeginToken).endToken;
6992 if (closeParen == null) {
6993 return null;
6994 }
6995 return closeParen.next;
6996 }
6997
6998 /**
6999 * Parse a prefixed identifier, starting at the given token, without actually creating a prefixed
7000 * identifier or changing the current token. Return the token following the pr efixed identifier
7001 * that was parsed, or `null` if the given token is not the first token in a v alid prefixed
7002 * identifier.
7003 *
7004 * This method must be kept in sync with [parsePrefixedIdentifier].
7005 *
7006 * <pre>
7007 * prefixedIdentifier ::=
7008 * identifier ('.' identifier)?
7009 * </pre>
7010 *
7011 * @param startToken the token at which parsing is to begin
7012 * @return the token following the prefixed identifier that was parsed
7013 */
7014 Token _skipPrefixedIdentifier(Token startToken) {
7015 Token token = _skipSimpleIdentifier(startToken);
7016 if (token == null) {
7017 return null;
7018 } else if (!_tokenMatches(token, TokenType.PERIOD)) {
7019 return token;
7020 }
7021 return _skipSimpleIdentifier(token.next);
7022 }
7023
7024 /**
7025 * Parse a return type, starting at the given token, without actually creating a return type or
7026 * changing the current token. Return the token following the return type that was parsed, or
7027 * `null` if the given token is not the first token in a valid return type.
7028 *
7029 * This method must be kept in sync with [parseReturnType].
7030 *
7031 * <pre>
7032 * returnType ::=
7033 * 'void'
7034 * | type
7035 * </pre>
7036 *
7037 * @param startToken the token at which parsing is to begin
7038 * @return the token following the return type that was parsed
7039 */
7040 Token _skipReturnType(Token startToken) {
7041 if (_tokenMatchesKeyword(startToken, Keyword.VOID)) {
7042 return startToken.next;
7043 } else {
7044 return _skipTypeName(startToken);
7045 }
7046 }
7047
7048 /**
7049 * Parse a simple identifier, starting at the given token, without actually cr eating a simple
7050 * identifier or changing the current token. Return the token following the si mple identifier that
7051 * was parsed, or `null` if the given token is not the first token in a valid simple
7052 * identifier.
7053 *
7054 * This method must be kept in sync with [parseSimpleIdentifier].
7055 *
7056 * <pre>
7057 * identifier ::=
7058 * IDENTIFIER
7059 * </pre>
7060 *
7061 * @param startToken the token at which parsing is to begin
7062 * @return the token following the simple identifier that was parsed
7063 */
7064 Token _skipSimpleIdentifier(Token startToken) {
7065 if (_tokenMatches(startToken, TokenType.IDENTIFIER) || (_tokenMatches(startT oken, TokenType.KEYWORD) && (startToken as KeywordToken).keyword.isPseudoKeyword )) {
7066 return startToken.next;
7067 }
7068 return null;
7069 }
7070
7071 /**
7072 * Parse a string literal that contains interpolations, starting at the given token, without
7073 * actually creating a string literal or changing the current token. Return th e token following
7074 * the string literal that was parsed, or `null` if the given token is not the first token
7075 * in a valid string literal.
7076 *
7077 * This method must be kept in sync with [parseStringInterpolation].
7078 *
7079 * @param startToken the token at which parsing is to begin
7080 * @return the string literal that was parsed
7081 */
7082 Token _skipStringInterpolation(Token startToken) {
7083 Token token = startToken;
7084 TokenType type = token.type;
7085 while (type == TokenType.STRING_INTERPOLATION_EXPRESSION || type == TokenTyp e.STRING_INTERPOLATION_IDENTIFIER) {
7086 if (type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
7087 token = token.next;
7088 type = token.type;
7089 //
7090 // Rather than verify that the following tokens represent a valid expres sion, we simply skip
7091 // tokens until we reach the end of the interpolation, being careful to handle nested string
7092 // literals.
7093 //
7094 int bracketNestingLevel = 1;
7095 while (bracketNestingLevel > 0) {
7096 if (type == TokenType.EOF) {
7097 return null;
7098 } else if (type == TokenType.OPEN_CURLY_BRACKET) {
7099 bracketNestingLevel++;
7100 } else if (type == TokenType.CLOSE_CURLY_BRACKET) {
7101 bracketNestingLevel--;
7102 } else if (type == TokenType.STRING) {
7103 token = _skipStringLiteral(token);
7104 if (token == null) {
7105 return null;
7106 }
7107 } else {
7108 token = token.next;
7109 }
7110 type = token.type;
7111 }
7112 token = token.next;
7113 type = token.type;
7114 } else {
7115 token = token.next;
7116 if (token.type != TokenType.IDENTIFIER) {
7117 return null;
7118 }
7119 token = token.next;
7120 }
7121 type = token.type;
7122 if (type == TokenType.STRING) {
7123 token = token.next;
7124 type = token.type;
7125 }
7126 }
7127 return token;
7128 }
7129
7130 /**
7131 * Parse a string literal, starting at the given token, without actually creat ing a string literal
7132 * or changing the current token. Return the token following the string litera l that was parsed,
7133 * or `null` if the given token is not the first token in a valid string liter al.
7134 *
7135 * This method must be kept in sync with [parseStringLiteral].
7136 *
7137 * <pre>
7138 * stringLiteral ::=
7139 * MULTI_LINE_STRING+
7140 * | SINGLE_LINE_STRING+
7141 * </pre>
7142 *
7143 * @param startToken the token at which parsing is to begin
7144 * @return the token following the string literal that was parsed
7145 */
7146 Token _skipStringLiteral(Token startToken) {
7147 Token token = startToken;
7148 while (token != null && _tokenMatches(token, TokenType.STRING)) {
7149 token = token.next;
7150 TokenType type = token.type;
7151 if (type == TokenType.STRING_INTERPOLATION_EXPRESSION || type == TokenType .STRING_INTERPOLATION_IDENTIFIER) {
7152 token = _skipStringInterpolation(token);
7153 }
7154 }
7155 if (identical(token, startToken)) {
7156 return null;
7157 }
7158 return token;
7159 }
7160
7161 /**
7162 * Parse a list of type arguments, starting at the given token, without actual ly creating a type argument list
7163 * or changing the current token. Return the token following the type argument list that was parsed,
7164 * or `null` if the given token is not the first token in a valid type argumen t list.
7165 *
7166 * This method must be kept in sync with [parseTypeArgumentList].
7167 *
7168 * <pre>
7169 * typeArguments ::=
7170 * '<' typeList '>'
7171 *
7172 * typeList ::=
7173 * type (',' type)*
7174 * </pre>
7175 *
7176 * @param startToken the token at which parsing is to begin
7177 * @return the token following the type argument list that was parsed
7178 */
7179 Token _skipTypeArgumentList(Token startToken) {
7180 Token token = startToken;
7181 if (!_tokenMatches(token, TokenType.LT)) {
7182 return null;
7183 }
7184 token = _skipTypeName(token.next);
7185 if (token == null) {
7186 return null;
7187 }
7188 while (_tokenMatches(token, TokenType.COMMA)) {
7189 token = _skipTypeName(token.next);
7190 if (token == null) {
7191 return null;
7192 }
7193 }
7194 if (token.type == TokenType.GT) {
7195 return token.next;
7196 } else if (token.type == TokenType.GT_GT) {
7197 Token second = new Token(TokenType.GT, token.offset + 1);
7198 second.setNextWithoutSettingPrevious(token.next);
7199 return second;
7200 }
7201 return null;
7202 }
7203
7204 /**
7205 * Parse a type name, starting at the given token, without actually creating a type name or
7206 * changing the current token. Return the token following the type name that w as parsed, or
7207 * `null` if the given token is not the first token in a valid type name.
7208 *
7209 * This method must be kept in sync with [parseTypeName].
7210 *
7211 * <pre>
7212 * type ::=
7213 * qualified typeArguments?
7214 * </pre>
7215 *
7216 * @param startToken the token at which parsing is to begin
7217 * @return the token following the type name that was parsed
7218 */
7219 Token _skipTypeName(Token startToken) {
7220 Token token = _skipPrefixedIdentifier(startToken);
7221 if (token == null) {
7222 return null;
7223 }
7224 if (_tokenMatches(token, TokenType.LT)) {
7225 token = _skipTypeArgumentList(token);
7226 }
7227 return token;
7228 }
7229
7230 /**
7231 * Parse a list of type parameters, starting at the given token, without actua lly creating a type
7232 * parameter list or changing the current token. Return the token following th e type parameter
7233 * list that was parsed, or `null` if the given token is not the first token i n a valid type
7234 * parameter list.
7235 *
7236 * This method must be kept in sync with [parseTypeParameterList].
7237 *
7238 * <pre>
7239 * typeParameterList ::=
7240 * '<' typeParameter (',' typeParameter)* '>'
7241 * </pre>
7242 *
7243 * @param startToken the token at which parsing is to begin
7244 * @return the token following the type parameter list that was parsed
7245 */
7246 Token _skipTypeParameterList(Token startToken) {
7247 if (!_tokenMatches(startToken, TokenType.LT)) {
7248 return null;
7249 }
7250 //
7251 // We can't skip a type parameter because it can be preceeded by metadata, s o we just assume
7252 // that everything before the matching end token is valid.
7253 //
7254 int depth = 1;
7255 Token next = startToken.next;
7256 while (depth > 0) {
7257 if (_tokenMatches(next, TokenType.EOF)) {
7258 return null;
7259 } else if (_tokenMatches(next, TokenType.LT)) {
7260 depth++;
7261 } else if (_tokenMatches(next, TokenType.GT)) {
7262 depth--;
7263 } else if (_tokenMatches(next, TokenType.GT_EQ)) {
7264 if (depth == 1) {
7265 Token fakeEquals = new Token(TokenType.EQ, next.offset + 2);
7266 fakeEquals.setNextWithoutSettingPrevious(next.next);
7267 return fakeEquals;
7268 }
7269 depth--;
7270 } else if (_tokenMatches(next, TokenType.GT_GT)) {
7271 depth -= 2;
7272 } else if (_tokenMatches(next, TokenType.GT_GT_EQ)) {
7273 if (depth < 2) {
7274 return null;
7275 } else if (depth == 2) {
7276 Token fakeEquals = new Token(TokenType.EQ, next.offset + 2);
7277 fakeEquals.setNextWithoutSettingPrevious(next.next);
7278 return fakeEquals;
7279 }
7280 depth -= 2;
7281 }
7282 next = next.next;
7283 }
7284 return next;
7285 }
7286
7287 /**
7288 * Return `true` if the given token has the given type.
7289 *
7290 * @param token the token being tested
7291 * @param type the type of token that is being tested for
7292 * @return `true` if the given token has the given type
7293 */
7294 bool _tokenMatches(Token token, TokenType type) => token.type == type;
7295
7296 /**
7297 * Return `true` if the given token is a valid identifier. Valid identifiers i nclude
7298 * built-in identifiers (pseudo-keywords).
7299 *
7300 * @return `true` if the given token is a valid identifier
7301 */
7302 bool _tokenMatchesIdentifier(Token token) => _tokenMatches(token, TokenType.ID ENTIFIER) || (_tokenMatches(token, TokenType.KEYWORD) && (token as KeywordToken) .keyword.isPseudoKeyword);
7303
7304 /**
7305 * Return `true` if the given token matches the given keyword.
7306 *
7307 * @param token the token being tested
7308 * @param keyword the keyword that is being tested for
7309 * @return `true` if the given token matches the given keyword
7310 */
7311 bool _tokenMatchesKeyword(Token token, Keyword keyword) => token.type == Token Type.KEYWORD && (token as KeywordToken).keyword == keyword;
7312
7313 /**
7314 * Return `true` if the given token matches the given identifier.
7315 *
7316 * @param token the token being tested
7317 * @param identifier the identifier that can optionally appear in the current location
7318 * @return `true` if the current token matches the given identifier
7319 */
7320 bool _tokenMatchesString(Token token, String identifier) => token.type == Toke nType.IDENTIFIER && token.lexeme == identifier;
7321
7322 /**
7323 * Translate the characters at the given index in the given string, appending the translated
7324 * character to the given builder. The index is assumed to be valid.
7325 *
7326 * @param builder the builder to which the translated character is to be appen ded
7327 * @param lexeme the string containing the character(s) to be translated
7328 * @param index the index of the character to be translated
7329 * @return the index of the next character to be translated
7330 */
7331 int _translateCharacter(JavaStringBuilder builder, String lexeme, int index) {
7332 int currentChar = lexeme.codeUnitAt(index);
7333 if (currentChar != 0x5C) {
7334 builder.appendChar(currentChar);
7335 return index + 1;
7336 }
7337 //
7338 // We have found an escape sequence, so we parse the string to determine wha t kind of escape
7339 // sequence and what character to add to the builder.
7340 //
7341 int length = lexeme.length;
7342 int currentIndex = index + 1;
7343 if (currentIndex >= length) {
7344 // Illegal escape sequence: no char after escape
7345 // This cannot actually happen because it would require the escape charact er to be the last
7346 // character in the string, but if it were it would escape the closing quo te, leaving the
7347 // string unclosed.
7348 // reportError(ParserErrorCode.MISSING_CHAR_IN_ESCAPE_SEQUENCE);
7349 return length;
7350 }
7351 currentChar = lexeme.codeUnitAt(currentIndex);
7352 if (currentChar == 0x6E) {
7353 builder.appendChar(0xA);
7354 } else if (currentChar == 0x72) {
7355 builder.appendChar(0xD);
7356 } else if (currentChar == 0x66) {
7357 builder.appendChar(0xC);
7358 } else if (currentChar == 0x62) {
7359 builder.appendChar(0x8);
7360 } else if (currentChar == 0x74) {
7361 builder.appendChar(0x9);
7362 } else if (currentChar == 0x76) {
7363 builder.appendChar(0xB);
7364 } else if (currentChar == 0x78) {
7365 if (currentIndex + 2 >= length) {
7366 // Illegal escape sequence: not enough hex digits
7367 _reportErrorForCurrentToken(ParserErrorCode.INVALID_HEX_ESCAPE, []);
7368 return length;
7369 }
7370 int firstDigit = lexeme.codeUnitAt(currentIndex + 1);
7371 int secondDigit = lexeme.codeUnitAt(currentIndex + 2);
7372 if (!_isHexDigit(firstDigit) || !_isHexDigit(secondDigit)) {
7373 // Illegal escape sequence: invalid hex digit
7374 _reportErrorForCurrentToken(ParserErrorCode.INVALID_HEX_ESCAPE, []);
7375 } else {
7376 builder.appendChar(((Character.digit(firstDigit, 16) << 4) + Character.d igit(secondDigit, 16)));
7377 }
7378 return currentIndex + 3;
7379 } else if (currentChar == 0x75) {
7380 currentIndex++;
7381 if (currentIndex >= length) {
7382 // Illegal escape sequence: not enough hex digits
7383 _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
7384 return length;
7385 }
7386 currentChar = lexeme.codeUnitAt(currentIndex);
7387 if (currentChar == 0x7B) {
7388 currentIndex++;
7389 if (currentIndex >= length) {
7390 // Illegal escape sequence: incomplete escape
7391 _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE, [] );
7392 return length;
7393 }
7394 currentChar = lexeme.codeUnitAt(currentIndex);
7395 int digitCount = 0;
7396 int value = 0;
7397 while (currentChar != 0x7D) {
7398 if (!_isHexDigit(currentChar)) {
7399 // Illegal escape sequence: invalid hex digit
7400 _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
7401 currentIndex++;
7402 while (currentIndex < length && lexeme.codeUnitAt(currentIndex) != 0 x7D) {
7403 currentIndex++;
7404 }
7405 return currentIndex + 1;
7406 }
7407 digitCount++;
7408 value = (value << 4) + Character.digit(currentChar, 16);
7409 currentIndex++;
7410 if (currentIndex >= length) {
7411 // Illegal escape sequence: incomplete escape
7412 _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
7413 return length;
7414 }
7415 currentChar = lexeme.codeUnitAt(currentIndex);
7416 }
7417 if (digitCount < 1 || digitCount > 6) {
7418 // Illegal escape sequence: not enough or too many hex digits
7419 _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE, [] );
7420 }
7421 _appendScalarValue(builder, lexeme.substring(index, currentIndex + 1), v alue, index, currentIndex);
7422 return currentIndex + 1;
7423 } else {
7424 if (currentIndex + 3 >= length) {
7425 // Illegal escape sequence: not enough hex digits
7426 _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE, [] );
7427 return length;
7428 }
7429 int firstDigit = currentChar;
7430 int secondDigit = lexeme.codeUnitAt(currentIndex + 1);
7431 int thirdDigit = lexeme.codeUnitAt(currentIndex + 2);
7432 int fourthDigit = lexeme.codeUnitAt(currentIndex + 3);
7433 if (!_isHexDigit(firstDigit) || !_isHexDigit(secondDigit) || !_isHexDigi t(thirdDigit) || !_isHexDigit(fourthDigit)) {
7434 // Illegal escape sequence: invalid hex digits
7435 _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE, [] );
7436 } else {
7437 _appendScalarValue(builder, lexeme.substring(index, currentIndex + 1), (((((Character.digit(firstDigit, 16) << 4) + Character.digit(secondDigit, 16)) << 4) + Character.digit(thirdDigit, 16)) << 4) + Character.digit(fourthDigit, 16 ), index, currentIndex + 3);
7438 }
7439 return currentIndex + 4;
7440 }
7441 } else {
7442 builder.appendChar(currentChar);
7443 }
7444 return currentIndex + 1;
7445 }
7446
7447 /**
7448 * Decrements the error reporting lock level. If level is more than `0`, then
7449 * [reportError] wont report any error.
7450 */
7451 void _unlockErrorListener() {
7452 if (_errorListenerLock == 0) {
7453 throw new IllegalStateException("Attempt to unlock not locked error listen er.");
7454 }
7455 _errorListenerLock--;
7456 }
7457
7458 /**
7459 * Validate that the given parameter list does not contain any field initializ ers.
7460 *
7461 * @param parameterList the parameter list to be validated
7462 */
7463 void _validateFormalParameterList(FormalParameterList parameterList) {
7464 for (FormalParameter parameter in parameterList.parameters) {
7465 if (parameter is FieldFormalParameter) {
7466 _reportErrorForNode(ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTO R, parameter.identifier, []);
7467 }
7468 }
7469 }
7470
7471 /**
7472 * Validate that the given set of modifiers is appropriate for a class and ret urn the 'abstract'
7473 * keyword if there is one.
7474 *
7475 * @param modifiers the modifiers being validated
7476 */
7477 Token _validateModifiersForClass(Modifiers modifiers) {
7478 _validateModifiersForTopLevelDeclaration(modifiers);
7479 if (modifiers.constKeyword != null) {
7480 _reportErrorForToken(ParserErrorCode.CONST_CLASS, modifiers.constKeyword, []);
7481 }
7482 if (modifiers.externalKeyword != null) {
7483 _reportErrorForToken(ParserErrorCode.EXTERNAL_CLASS, modifiers.externalKey word, []);
7484 }
7485 if (modifiers.finalKeyword != null) {
7486 _reportErrorForToken(ParserErrorCode.FINAL_CLASS, modifiers.finalKeyword, []);
7487 }
7488 if (modifiers.varKeyword != null) {
7489 _reportErrorForToken(ParserErrorCode.VAR_CLASS, modifiers.varKeyword, []);
7490 }
7491 return modifiers.abstractKeyword;
7492 }
7493
7494 /**
7495 * Validate that the given set of modifiers is appropriate for a constructor a nd return the
7496 * 'const' keyword if there is one.
7497 *
7498 * @param modifiers the modifiers being validated
7499 * @return the 'const' or 'final' keyword associated with the constructor
7500 */
7501 Token _validateModifiersForConstructor(Modifiers modifiers) {
7502 if (modifiers.abstractKeyword != null) {
7503 _reportErrorForToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER, modifiers.abst ractKeyword, []);
7504 }
7505 if (modifiers.finalKeyword != null) {
7506 _reportErrorForToken(ParserErrorCode.FINAL_CONSTRUCTOR, modifiers.finalKey word, []);
7507 }
7508 if (modifiers.staticKeyword != null) {
7509 _reportErrorForToken(ParserErrorCode.STATIC_CONSTRUCTOR, modifiers.staticK eyword, []);
7510 }
7511 if (modifiers.varKeyword != null) {
7512 _reportErrorForToken(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, modifie rs.varKeyword, []);
7513 }
7514 Token externalKeyword = modifiers.externalKeyword;
7515 Token constKeyword = modifiers.constKeyword;
7516 Token factoryKeyword = modifiers.factoryKeyword;
7517 if (externalKeyword != null && constKeyword != null && constKeyword.offset < externalKeyword.offset) {
7518 _reportErrorForToken(ParserErrorCode.EXTERNAL_AFTER_CONST, externalKeyword , []);
7519 }
7520 if (externalKeyword != null && factoryKeyword != null && factoryKeyword.offs et < externalKeyword.offset) {
7521 _reportErrorForToken(ParserErrorCode.EXTERNAL_AFTER_FACTORY, externalKeywo rd, []);
7522 }
7523 return constKeyword;
7524 }
7525
7526 /**
7527 * Validate that the given set of modifiers is appropriate for a class and ret urn the 'abstract'
7528 * keyword if there is one.
7529 *
7530 * @param modifiers the modifiers being validated
7531 */
7532 void _validateModifiersForEnum(Modifiers modifiers) {
7533 _validateModifiersForTopLevelDeclaration(modifiers);
7534 if (modifiers.abstractKeyword != null) {
7535 _reportErrorForToken(ParserErrorCode.ABSTRACT_ENUM, modifiers.abstractKeyw ord, []);
7536 }
7537 if (modifiers.constKeyword != null) {
7538 _reportErrorForToken(ParserErrorCode.CONST_ENUM, modifiers.constKeyword, [ ]);
7539 }
7540 if (modifiers.externalKeyword != null) {
7541 _reportErrorForToken(ParserErrorCode.EXTERNAL_ENUM, modifiers.externalKeyw ord, []);
7542 }
7543 if (modifiers.finalKeyword != null) {
7544 _reportErrorForToken(ParserErrorCode.FINAL_ENUM, modifiers.finalKeyword, [ ]);
7545 }
7546 if (modifiers.varKeyword != null) {
7547 _reportErrorForToken(ParserErrorCode.VAR_ENUM, modifiers.varKeyword, []);
7548 }
7549 }
7550
7551 /**
7552 * Validate that the given set of modifiers is appropriate for a field and ret urn the 'final',
7553 * 'const' or 'var' keyword if there is one.
7554 *
7555 * @param modifiers the modifiers being validated
7556 * @return the 'final', 'const' or 'var' keyword associated with the field
7557 */
7558 Token _validateModifiersForField(Modifiers modifiers) {
7559 if (modifiers.abstractKeyword != null) {
7560 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER, []);
7561 }
7562 if (modifiers.externalKeyword != null) {
7563 _reportErrorForToken(ParserErrorCode.EXTERNAL_FIELD, modifiers.externalKey word, []);
7564 }
7565 if (modifiers.factoryKeyword != null) {
7566 _reportErrorForToken(ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.fa ctoryKeyword, []);
7567 }
7568 Token staticKeyword = modifiers.staticKeyword;
7569 Token constKeyword = modifiers.constKeyword;
7570 Token finalKeyword = modifiers.finalKeyword;
7571 Token varKeyword = modifiers.varKeyword;
7572 if (constKeyword != null) {
7573 if (finalKeyword != null) {
7574 _reportErrorForToken(ParserErrorCode.CONST_AND_FINAL, finalKeyword, []);
7575 }
7576 if (varKeyword != null) {
7577 _reportErrorForToken(ParserErrorCode.CONST_AND_VAR, varKeyword, []);
7578 }
7579 if (staticKeyword != null && constKeyword.offset < staticKeyword.offset) {
7580 _reportErrorForToken(ParserErrorCode.STATIC_AFTER_CONST, staticKeyword, []);
7581 }
7582 } else if (finalKeyword != null) {
7583 if (varKeyword != null) {
7584 _reportErrorForToken(ParserErrorCode.FINAL_AND_VAR, varKeyword, []);
7585 }
7586 if (staticKeyword != null && finalKeyword.offset < staticKeyword.offset) {
7587 _reportErrorForToken(ParserErrorCode.STATIC_AFTER_FINAL, staticKeyword, []);
7588 }
7589 } else if (varKeyword != null && staticKeyword != null && varKeyword.offset < staticKeyword.offset) {
7590 _reportErrorForToken(ParserErrorCode.STATIC_AFTER_VAR, staticKeyword, []);
7591 }
7592 return _lexicallyFirst([constKeyword, finalKeyword, varKeyword]);
7593 }
7594
7595 /**
7596 * Validate that the given set of modifiers is appropriate for a local functio n.
7597 *
7598 * @param modifiers the modifiers being validated
7599 */
7600 void _validateModifiersForFunctionDeclarationStatement(Modifiers modifiers) {
7601 if (modifiers.abstractKeyword != null || modifiers.constKeyword != null || m odifiers.externalKeyword != null || modifiers.factoryKeyword != null || modifier s.finalKeyword != null || modifiers.staticKeyword != null || modifiers.varKeywor d != null) {
7602 _reportErrorForCurrentToken(ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MOD IFIER, []);
7603 }
7604 }
7605
7606 /**
7607 * Validate that the given set of modifiers is appropriate for a getter, sette r, or method.
7608 *
7609 * @param modifiers the modifiers being validated
7610 */
7611 void _validateModifiersForGetterOrSetterOrMethod(Modifiers modifiers) {
7612 if (modifiers.abstractKeyword != null) {
7613 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER, []);
7614 }
7615 if (modifiers.constKeyword != null) {
7616 _reportErrorForToken(ParserErrorCode.CONST_METHOD, modifiers.constKeyword, []);
7617 }
7618 if (modifiers.factoryKeyword != null) {
7619 _reportErrorForToken(ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.fa ctoryKeyword, []);
7620 }
7621 if (modifiers.finalKeyword != null) {
7622 _reportErrorForToken(ParserErrorCode.FINAL_METHOD, modifiers.finalKeyword, []);
7623 }
7624 if (modifiers.varKeyword != null) {
7625 _reportErrorForToken(ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword , []);
7626 }
7627 Token externalKeyword = modifiers.externalKeyword;
7628 Token staticKeyword = modifiers.staticKeyword;
7629 if (externalKeyword != null && staticKeyword != null && staticKeyword.offset < externalKeyword.offset) {
7630 _reportErrorForToken(ParserErrorCode.EXTERNAL_AFTER_STATIC, externalKeywor d, []);
7631 }
7632 }
7633
7634 /**
7635 * Validate that the given set of modifiers is appropriate for a getter, sette r, or method.
7636 *
7637 * @param modifiers the modifiers being validated
7638 */
7639 void _validateModifiersForOperator(Modifiers modifiers) {
7640 if (modifiers.abstractKeyword != null) {
7641 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER, []);
7642 }
7643 if (modifiers.constKeyword != null) {
7644 _reportErrorForToken(ParserErrorCode.CONST_METHOD, modifiers.constKeyword, []);
7645 }
7646 if (modifiers.factoryKeyword != null) {
7647 _reportErrorForToken(ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.fa ctoryKeyword, []);
7648 }
7649 if (modifiers.finalKeyword != null) {
7650 _reportErrorForToken(ParserErrorCode.FINAL_METHOD, modifiers.finalKeyword, []);
7651 }
7652 if (modifiers.staticKeyword != null) {
7653 _reportErrorForToken(ParserErrorCode.STATIC_OPERATOR, modifiers.staticKeyw ord, []);
7654 }
7655 if (modifiers.varKeyword != null) {
7656 _reportErrorForToken(ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword , []);
7657 }
7658 }
7659
7660 /**
7661 * Validate that the given set of modifiers is appropriate for a top-level dec laration.
7662 *
7663 * @param modifiers the modifiers being validated
7664 */
7665 void _validateModifiersForTopLevelDeclaration(Modifiers modifiers) {
7666 if (modifiers.factoryKeyword != null) {
7667 _reportErrorForToken(ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION, modifi ers.factoryKeyword, []);
7668 }
7669 if (modifiers.staticKeyword != null) {
7670 _reportErrorForToken(ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION, modifie rs.staticKeyword, []);
7671 }
7672 }
7673
7674 /**
7675 * Validate that the given set of modifiers is appropriate for a top-level fun ction.
7676 *
7677 * @param modifiers the modifiers being validated
7678 */
7679 void _validateModifiersForTopLevelFunction(Modifiers modifiers) {
7680 _validateModifiersForTopLevelDeclaration(modifiers);
7681 if (modifiers.abstractKeyword != null) {
7682 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION, [ ]);
7683 }
7684 if (modifiers.constKeyword != null) {
7685 _reportErrorForToken(ParserErrorCode.CONST_CLASS, modifiers.constKeyword, []);
7686 }
7687 if (modifiers.finalKeyword != null) {
7688 _reportErrorForToken(ParserErrorCode.FINAL_CLASS, modifiers.finalKeyword, []);
7689 }
7690 if (modifiers.varKeyword != null) {
7691 _reportErrorForToken(ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword , []);
7692 }
7693 }
7694
7695 /**
7696 * Validate that the given set of modifiers is appropriate for a field and ret urn the 'final',
7697 * 'const' or 'var' keyword if there is one.
7698 *
7699 * @param modifiers the modifiers being validated
7700 * @return the 'final', 'const' or 'var' keyword associated with the field
7701 */
7702 Token _validateModifiersForTopLevelVariable(Modifiers modifiers) {
7703 _validateModifiersForTopLevelDeclaration(modifiers);
7704 if (modifiers.abstractKeyword != null) {
7705 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_TOP_LEVEL_VARIABLE, [ ]);
7706 }
7707 if (modifiers.externalKeyword != null) {
7708 _reportErrorForToken(ParserErrorCode.EXTERNAL_FIELD, modifiers.externalKey word, []);
7709 }
7710 Token constKeyword = modifiers.constKeyword;
7711 Token finalKeyword = modifiers.finalKeyword;
7712 Token varKeyword = modifiers.varKeyword;
7713 if (constKeyword != null) {
7714 if (finalKeyword != null) {
7715 _reportErrorForToken(ParserErrorCode.CONST_AND_FINAL, finalKeyword, []);
7716 }
7717 if (varKeyword != null) {
7718 _reportErrorForToken(ParserErrorCode.CONST_AND_VAR, varKeyword, []);
7719 }
7720 } else if (finalKeyword != null) {
7721 if (varKeyword != null) {
7722 _reportErrorForToken(ParserErrorCode.FINAL_AND_VAR, varKeyword, []);
7723 }
7724 }
7725 return _lexicallyFirst([constKeyword, finalKeyword, varKeyword]);
7726 }
7727
7728 /**
7729 * Validate that the given set of modifiers is appropriate for a class and ret urn the 'abstract'
7730 * keyword if there is one.
7731 *
7732 * @param modifiers the modifiers being validated
7733 */
7734 void _validateModifiersForTypedef(Modifiers modifiers) {
7735 _validateModifiersForTopLevelDeclaration(modifiers);
7736 if (modifiers.abstractKeyword != null) {
7737 _reportErrorForToken(ParserErrorCode.ABSTRACT_TYPEDEF, modifiers.abstractK eyword, []);
7738 }
7739 if (modifiers.constKeyword != null) {
7740 _reportErrorForToken(ParserErrorCode.CONST_TYPEDEF, modifiers.constKeyword , []);
7741 }
7742 if (modifiers.externalKeyword != null) {
7743 _reportErrorForToken(ParserErrorCode.EXTERNAL_TYPEDEF, modifiers.externalK eyword, []);
7744 }
7745 if (modifiers.finalKeyword != null) {
7746 _reportErrorForToken(ParserErrorCode.FINAL_TYPEDEF, modifiers.finalKeyword , []);
7747 }
7748 if (modifiers.varKeyword != null) {
7749 _reportErrorForToken(ParserErrorCode.VAR_TYPEDEF, modifiers.varKeyword, [] );
7750 }
7751 }
7752 }
7753
7754 /**
7755 * The enumeration `ParserErrorCode` defines the error codes used for errors det ected by the
7756 * parser. The convention for this class is for the name of the error code to in dicate the problem
7757 * that caused the error to be generated and for the error message to explain wh at is wrong and,
7758 * when appropriate, how the problem can be corrected.
7759 */
7760 class ParserErrorCode extends Enum<ParserErrorCode> implements ErrorCode {
7761 static const ParserErrorCode ABSTRACT_CLASS_MEMBER = const ParserErrorCode.con 3('ABSTRACT_CLASS_MEMBER', 0, "Members of classes cannot be declared to be 'abst ract'");
7762
7763 static const ParserErrorCode ABSTRACT_ENUM = const ParserErrorCode.con3('ABSTR ACT_ENUM', 1, "Enums cannot be declared to be 'abstract'");
7764
7765 static const ParserErrorCode ABSTRACT_STATIC_METHOD = const ParserErrorCode.co n3('ABSTRACT_STATIC_METHOD', 2, "Static methods cannot be declared to be 'abstra ct'");
7766
7767 static const ParserErrorCode ABSTRACT_TOP_LEVEL_FUNCTION = const ParserErrorCo de.con3('ABSTRACT_TOP_LEVEL_FUNCTION', 3, "Top-level functions cannot be declare d to be 'abstract'");
7768
7769 static const ParserErrorCode ABSTRACT_TOP_LEVEL_VARIABLE = const ParserErrorCo de.con3('ABSTRACT_TOP_LEVEL_VARIABLE', 4, "Top-level variables cannot be declare d to be 'abstract'");
7770
7771 static const ParserErrorCode ABSTRACT_TYPEDEF = const ParserErrorCode.con3('AB STRACT_TYPEDEF', 5, "Type aliases cannot be declared to be 'abstract'");
7772
7773 static const ParserErrorCode ASSERT_DOES_NOT_TAKE_ASSIGNMENT = const ParserErr orCode.con3('ASSERT_DOES_NOT_TAKE_ASSIGNMENT', 6, "Assert cannot be called on an assignment");
7774
7775 static const ParserErrorCode ASSERT_DOES_NOT_TAKE_CASCADE = const ParserErrorC ode.con3('ASSERT_DOES_NOT_TAKE_CASCADE', 7, "Assert cannot be called on cascade" );
7776
7777 static const ParserErrorCode ASSERT_DOES_NOT_TAKE_THROW = const ParserErrorCod e.con3('ASSERT_DOES_NOT_TAKE_THROW', 8, "Assert cannot be called on throws");
7778
7779 static const ParserErrorCode ASSERT_DOES_NOT_TAKE_RETHROW = const ParserErrorC ode.con3('ASSERT_DOES_NOT_TAKE_RETHROW', 9, "Assert cannot be called on rethrows ");
7780
7781 static const ParserErrorCode BREAK_OUTSIDE_OF_LOOP = const ParserErrorCode.con 3('BREAK_OUTSIDE_OF_LOOP', 10, "A break statement cannot be used outside of a lo op or switch statement");
7782
7783 static const ParserErrorCode CONST_AND_FINAL = const ParserErrorCode.con3('CON ST_AND_FINAL', 11, "Members cannot be declared to be both 'const' and 'final'");
7784
7785 static const ParserErrorCode CONST_AND_VAR = const ParserErrorCode.con3('CONST _AND_VAR', 12, "Members cannot be declared to be both 'const' and 'var'");
7786
7787 static const ParserErrorCode CONST_CLASS = const ParserErrorCode.con3('CONST_C LASS', 13, "Classes cannot be declared to be 'const'");
7788
7789 static const ParserErrorCode CONST_CONSTRUCTOR_WITH_BODY = const ParserErrorCo de.con3('CONST_CONSTRUCTOR_WITH_BODY', 14, "'const' constructors cannot have a b ody");
7790
7791 static const ParserErrorCode CONST_ENUM = const ParserErrorCode.con3('CONST_EN UM', 15, "Enums cannot be declared to be 'const'");
7792
7793 static const ParserErrorCode CONST_FACTORY = const ParserErrorCode.con3('CONST _FACTORY', 16, "Only redirecting factory constructors can be declared to be 'con st'");
7794
7795 static const ParserErrorCode CONST_METHOD = const ParserErrorCode.con3('CONST_ METHOD', 17, "Getters, setters and methods cannot be declared to be 'const'");
7796
7797 static const ParserErrorCode CONST_TYPEDEF = const ParserErrorCode.con3('CONST _TYPEDEF', 18, "Type aliases cannot be declared to be 'const'");
7798
7799 static const ParserErrorCode CONSTRUCTOR_WITH_RETURN_TYPE = const ParserErrorC ode.con3('CONSTRUCTOR_WITH_RETURN_TYPE', 19, "Constructors cannot have a return type");
7800
7801 static const ParserErrorCode CONTINUE_OUTSIDE_OF_LOOP = const ParserErrorCode. con3('CONTINUE_OUTSIDE_OF_LOOP', 20, "A continue statement cannot be used outsid e of a loop or switch statement");
7802
7803 static const ParserErrorCode CONTINUE_WITHOUT_LABEL_IN_CASE = const ParserErro rCode.con3('CONTINUE_WITHOUT_LABEL_IN_CASE', 21, "A continue statement in a swit ch statement must have a label as a target");
7804
7805 static const ParserErrorCode DEFERRED_IMPORTS_NOT_SUPPORTED = const ParserErro rCode.con3('DEFERRED_IMPORTS_NOT_SUPPORTED', 22, "Deferred imports are not suppo rted by default");
7806
7807 static const ParserErrorCode DEPRECATED_CLASS_TYPE_ALIAS = const ParserErrorCo de.con3('DEPRECATED_CLASS_TYPE_ALIAS', 23, "The 'typedef' mixin application was replaced with 'class'");
7808
7809 static const ParserErrorCode DIRECTIVE_AFTER_DECLARATION = const ParserErrorCo de.con3('DIRECTIVE_AFTER_DECLARATION', 24, "Directives must appear before any de clarations");
7810
7811 static const ParserErrorCode DUPLICATE_LABEL_IN_SWITCH_STATEMENT = const Parse rErrorCode.con3('DUPLICATE_LABEL_IN_SWITCH_STATEMENT', 25, "The label {0} was al ready used in this switch statement");
7812
7813 static const ParserErrorCode DUPLICATED_MODIFIER = const ParserErrorCode.con3( 'DUPLICATED_MODIFIER', 26, "The modifier '{0}' was already specified.");
7814
7815 static const ParserErrorCode EMPTY_ENUM_BODY = const ParserErrorCode.con3('EMP TY_ENUM_BODY', 27, "An enum must declare at least one constant name");
7816
7817 static const ParserErrorCode EQUALITY_CANNOT_BE_EQUALITY_OPERAND = const Parse rErrorCode.con3('EQUALITY_CANNOT_BE_EQUALITY_OPERAND', 28, "Equality expression cannot be operand of another equality expression.");
7818
7819 static const ParserErrorCode EXPECTED_CASE_OR_DEFAULT = const ParserErrorCode. con3('EXPECTED_CASE_OR_DEFAULT', 29, "Expected 'case' or 'default'");
7820
7821 static const ParserErrorCode EXPECTED_CLASS_MEMBER = const ParserErrorCode.con 3('EXPECTED_CLASS_MEMBER', 30, "Expected a class member");
7822
7823 static const ParserErrorCode EXPECTED_EXECUTABLE = const ParserErrorCode.con3( 'EXPECTED_EXECUTABLE', 31, "Expected a method, getter, setter or operator declar ation");
7824
7825 static const ParserErrorCode EXPECTED_LIST_OR_MAP_LITERAL = const ParserErrorC ode.con3('EXPECTED_LIST_OR_MAP_LITERAL', 32, "Expected a list or map literal");
7826
7827 static const ParserErrorCode EXPECTED_STRING_LITERAL = const ParserErrorCode.c on3('EXPECTED_STRING_LITERAL', 33, "Expected a string literal");
7828
7829 static const ParserErrorCode EXPECTED_TOKEN = const ParserErrorCode.con3('EXPE CTED_TOKEN', 34, "Expected to find '{0}'");
7830
7831 static const ParserErrorCode EXPECTED_TYPE_NAME = const ParserErrorCode.con3(' EXPECTED_TYPE_NAME', 35, "Expected a type name");
7832
7833 static const ParserErrorCode EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE = const Par serErrorCode.con3('EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE', 36, "Export directive s must preceed part directives");
7834
7835 static const ParserErrorCode EXTERNAL_AFTER_CONST = const ParserErrorCode.con3 ('EXTERNAL_AFTER_CONST', 37, "The modifier 'external' should be before the modif ier 'const'");
7836
7837 static const ParserErrorCode EXTERNAL_AFTER_FACTORY = const ParserErrorCode.co n3('EXTERNAL_AFTER_FACTORY', 38, "The modifier 'external' should be before the m odifier 'factory'");
7838
7839 static const ParserErrorCode EXTERNAL_AFTER_STATIC = const ParserErrorCode.con 3('EXTERNAL_AFTER_STATIC', 39, "The modifier 'external' should be before the mod ifier 'static'");
7840
7841 static const ParserErrorCode EXTERNAL_CLASS = const ParserErrorCode.con3('EXTE RNAL_CLASS', 40, "Classes cannot be declared to be 'external'");
7842
7843 static const ParserErrorCode EXTERNAL_CONSTRUCTOR_WITH_BODY = const ParserErro rCode.con3('EXTERNAL_CONSTRUCTOR_WITH_BODY', 41, "External constructors cannot h ave a body");
7844
7845 static const ParserErrorCode EXTERNAL_ENUM = const ParserErrorCode.con3('EXTER NAL_ENUM', 42, "Enums cannot be declared to be 'external'");
7846
7847 static const ParserErrorCode EXTERNAL_FIELD = const ParserErrorCode.con3('EXTE RNAL_FIELD', 43, "Fields cannot be declared to be 'external'");
7848
7849 static const ParserErrorCode EXTERNAL_GETTER_WITH_BODY = const ParserErrorCode .con3('EXTERNAL_GETTER_WITH_BODY', 44, "External getters cannot have a body");
7850
7851 static const ParserErrorCode EXTERNAL_METHOD_WITH_BODY = const ParserErrorCode .con3('EXTERNAL_METHOD_WITH_BODY', 45, "External methods cannot have a body");
7852
7853 static const ParserErrorCode EXTERNAL_OPERATOR_WITH_BODY = const ParserErrorCo de.con3('EXTERNAL_OPERATOR_WITH_BODY', 46, "External operators cannot have a bod y");
7854
7855 static const ParserErrorCode EXTERNAL_SETTER_WITH_BODY = const ParserErrorCode .con3('EXTERNAL_SETTER_WITH_BODY', 47, "External setters cannot have a body");
7856
7857 static const ParserErrorCode EXTERNAL_TYPEDEF = const ParserErrorCode.con3('EX TERNAL_TYPEDEF', 48, "Type aliases cannot be declared to be 'external'");
7858
7859 static const ParserErrorCode FACTORY_TOP_LEVEL_DECLARATION = const ParserError Code.con3('FACTORY_TOP_LEVEL_DECLARATION', 49, "Top-level declarations cannot be declared to be 'factory'");
7860
7861 static const ParserErrorCode FACTORY_WITHOUT_BODY = const ParserErrorCode.con3 ('FACTORY_WITHOUT_BODY', 50, "A non-redirecting 'factory' constructor must have a body");
7862
7863 static const ParserErrorCode FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR = const Par serErrorCode.con3('FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR', 51, "Field initialize rs can only be used in a constructor");
7864
7865 static const ParserErrorCode FINAL_AND_VAR = const ParserErrorCode.con3('FINAL _AND_VAR', 52, "Members cannot be declared to be both 'final' and 'var'");
7866
7867 static const ParserErrorCode FINAL_CLASS = const ParserErrorCode.con3('FINAL_C LASS', 53, "Classes cannot be declared to be 'final'");
7868
7869 static const ParserErrorCode FINAL_CONSTRUCTOR = const ParserErrorCode.con3('F INAL_CONSTRUCTOR', 54, "A constructor cannot be declared to be 'final'");
7870
7871 static const ParserErrorCode FINAL_ENUM = const ParserErrorCode.con3('FINAL_EN UM', 55, "Enums cannot be declared to be 'final'");
7872
7873 static const ParserErrorCode FINAL_METHOD = const ParserErrorCode.con3('FINAL_ METHOD', 56, "Getters, setters and methods cannot be declared to be 'final'");
7874
7875 static const ParserErrorCode FINAL_TYPEDEF = const ParserErrorCode.con3('FINAL _TYPEDEF', 57, "Type aliases cannot be declared to be 'final'");
7876
7877 static const ParserErrorCode FUNCTION_TYPED_PARAMETER_VAR = const ParserErrorC ode.con3('FUNCTION_TYPED_PARAMETER_VAR', 58, "Function typed parameters cannot s pecify 'const', 'final' or 'var' instead of return type");
7878
7879 static const ParserErrorCode GETTER_IN_FUNCTION = const ParserErrorCode.con3(' GETTER_IN_FUNCTION', 59, "Getters cannot be defined within methods or functions" );
7880
7881 static const ParserErrorCode GETTER_WITH_PARAMETERS = const ParserErrorCode.co n3('GETTER_WITH_PARAMETERS', 60, "Getter should be declared without a parameter list");
7882
7883 static const ParserErrorCode ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE = const Pars erErrorCode.con3('ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE', 61, "Illegal assignment to non-assignable expression");
7884
7885 static const ParserErrorCode IMPLEMENTS_BEFORE_EXTENDS = const ParserErrorCode .con3('IMPLEMENTS_BEFORE_EXTENDS', 62, "The extends clause must be before the im plements clause");
7886
7887 static const ParserErrorCode IMPLEMENTS_BEFORE_WITH = const ParserErrorCode.co n3('IMPLEMENTS_BEFORE_WITH', 63, "The with clause must be before the implements clause");
7888
7889 static const ParserErrorCode IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE = const Par serErrorCode.con3('IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE', 64, "Import directive s must preceed part directives");
7890
7891 static const ParserErrorCode INITIALIZED_VARIABLE_IN_FOR_EACH = const ParserEr rorCode.con3('INITIALIZED_VARIABLE_IN_FOR_EACH', 65, "The loop variable in a for -each loop cannot be initialized");
7892
7893 static const ParserErrorCode INVALID_AWAIT_IN_FOR = const ParserErrorCode.con4 ('INVALID_AWAIT_IN_FOR', 66, "The modifier 'await' is not allowed for a normal ' for' statement", "Remove the keyword or use a for-each statement.");
7894
7895 static const ParserErrorCode INVALID_CODE_POINT = const ParserErrorCode.con3(' INVALID_CODE_POINT', 67, "The escape sequence '{0}' is not a valid code point");
7896
7897 static const ParserErrorCode INVALID_COMMENT_REFERENCE = const ParserErrorCode .con3('INVALID_COMMENT_REFERENCE', 68, "Comment references should contain a poss ibly prefixed identifier and can start with 'new', but should not contain anythi ng else");
7898
7899 static const ParserErrorCode INVALID_HEX_ESCAPE = const ParserErrorCode.con3(' INVALID_HEX_ESCAPE', 69, "An escape sequence starting with '\\x' must be followe d by 2 hexidecimal digits");
7900
7901 static const ParserErrorCode INVALID_OPERATOR = const ParserErrorCode.con3('IN VALID_OPERATOR', 70, "The string '{0}' is not a valid operator");
7902
7903 static const ParserErrorCode INVALID_OPERATOR_FOR_SUPER = const ParserErrorCod e.con3('INVALID_OPERATOR_FOR_SUPER', 71, "The operator '{0}' cannot be used with 'super'");
7904
7905 static const ParserErrorCode INVALID_STAR_AFTER_ASYNC = const ParserErrorCode. con4('INVALID_STAR_AFTER_ASYNC', 72, "The modifier 'async*' is not allowed for a n expression function body", "Convert the body to a block.");
7906
7907 static const ParserErrorCode INVALID_SYNC = const ParserErrorCode.con4('INVALI D_SYNC', 73, "The modifier 'sync' is not allowed for an exrpression function bod y", "Convert the body to a block.");
7908
7909 static const ParserErrorCode INVALID_UNICODE_ESCAPE = const ParserErrorCode.co n3('INVALID_UNICODE_ESCAPE', 74, "An escape sequence starting with '\\u' must be followed by 4 hexidecimal digits or from 1 to 6 digits between '{' and '}'");
7910
7911 static const ParserErrorCode LIBRARY_DIRECTIVE_NOT_FIRST = const ParserErrorCo de.con3('LIBRARY_DIRECTIVE_NOT_FIRST', 75, "The library directive must appear be fore all other directives");
7912
7913 static const ParserErrorCode LOCAL_FUNCTION_DECLARATION_MODIFIER = const Parse rErrorCode.con3('LOCAL_FUNCTION_DECLARATION_MODIFIER', 76, "Local function decla rations cannot specify any modifier");
7914
7915 static const ParserErrorCode MISSING_ASSIGNABLE_SELECTOR = const ParserErrorCo de.con3('MISSING_ASSIGNABLE_SELECTOR', 77, "Missing selector such as \".<identif ier>\" or \"[0]\"");
7916
7917 static const ParserErrorCode MISSING_CATCH_OR_FINALLY = const ParserErrorCode. con3('MISSING_CATCH_OR_FINALLY', 78, "A try statement must have either a catch o r finally clause");
7918
7919 static const ParserErrorCode MISSING_CLASS_BODY = const ParserErrorCode.con3(' MISSING_CLASS_BODY', 79, "A class definition must have a body, even if it is emp ty");
7920
7921 static const ParserErrorCode MISSING_CLOSING_PARENTHESIS = const ParserErrorCo de.con3('MISSING_CLOSING_PARENTHESIS', 80, "The closing parenthesis is missing") ;
7922
7923 static const ParserErrorCode MISSING_CONST_FINAL_VAR_OR_TYPE = const ParserErr orCode.con3('MISSING_CONST_FINAL_VAR_OR_TYPE', 81, "Variables must be declared u sing the keywords 'const', 'final', 'var' or a type name");
7924
7925 static const ParserErrorCode MISSING_ENUM_BODY = const ParserErrorCode.con3('M ISSING_ENUM_BODY', 82, "An enum definition must have a body with at least one co nstant name");
7926
7927 static const ParserErrorCode MISSING_EXPRESSION_IN_THROW = const ParserErrorCo de.con3('MISSING_EXPRESSION_IN_THROW', 83, "Throw expressions must compute the o bject to be thrown");
7928
7929 static const ParserErrorCode MISSING_FUNCTION_BODY = const ParserErrorCode.con 3('MISSING_FUNCTION_BODY', 84, "A function body must be provided");
7930
7931 static const ParserErrorCode MISSING_FUNCTION_PARAMETERS = const ParserErrorCo de.con3('MISSING_FUNCTION_PARAMETERS', 85, "Functions must have an explicit list of parameters");
7932
7933 static const ParserErrorCode MISSING_GET = const ParserErrorCode.con3('MISSING _GET', 86, "Getters must have the keyword 'get' before the getter name");
7934
7935 static const ParserErrorCode MISSING_IDENTIFIER = const ParserErrorCode.con3(' MISSING_IDENTIFIER', 87, "Expected an identifier");
7936
7937 static const ParserErrorCode MISSING_KEYWORD_OPERATOR = const ParserErrorCode. con3('MISSING_KEYWORD_OPERATOR', 88, "Operator declarations must be preceeded by the keyword 'operator'");
7938
7939 static const ParserErrorCode MISSING_NAME_IN_LIBRARY_DIRECTIVE = const ParserE rrorCode.con3('MISSING_NAME_IN_LIBRARY_DIRECTIVE', 89, "Library directives must include a library name");
7940
7941 static const ParserErrorCode MISSING_NAME_IN_PART_OF_DIRECTIVE = const ParserE rrorCode.con3('MISSING_NAME_IN_PART_OF_DIRECTIVE', 90, "Library directives must include a library name");
7942
7943 static const ParserErrorCode MISSING_PREFIX_IN_DEFERRED_IMPORT = const ParserE rrorCode.con3('MISSING_PREFIX_IN_DEFERRED_IMPORT', 91, "Deferred imports must ha ve a prefix");
7944
7945 static const ParserErrorCode MISSING_STAR_AFTER_SYNC = const ParserErrorCode.c on4('MISSING_STAR_AFTER_SYNC', 92, "The modifier 'sync' must be followed by a st ar ('*')", "Remove the modifier or add a star.");
7946
7947 static const ParserErrorCode MISSING_STATEMENT = const ParserErrorCode.con3('M ISSING_STATEMENT', 93, "Expected a statement");
7948
7949 static const ParserErrorCode MISSING_TERMINATOR_FOR_PARAMETER_GROUP = const Pa rserErrorCode.con3('MISSING_TERMINATOR_FOR_PARAMETER_GROUP', 94, "There is no '{ 0}' to close the parameter group");
7950
7951 static const ParserErrorCode MISSING_TYPEDEF_PARAMETERS = const ParserErrorCod e.con3('MISSING_TYPEDEF_PARAMETERS', 95, "Type aliases for functions must have a n explicit list of parameters");
7952
7953 static const ParserErrorCode MISSING_VARIABLE_IN_FOR_EACH = const ParserErrorC ode.con3('MISSING_VARIABLE_IN_FOR_EACH', 96, "A loop variable must be declared i n a for-each loop before the 'in', but none were found");
7954
7955 static const ParserErrorCode MIXED_PARAMETER_GROUPS = const ParserErrorCode.co n3('MIXED_PARAMETER_GROUPS', 97, "Cannot have both positional and named paramete rs in a single parameter list");
7956
7957 static const ParserErrorCode MULTIPLE_EXTENDS_CLAUSES = const ParserErrorCode. con3('MULTIPLE_EXTENDS_CLAUSES', 98, "Each class definition can have at most one extends clause");
7958
7959 static const ParserErrorCode MULTIPLE_IMPLEMENTS_CLAUSES = const ParserErrorCo de.con3('MULTIPLE_IMPLEMENTS_CLAUSES', 99, "Each class definition can have at mo st one implements clause");
7960
7961 static const ParserErrorCode MULTIPLE_LIBRARY_DIRECTIVES = const ParserErrorCo de.con3('MULTIPLE_LIBRARY_DIRECTIVES', 100, "Only one library directive may be d eclared in a file");
7962
7963 static const ParserErrorCode MULTIPLE_NAMED_PARAMETER_GROUPS = const ParserErr orCode.con3('MULTIPLE_NAMED_PARAMETER_GROUPS', 101, "Cannot have multiple groups of named parameters in a single parameter list");
7964
7965 static const ParserErrorCode MULTIPLE_PART_OF_DIRECTIVES = const ParserErrorCo de.con3('MULTIPLE_PART_OF_DIRECTIVES', 102, "Only one part-of directive may be d eclared in a file");
7966
7967 static const ParserErrorCode MULTIPLE_POSITIONAL_PARAMETER_GROUPS = const Pars erErrorCode.con3('MULTIPLE_POSITIONAL_PARAMETER_GROUPS', 103, "Cannot have multi ple groups of positional parameters in a single parameter list");
7968
7969 static const ParserErrorCode MULTIPLE_VARIABLES_IN_FOR_EACH = const ParserErro rCode.con3('MULTIPLE_VARIABLES_IN_FOR_EACH', 104, "A single loop variable must b e declared in a for-each loop before the 'in', but {0} were found");
7970
7971 static const ParserErrorCode MULTIPLE_WITH_CLAUSES = const ParserErrorCode.con 3('MULTIPLE_WITH_CLAUSES', 105, "Each class definition can have at most one with clause");
7972
7973 static const ParserErrorCode NAMED_FUNCTION_EXPRESSION = const ParserErrorCode .con3('NAMED_FUNCTION_EXPRESSION', 106, "Function expressions cannot be named");
7974
7975 static const ParserErrorCode NAMED_PARAMETER_OUTSIDE_GROUP = const ParserError Code.con3('NAMED_PARAMETER_OUTSIDE_GROUP', 107, "Named parameters must be enclos ed in curly braces ('{' and '}')");
7976
7977 static const ParserErrorCode NATIVE_CLAUSE_IN_NON_SDK_CODE = const ParserError Code.con3('NATIVE_CLAUSE_IN_NON_SDK_CODE', 108, "Native clause can only be used in the SDK and code that is loaded through native extensions");
7978
7979 static const ParserErrorCode NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE = const Pars erErrorCode.con3('NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE', 109, "Native functions can only be declared in the SDK and code that is loaded through native extension s");
7980
7981 static const ParserErrorCode NON_CONSTRUCTOR_FACTORY = const ParserErrorCode.c on3('NON_CONSTRUCTOR_FACTORY', 110, "Only constructors can be declared to be a ' factory'");
7982
7983 static const ParserErrorCode NON_IDENTIFIER_LIBRARY_NAME = const ParserErrorCo de.con3('NON_IDENTIFIER_LIBRARY_NAME', 111, "The name of a library must be an id entifier");
7984
7985 static const ParserErrorCode NON_PART_OF_DIRECTIVE_IN_PART = const ParserError Code.con3('NON_PART_OF_DIRECTIVE_IN_PART', 112, "The part-of directive must be t he only directive in a part");
7986
7987 static const ParserErrorCode NON_USER_DEFINABLE_OPERATOR = const ParserErrorCo de.con3('NON_USER_DEFINABLE_OPERATOR', 113, "The operator '{0}' is not user defi nable");
7988
7989 static const ParserErrorCode NORMAL_BEFORE_OPTIONAL_PARAMETERS = const ParserE rrorCode.con3('NORMAL_BEFORE_OPTIONAL_PARAMETERS', 114, "Normal parameters must occur before optional parameters");
7990
7991 static const ParserErrorCode POSITIONAL_AFTER_NAMED_ARGUMENT = const ParserErr orCode.con3('POSITIONAL_AFTER_NAMED_ARGUMENT', 115, "Positional arguments must o ccur before named arguments");
7992
7993 static const ParserErrorCode POSITIONAL_PARAMETER_OUTSIDE_GROUP = const Parser ErrorCode.con3('POSITIONAL_PARAMETER_OUTSIDE_GROUP', 116, "Positional parameters must be enclosed in square brackets ('[' and ']')");
7994
7995 static const ParserErrorCode REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR = const Pa rserErrorCode.con3('REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR', 117, "Only factory constructor can specify '=' redirection.");
7996
7997 static const ParserErrorCode SETTER_IN_FUNCTION = const ParserErrorCode.con3(' SETTER_IN_FUNCTION', 118, "Setters cannot be defined within methods or functions ");
7998
7999 static const ParserErrorCode STATIC_AFTER_CONST = const ParserErrorCode.con3(' STATIC_AFTER_CONST', 119, "The modifier 'static' should be before the modifier ' const'");
8000
8001 static const ParserErrorCode STATIC_AFTER_FINAL = const ParserErrorCode.con3(' STATIC_AFTER_FINAL', 120, "The modifier 'static' should be before the modifier ' final'");
8002
8003 static const ParserErrorCode STATIC_AFTER_VAR = const ParserErrorCode.con3('ST ATIC_AFTER_VAR', 121, "The modifier 'static' should be before the modifier 'var' ");
8004
8005 static const ParserErrorCode STATIC_CONSTRUCTOR = const ParserErrorCode.con3(' STATIC_CONSTRUCTOR', 122, "Constructors cannot be static");
8006
8007 static const ParserErrorCode STATIC_GETTER_WITHOUT_BODY = const ParserErrorCod e.con3('STATIC_GETTER_WITHOUT_BODY', 123, "A 'static' getter must have a body");
8008
8009 static const ParserErrorCode STATIC_OPERATOR = const ParserErrorCode.con3('STA TIC_OPERATOR', 124, "Operators cannot be static");
8010
8011 static const ParserErrorCode STATIC_SETTER_WITHOUT_BODY = const ParserErrorCod e.con3('STATIC_SETTER_WITHOUT_BODY', 125, "A 'static' setter must have a body");
8012
8013 static const ParserErrorCode STATIC_TOP_LEVEL_DECLARATION = const ParserErrorC ode.con3('STATIC_TOP_LEVEL_DECLARATION', 126, "Top-level declarations cannot be declared to be 'static'");
8014
8015 static const ParserErrorCode SWITCH_HAS_CASE_AFTER_DEFAULT_CASE = const Parser ErrorCode.con3('SWITCH_HAS_CASE_AFTER_DEFAULT_CASE', 127, "The 'default' case sh ould be the last case in a switch statement");
8016
8017 static const ParserErrorCode SWITCH_HAS_MULTIPLE_DEFAULT_CASES = const ParserE rrorCode.con3('SWITCH_HAS_MULTIPLE_DEFAULT_CASES', 128, "The 'default' case can only be declared once");
8018
8019 static const ParserErrorCode TOP_LEVEL_OPERATOR = const ParserErrorCode.con3(' TOP_LEVEL_OPERATOR', 129, "Operators must be declared within a class");
8020
8021 static const ParserErrorCode UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP = const ParserErrorCode.con3('UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP', 130, "There i s no '{0}' to open a parameter group");
8022
8023 static const ParserErrorCode UNEXPECTED_TOKEN = const ParserErrorCode.con3('UN EXPECTED_TOKEN', 131, "Unexpected token '{0}'");
8024
8025 static const ParserErrorCode WITH_BEFORE_EXTENDS = const ParserErrorCode.con3( 'WITH_BEFORE_EXTENDS', 132, "The extends clause must be before the with clause") ;
8026
8027 static const ParserErrorCode WITH_WITHOUT_EXTENDS = const ParserErrorCode.con3 ('WITH_WITHOUT_EXTENDS', 133, "The with clause cannot be used without an extends clause");
8028
8029 static const ParserErrorCode WRONG_SEPARATOR_FOR_NAMED_PARAMETER = const Parse rErrorCode.con3('WRONG_SEPARATOR_FOR_NAMED_PARAMETER', 134, "The default value o f a named parameter should be preceeded by ':'");
8030
8031 static const ParserErrorCode WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER = const ParserErrorCode.con3('WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER', 135, "The defau lt value of a positional parameter should be preceeded by '='");
8032
8033 static const ParserErrorCode WRONG_TERMINATOR_FOR_PARAMETER_GROUP = const Pars erErrorCode.con3('WRONG_TERMINATOR_FOR_PARAMETER_GROUP', 136, "Expected '{0}' to close parameter group");
8034
8035 static const ParserErrorCode VAR_AND_TYPE = const ParserErrorCode.con3('VAR_AN D_TYPE', 137, "Variables cannot be declared using both 'var' and a type name; re move the 'var'");
8036
8037 static const ParserErrorCode VAR_AS_TYPE_NAME = const ParserErrorCode.con3('VA R_AS_TYPE_NAME', 138, "The keyword 'var' cannot be used as a type name");
8038
8039 static const ParserErrorCode VAR_CLASS = const ParserErrorCode.con3('VAR_CLASS ', 139, "Classes cannot be declared to be 'var'");
8040
8041 static const ParserErrorCode VAR_ENUM = const ParserErrorCode.con3('VAR_ENUM', 140, "Enums cannot be declared to be 'var'");
8042
8043 static const ParserErrorCode VAR_RETURN_TYPE = const ParserErrorCode.con3('VAR _RETURN_TYPE', 141, "The return type cannot be 'var'");
8044
8045 static const ParserErrorCode VAR_TYPEDEF = const ParserErrorCode.con3('VAR_TYP EDEF', 142, "Type aliases cannot be declared to be 'var'");
8046
8047 static const ParserErrorCode VOID_PARAMETER = const ParserErrorCode.con3('VOID _PARAMETER', 143, "Parameters cannot have a type of 'void'");
8048
8049 static const ParserErrorCode VOID_VARIABLE = const ParserErrorCode.con3('VOID_ VARIABLE', 144, "Variables cannot have a type of 'void'");
8050
8051 static const List<ParserErrorCode> values = const [
8052 ABSTRACT_CLASS_MEMBER,
8053 ABSTRACT_ENUM,
8054 ABSTRACT_STATIC_METHOD,
8055 ABSTRACT_TOP_LEVEL_FUNCTION,
8056 ABSTRACT_TOP_LEVEL_VARIABLE,
8057 ABSTRACT_TYPEDEF,
8058 ASSERT_DOES_NOT_TAKE_ASSIGNMENT,
8059 ASSERT_DOES_NOT_TAKE_CASCADE,
8060 ASSERT_DOES_NOT_TAKE_THROW,
8061 ASSERT_DOES_NOT_TAKE_RETHROW,
8062 BREAK_OUTSIDE_OF_LOOP,
8063 CONST_AND_FINAL,
8064 CONST_AND_VAR,
8065 CONST_CLASS,
8066 CONST_CONSTRUCTOR_WITH_BODY,
8067 CONST_ENUM,
8068 CONST_FACTORY,
8069 CONST_METHOD,
8070 CONST_TYPEDEF,
8071 CONSTRUCTOR_WITH_RETURN_TYPE,
8072 CONTINUE_OUTSIDE_OF_LOOP,
8073 CONTINUE_WITHOUT_LABEL_IN_CASE,
8074 DEFERRED_IMPORTS_NOT_SUPPORTED,
8075 DEPRECATED_CLASS_TYPE_ALIAS,
8076 DIRECTIVE_AFTER_DECLARATION,
8077 DUPLICATE_LABEL_IN_SWITCH_STATEMENT,
8078 DUPLICATED_MODIFIER,
8079 EMPTY_ENUM_BODY,
8080 EQUALITY_CANNOT_BE_EQUALITY_OPERAND,
8081 EXPECTED_CASE_OR_DEFAULT,
8082 EXPECTED_CLASS_MEMBER,
8083 EXPECTED_EXECUTABLE,
8084 EXPECTED_LIST_OR_MAP_LITERAL,
8085 EXPECTED_STRING_LITERAL,
8086 EXPECTED_TOKEN,
8087 EXPECTED_TYPE_NAME,
8088 EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE,
8089 EXTERNAL_AFTER_CONST,
8090 EXTERNAL_AFTER_FACTORY,
8091 EXTERNAL_AFTER_STATIC,
8092 EXTERNAL_CLASS,
8093 EXTERNAL_CONSTRUCTOR_WITH_BODY,
8094 EXTERNAL_ENUM,
8095 EXTERNAL_FIELD,
8096 EXTERNAL_GETTER_WITH_BODY,
8097 EXTERNAL_METHOD_WITH_BODY,
8098 EXTERNAL_OPERATOR_WITH_BODY,
8099 EXTERNAL_SETTER_WITH_BODY,
8100 EXTERNAL_TYPEDEF,
8101 FACTORY_TOP_LEVEL_DECLARATION,
8102 FACTORY_WITHOUT_BODY,
8103 FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR,
8104 FINAL_AND_VAR,
8105 FINAL_CLASS,
8106 FINAL_CONSTRUCTOR,
8107 FINAL_ENUM,
8108 FINAL_METHOD,
8109 FINAL_TYPEDEF,
8110 FUNCTION_TYPED_PARAMETER_VAR,
8111 GETTER_IN_FUNCTION,
8112 GETTER_WITH_PARAMETERS,
8113 ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE,
8114 IMPLEMENTS_BEFORE_EXTENDS,
8115 IMPLEMENTS_BEFORE_WITH,
8116 IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE,
8117 INITIALIZED_VARIABLE_IN_FOR_EACH,
8118 INVALID_AWAIT_IN_FOR,
8119 INVALID_CODE_POINT,
8120 INVALID_COMMENT_REFERENCE,
8121 INVALID_HEX_ESCAPE,
8122 INVALID_OPERATOR,
8123 INVALID_OPERATOR_FOR_SUPER,
8124 INVALID_STAR_AFTER_ASYNC,
8125 INVALID_SYNC,
8126 INVALID_UNICODE_ESCAPE,
8127 LIBRARY_DIRECTIVE_NOT_FIRST,
8128 LOCAL_FUNCTION_DECLARATION_MODIFIER,
8129 MISSING_ASSIGNABLE_SELECTOR,
8130 MISSING_CATCH_OR_FINALLY,
8131 MISSING_CLASS_BODY,
8132 MISSING_CLOSING_PARENTHESIS,
8133 MISSING_CONST_FINAL_VAR_OR_TYPE,
8134 MISSING_ENUM_BODY,
8135 MISSING_EXPRESSION_IN_THROW,
8136 MISSING_FUNCTION_BODY,
8137 MISSING_FUNCTION_PARAMETERS,
8138 MISSING_GET,
8139 MISSING_IDENTIFIER,
8140 MISSING_KEYWORD_OPERATOR,
8141 MISSING_NAME_IN_LIBRARY_DIRECTIVE,
8142 MISSING_NAME_IN_PART_OF_DIRECTIVE,
8143 MISSING_PREFIX_IN_DEFERRED_IMPORT,
8144 MISSING_STAR_AFTER_SYNC,
8145 MISSING_STATEMENT,
8146 MISSING_TERMINATOR_FOR_PARAMETER_GROUP,
8147 MISSING_TYPEDEF_PARAMETERS,
8148 MISSING_VARIABLE_IN_FOR_EACH,
8149 MIXED_PARAMETER_GROUPS,
8150 MULTIPLE_EXTENDS_CLAUSES,
8151 MULTIPLE_IMPLEMENTS_CLAUSES,
8152 MULTIPLE_LIBRARY_DIRECTIVES,
8153 MULTIPLE_NAMED_PARAMETER_GROUPS,
8154 MULTIPLE_PART_OF_DIRECTIVES,
8155 MULTIPLE_POSITIONAL_PARAMETER_GROUPS,
8156 MULTIPLE_VARIABLES_IN_FOR_EACH,
8157 MULTIPLE_WITH_CLAUSES,
8158 NAMED_FUNCTION_EXPRESSION,
8159 NAMED_PARAMETER_OUTSIDE_GROUP,
8160 NATIVE_CLAUSE_IN_NON_SDK_CODE,
8161 NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE,
8162 NON_CONSTRUCTOR_FACTORY,
8163 NON_IDENTIFIER_LIBRARY_NAME,
8164 NON_PART_OF_DIRECTIVE_IN_PART,
8165 NON_USER_DEFINABLE_OPERATOR,
8166 NORMAL_BEFORE_OPTIONAL_PARAMETERS,
8167 POSITIONAL_AFTER_NAMED_ARGUMENT,
8168 POSITIONAL_PARAMETER_OUTSIDE_GROUP,
8169 REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR,
8170 SETTER_IN_FUNCTION,
8171 STATIC_AFTER_CONST,
8172 STATIC_AFTER_FINAL,
8173 STATIC_AFTER_VAR,
8174 STATIC_CONSTRUCTOR,
8175 STATIC_GETTER_WITHOUT_BODY,
8176 STATIC_OPERATOR,
8177 STATIC_SETTER_WITHOUT_BODY,
8178 STATIC_TOP_LEVEL_DECLARATION,
8179 SWITCH_HAS_CASE_AFTER_DEFAULT_CASE,
8180 SWITCH_HAS_MULTIPLE_DEFAULT_CASES,
8181 TOP_LEVEL_OPERATOR,
8182 UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP,
8183 UNEXPECTED_TOKEN,
8184 WITH_BEFORE_EXTENDS,
8185 WITH_WITHOUT_EXTENDS,
8186 WRONG_SEPARATOR_FOR_NAMED_PARAMETER,
8187 WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER,
8188 WRONG_TERMINATOR_FOR_PARAMETER_GROUP,
8189 VAR_AND_TYPE,
8190 VAR_AS_TYPE_NAME,
8191 VAR_CLASS,
8192 VAR_ENUM,
8193 VAR_RETURN_TYPE,
8194 VAR_TYPEDEF,
8195 VOID_PARAMETER,
8196 VOID_VARIABLE];
8197
8198 /**
8199 * The severity of this error.
8200 */
8201 final ErrorSeverity errorSeverity;
8202
8203 /**
8204 * The template used to create the message to be displayed for this error.
8205 */
8206 final String message;
8207
8208 /**
8209 * The template used to create the correction to be displayed for this error, or `null` if
8210 * there is no correction information for this error.
8211 */
8212 final String correction;
8213
8214 /**
8215 * Initialize a newly created error code to have the given severity and messag e.
8216 *
8217 * @param errorSeverity the severity of the error
8218 * @param message the message template used to create the message to be displa yed for the error
8219 */
8220 const ParserErrorCode.con1(String name, int ordinal, ErrorSeverity errorSeveri ty, String message) : this.con2(name, ordinal, errorSeverity, message, null);
8221
8222 /**
8223 * Initialize a newly created error code to have the given severity, message a nd correction.
8224 *
8225 * @param errorSeverity the severity of the error
8226 * @param message the template used to create the message to be displayed for the error
8227 * @param correction the template used to create the correction to be displaye d for the error
8228 */
8229 const ParserErrorCode.con2(String name, int ordinal, this.errorSeverity, this. message, this.correction) : super(name, ordinal);
8230
8231 /**
8232 * Initialize a newly created error code to have the given message and a sever ity of ERROR.
8233 *
8234 * @param message the message template used to create the message to be displa yed for the error
8235 */
8236 const ParserErrorCode.con3(String name, int ordinal, String message) : this.co n2(name, ordinal, ErrorSeverity.ERROR, message, null);
8237
8238 /**
8239 * Initialize a newly created error code to have the given message and a sever ity of ERROR.
8240 *
8241 * @param message the message template used to create the message to be displa yed for the error
8242 * @param correction the template used to create the correction to be displaye d for the error
8243 */
8244 const ParserErrorCode.con4(String name, int ordinal, String message, String co rrection) : this.con2(name, ordinal, ErrorSeverity.ERROR, message, correction);
8245
8246 @override
8247 ErrorType get type => ErrorType.SYNTACTIC_ERROR;
8248
8249 @override
8250 String get uniqueName => "${runtimeType.toString()}.${name}";
8251 }
8252
8253 /**
8254 * Instances of the class `SyntheticKeywordToken` implement a synthetic keyword token.
8255 */
8256 class Parser_SyntheticKeywordToken extends KeywordToken {
8257 /**
8258 * Initialize a newly created token to represent the given keyword.
8259 *
8260 * @param keyword the keyword being represented by this token
8261 * @param offset the offset from the beginning of the file to the first charac ter in the token
8262 */
8263 Parser_SyntheticKeywordToken(Keyword keyword, int offset) : super(keyword, off set);
8264
8265 @override
8266 Token copy() => new Parser_SyntheticKeywordToken(keyword, offset);
8267
8268 @override
8269 int get length => 0;
8270 }
8271
8272 /**
8273 * Instances of the class `ResolutionCopier` copies resolution information from one AST
8274 * structure to another as long as the structures of the corresponding children of a pair of nodes
8275 * are the same.
8276 */
8277 class ResolutionCopier implements AstVisitor<bool> {
8278 /**
8279 * Copy resolution data from one node to another.
8280 *
8281 * @param fromNode the node from which resolution information will be copied
8282 * @param toNode the node to which resolution information will be copied
8283 */
8284 static void copyResolutionData(AstNode fromNode, AstNode toNode) {
8285 ResolutionCopier copier = new ResolutionCopier();
8286 copier._isEqualNodes(fromNode, toNode);
8287 }
8288
8289 /**
8290 * The AST node with which the node being visited is to be compared. This is o nly valid at the
8291 * beginning of each visit method (until [isEqualNodes] is invoked).
8292 */
8293 AstNode _toNode;
8294
8295 @override
8296 bool visitAdjacentStrings(AdjacentStrings node) {
8297 AdjacentStrings toNode = this._toNode as AdjacentStrings;
8298 return _isEqualNodeLists(node.strings, toNode.strings);
8299 }
8300
8301 @override
8302 bool visitAnnotation(Annotation node) {
8303 Annotation toNode = this._toNode as Annotation;
8304 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualToke ns(node.atSign, toNode.atSign), _isEqualNodes(node.name, toNode.name)), _isEqual Tokens(node.period, toNode.period)), _isEqualNodes(node.constructorName, toNode. constructorName)), _isEqualNodes(node.arguments, toNode.arguments))) {
8305 toNode.element = node.element;
8306 return true;
8307 }
8308 return false;
8309 }
8310
8311 @override
8312 bool visitArgumentList(ArgumentList node) {
8313 ArgumentList toNode = this._toNode as ArgumentList;
8314 return javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.leftParenthesis, to Node.leftParenthesis), _isEqualNodeLists(node.arguments, toNode.arguments)), _is EqualTokens(node.rightParenthesis, toNode.rightParenthesis));
8315 }
8316
8317 @override
8318 bool visitAsExpression(AsExpression node) {
8319 AsExpression toNode = this._toNode as AsExpression;
8320 if (javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.expression, toNode.expr ession), _isEqualTokens(node.asOperator, toNode.asOperator)), _isEqualNodes(node .type, toNode.type))) {
8321 toNode.propagatedType = node.propagatedType;
8322 toNode.staticType = node.staticType;
8323 return true;
8324 }
8325 return false;
8326 }
8327
8328 @override
8329 bool visitAssertStatement(AssertStatement node) {
8330 AssertStatement toNode = this._toNode as AssertStatement;
8331 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualT okens(node.keyword, toNode.keyword), _isEqualTokens(node.leftParenthesis, toNode .leftParenthesis)), _isEqualNodes(node.condition, toNode.condition)), _isEqualTo kens(node.rightParenthesis, toNode.rightParenthesis)), _isEqualTokens(node.semic olon, toNode.semicolon));
8332 }
8333
8334 @override
8335 bool visitAssignmentExpression(AssignmentExpression node) {
8336 AssignmentExpression toNode = this._toNode as AssignmentExpression;
8337 if (javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.leftHandSide, toNode.le ftHandSide), _isEqualTokens(node.operator, toNode.operator)), _isEqualNodes(node .rightHandSide, toNode.rightHandSide))) {
8338 toNode.propagatedElement = node.propagatedElement;
8339 toNode.propagatedType = node.propagatedType;
8340 toNode.staticElement = node.staticElement;
8341 toNode.staticType = node.staticType;
8342 return true;
8343 }
8344 return false;
8345 }
8346
8347 @override
8348 bool visitAwaitExpression(AwaitExpression node) {
8349 AwaitExpression toNode = this._toNode as AwaitExpression;
8350 return javaBooleanAnd(_isEqualTokens(node.awaitKeyword, toNode.awaitKeyword) , _isEqualNodes(node.expression, toNode.expression));
8351 }
8352
8353 @override
8354 bool visitBinaryExpression(BinaryExpression node) {
8355 BinaryExpression toNode = this._toNode as BinaryExpression;
8356 if (javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.leftOperand, toNode.lef tOperand), _isEqualTokens(node.operator, toNode.operator)), _isEqualNodes(node.r ightOperand, toNode.rightOperand))) {
8357 toNode.propagatedElement = node.propagatedElement;
8358 toNode.propagatedType = node.propagatedType;
8359 toNode.staticElement = node.staticElement;
8360 toNode.staticType = node.staticType;
8361 return true;
8362 }
8363 return false;
8364 }
8365
8366 @override
8367 bool visitBlock(Block node) {
8368 Block toNode = this._toNode as Block;
8369 return javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.leftBracket, toNode .leftBracket), _isEqualNodeLists(node.statements, toNode.statements)), _isEqualT okens(node.rightBracket, toNode.rightBracket));
8370 }
8371
8372 @override
8373 bool visitBlockFunctionBody(BlockFunctionBody node) {
8374 BlockFunctionBody toNode = this._toNode as BlockFunctionBody;
8375 return _isEqualNodes(node.block, toNode.block);
8376 }
8377
8378 @override
8379 bool visitBooleanLiteral(BooleanLiteral node) {
8380 BooleanLiteral toNode = this._toNode as BooleanLiteral;
8381 if (javaBooleanAnd(_isEqualTokens(node.literal, toNode.literal), node.value == toNode.value)) {
8382 toNode.propagatedType = node.propagatedType;
8383 toNode.staticType = node.staticType;
8384 return true;
8385 }
8386 return false;
8387 }
8388
8389 @override
8390 bool visitBreakStatement(BreakStatement node) {
8391 BreakStatement toNode = this._toNode as BreakStatement;
8392 return javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.keyword, toNode.key word), _isEqualNodes(node.label, toNode.label)), _isEqualTokens(node.semicolon, toNode.semicolon));
8393 }
8394
8395 @override
8396 bool visitCascadeExpression(CascadeExpression node) {
8397 CascadeExpression toNode = this._toNode as CascadeExpression;
8398 if (javaBooleanAnd(_isEqualNodes(node.target, toNode.target), _isEqualNodeLi sts(node.cascadeSections, toNode.cascadeSections))) {
8399 toNode.propagatedType = node.propagatedType;
8400 toNode.staticType = node.staticType;
8401 return true;
8402 }
8403 return false;
8404 }
8405
8406 @override
8407 bool visitCatchClause(CatchClause node) {
8408 CatchClause toNode = this._toNode as CatchClause;
8409 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole anAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.onKeyword , toNode.onKeyword), _isEqualNodes(node.exceptionType, toNode.exceptionType)), _ isEqualTokens(node.catchKeyword, toNode.catchKeyword)), _isEqualTokens(node.left Parenthesis, toNode.leftParenthesis)), _isEqualNodes(node.exceptionParameter, to Node.exceptionParameter)), _isEqualTokens(node.comma, toNode.comma)), _isEqualNo des(node.stackTraceParameter, toNode.stackTraceParameter)), _isEqualTokens(node. rightParenthesis, toNode.rightParenthesis)), _isEqualNodes(node.body, toNode.bod y));
8410 }
8411
8412 @override
8413 bool visitClassDeclaration(ClassDeclaration node) {
8414 ClassDeclaration toNode = this._toNode as ClassDeclaration;
8415 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole anAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd (javaBooleanAnd(_isEqualNodes(node.documentationComment, toNode.documentationCom ment), _isEqualNodeLists(node.metadata, toNode.metadata)), _isEqualTokens(node.a bstractKeyword, toNode.abstractKeyword)), _isEqualTokens(node.classKeyword, toNo de.classKeyword)), _isEqualNodes(node.name, toNode.name)), _isEqualNodes(node.ty peParameters, toNode.typeParameters)), _isEqualNodes(node.extendsClause, toNode. extendsClause)), _isEqualNodes(node.withClause, toNode.withClause)), _isEqualNod es(node.implementsClause, toNode.implementsClause)), _isEqualTokens(node.leftBra cket, toNode.leftBracket)), _isEqualNodeLists(node.members, toNode.members)), _i sEqualTokens(node.rightBracket, toNode.rightBracket));
8416 }
8417
8418 @override
8419 bool visitClassTypeAlias(ClassTypeAlias node) {
8420 ClassTypeAlias toNode = this._toNode as ClassTypeAlias;
8421 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole anAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd (_isEqualNodes(node.documentationComment, toNode.documentationComment), _isEqual NodeLists(node.metadata, toNode.metadata)), _isEqualTokens(node.keyword, toNode. keyword)), _isEqualNodes(node.name, toNode.name)), _isEqualNodes(node.typeParame ters, toNode.typeParameters)), _isEqualTokens(node.equals, toNode.equals)), _isE qualTokens(node.abstractKeyword, toNode.abstractKeyword)), _isEqualNodes(node.su perclass, toNode.superclass)), _isEqualNodes(node.withClause, toNode.withClause) ), _isEqualNodes(node.implementsClause, toNode.implementsClause)), _isEqualToken s(node.semicolon, toNode.semicolon));
8422 }
8423
8424 @override
8425 bool visitComment(Comment node) {
8426 Comment toNode = this._toNode as Comment;
8427 return _isEqualNodeLists(node.references, toNode.references);
8428 }
8429
8430 @override
8431 bool visitCommentReference(CommentReference node) {
8432 CommentReference toNode = this._toNode as CommentReference;
8433 return javaBooleanAnd(_isEqualTokens(node.newKeyword, toNode.newKeyword), _i sEqualNodes(node.identifier, toNode.identifier));
8434 }
8435
8436 @override
8437 bool visitCompilationUnit(CompilationUnit node) {
8438 CompilationUnit toNode = this._toNode as CompilationUnit;
8439 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualToke ns(node.beginToken, toNode.beginToken), _isEqualNodes(node.scriptTag, toNode.scr iptTag)), _isEqualNodeLists(node.directives, toNode.directives)), _isEqualNodeLi sts(node.declarations, toNode.declarations)), _isEqualTokens(node.endToken, toNo de.endToken))) {
8440 toNode.element = node.element;
8441 return true;
8442 }
8443 return false;
8444 }
8445
8446 @override
8447 bool visitConditionalExpression(ConditionalExpression node) {
8448 ConditionalExpression toNode = this._toNode as ConditionalExpression;
8449 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualNode s(node.condition, toNode.condition), _isEqualTokens(node.question, toNode.questi on)), _isEqualNodes(node.thenExpression, toNode.thenExpression)), _isEqualTokens (node.colon, toNode.colon)), _isEqualNodes(node.elseExpression, toNode.elseExpre ssion))) {
8450 toNode.propagatedType = node.propagatedType;
8451 toNode.staticType = node.staticType;
8452 return true;
8453 }
8454 return false;
8455 }
8456
8457 @override
8458 bool visitConstructorDeclaration(ConstructorDeclaration node) {
8459 ConstructorDeclaration toNode = this._toNode as ConstructorDeclaration;
8460 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanA nd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(ja vaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.documentationComment, toNode.docu mentationComment), _isEqualNodeLists(node.metadata, toNode.metadata)), _isEqualT okens(node.externalKeyword, toNode.externalKeyword)), _isEqualTokens(node.constK eyword, toNode.constKeyword)), _isEqualTokens(node.factoryKeyword, toNode.factor yKeyword)), _isEqualNodes(node.returnType, toNode.returnType)), _isEqualTokens(n ode.period, toNode.period)), _isEqualNodes(node.name, toNode.name)), _isEqualNod es(node.parameters, toNode.parameters)), _isEqualTokens(node.separator, toNode.s eparator)), _isEqualNodeLists(node.initializers, toNode.initializers)), _isEqual Nodes(node.redirectedConstructor, toNode.redirectedConstructor)), _isEqualNodes( node.body, toNode.body))) {
8461 toNode.element = node.element;
8462 return true;
8463 }
8464 return false;
8465 }
8466
8467 @override
8468 bool visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
8469 ConstructorFieldInitializer toNode = this._toNode as ConstructorFieldInitial izer;
8470 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualT okens(node.keyword, toNode.keyword), _isEqualTokens(node.period, toNode.period)) , _isEqualNodes(node.fieldName, toNode.fieldName)), _isEqualTokens(node.equals, toNode.equals)), _isEqualNodes(node.expression, toNode.expression));
8471 }
8472
8473 @override
8474 bool visitConstructorName(ConstructorName node) {
8475 ConstructorName toNode = this._toNode as ConstructorName;
8476 if (javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.type, toNode.type), _is EqualTokens(node.period, toNode.period)), _isEqualNodes(node.name, toNode.name)) ) {
8477 toNode.staticElement = node.staticElement;
8478 return true;
8479 }
8480 return false;
8481 }
8482
8483 @override
8484 bool visitContinueStatement(ContinueStatement node) {
8485 ContinueStatement toNode = this._toNode as ContinueStatement;
8486 return javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.keyword, toNode.key word), _isEqualNodes(node.label, toNode.label)), _isEqualTokens(node.semicolon, toNode.semicolon));
8487 }
8488
8489 @override
8490 bool visitDeclaredIdentifier(DeclaredIdentifier node) {
8491 DeclaredIdentifier toNode = this._toNode as DeclaredIdentifier;
8492 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualN odes(node.documentationComment, toNode.documentationComment), _isEqualNodeLists( node.metadata, toNode.metadata)), _isEqualTokens(node.keyword, toNode.keyword)), _isEqualNodes(node.type, toNode.type)), _isEqualNodes(node.identifier, toNode.i dentifier));
8493 }
8494
8495 @override
8496 bool visitDefaultFormalParameter(DefaultFormalParameter node) {
8497 DefaultFormalParameter toNode = this._toNode as DefaultFormalParameter;
8498 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.param eter, toNode.parameter), node.kind == toNode.kind), _isEqualTokens(node.separato r, toNode.separator)), _isEqualNodes(node.defaultValue, toNode.defaultValue));
8499 }
8500
8501 @override
8502 bool visitDoStatement(DoStatement node) {
8503 DoStatement toNode = this._toNode as DoStatement;
8504 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole anAnd(javaBooleanAnd(_isEqualTokens(node.doKeyword, toNode.doKeyword), _isEqualN odes(node.body, toNode.body)), _isEqualTokens(node.whileKeyword, toNode.whileKey word)), _isEqualTokens(node.leftParenthesis, toNode.leftParenthesis)), _isEqualN odes(node.condition, toNode.condition)), _isEqualTokens(node.rightParenthesis, t oNode.rightParenthesis)), _isEqualTokens(node.semicolon, toNode.semicolon));
8505 }
8506
8507 @override
8508 bool visitDoubleLiteral(DoubleLiteral node) {
8509 DoubleLiteral toNode = this._toNode as DoubleLiteral;
8510 if (javaBooleanAnd(_isEqualTokens(node.literal, toNode.literal), node.value == toNode.value)) {
8511 toNode.propagatedType = node.propagatedType;
8512 toNode.staticType = node.staticType;
8513 return true;
8514 }
8515 return false;
8516 }
8517
8518 @override
8519 bool visitEmptyFunctionBody(EmptyFunctionBody node) {
8520 EmptyFunctionBody toNode = this._toNode as EmptyFunctionBody;
8521 return _isEqualTokens(node.semicolon, toNode.semicolon);
8522 }
8523
8524 @override
8525 bool visitEmptyStatement(EmptyStatement node) {
8526 EmptyStatement toNode = this._toNode as EmptyStatement;
8527 return _isEqualTokens(node.semicolon, toNode.semicolon);
8528 }
8529
8530 @override
8531 bool visitEnumConstantDeclaration(EnumConstantDeclaration node) {
8532 EnumConstantDeclaration toNode = this._toNode as EnumConstantDeclaration;
8533 return javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.documentationComment , toNode.documentationComment), _isEqualNodeLists(node.metadata, toNode.metadata )), _isEqualNodes(node.name, toNode.name));
8534 }
8535
8536 @override
8537 bool visitEnumDeclaration(EnumDeclaration node) {
8538 EnumDeclaration toNode = this._toNode as EnumDeclaration;
8539 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole anAnd(javaBooleanAnd(_isEqualNodes(node.documentationComment, toNode.documentati onComment), _isEqualNodeLists(node.metadata, toNode.metadata)), _isEqualTokens(n ode.keyword, toNode.keyword)), _isEqualNodes(node.name, toNode.name)), _isEqualT okens(node.leftBracket, toNode.leftBracket)), _isEqualNodeLists(node.constants, toNode.constants)), _isEqualTokens(node.rightBracket, toNode.rightBracket));
8540 }
8541
8542 @override
8543 bool visitExportDirective(ExportDirective node) {
8544 ExportDirective toNode = this._toNode as ExportDirective;
8545 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanA nd(_isEqualNodes(node.documentationComment, toNode.documentationComment), _isEqu alNodeLists(node.metadata, toNode.metadata)), _isEqualTokens(node.keyword, toNod e.keyword)), _isEqualNodes(node.uri, toNode.uri)), _isEqualNodeLists(node.combin ators, toNode.combinators)), _isEqualTokens(node.semicolon, toNode.semicolon))) {
8546 toNode.element = node.element;
8547 return true;
8548 }
8549 return false;
8550 }
8551
8552 @override
8553 bool visitExpressionFunctionBody(ExpressionFunctionBody node) {
8554 ExpressionFunctionBody toNode = this._toNode as ExpressionFunctionBody;
8555 return javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.functionDefinition, toNode.functionDefinition), _isEqualNodes(node.expression, toNode.expression)), _isEqualTokens(node.semicolon, toNode.semicolon));
8556 }
8557
8558 @override
8559 bool visitExpressionStatement(ExpressionStatement node) {
8560 ExpressionStatement toNode = this._toNode as ExpressionStatement;
8561 return javaBooleanAnd(_isEqualNodes(node.expression, toNode.expression), _is EqualTokens(node.semicolon, toNode.semicolon));
8562 }
8563
8564 @override
8565 bool visitExtendsClause(ExtendsClause node) {
8566 ExtendsClause toNode = this._toNode as ExtendsClause;
8567 return javaBooleanAnd(_isEqualTokens(node.keyword, toNode.keyword), _isEqual Nodes(node.superclass, toNode.superclass));
8568 }
8569
8570 @override
8571 bool visitFieldDeclaration(FieldDeclaration node) {
8572 FieldDeclaration toNode = this._toNode as FieldDeclaration;
8573 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualN odes(node.documentationComment, toNode.documentationComment), _isEqualNodeLists( node.metadata, toNode.metadata)), _isEqualTokens(node.staticKeyword, toNode.stat icKeyword)), _isEqualNodes(node.fields, toNode.fields)), _isEqualTokens(node.sem icolon, toNode.semicolon));
8574 }
8575
8576 @override
8577 bool visitFieldFormalParameter(FieldFormalParameter node) {
8578 FieldFormalParameter toNode = this._toNode as FieldFormalParameter;
8579 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole anAnd(javaBooleanAnd(_isEqualNodes(node.documentationComment, toNode.documentati onComment), _isEqualNodeLists(node.metadata, toNode.metadata)), _isEqualTokens(n ode.keyword, toNode.keyword)), _isEqualNodes(node.type, toNode.type)), _isEqualT okens(node.thisToken, toNode.thisToken)), _isEqualTokens(node.period, toNode.per iod)), _isEqualNodes(node.identifier, toNode.identifier));
8580 }
8581
8582 @override
8583 bool visitForEachStatement(ForEachStatement node) {
8584 ForEachStatement toNode = this._toNode as ForEachStatement;
8585 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole anAnd(javaBooleanAnd(_isEqualTokens(node.forKeyword, toNode.forKeyword), _isEqua lTokens(node.leftParenthesis, toNode.leftParenthesis)), _isEqualNodes(node.loopV ariable, toNode.loopVariable)), _isEqualTokens(node.inKeyword, toNode.inKeyword) ), _isEqualNodes(node.iterator, toNode.iterator)), _isEqualTokens(node.rightPare nthesis, toNode.rightParenthesis)), _isEqualNodes(node.body, toNode.body));
8586 }
8587
8588 @override
8589 bool visitFormalParameterList(FormalParameterList node) {
8590 FormalParameterList toNode = this._toNode as FormalParameterList;
8591 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualT okens(node.leftParenthesis, toNode.leftParenthesis), _isEqualNodeLists(node.para meters, toNode.parameters)), _isEqualTokens(node.leftDelimiter, toNode.leftDelim iter)), _isEqualTokens(node.rightDelimiter, toNode.rightDelimiter)), _isEqualTok ens(node.rightParenthesis, toNode.rightParenthesis));
8592 }
8593
8594 @override
8595 bool visitForStatement(ForStatement node) {
8596 ForStatement toNode = this._toNode as ForStatement;
8597 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole anAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualTokens (node.forKeyword, toNode.forKeyword), _isEqualTokens(node.leftParenthesis, toNod e.leftParenthesis)), _isEqualNodes(node.variables, toNode.variables)), _isEqualN odes(node.initialization, toNode.initialization)), _isEqualTokens(node.leftSepar ator, toNode.leftSeparator)), _isEqualNodes(node.condition, toNode.condition)), _isEqualTokens(node.rightSeparator, toNode.rightSeparator)), _isEqualNodeLists(n ode.updaters, toNode.updaters)), _isEqualTokens(node.rightParenthesis, toNode.ri ghtParenthesis)), _isEqualNodes(node.body, toNode.body));
8598 }
8599
8600 @override
8601 bool visitFunctionDeclaration(FunctionDeclaration node) {
8602 FunctionDeclaration toNode = this._toNode as FunctionDeclaration;
8603 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole anAnd(javaBooleanAnd(_isEqualNodes(node.documentationComment, toNode.documentati onComment), _isEqualNodeLists(node.metadata, toNode.metadata)), _isEqualTokens(n ode.externalKeyword, toNode.externalKeyword)), _isEqualNodes(node.returnType, to Node.returnType)), _isEqualTokens(node.propertyKeyword, toNode.propertyKeyword)) , _isEqualNodes(node.name, toNode.name)), _isEqualNodes(node.functionExpression, toNode.functionExpression));
8604 }
8605
8606 @override
8607 bool visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
8608 FunctionDeclarationStatement toNode = this._toNode as FunctionDeclarationSta tement;
8609 return _isEqualNodes(node.functionDeclaration, toNode.functionDeclaration);
8610 }
8611
8612 @override
8613 bool visitFunctionExpression(FunctionExpression node) {
8614 FunctionExpression toNode = this._toNode as FunctionExpression;
8615 if (javaBooleanAnd(_isEqualNodes(node.parameters, toNode.parameters), _isEqu alNodes(node.body, toNode.body))) {
8616 toNode.element = node.element;
8617 toNode.propagatedType = node.propagatedType;
8618 toNode.staticType = node.staticType;
8619 return true;
8620 }
8621 return false;
8622 }
8623
8624 @override
8625 bool visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
8626 FunctionExpressionInvocation toNode = this._toNode as FunctionExpressionInvo cation;
8627 if (javaBooleanAnd(_isEqualNodes(node.function, toNode.function), _isEqualNo des(node.argumentList, toNode.argumentList))) {
8628 toNode.propagatedElement = node.propagatedElement;
8629 toNode.propagatedType = node.propagatedType;
8630 toNode.staticElement = node.staticElement;
8631 toNode.staticType = node.staticType;
8632 return true;
8633 }
8634 return false;
8635 }
8636
8637 @override
8638 bool visitFunctionTypeAlias(FunctionTypeAlias node) {
8639 FunctionTypeAlias toNode = this._toNode as FunctionTypeAlias;
8640 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole anAnd(javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.documentationComment, toN ode.documentationComment), _isEqualNodeLists(node.metadata, toNode.metadata)), _ isEqualTokens(node.keyword, toNode.keyword)), _isEqualNodes(node.returnType, toN ode.returnType)), _isEqualNodes(node.name, toNode.name)), _isEqualNodes(node.typ eParameters, toNode.typeParameters)), _isEqualNodes(node.parameters, toNode.para meters)), _isEqualTokens(node.semicolon, toNode.semicolon));
8641 }
8642
8643 @override
8644 bool visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
8645 FunctionTypedFormalParameter toNode = this._toNode as FunctionTypedFormalPar ameter;
8646 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualN odes(node.documentationComment, toNode.documentationComment), _isEqualNodeLists( node.metadata, toNode.metadata)), _isEqualNodes(node.returnType, toNode.returnTy pe)), _isEqualNodes(node.identifier, toNode.identifier)), _isEqualNodes(node.par ameters, toNode.parameters));
8647 }
8648
8649 @override
8650 bool visitHideCombinator(HideCombinator node) {
8651 HideCombinator toNode = this._toNode as HideCombinator;
8652 return javaBooleanAnd(_isEqualTokens(node.keyword, toNode.keyword), _isEqual NodeLists(node.hiddenNames, toNode.hiddenNames));
8653 }
8654
8655 @override
8656 bool visitIfStatement(IfStatement node) {
8657 IfStatement toNode = this._toNode as IfStatement;
8658 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole anAnd(javaBooleanAnd(_isEqualTokens(node.ifKeyword, toNode.ifKeyword), _isEqualT okens(node.leftParenthesis, toNode.leftParenthesis)), _isEqualNodes(node.conditi on, toNode.condition)), _isEqualTokens(node.rightParenthesis, toNode.rightParent hesis)), _isEqualNodes(node.thenStatement, toNode.thenStatement)), _isEqualToken s(node.elseKeyword, toNode.elseKeyword)), _isEqualNodes(node.elseStatement, toNo de.elseStatement));
8659 }
8660
8661 @override
8662 bool visitImplementsClause(ImplementsClause node) {
8663 ImplementsClause toNode = this._toNode as ImplementsClause;
8664 return javaBooleanAnd(_isEqualTokens(node.keyword, toNode.keyword), _isEqual NodeLists(node.interfaces, toNode.interfaces));
8665 }
8666
8667 @override
8668 bool visitImportDirective(ImportDirective node) {
8669 ImportDirective toNode = this._toNode as ImportDirective;
8670 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanA nd(javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.documentationComment, toNode .documentationComment), _isEqualNodeLists(node.metadata, toNode.metadata)), _isE qualTokens(node.keyword, toNode.keyword)), _isEqualNodes(node.uri, toNode.uri)), _isEqualTokens(node.asToken, toNode.asToken)), _isEqualNodes(node.prefix, toNod e.prefix)), _isEqualNodeLists(node.combinators, toNode.combinators)), _isEqualTo kens(node.semicolon, toNode.semicolon))) {
8671 toNode.element = node.element;
8672 return true;
8673 }
8674 return false;
8675 }
8676
8677 @override
8678 bool visitIndexExpression(IndexExpression node) {
8679 IndexExpression toNode = this._toNode as IndexExpression;
8680 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.target, toNode.target), _isEqualTokens(node.leftBracket, toNode.leftBracket)), _isEqualN odes(node.index, toNode.index)), _isEqualTokens(node.rightBracket, toNode.rightB racket))) {
8681 toNode.auxiliaryElements = node.auxiliaryElements;
8682 toNode.propagatedElement = node.propagatedElement;
8683 toNode.propagatedType = node.propagatedType;
8684 toNode.staticElement = node.staticElement;
8685 toNode.staticType = node.staticType;
8686 return true;
8687 }
8688 return false;
8689 }
8690
8691 @override
8692 bool visitInstanceCreationExpression(InstanceCreationExpression node) {
8693 InstanceCreationExpression toNode = this._toNode as InstanceCreationExpressi on;
8694 if (javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.keyword, toNode.keywor d), _isEqualNodes(node.constructorName, toNode.constructorName)), _isEqualNodes( node.argumentList, toNode.argumentList))) {
8695 toNode.propagatedType = node.propagatedType;
8696 toNode.staticElement = node.staticElement;
8697 toNode.staticType = node.staticType;
8698 return true;
8699 }
8700 return false;
8701 }
8702
8703 @override
8704 bool visitIntegerLiteral(IntegerLiteral node) {
8705 IntegerLiteral toNode = this._toNode as IntegerLiteral;
8706 if (javaBooleanAnd(_isEqualTokens(node.literal, toNode.literal), identical(n ode.value, toNode.value))) {
8707 toNode.propagatedType = node.propagatedType;
8708 toNode.staticType = node.staticType;
8709 return true;
8710 }
8711 return false;
8712 }
8713
8714 @override
8715 bool visitInterpolationExpression(InterpolationExpression node) {
8716 InterpolationExpression toNode = this._toNode as InterpolationExpression;
8717 return javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.leftBracket, toNode .leftBracket), _isEqualNodes(node.expression, toNode.expression)), _isEqualToken s(node.rightBracket, toNode.rightBracket));
8718 }
8719
8720 @override
8721 bool visitInterpolationString(InterpolationString node) {
8722 InterpolationString toNode = this._toNode as InterpolationString;
8723 return javaBooleanAnd(_isEqualTokens(node.contents, toNode.contents), node.v alue == toNode.value);
8724 }
8725
8726 @override
8727 bool visitIsExpression(IsExpression node) {
8728 IsExpression toNode = this._toNode as IsExpression;
8729 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.expressi on, toNode.expression), _isEqualTokens(node.isOperator, toNode.isOperator)), _is EqualTokens(node.notOperator, toNode.notOperator)), _isEqualNodes(node.type, toN ode.type))) {
8730 toNode.propagatedType = node.propagatedType;
8731 toNode.staticType = node.staticType;
8732 return true;
8733 }
8734 return false;
8735 }
8736
8737 @override
8738 bool visitLabel(Label node) {
8739 Label toNode = this._toNode as Label;
8740 return javaBooleanAnd(_isEqualNodes(node.label, toNode.label), _isEqualToken s(node.colon, toNode.colon));
8741 }
8742
8743 @override
8744 bool visitLabeledStatement(LabeledStatement node) {
8745 LabeledStatement toNode = this._toNode as LabeledStatement;
8746 return javaBooleanAnd(_isEqualNodeLists(node.labels, toNode.labels), _isEqua lNodes(node.statement, toNode.statement));
8747 }
8748
8749 @override
8750 bool visitLibraryDirective(LibraryDirective node) {
8751 LibraryDirective toNode = this._toNode as LibraryDirective;
8752 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualN odes(node.documentationComment, toNode.documentationComment), _isEqualNodeLists( node.metadata, toNode.metadata)), _isEqualTokens(node.libraryToken, toNode.libra ryToken)), _isEqualNodes(node.name, toNode.name)), _isEqualTokens(node.semicolon , toNode.semicolon));
8753 }
8754
8755 @override
8756 bool visitLibraryIdentifier(LibraryIdentifier node) {
8757 LibraryIdentifier toNode = this._toNode as LibraryIdentifier;
8758 if (_isEqualNodeLists(node.components, toNode.components)) {
8759 toNode.propagatedType = node.propagatedType;
8760 toNode.staticType = node.staticType;
8761 return true;
8762 }
8763 return false;
8764 }
8765
8766 @override
8767 bool visitListLiteral(ListLiteral node) {
8768 ListLiteral toNode = this._toNode as ListLiteral;
8769 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualToke ns(node.constKeyword, toNode.constKeyword), _isEqualNodes(node.typeArguments, to Node.typeArguments)), _isEqualTokens(node.leftBracket, toNode.leftBracket)), _is EqualNodeLists(node.elements, toNode.elements)), _isEqualTokens(node.rightBracke t, toNode.rightBracket))) {
8770 toNode.propagatedType = node.propagatedType;
8771 toNode.staticType = node.staticType;
8772 return true;
8773 }
8774 return false;
8775 }
8776
8777 @override
8778 bool visitMapLiteral(MapLiteral node) {
8779 MapLiteral toNode = this._toNode as MapLiteral;
8780 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualToke ns(node.constKeyword, toNode.constKeyword), _isEqualNodes(node.typeArguments, to Node.typeArguments)), _isEqualTokens(node.leftBracket, toNode.leftBracket)), _is EqualNodeLists(node.entries, toNode.entries)), _isEqualTokens(node.rightBracket, toNode.rightBracket))) {
8781 toNode.propagatedType = node.propagatedType;
8782 toNode.staticType = node.staticType;
8783 return true;
8784 }
8785 return false;
8786 }
8787
8788 @override
8789 bool visitMapLiteralEntry(MapLiteralEntry node) {
8790 MapLiteralEntry toNode = this._toNode as MapLiteralEntry;
8791 return javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.key, toNode.key), _i sEqualTokens(node.separator, toNode.separator)), _isEqualNodes(node.value, toNod e.value));
8792 }
8793
8794 @override
8795 bool visitMethodDeclaration(MethodDeclaration node) {
8796 MethodDeclaration toNode = this._toNode as MethodDeclaration;
8797 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole anAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualNodes( node.documentationComment, toNode.documentationComment), _isEqualNodeLists(node. metadata, toNode.metadata)), _isEqualTokens(node.externalKeyword, toNode.externa lKeyword)), _isEqualTokens(node.modifierKeyword, toNode.modifierKeyword)), _isEq ualNodes(node.returnType, toNode.returnType)), _isEqualTokens(node.propertyKeywo rd, toNode.propertyKeyword)), _isEqualTokens(node.propertyKeyword, toNode.proper tyKeyword)), _isEqualNodes(node.name, toNode.name)), _isEqualNodes(node.paramete rs, toNode.parameters)), _isEqualNodes(node.body, toNode.body));
8798 }
8799
8800 @override
8801 bool visitMethodInvocation(MethodInvocation node) {
8802 MethodInvocation toNode = this._toNode as MethodInvocation;
8803 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.target, toNode.target), _isEqualTokens(node.period, toNode.period)), _isEqualNodes(node. methodName, toNode.methodName)), _isEqualNodes(node.argumentList, toNode.argumen tList))) {
8804 toNode.propagatedType = node.propagatedType;
8805 toNode.staticType = node.staticType;
8806 return true;
8807 }
8808 return false;
8809 }
8810
8811 @override
8812 bool visitNamedExpression(NamedExpression node) {
8813 NamedExpression toNode = this._toNode as NamedExpression;
8814 if (javaBooleanAnd(_isEqualNodes(node.name, toNode.name), _isEqualNodes(node .expression, toNode.expression))) {
8815 toNode.propagatedType = node.propagatedType;
8816 toNode.staticType = node.staticType;
8817 return true;
8818 }
8819 return false;
8820 }
8821
8822 @override
8823 bool visitNativeClause(NativeClause node) {
8824 NativeClause toNode = this._toNode as NativeClause;
8825 return javaBooleanAnd(_isEqualTokens(node.keyword, toNode.keyword), _isEqual Nodes(node.name, toNode.name));
8826 }
8827
8828 @override
8829 bool visitNativeFunctionBody(NativeFunctionBody node) {
8830 NativeFunctionBody toNode = this._toNode as NativeFunctionBody;
8831 return javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.nativeToken, toNode .nativeToken), _isEqualNodes(node.stringLiteral, toNode.stringLiteral)), _isEqua lTokens(node.semicolon, toNode.semicolon));
8832 }
8833
8834 @override
8835 bool visitNullLiteral(NullLiteral node) {
8836 NullLiteral toNode = this._toNode as NullLiteral;
8837 if (_isEqualTokens(node.literal, toNode.literal)) {
8838 toNode.propagatedType = node.propagatedType;
8839 toNode.staticType = node.staticType;
8840 return true;
8841 }
8842 return false;
8843 }
8844
8845 @override
8846 bool visitParenthesizedExpression(ParenthesizedExpression node) {
8847 ParenthesizedExpression toNode = this._toNode as ParenthesizedExpression;
8848 if (javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.leftParenthesis, toNod e.leftParenthesis), _isEqualNodes(node.expression, toNode.expression)), _isEqual Tokens(node.rightParenthesis, toNode.rightParenthesis))) {
8849 toNode.propagatedType = node.propagatedType;
8850 toNode.staticType = node.staticType;
8851 return true;
8852 }
8853 return false;
8854 }
8855
8856 @override
8857 bool visitPartDirective(PartDirective node) {
8858 PartDirective toNode = this._toNode as PartDirective;
8859 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualNode s(node.documentationComment, toNode.documentationComment), _isEqualNodeLists(nod e.metadata, toNode.metadata)), _isEqualTokens(node.partToken, toNode.partToken)) , _isEqualNodes(node.uri, toNode.uri)), _isEqualTokens(node.semicolon, toNode.se micolon))) {
8860 toNode.element = node.element;
8861 return true;
8862 }
8863 return false;
8864 }
8865
8866 @override
8867 bool visitPartOfDirective(PartOfDirective node) {
8868 PartOfDirective toNode = this._toNode as PartOfDirective;
8869 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanA nd(_isEqualNodes(node.documentationComment, toNode.documentationComment), _isEqu alNodeLists(node.metadata, toNode.metadata)), _isEqualTokens(node.partToken, toN ode.partToken)), _isEqualTokens(node.ofToken, toNode.ofToken)), _isEqualNodes(no de.libraryName, toNode.libraryName)), _isEqualTokens(node.semicolon, toNode.semi colon))) {
8870 toNode.element = node.element;
8871 return true;
8872 }
8873 return false;
8874 }
8875
8876 @override
8877 bool visitPostfixExpression(PostfixExpression node) {
8878 PostfixExpression toNode = this._toNode as PostfixExpression;
8879 if (javaBooleanAnd(_isEqualNodes(node.operand, toNode.operand), _isEqualToke ns(node.operator, toNode.operator))) {
8880 toNode.propagatedElement = node.propagatedElement;
8881 toNode.propagatedType = node.propagatedType;
8882 toNode.staticElement = node.staticElement;
8883 toNode.staticType = node.staticType;
8884 return true;
8885 }
8886 return false;
8887 }
8888
8889 @override
8890 bool visitPrefixedIdentifier(PrefixedIdentifier node) {
8891 PrefixedIdentifier toNode = this._toNode as PrefixedIdentifier;
8892 if (javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.prefix, toNode.prefix), _isEqualTokens(node.period, toNode.period)), _isEqualNodes(node.identifier, toN ode.identifier))) {
8893 toNode.propagatedType = node.propagatedType;
8894 toNode.staticType = node.staticType;
8895 return true;
8896 }
8897 return false;
8898 }
8899
8900 @override
8901 bool visitPrefixExpression(PrefixExpression node) {
8902 PrefixExpression toNode = this._toNode as PrefixExpression;
8903 if (javaBooleanAnd(_isEqualTokens(node.operator, toNode.operator), _isEqualN odes(node.operand, toNode.operand))) {
8904 toNode.propagatedElement = node.propagatedElement;
8905 toNode.propagatedType = node.propagatedType;
8906 toNode.staticElement = node.staticElement;
8907 toNode.staticType = node.staticType;
8908 return true;
8909 }
8910 return false;
8911 }
8912
8913 @override
8914 bool visitPropertyAccess(PropertyAccess node) {
8915 PropertyAccess toNode = this._toNode as PropertyAccess;
8916 if (javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.target, toNode.target), _isEqualTokens(node.operator, toNode.operator)), _isEqualNodes(node.propertyNam e, toNode.propertyName))) {
8917 toNode.propagatedType = node.propagatedType;
8918 toNode.staticType = node.staticType;
8919 return true;
8920 }
8921 return false;
8922 }
8923
8924 @override
8925 bool visitRedirectingConstructorInvocation(RedirectingConstructorInvocation no de) {
8926 RedirectingConstructorInvocation toNode = this._toNode as RedirectingConstru ctorInvocation;
8927 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.keyword , toNode.keyword), _isEqualTokens(node.period, toNode.period)), _isEqualNodes(no de.constructorName, toNode.constructorName)), _isEqualNodes(node.argumentList, t oNode.argumentList))) {
8928 toNode.staticElement = node.staticElement;
8929 return true;
8930 }
8931 return false;
8932 }
8933
8934 @override
8935 bool visitRethrowExpression(RethrowExpression node) {
8936 RethrowExpression toNode = this._toNode as RethrowExpression;
8937 if (_isEqualTokens(node.keyword, toNode.keyword)) {
8938 toNode.propagatedType = node.propagatedType;
8939 toNode.staticType = node.staticType;
8940 return true;
8941 }
8942 return false;
8943 }
8944
8945 @override
8946 bool visitReturnStatement(ReturnStatement node) {
8947 ReturnStatement toNode = this._toNode as ReturnStatement;
8948 return javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.keyword, toNode.key word), _isEqualNodes(node.expression, toNode.expression)), _isEqualTokens(node.s emicolon, toNode.semicolon));
8949 }
8950
8951 @override
8952 bool visitScriptTag(ScriptTag node) {
8953 ScriptTag toNode = this._toNode as ScriptTag;
8954 return _isEqualTokens(node.scriptTag, toNode.scriptTag);
8955 }
8956
8957 @override
8958 bool visitShowCombinator(ShowCombinator node) {
8959 ShowCombinator toNode = this._toNode as ShowCombinator;
8960 return javaBooleanAnd(_isEqualTokens(node.keyword, toNode.keyword), _isEqual NodeLists(node.shownNames, toNode.shownNames));
8961 }
8962
8963 @override
8964 bool visitSimpleFormalParameter(SimpleFormalParameter node) {
8965 SimpleFormalParameter toNode = this._toNode as SimpleFormalParameter;
8966 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualN odes(node.documentationComment, toNode.documentationComment), _isEqualNodeLists( node.metadata, toNode.metadata)), _isEqualTokens(node.keyword, toNode.keyword)), _isEqualNodes(node.type, toNode.type)), _isEqualNodes(node.identifier, toNode.i dentifier));
8967 }
8968
8969 @override
8970 bool visitSimpleIdentifier(SimpleIdentifier node) {
8971 SimpleIdentifier toNode = this._toNode as SimpleIdentifier;
8972 if (_isEqualTokens(node.token, toNode.token)) {
8973 toNode.staticElement = node.staticElement;
8974 toNode.staticType = node.staticType;
8975 toNode.propagatedElement = node.propagatedElement;
8976 toNode.propagatedType = node.propagatedType;
8977 toNode.auxiliaryElements = node.auxiliaryElements;
8978 return true;
8979 }
8980 return false;
8981 }
8982
8983 @override
8984 bool visitSimpleStringLiteral(SimpleStringLiteral node) {
8985 SimpleStringLiteral toNode = this._toNode as SimpleStringLiteral;
8986 if (javaBooleanAnd(_isEqualTokens(node.literal, toNode.literal), identical(n ode.value, toNode.value))) {
8987 toNode.propagatedType = node.propagatedType;
8988 toNode.staticType = node.staticType;
8989 return true;
8990 }
8991 return false;
8992 }
8993
8994 @override
8995 bool visitStringInterpolation(StringInterpolation node) {
8996 StringInterpolation toNode = this._toNode as StringInterpolation;
8997 if (_isEqualNodeLists(node.elements, toNode.elements)) {
8998 toNode.propagatedType = node.propagatedType;
8999 toNode.staticType = node.staticType;
9000 return true;
9001 }
9002 return false;
9003 }
9004
9005 @override
9006 bool visitSuperConstructorInvocation(SuperConstructorInvocation node) {
9007 SuperConstructorInvocation toNode = this._toNode as SuperConstructorInvocati on;
9008 if (javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.keyword , toNode.keyword), _isEqualTokens(node.period, toNode.period)), _isEqualNodes(no de.constructorName, toNode.constructorName)), _isEqualNodes(node.argumentList, t oNode.argumentList))) {
9009 toNode.staticElement = node.staticElement;
9010 return true;
9011 }
9012 return false;
9013 }
9014
9015 @override
9016 bool visitSuperExpression(SuperExpression node) {
9017 SuperExpression toNode = this._toNode as SuperExpression;
9018 if (_isEqualTokens(node.keyword, toNode.keyword)) {
9019 toNode.propagatedType = node.propagatedType;
9020 toNode.staticType = node.staticType;
9021 return true;
9022 }
9023 return false;
9024 }
9025
9026 @override
9027 bool visitSwitchCase(SwitchCase node) {
9028 SwitchCase toNode = this._toNode as SwitchCase;
9029 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualN odeLists(node.labels, toNode.labels), _isEqualTokens(node.keyword, toNode.keywor d)), _isEqualNodes(node.expression, toNode.expression)), _isEqualTokens(node.col on, toNode.colon)), _isEqualNodeLists(node.statements, toNode.statements));
9030 }
9031
9032 @override
9033 bool visitSwitchDefault(SwitchDefault node) {
9034 SwitchDefault toNode = this._toNode as SwitchDefault;
9035 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualNodeLists(node.l abels, toNode.labels), _isEqualTokens(node.keyword, toNode.keyword)), _isEqualTo kens(node.colon, toNode.colon)), _isEqualNodeLists(node.statements, toNode.state ments));
9036 }
9037
9038 @override
9039 bool visitSwitchStatement(SwitchStatement node) {
9040 SwitchStatement toNode = this._toNode as SwitchStatement;
9041 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBoole anAnd(javaBooleanAnd(_isEqualTokens(node.keyword, toNode.keyword), _isEqualToken s(node.leftParenthesis, toNode.leftParenthesis)), _isEqualNodes(node.expression, toNode.expression)), _isEqualTokens(node.rightParenthesis, toNode.rightParenthe sis)), _isEqualTokens(node.leftBracket, toNode.leftBracket)), _isEqualNodeLists( node.members, toNode.members)), _isEqualTokens(node.rightBracket, toNode.rightBr acket));
9042 }
9043
9044 @override
9045 bool visitSymbolLiteral(SymbolLiteral node) {
9046 SymbolLiteral toNode = this._toNode as SymbolLiteral;
9047 if (javaBooleanAnd(_isEqualTokens(node.poundSign, toNode.poundSign), _isEqua lTokenLists(node.components, toNode.components))) {
9048 toNode.propagatedType = node.propagatedType;
9049 toNode.staticType = node.staticType;
9050 return true;
9051 }
9052 return false;
9053 }
9054
9055 @override
9056 bool visitThisExpression(ThisExpression node) {
9057 ThisExpression toNode = this._toNode as ThisExpression;
9058 if (_isEqualTokens(node.keyword, toNode.keyword)) {
9059 toNode.propagatedType = node.propagatedType;
9060 toNode.staticType = node.staticType;
9061 return true;
9062 }
9063 return false;
9064 }
9065
9066 @override
9067 bool visitThrowExpression(ThrowExpression node) {
9068 ThrowExpression toNode = this._toNode as ThrowExpression;
9069 if (javaBooleanAnd(_isEqualTokens(node.keyword, toNode.keyword), _isEqualNod es(node.expression, toNode.expression))) {
9070 toNode.propagatedType = node.propagatedType;
9071 toNode.staticType = node.staticType;
9072 return true;
9073 }
9074 return false;
9075 }
9076
9077 @override
9078 bool visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
9079 TopLevelVariableDeclaration toNode = this._toNode as TopLevelVariableDeclara tion;
9080 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualNodes(node.docum entationComment, toNode.documentationComment), _isEqualNodeLists(node.metadata, toNode.metadata)), _isEqualNodes(node.variables, toNode.variables)), _isEqualTok ens(node.semicolon, toNode.semicolon));
9081 }
9082
9083 @override
9084 bool visitTryStatement(TryStatement node) {
9085 TryStatement toNode = this._toNode as TryStatement;
9086 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualT okens(node.tryKeyword, toNode.tryKeyword), _isEqualNodes(node.body, toNode.body) ), _isEqualNodeLists(node.catchClauses, toNode.catchClauses)), _isEqualTokens(no de.finallyKeyword, toNode.finallyKeyword)), _isEqualNodes(node.finallyBlock, toN ode.finallyBlock));
9087 }
9088
9089 @override
9090 bool visitTypeArgumentList(TypeArgumentList node) {
9091 TypeArgumentList toNode = this._toNode as TypeArgumentList;
9092 return javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.leftBracket, toNode .leftBracket), _isEqualNodeLists(node.arguments, toNode.arguments)), _isEqualTok ens(node.rightBracket, toNode.rightBracket));
9093 }
9094
9095 @override
9096 bool visitTypeName(TypeName node) {
9097 TypeName toNode = this._toNode as TypeName;
9098 if (javaBooleanAnd(_isEqualNodes(node.name, toNode.name), _isEqualNodes(node .typeArguments, toNode.typeArguments))) {
9099 toNode.type = node.type;
9100 return true;
9101 }
9102 return false;
9103 }
9104
9105 @override
9106 bool visitTypeParameter(TypeParameter node) {
9107 TypeParameter toNode = this._toNode as TypeParameter;
9108 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualN odes(node.documentationComment, toNode.documentationComment), _isEqualNodeLists( node.metadata, toNode.metadata)), _isEqualNodes(node.name, toNode.name)), _isEqu alTokens(node.keyword, toNode.keyword)), _isEqualNodes(node.bound, toNode.bound) );
9109 }
9110
9111 @override
9112 bool visitTypeParameterList(TypeParameterList node) {
9113 TypeParameterList toNode = this._toNode as TypeParameterList;
9114 return javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.leftBracket, toNode .leftBracket), _isEqualNodeLists(node.typeParameters, toNode.typeParameters)), _ isEqualTokens(node.rightBracket, toNode.rightBracket));
9115 }
9116
9117 @override
9118 bool visitVariableDeclaration(VariableDeclaration node) {
9119 VariableDeclaration toNode = this._toNode as VariableDeclaration;
9120 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualN odes(node.documentationComment, toNode.documentationComment), _isEqualNodeLists( node.metadata, toNode.metadata)), _isEqualNodes(node.name, toNode.name)), _isEqu alTokens(node.equals, toNode.equals)), _isEqualNodes(node.initializer, toNode.in itializer));
9121 }
9122
9123 @override
9124 bool visitVariableDeclarationList(VariableDeclarationList node) {
9125 VariableDeclarationList toNode = this._toNode as VariableDeclarationList;
9126 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualN odes(node.documentationComment, toNode.documentationComment), _isEqualNodeLists( node.metadata, toNode.metadata)), _isEqualTokens(node.keyword, toNode.keyword)), _isEqualNodes(node.type, toNode.type)), _isEqualNodeLists(node.variables, toNod e.variables));
9127 }
9128
9129 @override
9130 bool visitVariableDeclarationStatement(VariableDeclarationStatement node) {
9131 VariableDeclarationStatement toNode = this._toNode as VariableDeclarationSta tement;
9132 return javaBooleanAnd(_isEqualNodes(node.variables, toNode.variables), _isEq ualTokens(node.semicolon, toNode.semicolon));
9133 }
9134
9135 @override
9136 bool visitWhileStatement(WhileStatement node) {
9137 WhileStatement toNode = this._toNode as WhileStatement;
9138 return javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(javaBooleanAnd(_isEqualT okens(node.keyword, toNode.keyword), _isEqualTokens(node.leftParenthesis, toNode .leftParenthesis)), _isEqualNodes(node.condition, toNode.condition)), _isEqualTo kens(node.rightParenthesis, toNode.rightParenthesis)), _isEqualNodes(node.body, toNode.body));
9139 }
9140
9141 @override
9142 bool visitWithClause(WithClause node) {
9143 WithClause toNode = this._toNode as WithClause;
9144 return javaBooleanAnd(_isEqualTokens(node.withKeyword, toNode.withKeyword), _isEqualNodeLists(node.mixinTypes, toNode.mixinTypes));
9145 }
9146
9147 @override
9148 bool visitYieldStatement(YieldStatement node) {
9149 YieldStatement toNode = this._toNode as YieldStatement;
9150 return javaBooleanAnd(javaBooleanAnd(_isEqualTokens(node.yieldKeyword, toNod e.yieldKeyword), _isEqualNodes(node.expression, toNode.expression)), _isEqualTok ens(node.semicolon, toNode.semicolon));
9151 }
9152
9153 /**
9154 * Return `true` if the given lists of AST nodes have the same size and corres ponding
9155 * elements are equal.
9156 *
9157 * @param first the first node being compared
9158 * @param second the second node being compared
9159 * @return `true` if the given AST nodes have the same size and corresponding elements are
9160 * equal
9161 */
9162 bool _isEqualNodeLists(NodeList first, NodeList second) {
9163 if (first == null) {
9164 return second == null;
9165 } else if (second == null) {
9166 return false;
9167 }
9168 int size = first.length;
9169 if (second.length != size) {
9170 return false;
9171 }
9172 bool equal = true;
9173 for (int i = 0; i < size; i++) {
9174 if (!_isEqualNodes(first[i], second[i])) {
9175 equal = false;
9176 }
9177 }
9178 return equal;
9179 }
9180
9181 /**
9182 * Return `true` if the given AST nodes have the same structure. As a side-eff ect, if the
9183 * nodes do have the same structure, any resolution data from the first node w ill be copied to the
9184 * second node.
9185 *
9186 * @param fromNode the node from which resolution information will be copied
9187 * @param toNode the node to which resolution information will be copied
9188 * @return `true` if the given AST nodes have the same structure
9189 */
9190 bool _isEqualNodes(AstNode fromNode, AstNode toNode) {
9191 if (fromNode == null) {
9192 return toNode == null;
9193 } else if (toNode == null) {
9194 return false;
9195 } else if (fromNode.runtimeType == toNode.runtimeType) {
9196 this._toNode = toNode;
9197 return fromNode.accept(this);
9198 }
9199 //
9200 // Check for a simple transformation caused by entering a period.
9201 //
9202 if (toNode is PrefixedIdentifier) {
9203 SimpleIdentifier prefix = toNode.prefix;
9204 if (fromNode.runtimeType == prefix.runtimeType) {
9205 this._toNode = prefix;
9206 return fromNode.accept(this);
9207 }
9208 } else if (toNode is PropertyAccess) {
9209 Expression target = toNode.target;
9210 if (fromNode.runtimeType == target.runtimeType) {
9211 this._toNode = target;
9212 return fromNode.accept(this);
9213 }
9214 }
9215 return false;
9216 }
9217
9218 /**
9219 * Return `true` if the given arrays of tokens have the same length and corres ponding
9220 * elements are equal.
9221 *
9222 * @param first the first node being compared
9223 * @param second the second node being compared
9224 * @return `true` if the given arrays of tokens have the same length and corre sponding
9225 * elements are equal
9226 */
9227 bool _isEqualTokenLists(List<Token> first, List<Token> second) {
9228 int length = first.length;
9229 if (second.length != length) {
9230 return false;
9231 }
9232 for (int i = 0; i < length; i++) {
9233 if (!_isEqualTokens(first[i], second[i])) {
9234 return false;
9235 }
9236 }
9237 return true;
9238 }
9239
9240 /**
9241 * Return `true` if the given tokens have the same structure.
9242 *
9243 * @param first the first node being compared
9244 * @param second the second node being compared
9245 * @return `true` if the given tokens have the same structure
9246 */
9247 bool _isEqualTokens(Token first, Token second) {
9248 if (first == null) {
9249 return second == null;
9250 } else if (second == null) {
9251 return false;
9252 }
9253 return first.lexeme == second.lexeme;
9254 }
9255 }
9256 Map<String, MethodTrampoline> methodTable_Parser = <String, MethodTrampoline> {
9257 'parseCompilationUnit_1': new MethodTrampoline(1, (Parser target, arg0) => tar get.parseCompilationUnit(arg0)),
9258 'parseDirectives_1': new MethodTrampoline(1, (Parser target, arg0) => target.p arseDirectives(arg0)),
9259 'parseExpression_1': new MethodTrampoline(1, (Parser target, arg0) => target.p arseExpression(arg0)),
9260 'parseStatement_1': new MethodTrampoline(1, (Parser target, arg0) => target.pa rseStatement(arg0)),
9261 'parseStatements_1': new MethodTrampoline(1, (Parser target, arg0) => target.p arseStatements(arg0)),
9262 'parseAnnotation_0': new MethodTrampoline(0, (Parser target) => target.parseAn notation()),
9263 'parseArgument_0': new MethodTrampoline(0, (Parser target) => target.parseArgu ment()),
9264 'parseArgumentList_0': new MethodTrampoline(0, (Parser target) => target.parse ArgumentList()),
9265 'parseBitwiseOrExpression_0': new MethodTrampoline(0, (Parser target) => targe t.parseBitwiseOrExpression()),
9266 'parseBlock_0': new MethodTrampoline(0, (Parser target) => target.parseBlock() ),
9267 'parseClassMember_1': new MethodTrampoline(1, (Parser target, arg0) => target. parseClassMember(arg0)),
9268 'parseCompilationUnit_0': new MethodTrampoline(0, (Parser target) => target.pa rseCompilationUnit2()),
9269 'parseConditionalExpression_0': new MethodTrampoline(0, (Parser target) => tar get.parseConditionalExpression()),
9270 'parseConstructorName_0': new MethodTrampoline(0, (Parser target) => target.pa rseConstructorName()),
9271 'parseExpression_0': new MethodTrampoline(0, (Parser target) => target.parseEx pression2()),
9272 'parseExpressionWithoutCascade_0': new MethodTrampoline(0, (Parser target) => target.parseExpressionWithoutCascade()),
9273 'parseExtendsClause_0': new MethodTrampoline(0, (Parser target) => target.pars eExtendsClause()),
9274 'parseFormalParameterList_0': new MethodTrampoline(0, (Parser target) => targe t.parseFormalParameterList()),
9275 'parseFunctionExpression_0': new MethodTrampoline(0, (Parser target) => target .parseFunctionExpression()),
9276 'parseImplementsClause_0': new MethodTrampoline(0, (Parser target) => target.p arseImplementsClause()),
9277 'parseLabel_0': new MethodTrampoline(0, (Parser target) => target.parseLabel() ),
9278 'parseLibraryIdentifier_0': new MethodTrampoline(0, (Parser target) => target. parseLibraryIdentifier()),
9279 'parseLogicalOrExpression_0': new MethodTrampoline(0, (Parser target) => targe t.parseLogicalOrExpression()),
9280 'parseMapLiteralEntry_0': new MethodTrampoline(0, (Parser target) => target.pa rseMapLiteralEntry()),
9281 'parseNormalFormalParameter_0': new MethodTrampoline(0, (Parser target) => tar get.parseNormalFormalParameter()),
9282 'parsePrefixedIdentifier_0': new MethodTrampoline(0, (Parser target) => target .parsePrefixedIdentifier()),
9283 'parseReturnType_0': new MethodTrampoline(0, (Parser target) => target.parseRe turnType()),
9284 'parseSimpleIdentifier_0': new MethodTrampoline(0, (Parser target) => target.p arseSimpleIdentifier()),
9285 'parseStatement_0': new MethodTrampoline(0, (Parser target) => target.parseSta tement2()),
9286 'parseStringLiteral_0': new MethodTrampoline(0, (Parser target) => target.pars eStringLiteral()),
9287 'parseTypeArgumentList_0': new MethodTrampoline(0, (Parser target) => target.p arseTypeArgumentList()),
9288 'parseTypeName_0': new MethodTrampoline(0, (Parser target) => target.parseType Name()),
9289 'parseTypeParameter_0': new MethodTrampoline(0, (Parser target) => target.pars eTypeParameter()),
9290 'parseTypeParameterList_0': new MethodTrampoline(0, (Parser target) => target. parseTypeParameterList()),
9291 'parseWithClause_0': new MethodTrampoline(0, (Parser target) => target.parseWi thClause()),
9292 'advance_0': new MethodTrampoline(0, (Parser target) => target._advance()),
9293 'appendScalarValue_5': new MethodTrampoline(5, (Parser target, arg0, arg1, arg 2, arg3, arg4) => target._appendScalarValue(arg0, arg1, arg2, arg3, arg4)),
9294 'computeStringValue_3': new MethodTrampoline(3, (Parser target, arg0, arg1, ar g2) => target._computeStringValue(arg0, arg1, arg2)),
9295 'convertToFunctionDeclaration_1': new MethodTrampoline(1, (Parser target, arg0 ) => target._convertToFunctionDeclaration(arg0)),
9296 'couldBeStartOfCompilationUnitMember_0': new MethodTrampoline(0, (Parser targe t) => target._couldBeStartOfCompilationUnitMember()),
9297 'createSyntheticIdentifier_0': new MethodTrampoline(0, (Parser target) => targ et._createSyntheticIdentifier()),
9298 'createSyntheticKeyword_1': new MethodTrampoline(1, (Parser target, arg0) => t arget._createSyntheticKeyword(arg0)),
9299 'createSyntheticStringLiteral_0': new MethodTrampoline(0, (Parser target) => t arget._createSyntheticStringLiteral()),
9300 'createSyntheticToken_1': new MethodTrampoline(1, (Parser target, arg0) => tar get._createSyntheticToken(arg0)),
9301 'ensureAssignable_1': new MethodTrampoline(1, (Parser target, arg0) => target. _ensureAssignable(arg0)),
9302 'expect_1': new MethodTrampoline(1, (Parser target, arg0) => target._expect(ar g0)),
9303 'expectGt_0': new MethodTrampoline(0, (Parser target) => target._expectGt()),
9304 'expectKeyword_1': new MethodTrampoline(1, (Parser target, arg0) => target._ex pectKeyword(arg0)),
9305 'expectSemicolon_0': new MethodTrampoline(0, (Parser target) => target._expect Semicolon()),
9306 'findRange_2': new MethodTrampoline(2, (Parser target, arg0, arg1) => target._ findRange(arg0, arg1)),
9307 'getCodeBlockRanges_1': new MethodTrampoline(1, (Parser target, arg0) => targe t._getCodeBlockRanges(arg0)),
9308 'getEndToken_1': new MethodTrampoline(1, (Parser target, arg0) => target._getE ndToken(arg0)),
9309 'injectToken_1': new MethodTrampoline(1, (Parser target, arg0) => target._inje ctToken(arg0)),
9310 'isFunctionDeclaration_0': new MethodTrampoline(0, (Parser target) => target._ isFunctionDeclaration()),
9311 'isFunctionExpression_1': new MethodTrampoline(1, (Parser target, arg0) => tar get._isFunctionExpression(arg0)),
9312 'isHexDigit_1': new MethodTrampoline(1, (Parser target, arg0) => target._isHex Digit(arg0)),
9313 'isInitializedVariableDeclaration_0': new MethodTrampoline(0, (Parser target) => target._isInitializedVariableDeclaration()),
9314 'isLinkText_2': new MethodTrampoline(2, (Parser target, arg0, arg1) => target. _isLinkText(arg0, arg1)),
9315 'isOperator_1': new MethodTrampoline(1, (Parser target, arg0) => target._isOpe rator(arg0)),
9316 'isSwitchMember_0': new MethodTrampoline(0, (Parser target) => target._isSwitc hMember()),
9317 'isTypedIdentifier_1': new MethodTrampoline(1, (Parser target, arg0) => target ._isTypedIdentifier(arg0)),
9318 'lexicallyFirst_1': new MethodTrampoline(1, (Parser target, arg0) => target._l exicallyFirst(arg0)),
9319 'lockErrorListener_0': new MethodTrampoline(0, (Parser target) => target._lock ErrorListener()),
9320 'matches_1': new MethodTrampoline(1, (Parser target, arg0) => target._matches( arg0)),
9321 'matchesGt_0': new MethodTrampoline(0, (Parser target) => target._matchesGt()) ,
9322 'matchesIdentifier_0': new MethodTrampoline(0, (Parser target) => target._matc hesIdentifier()),
9323 'matchesKeyword_1': new MethodTrampoline(1, (Parser target, arg0) => target._m atchesKeyword(arg0)),
9324 'matchesString_1': new MethodTrampoline(1, (Parser target, arg0) => target._ma tchesString(arg0)),
9325 'optional_1': new MethodTrampoline(1, (Parser target, arg0) => target._optiona l(arg0)),
9326 'parseAdditiveExpression_0': new MethodTrampoline(0, (Parser target) => target ._parseAdditiveExpression()),
9327 'parseAssertStatement_0': new MethodTrampoline(0, (Parser target) => target._p arseAssertStatement()),
9328 'parseAssignableExpression_1': new MethodTrampoline(1, (Parser target, arg0) = > target._parseAssignableExpression(arg0)),
9329 'parseAssignableSelector_2': new MethodTrampoline(2, (Parser target, arg0, arg 1) => target._parseAssignableSelector(arg0, arg1)),
9330 'parseAwaitExpression_0': new MethodTrampoline(0, (Parser target) => target._p arseAwaitExpression()),
9331 'parseBitwiseAndExpression_0': new MethodTrampoline(0, (Parser target) => targ et._parseBitwiseAndExpression()),
9332 'parseBitwiseXorExpression_0': new MethodTrampoline(0, (Parser target) => targ et._parseBitwiseXorExpression()),
9333 'parseBreakStatement_0': new MethodTrampoline(0, (Parser target) => target._pa rseBreakStatement()),
9334 'parseCascadeSection_0': new MethodTrampoline(0, (Parser target) => target._pa rseCascadeSection()),
9335 'parseClassDeclaration_2': new MethodTrampoline(2, (Parser target, arg0, arg1) => target._parseClassDeclaration(arg0, arg1)),
9336 'parseClassMembers_2': new MethodTrampoline(2, (Parser target, arg0, arg1) => target._parseClassMembers(arg0, arg1)),
9337 'parseClassTypeAlias_3': new MethodTrampoline(3, (Parser target, arg0, arg1, a rg2) => target._parseClassTypeAlias(arg0, arg1, arg2)),
9338 'parseCombinators_0': new MethodTrampoline(0, (Parser target) => target._parse Combinators()),
9339 'parseCommentAndMetadata_0': new MethodTrampoline(0, (Parser target) => target ._parseCommentAndMetadata()),
9340 'parseCommentReference_2': new MethodTrampoline(2, (Parser target, arg0, arg1) => target._parseCommentReference(arg0, arg1)),
9341 'parseCommentReferences_1': new MethodTrampoline(1, (Parser target, arg0) => t arget._parseCommentReferences(arg0)),
9342 'parseCompilationUnitMember_1': new MethodTrampoline(1, (Parser target, arg0) => target._parseCompilationUnitMember(arg0)),
9343 'parseConstExpression_0': new MethodTrampoline(0, (Parser target) => target._p arseConstExpression()),
9344 'parseConstructor_8': new MethodTrampoline(8, (Parser target, arg0, arg1, arg2 , arg3, arg4, arg5, arg6, arg7) => target._parseConstructor(arg0, arg1, arg2, ar g3, arg4, arg5, arg6, arg7)),
9345 'parseConstructorFieldInitializer_0': new MethodTrampoline(0, (Parser target) => target._parseConstructorFieldInitializer()),
9346 'parseContinueStatement_0': new MethodTrampoline(0, (Parser target) => target. _parseContinueStatement()),
9347 'parseDirective_1': new MethodTrampoline(1, (Parser target, arg0) => target._p arseDirective(arg0)),
9348 'parseDirectives_0': new MethodTrampoline(0, (Parser target) => target._parseD irectives()),
9349 'parseDocumentationComment_0': new MethodTrampoline(0, (Parser target) => targ et._parseDocumentationComment()),
9350 'parseDoStatement_0': new MethodTrampoline(0, (Parser target) => target._parse DoStatement()),
9351 'parseEmptyStatement_0': new MethodTrampoline(0, (Parser target) => target._pa rseEmptyStatement()),
9352 'parseEnumConstantDeclaration_0': new MethodTrampoline(0, (Parser target) => t arget._parseEnumConstantDeclaration()),
9353 'parseEnumDeclaration_1': new MethodTrampoline(1, (Parser target, arg0) => tar get._parseEnumDeclaration(arg0)),
9354 'parseEqualityExpression_0': new MethodTrampoline(0, (Parser target) => target ._parseEqualityExpression()),
9355 'parseExportDirective_1': new MethodTrampoline(1, (Parser target, arg0) => tar get._parseExportDirective(arg0)),
9356 'parseExpressionList_0': new MethodTrampoline(0, (Parser target) => target._pa rseExpressionList()),
9357 'parseFinalConstVarOrType_1': new MethodTrampoline(1, (Parser target, arg0) => target._parseFinalConstVarOrType(arg0)),
9358 'parseFormalParameter_1': new MethodTrampoline(1, (Parser target, arg0) => tar get._parseFormalParameter(arg0)),
9359 'parseForStatement_0': new MethodTrampoline(0, (Parser target) => target._pars eForStatement()),
9360 'parseFunctionBody_3': new MethodTrampoline(3, (Parser target, arg0, arg1, arg 2) => target._parseFunctionBody(arg0, arg1, arg2)),
9361 'parseFunctionDeclaration_3': new MethodTrampoline(3, (Parser target, arg0, ar g1, arg2) => target._parseFunctionDeclaration(arg0, arg1, arg2)),
9362 'parseFunctionDeclarationStatement_0': new MethodTrampoline(0, (Parser target) => target._parseFunctionDeclarationStatement()),
9363 'parseFunctionDeclarationStatementAfterReturnType_2': new MethodTrampoline(2, (Parser target, arg0, arg1) => target._parseFunctionDeclarationStatementAfterRet urnType(arg0, arg1)),
9364 'parseFunctionTypeAlias_2': new MethodTrampoline(2, (Parser target, arg0, arg1 ) => target._parseFunctionTypeAlias(arg0, arg1)),
9365 'parseGetter_4': new MethodTrampoline(4, (Parser target, arg0, arg1, arg2, arg 3) => target._parseGetter(arg0, arg1, arg2, arg3)),
9366 'parseIdentifierList_0': new MethodTrampoline(0, (Parser target) => target._pa rseIdentifierList()),
9367 'parseIfStatement_0': new MethodTrampoline(0, (Parser target) => target._parse IfStatement()),
9368 'parseImportDirective_1': new MethodTrampoline(1, (Parser target, arg0) => tar get._parseImportDirective(arg0)),
9369 'parseInitializedIdentifierList_4': new MethodTrampoline(4, (Parser target, ar g0, arg1, arg2, arg3) => target._parseInitializedIdentifierList(arg0, arg1, arg2 , arg3)),
9370 'parseInstanceCreationExpression_1': new MethodTrampoline(1, (Parser target, a rg0) => target._parseInstanceCreationExpression(arg0)),
9371 'parseLibraryDirective_1': new MethodTrampoline(1, (Parser target, arg0) => ta rget._parseLibraryDirective(arg0)),
9372 'parseLibraryName_2': new MethodTrampoline(2, (Parser target, arg0, arg1) => t arget._parseLibraryName(arg0, arg1)),
9373 'parseListLiteral_2': new MethodTrampoline(2, (Parser target, arg0, arg1) => t arget._parseListLiteral(arg0, arg1)),
9374 'parseListOrMapLiteral_1': new MethodTrampoline(1, (Parser target, arg0) => ta rget._parseListOrMapLiteral(arg0)),
9375 'parseLogicalAndExpression_0': new MethodTrampoline(0, (Parser target) => targ et._parseLogicalAndExpression()),
9376 'parseMapLiteral_2': new MethodTrampoline(2, (Parser target, arg0, arg1) => ta rget._parseMapLiteral(arg0, arg1)),
9377 'parseMethodDeclarationAfterParameters_6': new MethodTrampoline(6, (Parser tar get, arg0, arg1, arg2, arg3, arg4, arg5) => target._parseMethodDeclarationAfterP arameters(arg0, arg1, arg2, arg3, arg4, arg5)),
9378 'parseMethodDeclarationAfterReturnType_4': new MethodTrampoline(4, (Parser tar get, arg0, arg1, arg2, arg3) => target._parseMethodDeclarationAfterReturnType(ar g0, arg1, arg2, arg3)),
9379 'parseModifiers_0': new MethodTrampoline(0, (Parser target) => target._parseMo difiers()),
9380 'parseMultiplicativeExpression_0': new MethodTrampoline(0, (Parser target) => target._parseMultiplicativeExpression()),
9381 'parseNativeClause_0': new MethodTrampoline(0, (Parser target) => target._pars eNativeClause()),
9382 'parseNewExpression_0': new MethodTrampoline(0, (Parser target) => target._par seNewExpression()),
9383 'parseNonLabeledStatement_0': new MethodTrampoline(0, (Parser target) => targe t._parseNonLabeledStatement()),
9384 'parseOperator_3': new MethodTrampoline(3, (Parser target, arg0, arg1, arg2) = > target._parseOperator(arg0, arg1, arg2)),
9385 'parseOptionalReturnType_0': new MethodTrampoline(0, (Parser target) => target ._parseOptionalReturnType()),
9386 'parsePartDirective_1': new MethodTrampoline(1, (Parser target, arg0) => targe t._parsePartDirective(arg0)),
9387 'parsePostfixExpression_0': new MethodTrampoline(0, (Parser target) => target. _parsePostfixExpression()),
9388 'parsePrimaryExpression_0': new MethodTrampoline(0, (Parser target) => target. _parsePrimaryExpression()),
9389 'parseRedirectingConstructorInvocation_0': new MethodTrampoline(0, (Parser tar get) => target._parseRedirectingConstructorInvocation()),
9390 'parseRelationalExpression_0': new MethodTrampoline(0, (Parser target) => targ et._parseRelationalExpression()),
9391 'parseRethrowExpression_0': new MethodTrampoline(0, (Parser target) => target. _parseRethrowExpression()),
9392 'parseReturnStatement_0': new MethodTrampoline(0, (Parser target) => target._p arseReturnStatement()),
9393 'parseSetter_4': new MethodTrampoline(4, (Parser target, arg0, arg1, arg2, arg 3) => target._parseSetter(arg0, arg1, arg2, arg3)),
9394 'parseShiftExpression_0': new MethodTrampoline(0, (Parser target) => target._p arseShiftExpression()),
9395 'parseStatementList_0': new MethodTrampoline(0, (Parser target) => target._par seStatementList()),
9396 'parseStringInterpolation_1': new MethodTrampoline(1, (Parser target, arg0) => target._parseStringInterpolation(arg0)),
9397 'parseSuperConstructorInvocation_0': new MethodTrampoline(0, (Parser target) = > target._parseSuperConstructorInvocation()),
9398 'parseSwitchStatement_0': new MethodTrampoline(0, (Parser target) => target._p arseSwitchStatement()),
9399 'parseSymbolLiteral_0': new MethodTrampoline(0, (Parser target) => target._par seSymbolLiteral()),
9400 'parseThrowExpression_0': new MethodTrampoline(0, (Parser target) => target._p arseThrowExpression()),
9401 'parseThrowExpressionWithoutCascade_0': new MethodTrampoline(0, (Parser target ) => target._parseThrowExpressionWithoutCascade()),
9402 'parseTryStatement_0': new MethodTrampoline(0, (Parser target) => target._pars eTryStatement()),
9403 'parseTypeAlias_1': new MethodTrampoline(1, (Parser target, arg0) => target._p arseTypeAlias(arg0)),
9404 'parseUnaryExpression_0': new MethodTrampoline(0, (Parser target) => target._p arseUnaryExpression()),
9405 'parseVariableDeclaration_0': new MethodTrampoline(0, (Parser target) => targe t._parseVariableDeclaration()),
9406 'parseVariableDeclarationListAfterMetadata_1': new MethodTrampoline(1, (Parser target, arg0) => target._parseVariableDeclarationListAfterMetadata(arg0)),
9407 'parseVariableDeclarationListAfterType_3': new MethodTrampoline(3, (Parser tar get, arg0, arg1, arg2) => target._parseVariableDeclarationListAfterType(arg0, ar g1, arg2)),
9408 'parseVariableDeclarationStatementAfterMetadata_1': new MethodTrampoline(1, (P arser target, arg0) => target._parseVariableDeclarationStatementAfterMetadata(ar g0)),
9409 'parseVariableDeclarationStatementAfterType_3': new MethodTrampoline(3, (Parse r target, arg0, arg1, arg2) => target._parseVariableDeclarationStatementAfterTyp e(arg0, arg1, arg2)),
9410 'parseWhileStatement_0': new MethodTrampoline(0, (Parser target) => target._pa rseWhileStatement()),
9411 'parseYieldStatement_0': new MethodTrampoline(0, (Parser target) => target._pa rseYieldStatement()),
9412 'peek_0': new MethodTrampoline(0, (Parser target) => target._peek()),
9413 'peekAt_1': new MethodTrampoline(1, (Parser target, arg0) => target._peekAt(ar g0)),
9414 'reportError_1': new MethodTrampoline(1, (Parser target, arg0) => target._repo rtError(arg0)),
9415 'reportErrorForCurrentToken_2': new MethodTrampoline(2, (Parser target, arg0, arg1) => target._reportErrorForCurrentToken(arg0, arg1)),
9416 'reportErrorForNode_3': new MethodTrampoline(3, (Parser target, arg0, arg1, ar g2) => target._reportErrorForNode(arg0, arg1, arg2)),
9417 'reportErrorForToken_3': new MethodTrampoline(3, (Parser target, arg0, arg1, a rg2) => target._reportErrorForToken(arg0, arg1, arg2)),
9418 'skipBlock_0': new MethodTrampoline(0, (Parser target) => target._skipBlock()) ,
9419 'skipFinalConstVarOrType_1': new MethodTrampoline(1, (Parser target, arg0) => target._skipFinalConstVarOrType(arg0)),
9420 'skipFormalParameterList_1': new MethodTrampoline(1, (Parser target, arg0) => target._skipFormalParameterList(arg0)),
9421 'skipPastMatchingToken_1': new MethodTrampoline(1, (Parser target, arg0) => ta rget._skipPastMatchingToken(arg0)),
9422 'skipPrefixedIdentifier_1': new MethodTrampoline(1, (Parser target, arg0) => t arget._skipPrefixedIdentifier(arg0)),
9423 'skipReturnType_1': new MethodTrampoline(1, (Parser target, arg0) => target._s kipReturnType(arg0)),
9424 'skipSimpleIdentifier_1': new MethodTrampoline(1, (Parser target, arg0) => tar get._skipSimpleIdentifier(arg0)),
9425 'skipStringInterpolation_1': new MethodTrampoline(1, (Parser target, arg0) => target._skipStringInterpolation(arg0)),
9426 'skipStringLiteral_1': new MethodTrampoline(1, (Parser target, arg0) => target ._skipStringLiteral(arg0)),
9427 'skipTypeArgumentList_1': new MethodTrampoline(1, (Parser target, arg0) => tar get._skipTypeArgumentList(arg0)),
9428 'skipTypeName_1': new MethodTrampoline(1, (Parser target, arg0) => target._ski pTypeName(arg0)),
9429 'skipTypeParameterList_1': new MethodTrampoline(1, (Parser target, arg0) => ta rget._skipTypeParameterList(arg0)),
9430 'tokenMatches_2': new MethodTrampoline(2, (Parser target, arg0, arg1) => targe t._tokenMatches(arg0, arg1)),
9431 'tokenMatchesIdentifier_1': new MethodTrampoline(1, (Parser target, arg0) => t arget._tokenMatchesIdentifier(arg0)),
9432 'tokenMatchesKeyword_2': new MethodTrampoline(2, (Parser target, arg0, arg1) = > target._tokenMatchesKeyword(arg0, arg1)),
9433 'tokenMatchesString_2': new MethodTrampoline(2, (Parser target, arg0, arg1) => target._tokenMatchesString(arg0, arg1)),
9434 'translateCharacter_3': new MethodTrampoline(3, (Parser target, arg0, arg1, ar g2) => target._translateCharacter(arg0, arg1, arg2)),
9435 'unlockErrorListener_0': new MethodTrampoline(0, (Parser target) => target._un lockErrorListener()),
9436 'validateFormalParameterList_1': new MethodTrampoline(1, (Parser target, arg0) => target._validateFormalParameterList(arg0)),
9437 'validateModifiersForClass_1': new MethodTrampoline(1, (Parser target, arg0) = > target._validateModifiersForClass(arg0)),
9438 'validateModifiersForConstructor_1': new MethodTrampoline(1, (Parser target, a rg0) => target._validateModifiersForConstructor(arg0)),
9439 'validateModifiersForEnum_1': new MethodTrampoline(1, (Parser target, arg0) => target._validateModifiersForEnum(arg0)),
9440 'validateModifiersForField_1': new MethodTrampoline(1, (Parser target, arg0) = > target._validateModifiersForField(arg0)),
9441 'validateModifiersForFunctionDeclarationStatement_1': new MethodTrampoline(1, (Parser target, arg0) => target._validateModifiersForFunctionDeclarationStatemen t(arg0)),
9442 'validateModifiersForGetterOrSetterOrMethod_1': new MethodTrampoline(1, (Parse r target, arg0) => target._validateModifiersForGetterOrSetterOrMethod(arg0)),
9443 'validateModifiersForOperator_1': new MethodTrampoline(1, (Parser target, arg0 ) => target._validateModifiersForOperator(arg0)),
9444 'validateModifiersForTopLevelDeclaration_1': new MethodTrampoline(1, (Parser t arget, arg0) => target._validateModifiersForTopLevelDeclaration(arg0)),
9445 'validateModifiersForTopLevelFunction_1': new MethodTrampoline(1, (Parser targ et, arg0) => target._validateModifiersForTopLevelFunction(arg0)),
9446 'validateModifiersForTopLevelVariable_1': new MethodTrampoline(1, (Parser targ et, arg0) => target._validateModifiersForTopLevelVariable(arg0)),
9447 'validateModifiersForTypedef_1': new MethodTrampoline(1, (Parser target, arg0) => target._validateModifiersForTypedef(arg0)),};
9448
9449
9450 Object invokeParserMethodImpl(Parser parser, String methodName, List<Object> obj ects, Token tokenStream) {
9451 parser.currentToken = tokenStream;
9452 MethodTrampoline method = methodTable_Parser['${methodName}_${objects.length}' ];
9453 return method.invoke(parser, objects);
9454 }
9455
9456
9457 /**
9458 * Wrapper around [Function] which should be called with "target" and "arguments ".
9459 */
9460 class MethodTrampoline {
9461 int parameterCount;
9462 Function trampoline;
9463 MethodTrampoline(this.parameterCount, this.trampoline);
9464 Object invoke(target, List arguments) {
9465 if (arguments.length != parameterCount) {
9466 throw new IllegalArgumentException("${arguments.length} != $parameterCount ");
9467 }
9468 switch (parameterCount) {
9469 case 0:
9470 return trampoline(target);
9471 case 1:
9472 return trampoline(target, arguments[0]);
9473 case 2:
9474 return trampoline(target, arguments[0], arguments[1]);
9475 case 3:
9476 return trampoline(target, arguments[0], arguments[1], arguments[2]);
9477 case 4:
9478 return trampoline(target, arguments[0], arguments[1], arguments[2], argu ments[3]);
9479 default:
9480 throw new IllegalArgumentException("Not implemented for > 4 arguments");
9481 }
9482 }
9483 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698