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

Side by Side Diff: pkg/analyzer_experimental/lib/src/generated/parser.dart

Issue 45573002: Rename analyzer_experimental to analyzer. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Tweaks before publishing. Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // This code was auto-generated, is not intended to be edited, and is subject to
2 // significant change. Please see the README file for more information.
3 library engine.parser;
4 import 'dart:collection';
5 import 'java_core.dart';
6 import 'instrumentation.dart';
7 import 'error.dart';
8 import 'source.dart';
9 import 'scanner.dart';
10 import 'ast.dart';
11 import 'utilities_dart.dart';
12 import 'engine.dart' show AnalysisEngine;
13 /**
14 * Instances of the class `CommentAndMetadata` implement a simple data-holder fo r a method
15 * that needs to return multiple values.
16 *
17 * @coverage dart.engine.parser
18 */
19 class CommentAndMetadata {
20
21 /**
22 * The documentation comment that was parsed, or `null` if none was given.
23 */
24 Comment comment;
25
26 /**
27 * The metadata that was parsed.
28 */
29 List<Annotation> metadata;
30
31 /**
32 * Initialize a newly created holder with the given data.
33 *
34 * @param comment the documentation comment that was parsed
35 * @param metadata the metadata that was parsed
36 */
37 CommentAndMetadata(Comment comment, List<Annotation> metadata) {
38 this.comment = comment;
39 this.metadata = metadata;
40 }
41 }
42 /**
43 * Instances of the class `FinalConstVarOrType` implement a simple data-holder f or a method
44 * that needs to return multiple values.
45 *
46 * @coverage dart.engine.parser
47 */
48 class FinalConstVarOrType {
49
50 /**
51 * The 'final', 'const' or 'var' keyword, or `null` if none was given.
52 */
53 Token keyword;
54
55 /**
56 * The type, of `null` if no type was specified.
57 */
58 TypeName type;
59
60 /**
61 * Initialize a newly created holder with the given data.
62 *
63 * @param keyword the 'final', 'const' or 'var' keyword
64 * @param type the type
65 */
66 FinalConstVarOrType(Token keyword, TypeName type) {
67 this.keyword = keyword;
68 this.type = type;
69 }
70 }
71 /**
72 * Instances of the class `Modifiers` implement a simple data-holder for a metho d that needs
73 * to return multiple values.
74 *
75 * @coverage dart.engine.parser
76 */
77 class Modifiers {
78
79 /**
80 * The token representing the keyword 'abstract', or `null` if the keyword was not found.
81 */
82 Token abstractKeyword;
83
84 /**
85 * The token representing the keyword 'const', or `null` if the keyword was no t found.
86 */
87 Token constKeyword;
88
89 /**
90 * The token representing the keyword 'external', or `null` if the keyword was not found.
91 */
92 Token externalKeyword;
93
94 /**
95 * The token representing the keyword 'factory', or `null` if the keyword was not found.
96 */
97 Token factoryKeyword;
98
99 /**
100 * The token representing the keyword 'final', or `null` if the keyword was no t found.
101 */
102 Token finalKeyword;
103
104 /**
105 * The token representing the keyword 'static', or `null` if the keyword was n ot found.
106 */
107 Token staticKeyword;
108
109 /**
110 * The token representing the keyword 'var', or `null` if the keyword was not found.
111 */
112 Token varKeyword;
113 String toString() {
114 JavaStringBuilder builder = new JavaStringBuilder();
115 bool needsSpace = appendKeyword(builder, false, abstractKeyword);
116 needsSpace = appendKeyword(builder, needsSpace, constKeyword);
117 needsSpace = appendKeyword(builder, needsSpace, externalKeyword);
118 needsSpace = appendKeyword(builder, needsSpace, factoryKeyword);
119 needsSpace = appendKeyword(builder, needsSpace, finalKeyword);
120 needsSpace = appendKeyword(builder, needsSpace, staticKeyword);
121 appendKeyword(builder, needsSpace, varKeyword);
122 return builder.toString();
123 }
124
125 /**
126 * If the given keyword is not `null`, append it to the given builder, prefixi ng it with a
127 * space if needed.
128 *
129 * @param builder the builder to which the keyword will be appended
130 * @param needsSpace `true` if the keyword needs to be prefixed with a space
131 * @param keyword the keyword to be appended
132 * @return `true` if subsequent keywords need to be prefixed with a space
133 */
134 bool appendKeyword(JavaStringBuilder builder, bool needsSpace, Token keyword) {
135 if (keyword != null) {
136 if (needsSpace) {
137 builder.appendChar(0x20);
138 }
139 builder.append(keyword.lexeme);
140 return true;
141 }
142 return needsSpace;
143 }
144 }
145 /**
146 * Instances of the class `Parser` are used to parse tokens into an AST structur e.
147 *
148 * @coverage dart.engine.parser
149 */
150 class Parser {
151
152 /**
153 * The source being parsed.
154 */
155 Source _source;
156
157 /**
158 * The error listener that will be informed of any errors that are found durin g the parse.
159 */
160 AnalysisErrorListener _errorListener;
161
162 /**
163 * The next token to be parsed.
164 */
165 Token _currentToken;
166
167 /**
168 * A flag indicating whether the parser is currently in the body of a loop.
169 */
170 bool _inLoop = false;
171
172 /**
173 * A flag indicating whether the parser is currently in a switch statement.
174 */
175 bool _inSwitch = false;
176 static String _HIDE = "hide";
177 static String _OF = "of";
178 static String _ON = "on";
179 static String _SHOW = "show";
180 static String _NATIVE = "native";
181
182 /**
183 * Initialize a newly created parser.
184 *
185 * @param source the source being parsed
186 * @param errorListener the error listener that will be informed of any errors that are found
187 * during the parse
188 */
189 Parser(Source source, AnalysisErrorListener errorListener) {
190 this._source = source;
191 this._errorListener = errorListener;
192 }
193
194 /**
195 * Parse a compilation unit, starting with the given token.
196 *
197 * @param token the first token of the compilation unit
198 * @return the compilation unit that was parsed
199 */
200 CompilationUnit parseCompilationUnit(Token token) {
201 InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engi ne.Parser.parseCompilationUnit");
202 try {
203 _currentToken = token;
204 CompilationUnit compilationUnit = parseCompilationUnit2();
205 gatherTodoComments(token);
206 return compilationUnit;
207 } finally {
208 instrumentation.log2(2);
209 }
210 }
211
212 /**
213 * Parse an expression, starting with the given token.
214 *
215 * @param token the first token of the expression
216 * @return the expression that was parsed, or `null` if the tokens do not repr esent a
217 * recognizable expression
218 */
219 Expression parseExpression(Token token) {
220 InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engi ne.Parser.parseExpression");
221 try {
222 _currentToken = token;
223 return parseExpression2();
224 } finally {
225 instrumentation.log();
226 }
227 }
228
229 /**
230 * Parse a statement, starting with the given token.
231 *
232 * @param token the first token of the statement
233 * @return the statement that was parsed, or `null` if the tokens do not repre sent a
234 * recognizable statement
235 */
236 Statement parseStatement(Token token) {
237 InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engi ne.Parser.parseStatement");
238 try {
239 _currentToken = token;
240 return parseStatement2();
241 } finally {
242 instrumentation.log();
243 }
244 }
245
246 /**
247 * Parse a sequence of statements, starting with the given token.
248 *
249 * @param token the first token of the sequence of statement
250 * @return the statements that were parsed, or `null` if the tokens do not rep resent a
251 * recognizable sequence of statements
252 */
253 List<Statement> parseStatements(Token token) {
254 InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engi ne.Parser.parseStatements");
255 try {
256 _currentToken = token;
257 return parseStatements2();
258 } finally {
259 instrumentation.log();
260 }
261 }
262 void set currentToken(Token currentToken) {
263 this._currentToken = currentToken;
264 }
265
266 /**
267 * Advance to the next token in the token stream.
268 */
269 void advance() {
270 _currentToken = _currentToken.next;
271 }
272
273 /**
274 * Append the character equivalent of the given scalar value to the given buil der. Use the start
275 * and end indices to report an error, and don't append anything to the builde r, if the scalar
276 * value is invalid.
277 *
278 * @param builder the builder to which the scalar value is to be appended
279 * @param escapeSequence the escape sequence that was parsed to produce the sc alar value
280 * @param scalarValue the value to be appended
281 * @param startIndex the index of the first character representing the scalar value
282 * @param endIndex the index of the last character representing the scalar val ue
283 */
284 void appendScalarValue(JavaStringBuilder builder, String escapeSequence, int s calarValue, int startIndex, int endIndex) {
285 if (scalarValue < 0 || scalarValue > Character.MAX_CODE_POINT || (scalarValu e >= 0xD800 && scalarValue <= 0xDFFF)) {
286 reportError8(ParserErrorCode.INVALID_CODE_POINT, [escapeSequence]);
287 return;
288 }
289 if (scalarValue < Character.MAX_VALUE) {
290 builder.appendChar(scalarValue as int);
291 } else {
292 builder.append(Character.toChars(scalarValue));
293 }
294 }
295
296 /**
297 * Compute the content of a string with the given literal representation.
298 *
299 * @param lexeme the literal representation of the string
300 * @param first `true` if this is the first token in a string literal
301 * @param last `true` if this is the last token in a string literal
302 * @return the actual value of the string
303 */
304 String computeStringValue(String lexeme, bool first, bool last) {
305 bool isRaw = false;
306 int start = 0;
307 if (first) {
308 if (lexeme.startsWith("r\"\"\"") || lexeme.startsWith("r'''")) {
309 isRaw = true;
310 start += 4;
311 } else if (lexeme.startsWith("r\"") || lexeme.startsWith("r'")) {
312 isRaw = true;
313 start += 2;
314 } else if (lexeme.startsWith("\"\"\"") || lexeme.startsWith("'''")) {
315 start += 3;
316 } else if (lexeme.startsWith("\"") || lexeme.startsWith("'")) {
317 start += 1;
318 }
319 }
320 int end = lexeme.length;
321 if (last) {
322 if (lexeme.endsWith("\"\"\"") || lexeme.endsWith("'''")) {
323 end -= 3;
324 } else if (lexeme.endsWith("\"") || lexeme.endsWith("'")) {
325 end -= 1;
326 }
327 }
328 if (end - start + 1 < 0) {
329 AnalysisEngine.instance.logger.logError("Internal error: computeStringValu e(${lexeme}, ${first}, ${last})");
330 return "";
331 }
332 if (isRaw) {
333 return lexeme.substring(start, end);
334 }
335 JavaStringBuilder builder = new JavaStringBuilder();
336 int index = start;
337 while (index < end) {
338 index = translateCharacter(builder, lexeme, index);
339 }
340 return builder.toString();
341 }
342
343 /**
344 * Convert the given method declaration into the nearest valid top-level funct ion declaration.
345 *
346 * @param method the method to be converted
347 * @return the function declaration that most closely captures the components of the given method
348 * declaration
349 */
350 FunctionDeclaration convertToFunctionDeclaration(MethodDeclaration method) => new FunctionDeclaration.full(method.documentationComment, method.metadata, metho d.externalKeyword, method.returnType, method.propertyKeyword, method.name, new F unctionExpression.full(method.parameters, method.body));
351
352 /**
353 * Return `true` if the current token could be the start of a compilation unit member. This
354 * method is used for recovery purposes to decide when to stop skipping tokens after finding an
355 * error while parsing a compilation unit member.
356 *
357 * @return `true` if the current token could be the start of a compilation uni t member
358 */
359 bool couldBeStartOfCompilationUnitMember() {
360 if ((matches(Keyword.IMPORT) || matches(Keyword.EXPORT) || matches(Keyword.L IBRARY) || matches(Keyword.PART)) && !matches4(peek(), TokenType.PERIOD) && !mat ches4(peek(), TokenType.LT)) {
361 return true;
362 } else if (matches(Keyword.CLASS)) {
363 return true;
364 } else if (matches(Keyword.TYPEDEF) && !matches4(peek(), TokenType.PERIOD) & & !matches4(peek(), TokenType.LT)) {
365 return true;
366 } else if (matches(Keyword.VOID) || ((matches(Keyword.GET) || matches(Keywor d.SET)) && matchesIdentifier2(peek())) || (matches(Keyword.OPERATOR) && isOperat or(peek()))) {
367 return true;
368 } else if (matchesIdentifier()) {
369 if (matches4(peek(), TokenType.OPEN_PAREN)) {
370 return true;
371 }
372 Token token = skipReturnType(_currentToken);
373 if (token == null) {
374 return false;
375 }
376 if (matches(Keyword.GET) || matches(Keyword.SET) || (matches(Keyword.OPERA TOR) && isOperator(peek())) || matchesIdentifier()) {
377 return true;
378 }
379 }
380 return false;
381 }
382
383 /**
384 * Create a synthetic identifier.
385 *
386 * @return the synthetic identifier that was created
387 */
388 SimpleIdentifier createSyntheticIdentifier() => new SimpleIdentifier.full(crea teSyntheticToken2(TokenType.IDENTIFIER));
389
390 /**
391 * Create a synthetic string literal.
392 *
393 * @return the synthetic string literal that was created
394 */
395 SimpleStringLiteral createSyntheticStringLiteral() => new SimpleStringLiteral. full(createSyntheticToken2(TokenType.STRING), "");
396
397 /**
398 * Create a synthetic token representing the given keyword.
399 *
400 * @return the synthetic token that was created
401 */
402 Token createSyntheticToken(Keyword keyword) => new Parser_SyntheticKeywordToke n(keyword, _currentToken.offset);
403
404 /**
405 * Create a synthetic token with the given type.
406 *
407 * @return the synthetic token that was created
408 */
409 Token createSyntheticToken2(TokenType type) => new StringToken(type, "", _curr entToken.offset);
410
411 /**
412 * Check that the given expression is assignable and report an error if it isn 't.
413 *
414 * <pre>
415 * assignableExpression ::=
416 * primary (arguments* assignableSelector)+
417 * | 'super' assignableSelector
418 * | identifier
419 *
420 * assignableSelector ::=
421 * '[' expression ']'
422 * | '.' identifier
423 * </pre>
424 *
425 * @param expression the expression being checked
426 */
427 void ensureAssignable(Expression expression) {
428 if (expression != null && !expression.isAssignable) {
429 reportError8(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, []);
430 }
431 }
432
433 /**
434 * If the current token is a keyword matching the given string, return it afte r advancing to the
435 * next token. Otherwise report an error and return the current token without advancing.
436 *
437 * @param keyword the keyword that is expected
438 * @return the token that matched the given type
439 */
440 Token expect(Keyword keyword) {
441 if (matches(keyword)) {
442 return andAdvance;
443 }
444 reportError8(ParserErrorCode.EXPECTED_TOKEN, [keyword.syntax]);
445 return _currentToken;
446 }
447
448 /**
449 * If the current token has the expected type, return it after advancing to th e next token.
450 * Otherwise report an error and return the current token without advancing.
451 *
452 * @param type the type of token that is expected
453 * @return the token that matched the given type
454 */
455 Token expect2(TokenType type) {
456 if (matches5(type)) {
457 return andAdvance;
458 }
459 if (identical(type, TokenType.SEMICOLON)) {
460 reportError9(ParserErrorCode.EXPECTED_TOKEN, _currentToken.previous, [type .lexeme]);
461 } else {
462 reportError8(ParserErrorCode.EXPECTED_TOKEN, [type.lexeme]);
463 }
464 return _currentToken;
465 }
466
467 /**
468 * Search the given list of ranges for a range that contains the given index. Return the range
469 * that was found, or `null` if none of the ranges contain the index.
470 *
471 * @param ranges the ranges to be searched
472 * @param index the index contained in the returned range
473 * @return the range that was found
474 */
475 List<int> findRange(List<List<int>> ranges, int index) {
476 for (List<int> range in ranges) {
477 if (range[0] <= index && index <= range[1]) {
478 return range;
479 } else if (index < range[0]) {
480 return null;
481 }
482 }
483 return null;
484 }
485 void gatherTodoComments(Token token) {
486 while (token != null && token.type != TokenType.EOF) {
487 Token commentToken = token.precedingComments;
488 while (commentToken != null) {
489 if (identical(commentToken.type, TokenType.SINGLE_LINE_COMMENT) || ident ical(commentToken.type, TokenType.MULTI_LINE_COMMENT)) {
490 scrapeTodoComment(commentToken);
491 }
492 commentToken = commentToken.next;
493 }
494 token = token.next;
495 }
496 }
497
498 /**
499 * Advance to the next token in the token stream, making it the new current to ken.
500 *
501 * @return the token that was current before this method was invoked
502 */
503 Token get andAdvance {
504 Token token = _currentToken;
505 advance();
506 return token;
507 }
508
509 /**
510 * Return a list of the ranges of characters in the given comment string that should be treated as
511 * code blocks.
512 *
513 * @param comment the comment being processed
514 * @return the ranges of characters that should be treated as code blocks
515 */
516 List<List<int>> getCodeBlockRanges(String comment) {
517 List<List<int>> ranges = new List<List<int>>();
518 int length = comment.length;
519 int index = 0;
520 if (comment.startsWith("/**") || comment.startsWith("///")) {
521 index = 3;
522 }
523 while (index < length) {
524 int currentChar = comment.codeUnitAt(index);
525 if (currentChar == 0xD || currentChar == 0xA) {
526 index = index + 1;
527 while (index < length && Character.isWhitespace(comment.codeUnitAt(index ))) {
528 index = index + 1;
529 }
530 if (JavaString.startsWithBefore(comment, "* ", index)) {
531 int end = index + 6;
532 while (end < length && comment.codeUnitAt(end) != 0xD && comment.codeU nitAt(end) != 0xA) {
533 end = end + 1;
534 }
535 ranges.add(<int> [index, end]);
536 index = end;
537 }
538 } else if (JavaString.startsWithBefore(comment, "[:", index)) {
539 int end = JavaString.indexOf(comment, ":]", index + 2);
540 if (end < 0) {
541 end = length;
542 }
543 ranges.add(<int> [index, end]);
544 index = end + 1;
545 } else {
546 index = index + 1;
547 }
548 }
549 return ranges;
550 }
551
552 /**
553 * Return the end token associated with the given begin token, or `null` if ei ther the given
554 * token is not a begin token or it does not have an end token associated with it.
555 *
556 * @param beginToken the token that is expected to have an end token associate d with it
557 * @return the end token associated with the begin token
558 */
559 Token getEndToken(Token beginToken) {
560 if (beginToken is BeginToken) {
561 return ((beginToken as BeginToken)).endToken;
562 }
563 return null;
564 }
565
566 /**
567 * Return `true` if the current token is the first token of a return type that is followed
568 * by an identifier, possibly followed by a list of type parameters, followed by a
569 * left-parenthesis. This is used by parseTypeAlias to determine whether or no t to parse a return
570 * type.
571 *
572 * @return `true` if we can successfully parse the rest of a type alias if we first parse a
573 * return type.
574 */
575 bool hasReturnTypeInTypeAlias() {
576 Token next = skipReturnType(_currentToken);
577 if (next == null) {
578 return false;
579 }
580 return matchesIdentifier2(next);
581 }
582
583 /**
584 * Return `true` if the current token appears to be the beginning of a functio n declaration.
585 *
586 * @return `true` if the current token appears to be the beginning of a functi on declaration
587 */
588 bool isFunctionDeclaration() {
589 if (matches(Keyword.VOID)) {
590 return true;
591 }
592 Token afterReturnType = skipTypeName(_currentToken);
593 if (afterReturnType == null) {
594 afterReturnType = _currentToken;
595 }
596 Token afterIdentifier = skipSimpleIdentifier(afterReturnType);
597 if (afterIdentifier == null) {
598 afterIdentifier = skipSimpleIdentifier(_currentToken);
599 }
600 if (afterIdentifier == null) {
601 return false;
602 }
603 if (isFunctionExpression(afterIdentifier)) {
604 return true;
605 }
606 if (matches(Keyword.GET)) {
607 Token afterName = skipSimpleIdentifier(_currentToken.next);
608 if (afterName == null) {
609 return false;
610 }
611 return matches4(afterName, TokenType.FUNCTION) || matches4(afterName, Toke nType.OPEN_CURLY_BRACKET);
612 }
613 return false;
614 }
615
616 /**
617 * Return `true` if the given token appears to be the beginning of a function expression.
618 *
619 * @param startToken the token that might be the start of a function expressio n
620 * @return `true` if the given token appears to be the beginning of a function expression
621 */
622 bool isFunctionExpression(Token startToken) {
623 Token afterParameters = skipFormalParameterList(startToken);
624 if (afterParameters == null) {
625 return false;
626 }
627 return matchesAny(afterParameters, [TokenType.OPEN_CURLY_BRACKET, TokenType. FUNCTION]);
628 }
629
630 /**
631 * Return `true` if the given character is a valid hexadecimal digit.
632 *
633 * @param character the character being tested
634 * @return `true` if the character is a valid hexadecimal digit
635 */
636 bool isHexDigit(int character) => (0x30 <= character && character <= 0x39) || (0x41 <= character && character <= 0x46) || (0x61 <= character && character <= 0 x66);
637
638 /**
639 * Return `true` if the current token is the first token in an initialized var iable
640 * declaration rather than an expression. This method assumes that we have alr eady skipped past
641 * any metadata that might be associated with the declaration.
642 *
643 * <pre>
644 * initializedVariableDeclaration ::=
645 * declaredIdentifier ('=' expression)? (',' initializedIdentifier)*
646 *
647 * declaredIdentifier ::=
648 * metadata finalConstVarOrType identifier
649 *
650 * finalConstVarOrType ::=
651 * 'final' type?
652 * | 'const' type?
653 * | 'var'
654 * | type
655 *
656 * type ::=
657 * qualified typeArguments?
658 *
659 * initializedIdentifier ::=
660 * identifier ('=' expression)?
661 * </pre>
662 *
663 * @return `true` if the current token is the first token in an initialized va riable
664 * declaration
665 */
666 bool isInitializedVariableDeclaration() {
667 if (matches(Keyword.FINAL) || matches(Keyword.VAR)) {
668 return true;
669 }
670 if (matches(Keyword.CONST)) {
671 return !matchesAny(peek(), [
672 TokenType.LT,
673 TokenType.OPEN_CURLY_BRACKET,
674 TokenType.OPEN_SQUARE_BRACKET,
675 TokenType.INDEX]);
676 }
677 Token token = skipTypeName(_currentToken);
678 if (token == null) {
679 return false;
680 }
681 token = skipSimpleIdentifier(token);
682 if (token == null) {
683 return false;
684 }
685 TokenType type = token.type;
686 return identical(type, TokenType.EQ) || identical(type, TokenType.COMMA) || identical(type, TokenType.SEMICOLON) || matches3(token, Keyword.IN);
687 }
688
689 /**
690 * Given that we have just found bracketed text within a comment, look to see whether that text is
691 * (a) followed by a parenthesized link address, (b) followed by a colon, or ( c) followed by
692 * optional whitespace and another square bracket.
693 *
694 * This method uses the syntax described by the <a
695 * href="http://daringfireball.net/projects/markdown/syntax">markdown</a> proj ect.
696 *
697 * @param comment the comment text in which the bracketed text was found
698 * @param rightIndex the index of the right bracket
699 * @return `true` if the bracketed text is followed by a link address
700 */
701 bool isLinkText(String comment, int rightIndex) {
702 int length = comment.length;
703 int index = rightIndex + 1;
704 if (index >= length) {
705 return false;
706 }
707 int nextChar = comment.codeUnitAt(index);
708 if (nextChar == 0x28 || nextChar == 0x3A) {
709 return true;
710 }
711 while (Character.isWhitespace(nextChar)) {
712 index = index + 1;
713 if (index >= length) {
714 return false;
715 }
716 nextChar = comment.codeUnitAt(index);
717 }
718 return nextChar == 0x5B;
719 }
720
721 /**
722 * Return `true` if the given token appears to be the beginning of an operator declaration.
723 *
724 * @param startToken the token that might be the start of an operator declarat ion
725 * @return `true` if the given token appears to be the beginning of an operato r declaration
726 */
727 bool isOperator(Token startToken) {
728 if (startToken.isOperator) {
729 Token token = startToken.next;
730 while (token.isOperator) {
731 token = token.next;
732 }
733 return matches4(token, TokenType.OPEN_PAREN);
734 }
735 return false;
736 }
737
738 /**
739 * Return `true` if the current token appears to be the beginning of a switch member.
740 *
741 * @return `true` if the current token appears to be the beginning of a switch member
742 */
743 bool isSwitchMember() {
744 Token token = _currentToken;
745 while (matches4(token, TokenType.IDENTIFIER) && matches4(token.next, TokenTy pe.COLON)) {
746 token = token.next.next;
747 }
748 if (identical(token.type, TokenType.KEYWORD)) {
749 Keyword keyword = ((token as KeywordToken)).keyword;
750 return identical(keyword, Keyword.CASE) || identical(keyword, Keyword.DEFA ULT);
751 }
752 return false;
753 }
754
755 /**
756 * Return `true` if the given token appears to be the first token of a type na me that is
757 * followed by a variable or field formal parameter.
758 *
759 * @param startToken the first token of the sequence being checked
760 * @return `true` if there is a type name and variable starting at the given t oken
761 */
762 bool isTypedIdentifier(Token startToken) {
763 Token token = skipReturnType(startToken);
764 if (token == null) {
765 return false;
766 } else if (matchesIdentifier2(token)) {
767 return true;
768 } else if (matches3(token, Keyword.THIS) && matches4(token.next, TokenType.P ERIOD) && matchesIdentifier2(token.next.next)) {
769 return true;
770 }
771 return false;
772 }
773
774 /**
775 * Compare the given tokens to find the token that appears first in the source being parsed. That
776 * is, return the left-most of all of the tokens. The arguments are allowed to be `null`.
777 * Return the token with the smallest offset, or `null` if there are no argume nts or if all
778 * of the arguments are `null`.
779 *
780 * @param tokens the tokens being compared
781 * @return the token with the smallest offset
782 */
783 Token lexicallyFirst(List<Token> tokens) {
784 Token first = null;
785 int firstOffset = 2147483647;
786 for (Token token in tokens) {
787 if (token != null) {
788 int offset = token.offset;
789 if (offset < firstOffset) {
790 first = token;
791 firstOffset = offset;
792 }
793 }
794 }
795 return first;
796 }
797
798 /**
799 * Return `true` if the current token matches the given keyword.
800 *
801 * @param keyword the keyword that can optionally appear in the current locati on
802 * @return `true` if the current token matches the given keyword
803 */
804 bool matches(Keyword keyword) => matches3(_currentToken, keyword);
805
806 /**
807 * Return `true` if the current token matches the given identifier.
808 *
809 * @param identifier the identifier that can optionally appear in the current location
810 * @return `true` if the current token matches the given identifier
811 */
812 bool matches2(String identifier) => identical(_currentToken.type, TokenType.ID ENTIFIER) && _currentToken.lexeme == identifier;
813
814 /**
815 * Return `true` if the given token matches the given keyword.
816 *
817 * @param token the token being tested
818 * @param keyword the keyword that is being tested for
819 * @return `true` if the given token matches the given keyword
820 */
821 bool matches3(Token token, Keyword keyword) => identical(token.type, TokenType .KEYWORD) && identical(((token as KeywordToken)).keyword, keyword);
822
823 /**
824 * Return `true` if the given token has the given type.
825 *
826 * @param token the token being tested
827 * @param type the type of token that is being tested for
828 * @return `true` if the given token has the given type
829 */
830 bool matches4(Token token, TokenType type) => identical(token.type, type);
831
832 /**
833 * Return `true` if the current token has the given type. Note that this metho d, unlike
834 * other variants, will modify the token stream if possible to match a wider r ange of tokens. In
835 * particular, if we are attempting to match a '>' and the next token is eithe r a '>>' or '>>>',
836 * the token stream will be re-written and `true` will be returned.
837 *
838 * @param type the type of token that can optionally appear in the current loc ation
839 * @return `true` if the current token has the given type
840 */
841 bool matches5(TokenType type) {
842 TokenType currentType = _currentToken.type;
843 if (currentType != type) {
844 if (identical(type, TokenType.GT)) {
845 if (identical(currentType, TokenType.GT_GT)) {
846 int offset = _currentToken.offset;
847 Token first = new Token(TokenType.GT, offset);
848 Token second = new Token(TokenType.GT, offset + 1);
849 second.setNext(_currentToken.next);
850 first.setNext(second);
851 _currentToken.previous.setNext(first);
852 _currentToken = first;
853 return true;
854 } else if (identical(currentType, TokenType.GT_EQ)) {
855 int offset = _currentToken.offset;
856 Token first = new Token(TokenType.GT, offset);
857 Token second = new Token(TokenType.EQ, offset + 1);
858 second.setNext(_currentToken.next);
859 first.setNext(second);
860 _currentToken.previous.setNext(first);
861 _currentToken = first;
862 return true;
863 } else if (identical(currentType, TokenType.GT_GT_EQ)) {
864 int offset = _currentToken.offset;
865 Token first = new Token(TokenType.GT, offset);
866 Token second = new Token(TokenType.GT, offset + 1);
867 Token third = new Token(TokenType.EQ, offset + 2);
868 third.setNext(_currentToken.next);
869 second.setNext(third);
870 first.setNext(second);
871 _currentToken.previous.setNext(first);
872 _currentToken = first;
873 return true;
874 }
875 }
876 return false;
877 }
878 return true;
879 }
880
881 /**
882 * Return `true` if the given token has any one of the given types.
883 *
884 * @param token the token being tested
885 * @param types the types of token that are being tested for
886 * @return `true` if the given token has any of the given types
887 */
888 bool matchesAny(Token token, List<TokenType> types) {
889 TokenType actualType = token.type;
890 for (TokenType type in types) {
891 if (identical(actualType, type)) {
892 return true;
893 }
894 }
895 return false;
896 }
897
898 /**
899 * Return `true` if the current token is a valid identifier. Valid identifiers include
900 * built-in identifiers (pseudo-keywords).
901 *
902 * @return `true` if the current token is a valid identifier
903 */
904 bool matchesIdentifier() => matchesIdentifier2(_currentToken);
905
906 /**
907 * Return `true` if the given token is a valid identifier. Valid identifiers i nclude
908 * built-in identifiers (pseudo-keywords).
909 *
910 * @return `true` if the given token is a valid identifier
911 */
912 bool matchesIdentifier2(Token token) => matches4(token, TokenType.IDENTIFIER) || (matches4(token, TokenType.KEYWORD) && ((token as KeywordToken)).keyword.isPs eudoKeyword);
913
914 /**
915 * If the current token has the given type, then advance to the next token and return `true`
916 * . Otherwise, return `false` without advancing.
917 *
918 * @param type the type of token that can optionally appear in the current loc ation
919 * @return `true` if the current token has the given type
920 */
921 bool optional(TokenType type) {
922 if (matches5(type)) {
923 advance();
924 return true;
925 }
926 return false;
927 }
928
929 /**
930 * Parse an additive expression.
931 *
932 * <pre>
933 * additiveExpression ::=
934 * multiplicativeExpression (additiveOperator multiplicativeExpression)*
935 * | 'super' (additiveOperator multiplicativeExpression)+
936 * </pre>
937 *
938 * @return the additive expression that was parsed
939 */
940 Expression parseAdditiveExpression() {
941 Expression expression;
942 if (matches(Keyword.SUPER) && _currentToken.next.type.isAdditiveOperator) {
943 expression = new SuperExpression.full(andAdvance);
944 } else {
945 expression = parseMultiplicativeExpression();
946 }
947 while (_currentToken.type.isAdditiveOperator) {
948 Token operator = andAdvance;
949 expression = new BinaryExpression.full(expression, operator, parseMultipli cativeExpression());
950 }
951 return expression;
952 }
953
954 /**
955 * Parse an annotation.
956 *
957 * <pre>
958 * annotation ::=
959 * '@' qualified ('.' identifier)? arguments?
960 * </pre>
961 *
962 * @return the annotation that was parsed
963 */
964 Annotation parseAnnotation() {
965 Token atSign = expect2(TokenType.AT);
966 Identifier name = parsePrefixedIdentifier();
967 Token period = null;
968 SimpleIdentifier constructorName = null;
969 if (matches5(TokenType.PERIOD)) {
970 period = andAdvance;
971 constructorName = parseSimpleIdentifier();
972 }
973 ArgumentList arguments = null;
974 if (matches5(TokenType.OPEN_PAREN)) {
975 arguments = parseArgumentList();
976 }
977 return new Annotation.full(atSign, name, period, constructorName, arguments) ;
978 }
979
980 /**
981 * Parse an argument.
982 *
983 * <pre>
984 * argument ::=
985 * namedArgument
986 * | expression
987 *
988 * namedArgument ::=
989 * label expression
990 * </pre>
991 *
992 * @return the argument that was parsed
993 */
994 Expression parseArgument() {
995 if (matchesIdentifier() && matches4(peek(), TokenType.COLON)) {
996 SimpleIdentifier label = new SimpleIdentifier.full(andAdvance);
997 Label name = new Label.full(label, andAdvance);
998 return new NamedExpression.full(name, parseExpression2());
999 } else {
1000 return parseExpression2();
1001 }
1002 }
1003
1004 /**
1005 * Parse an argument definition test.
1006 *
1007 * <pre>
1008 * argumentDefinitionTest ::=
1009 * '?' identifier
1010 * </pre>
1011 *
1012 * @return the argument definition test that was parsed
1013 */
1014 ArgumentDefinitionTest parseArgumentDefinitionTest() {
1015 Token question = expect2(TokenType.QUESTION);
1016 SimpleIdentifier identifier = parseSimpleIdentifier();
1017 reportError9(ParserErrorCode.DEPRECATED_ARGUMENT_DEFINITION_TEST, question, []);
1018 return new ArgumentDefinitionTest.full(question, identifier);
1019 }
1020
1021 /**
1022 * Parse a list of arguments.
1023 *
1024 * <pre>
1025 * arguments ::=
1026 * '(' argumentList? ')'
1027 *
1028 * argumentList ::=
1029 * namedArgument (',' namedArgument)*
1030 * | expressionList (',' namedArgument)*
1031 * </pre>
1032 *
1033 * @return the argument list that was parsed
1034 */
1035 ArgumentList parseArgumentList() {
1036 Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
1037 List<Expression> arguments = new List<Expression>();
1038 if (matches5(TokenType.CLOSE_PAREN)) {
1039 return new ArgumentList.full(leftParenthesis, arguments, andAdvance);
1040 }
1041 Expression argument = parseArgument();
1042 arguments.add(argument);
1043 bool foundNamedArgument = argument is NamedExpression;
1044 bool generatedError = false;
1045 while (optional(TokenType.COMMA)) {
1046 argument = parseArgument();
1047 arguments.add(argument);
1048 if (foundNamedArgument) {
1049 if (!generatedError && argument is! NamedExpression) {
1050 reportError8(ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT, []);
1051 generatedError = true;
1052 }
1053 } else if (argument is NamedExpression) {
1054 foundNamedArgument = true;
1055 }
1056 }
1057 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
1058 return new ArgumentList.full(leftParenthesis, arguments, rightParenthesis);
1059 }
1060
1061 /**
1062 * Parse an assert statement.
1063 *
1064 * <pre>
1065 * assertStatement ::=
1066 * 'assert' '(' conditionalExpression ')' ';'
1067 * </pre>
1068 *
1069 * @return the assert statement
1070 */
1071 AssertStatement parseAssertStatement() {
1072 Token keyword = expect(Keyword.ASSERT);
1073 Token leftParen = expect2(TokenType.OPEN_PAREN);
1074 Expression expression = parseExpression2();
1075 if (expression is AssignmentExpression) {
1076 reportError(ParserErrorCode.ASSERT_DOES_NOT_TAKE_ASSIGNMENT, expression, [ ]);
1077 } else if (expression is CascadeExpression) {
1078 reportError(ParserErrorCode.ASSERT_DOES_NOT_TAKE_CASCADE, expression, []);
1079 } else if (expression is ThrowExpression) {
1080 reportError(ParserErrorCode.ASSERT_DOES_NOT_TAKE_THROW, expression, []);
1081 } else if (expression is RethrowExpression) {
1082 reportError(ParserErrorCode.ASSERT_DOES_NOT_TAKE_RETHROW, expression, []);
1083 }
1084 Token rightParen = expect2(TokenType.CLOSE_PAREN);
1085 Token semicolon = expect2(TokenType.SEMICOLON);
1086 return new AssertStatement.full(keyword, leftParen, expression, rightParen, semicolon);
1087 }
1088
1089 /**
1090 * Parse an assignable expression.
1091 *
1092 * <pre>
1093 * assignableExpression ::=
1094 * primary (arguments* assignableSelector)+
1095 * | 'super' assignableSelector
1096 * | identifier
1097 * </pre>
1098 *
1099 * @param primaryAllowed `true` if the expression is allowed to be a primary w ithout any
1100 * assignable selector
1101 * @return the assignable expression that was parsed
1102 */
1103 Expression parseAssignableExpression(bool primaryAllowed) {
1104 if (matches(Keyword.SUPER)) {
1105 return parseAssignableSelector(new SuperExpression.full(andAdvance), false );
1106 }
1107 Expression expression = parsePrimaryExpression();
1108 bool isOptional = primaryAllowed || expression is SimpleIdentifier;
1109 while (true) {
1110 while (matches5(TokenType.OPEN_PAREN)) {
1111 ArgumentList argumentList = parseArgumentList();
1112 if (expression is SimpleIdentifier) {
1113 expression = new MethodInvocation.full(null, null, expression as Simpl eIdentifier, argumentList);
1114 } else if (expression is PrefixedIdentifier) {
1115 PrefixedIdentifier identifier = expression as PrefixedIdentifier;
1116 expression = new MethodInvocation.full(identifier.prefix, identifier.p eriod, identifier.identifier, argumentList);
1117 } else if (expression is PropertyAccess) {
1118 PropertyAccess access = expression as PropertyAccess;
1119 expression = new MethodInvocation.full(access.target, access.operator, access.propertyName, argumentList);
1120 } else {
1121 expression = new FunctionExpressionInvocation.full(expression, argumen tList);
1122 }
1123 if (!primaryAllowed) {
1124 isOptional = false;
1125 }
1126 }
1127 Expression selectorExpression = parseAssignableSelector(expression, isOpti onal || (expression is PrefixedIdentifier));
1128 if (identical(selectorExpression, expression)) {
1129 if (!isOptional && (expression is PrefixedIdentifier)) {
1130 PrefixedIdentifier identifier = expression as PrefixedIdentifier;
1131 expression = new PropertyAccess.full(identifier.prefix, identifier.per iod, identifier.identifier);
1132 }
1133 return expression;
1134 }
1135 expression = selectorExpression;
1136 isOptional = true;
1137 }
1138 }
1139
1140 /**
1141 * Parse an assignable selector.
1142 *
1143 * <pre>
1144 * assignableSelector ::=
1145 * '[' expression ']'
1146 * | '.' identifier
1147 * </pre>
1148 *
1149 * @param prefix the expression preceding the selector
1150 * @param optional `true` if the selector is optional
1151 * @return the assignable selector that was parsed
1152 */
1153 Expression parseAssignableSelector(Expression prefix, bool optional) {
1154 if (matches5(TokenType.OPEN_SQUARE_BRACKET)) {
1155 Token leftBracket = andAdvance;
1156 Expression index = parseExpression2();
1157 Token rightBracket = expect2(TokenType.CLOSE_SQUARE_BRACKET);
1158 return new IndexExpression.forTarget_full(prefix, leftBracket, index, righ tBracket);
1159 } else if (matches5(TokenType.PERIOD)) {
1160 Token period = andAdvance;
1161 return new PropertyAccess.full(prefix, period, parseSimpleIdentifier());
1162 } else {
1163 if (!optional) {
1164 reportError8(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, []);
1165 }
1166 return prefix;
1167 }
1168 }
1169
1170 /**
1171 * Parse a bitwise and expression.
1172 *
1173 * <pre>
1174 * bitwiseAndExpression ::=
1175 * shiftExpression ('&' shiftExpression)*
1176 * | 'super' ('&' shiftExpression)+
1177 * </pre>
1178 *
1179 * @return the bitwise and expression that was parsed
1180 */
1181 Expression parseBitwiseAndExpression() {
1182 Expression expression;
1183 if (matches(Keyword.SUPER) && matches4(peek(), TokenType.AMPERSAND)) {
1184 expression = new SuperExpression.full(andAdvance);
1185 } else {
1186 expression = parseShiftExpression();
1187 }
1188 while (matches5(TokenType.AMPERSAND)) {
1189 Token operator = andAdvance;
1190 expression = new BinaryExpression.full(expression, operator, parseShiftExp ression());
1191 }
1192 return expression;
1193 }
1194
1195 /**
1196 * Parse a bitwise or expression.
1197 *
1198 * <pre>
1199 * bitwiseOrExpression ::=
1200 * bitwiseXorExpression ('|' bitwiseXorExpression)*
1201 * | 'super' ('|' bitwiseXorExpression)+
1202 * </pre>
1203 *
1204 * @return the bitwise or expression that was parsed
1205 */
1206 Expression parseBitwiseOrExpression() {
1207 Expression expression;
1208 if (matches(Keyword.SUPER) && matches4(peek(), TokenType.BAR)) {
1209 expression = new SuperExpression.full(andAdvance);
1210 } else {
1211 expression = parseBitwiseXorExpression();
1212 }
1213 while (matches5(TokenType.BAR)) {
1214 Token operator = andAdvance;
1215 expression = new BinaryExpression.full(expression, operator, parseBitwiseX orExpression());
1216 }
1217 return expression;
1218 }
1219
1220 /**
1221 * Parse a bitwise exclusive-or expression.
1222 *
1223 * <pre>
1224 * bitwiseXorExpression ::=
1225 * bitwiseAndExpression ('^' bitwiseAndExpression)*
1226 * | 'super' ('^' bitwiseAndExpression)+
1227 * </pre>
1228 *
1229 * @return the bitwise exclusive-or expression that was parsed
1230 */
1231 Expression parseBitwiseXorExpression() {
1232 Expression expression;
1233 if (matches(Keyword.SUPER) && matches4(peek(), TokenType.CARET)) {
1234 expression = new SuperExpression.full(andAdvance);
1235 } else {
1236 expression = parseBitwiseAndExpression();
1237 }
1238 while (matches5(TokenType.CARET)) {
1239 Token operator = andAdvance;
1240 expression = new BinaryExpression.full(expression, operator, parseBitwiseA ndExpression());
1241 }
1242 return expression;
1243 }
1244
1245 /**
1246 * Parse a block.
1247 *
1248 * <pre>
1249 * block ::=
1250 * '{' statements '}'
1251 * </pre>
1252 *
1253 * @return the block that was parsed
1254 */
1255 Block parseBlock() {
1256 Token leftBracket = expect2(TokenType.OPEN_CURLY_BRACKET);
1257 List<Statement> statements = new List<Statement>();
1258 Token statementStart = _currentToken;
1259 while (!matches5(TokenType.EOF) && !matches5(TokenType.CLOSE_CURLY_BRACKET)) {
1260 Statement statement = parseStatement2();
1261 if (statement != null) {
1262 statements.add(statement);
1263 }
1264 if (identical(_currentToken, statementStart)) {
1265 reportError9(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_currentT oken.lexeme]);
1266 advance();
1267 }
1268 statementStart = _currentToken;
1269 }
1270 Token rightBracket = expect2(TokenType.CLOSE_CURLY_BRACKET);
1271 return new Block.full(leftBracket, statements, rightBracket);
1272 }
1273
1274 /**
1275 * Parse a break statement.
1276 *
1277 * <pre>
1278 * breakStatement ::=
1279 * 'break' identifier? ';'
1280 * </pre>
1281 *
1282 * @return the break statement that was parsed
1283 */
1284 Statement parseBreakStatement() {
1285 Token breakKeyword = expect(Keyword.BREAK);
1286 SimpleIdentifier label = null;
1287 if (matchesIdentifier()) {
1288 label = parseSimpleIdentifier();
1289 }
1290 if (!_inLoop && !_inSwitch && label == null) {
1291 reportError9(ParserErrorCode.BREAK_OUTSIDE_OF_LOOP, breakKeyword, []);
1292 }
1293 Token semicolon = expect2(TokenType.SEMICOLON);
1294 return new BreakStatement.full(breakKeyword, label, semicolon);
1295 }
1296
1297 /**
1298 * Parse a cascade section.
1299 *
1300 * <pre>
1301 * cascadeSection ::=
1302 * '..' (cascadeSelector arguments*) (assignableSelector arguments*)* casc adeAssignment?
1303 *
1304 * cascadeSelector ::=
1305 * '[' expression ']'
1306 * | identifier
1307 *
1308 * cascadeAssignment ::=
1309 * assignmentOperator expressionWithoutCascade
1310 * </pre>
1311 *
1312 * @return the expression representing the cascaded method invocation
1313 */
1314 Expression parseCascadeSection() {
1315 Token period = expect2(TokenType.PERIOD_PERIOD);
1316 Expression expression = null;
1317 SimpleIdentifier functionName = null;
1318 if (matchesIdentifier()) {
1319 functionName = parseSimpleIdentifier();
1320 } else if (identical(_currentToken.type, TokenType.OPEN_SQUARE_BRACKET)) {
1321 Token leftBracket = andAdvance;
1322 Expression index = parseExpression2();
1323 Token rightBracket = expect2(TokenType.CLOSE_SQUARE_BRACKET);
1324 expression = new IndexExpression.forCascade_full(period, leftBracket, inde x, rightBracket);
1325 period = null;
1326 } else {
1327 reportError9(ParserErrorCode.MISSING_IDENTIFIER, _currentToken, [_currentT oken.lexeme]);
1328 functionName = createSyntheticIdentifier();
1329 }
1330 if (identical(_currentToken.type, TokenType.OPEN_PAREN)) {
1331 while (identical(_currentToken.type, TokenType.OPEN_PAREN)) {
1332 if (functionName != null) {
1333 expression = new MethodInvocation.full(expression, period, functionNam e, parseArgumentList());
1334 period = null;
1335 functionName = null;
1336 } else if (expression == null) {
1337 expression = new MethodInvocation.full(expression, period, createSynth eticIdentifier(), parseArgumentList());
1338 } else {
1339 expression = new FunctionExpressionInvocation.full(expression, parseAr gumentList());
1340 }
1341 }
1342 } else if (functionName != null) {
1343 expression = new PropertyAccess.full(expression, period, functionName);
1344 period = null;
1345 }
1346 bool progress = true;
1347 while (progress) {
1348 progress = false;
1349 Expression selector = parseAssignableSelector(expression, true);
1350 if (selector != expression) {
1351 expression = selector;
1352 progress = true;
1353 while (identical(_currentToken.type, TokenType.OPEN_PAREN)) {
1354 expression = new FunctionExpressionInvocation.full(expression, parseAr gumentList());
1355 }
1356 }
1357 }
1358 if (_currentToken.type.isAssignmentOperator) {
1359 Token operator = andAdvance;
1360 ensureAssignable(expression);
1361 expression = new AssignmentExpression.full(expression, operator, parseExpr essionWithoutCascade());
1362 }
1363 return expression;
1364 }
1365
1366 /**
1367 * Parse a class declaration.
1368 *
1369 * <pre>
1370 * classDeclaration ::=
1371 * metadata 'abstract'? 'class' name typeParameterList? (extendsClause wit hClause?)? implementsClause? '{' classMembers '}' |
1372 * metadata 'abstract'? 'class' mixinApplicationClass
1373 * </pre>
1374 *
1375 * @param commentAndMetadata the metadata to be associated with the member
1376 * @param abstractKeyword the token for the keyword 'abstract', or `null` if t he keyword was
1377 * not given
1378 * @return the class declaration that was parsed
1379 */
1380 CompilationUnitMember parseClassDeclaration(CommentAndMetadata commentAndMetad ata, Token abstractKeyword) {
1381 Token keyword = expect(Keyword.CLASS);
1382 if (matchesIdentifier()) {
1383 Token next = peek();
1384 if (matches4(next, TokenType.LT)) {
1385 next = skipTypeParameterList(next);
1386 if (next != null && matches4(next, TokenType.EQ)) {
1387 return parseClassTypeAlias(commentAndMetadata, keyword);
1388 }
1389 } else if (matches4(next, TokenType.EQ)) {
1390 return parseClassTypeAlias(commentAndMetadata, keyword);
1391 }
1392 }
1393 SimpleIdentifier name = parseSimpleIdentifier();
1394 String className = name.name;
1395 TypeParameterList typeParameters = null;
1396 if (matches5(TokenType.LT)) {
1397 typeParameters = parseTypeParameterList();
1398 }
1399 ExtendsClause extendsClause = null;
1400 WithClause withClause = null;
1401 ImplementsClause implementsClause = null;
1402 bool foundClause = true;
1403 while (foundClause) {
1404 if (matches(Keyword.EXTENDS)) {
1405 if (extendsClause == null) {
1406 extendsClause = parseExtendsClause();
1407 if (withClause != null) {
1408 reportError9(ParserErrorCode.WITH_BEFORE_EXTENDS, withClause.withKey word, []);
1409 } else if (implementsClause != null) {
1410 reportError9(ParserErrorCode.IMPLEMENTS_BEFORE_EXTENDS, implementsCl ause.keyword, []);
1411 }
1412 } else {
1413 reportError9(ParserErrorCode.MULTIPLE_EXTENDS_CLAUSES, extendsClause.k eyword, []);
1414 parseExtendsClause();
1415 }
1416 } else if (matches(Keyword.WITH)) {
1417 if (withClause == null) {
1418 withClause = parseWithClause();
1419 if (implementsClause != null) {
1420 reportError9(ParserErrorCode.IMPLEMENTS_BEFORE_WITH, implementsClaus e.keyword, []);
1421 }
1422 } else {
1423 reportError9(ParserErrorCode.MULTIPLE_WITH_CLAUSES, withClause.withKey word, []);
1424 parseWithClause();
1425 }
1426 } else if (matches(Keyword.IMPLEMENTS)) {
1427 if (implementsClause == null) {
1428 implementsClause = parseImplementsClause();
1429 } else {
1430 reportError9(ParserErrorCode.MULTIPLE_IMPLEMENTS_CLAUSES, implementsCl ause.keyword, []);
1431 parseImplementsClause();
1432 }
1433 } else {
1434 foundClause = false;
1435 }
1436 }
1437 if (withClause != null && extendsClause == null) {
1438 reportError9(ParserErrorCode.WITH_WITHOUT_EXTENDS, withClause.withKeyword, []);
1439 }
1440 NativeClause nativeClause = null;
1441 if (matches2(_NATIVE) && matches4(peek(), TokenType.STRING)) {
1442 nativeClause = parseNativeClause();
1443 }
1444 Token leftBracket = null;
1445 List<ClassMember> members = null;
1446 Token rightBracket = null;
1447 if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
1448 leftBracket = expect2(TokenType.OPEN_CURLY_BRACKET);
1449 members = parseClassMembers(className, getEndToken(leftBracket));
1450 rightBracket = expect2(TokenType.CLOSE_CURLY_BRACKET);
1451 } else {
1452 leftBracket = createSyntheticToken2(TokenType.OPEN_CURLY_BRACKET);
1453 rightBracket = createSyntheticToken2(TokenType.CLOSE_CURLY_BRACKET);
1454 reportError8(ParserErrorCode.MISSING_CLASS_BODY, []);
1455 }
1456 ClassDeclaration classDeclaration = new ClassDeclaration.full(commentAndMeta data.comment, commentAndMetadata.metadata, abstractKeyword, keyword, name, typeP arameters, extendsClause, withClause, implementsClause, leftBracket, members, ri ghtBracket);
1457 classDeclaration.nativeClause = nativeClause;
1458 return classDeclaration;
1459 }
1460
1461 /**
1462 * Parse a class member.
1463 *
1464 * <pre>
1465 * classMemberDefinition ::=
1466 * declaration ';'
1467 * | methodSignature functionBody
1468 * </pre>
1469 *
1470 * @param className the name of the class containing the member being parsed
1471 * @return the class member that was parsed, or `null` if what was found was n ot a valid
1472 * class member
1473 */
1474 ClassMember parseClassMember(String className) {
1475 CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
1476 Modifiers modifiers = parseModifiers();
1477 if (matches(Keyword.VOID)) {
1478 TypeName returnType = parseReturnType();
1479 if (matches(Keyword.GET) && matchesIdentifier2(peek())) {
1480 validateModifiersForGetterOrSetterOrMethod(modifiers);
1481 return parseGetter(commentAndMetadata, modifiers.externalKeyword, modifi ers.staticKeyword, returnType);
1482 } else if (matches(Keyword.SET) && matchesIdentifier2(peek())) {
1483 validateModifiersForGetterOrSetterOrMethod(modifiers);
1484 return parseSetter(commentAndMetadata, modifiers.externalKeyword, modifi ers.staticKeyword, returnType);
1485 } else if (matches(Keyword.OPERATOR) && isOperator(peek())) {
1486 validateModifiersForOperator(modifiers);
1487 return parseOperator(commentAndMetadata, modifiers.externalKeyword, retu rnType);
1488 } else if (matchesIdentifier() && matchesAny(peek(), [
1489 TokenType.OPEN_PAREN,
1490 TokenType.OPEN_CURLY_BRACKET,
1491 TokenType.FUNCTION])) {
1492 validateModifiersForGetterOrSetterOrMethod(modifiers);
1493 return parseMethodDeclaration(commentAndMetadata, modifiers.externalKeyw ord, modifiers.staticKeyword, returnType);
1494 } else {
1495 if (matchesIdentifier()) {
1496 if (matchesAny(peek(), [TokenType.EQ, TokenType.COMMA, TokenType.SEMIC OLON])) {
1497 reportError(ParserErrorCode.VOID_VARIABLE, returnType, []);
1498 return parseInitializedIdentifierList(commentAndMetadata, modifiers. staticKeyword, validateModifiersForField(modifiers), returnType);
1499 }
1500 }
1501 if (isOperator(_currentToken)) {
1502 validateModifiersForOperator(modifiers);
1503 return parseOperator(commentAndMetadata, modifiers.externalKeyword, re turnType);
1504 }
1505 reportError9(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken, []);
1506 return null;
1507 }
1508 } else if (matches(Keyword.GET) && matchesIdentifier2(peek())) {
1509 validateModifiersForGetterOrSetterOrMethod(modifiers);
1510 return parseGetter(commentAndMetadata, modifiers.externalKeyword, modifier s.staticKeyword, null);
1511 } else if (matches(Keyword.SET) && matchesIdentifier2(peek())) {
1512 validateModifiersForGetterOrSetterOrMethod(modifiers);
1513 return parseSetter(commentAndMetadata, modifiers.externalKeyword, modifier s.staticKeyword, null);
1514 } else if (matches(Keyword.OPERATOR) && isOperator(peek())) {
1515 validateModifiersForOperator(modifiers);
1516 return parseOperator(commentAndMetadata, modifiers.externalKeyword, null);
1517 } else if (!matchesIdentifier()) {
1518 if (isOperator(_currentToken)) {
1519 validateModifiersForOperator(modifiers);
1520 return parseOperator(commentAndMetadata, modifiers.externalKeyword, null );
1521 }
1522 reportError9(ParserErrorCode.EXPECTED_CLASS_MEMBER, _currentToken, []);
1523 return null;
1524 } else if (matches4(peek(), TokenType.PERIOD) && matchesIdentifier2(peek2(2) ) && matches4(peek2(3), TokenType.OPEN_PAREN)) {
1525 return parseConstructor(commentAndMetadata, modifiers.externalKeyword, val idateModifiersForConstructor(modifiers), modifiers.factoryKeyword, parseSimpleId entifier(), andAdvance, parseSimpleIdentifier(), parseFormalParameterList());
1526 } else if (matches4(peek(), TokenType.OPEN_PAREN)) {
1527 SimpleIdentifier methodName = parseSimpleIdentifier();
1528 FormalParameterList parameters = parseFormalParameterList();
1529 if (matches5(TokenType.COLON) || modifiers.factoryKeyword != null || metho dName.name == className) {
1530 return parseConstructor(commentAndMetadata, modifiers.externalKeyword, v alidateModifiersForConstructor(modifiers), modifiers.factoryKeyword, methodName, null, null, parameters);
1531 }
1532 validateModifiersForGetterOrSetterOrMethod(modifiers);
1533 validateFormalParameterList(parameters);
1534 return parseMethodDeclaration2(commentAndMetadata, modifiers.externalKeywo rd, modifiers.staticKeyword, null, methodName, parameters);
1535 } else if (matchesAny(peek(), [TokenType.EQ, TokenType.COMMA, TokenType.SEMI COLON])) {
1536 if (modifiers.constKeyword == null && modifiers.finalKeyword == null && mo difiers.varKeyword == null) {
1537 reportError8(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, []);
1538 }
1539 return parseInitializedIdentifierList(commentAndMetadata, modifiers.static Keyword, validateModifiersForField(modifiers), null);
1540 }
1541 TypeName type = parseTypeName();
1542 if (matches(Keyword.GET) && matchesIdentifier2(peek())) {
1543 validateModifiersForGetterOrSetterOrMethod(modifiers);
1544 return parseGetter(commentAndMetadata, modifiers.externalKeyword, modifier s.staticKeyword, type);
1545 } else if (matches(Keyword.SET) && matchesIdentifier2(peek())) {
1546 validateModifiersForGetterOrSetterOrMethod(modifiers);
1547 return parseSetter(commentAndMetadata, modifiers.externalKeyword, modifier s.staticKeyword, type);
1548 } else if (matches(Keyword.OPERATOR) && isOperator(peek())) {
1549 validateModifiersForOperator(modifiers);
1550 return parseOperator(commentAndMetadata, modifiers.externalKeyword, type);
1551 } else if (!matchesIdentifier()) {
1552 if (matches5(TokenType.CLOSE_CURLY_BRACKET)) {
1553 return parseInitializedIdentifierList(commentAndMetadata, modifiers.stat icKeyword, validateModifiersForField(modifiers), type);
1554 }
1555 if (isOperator(_currentToken)) {
1556 validateModifiersForOperator(modifiers);
1557 return parseOperator(commentAndMetadata, modifiers.externalKeyword, type );
1558 }
1559 reportError9(ParserErrorCode.EXPECTED_CLASS_MEMBER, _currentToken, []);
1560 return null;
1561 } else if (matches4(peek(), TokenType.OPEN_PAREN)) {
1562 SimpleIdentifier methodName = parseSimpleIdentifier();
1563 FormalParameterList parameters = parseFormalParameterList();
1564 if (methodName.name == className) {
1565 reportError(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, type, []);
1566 return parseConstructor(commentAndMetadata, modifiers.externalKeyword, v alidateModifiersForConstructor(modifiers), modifiers.factoryKeyword, methodName, null, null, parameters);
1567 }
1568 validateModifiersForGetterOrSetterOrMethod(modifiers);
1569 validateFormalParameterList(parameters);
1570 return parseMethodDeclaration2(commentAndMetadata, modifiers.externalKeywo rd, modifiers.staticKeyword, type, methodName, parameters);
1571 }
1572 return parseInitializedIdentifierList(commentAndMetadata, modifiers.staticKe yword, validateModifiersForField(modifiers), type);
1573 }
1574
1575 /**
1576 * Parse a list of class members.
1577 *
1578 * <pre>
1579 * classMembers ::=
1580 * (metadata memberDefinition)*
1581 * </pre>
1582 *
1583 * @param className the name of the class whose members are being parsed
1584 * @param closingBracket the closing bracket for the class, or `null` if the c losing bracket
1585 * is missing
1586 * @return the list of class members that were parsed
1587 */
1588 List<ClassMember> parseClassMembers(String className, Token closingBracket) {
1589 List<ClassMember> members = new List<ClassMember>();
1590 Token memberStart = _currentToken;
1591 while (!matches5(TokenType.EOF) && !matches5(TokenType.CLOSE_CURLY_BRACKET) && (closingBracket != null || (!matches(Keyword.CLASS) && !matches(Keyword.TYPED EF)))) {
1592 if (matches5(TokenType.SEMICOLON)) {
1593 reportError9(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_currentT oken.lexeme]);
1594 advance();
1595 } else {
1596 ClassMember member = parseClassMember(className);
1597 if (member != null) {
1598 members.add(member);
1599 }
1600 }
1601 if (identical(_currentToken, memberStart)) {
1602 reportError9(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_currentT oken.lexeme]);
1603 advance();
1604 }
1605 memberStart = _currentToken;
1606 }
1607 return members;
1608 }
1609
1610 /**
1611 * Parse a class type alias.
1612 *
1613 * <pre>
1614 * classTypeAlias ::=
1615 * identifier typeParameters? '=' 'abstract'? mixinApplication
1616 *
1617 * mixinApplication ::=
1618 * type withClause implementsClause? ';'
1619 * </pre>
1620 *
1621 * @param commentAndMetadata the metadata to be associated with the member
1622 * @param keyword the token representing the 'typedef' keyword
1623 * @return the class type alias that was parsed
1624 */
1625 ClassTypeAlias parseClassTypeAlias(CommentAndMetadata commentAndMetadata, Toke n keyword) {
1626 SimpleIdentifier className = parseSimpleIdentifier();
1627 TypeParameterList typeParameters = null;
1628 if (matches5(TokenType.LT)) {
1629 typeParameters = parseTypeParameterList();
1630 }
1631 Token equals = expect2(TokenType.EQ);
1632 Token abstractKeyword = null;
1633 if (matches(Keyword.ABSTRACT)) {
1634 abstractKeyword = andAdvance;
1635 }
1636 TypeName superclass = parseTypeName();
1637 WithClause withClause = null;
1638 if (matches(Keyword.WITH)) {
1639 withClause = parseWithClause();
1640 }
1641 ImplementsClause implementsClause = null;
1642 if (matches(Keyword.IMPLEMENTS)) {
1643 implementsClause = parseImplementsClause();
1644 }
1645 Token semicolon;
1646 if (matches5(TokenType.SEMICOLON)) {
1647 semicolon = andAdvance;
1648 } else {
1649 if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
1650 reportError8(ParserErrorCode.EXPECTED_TOKEN, [TokenType.SEMICOLON.lexeme ]);
1651 Token leftBracket = andAdvance;
1652 parseClassMembers(className.name, getEndToken(leftBracket));
1653 expect2(TokenType.CLOSE_CURLY_BRACKET);
1654 } else {
1655 reportError9(ParserErrorCode.EXPECTED_TOKEN, _currentToken.previous, [To kenType.SEMICOLON.lexeme]);
1656 }
1657 semicolon = createSyntheticToken2(TokenType.SEMICOLON);
1658 }
1659 return new ClassTypeAlias.full(commentAndMetadata.comment, commentAndMetadat a.metadata, keyword, className, typeParameters, equals, abstractKeyword, supercl ass, withClause, implementsClause, semicolon);
1660 }
1661
1662 /**
1663 * Parse a list of combinators in a directive.
1664 *
1665 * <pre>
1666 * combinator ::=
1667 * 'show' identifier (',' identifier)*
1668 * | 'hide' identifier (',' identifier)*
1669 * </pre>
1670 *
1671 * @return the combinators that were parsed
1672 */
1673 List<Combinator> parseCombinators() {
1674 List<Combinator> combinators = new List<Combinator>();
1675 while (matches2(_SHOW) || matches2(_HIDE)) {
1676 Token keyword = expect2(TokenType.IDENTIFIER);
1677 if (keyword.lexeme == _SHOW) {
1678 List<SimpleIdentifier> shownNames = parseIdentifierList();
1679 combinators.add(new ShowCombinator.full(keyword, shownNames));
1680 } else {
1681 List<SimpleIdentifier> hiddenNames = parseIdentifierList();
1682 combinators.add(new HideCombinator.full(keyword, hiddenNames));
1683 }
1684 }
1685 return combinators;
1686 }
1687
1688 /**
1689 * Parse the documentation comment and metadata preceding a declaration. This method allows any
1690 * number of documentation comments to occur before, after or between the meta data, but only
1691 * returns the last (right-most) documentation comment that is found.
1692 *
1693 * <pre>
1694 * metadata ::=
1695 * annotation*
1696 * </pre>
1697 *
1698 * @return the documentation comment and metadata that were parsed
1699 */
1700 CommentAndMetadata parseCommentAndMetadata() {
1701 Comment comment = parseDocumentationComment();
1702 List<Annotation> metadata = new List<Annotation>();
1703 while (matches5(TokenType.AT)) {
1704 metadata.add(parseAnnotation());
1705 Comment optionalComment = parseDocumentationComment();
1706 if (optionalComment != null) {
1707 comment = optionalComment;
1708 }
1709 }
1710 return new CommentAndMetadata(comment, metadata);
1711 }
1712
1713 /**
1714 * Parse a comment reference from the source between square brackets.
1715 *
1716 * <pre>
1717 * commentReference ::=
1718 * 'new'? prefixedIdentifier
1719 * </pre>
1720 *
1721 * @param referenceSource the source occurring between the square brackets wit hin a documentation
1722 * comment
1723 * @param sourceOffset the offset of the first character of the reference sour ce
1724 * @return the comment reference that was parsed, or `null` if no reference co uld be found
1725 */
1726 CommentReference parseCommentReference(String referenceSource, int sourceOffse t) {
1727 if (referenceSource.length == 0) {
1728 return null;
1729 }
1730 try {
1731 List<bool> errorFound = [false];
1732 AnalysisErrorListener listener = new AnalysisErrorListener_15(errorFound);
1733 Scanner scanner = new Scanner(null, new SubSequenceReader(new CharSequence (referenceSource), sourceOffset), listener);
1734 scanner.setSourceStart(1, 1);
1735 Token firstToken = scanner.tokenize();
1736 if (errorFound[0]) {
1737 return null;
1738 }
1739 Token newKeyword = null;
1740 if (matches3(firstToken, Keyword.NEW)) {
1741 newKeyword = firstToken;
1742 firstToken = firstToken.next;
1743 }
1744 if (matchesIdentifier2(firstToken)) {
1745 Token secondToken = firstToken.next;
1746 Token thirdToken = secondToken.next;
1747 Token nextToken;
1748 Identifier identifier;
1749 if (matches4(secondToken, TokenType.PERIOD) && matchesIdentifier2(thirdT oken)) {
1750 identifier = new PrefixedIdentifier.full(new SimpleIdentifier.full(fir stToken), secondToken, new SimpleIdentifier.full(thirdToken));
1751 nextToken = thirdToken.next;
1752 } else {
1753 identifier = new SimpleIdentifier.full(firstToken);
1754 nextToken = firstToken.next;
1755 }
1756 if (nextToken.type != TokenType.EOF) {
1757 return null;
1758 }
1759 return new CommentReference.full(newKeyword, identifier);
1760 } else if (matches3(firstToken, Keyword.THIS) || matches3(firstToken, Keyw ord.NULL) || matches3(firstToken, Keyword.TRUE) || matches3(firstToken, Keyword. FALSE)) {
1761 return null;
1762 }
1763 } on JavaException catch (exception) {
1764 }
1765 return null;
1766 }
1767
1768 /**
1769 * Parse all of the comment references occurring in the given array of documen tation comments.
1770 *
1771 * <pre>
1772 * commentReference ::=
1773 * '[' 'new'? qualified ']' libraryReference?
1774 *
1775 * libraryReference ::=
1776 * '(' stringLiteral ')'
1777 * </pre>
1778 *
1779 * @param tokens the comment tokens representing the documentation comments to be parsed
1780 * @return the comment references that were parsed
1781 */
1782 List<CommentReference> parseCommentReferences(List<Token> tokens) {
1783 List<CommentReference> references = new List<CommentReference>();
1784 for (Token token in tokens) {
1785 String comment = token.lexeme;
1786 int length = comment.length;
1787 List<List<int>> codeBlockRanges = getCodeBlockRanges(comment);
1788 int leftIndex = comment.indexOf('[');
1789 while (leftIndex >= 0 && leftIndex + 1 < length) {
1790 List<int> range = findRange(codeBlockRanges, leftIndex);
1791 if (range == null) {
1792 int rightIndex = JavaString.indexOf(comment, ']', leftIndex);
1793 if (rightIndex >= 0) {
1794 int firstChar = comment.codeUnitAt(leftIndex + 1);
1795 if (firstChar != 0x27 && firstChar != 0x22) {
1796 if (isLinkText(comment, rightIndex)) {
1797 } else {
1798 CommentReference reference = parseCommentReference(comment.subst ring(leftIndex + 1, rightIndex), token.offset + leftIndex + 1);
1799 if (reference != null) {
1800 references.add(reference);
1801 }
1802 }
1803 }
1804 } else {
1805 rightIndex = leftIndex + 1;
1806 }
1807 leftIndex = JavaString.indexOf(comment, '[', rightIndex);
1808 } else {
1809 leftIndex = JavaString.indexOf(comment, '[', range[1] + 1);
1810 }
1811 }
1812 }
1813 return references;
1814 }
1815
1816 /**
1817 * Parse a compilation unit.
1818 *
1819 * Specified:
1820 *
1821 * <pre>
1822 * compilationUnit ::=
1823 * scriptTag? directive* topLevelDeclaration*
1824 * </pre>
1825 * Actual:
1826 *
1827 * <pre>
1828 * compilationUnit ::=
1829 * scriptTag? topLevelElement*
1830 *
1831 * topLevelElement ::=
1832 * directive
1833 * | topLevelDeclaration
1834 * </pre>
1835 *
1836 * @return the compilation unit that was parsed
1837 */
1838 CompilationUnit parseCompilationUnit2() {
1839 Token firstToken = _currentToken;
1840 ScriptTag scriptTag = null;
1841 if (matches5(TokenType.SCRIPT_TAG)) {
1842 scriptTag = new ScriptTag.full(andAdvance);
1843 }
1844 bool libraryDirectiveFound = false;
1845 bool partOfDirectiveFound = false;
1846 bool partDirectiveFound = false;
1847 bool directiveFoundAfterDeclaration = false;
1848 List<Directive> directives = new List<Directive>();
1849 List<CompilationUnitMember> declarations = new List<CompilationUnitMember>() ;
1850 Token memberStart = _currentToken;
1851 while (!matches5(TokenType.EOF)) {
1852 CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
1853 if ((matches(Keyword.IMPORT) || matches(Keyword.EXPORT) || matches(Keyword .LIBRARY) || matches(Keyword.PART)) && !matches4(peek(), TokenType.PERIOD) && !m atches4(peek(), TokenType.LT)) {
1854 Directive directive = parseDirective(commentAndMetadata);
1855 if (declarations.length > 0 && !directiveFoundAfterDeclaration) {
1856 reportError8(ParserErrorCode.DIRECTIVE_AFTER_DECLARATION, []);
1857 directiveFoundAfterDeclaration = true;
1858 }
1859 if (directive is LibraryDirective) {
1860 if (libraryDirectiveFound) {
1861 reportError8(ParserErrorCode.MULTIPLE_LIBRARY_DIRECTIVES, []);
1862 } else {
1863 if (directives.length > 0) {
1864 reportError8(ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST, []);
1865 }
1866 libraryDirectiveFound = true;
1867 }
1868 } else if (directive is PartDirective) {
1869 partDirectiveFound = true;
1870 } else if (partDirectiveFound) {
1871 if (directive is ExportDirective) {
1872 reportError9(ParserErrorCode.EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE, ((directive as NamespaceDirective)).keyword, []);
1873 } else if (directive is ImportDirective) {
1874 reportError9(ParserErrorCode.IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE, ((directive as NamespaceDirective)).keyword, []);
1875 }
1876 }
1877 if (directive is PartOfDirective) {
1878 if (partOfDirectiveFound) {
1879 reportError8(ParserErrorCode.MULTIPLE_PART_OF_DIRECTIVES, []);
1880 } else {
1881 for (Directive precedingDirective in directives) {
1882 reportError9(ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART, preced ingDirective.keyword, []);
1883 }
1884 partOfDirectiveFound = true;
1885 }
1886 } else {
1887 if (partOfDirectiveFound) {
1888 reportError9(ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART, directiv e.keyword, []);
1889 }
1890 }
1891 directives.add(directive);
1892 } else if (matches5(TokenType.SEMICOLON)) {
1893 reportError9(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_currentT oken.lexeme]);
1894 advance();
1895 } else {
1896 CompilationUnitMember member = parseCompilationUnitMember(commentAndMeta data);
1897 if (member != null) {
1898 declarations.add(member);
1899 }
1900 }
1901 if (identical(_currentToken, memberStart)) {
1902 reportError9(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_currentT oken.lexeme]);
1903 advance();
1904 while (!matches5(TokenType.EOF) && !couldBeStartOfCompilationUnitMember( )) {
1905 advance();
1906 }
1907 }
1908 memberStart = _currentToken;
1909 }
1910 return new CompilationUnit.full(firstToken, scriptTag, directives, declarati ons, _currentToken);
1911 }
1912
1913 /**
1914 * Parse a compilation unit member.
1915 *
1916 * <pre>
1917 * compilationUnitMember ::=
1918 * classDefinition
1919 * | functionTypeAlias
1920 * | external functionSignature
1921 * | external getterSignature
1922 * | external setterSignature
1923 * | functionSignature functionBody
1924 * | returnType? getOrSet identifier formalParameterList functionBody
1925 * | (final | const) type? staticFinalDeclarationList ';'
1926 * | variableDeclaration ';'
1927 * </pre>
1928 *
1929 * @param commentAndMetadata the metadata to be associated with the member
1930 * @return the compilation unit member that was parsed, or `null` if what was parsed could
1931 * not be represented as a compilation unit member
1932 */
1933 CompilationUnitMember parseCompilationUnitMember(CommentAndMetadata commentAnd Metadata) {
1934 Modifiers modifiers = parseModifiers();
1935 if (matches(Keyword.CLASS)) {
1936 return parseClassDeclaration(commentAndMetadata, validateModifiersForClass (modifiers));
1937 } else if (matches(Keyword.TYPEDEF) && !matches4(peek(), TokenType.PERIOD) & & !matches4(peek(), TokenType.LT)) {
1938 validateModifiersForTypedef(modifiers);
1939 return parseTypeAlias(commentAndMetadata);
1940 }
1941 if (matches(Keyword.VOID)) {
1942 TypeName returnType = parseReturnType();
1943 if ((matches(Keyword.GET) || matches(Keyword.SET)) && matchesIdentifier2(p eek())) {
1944 validateModifiersForTopLevelFunction(modifiers);
1945 return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKe yword, null);
1946 } else if (matches(Keyword.OPERATOR) && isOperator(peek())) {
1947 reportError9(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken, []);
1948 return convertToFunctionDeclaration(parseOperator(commentAndMetadata, mo difiers.externalKeyword, returnType));
1949 } else if (matchesIdentifier() && matchesAny(peek(), [
1950 TokenType.OPEN_PAREN,
1951 TokenType.OPEN_CURLY_BRACKET,
1952 TokenType.FUNCTION])) {
1953 validateModifiersForTopLevelFunction(modifiers);
1954 return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKe yword, returnType);
1955 } else {
1956 if (matchesIdentifier()) {
1957 if (matchesAny(peek(), [TokenType.EQ, TokenType.COMMA, TokenType.SEMIC OLON])) {
1958 reportError(ParserErrorCode.VOID_VARIABLE, returnType, []);
1959 return new TopLevelVariableDeclaration.full(commentAndMetadata.comme nt, commentAndMetadata.metadata, parseVariableDeclarationList2(null, validateMod ifiersForTopLevelVariable(modifiers), null), expect2(TokenType.SEMICOLON));
1960 }
1961 }
1962 reportError9(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken, []);
1963 return null;
1964 }
1965 } else if ((matches(Keyword.GET) || matches(Keyword.SET)) && matchesIdentifi er2(peek())) {
1966 validateModifiersForTopLevelFunction(modifiers);
1967 return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKeyw ord, null);
1968 } else if (matches(Keyword.OPERATOR) && isOperator(peek())) {
1969 reportError9(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken, []);
1970 return convertToFunctionDeclaration(parseOperator(commentAndMetadata, modi fiers.externalKeyword, null));
1971 } else if (!matchesIdentifier()) {
1972 reportError9(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken, []);
1973 return null;
1974 } else if (matches4(peek(), TokenType.OPEN_PAREN)) {
1975 validateModifiersForTopLevelFunction(modifiers);
1976 return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKeyw ord, null);
1977 } else if (matchesAny(peek(), [TokenType.EQ, TokenType.COMMA, TokenType.SEMI COLON])) {
1978 if (modifiers.constKeyword == null && modifiers.finalKeyword == null && mo difiers.varKeyword == null) {
1979 reportError8(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, []);
1980 }
1981 return new TopLevelVariableDeclaration.full(commentAndMetadata.comment, co mmentAndMetadata.metadata, parseVariableDeclarationList2(null, validateModifiers ForTopLevelVariable(modifiers), null), expect2(TokenType.SEMICOLON));
1982 }
1983 TypeName returnType = parseReturnType();
1984 if ((matches(Keyword.GET) || matches(Keyword.SET)) && matchesIdentifier2(pee k())) {
1985 validateModifiersForTopLevelFunction(modifiers);
1986 return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKeyw ord, returnType);
1987 } else if (matches(Keyword.OPERATOR) && isOperator(peek())) {
1988 reportError9(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken, []);
1989 return convertToFunctionDeclaration(parseOperator(commentAndMetadata, modi fiers.externalKeyword, returnType));
1990 } else if (matches5(TokenType.AT)) {
1991 return new TopLevelVariableDeclaration.full(commentAndMetadata.comment, co mmentAndMetadata.metadata, parseVariableDeclarationList2(null, validateModifiers ForTopLevelVariable(modifiers), returnType), expect2(TokenType.SEMICOLON));
1992 } else if (!matchesIdentifier()) {
1993 reportError9(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken, []);
1994 Token semicolon;
1995 if (matches5(TokenType.SEMICOLON)) {
1996 semicolon = andAdvance;
1997 } else {
1998 semicolon = createSyntheticToken2(TokenType.SEMICOLON);
1999 }
2000 List<VariableDeclaration> variables = new List<VariableDeclaration>();
2001 variables.add(new VariableDeclaration.full(null, null, createSyntheticIden tifier(), null, null));
2002 return new TopLevelVariableDeclaration.full(commentAndMetadata.comment, co mmentAndMetadata.metadata, new VariableDeclarationList.full(null, null, null, re turnType, variables), semicolon);
2003 }
2004 if (matchesAny(peek(), [
2005 TokenType.OPEN_PAREN,
2006 TokenType.FUNCTION,
2007 TokenType.OPEN_CURLY_BRACKET])) {
2008 validateModifiersForTopLevelFunction(modifiers);
2009 return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKeyw ord, returnType);
2010 }
2011 return new TopLevelVariableDeclaration.full(commentAndMetadata.comment, comm entAndMetadata.metadata, parseVariableDeclarationList2(null, validateModifiersFo rTopLevelVariable(modifiers), returnType), expect2(TokenType.SEMICOLON));
2012 }
2013
2014 /**
2015 * Parse a conditional expression.
2016 *
2017 * <pre>
2018 * conditionalExpression ::=
2019 * logicalOrExpression ('?' expressionWithoutCascade ':' expressionWithout Cascade)?
2020 * </pre>
2021 *
2022 * @return the conditional expression that was parsed
2023 */
2024 Expression parseConditionalExpression() {
2025 Expression condition = parseLogicalOrExpression();
2026 if (!matches5(TokenType.QUESTION)) {
2027 return condition;
2028 }
2029 Token question = andAdvance;
2030 Expression thenExpression = parseExpressionWithoutCascade();
2031 Token colon = expect2(TokenType.COLON);
2032 Expression elseExpression = parseExpressionWithoutCascade();
2033 return new ConditionalExpression.full(condition, question, thenExpression, c olon, elseExpression);
2034 }
2035
2036 /**
2037 * Parse a const expression.
2038 *
2039 * <pre>
2040 * constExpression ::=
2041 * instanceCreationExpression
2042 * | listLiteral
2043 * | mapLiteral
2044 * </pre>
2045 *
2046 * @return the const expression that was parsed
2047 */
2048 Expression parseConstExpression() {
2049 Token keyword = expect(Keyword.CONST);
2050 if (matches5(TokenType.OPEN_SQUARE_BRACKET) || matches5(TokenType.INDEX)) {
2051 return parseListLiteral(keyword, null);
2052 } else if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
2053 return parseMapLiteral(keyword, null);
2054 } else if (matches5(TokenType.LT)) {
2055 return parseListOrMapLiteral(keyword);
2056 }
2057 return parseInstanceCreationExpression(keyword);
2058 }
2059 ConstructorDeclaration parseConstructor(CommentAndMetadata commentAndMetadata, Token externalKeyword, Token constKeyword, Token factoryKeyword, SimpleIdentifi er returnType, Token period, SimpleIdentifier name, FormalParameterList paramete rs) {
2060 bool bodyAllowed = externalKeyword == null;
2061 Token separator = null;
2062 List<ConstructorInitializer> initializers = null;
2063 if (matches5(TokenType.COLON)) {
2064 separator = andAdvance;
2065 initializers = new List<ConstructorInitializer>();
2066 do {
2067 if (matches(Keyword.THIS)) {
2068 if (matches4(peek(), TokenType.OPEN_PAREN)) {
2069 bodyAllowed = false;
2070 initializers.add(parseRedirectingConstructorInvocation());
2071 } else if (matches4(peek(), TokenType.PERIOD) && matches4(peek2(3), To kenType.OPEN_PAREN)) {
2072 bodyAllowed = false;
2073 initializers.add(parseRedirectingConstructorInvocation());
2074 } else {
2075 initializers.add(parseConstructorFieldInitializer());
2076 }
2077 } else if (matches(Keyword.SUPER)) {
2078 initializers.add(parseSuperConstructorInvocation());
2079 } else {
2080 initializers.add(parseConstructorFieldInitializer());
2081 }
2082 } while (optional(TokenType.COMMA));
2083 }
2084 ConstructorName redirectedConstructor = null;
2085 FunctionBody body;
2086 if (matches5(TokenType.EQ)) {
2087 separator = andAdvance;
2088 redirectedConstructor = parseConstructorName();
2089 body = new EmptyFunctionBody.full(expect2(TokenType.SEMICOLON));
2090 if (factoryKeyword == null) {
2091 reportError(ParserErrorCode.REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR, redi rectedConstructor, []);
2092 }
2093 } else {
2094 body = parseFunctionBody(true, ParserErrorCode.MISSING_FUNCTION_BODY, fals e);
2095 if (constKeyword != null && factoryKeyword != null) {
2096 reportError9(ParserErrorCode.CONST_FACTORY, factoryKeyword, []);
2097 } else if (body is EmptyFunctionBody) {
2098 if (factoryKeyword != null && externalKeyword == null) {
2099 reportError9(ParserErrorCode.FACTORY_WITHOUT_BODY, factoryKeyword, []) ;
2100 }
2101 } else {
2102 if (constKeyword != null) {
2103 reportError(ParserErrorCode.CONST_CONSTRUCTOR_WITH_BODY, body, []);
2104 } else if (!bodyAllowed) {
2105 reportError(ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_BODY, body, []);
2106 }
2107 }
2108 }
2109 return new ConstructorDeclaration.full(commentAndMetadata.comment, commentAn dMetadata.metadata, externalKeyword, constKeyword, factoryKeyword, returnType, p eriod, name, parameters, separator, initializers, redirectedConstructor, body);
2110 }
2111
2112 /**
2113 * Parse a field initializer within a constructor.
2114 *
2115 * <pre>
2116 * fieldInitializer:
2117 * ('this' '.')? identifier '=' conditionalExpression cascadeSection*
2118 * </pre>
2119 *
2120 * @return the field initializer that was parsed
2121 */
2122 ConstructorFieldInitializer parseConstructorFieldInitializer() {
2123 Token keyword = null;
2124 Token period = null;
2125 if (matches(Keyword.THIS)) {
2126 keyword = andAdvance;
2127 period = expect2(TokenType.PERIOD);
2128 }
2129 SimpleIdentifier fieldName = parseSimpleIdentifier();
2130 Token equals = expect2(TokenType.EQ);
2131 Expression expression = parseConditionalExpression();
2132 TokenType tokenType = _currentToken.type;
2133 if (identical(tokenType, TokenType.PERIOD_PERIOD)) {
2134 List<Expression> cascadeSections = new List<Expression>();
2135 while (identical(tokenType, TokenType.PERIOD_PERIOD)) {
2136 Expression section = parseCascadeSection();
2137 if (section != null) {
2138 cascadeSections.add(section);
2139 }
2140 tokenType = _currentToken.type;
2141 }
2142 expression = new CascadeExpression.full(expression, cascadeSections);
2143 }
2144 return new ConstructorFieldInitializer.full(keyword, period, fieldName, equa ls, expression);
2145 }
2146
2147 /**
2148 * Parse the name of a constructor.
2149 *
2150 * <pre>
2151 * constructorName:
2152 * type ('.' identifier)?
2153 * </pre>
2154 *
2155 * @return the constructor name that was parsed
2156 */
2157 ConstructorName parseConstructorName() {
2158 TypeName type = parseTypeName();
2159 Token period = null;
2160 SimpleIdentifier name = null;
2161 if (matches5(TokenType.PERIOD)) {
2162 period = andAdvance;
2163 name = parseSimpleIdentifier();
2164 }
2165 return new ConstructorName.full(type, period, name);
2166 }
2167
2168 /**
2169 * Parse a continue statement.
2170 *
2171 * <pre>
2172 * continueStatement ::=
2173 * 'continue' identifier? ';'
2174 * </pre>
2175 *
2176 * @return the continue statement that was parsed
2177 */
2178 Statement parseContinueStatement() {
2179 Token continueKeyword = expect(Keyword.CONTINUE);
2180 if (!_inLoop && !_inSwitch) {
2181 reportError9(ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP, continueKeyword, [] );
2182 }
2183 SimpleIdentifier label = null;
2184 if (matchesIdentifier()) {
2185 label = parseSimpleIdentifier();
2186 }
2187 if (_inSwitch && !_inLoop && label == null) {
2188 reportError9(ParserErrorCode.CONTINUE_WITHOUT_LABEL_IN_CASE, continueKeywo rd, []);
2189 }
2190 Token semicolon = expect2(TokenType.SEMICOLON);
2191 return new ContinueStatement.full(continueKeyword, label, semicolon);
2192 }
2193
2194 /**
2195 * Parse a directive.
2196 *
2197 * <pre>
2198 * directive ::=
2199 * exportDirective
2200 * | libraryDirective
2201 * | importDirective
2202 * | partDirective
2203 * </pre>
2204 *
2205 * @param commentAndMetadata the metadata to be associated with the directive
2206 * @return the directive that was parsed
2207 */
2208 Directive parseDirective(CommentAndMetadata commentAndMetadata) {
2209 if (matches(Keyword.IMPORT)) {
2210 return parseImportDirective(commentAndMetadata);
2211 } else if (matches(Keyword.EXPORT)) {
2212 return parseExportDirective(commentAndMetadata);
2213 } else if (matches(Keyword.LIBRARY)) {
2214 return parseLibraryDirective(commentAndMetadata);
2215 } else if (matches(Keyword.PART)) {
2216 return parsePartDirective(commentAndMetadata);
2217 } else {
2218 throw new IllegalStateException("parseDirective invoked in an invalid stat e; currentToken = ${_currentToken}");
2219 }
2220 }
2221
2222 /**
2223 * Parse a documentation comment.
2224 *
2225 * <pre>
2226 * documentationComment ::=
2227 * multiLineComment?
2228 * | singleLineComment*
2229 * </pre>
2230 *
2231 * @return the documentation comment that was parsed, or `null` if there was n o comment
2232 */
2233 Comment parseDocumentationComment() {
2234 List<Token> commentTokens = new List<Token>();
2235 Token commentToken = _currentToken.precedingComments;
2236 while (commentToken != null) {
2237 if (identical(commentToken.type, TokenType.SINGLE_LINE_COMMENT)) {
2238 if (commentToken.lexeme.startsWith("///")) {
2239 if (commentTokens.length == 1 && commentTokens[0].lexeme.startsWith("/ **")) {
2240 commentTokens.clear();
2241 }
2242 commentTokens.add(commentToken);
2243 }
2244 } else {
2245 if (commentToken.lexeme.startsWith("/**")) {
2246 commentTokens.clear();
2247 commentTokens.add(commentToken);
2248 }
2249 }
2250 commentToken = commentToken.next;
2251 }
2252 if (commentTokens.isEmpty) {
2253 return null;
2254 }
2255 List<Token> tokens = new List.from(commentTokens);
2256 List<CommentReference> references = parseCommentReferences(tokens);
2257 return Comment.createDocumentationComment2(tokens, references);
2258 }
2259
2260 /**
2261 * Parse a do statement.
2262 *
2263 * <pre>
2264 * doStatement ::=
2265 * 'do' statement 'while' '(' expression ')' ';'
2266 * </pre>
2267 *
2268 * @return the do statement that was parsed
2269 */
2270 Statement parseDoStatement() {
2271 bool wasInLoop = _inLoop;
2272 _inLoop = true;
2273 try {
2274 Token doKeyword = expect(Keyword.DO);
2275 Statement body = parseStatement2();
2276 Token whileKeyword = expect(Keyword.WHILE);
2277 Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
2278 Expression condition = parseExpression2();
2279 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
2280 Token semicolon = expect2(TokenType.SEMICOLON);
2281 return new DoStatement.full(doKeyword, body, whileKeyword, leftParenthesis , condition, rightParenthesis, semicolon);
2282 } finally {
2283 _inLoop = wasInLoop;
2284 }
2285 }
2286
2287 /**
2288 * Parse an empty statement.
2289 *
2290 * <pre>
2291 * emptyStatement ::=
2292 * ';'
2293 * </pre>
2294 *
2295 * @return the empty statement that was parsed
2296 */
2297 Statement parseEmptyStatement() => new EmptyStatement.full(andAdvance);
2298
2299 /**
2300 * Parse an equality expression.
2301 *
2302 * <pre>
2303 * equalityExpression ::=
2304 * relationalExpression (equalityOperator relationalExpression)?
2305 * | 'super' equalityOperator relationalExpression
2306 * </pre>
2307 *
2308 * @return the equality expression that was parsed
2309 */
2310 Expression parseEqualityExpression() {
2311 Expression expression;
2312 if (matches(Keyword.SUPER) && _currentToken.next.type.isEqualityOperator) {
2313 expression = new SuperExpression.full(andAdvance);
2314 } else {
2315 expression = parseRelationalExpression();
2316 }
2317 bool leftEqualityExpression = false;
2318 while (_currentToken.type.isEqualityOperator) {
2319 Token operator = andAdvance;
2320 if (leftEqualityExpression) {
2321 reportError(ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND, express ion, []);
2322 }
2323 expression = new BinaryExpression.full(expression, operator, parseRelation alExpression());
2324 leftEqualityExpression = true;
2325 }
2326 return expression;
2327 }
2328
2329 /**
2330 * Parse an export directive.
2331 *
2332 * <pre>
2333 * exportDirective ::=
2334 * metadata 'export' stringLiteral combinator*';'
2335 * </pre>
2336 *
2337 * @param commentAndMetadata the metadata to be associated with the directive
2338 * @return the export directive that was parsed
2339 */
2340 ExportDirective parseExportDirective(CommentAndMetadata commentAndMetadata) {
2341 Token exportKeyword = expect(Keyword.EXPORT);
2342 StringLiteral libraryUri = parseStringLiteral();
2343 List<Combinator> combinators = parseCombinators();
2344 Token semicolon = expect2(TokenType.SEMICOLON);
2345 return new ExportDirective.full(commentAndMetadata.comment, commentAndMetada ta.metadata, exportKeyword, libraryUri, combinators, semicolon);
2346 }
2347
2348 /**
2349 * Parse an expression that does not contain any cascades.
2350 *
2351 * <pre>
2352 * expression ::=
2353 * assignableExpression assignmentOperator expression
2354 * | conditionalExpression cascadeSection*
2355 * | throwExpression
2356 * </pre>
2357 *
2358 * @return the expression that was parsed
2359 */
2360 Expression parseExpression2() {
2361 if (matches(Keyword.THROW)) {
2362 return parseThrowExpression();
2363 } else if (matches(Keyword.RETHROW)) {
2364 return parseRethrowExpression();
2365 }
2366 Expression expression = parseConditionalExpression();
2367 TokenType tokenType = _currentToken.type;
2368 if (identical(tokenType, TokenType.PERIOD_PERIOD)) {
2369 List<Expression> cascadeSections = new List<Expression>();
2370 while (identical(tokenType, TokenType.PERIOD_PERIOD)) {
2371 Expression section = parseCascadeSection();
2372 if (section != null) {
2373 cascadeSections.add(section);
2374 }
2375 tokenType = _currentToken.type;
2376 }
2377 return new CascadeExpression.full(expression, cascadeSections);
2378 } else if (tokenType.isAssignmentOperator) {
2379 Token operator = andAdvance;
2380 ensureAssignable(expression);
2381 return new AssignmentExpression.full(expression, operator, parseExpression 2());
2382 }
2383 return expression;
2384 }
2385
2386 /**
2387 * Parse a list of expressions.
2388 *
2389 * <pre>
2390 * expressionList ::=
2391 * expression (',' expression)*
2392 * </pre>
2393 *
2394 * @return the expression that was parsed
2395 */
2396 List<Expression> parseExpressionList() {
2397 List<Expression> expressions = new List<Expression>();
2398 expressions.add(parseExpression2());
2399 while (optional(TokenType.COMMA)) {
2400 expressions.add(parseExpression2());
2401 }
2402 return expressions;
2403 }
2404
2405 /**
2406 * Parse an expression that does not contain any cascades.
2407 *
2408 * <pre>
2409 * expressionWithoutCascade ::=
2410 * assignableExpression assignmentOperator expressionWithoutCascade
2411 * | conditionalExpression
2412 * | throwExpressionWithoutCascade
2413 * </pre>
2414 *
2415 * @return the expression that was parsed
2416 */
2417 Expression parseExpressionWithoutCascade() {
2418 if (matches(Keyword.THROW)) {
2419 return parseThrowExpressionWithoutCascade();
2420 } else if (matches(Keyword.RETHROW)) {
2421 return parseRethrowExpression();
2422 }
2423 Expression expression = parseConditionalExpression();
2424 if (_currentToken.type.isAssignmentOperator) {
2425 Token operator = andAdvance;
2426 ensureAssignable(expression);
2427 expression = new AssignmentExpression.full(expression, operator, parseExpr essionWithoutCascade());
2428 }
2429 return expression;
2430 }
2431
2432 /**
2433 * Parse a class extends clause.
2434 *
2435 * <pre>
2436 * classExtendsClause ::=
2437 * 'extends' type
2438 * </pre>
2439 *
2440 * @return the class extends clause that was parsed
2441 */
2442 ExtendsClause parseExtendsClause() {
2443 Token keyword = expect(Keyword.EXTENDS);
2444 TypeName superclass = parseTypeName();
2445 return new ExtendsClause.full(keyword, superclass);
2446 }
2447
2448 /**
2449 * Parse the 'final', 'const', 'var' or type preceding a variable declaration.
2450 *
2451 * <pre>
2452 * finalConstVarOrType ::=
2453 * | 'final' type?
2454 * | 'const' type?
2455 * | 'var'
2456 * | type
2457 * </pre>
2458 *
2459 * @param optional `true` if the keyword and type are optional
2460 * @return the 'final', 'const', 'var' or type that was parsed
2461 */
2462 FinalConstVarOrType parseFinalConstVarOrType(bool optional) {
2463 Token keyword = null;
2464 TypeName type = null;
2465 if (matches(Keyword.FINAL) || matches(Keyword.CONST)) {
2466 keyword = andAdvance;
2467 if (isTypedIdentifier(_currentToken)) {
2468 type = parseTypeName();
2469 }
2470 } else if (matches(Keyword.VAR)) {
2471 keyword = andAdvance;
2472 } else {
2473 if (isTypedIdentifier(_currentToken)) {
2474 type = parseReturnType();
2475 } else if (!optional) {
2476 reportError8(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, []);
2477 }
2478 }
2479 return new FinalConstVarOrType(keyword, type);
2480 }
2481
2482 /**
2483 * Parse a formal parameter. At most one of `isOptional` and `isNamed` can be
2484 * `true`.
2485 *
2486 * <pre>
2487 * defaultFormalParameter ::=
2488 * normalFormalParameter ('=' expression)?
2489 *
2490 * defaultNamedParameter ::=
2491 * normalFormalParameter (':' expression)?
2492 * </pre>
2493 *
2494 * @param kind the kind of parameter being expected based on the presence or a bsence of group
2495 * delimiters
2496 * @return the formal parameter that was parsed
2497 */
2498 FormalParameter parseFormalParameter(ParameterKind kind) {
2499 NormalFormalParameter parameter = parseNormalFormalParameter();
2500 if (matches5(TokenType.EQ)) {
2501 Token seperator = andAdvance;
2502 Expression defaultValue = parseExpression2();
2503 if (identical(kind, ParameterKind.NAMED)) {
2504 reportError9(ParserErrorCode.WRONG_SEPARATOR_FOR_NAMED_PARAMETER, sepera tor, []);
2505 } else if (identical(kind, ParameterKind.REQUIRED)) {
2506 reportError(ParserErrorCode.POSITIONAL_PARAMETER_OUTSIDE_GROUP, paramete r, []);
2507 }
2508 return new DefaultFormalParameter.full(parameter, kind, seperator, default Value);
2509 } else if (matches5(TokenType.COLON)) {
2510 Token seperator = andAdvance;
2511 Expression defaultValue = parseExpression2();
2512 if (identical(kind, ParameterKind.POSITIONAL)) {
2513 reportError9(ParserErrorCode.WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER, s eperator, []);
2514 } else if (identical(kind, ParameterKind.REQUIRED)) {
2515 reportError(ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP, parameter, [] );
2516 }
2517 return new DefaultFormalParameter.full(parameter, kind, seperator, default Value);
2518 } else if (kind != ParameterKind.REQUIRED) {
2519 return new DefaultFormalParameter.full(parameter, kind, null, null);
2520 }
2521 return parameter;
2522 }
2523
2524 /**
2525 * Parse a list of formal parameters.
2526 *
2527 * <pre>
2528 * formalParameterList ::=
2529 * '(' ')'
2530 * | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
2531 * | '(' optionalFormalParameters ')'
2532 *
2533 * normalFormalParameters ::=
2534 * normalFormalParameter (',' normalFormalParameter)*
2535 *
2536 * optionalFormalParameters ::=
2537 * optionalPositionalFormalParameters
2538 * | namedFormalParameters
2539 *
2540 * optionalPositionalFormalParameters ::=
2541 * '[' defaultFormalParameter (',' defaultFormalParameter)* ']'
2542 *
2543 * namedFormalParameters ::=
2544 * '{' defaultNamedParameter (',' defaultNamedParameter)* '}'
2545 * </pre>
2546 *
2547 * @return the formal parameters that were parsed
2548 */
2549 FormalParameterList parseFormalParameterList() {
2550 Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
2551 if (matches5(TokenType.CLOSE_PAREN)) {
2552 return new FormalParameterList.full(leftParenthesis, null, null, null, and Advance);
2553 }
2554 List<FormalParameter> parameters = new List<FormalParameter>();
2555 List<FormalParameter> normalParameters = new List<FormalParameter>();
2556 List<FormalParameter> positionalParameters = new List<FormalParameter>();
2557 List<FormalParameter> namedParameters = new List<FormalParameter>();
2558 List<FormalParameter> currentParameters = normalParameters;
2559 Token leftSquareBracket = null;
2560 Token rightSquareBracket = null;
2561 Token leftCurlyBracket = null;
2562 Token rightCurlyBracket = null;
2563 ParameterKind kind = ParameterKind.REQUIRED;
2564 bool firstParameter = true;
2565 bool reportedMuliplePositionalGroups = false;
2566 bool reportedMulipleNamedGroups = false;
2567 bool reportedMixedGroups = false;
2568 bool wasOptionalParameter = false;
2569 Token initialToken = null;
2570 do {
2571 if (firstParameter) {
2572 firstParameter = false;
2573 } else if (!optional(TokenType.COMMA)) {
2574 if (getEndToken(leftParenthesis) != null) {
2575 reportError8(ParserErrorCode.EXPECTED_TOKEN, [TokenType.COMMA.lexeme]) ;
2576 } else {
2577 reportError9(ParserErrorCode.MISSING_CLOSING_PARENTHESIS, _currentToke n.previous, []);
2578 break;
2579 }
2580 }
2581 initialToken = _currentToken;
2582 if (matches5(TokenType.OPEN_SQUARE_BRACKET)) {
2583 wasOptionalParameter = true;
2584 if (leftSquareBracket != null && !reportedMuliplePositionalGroups) {
2585 reportError8(ParserErrorCode.MULTIPLE_POSITIONAL_PARAMETER_GROUPS, []) ;
2586 reportedMuliplePositionalGroups = true;
2587 }
2588 if (leftCurlyBracket != null && !reportedMixedGroups) {
2589 reportError8(ParserErrorCode.MIXED_PARAMETER_GROUPS, []);
2590 reportedMixedGroups = true;
2591 }
2592 leftSquareBracket = andAdvance;
2593 currentParameters = positionalParameters;
2594 kind = ParameterKind.POSITIONAL;
2595 } else if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
2596 wasOptionalParameter = true;
2597 if (leftCurlyBracket != null && !reportedMulipleNamedGroups) {
2598 reportError8(ParserErrorCode.MULTIPLE_NAMED_PARAMETER_GROUPS, []);
2599 reportedMulipleNamedGroups = true;
2600 }
2601 if (leftSquareBracket != null && !reportedMixedGroups) {
2602 reportError8(ParserErrorCode.MIXED_PARAMETER_GROUPS, []);
2603 reportedMixedGroups = true;
2604 }
2605 leftCurlyBracket = andAdvance;
2606 currentParameters = namedParameters;
2607 kind = ParameterKind.NAMED;
2608 }
2609 FormalParameter parameter = parseFormalParameter(kind);
2610 parameters.add(parameter);
2611 currentParameters.add(parameter);
2612 if (identical(kind, ParameterKind.REQUIRED) && wasOptionalParameter) {
2613 reportError(ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS, parameter , []);
2614 }
2615 if (matches5(TokenType.CLOSE_SQUARE_BRACKET)) {
2616 rightSquareBracket = andAdvance;
2617 currentParameters = normalParameters;
2618 if (leftSquareBracket == null) {
2619 if (leftCurlyBracket != null) {
2620 reportError8(ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP, [ "}"]);
2621 rightCurlyBracket = rightSquareBracket;
2622 rightSquareBracket = null;
2623 } else {
2624 reportError8(ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GRO UP, ["["]);
2625 }
2626 }
2627 kind = ParameterKind.REQUIRED;
2628 } else if (matches5(TokenType.CLOSE_CURLY_BRACKET)) {
2629 rightCurlyBracket = andAdvance;
2630 currentParameters = normalParameters;
2631 if (leftCurlyBracket == null) {
2632 if (leftSquareBracket != null) {
2633 reportError8(ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP, [ "]"]);
2634 rightSquareBracket = rightCurlyBracket;
2635 rightCurlyBracket = null;
2636 } else {
2637 reportError8(ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GRO UP, ["{"]);
2638 }
2639 }
2640 kind = ParameterKind.REQUIRED;
2641 }
2642 } while (!matches5(TokenType.CLOSE_PAREN) && initialToken != _currentToken);
2643 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
2644 if (leftSquareBracket != null && rightSquareBracket == null) {
2645 reportError8(ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP, ["]"] );
2646 }
2647 if (leftCurlyBracket != null && rightCurlyBracket == null) {
2648 reportError8(ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP, ["}"] );
2649 }
2650 if (leftSquareBracket == null) {
2651 leftSquareBracket = leftCurlyBracket;
2652 }
2653 if (rightSquareBracket == null) {
2654 rightSquareBracket = rightCurlyBracket;
2655 }
2656 return new FormalParameterList.full(leftParenthesis, parameters, leftSquareB racket, rightSquareBracket, rightParenthesis);
2657 }
2658
2659 /**
2660 * Parse a for statement.
2661 *
2662 * <pre>
2663 * forStatement ::=
2664 * 'for' '(' forLoopParts ')' statement
2665 *
2666 * forLoopParts ::=
2667 * forInitializerStatement expression? ';' expressionList?
2668 * | declaredIdentifier 'in' expression
2669 * | identifier 'in' expression
2670 *
2671 * forInitializerStatement ::=
2672 * localVariableDeclaration ';'
2673 * | expression? ';'
2674 * </pre>
2675 *
2676 * @return the for statement that was parsed
2677 */
2678 Statement parseForStatement() {
2679 bool wasInLoop = _inLoop;
2680 _inLoop = true;
2681 try {
2682 Token forKeyword = expect(Keyword.FOR);
2683 Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
2684 VariableDeclarationList variableList = null;
2685 Expression initialization = null;
2686 if (!matches5(TokenType.SEMICOLON)) {
2687 CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
2688 if (matchesIdentifier() && matches3(peek(), Keyword.IN)) {
2689 List<VariableDeclaration> variables = new List<VariableDeclaration>();
2690 SimpleIdentifier variableName = parseSimpleIdentifier();
2691 variables.add(new VariableDeclaration.full(null, null, variableName, n ull, null));
2692 variableList = new VariableDeclarationList.full(commentAndMetadata.com ment, commentAndMetadata.metadata, null, null, variables);
2693 } else if (isInitializedVariableDeclaration()) {
2694 variableList = parseVariableDeclarationList(commentAndMetadata);
2695 } else {
2696 initialization = parseExpression2();
2697 }
2698 if (matches(Keyword.IN)) {
2699 DeclaredIdentifier loopVariable = null;
2700 SimpleIdentifier identifier = null;
2701 if (variableList == null) {
2702 reportError8(ParserErrorCode.MISSING_VARIABLE_IN_FOR_EACH, []);
2703 } else {
2704 NodeList<VariableDeclaration> variables = variableList.variables;
2705 if (variables.length > 1) {
2706 reportError8(ParserErrorCode.MULTIPLE_VARIABLES_IN_FOR_EACH, [vari ables.length.toString()]);
2707 }
2708 VariableDeclaration variable = variables[0];
2709 if (variable.initializer != null) {
2710 reportError8(ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH, []) ;
2711 }
2712 Token keyword = variableList.keyword;
2713 TypeName type = variableList.type;
2714 if (keyword != null || type != null) {
2715 loopVariable = new DeclaredIdentifier.full(commentAndMetadata.comm ent, commentAndMetadata.metadata, keyword, type, variable.name);
2716 } else {
2717 if (!commentAndMetadata.metadata.isEmpty) {
2718 }
2719 identifier = variable.name;
2720 }
2721 }
2722 Token inKeyword = expect(Keyword.IN);
2723 Expression iterator = parseExpression2();
2724 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
2725 Statement body = parseStatement2();
2726 if (loopVariable == null) {
2727 return new ForEachStatement.con2_full(forKeyword, leftParenthesis, i dentifier, inKeyword, iterator, rightParenthesis, body);
2728 }
2729 return new ForEachStatement.con1_full(forKeyword, leftParenthesis, loo pVariable, inKeyword, iterator, rightParenthesis, body);
2730 }
2731 }
2732 Token leftSeparator = expect2(TokenType.SEMICOLON);
2733 Expression condition = null;
2734 if (!matches5(TokenType.SEMICOLON)) {
2735 condition = parseExpression2();
2736 }
2737 Token rightSeparator = expect2(TokenType.SEMICOLON);
2738 List<Expression> updaters = null;
2739 if (!matches5(TokenType.CLOSE_PAREN)) {
2740 updaters = parseExpressionList();
2741 }
2742 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
2743 Statement body = parseStatement2();
2744 return new ForStatement.full(forKeyword, leftParenthesis, variableList, in itialization, leftSeparator, condition, rightSeparator, updaters, rightParenthes is, body);
2745 } finally {
2746 _inLoop = wasInLoop;
2747 }
2748 }
2749
2750 /**
2751 * Parse a function body.
2752 *
2753 * <pre>
2754 * functionBody ::=
2755 * '=>' expression ';'
2756 * | block
2757 *
2758 * functionExpressionBody ::=
2759 * '=>' expression
2760 * | block
2761 * </pre>
2762 *
2763 * @param mayBeEmpty `true` if the function body is allowed to be empty
2764 * @param emptyErrorCode the error code to report if function body expecte, bu t not found
2765 * @param inExpression `true` if the function body is being parsed as part of an expression
2766 * and therefore does not have a terminating semicolon
2767 * @return the function body that was parsed
2768 */
2769 FunctionBody parseFunctionBody(bool mayBeEmpty, ParserErrorCode emptyErrorCode , bool inExpression) {
2770 bool wasInLoop = _inLoop;
2771 bool wasInSwitch = _inSwitch;
2772 _inLoop = false;
2773 _inSwitch = false;
2774 try {
2775 if (matches5(TokenType.SEMICOLON)) {
2776 if (!mayBeEmpty) {
2777 reportError8(emptyErrorCode, []);
2778 }
2779 return new EmptyFunctionBody.full(andAdvance);
2780 } else if (matches5(TokenType.FUNCTION)) {
2781 Token functionDefinition = andAdvance;
2782 Expression expression = parseExpression2();
2783 Token semicolon = null;
2784 if (!inExpression) {
2785 semicolon = expect2(TokenType.SEMICOLON);
2786 }
2787 return new ExpressionFunctionBody.full(functionDefinition, expression, s emicolon);
2788 } else if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
2789 return new BlockFunctionBody.full(parseBlock());
2790 } else if (matches2(_NATIVE)) {
2791 Token nativeToken = andAdvance;
2792 StringLiteral stringLiteral = null;
2793 if (matches5(TokenType.STRING)) {
2794 stringLiteral = parseStringLiteral();
2795 }
2796 return new NativeFunctionBody.full(nativeToken, stringLiteral, expect2(T okenType.SEMICOLON));
2797 } else {
2798 reportError8(emptyErrorCode, []);
2799 return new EmptyFunctionBody.full(createSyntheticToken2(TokenType.SEMICO LON));
2800 }
2801 } finally {
2802 _inLoop = wasInLoop;
2803 _inSwitch = wasInSwitch;
2804 }
2805 }
2806
2807 /**
2808 * Parse a function declaration.
2809 *
2810 * <pre>
2811 * functionDeclaration ::=
2812 * functionSignature functionBody
2813 * | returnType? getOrSet identifier formalParameterList functionBody
2814 * </pre>
2815 *
2816 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
2817 * declaration
2818 * @param externalKeyword the 'external' keyword, or `null` if the function is not external
2819 * @param returnType the return type, or `null` if there is no return type
2820 * @param isStatement `true` if the function declaration is being parsed as a statement
2821 * @return the function declaration that was parsed
2822 */
2823 FunctionDeclaration parseFunctionDeclaration(CommentAndMetadata commentAndMeta data, Token externalKeyword, TypeName returnType) {
2824 Token keyword = null;
2825 bool isGetter = false;
2826 if (matches(Keyword.GET) && !matches4(peek(), TokenType.OPEN_PAREN)) {
2827 keyword = andAdvance;
2828 isGetter = true;
2829 } else if (matches(Keyword.SET) && !matches4(peek(), TokenType.OPEN_PAREN)) {
2830 keyword = andAdvance;
2831 }
2832 SimpleIdentifier name = parseSimpleIdentifier();
2833 FormalParameterList parameters = null;
2834 if (!isGetter) {
2835 if (matches5(TokenType.OPEN_PAREN)) {
2836 parameters = parseFormalParameterList();
2837 validateFormalParameterList(parameters);
2838 } else {
2839 reportError8(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, []);
2840 }
2841 } else if (matches5(TokenType.OPEN_PAREN)) {
2842 reportError8(ParserErrorCode.GETTER_WITH_PARAMETERS, []);
2843 parseFormalParameterList();
2844 }
2845 FunctionBody body;
2846 if (externalKeyword == null) {
2847 body = parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTION_BODY, fal se);
2848 } else {
2849 body = new EmptyFunctionBody.full(expect2(TokenType.SEMICOLON));
2850 }
2851 return new FunctionDeclaration.full(commentAndMetadata.comment, commentAndMe tadata.metadata, externalKeyword, returnType, keyword, name, new FunctionExpress ion.full(parameters, body));
2852 }
2853
2854 /**
2855 * Parse a function declaration statement.
2856 *
2857 * <pre>
2858 * functionDeclarationStatement ::=
2859 * functionSignature functionBody
2860 * </pre>
2861 *
2862 * @return the function declaration statement that was parsed
2863 */
2864 Statement parseFunctionDeclarationStatement() {
2865 Modifiers modifiers = parseModifiers();
2866 validateModifiersForFunctionDeclarationStatement(modifiers);
2867 return parseFunctionDeclarationStatement2(parseCommentAndMetadata(), parseOp tionalReturnType());
2868 }
2869
2870 /**
2871 * Parse a function declaration statement.
2872 *
2873 * <pre>
2874 * functionDeclarationStatement ::=
2875 * functionSignature functionBody
2876 * </pre>
2877 *
2878 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
2879 * declaration
2880 * @param returnType the return type, or `null` if there is no return type
2881 * @return the function declaration statement that was parsed
2882 */
2883 Statement parseFunctionDeclarationStatement2(CommentAndMetadata commentAndMeta data, TypeName returnType) {
2884 FunctionDeclaration declaration = parseFunctionDeclaration(commentAndMetadat a, null, returnType);
2885 Token propertyKeyword = declaration.propertyKeyword;
2886 if (propertyKeyword != null) {
2887 if (identical(((propertyKeyword as KeywordToken)).keyword, Keyword.GET)) {
2888 reportError9(ParserErrorCode.GETTER_IN_FUNCTION, propertyKeyword, []);
2889 } else {
2890 reportError9(ParserErrorCode.SETTER_IN_FUNCTION, propertyKeyword, []);
2891 }
2892 }
2893 return new FunctionDeclarationStatement.full(declaration);
2894 }
2895
2896 /**
2897 * Parse a function expression.
2898 *
2899 * <pre>
2900 * functionExpression ::=
2901 * formalParameterList functionExpressionBody
2902 * </pre>
2903 *
2904 * @return the function expression that was parsed
2905 */
2906 FunctionExpression parseFunctionExpression() {
2907 FormalParameterList parameters = parseFormalParameterList();
2908 validateFormalParameterList(parameters);
2909 FunctionBody body = parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTIO N_BODY, true);
2910 return new FunctionExpression.full(parameters, body);
2911 }
2912
2913 /**
2914 * Parse a function type alias.
2915 *
2916 * <pre>
2917 * functionTypeAlias ::=
2918 * functionPrefix typeParameterList? formalParameterList ';'
2919 *
2920 * functionPrefix ::=
2921 * returnType? name
2922 * </pre>
2923 *
2924 * @param commentAndMetadata the metadata to be associated with the member
2925 * @param keyword the token representing the 'typedef' keyword
2926 * @return the function type alias that was parsed
2927 */
2928 FunctionTypeAlias parseFunctionTypeAlias(CommentAndMetadata commentAndMetadata , Token keyword) {
2929 TypeName returnType = null;
2930 if (hasReturnTypeInTypeAlias()) {
2931 returnType = parseReturnType();
2932 }
2933 SimpleIdentifier name = parseSimpleIdentifier();
2934 TypeParameterList typeParameters = null;
2935 if (matches5(TokenType.LT)) {
2936 typeParameters = parseTypeParameterList();
2937 }
2938 if (matches5(TokenType.SEMICOLON) || matches5(TokenType.EOF)) {
2939 reportError8(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, []);
2940 FormalParameterList parameters = new FormalParameterList.full(createSynthe ticToken2(TokenType.OPEN_PAREN), null, null, null, createSyntheticToken2(TokenTy pe.CLOSE_PAREN));
2941 Token semicolon = expect2(TokenType.SEMICOLON);
2942 return new FunctionTypeAlias.full(commentAndMetadata.comment, commentAndMe tadata.metadata, keyword, returnType, name, typeParameters, parameters, semicolo n);
2943 } else if (!matches5(TokenType.OPEN_PAREN)) {
2944 reportError8(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, []);
2945 return new FunctionTypeAlias.full(commentAndMetadata.comment, commentAndMe tadata.metadata, keyword, returnType, name, typeParameters, new FormalParameterL ist.full(createSyntheticToken2(TokenType.OPEN_PAREN), null, null, null, createSy ntheticToken2(TokenType.CLOSE_PAREN)), createSyntheticToken2(TokenType.SEMICOLON ));
2946 }
2947 FormalParameterList parameters = parseFormalParameterList();
2948 validateFormalParameterList(parameters);
2949 Token semicolon = expect2(TokenType.SEMICOLON);
2950 return new FunctionTypeAlias.full(commentAndMetadata.comment, commentAndMeta data.metadata, keyword, returnType, name, typeParameters, parameters, semicolon) ;
2951 }
2952
2953 /**
2954 * Parse a getter.
2955 *
2956 * <pre>
2957 * getter ::=
2958 * getterSignature functionBody?
2959 *
2960 * getterSignature ::=
2961 * 'external'? 'static'? returnType? 'get' identifier
2962 * </pre>
2963 *
2964 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
2965 * declaration
2966 * @param externalKeyword the 'external' token
2967 * @param staticKeyword the static keyword, or `null` if the getter is not sta tic
2968 * @param the return type that has already been parsed, or `null` if there was no return
2969 * type
2970 * @return the getter that was parsed
2971 */
2972 MethodDeclaration parseGetter(CommentAndMetadata commentAndMetadata, Token ext ernalKeyword, Token staticKeyword, TypeName returnType) {
2973 Token propertyKeyword = expect(Keyword.GET);
2974 SimpleIdentifier name = parseSimpleIdentifier();
2975 if (matches5(TokenType.OPEN_PAREN) && matches4(peek(), TokenType.CLOSE_PAREN )) {
2976 reportError8(ParserErrorCode.GETTER_WITH_PARAMETERS, []);
2977 advance();
2978 advance();
2979 }
2980 FunctionBody body = parseFunctionBody(externalKeyword != null || staticKeywo rd == null, ParserErrorCode.STATIC_GETTER_WITHOUT_BODY, false);
2981 if (externalKeyword != null && body is! EmptyFunctionBody) {
2982 reportError8(ParserErrorCode.EXTERNAL_GETTER_WITH_BODY, []);
2983 }
2984 return new MethodDeclaration.full(commentAndMetadata.comment, commentAndMeta data.metadata, externalKeyword, staticKeyword, returnType, propertyKeyword, null , name, null, body);
2985 }
2986
2987 /**
2988 * Parse a list of identifiers.
2989 *
2990 * <pre>
2991 * identifierList ::=
2992 * identifier (',' identifier)*
2993 * </pre>
2994 *
2995 * @return the list of identifiers that were parsed
2996 */
2997 List<SimpleIdentifier> parseIdentifierList() {
2998 List<SimpleIdentifier> identifiers = new List<SimpleIdentifier>();
2999 identifiers.add(parseSimpleIdentifier());
3000 while (matches5(TokenType.COMMA)) {
3001 advance();
3002 identifiers.add(parseSimpleIdentifier());
3003 }
3004 return identifiers;
3005 }
3006
3007 /**
3008 * Parse an if statement.
3009 *
3010 * <pre>
3011 * ifStatement ::=
3012 * 'if' '(' expression ')' statement ('else' statement)?
3013 * </pre>
3014 *
3015 * @return the if statement that was parsed
3016 */
3017 Statement parseIfStatement() {
3018 Token ifKeyword = expect(Keyword.IF);
3019 Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
3020 Expression condition = parseExpression2();
3021 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
3022 Statement thenStatement = parseStatement2();
3023 Token elseKeyword = null;
3024 Statement elseStatement = null;
3025 if (matches(Keyword.ELSE)) {
3026 elseKeyword = andAdvance;
3027 elseStatement = parseStatement2();
3028 }
3029 return new IfStatement.full(ifKeyword, leftParenthesis, condition, rightPare nthesis, thenStatement, elseKeyword, elseStatement);
3030 }
3031
3032 /**
3033 * Parse an implements clause.
3034 *
3035 * <pre>
3036 * implementsClause ::=
3037 * 'implements' type (',' type)*
3038 * </pre>
3039 *
3040 * @return the implements clause that was parsed
3041 */
3042 ImplementsClause parseImplementsClause() {
3043 Token keyword = expect(Keyword.IMPLEMENTS);
3044 List<TypeName> interfaces = new List<TypeName>();
3045 interfaces.add(parseTypeName());
3046 while (optional(TokenType.COMMA)) {
3047 interfaces.add(parseTypeName());
3048 }
3049 return new ImplementsClause.full(keyword, interfaces);
3050 }
3051
3052 /**
3053 * Parse an import directive.
3054 *
3055 * <pre>
3056 * importDirective ::=
3057 * metadata 'import' stringLiteral ('as' identifier)? combinator*';'
3058 * </pre>
3059 *
3060 * @param commentAndMetadata the metadata to be associated with the directive
3061 * @return the import directive that was parsed
3062 */
3063 ImportDirective parseImportDirective(CommentAndMetadata commentAndMetadata) {
3064 Token importKeyword = expect(Keyword.IMPORT);
3065 StringLiteral libraryUri = parseStringLiteral();
3066 Token asToken = null;
3067 SimpleIdentifier prefix = null;
3068 if (matches(Keyword.AS)) {
3069 asToken = andAdvance;
3070 prefix = parseSimpleIdentifier();
3071 }
3072 List<Combinator> combinators = parseCombinators();
3073 Token semicolon = expect2(TokenType.SEMICOLON);
3074 return new ImportDirective.full(commentAndMetadata.comment, commentAndMetada ta.metadata, importKeyword, libraryUri, asToken, prefix, combinators, semicolon) ;
3075 }
3076
3077 /**
3078 * Parse a list of initialized identifiers.
3079 *
3080 * <pre>
3081 * ?? ::=
3082 * 'static'? ('var' | type) initializedIdentifierList ';'
3083 * | 'final' type? initializedIdentifierList ';'
3084 *
3085 * initializedIdentifierList ::=
3086 * initializedIdentifier (',' initializedIdentifier)*
3087 *
3088 * initializedIdentifier ::=
3089 * identifier ('=' expression)?
3090 * </pre>
3091 *
3092 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
3093 * declaration
3094 * @param staticKeyword the static keyword, or `null` if the getter is not sta tic
3095 * @param keyword the token representing the 'final', 'const' or 'var' keyword , or `null` if
3096 * there is no keyword
3097 * @param type the type that has already been parsed, or `null` if 'var' was p rovided
3098 * @return the getter that was parsed
3099 */
3100 FieldDeclaration parseInitializedIdentifierList(CommentAndMetadata commentAndM etadata, Token staticKeyword, Token keyword, TypeName type) {
3101 VariableDeclarationList fieldList = parseVariableDeclarationList2(null, keyw ord, type);
3102 return new FieldDeclaration.full(commentAndMetadata.comment, commentAndMetad ata.metadata, staticKeyword, fieldList, expect2(TokenType.SEMICOLON));
3103 }
3104
3105 /**
3106 * Parse an instance creation expression.
3107 *
3108 * <pre>
3109 * instanceCreationExpression ::=
3110 * ('new' | 'const') type ('.' identifier)? argumentList
3111 * </pre>
3112 *
3113 * @param keyword the 'new' or 'const' keyword that introduces the expression
3114 * @return the instance creation expression that was parsed
3115 */
3116 InstanceCreationExpression parseInstanceCreationExpression(Token keyword) {
3117 ConstructorName constructorName = parseConstructorName();
3118 ArgumentList argumentList = parseArgumentList();
3119 return new InstanceCreationExpression.full(keyword, constructorName, argumen tList);
3120 }
3121
3122 /**
3123 * Parse a library directive.
3124 *
3125 * <pre>
3126 * libraryDirective ::=
3127 * metadata 'library' identifier ';'
3128 * </pre>
3129 *
3130 * @param commentAndMetadata the metadata to be associated with the directive
3131 * @return the library directive that was parsed
3132 */
3133 LibraryDirective parseLibraryDirective(CommentAndMetadata commentAndMetadata) {
3134 Token keyword = expect(Keyword.LIBRARY);
3135 LibraryIdentifier libraryName = parseLibraryName(ParserErrorCode.MISSING_NAM E_IN_LIBRARY_DIRECTIVE, keyword);
3136 Token semicolon = expect2(TokenType.SEMICOLON);
3137 return new LibraryDirective.full(commentAndMetadata.comment, commentAndMetad ata.metadata, keyword, libraryName, semicolon);
3138 }
3139
3140 /**
3141 * Parse a library identifier.
3142 *
3143 * <pre>
3144 * libraryIdentifier ::=
3145 * identifier ('.' identifier)*
3146 * </pre>
3147 *
3148 * @return the library identifier that was parsed
3149 */
3150 LibraryIdentifier parseLibraryIdentifier() {
3151 List<SimpleIdentifier> components = new List<SimpleIdentifier>();
3152 components.add(parseSimpleIdentifier());
3153 while (matches5(TokenType.PERIOD)) {
3154 advance();
3155 components.add(parseSimpleIdentifier());
3156 }
3157 return new LibraryIdentifier.full(components);
3158 }
3159
3160 /**
3161 * Parse a library name.
3162 *
3163 * <pre>
3164 * libraryName ::=
3165 * libraryIdentifier
3166 * </pre>
3167 *
3168 * @param missingNameError the error code to be used if the library name is mi ssing
3169 * @param missingNameToken the token associated with the error produced if the library name is
3170 * missing
3171 * @return the library name that was parsed
3172 */
3173 LibraryIdentifier parseLibraryName(ParserErrorCode missingNameError, Token mis singNameToken) {
3174 if (matchesIdentifier()) {
3175 return parseLibraryIdentifier();
3176 } else if (matches5(TokenType.STRING)) {
3177 StringLiteral string = parseStringLiteral();
3178 reportError(ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME, string, []);
3179 } else {
3180 reportError9(missingNameError, missingNameToken, []);
3181 }
3182 List<SimpleIdentifier> components = new List<SimpleIdentifier>();
3183 components.add(createSyntheticIdentifier());
3184 return new LibraryIdentifier.full(components);
3185 }
3186
3187 /**
3188 * Parse a list literal.
3189 *
3190 * <pre>
3191 * listLiteral ::=
3192 * 'const'? typeArguments? '[' (expressionList ','?)? ']'
3193 * </pre>
3194 *
3195 * @param modifier the 'const' modifier appearing before the literal, or `null ` if there is
3196 * no modifier
3197 * @param typeArguments the type arguments appearing before the literal, or `n ull` if there
3198 * are no type arguments
3199 * @return the list literal that was parsed
3200 */
3201 ListLiteral parseListLiteral(Token modifier, TypeArgumentList typeArguments) {
3202 if (matches5(TokenType.INDEX)) {
3203 BeginToken leftBracket = new BeginToken(TokenType.OPEN_SQUARE_BRACKET, _cu rrentToken.offset);
3204 Token rightBracket = new Token(TokenType.CLOSE_SQUARE_BRACKET, _currentTok en.offset + 1);
3205 leftBracket.endToken = rightBracket;
3206 rightBracket.setNext(_currentToken.next);
3207 leftBracket.setNext(rightBracket);
3208 _currentToken.previous.setNext(leftBracket);
3209 _currentToken = _currentToken.next;
3210 return new ListLiteral.full(modifier, typeArguments, leftBracket, null, ri ghtBracket);
3211 }
3212 Token leftBracket = expect2(TokenType.OPEN_SQUARE_BRACKET);
3213 if (matches5(TokenType.CLOSE_SQUARE_BRACKET)) {
3214 return new ListLiteral.full(modifier, typeArguments, leftBracket, null, an dAdvance);
3215 }
3216 List<Expression> elements = new List<Expression>();
3217 elements.add(parseExpression2());
3218 while (optional(TokenType.COMMA)) {
3219 if (matches5(TokenType.CLOSE_SQUARE_BRACKET)) {
3220 return new ListLiteral.full(modifier, typeArguments, leftBracket, elemen ts, andAdvance);
3221 }
3222 elements.add(parseExpression2());
3223 }
3224 Token rightBracket = expect2(TokenType.CLOSE_SQUARE_BRACKET);
3225 return new ListLiteral.full(modifier, typeArguments, leftBracket, elements, rightBracket);
3226 }
3227
3228 /**
3229 * Parse a list or map literal.
3230 *
3231 * <pre>
3232 * listOrMapLiteral ::=
3233 * listLiteral
3234 * | mapLiteral
3235 * </pre>
3236 *
3237 * @param modifier the 'const' modifier appearing before the literal, or `null ` if there is
3238 * no modifier
3239 * @return the list or map literal that was parsed
3240 */
3241 TypedLiteral parseListOrMapLiteral(Token modifier) {
3242 TypeArgumentList typeArguments = null;
3243 if (matches5(TokenType.LT)) {
3244 typeArguments = parseTypeArgumentList();
3245 }
3246 if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
3247 return parseMapLiteral(modifier, typeArguments);
3248 } else if (matches5(TokenType.OPEN_SQUARE_BRACKET) || matches5(TokenType.IND EX)) {
3249 return parseListLiteral(modifier, typeArguments);
3250 }
3251 reportError8(ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL, []);
3252 return new ListLiteral.full(modifier, typeArguments, createSyntheticToken2(T okenType.OPEN_SQUARE_BRACKET), null, createSyntheticToken2(TokenType.CLOSE_SQUAR E_BRACKET));
3253 }
3254
3255 /**
3256 * Parse a logical and expression.
3257 *
3258 * <pre>
3259 * logicalAndExpression ::=
3260 * equalityExpression ('&&' equalityExpression)*
3261 * </pre>
3262 *
3263 * @return the logical and expression that was parsed
3264 */
3265 Expression parseLogicalAndExpression() {
3266 Expression expression = parseEqualityExpression();
3267 while (matches5(TokenType.AMPERSAND_AMPERSAND)) {
3268 Token operator = andAdvance;
3269 expression = new BinaryExpression.full(expression, operator, parseEquality Expression());
3270 }
3271 return expression;
3272 }
3273
3274 /**
3275 * Parse a logical or expression.
3276 *
3277 * <pre>
3278 * logicalOrExpression ::=
3279 * logicalAndExpression ('||' logicalAndExpression)*
3280 * </pre>
3281 *
3282 * @return the logical or expression that was parsed
3283 */
3284 Expression parseLogicalOrExpression() {
3285 Expression expression = parseLogicalAndExpression();
3286 while (matches5(TokenType.BAR_BAR)) {
3287 Token operator = andAdvance;
3288 expression = new BinaryExpression.full(expression, operator, parseLogicalA ndExpression());
3289 }
3290 return expression;
3291 }
3292
3293 /**
3294 * Parse a map literal.
3295 *
3296 * <pre>
3297 * mapLiteral ::=
3298 * 'const'? typeArguments? '{' (mapLiteralEntry (',' mapLiteralEntry)* ',' ?)? '}'
3299 * </pre>
3300 *
3301 * @param modifier the 'const' modifier appearing before the literal, or `null ` if there is
3302 * no modifier
3303 * @param typeArguments the type arguments that were declared, or `null` if th ere are no
3304 * type arguments
3305 * @return the map literal that was parsed
3306 */
3307 MapLiteral parseMapLiteral(Token modifier, TypeArgumentList typeArguments) {
3308 Token leftBracket = expect2(TokenType.OPEN_CURLY_BRACKET);
3309 List<MapLiteralEntry> entries = new List<MapLiteralEntry>();
3310 if (matches5(TokenType.CLOSE_CURLY_BRACKET)) {
3311 return new MapLiteral.full(modifier, typeArguments, leftBracket, entries, andAdvance);
3312 }
3313 entries.add(parseMapLiteralEntry());
3314 while (optional(TokenType.COMMA)) {
3315 if (matches5(TokenType.CLOSE_CURLY_BRACKET)) {
3316 return new MapLiteral.full(modifier, typeArguments, leftBracket, entries , andAdvance);
3317 }
3318 entries.add(parseMapLiteralEntry());
3319 }
3320 Token rightBracket = expect2(TokenType.CLOSE_CURLY_BRACKET);
3321 return new MapLiteral.full(modifier, typeArguments, leftBracket, entries, ri ghtBracket);
3322 }
3323
3324 /**
3325 * Parse a map literal entry.
3326 *
3327 * <pre>
3328 * mapLiteralEntry ::=
3329 * expression ':' expression
3330 * </pre>
3331 *
3332 * @return the map literal entry that was parsed
3333 */
3334 MapLiteralEntry parseMapLiteralEntry() {
3335 Expression key = parseExpression2();
3336 Token separator = expect2(TokenType.COLON);
3337 Expression value = parseExpression2();
3338 return new MapLiteralEntry.full(key, separator, value);
3339 }
3340
3341 /**
3342 * Parse a method declaration.
3343 *
3344 * <pre>
3345 * functionDeclaration ::=
3346 * 'external'? 'static'? functionSignature functionBody
3347 * | 'external'? functionSignature ';'
3348 * </pre>
3349 *
3350 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
3351 * declaration
3352 * @param externalKeyword the 'external' token
3353 * @param staticKeyword the static keyword, or `null` if the getter is not sta tic
3354 * @param returnType the return type of the method
3355 * @return the method declaration that was parsed
3356 */
3357 MethodDeclaration parseMethodDeclaration(CommentAndMetadata commentAndMetadata , Token externalKeyword, Token staticKeyword, TypeName returnType) {
3358 SimpleIdentifier methodName = parseSimpleIdentifier();
3359 FormalParameterList parameters = parseFormalParameterList();
3360 validateFormalParameterList(parameters);
3361 return parseMethodDeclaration2(commentAndMetadata, externalKeyword, staticKe yword, returnType, methodName, parameters);
3362 }
3363
3364 /**
3365 * Parse a method declaration.
3366 *
3367 * <pre>
3368 * functionDeclaration ::=
3369 * ('external' 'static'?)? functionSignature functionBody
3370 * | 'external'? functionSignature ';'
3371 * </pre>
3372 *
3373 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
3374 * declaration
3375 * @param externalKeyword the 'external' token
3376 * @param staticKeyword the static keyword, or `null` if the getter is not sta tic
3377 * @param returnType the return type of the method
3378 * @param name the name of the method
3379 * @param parameters the parameters to the method
3380 * @return the method declaration that was parsed
3381 */
3382 MethodDeclaration parseMethodDeclaration2(CommentAndMetadata commentAndMetadat a, Token externalKeyword, Token staticKeyword, TypeName returnType, SimpleIdenti fier name, FormalParameterList parameters) {
3383 FunctionBody body = parseFunctionBody(externalKeyword != null || staticKeywo rd == null, ParserErrorCode.MISSING_FUNCTION_BODY, false);
3384 if (externalKeyword != null) {
3385 if (body is! EmptyFunctionBody) {
3386 reportError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, body, []);
3387 }
3388 } else if (staticKeyword != null) {
3389 if (body is EmptyFunctionBody) {
3390 reportError(ParserErrorCode.ABSTRACT_STATIC_METHOD, body, []);
3391 }
3392 }
3393 return new MethodDeclaration.full(commentAndMetadata.comment, commentAndMeta data.metadata, externalKeyword, staticKeyword, returnType, null, null, name, par ameters, body);
3394 }
3395
3396 /**
3397 * Parse the modifiers preceding a declaration. This method allows the modifie rs to appear in any
3398 * order but does generate errors for duplicated modifiers. Checks for other p roblems, such as
3399 * having the modifiers appear in the wrong order or specifying both 'const' a nd 'final', are
3400 * reported in one of the methods whose name is prefixed with `validateModifie rsFor`.
3401 *
3402 * <pre>
3403 * modifiers ::=
3404 * ('abstract' | 'const' | 'external' | 'factory' | 'final' | 'static' | ' var')*
3405 * </pre>
3406 *
3407 * @return the modifiers that were parsed
3408 */
3409 Modifiers parseModifiers() {
3410 Modifiers modifiers = new Modifiers();
3411 bool progress = true;
3412 while (progress) {
3413 if (matches(Keyword.ABSTRACT) && !matches4(peek(), TokenType.PERIOD) && !m atches4(peek(), TokenType.LT)) {
3414 if (modifiers.abstractKeyword != null) {
3415 reportError8(ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexem e]);
3416 advance();
3417 } else {
3418 modifiers.abstractKeyword = andAdvance;
3419 }
3420 } else if (matches(Keyword.CONST)) {
3421 if (modifiers.constKeyword != null) {
3422 reportError8(ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexem e]);
3423 advance();
3424 } else {
3425 modifiers.constKeyword = andAdvance;
3426 }
3427 } else if (matches(Keyword.EXTERNAL) && !matches4(peek(), TokenType.PERIOD ) && !matches4(peek(), TokenType.LT)) {
3428 if (modifiers.externalKeyword != null) {
3429 reportError8(ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexem e]);
3430 advance();
3431 } else {
3432 modifiers.externalKeyword = andAdvance;
3433 }
3434 } else if (matches(Keyword.FACTORY) && !matches4(peek(), TokenType.PERIOD) && !matches4(peek(), TokenType.LT)) {
3435 if (modifiers.factoryKeyword != null) {
3436 reportError8(ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexem e]);
3437 advance();
3438 } else {
3439 modifiers.factoryKeyword = andAdvance;
3440 }
3441 } else if (matches(Keyword.FINAL)) {
3442 if (modifiers.finalKeyword != null) {
3443 reportError8(ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexem e]);
3444 advance();
3445 } else {
3446 modifiers.finalKeyword = andAdvance;
3447 }
3448 } else if (matches(Keyword.STATIC) && !matches4(peek(), TokenType.PERIOD) && !matches4(peek(), TokenType.LT)) {
3449 if (modifiers.staticKeyword != null) {
3450 reportError8(ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexem e]);
3451 advance();
3452 } else {
3453 modifiers.staticKeyword = andAdvance;
3454 }
3455 } else if (matches(Keyword.VAR)) {
3456 if (modifiers.varKeyword != null) {
3457 reportError8(ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexem e]);
3458 advance();
3459 } else {
3460 modifiers.varKeyword = andAdvance;
3461 }
3462 } else {
3463 progress = false;
3464 }
3465 }
3466 return modifiers;
3467 }
3468
3469 /**
3470 * Parse a multiplicative expression.
3471 *
3472 * <pre>
3473 * multiplicativeExpression ::=
3474 * unaryExpression (multiplicativeOperator unaryExpression)*
3475 * | 'super' (multiplicativeOperator unaryExpression)+
3476 * </pre>
3477 *
3478 * @return the multiplicative expression that was parsed
3479 */
3480 Expression parseMultiplicativeExpression() {
3481 Expression expression;
3482 if (matches(Keyword.SUPER) && _currentToken.next.type.isMultiplicativeOperat or) {
3483 expression = new SuperExpression.full(andAdvance);
3484 } else {
3485 expression = parseUnaryExpression();
3486 }
3487 while (_currentToken.type.isMultiplicativeOperator) {
3488 Token operator = andAdvance;
3489 expression = new BinaryExpression.full(expression, operator, parseUnaryExp ression());
3490 }
3491 return expression;
3492 }
3493
3494 /**
3495 * Parse a class native clause.
3496 *
3497 * <pre>
3498 * classNativeClause ::=
3499 * 'native' name
3500 * </pre>
3501 *
3502 * @return the class native clause that was parsed
3503 */
3504 NativeClause parseNativeClause() {
3505 Token keyword = andAdvance;
3506 StringLiteral name = parseStringLiteral();
3507 return new NativeClause.full(keyword, name);
3508 }
3509
3510 /**
3511 * Parse a new expression.
3512 *
3513 * <pre>
3514 * newExpression ::=
3515 * instanceCreationExpression
3516 * </pre>
3517 *
3518 * @return the new expression that was parsed
3519 */
3520 InstanceCreationExpression parseNewExpression() => parseInstanceCreationExpres sion(expect(Keyword.NEW));
3521
3522 /**
3523 * Parse a non-labeled statement.
3524 *
3525 * <pre>
3526 * nonLabeledStatement ::=
3527 * block
3528 * | assertStatement
3529 * | breakStatement
3530 * | continueStatement
3531 * | doStatement
3532 * | forStatement
3533 * | ifStatement
3534 * | returnStatement
3535 * | switchStatement
3536 * | tryStatement
3537 * | whileStatement
3538 * | variableDeclarationList ';'
3539 * | expressionStatement
3540 * | functionSignature functionBody
3541 * </pre>
3542 *
3543 * @return the non-labeled statement that was parsed
3544 */
3545 Statement parseNonLabeledStatement() {
3546 CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
3547 if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
3548 if (matches4(peek(), TokenType.STRING)) {
3549 Token afterString = skipStringLiteral(_currentToken.next);
3550 if (afterString != null && identical(afterString.type, TokenType.COLON)) {
3551 return new ExpressionStatement.full(parseExpression2(), expect2(TokenT ype.SEMICOLON));
3552 }
3553 }
3554 return parseBlock();
3555 } else if (matches5(TokenType.KEYWORD) && !((_currentToken as KeywordToken)) .keyword.isPseudoKeyword) {
3556 Keyword keyword = ((_currentToken as KeywordToken)).keyword;
3557 if (identical(keyword, Keyword.ASSERT)) {
3558 return parseAssertStatement();
3559 } else if (identical(keyword, Keyword.BREAK)) {
3560 return parseBreakStatement();
3561 } else if (identical(keyword, Keyword.CONTINUE)) {
3562 return parseContinueStatement();
3563 } else if (identical(keyword, Keyword.DO)) {
3564 return parseDoStatement();
3565 } else if (identical(keyword, Keyword.FOR)) {
3566 return parseForStatement();
3567 } else if (identical(keyword, Keyword.IF)) {
3568 return parseIfStatement();
3569 } else if (identical(keyword, Keyword.RETHROW)) {
3570 return new ExpressionStatement.full(parseRethrowExpression(), expect2(To kenType.SEMICOLON));
3571 } else if (identical(keyword, Keyword.RETURN)) {
3572 return parseReturnStatement();
3573 } else if (identical(keyword, Keyword.SWITCH)) {
3574 return parseSwitchStatement();
3575 } else if (identical(keyword, Keyword.THROW)) {
3576 return new ExpressionStatement.full(parseThrowExpression(), expect2(Toke nType.SEMICOLON));
3577 } else if (identical(keyword, Keyword.TRY)) {
3578 return parseTryStatement();
3579 } else if (identical(keyword, Keyword.WHILE)) {
3580 return parseWhileStatement();
3581 } else if (identical(keyword, Keyword.VAR) || identical(keyword, Keyword.F INAL)) {
3582 return parseVariableDeclarationStatement(commentAndMetadata);
3583 } else if (identical(keyword, Keyword.VOID)) {
3584 TypeName returnType = parseReturnType();
3585 if (matchesIdentifier() && matchesAny(peek(), [
3586 TokenType.OPEN_PAREN,
3587 TokenType.OPEN_CURLY_BRACKET,
3588 TokenType.FUNCTION])) {
3589 return parseFunctionDeclarationStatement2(commentAndMetadata, returnTy pe);
3590 } else {
3591 if (matchesIdentifier()) {
3592 if (matchesAny(peek(), [TokenType.EQ, TokenType.COMMA, TokenType.SEM ICOLON])) {
3593 reportError(ParserErrorCode.VOID_VARIABLE, returnType, []);
3594 return parseVariableDeclarationStatement(commentAndMetadata);
3595 }
3596 } else if (matches5(TokenType.CLOSE_CURLY_BRACKET)) {
3597 return parseVariableDeclarationStatement2(commentAndMetadata, null, returnType);
3598 }
3599 reportError8(ParserErrorCode.MISSING_STATEMENT, []);
3600 return new EmptyStatement.full(createSyntheticToken2(TokenType.SEMICOL ON));
3601 }
3602 } else if (identical(keyword, Keyword.CONST)) {
3603 if (matchesAny(peek(), [
3604 TokenType.LT,
3605 TokenType.OPEN_CURLY_BRACKET,
3606 TokenType.OPEN_SQUARE_BRACKET,
3607 TokenType.INDEX])) {
3608 return new ExpressionStatement.full(parseExpression2(), expect2(TokenT ype.SEMICOLON));
3609 } else if (matches4(peek(), TokenType.IDENTIFIER)) {
3610 Token afterType = skipTypeName(peek());
3611 if (afterType != null) {
3612 if (matches4(afterType, TokenType.OPEN_PAREN) || (matches4(afterType , TokenType.PERIOD) && matches4(afterType.next, TokenType.IDENTIFIER) && matches 4(afterType.next.next, TokenType.OPEN_PAREN))) {
3613 return new ExpressionStatement.full(parseExpression2(), expect2(To kenType.SEMICOLON));
3614 }
3615 }
3616 }
3617 return parseVariableDeclarationStatement(commentAndMetadata);
3618 } else if (identical(keyword, Keyword.NEW) || identical(keyword, Keyword.T RUE) || identical(keyword, Keyword.FALSE) || identical(keyword, Keyword.NULL) || identical(keyword, Keyword.SUPER) || identical(keyword, Keyword.THIS)) {
3619 return new ExpressionStatement.full(parseExpression2(), expect2(TokenTyp e.SEMICOLON));
3620 } else {
3621 reportError8(ParserErrorCode.MISSING_STATEMENT, []);
3622 return new EmptyStatement.full(createSyntheticToken2(TokenType.SEMICOLON ));
3623 }
3624 } else if (matches5(TokenType.SEMICOLON)) {
3625 return parseEmptyStatement();
3626 } else if (isInitializedVariableDeclaration()) {
3627 return parseVariableDeclarationStatement(commentAndMetadata);
3628 } else if (isFunctionDeclaration()) {
3629 return parseFunctionDeclarationStatement();
3630 } else if (matches5(TokenType.CLOSE_CURLY_BRACKET)) {
3631 reportError8(ParserErrorCode.MISSING_STATEMENT, []);
3632 return new EmptyStatement.full(createSyntheticToken2(TokenType.SEMICOLON)) ;
3633 } else {
3634 return new ExpressionStatement.full(parseExpression2(), expect2(TokenType. SEMICOLON));
3635 }
3636 }
3637
3638 /**
3639 * Parse a normal formal parameter.
3640 *
3641 * <pre>
3642 * normalFormalParameter ::=
3643 * functionSignature
3644 * | fieldFormalParameter
3645 * | simpleFormalParameter
3646 *
3647 * functionSignature:
3648 * metadata returnType? identifier formalParameterList
3649 *
3650 * fieldFormalParameter ::=
3651 * metadata finalConstVarOrType? 'this' '.' identifier
3652 *
3653 * simpleFormalParameter ::=
3654 * declaredIdentifier
3655 * | metadata identifier
3656 * </pre>
3657 *
3658 * @return the normal formal parameter that was parsed
3659 */
3660 NormalFormalParameter parseNormalFormalParameter() {
3661 CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
3662 FinalConstVarOrType holder = parseFinalConstVarOrType(true);
3663 Token thisKeyword = null;
3664 Token period = null;
3665 if (matches(Keyword.THIS)) {
3666 thisKeyword = andAdvance;
3667 period = expect2(TokenType.PERIOD);
3668 }
3669 SimpleIdentifier identifier = parseSimpleIdentifier();
3670 if (matches5(TokenType.OPEN_PAREN)) {
3671 FormalParameterList parameters = parseFormalParameterList();
3672 if (thisKeyword == null) {
3673 if (holder.keyword != null) {
3674 reportError9(ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, holder.keyw ord, []);
3675 }
3676 return new FunctionTypedFormalParameter.full(commentAndMetadata.comment, commentAndMetadata.metadata, holder.type, identifier, parameters);
3677 } else {
3678 return new FieldFormalParameter.full(commentAndMetadata.comment, comment AndMetadata.metadata, holder.keyword, holder.type, thisKeyword, period, identifi er, parameters);
3679 }
3680 }
3681 TypeName type = holder.type;
3682 if (type != null) {
3683 if (matches3(type.name.beginToken, Keyword.VOID)) {
3684 reportError9(ParserErrorCode.VOID_PARAMETER, type.name.beginToken, []);
3685 } else if (holder.keyword != null && matches3(holder.keyword, Keyword.VAR) ) {
3686 reportError9(ParserErrorCode.VAR_AND_TYPE, holder.keyword, []);
3687 }
3688 }
3689 if (thisKeyword != null) {
3690 return new FieldFormalParameter.full(commentAndMetadata.comment, commentAn dMetadata.metadata, holder.keyword, holder.type, thisKeyword, period, identifier , null);
3691 }
3692 return new SimpleFormalParameter.full(commentAndMetadata.comment, commentAnd Metadata.metadata, holder.keyword, holder.type, identifier);
3693 }
3694
3695 /**
3696 * Parse an operator declaration.
3697 *
3698 * <pre>
3699 * operatorDeclaration ::=
3700 * operatorSignature (';' | functionBody)
3701 *
3702 * operatorSignature ::=
3703 * 'external'? returnType? 'operator' operator formalParameterList
3704 * </pre>
3705 *
3706 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
3707 * declaration
3708 * @param externalKeyword the 'external' token
3709 * @param the return type that has already been parsed, or `null` if there was no return
3710 * type
3711 * @return the operator declaration that was parsed
3712 */
3713 MethodDeclaration parseOperator(CommentAndMetadata commentAndMetadata, Token e xternalKeyword, TypeName returnType) {
3714 Token operatorKeyword;
3715 if (matches(Keyword.OPERATOR)) {
3716 operatorKeyword = andAdvance;
3717 } else {
3718 reportError9(ParserErrorCode.MISSING_KEYWORD_OPERATOR, _currentToken, []);
3719 operatorKeyword = createSyntheticToken(Keyword.OPERATOR);
3720 }
3721 if (!_currentToken.isUserDefinableOperator) {
3722 reportError8(ParserErrorCode.NON_USER_DEFINABLE_OPERATOR, [_currentToken.l exeme]);
3723 }
3724 SimpleIdentifier name = new SimpleIdentifier.full(andAdvance);
3725 if (matches5(TokenType.EQ)) {
3726 Token previous = _currentToken.previous;
3727 if ((matches4(previous, TokenType.EQ_EQ) || matches4(previous, TokenType.B ANG_EQ)) && _currentToken.offset == previous.offset + 2) {
3728 reportError8(ParserErrorCode.INVALID_OPERATOR, ["${previous.lexeme}${_cu rrentToken.lexeme}"]);
3729 advance();
3730 }
3731 }
3732 FormalParameterList parameters = parseFormalParameterList();
3733 validateFormalParameterList(parameters);
3734 FunctionBody body = parseFunctionBody(true, ParserErrorCode.MISSING_FUNCTION _BODY, false);
3735 if (externalKeyword != null && body is! EmptyFunctionBody) {
3736 reportError8(ParserErrorCode.EXTERNAL_OPERATOR_WITH_BODY, []);
3737 }
3738 return new MethodDeclaration.full(commentAndMetadata.comment, commentAndMeta data.metadata, externalKeyword, null, returnType, null, operatorKeyword, name, p arameters, body);
3739 }
3740
3741 /**
3742 * Parse a return type if one is given, otherwise return `null` without advanc ing.
3743 *
3744 * @return the return type that was parsed
3745 */
3746 TypeName parseOptionalReturnType() {
3747 if (matches(Keyword.VOID)) {
3748 return parseReturnType();
3749 } else if (matchesIdentifier() && !matches(Keyword.GET) && !matches(Keyword. SET) && !matches(Keyword.OPERATOR) && (matchesIdentifier2(peek()) || matches4(pe ek(), TokenType.LT))) {
3750 return parseReturnType();
3751 } else if (matchesIdentifier() && matches4(peek(), TokenType.PERIOD) && matc hesIdentifier2(peek2(2)) && (matchesIdentifier2(peek2(3)) || matches4(peek2(3), TokenType.LT))) {
3752 return parseReturnType();
3753 }
3754 return null;
3755 }
3756
3757 /**
3758 * Parse a part or part-of directive.
3759 *
3760 * <pre>
3761 * partDirective ::=
3762 * metadata 'part' stringLiteral ';'
3763 *
3764 * partOfDirective ::=
3765 * metadata 'part' 'of' identifier ';'
3766 * </pre>
3767 *
3768 * @param commentAndMetadata the metadata to be associated with the directive
3769 * @return the part or part-of directive that was parsed
3770 */
3771 Directive parsePartDirective(CommentAndMetadata commentAndMetadata) {
3772 Token partKeyword = expect(Keyword.PART);
3773 if (matches2(_OF)) {
3774 Token ofKeyword = andAdvance;
3775 LibraryIdentifier libraryName = parseLibraryName(ParserErrorCode.MISSING_N AME_IN_PART_OF_DIRECTIVE, ofKeyword);
3776 Token semicolon = expect2(TokenType.SEMICOLON);
3777 return new PartOfDirective.full(commentAndMetadata.comment, commentAndMeta data.metadata, partKeyword, ofKeyword, libraryName, semicolon);
3778 }
3779 StringLiteral partUri = parseStringLiteral();
3780 Token semicolon = expect2(TokenType.SEMICOLON);
3781 return new PartDirective.full(commentAndMetadata.comment, commentAndMetadata .metadata, partKeyword, partUri, semicolon);
3782 }
3783
3784 /**
3785 * Parse a postfix expression.
3786 *
3787 * <pre>
3788 * postfixExpression ::=
3789 * assignableExpression postfixOperator
3790 * | primary selector*
3791 *
3792 * selector ::=
3793 * assignableSelector
3794 * | argumentList
3795 * </pre>
3796 *
3797 * @return the postfix expression that was parsed
3798 */
3799 Expression parsePostfixExpression() {
3800 Expression operand = parseAssignableExpression(true);
3801 if (matches5(TokenType.OPEN_SQUARE_BRACKET) || matches5(TokenType.PERIOD) || matches5(TokenType.OPEN_PAREN)) {
3802 do {
3803 if (matches5(TokenType.OPEN_PAREN)) {
3804 ArgumentList argumentList = parseArgumentList();
3805 if (operand is PropertyAccess) {
3806 PropertyAccess access = operand as PropertyAccess;
3807 operand = new MethodInvocation.full(access.target, access.operator, access.propertyName, argumentList);
3808 } else {
3809 operand = new FunctionExpressionInvocation.full(operand, argumentLis t);
3810 }
3811 } else {
3812 operand = parseAssignableSelector(operand, true);
3813 }
3814 } while (matches5(TokenType.OPEN_SQUARE_BRACKET) || matches5(TokenType.PER IOD) || matches5(TokenType.OPEN_PAREN));
3815 return operand;
3816 }
3817 if (!_currentToken.type.isIncrementOperator) {
3818 return operand;
3819 }
3820 if (operand is Literal || operand is FunctionExpressionInvocation) {
3821 reportError8(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, []);
3822 }
3823 Token operator = andAdvance;
3824 return new PostfixExpression.full(operand, operator);
3825 }
3826
3827 /**
3828 * Parse a prefixed identifier.
3829 *
3830 * <pre>
3831 * prefixedIdentifier ::=
3832 * identifier ('.' identifier)?
3833 * </pre>
3834 *
3835 * @return the prefixed identifier that was parsed
3836 */
3837 Identifier parsePrefixedIdentifier() {
3838 SimpleIdentifier qualifier = parseSimpleIdentifier();
3839 if (!matches5(TokenType.PERIOD)) {
3840 return qualifier;
3841 }
3842 Token period = andAdvance;
3843 SimpleIdentifier qualified = parseSimpleIdentifier();
3844 return new PrefixedIdentifier.full(qualifier, period, qualified);
3845 }
3846
3847 /**
3848 * Parse a primary expression.
3849 *
3850 * <pre>
3851 * primary ::=
3852 * thisExpression
3853 * | 'super' assignableSelector
3854 * | functionExpression
3855 * | literal
3856 * | identifier
3857 * | newExpression
3858 * | constObjectExpression
3859 * | '(' expression ')'
3860 * | argumentDefinitionTest
3861 *
3862 * literal ::=
3863 * nullLiteral
3864 * | booleanLiteral
3865 * | numericLiteral
3866 * | stringLiteral
3867 * | symbolLiteral
3868 * | mapLiteral
3869 * | listLiteral
3870 * </pre>
3871 *
3872 * @return the primary expression that was parsed
3873 */
3874 Expression parsePrimaryExpression() {
3875 if (matches(Keyword.THIS)) {
3876 return new ThisExpression.full(andAdvance);
3877 } else if (matches(Keyword.SUPER)) {
3878 return parseAssignableSelector(new SuperExpression.full(andAdvance), false );
3879 } else if (matches(Keyword.NULL)) {
3880 return new NullLiteral.full(andAdvance);
3881 } else if (matches(Keyword.FALSE)) {
3882 return new BooleanLiteral.full(andAdvance, false);
3883 } else if (matches(Keyword.TRUE)) {
3884 return new BooleanLiteral.full(andAdvance, true);
3885 } else if (matches5(TokenType.DOUBLE)) {
3886 Token token = andAdvance;
3887 double value = 0.0;
3888 try {
3889 value = double.parse(token.lexeme);
3890 } on FormatException catch (exception) {
3891 }
3892 return new DoubleLiteral.full(token, value);
3893 } else if (matches5(TokenType.HEXADECIMAL)) {
3894 Token token = andAdvance;
3895 int value = null;
3896 try {
3897 value = int.parse(token.lexeme.substring(2), radix: 16);
3898 } on FormatException catch (exception) {
3899 }
3900 return new IntegerLiteral.full(token, value);
3901 } else if (matches5(TokenType.INT)) {
3902 Token token = andAdvance;
3903 int value = null;
3904 try {
3905 value = int.parse(token.lexeme);
3906 } on FormatException catch (exception) {
3907 }
3908 return new IntegerLiteral.full(token, value);
3909 } else if (matches5(TokenType.STRING)) {
3910 return parseStringLiteral();
3911 } else if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
3912 return parseMapLiteral(null, null);
3913 } else if (matches5(TokenType.OPEN_SQUARE_BRACKET) || matches5(TokenType.IND EX)) {
3914 return parseListLiteral(null, null);
3915 } else if (matchesIdentifier()) {
3916 return parsePrefixedIdentifier();
3917 } else if (matches(Keyword.NEW)) {
3918 return parseNewExpression();
3919 } else if (matches(Keyword.CONST)) {
3920 return parseConstExpression();
3921 } else if (matches5(TokenType.OPEN_PAREN)) {
3922 if (isFunctionExpression(_currentToken)) {
3923 return parseFunctionExpression();
3924 }
3925 Token leftParenthesis = andAdvance;
3926 Expression expression = parseExpression2();
3927 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
3928 return new ParenthesizedExpression.full(leftParenthesis, expression, right Parenthesis);
3929 } else if (matches5(TokenType.LT)) {
3930 return parseListOrMapLiteral(null);
3931 } else if (matches5(TokenType.QUESTION)) {
3932 return parseArgumentDefinitionTest();
3933 } else if (matches(Keyword.VOID)) {
3934 reportError8(ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken.lexeme]);
3935 advance();
3936 return parsePrimaryExpression();
3937 } else if (matches5(TokenType.HASH)) {
3938 return parseSymbolLiteral();
3939 } else {
3940 reportError8(ParserErrorCode.MISSING_IDENTIFIER, []);
3941 return createSyntheticIdentifier();
3942 }
3943 }
3944
3945 /**
3946 * Parse a redirecting constructor invocation.
3947 *
3948 * <pre>
3949 * redirectingConstructorInvocation ::=
3950 * 'this' ('.' identifier)? arguments
3951 * </pre>
3952 *
3953 * @return the redirecting constructor invocation that was parsed
3954 */
3955 RedirectingConstructorInvocation parseRedirectingConstructorInvocation() {
3956 Token keyword = expect(Keyword.THIS);
3957 Token period = null;
3958 SimpleIdentifier constructorName = null;
3959 if (matches5(TokenType.PERIOD)) {
3960 period = andAdvance;
3961 constructorName = parseSimpleIdentifier();
3962 }
3963 ArgumentList argumentList = parseArgumentList();
3964 return new RedirectingConstructorInvocation.full(keyword, period, constructo rName, argumentList);
3965 }
3966
3967 /**
3968 * Parse a relational expression.
3969 *
3970 * <pre>
3971 * relationalExpression ::=
3972 * bitwiseOrExpression ('is' '!'? type | 'as' type | relationalOperator bi twiseOrExpression)?
3973 * | 'super' relationalOperator bitwiseOrExpression
3974 * </pre>
3975 *
3976 * @return the relational expression that was parsed
3977 */
3978 Expression parseRelationalExpression() {
3979 if (matches(Keyword.SUPER) && _currentToken.next.type.isRelationalOperator) {
3980 Expression expression = new SuperExpression.full(andAdvance);
3981 Token operator = andAdvance;
3982 expression = new BinaryExpression.full(expression, operator, parseBitwiseO rExpression());
3983 return expression;
3984 }
3985 Expression expression = parseBitwiseOrExpression();
3986 if (matches(Keyword.AS)) {
3987 Token asOperator = andAdvance;
3988 expression = new AsExpression.full(expression, asOperator, parseTypeName() );
3989 } else if (matches(Keyword.IS)) {
3990 Token isOperator = andAdvance;
3991 Token notOperator = null;
3992 if (matches5(TokenType.BANG)) {
3993 notOperator = andAdvance;
3994 }
3995 expression = new IsExpression.full(expression, isOperator, notOperator, pa rseTypeName());
3996 } else if (_currentToken.type.isRelationalOperator) {
3997 Token operator = andAdvance;
3998 expression = new BinaryExpression.full(expression, operator, parseBitwiseO rExpression());
3999 }
4000 return expression;
4001 }
4002
4003 /**
4004 * Parse a rethrow expression.
4005 *
4006 * <pre>
4007 * rethrowExpression ::=
4008 * 'rethrow'
4009 * </pre>
4010 *
4011 * @return the rethrow expression that was parsed
4012 */
4013 Expression parseRethrowExpression() => new RethrowExpression.full(expect(Keywo rd.RETHROW));
4014
4015 /**
4016 * Parse a return statement.
4017 *
4018 * <pre>
4019 * returnStatement ::=
4020 * 'return' expression? ';'
4021 * </pre>
4022 *
4023 * @return the return statement that was parsed
4024 */
4025 Statement parseReturnStatement() {
4026 Token returnKeyword = expect(Keyword.RETURN);
4027 if (matches5(TokenType.SEMICOLON)) {
4028 return new ReturnStatement.full(returnKeyword, null, andAdvance);
4029 }
4030 Expression expression = parseExpression2();
4031 Token semicolon = expect2(TokenType.SEMICOLON);
4032 return new ReturnStatement.full(returnKeyword, expression, semicolon);
4033 }
4034
4035 /**
4036 * Parse a return type.
4037 *
4038 * <pre>
4039 * returnType ::=
4040 * 'void'
4041 * | type
4042 * </pre>
4043 *
4044 * @return the return type that was parsed
4045 */
4046 TypeName parseReturnType() {
4047 if (matches(Keyword.VOID)) {
4048 return new TypeName.full(new SimpleIdentifier.full(andAdvance), null);
4049 } else {
4050 return parseTypeName();
4051 }
4052 }
4053
4054 /**
4055 * Parse a setter.
4056 *
4057 * <pre>
4058 * setter ::=
4059 * setterSignature functionBody?
4060 *
4061 * setterSignature ::=
4062 * 'external'? 'static'? returnType? 'set' identifier formalParameterList
4063 * </pre>
4064 *
4065 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
4066 * declaration
4067 * @param externalKeyword the 'external' token
4068 * @param staticKeyword the static keyword, or `null` if the setter is not sta tic
4069 * @param the return type that has already been parsed, or `null` if there was no return
4070 * type
4071 * @return the setter that was parsed
4072 */
4073 MethodDeclaration parseSetter(CommentAndMetadata commentAndMetadata, Token ext ernalKeyword, Token staticKeyword, TypeName returnType) {
4074 Token propertyKeyword = expect(Keyword.SET);
4075 SimpleIdentifier name = parseSimpleIdentifier();
4076 FormalParameterList parameters = parseFormalParameterList();
4077 validateFormalParameterList(parameters);
4078 FunctionBody body = parseFunctionBody(externalKeyword != null || staticKeywo rd == null, ParserErrorCode.STATIC_SETTER_WITHOUT_BODY, false);
4079 if (externalKeyword != null && body is! EmptyFunctionBody) {
4080 reportError8(ParserErrorCode.EXTERNAL_SETTER_WITH_BODY, []);
4081 }
4082 return new MethodDeclaration.full(commentAndMetadata.comment, commentAndMeta data.metadata, externalKeyword, staticKeyword, returnType, propertyKeyword, null , name, parameters, body);
4083 }
4084
4085 /**
4086 * Parse a shift expression.
4087 *
4088 * <pre>
4089 * shiftExpression ::=
4090 * additiveExpression (shiftOperator additiveExpression)*
4091 * | 'super' (shiftOperator additiveExpression)+
4092 * </pre>
4093 *
4094 * @return the shift expression that was parsed
4095 */
4096 Expression parseShiftExpression() {
4097 Expression expression;
4098 if (matches(Keyword.SUPER) && _currentToken.next.type.isShiftOperator) {
4099 expression = new SuperExpression.full(andAdvance);
4100 } else {
4101 expression = parseAdditiveExpression();
4102 }
4103 while (_currentToken.type.isShiftOperator) {
4104 Token operator = andAdvance;
4105 expression = new BinaryExpression.full(expression, operator, parseAdditive Expression());
4106 }
4107 return expression;
4108 }
4109
4110 /**
4111 * Parse a simple identifier.
4112 *
4113 * <pre>
4114 * identifier ::=
4115 * IDENTIFIER
4116 * </pre>
4117 *
4118 * @return the simple identifier that was parsed
4119 */
4120 SimpleIdentifier parseSimpleIdentifier() {
4121 if (matchesIdentifier()) {
4122 return new SimpleIdentifier.full(andAdvance);
4123 }
4124 reportError8(ParserErrorCode.MISSING_IDENTIFIER, []);
4125 return createSyntheticIdentifier();
4126 }
4127
4128 /**
4129 * Parse a statement.
4130 *
4131 * <pre>
4132 * statement ::=
4133 * label* nonLabeledStatement
4134 * </pre>
4135 *
4136 * @return the statement that was parsed
4137 */
4138 Statement parseStatement2() {
4139 List<Label> labels = new List<Label>();
4140 while (matchesIdentifier() && matches4(peek(), TokenType.COLON)) {
4141 SimpleIdentifier label = parseSimpleIdentifier();
4142 Token colon = expect2(TokenType.COLON);
4143 labels.add(new Label.full(label, colon));
4144 }
4145 Statement statement = parseNonLabeledStatement();
4146 if (labels.isEmpty) {
4147 return statement;
4148 }
4149 return new LabeledStatement.full(labels, statement);
4150 }
4151
4152 /**
4153 * Parse a list of statements within a switch statement.
4154 *
4155 * <pre>
4156 * statements ::=
4157 * statement*
4158 * </pre>
4159 *
4160 * @return the statements that were parsed
4161 */
4162 List<Statement> parseStatements2() {
4163 List<Statement> statements = new List<Statement>();
4164 Token statementStart = _currentToken;
4165 while (!matches5(TokenType.EOF) && !matches5(TokenType.CLOSE_CURLY_BRACKET) && !isSwitchMember()) {
4166 statements.add(parseStatement2());
4167 if (identical(_currentToken, statementStart)) {
4168 reportError9(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_currentT oken.lexeme]);
4169 advance();
4170 }
4171 statementStart = _currentToken;
4172 }
4173 return statements;
4174 }
4175
4176 /**
4177 * Parse a string literal that contains interpolations.
4178 *
4179 * @return the string literal that was parsed
4180 */
4181 StringInterpolation parseStringInterpolation(Token string) {
4182 List<InterpolationElement> elements = new List<InterpolationElement>();
4183 bool hasMore = matches5(TokenType.STRING_INTERPOLATION_EXPRESSION) || matche s5(TokenType.STRING_INTERPOLATION_IDENTIFIER);
4184 elements.add(new InterpolationString.full(string, computeStringValue(string. lexeme, true, !hasMore)));
4185 while (hasMore) {
4186 if (matches5(TokenType.STRING_INTERPOLATION_EXPRESSION)) {
4187 Token openToken = andAdvance;
4188 Expression expression = parseExpression2();
4189 Token rightBracket = expect2(TokenType.CLOSE_CURLY_BRACKET);
4190 elements.add(new InterpolationExpression.full(openToken, expression, rig htBracket));
4191 } else {
4192 Token openToken = andAdvance;
4193 Expression expression = null;
4194 if (matches(Keyword.THIS)) {
4195 expression = new ThisExpression.full(andAdvance);
4196 } else {
4197 expression = parseSimpleIdentifier();
4198 }
4199 elements.add(new InterpolationExpression.full(openToken, expression, nul l));
4200 }
4201 if (matches5(TokenType.STRING)) {
4202 string = andAdvance;
4203 hasMore = matches5(TokenType.STRING_INTERPOLATION_EXPRESSION) || matches 5(TokenType.STRING_INTERPOLATION_IDENTIFIER);
4204 elements.add(new InterpolationString.full(string, computeStringValue(str ing.lexeme, false, !hasMore)));
4205 }
4206 }
4207 return new StringInterpolation.full(elements);
4208 }
4209
4210 /**
4211 * Parse a string literal.
4212 *
4213 * <pre>
4214 * stringLiteral ::=
4215 * MULTI_LINE_STRING+
4216 * | SINGLE_LINE_STRING+
4217 * </pre>
4218 *
4219 * @return the string literal that was parsed
4220 */
4221 StringLiteral parseStringLiteral() {
4222 List<StringLiteral> strings = new List<StringLiteral>();
4223 while (matches5(TokenType.STRING)) {
4224 Token string = andAdvance;
4225 if (matches5(TokenType.STRING_INTERPOLATION_EXPRESSION) || matches5(TokenT ype.STRING_INTERPOLATION_IDENTIFIER)) {
4226 strings.add(parseStringInterpolation(string));
4227 } else {
4228 strings.add(new SimpleStringLiteral.full(string, computeStringValue(stri ng.lexeme, true, true)));
4229 }
4230 }
4231 if (strings.length < 1) {
4232 reportError8(ParserErrorCode.EXPECTED_STRING_LITERAL, []);
4233 return createSyntheticStringLiteral();
4234 } else if (strings.length == 1) {
4235 return strings[0];
4236 } else {
4237 return new AdjacentStrings.full(strings);
4238 }
4239 }
4240
4241 /**
4242 * Parse a super constructor invocation.
4243 *
4244 * <pre>
4245 * superConstructorInvocation ::=
4246 * 'super' ('.' identifier)? arguments
4247 * </pre>
4248 *
4249 * @return the super constructor invocation that was parsed
4250 */
4251 SuperConstructorInvocation parseSuperConstructorInvocation() {
4252 Token keyword = expect(Keyword.SUPER);
4253 Token period = null;
4254 SimpleIdentifier constructorName = null;
4255 if (matches5(TokenType.PERIOD)) {
4256 period = andAdvance;
4257 constructorName = parseSimpleIdentifier();
4258 }
4259 ArgumentList argumentList = parseArgumentList();
4260 return new SuperConstructorInvocation.full(keyword, period, constructorName, argumentList);
4261 }
4262
4263 /**
4264 * Parse a switch statement.
4265 *
4266 * <pre>
4267 * switchStatement ::=
4268 * 'switch' '(' expression ')' '{' switchCase* defaultCase? '}'
4269 *
4270 * switchCase ::=
4271 * label* ('case' expression ':') statements
4272 *
4273 * defaultCase ::=
4274 * label* 'default' ':' statements
4275 * </pre>
4276 *
4277 * @return the switch statement that was parsed
4278 */
4279 SwitchStatement parseSwitchStatement() {
4280 bool wasInSwitch = _inSwitch;
4281 _inSwitch = true;
4282 try {
4283 Set<String> definedLabels = new Set<String>();
4284 Token keyword = expect(Keyword.SWITCH);
4285 Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
4286 Expression expression = parseExpression2();
4287 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
4288 Token leftBracket = expect2(TokenType.OPEN_CURLY_BRACKET);
4289 Token defaultKeyword = null;
4290 List<SwitchMember> members = new List<SwitchMember>();
4291 while (!matches5(TokenType.EOF) && !matches5(TokenType.CLOSE_CURLY_BRACKET )) {
4292 List<Label> labels = new List<Label>();
4293 while (matchesIdentifier() && matches4(peek(), TokenType.COLON)) {
4294 SimpleIdentifier identifier = parseSimpleIdentifier();
4295 String label = identifier.token.lexeme;
4296 if (definedLabels.contains(label)) {
4297 reportError9(ParserErrorCode.DUPLICATE_LABEL_IN_SWITCH_STATEMENT, id entifier.token, [label]);
4298 } else {
4299 javaSetAdd(definedLabels, label);
4300 }
4301 Token colon = expect2(TokenType.COLON);
4302 labels.add(new Label.full(identifier, colon));
4303 }
4304 if (matches(Keyword.CASE)) {
4305 Token caseKeyword = andAdvance;
4306 Expression caseExpression = parseExpression2();
4307 Token colon = expect2(TokenType.COLON);
4308 members.add(new SwitchCase.full(labels, caseKeyword, caseExpression, c olon, parseStatements2()));
4309 if (defaultKeyword != null) {
4310 reportError9(ParserErrorCode.SWITCH_HAS_CASE_AFTER_DEFAULT_CASE, cas eKeyword, []);
4311 }
4312 } else if (matches(Keyword.DEFAULT)) {
4313 if (defaultKeyword != null) {
4314 reportError9(ParserErrorCode.SWITCH_HAS_MULTIPLE_DEFAULT_CASES, peek (), []);
4315 }
4316 defaultKeyword = andAdvance;
4317 Token colon = expect2(TokenType.COLON);
4318 members.add(new SwitchDefault.full(labels, defaultKeyword, colon, pars eStatements2()));
4319 } else {
4320 reportError8(ParserErrorCode.EXPECTED_CASE_OR_DEFAULT, []);
4321 while (!matches5(TokenType.EOF) && !matches5(TokenType.CLOSE_CURLY_BRA CKET) && !matches(Keyword.CASE) && !matches(Keyword.DEFAULT)) {
4322 advance();
4323 }
4324 }
4325 }
4326 Token rightBracket = expect2(TokenType.CLOSE_CURLY_BRACKET);
4327 return new SwitchStatement.full(keyword, leftParenthesis, expression, righ tParenthesis, leftBracket, members, rightBracket);
4328 } finally {
4329 _inSwitch = wasInSwitch;
4330 }
4331 }
4332
4333 /**
4334 * Parse a symbol literal.
4335 *
4336 * <pre>
4337 * symbolLiteral ::=
4338 * '#' identifier ('.' identifier)*
4339 * </pre>
4340 *
4341 * @return the symbol literal that was parsed
4342 */
4343 SymbolLiteral parseSymbolLiteral() {
4344 Token poundSign = andAdvance;
4345 List<Token> components = new List<Token>();
4346 if (matchesIdentifier()) {
4347 components.add(andAdvance);
4348 while (matches5(TokenType.PERIOD)) {
4349 advance();
4350 if (matchesIdentifier()) {
4351 components.add(andAdvance);
4352 } else {
4353 reportError8(ParserErrorCode.MISSING_IDENTIFIER, []);
4354 components.add(createSyntheticToken2(TokenType.IDENTIFIER));
4355 break;
4356 }
4357 }
4358 } else if (_currentToken.isOperator) {
4359 components.add(andAdvance);
4360 } else {
4361 reportError8(ParserErrorCode.MISSING_IDENTIFIER, []);
4362 components.add(createSyntheticToken2(TokenType.IDENTIFIER));
4363 }
4364 return new SymbolLiteral.full(poundSign, new List.from(components));
4365 }
4366
4367 /**
4368 * Parse a throw expression.
4369 *
4370 * <pre>
4371 * throwExpression ::=
4372 * 'throw' expression
4373 * </pre>
4374 *
4375 * @return the throw expression that was parsed
4376 */
4377 Expression parseThrowExpression() {
4378 Token keyword = expect(Keyword.THROW);
4379 if (matches5(TokenType.SEMICOLON) || matches5(TokenType.CLOSE_PAREN)) {
4380 reportError9(ParserErrorCode.MISSING_EXPRESSION_IN_THROW, _currentToken, [ ]);
4381 return new ThrowExpression.full(keyword, createSyntheticIdentifier());
4382 }
4383 Expression expression = parseExpression2();
4384 return new ThrowExpression.full(keyword, expression);
4385 }
4386
4387 /**
4388 * Parse a throw expression.
4389 *
4390 * <pre>
4391 * throwExpressionWithoutCascade ::=
4392 * 'throw' expressionWithoutCascade
4393 * </pre>
4394 *
4395 * @return the throw expression that was parsed
4396 */
4397 Expression parseThrowExpressionWithoutCascade() {
4398 Token keyword = expect(Keyword.THROW);
4399 if (matches5(TokenType.SEMICOLON) || matches5(TokenType.CLOSE_PAREN)) {
4400 reportError9(ParserErrorCode.MISSING_EXPRESSION_IN_THROW, _currentToken, [ ]);
4401 return new ThrowExpression.full(keyword, createSyntheticIdentifier());
4402 }
4403 Expression expression = parseExpressionWithoutCascade();
4404 return new ThrowExpression.full(keyword, expression);
4405 }
4406
4407 /**
4408 * Parse a try statement.
4409 *
4410 * <pre>
4411 * tryStatement ::=
4412 * 'try' block (onPart+ finallyPart? | finallyPart)
4413 *
4414 * onPart ::=
4415 * catchPart block
4416 * | 'on' type catchPart? block
4417 *
4418 * catchPart ::=
4419 * 'catch' '(' identifier (',' identifier)? ')'
4420 *
4421 * finallyPart ::=
4422 * 'finally' block
4423 * </pre>
4424 *
4425 * @return the try statement that was parsed
4426 */
4427 Statement parseTryStatement() {
4428 Token tryKeyword = expect(Keyword.TRY);
4429 Block body = parseBlock();
4430 List<CatchClause> catchClauses = new List<CatchClause>();
4431 Block finallyClause = null;
4432 while (matches2(_ON) || matches(Keyword.CATCH)) {
4433 Token onKeyword = null;
4434 TypeName exceptionType = null;
4435 if (matches2(_ON)) {
4436 onKeyword = andAdvance;
4437 exceptionType = parseTypeName();
4438 }
4439 Token catchKeyword = null;
4440 Token leftParenthesis = null;
4441 SimpleIdentifier exceptionParameter = null;
4442 Token comma = null;
4443 SimpleIdentifier stackTraceParameter = null;
4444 Token rightParenthesis = null;
4445 if (matches(Keyword.CATCH)) {
4446 catchKeyword = andAdvance;
4447 leftParenthesis = expect2(TokenType.OPEN_PAREN);
4448 exceptionParameter = parseSimpleIdentifier();
4449 if (matches5(TokenType.COMMA)) {
4450 comma = andAdvance;
4451 stackTraceParameter = parseSimpleIdentifier();
4452 }
4453 rightParenthesis = expect2(TokenType.CLOSE_PAREN);
4454 }
4455 Block catchBody = parseBlock();
4456 catchClauses.add(new CatchClause.full(onKeyword, exceptionType, catchKeywo rd, leftParenthesis, exceptionParameter, comma, stackTraceParameter, rightParent hesis, catchBody));
4457 }
4458 Token finallyKeyword = null;
4459 if (matches(Keyword.FINALLY)) {
4460 finallyKeyword = andAdvance;
4461 finallyClause = parseBlock();
4462 } else {
4463 if (catchClauses.isEmpty) {
4464 reportError8(ParserErrorCode.MISSING_CATCH_OR_FINALLY, []);
4465 }
4466 }
4467 return new TryStatement.full(tryKeyword, body, catchClauses, finallyKeyword, finallyClause);
4468 }
4469
4470 /**
4471 * Parse a type alias.
4472 *
4473 * <pre>
4474 * typeAlias ::=
4475 * 'typedef' typeAliasBody
4476 *
4477 * typeAliasBody ::=
4478 * classTypeAlias
4479 * | functionTypeAlias
4480 *
4481 * classTypeAlias ::=
4482 * identifier typeParameters? '=' 'abstract'? mixinApplication
4483 *
4484 * mixinApplication ::=
4485 * qualified withClause implementsClause? ';'
4486 *
4487 * functionTypeAlias ::=
4488 * functionPrefix typeParameterList? formalParameterList ';'
4489 *
4490 * functionPrefix ::=
4491 * returnType? name
4492 * </pre>
4493 *
4494 * @param commentAndMetadata the metadata to be associated with the member
4495 * @return the type alias that was parsed
4496 */
4497 TypeAlias parseTypeAlias(CommentAndMetadata commentAndMetadata) {
4498 Token keyword = expect(Keyword.TYPEDEF);
4499 if (matchesIdentifier()) {
4500 Token next = peek();
4501 if (matches4(next, TokenType.LT)) {
4502 next = skipTypeParameterList(next);
4503 if (next != null && matches4(next, TokenType.EQ)) {
4504 TypeAlias typeAlias = parseClassTypeAlias(commentAndMetadata, keyword) ;
4505 reportError9(ParserErrorCode.DEPRECATED_CLASS_TYPE_ALIAS, keyword, []) ;
4506 return typeAlias;
4507 }
4508 } else if (matches4(next, TokenType.EQ)) {
4509 TypeAlias typeAlias = parseClassTypeAlias(commentAndMetadata, keyword);
4510 reportError9(ParserErrorCode.DEPRECATED_CLASS_TYPE_ALIAS, keyword, []);
4511 return typeAlias;
4512 }
4513 }
4514 return parseFunctionTypeAlias(commentAndMetadata, keyword);
4515 }
4516
4517 /**
4518 * Parse a list of type arguments.
4519 *
4520 * <pre>
4521 * typeArguments ::=
4522 * '<' typeList '>'
4523 *
4524 * typeList ::=
4525 * type (',' type)*
4526 * </pre>
4527 *
4528 * @return the type argument list that was parsed
4529 */
4530 TypeArgumentList parseTypeArgumentList() {
4531 Token leftBracket = expect2(TokenType.LT);
4532 List<TypeName> arguments = new List<TypeName>();
4533 arguments.add(parseTypeName());
4534 while (optional(TokenType.COMMA)) {
4535 arguments.add(parseTypeName());
4536 }
4537 Token rightBracket = expect2(TokenType.GT);
4538 return new TypeArgumentList.full(leftBracket, arguments, rightBracket);
4539 }
4540
4541 /**
4542 * Parse a type name.
4543 *
4544 * <pre>
4545 * type ::=
4546 * qualified typeArguments?
4547 * </pre>
4548 *
4549 * @return the type name that was parsed
4550 */
4551 TypeName parseTypeName() {
4552 Identifier typeName;
4553 if (matches(Keyword.VAR)) {
4554 reportError8(ParserErrorCode.VAR_AS_TYPE_NAME, []);
4555 typeName = new SimpleIdentifier.full(andAdvance);
4556 } else if (matchesIdentifier()) {
4557 typeName = parsePrefixedIdentifier();
4558 } else {
4559 typeName = createSyntheticIdentifier();
4560 reportError8(ParserErrorCode.EXPECTED_TYPE_NAME, []);
4561 }
4562 TypeArgumentList typeArguments = null;
4563 if (matches5(TokenType.LT)) {
4564 typeArguments = parseTypeArgumentList();
4565 }
4566 return new TypeName.full(typeName, typeArguments);
4567 }
4568
4569 /**
4570 * Parse a type parameter.
4571 *
4572 * <pre>
4573 * typeParameter ::=
4574 * metadata name ('extends' bound)?
4575 * </pre>
4576 *
4577 * @return the type parameter that was parsed
4578 */
4579 TypeParameter parseTypeParameter() {
4580 CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
4581 SimpleIdentifier name = parseSimpleIdentifier();
4582 if (matches(Keyword.EXTENDS)) {
4583 Token keyword = andAdvance;
4584 TypeName bound = parseTypeName();
4585 return new TypeParameter.full(commentAndMetadata.comment, commentAndMetada ta.metadata, name, keyword, bound);
4586 }
4587 return new TypeParameter.full(commentAndMetadata.comment, commentAndMetadata .metadata, name, null, null);
4588 }
4589
4590 /**
4591 * Parse a list of type parameters.
4592 *
4593 * <pre>
4594 * typeParameterList ::=
4595 * '<' typeParameter (',' typeParameter)* '>'
4596 * </pre>
4597 *
4598 * @return the list of type parameters that were parsed
4599 */
4600 TypeParameterList parseTypeParameterList() {
4601 Token leftBracket = expect2(TokenType.LT);
4602 List<TypeParameter> typeParameters = new List<TypeParameter>();
4603 typeParameters.add(parseTypeParameter());
4604 while (optional(TokenType.COMMA)) {
4605 typeParameters.add(parseTypeParameter());
4606 }
4607 Token rightBracket = expect2(TokenType.GT);
4608 return new TypeParameterList.full(leftBracket, typeParameters, rightBracket) ;
4609 }
4610
4611 /**
4612 * Parse a unary expression.
4613 *
4614 * <pre>
4615 * unaryExpression ::=
4616 * prefixOperator unaryExpression
4617 * | postfixExpression
4618 * | unaryOperator 'super'
4619 * | '-' 'super'
4620 * | incrementOperator assignableExpression
4621 * </pre>
4622 *
4623 * @return the unary expression that was parsed
4624 */
4625 Expression parseUnaryExpression() {
4626 if (matches5(TokenType.MINUS) || matches5(TokenType.BANG) || matches5(TokenT ype.TILDE)) {
4627 Token operator = andAdvance;
4628 if (matches(Keyword.SUPER)) {
4629 if (matches4(peek(), TokenType.OPEN_SQUARE_BRACKET) || matches4(peek(), TokenType.PERIOD)) {
4630 return new PrefixExpression.full(operator, parseUnaryExpression());
4631 }
4632 return new PrefixExpression.full(operator, new SuperExpression.full(andA dvance));
4633 }
4634 return new PrefixExpression.full(operator, parseUnaryExpression());
4635 } else if (_currentToken.type.isIncrementOperator) {
4636 Token operator = andAdvance;
4637 if (matches(Keyword.SUPER)) {
4638 if (matches4(peek(), TokenType.OPEN_SQUARE_BRACKET) || matches4(peek(), TokenType.PERIOD)) {
4639 return new PrefixExpression.full(operator, parseUnaryExpression());
4640 }
4641 if (identical(operator.type, TokenType.MINUS_MINUS)) {
4642 int offset = operator.offset;
4643 Token firstOperator = new Token(TokenType.MINUS, offset);
4644 Token secondOperator = new Token(TokenType.MINUS, offset + 1);
4645 secondOperator.setNext(_currentToken);
4646 firstOperator.setNext(secondOperator);
4647 operator.previous.setNext(firstOperator);
4648 return new PrefixExpression.full(firstOperator, new PrefixExpression.f ull(secondOperator, new SuperExpression.full(andAdvance)));
4649 } else {
4650 reportError8(ParserErrorCode.INVALID_OPERATOR_FOR_SUPER, [operator.lex eme]);
4651 return new PrefixExpression.full(operator, new SuperExpression.full(an dAdvance));
4652 }
4653 }
4654 return new PrefixExpression.full(operator, parseAssignableExpression(false ));
4655 } else if (matches5(TokenType.PLUS)) {
4656 reportError8(ParserErrorCode.MISSING_IDENTIFIER, []);
4657 return createSyntheticIdentifier();
4658 }
4659 return parsePostfixExpression();
4660 }
4661
4662 /**
4663 * Parse a variable declaration.
4664 *
4665 * <pre>
4666 * variableDeclaration ::=
4667 * identifier ('=' expression)?
4668 * </pre>
4669 *
4670 * @return the variable declaration that was parsed
4671 */
4672 VariableDeclaration parseVariableDeclaration() {
4673 CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
4674 SimpleIdentifier name = parseSimpleIdentifier();
4675 Token equals = null;
4676 Expression initializer = null;
4677 if (matches5(TokenType.EQ)) {
4678 equals = andAdvance;
4679 initializer = parseExpression2();
4680 }
4681 return new VariableDeclaration.full(commentAndMetadata.comment, commentAndMe tadata.metadata, name, equals, initializer);
4682 }
4683
4684 /**
4685 * Parse a variable declaration list.
4686 *
4687 * <pre>
4688 * variableDeclarationList ::=
4689 * finalConstVarOrType variableDeclaration (',' variableDeclaration)*
4690 * </pre>
4691 *
4692 * @param commentAndMetadata the metadata to be associated with the variable d eclaration list
4693 * @return the variable declaration list that was parsed
4694 */
4695 VariableDeclarationList parseVariableDeclarationList(CommentAndMetadata commen tAndMetadata) {
4696 FinalConstVarOrType holder = parseFinalConstVarOrType(false);
4697 return parseVariableDeclarationList2(commentAndMetadata, holder.keyword, hol der.type);
4698 }
4699
4700 /**
4701 * Parse a variable declaration list.
4702 *
4703 * <pre>
4704 * variableDeclarationList ::=
4705 * finalConstVarOrType variableDeclaration (',' variableDeclaration)*
4706 * </pre>
4707 *
4708 * @param commentAndMetadata the metadata to be associated with the variable d eclaration list, or
4709 * `null` if there is no attempt at parsing the comment and metadata
4710 * @param keyword the token representing the 'final', 'const' or 'var' keyword , or `null` if
4711 * there is no keyword
4712 * @param type the type of the variables in the list
4713 * @return the variable declaration list that was parsed
4714 */
4715 VariableDeclarationList parseVariableDeclarationList2(CommentAndMetadata comme ntAndMetadata, Token keyword, TypeName type) {
4716 if (type != null && keyword != null && matches3(keyword, Keyword.VAR)) {
4717 reportError9(ParserErrorCode.VAR_AND_TYPE, keyword, []);
4718 }
4719 List<VariableDeclaration> variables = new List<VariableDeclaration>();
4720 variables.add(parseVariableDeclaration());
4721 while (matches5(TokenType.COMMA)) {
4722 advance();
4723 variables.add(parseVariableDeclaration());
4724 }
4725 return new VariableDeclarationList.full(commentAndMetadata != null ? comment AndMetadata.comment : null, commentAndMetadata != null ? commentAndMetadata.meta data : null, keyword, type, variables);
4726 }
4727
4728 /**
4729 * Parse a variable declaration statement.
4730 *
4731 * <pre>
4732 * variableDeclarationStatement ::=
4733 * variableDeclarationList ';'
4734 * </pre>
4735 *
4736 * @param commentAndMetadata the metadata to be associated with the variable d eclaration
4737 * statement, or `null` if there is no attempt at parsing the comment and metadata
4738 * @return the variable declaration statement that was parsed
4739 */
4740 VariableDeclarationStatement parseVariableDeclarationStatement(CommentAndMetad ata commentAndMetadata) {
4741 VariableDeclarationList variableList = parseVariableDeclarationList(commentA ndMetadata);
4742 Token semicolon = expect2(TokenType.SEMICOLON);
4743 return new VariableDeclarationStatement.full(variableList, semicolon);
4744 }
4745
4746 /**
4747 * Parse a variable declaration statement.
4748 *
4749 * <pre>
4750 * variableDeclarationStatement ::=
4751 * variableDeclarationList ';'
4752 * </pre>
4753 *
4754 * @param commentAndMetadata the metadata to be associated with the variable d eclaration
4755 * statement, or `null` if there is no attempt at parsing the comment and metadata
4756 * @param keyword the token representing the 'final', 'const' or 'var' keyword , or `null` if
4757 * there is no keyword
4758 * @param type the type of the variables in the list
4759 * @return the variable declaration statement that was parsed
4760 */
4761 VariableDeclarationStatement parseVariableDeclarationStatement2(CommentAndMeta data commentAndMetadata, Token keyword, TypeName type) {
4762 VariableDeclarationList variableList = parseVariableDeclarationList2(comment AndMetadata, keyword, type);
4763 Token semicolon = expect2(TokenType.SEMICOLON);
4764 return new VariableDeclarationStatement.full(variableList, semicolon);
4765 }
4766
4767 /**
4768 * Parse a while statement.
4769 *
4770 * <pre>
4771 * whileStatement ::=
4772 * 'while' '(' expression ')' statement
4773 * </pre>
4774 *
4775 * @return the while statement that was parsed
4776 */
4777 Statement parseWhileStatement() {
4778 bool wasInLoop = _inLoop;
4779 _inLoop = true;
4780 try {
4781 Token keyword = expect(Keyword.WHILE);
4782 Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
4783 Expression condition = parseExpression2();
4784 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
4785 Statement body = parseStatement2();
4786 return new WhileStatement.full(keyword, leftParenthesis, condition, rightP arenthesis, body);
4787 } finally {
4788 _inLoop = wasInLoop;
4789 }
4790 }
4791
4792 /**
4793 * Parse a with clause.
4794 *
4795 * <pre>
4796 * withClause ::=
4797 * 'with' typeName (',' typeName)*
4798 * </pre>
4799 *
4800 * @return the with clause that was parsed
4801 */
4802 WithClause parseWithClause() {
4803 Token with2 = expect(Keyword.WITH);
4804 List<TypeName> types = new List<TypeName>();
4805 types.add(parseTypeName());
4806 while (optional(TokenType.COMMA)) {
4807 types.add(parseTypeName());
4808 }
4809 return new WithClause.full(with2, types);
4810 }
4811
4812 /**
4813 * Return the token that is immediately after the current token. This is equiv alent to
4814 * [peek].
4815 *
4816 * @return the token that is immediately after the current token
4817 */
4818 Token peek() => _currentToken.next;
4819
4820 /**
4821 * Return the token that is the given distance after the current token.
4822 *
4823 * @param distance the number of tokens to look ahead, where `0` is the curren t token,
4824 * `1` is the next token, etc.
4825 * @return the token that is the given distance after the current token
4826 */
4827 Token peek2(int distance) {
4828 Token token = _currentToken;
4829 for (int i = 0; i < distance; i++) {
4830 token = token.next;
4831 }
4832 return token;
4833 }
4834
4835 /**
4836 * Report an error with the given error code and arguments.
4837 *
4838 * @param errorCode the error code of the error to be reported
4839 * @param node the node specifying the location of the error
4840 * @param arguments the arguments to the error, used to compose the error mess age
4841 */
4842 void reportError(ParserErrorCode errorCode, ASTNode node, List<Object> argumen ts) {
4843 _errorListener.onError(new AnalysisError.con2(_source, node.offset, node.len gth, errorCode, arguments));
4844 }
4845
4846 /**
4847 * Report an error with the given error code and arguments.
4848 *
4849 * @param errorCode the error code of the error to be reported
4850 * @param arguments the arguments to the error, used to compose the error mess age
4851 */
4852 void reportError8(ParserErrorCode errorCode, List<Object> arguments) {
4853 reportError9(errorCode, _currentToken, arguments);
4854 }
4855
4856 /**
4857 * Report an error with the given error code and arguments.
4858 *
4859 * @param errorCode the error code of the error to be reported
4860 * @param token the token specifying the location of the error
4861 * @param arguments the arguments to the error, used to compose the error mess age
4862 */
4863 void reportError9(ParserErrorCode errorCode, Token token, List<Object> argumen ts) {
4864 _errorListener.onError(new AnalysisError.con2(_source, token.offset, token.l ength, errorCode, arguments));
4865 }
4866
4867 /**
4868 * Look for user defined tasks in comments and convert them into info level an alysis issues.
4869 *
4870 * @param commentToken the comment token to analyze
4871 */
4872 void scrapeTodoComment(Token commentToken) {
4873 JavaPatternMatcher matcher = new JavaPatternMatcher(TodoCode.TODO_REGEX, com mentToken.lexeme);
4874 if (matcher.find()) {
4875 int offset = commentToken.offset + matcher.start() + matcher.group(1).leng th;
4876 int length = matcher.group(2).length;
4877 // _errorListener.onError(new AnalysisError.con2(_source, offset, length, TodoCode.TODO, [matcher.group(2)]));
4878 }
4879 }
4880
4881 /**
4882 * Parse the 'final', 'const', 'var' or type preceding a variable declaration, starting at the
4883 * given token, without actually creating a type or changing the current token . Return the token
4884 * following the type that was parsed, or `null` if the given token is not the first token
4885 * in a valid type.
4886 *
4887 * <pre>
4888 * finalConstVarOrType ::=
4889 * | 'final' type?
4890 * | 'const' type?
4891 * | 'var'
4892 * | type
4893 * </pre>
4894 *
4895 * @param startToken the token at which parsing is to begin
4896 * @return the token following the type that was parsed
4897 */
4898 Token skipFinalConstVarOrType(Token startToken) {
4899 if (matches3(startToken, Keyword.FINAL) || matches3(startToken, Keyword.CONS T)) {
4900 Token next = startToken.next;
4901 if (matchesIdentifier2(next.next) || matches4(next.next, TokenType.LT) || matches3(next.next, Keyword.THIS)) {
4902 return skipTypeName(next);
4903 }
4904 } else if (matches3(startToken, Keyword.VAR)) {
4905 return startToken.next;
4906 } else if (matchesIdentifier2(startToken)) {
4907 Token next = startToken.next;
4908 if (matchesIdentifier2(next) || matches4(next, TokenType.LT) || matches3(n ext, Keyword.THIS) || (matches4(next, TokenType.PERIOD) && matchesIdentifier2(ne xt.next) && (matchesIdentifier2(next.next.next) || matches4(next.next.next, Toke nType.LT) || matches3(next.next.next, Keyword.THIS)))) {
4909 return skipReturnType(startToken);
4910 }
4911 }
4912 return null;
4913 }
4914
4915 /**
4916 * Parse a list of formal parameters, starting at the given token, without act ually creating a
4917 * formal parameter list or changing the current token. Return the token follo wing the formal
4918 * parameter list that was parsed, or `null` if the given token is not the fir st token in a
4919 * valid list of formal parameter.
4920 *
4921 * Note that unlike other skip methods, this method uses a heuristic. In the w orst case, the
4922 * parameters could be prefixed by metadata, which would require us to be able to skip arbitrary
4923 * expressions. Rather than duplicate the logic of most of the parse methods w e simply look for
4924 * something that is likely to be a list of parameters and then skip to return ing the token after
4925 * the closing parenthesis.
4926 *
4927 * This method must be kept in sync with [parseFormalParameterList].
4928 *
4929 * <pre>
4930 * formalParameterList ::=
4931 * '(' ')'
4932 * | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
4933 * | '(' optionalFormalParameters ')'
4934 *
4935 * normalFormalParameters ::=
4936 * normalFormalParameter (',' normalFormalParameter)*
4937 *
4938 * optionalFormalParameters ::=
4939 * optionalPositionalFormalParameters
4940 * | namedFormalParameters
4941 *
4942 * optionalPositionalFormalParameters ::=
4943 * '[' defaultFormalParameter (',' defaultFormalParameter)* ']'
4944 *
4945 * namedFormalParameters ::=
4946 * '{' defaultNamedParameter (',' defaultNamedParameter)* '}'
4947 * </pre>
4948 *
4949 * @param startToken the token at which parsing is to begin
4950 * @return the token following the formal parameter list that was parsed
4951 */
4952 Token skipFormalParameterList(Token startToken) {
4953 if (!matches4(startToken, TokenType.OPEN_PAREN)) {
4954 return null;
4955 }
4956 Token next = startToken.next;
4957 if (matches4(next, TokenType.CLOSE_PAREN)) {
4958 return next.next;
4959 }
4960 if (matchesAny(next, [
4961 TokenType.AT,
4962 TokenType.OPEN_SQUARE_BRACKET,
4963 TokenType.OPEN_CURLY_BRACKET]) || matches3(next, Keyword.VOID) || (match esIdentifier2(next) && (matchesAny(next.next, [TokenType.COMMA, TokenType.CLOSE_ PAREN])))) {
4964 return skipPastMatchingToken(startToken);
4965 }
4966 if (matchesIdentifier2(next) && matches4(next.next, TokenType.OPEN_PAREN)) {
4967 Token afterParameters = skipFormalParameterList(next.next);
4968 if (afterParameters != null && (matchesAny(afterParameters, [TokenType.COM MA, TokenType.CLOSE_PAREN]))) {
4969 return skipPastMatchingToken(startToken);
4970 }
4971 }
4972 Token afterType = skipFinalConstVarOrType(next);
4973 if (afterType == null) {
4974 return null;
4975 }
4976 if (skipSimpleIdentifier(afterType) == null) {
4977 return null;
4978 }
4979 return skipPastMatchingToken(startToken);
4980 }
4981
4982 /**
4983 * If the given token is a begin token with an associated end token, then retu rn the token
4984 * following the end token. Otherwise, return `null`.
4985 *
4986 * @param startToken the token that is assumed to be a being token
4987 * @return the token following the matching end token
4988 */
4989 Token skipPastMatchingToken(Token startToken) {
4990 if (startToken is! BeginToken) {
4991 return null;
4992 }
4993 Token closeParen = ((startToken as BeginToken)).endToken;
4994 if (closeParen == null) {
4995 return null;
4996 }
4997 return closeParen.next;
4998 }
4999
5000 /**
5001 * Parse a prefixed identifier, starting at the given token, without actually creating a prefixed
5002 * identifier or changing the current token. Return the token following the pr efixed identifier
5003 * that was parsed, or `null` if the given token is not the first token in a v alid prefixed
5004 * identifier.
5005 *
5006 * This method must be kept in sync with [parsePrefixedIdentifier].
5007 *
5008 * <pre>
5009 * prefixedIdentifier ::=
5010 * identifier ('.' identifier)?
5011 * </pre>
5012 *
5013 * @param startToken the token at which parsing is to begin
5014 * @return the token following the prefixed identifier that was parsed
5015 */
5016 Token skipPrefixedIdentifier(Token startToken) {
5017 Token token = skipSimpleIdentifier(startToken);
5018 if (token == null) {
5019 return null;
5020 } else if (!matches4(token, TokenType.PERIOD)) {
5021 return token;
5022 }
5023 return skipSimpleIdentifier(token.next);
5024 }
5025
5026 /**
5027 * Parse a return type, starting at the given token, without actually creating a return type or
5028 * changing the current token. Return the token following the return type that was parsed, or
5029 * `null` if the given token is not the first token in a valid return type.
5030 *
5031 * This method must be kept in sync with [parseReturnType].
5032 *
5033 * <pre>
5034 * returnType ::=
5035 * 'void'
5036 * | type
5037 * </pre>
5038 *
5039 * @param startToken the token at which parsing is to begin
5040 * @return the token following the return type that was parsed
5041 */
5042 Token skipReturnType(Token startToken) {
5043 if (matches3(startToken, Keyword.VOID)) {
5044 return startToken.next;
5045 } else {
5046 return skipTypeName(startToken);
5047 }
5048 }
5049
5050 /**
5051 * Parse a simple identifier, starting at the given token, without actually cr eating a simple
5052 * identifier or changing the current token. Return the token following the si mple identifier that
5053 * was parsed, or `null` if the given token is not the first token in a valid simple
5054 * identifier.
5055 *
5056 * This method must be kept in sync with [parseSimpleIdentifier].
5057 *
5058 * <pre>
5059 * identifier ::=
5060 * IDENTIFIER
5061 * </pre>
5062 *
5063 * @param startToken the token at which parsing is to begin
5064 * @return the token following the simple identifier that was parsed
5065 */
5066 Token skipSimpleIdentifier(Token startToken) {
5067 if (matches4(startToken, TokenType.IDENTIFIER) || (matches4(startToken, Toke nType.KEYWORD) && ((startToken as KeywordToken)).keyword.isPseudoKeyword)) {
5068 return startToken.next;
5069 }
5070 return null;
5071 }
5072
5073 /**
5074 * Parse a string literal that contains interpolations, starting at the given token, without
5075 * actually creating a string literal or changing the current token. Return th e token following
5076 * the string literal that was parsed, or `null` if the given token is not the first token
5077 * in a valid string literal.
5078 *
5079 * This method must be kept in sync with [parseStringInterpolation].
5080 *
5081 * @param startToken the token at which parsing is to begin
5082 * @return the string literal that was parsed
5083 */
5084 Token skipStringInterpolation(Token startToken) {
5085 Token token = startToken;
5086 TokenType type = token.type;
5087 while (identical(type, TokenType.STRING_INTERPOLATION_EXPRESSION) || identic al(type, TokenType.STRING_INTERPOLATION_IDENTIFIER)) {
5088 if (identical(type, TokenType.STRING_INTERPOLATION_EXPRESSION)) {
5089 token = token.next;
5090 type = token.type;
5091 int bracketNestingLevel = 1;
5092 while (bracketNestingLevel > 0) {
5093 if (identical(type, TokenType.EOF)) {
5094 return null;
5095 } else if (identical(type, TokenType.OPEN_CURLY_BRACKET)) {
5096 bracketNestingLevel++;
5097 } else if (identical(type, TokenType.CLOSE_CURLY_BRACKET)) {
5098 bracketNestingLevel--;
5099 } else if (identical(type, TokenType.STRING)) {
5100 token = skipStringLiteral(token);
5101 if (token == null) {
5102 return null;
5103 }
5104 } else {
5105 token = token.next;
5106 }
5107 type = token.type;
5108 }
5109 token = token.next;
5110 type = token.type;
5111 } else {
5112 token = token.next;
5113 if (token.type != TokenType.IDENTIFIER) {
5114 return null;
5115 }
5116 token = token.next;
5117 }
5118 type = token.type;
5119 if (identical(type, TokenType.STRING)) {
5120 token = token.next;
5121 type = token.type;
5122 }
5123 }
5124 return token;
5125 }
5126
5127 /**
5128 * Parse a string literal, starting at the given token, without actually creat ing a string literal
5129 * or changing the current token. Return the token following the string litera l that was parsed,
5130 * or `null` if the given token is not the first token in a valid string liter al.
5131 *
5132 * This method must be kept in sync with [parseStringLiteral].
5133 *
5134 * <pre>
5135 * stringLiteral ::=
5136 * MULTI_LINE_STRING+
5137 * | SINGLE_LINE_STRING+
5138 * </pre>
5139 *
5140 * @param startToken the token at which parsing is to begin
5141 * @return the token following the string literal that was parsed
5142 */
5143 Token skipStringLiteral(Token startToken) {
5144 Token token = startToken;
5145 while (token != null && matches4(token, TokenType.STRING)) {
5146 token = token.next;
5147 TokenType type = token.type;
5148 if (identical(type, TokenType.STRING_INTERPOLATION_EXPRESSION) || identica l(type, TokenType.STRING_INTERPOLATION_IDENTIFIER)) {
5149 token = skipStringInterpolation(token);
5150 }
5151 }
5152 if (identical(token, startToken)) {
5153 return null;
5154 }
5155 return token;
5156 }
5157
5158 /**
5159 * Parse a list of type arguments, starting at the given token, without actual ly creating a type argument list
5160 * or changing the current token. Return the token following the type argument list that was parsed,
5161 * or `null` if the given token is not the first token in a valid type argumen t list.
5162 *
5163 * This method must be kept in sync with [parseTypeArgumentList].
5164 *
5165 * <pre>
5166 * typeArguments ::=
5167 * '<' typeList '>'
5168 *
5169 * typeList ::=
5170 * type (',' type)*
5171 * </pre>
5172 *
5173 * @param startToken the token at which parsing is to begin
5174 * @return the token following the type argument list that was parsed
5175 */
5176 Token skipTypeArgumentList(Token startToken) {
5177 Token token = startToken;
5178 if (!matches4(token, TokenType.LT)) {
5179 return null;
5180 }
5181 token = skipTypeName(token.next);
5182 if (token == null) {
5183 return null;
5184 }
5185 while (matches4(token, TokenType.COMMA)) {
5186 token = skipTypeName(token.next);
5187 if (token == null) {
5188 return null;
5189 }
5190 }
5191 if (identical(token.type, TokenType.GT)) {
5192 return token.next;
5193 } else if (identical(token.type, TokenType.GT_GT)) {
5194 Token second = new Token(TokenType.GT, token.offset + 1);
5195 second.setNextWithoutSettingPrevious(token.next);
5196 return second;
5197 }
5198 return null;
5199 }
5200
5201 /**
5202 * Parse a type name, starting at the given token, without actually creating a type name or
5203 * changing the current token. Return the token following the type name that w as parsed, or
5204 * `null` if the given token is not the first token in a valid type name.
5205 *
5206 * This method must be kept in sync with [parseTypeName].
5207 *
5208 * <pre>
5209 * type ::=
5210 * qualified typeArguments?
5211 * </pre>
5212 *
5213 * @param startToken the token at which parsing is to begin
5214 * @return the token following the type name that was parsed
5215 */
5216 Token skipTypeName(Token startToken) {
5217 Token token = skipPrefixedIdentifier(startToken);
5218 if (token == null) {
5219 return null;
5220 }
5221 if (matches4(token, TokenType.LT)) {
5222 token = skipTypeArgumentList(token);
5223 }
5224 return token;
5225 }
5226
5227 /**
5228 * Parse a list of type parameters, starting at the given token, without actua lly creating a type
5229 * parameter list or changing the current token. Return the token following th e type parameter
5230 * list that was parsed, or `null` if the given token is not the first token i n a valid type
5231 * parameter list.
5232 *
5233 * This method must be kept in sync with [parseTypeParameterList].
5234 *
5235 * <pre>
5236 * typeParameterList ::=
5237 * '<' typeParameter (',' typeParameter)* '>'
5238 * </pre>
5239 *
5240 * @param startToken the token at which parsing is to begin
5241 * @return the token following the type parameter list that was parsed
5242 */
5243 Token skipTypeParameterList(Token startToken) {
5244 if (!matches4(startToken, TokenType.LT)) {
5245 return null;
5246 }
5247 int depth = 1;
5248 Token next = startToken.next;
5249 while (depth > 0) {
5250 if (matches4(next, TokenType.EOF)) {
5251 return null;
5252 } else if (matches4(next, TokenType.LT)) {
5253 depth++;
5254 } else if (matches4(next, TokenType.GT)) {
5255 depth--;
5256 } else if (matches4(next, TokenType.GT_EQ)) {
5257 if (depth == 1) {
5258 Token fakeEquals = new Token(TokenType.EQ, next.offset + 2);
5259 fakeEquals.setNextWithoutSettingPrevious(next.next);
5260 return fakeEquals;
5261 }
5262 depth--;
5263 } else if (matches4(next, TokenType.GT_GT)) {
5264 depth -= 2;
5265 } else if (matches4(next, TokenType.GT_GT_EQ)) {
5266 if (depth < 2) {
5267 return null;
5268 } else if (depth == 2) {
5269 Token fakeEquals = new Token(TokenType.EQ, next.offset + 2);
5270 fakeEquals.setNextWithoutSettingPrevious(next.next);
5271 return fakeEquals;
5272 }
5273 depth -= 2;
5274 }
5275 next = next.next;
5276 }
5277 return next;
5278 }
5279
5280 /**
5281 * Translate the characters at the given index in the given string, appending the translated
5282 * character to the given builder. The index is assumed to be valid.
5283 *
5284 * @param builder the builder to which the translated character is to be appen ded
5285 * @param lexeme the string containing the character(s) to be translated
5286 * @param index the index of the character to be translated
5287 * @return the index of the next character to be translated
5288 */
5289 int translateCharacter(JavaStringBuilder builder, String lexeme, int index) {
5290 int currentChar = lexeme.codeUnitAt(index);
5291 if (currentChar != 0x5C) {
5292 builder.appendChar(currentChar);
5293 return index + 1;
5294 }
5295 int length = lexeme.length;
5296 int currentIndex = index + 1;
5297 if (currentIndex >= length) {
5298 return length;
5299 }
5300 currentChar = lexeme.codeUnitAt(currentIndex);
5301 if (currentChar == 0x6E) {
5302 builder.appendChar(0xA);
5303 } else if (currentChar == 0x72) {
5304 builder.appendChar(0xD);
5305 } else if (currentChar == 0x66) {
5306 builder.appendChar(0xC);
5307 } else if (currentChar == 0x62) {
5308 builder.appendChar(0x8);
5309 } else if (currentChar == 0x74) {
5310 builder.appendChar(0x9);
5311 } else if (currentChar == 0x76) {
5312 builder.appendChar(0xB);
5313 } else if (currentChar == 0x78) {
5314 if (currentIndex + 2 >= length) {
5315 reportError8(ParserErrorCode.INVALID_HEX_ESCAPE, []);
5316 return length;
5317 }
5318 int firstDigit = lexeme.codeUnitAt(currentIndex + 1);
5319 int secondDigit = lexeme.codeUnitAt(currentIndex + 2);
5320 if (!isHexDigit(firstDigit) || !isHexDigit(secondDigit)) {
5321 reportError8(ParserErrorCode.INVALID_HEX_ESCAPE, []);
5322 } else {
5323 builder.appendChar(((Character.digit(firstDigit, 16) << 4) + Character.d igit(secondDigit, 16)) as int);
5324 }
5325 return currentIndex + 3;
5326 } else if (currentChar == 0x75) {
5327 currentIndex++;
5328 if (currentIndex >= length) {
5329 reportError8(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
5330 return length;
5331 }
5332 currentChar = lexeme.codeUnitAt(currentIndex);
5333 if (currentChar == 0x7B) {
5334 currentIndex++;
5335 if (currentIndex >= length) {
5336 reportError8(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
5337 return length;
5338 }
5339 currentChar = lexeme.codeUnitAt(currentIndex);
5340 int digitCount = 0;
5341 int value = 0;
5342 while (currentChar != 0x7D) {
5343 if (!isHexDigit(currentChar)) {
5344 reportError8(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
5345 currentIndex++;
5346 while (currentIndex < length && lexeme.codeUnitAt(currentIndex) != 0 x7D) {
5347 currentIndex++;
5348 }
5349 return currentIndex + 1;
5350 }
5351 digitCount++;
5352 value = (value << 4) + Character.digit(currentChar, 16);
5353 currentIndex++;
5354 if (currentIndex >= length) {
5355 reportError8(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
5356 return length;
5357 }
5358 currentChar = lexeme.codeUnitAt(currentIndex);
5359 }
5360 if (digitCount < 1 || digitCount > 6) {
5361 reportError8(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
5362 }
5363 appendScalarValue(builder, lexeme.substring(index, currentIndex + 1), va lue, index, currentIndex);
5364 return currentIndex + 1;
5365 } else {
5366 if (currentIndex + 3 >= length) {
5367 reportError8(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
5368 return length;
5369 }
5370 int firstDigit = currentChar;
5371 int secondDigit = lexeme.codeUnitAt(currentIndex + 1);
5372 int thirdDigit = lexeme.codeUnitAt(currentIndex + 2);
5373 int fourthDigit = lexeme.codeUnitAt(currentIndex + 3);
5374 if (!isHexDigit(firstDigit) || !isHexDigit(secondDigit) || !isHexDigit(t hirdDigit) || !isHexDigit(fourthDigit)) {
5375 reportError8(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
5376 } else {
5377 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);
5378 }
5379 return currentIndex + 4;
5380 }
5381 } else {
5382 builder.appendChar(currentChar);
5383 }
5384 return currentIndex + 1;
5385 }
5386
5387 /**
5388 * Validate that the given parameter list does not contain any field initializ ers.
5389 *
5390 * @param parameterList the parameter list to be validated
5391 */
5392 void validateFormalParameterList(FormalParameterList parameterList) {
5393 for (FormalParameter parameter in parameterList.parameters) {
5394 if (parameter is FieldFormalParameter) {
5395 reportError(ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR, ((par ameter as FieldFormalParameter)).identifier, []);
5396 }
5397 }
5398 }
5399
5400 /**
5401 * Validate that the given set of modifiers is appropriate for a class and ret urn the 'abstract'
5402 * keyword if there is one.
5403 *
5404 * @param modifiers the modifiers being validated
5405 */
5406 Token validateModifiersForClass(Modifiers modifiers) {
5407 validateModifiersForTopLevelDeclaration(modifiers);
5408 if (modifiers.constKeyword != null) {
5409 reportError9(ParserErrorCode.CONST_CLASS, modifiers.constKeyword, []);
5410 }
5411 if (modifiers.externalKeyword != null) {
5412 reportError9(ParserErrorCode.EXTERNAL_CLASS, modifiers.externalKeyword, [] );
5413 }
5414 if (modifiers.finalKeyword != null) {
5415 reportError9(ParserErrorCode.FINAL_CLASS, modifiers.finalKeyword, []);
5416 }
5417 if (modifiers.varKeyword != null) {
5418 reportError9(ParserErrorCode.VAR_CLASS, modifiers.varKeyword, []);
5419 }
5420 return modifiers.abstractKeyword;
5421 }
5422
5423 /**
5424 * Validate that the given set of modifiers is appropriate for a constructor a nd return the
5425 * 'const' keyword if there is one.
5426 *
5427 * @param modifiers the modifiers being validated
5428 * @return the 'const' or 'final' keyword associated with the constructor
5429 */
5430 Token validateModifiersForConstructor(Modifiers modifiers) {
5431 if (modifiers.abstractKeyword != null) {
5432 reportError8(ParserErrorCode.ABSTRACT_CLASS_MEMBER, []);
5433 }
5434 if (modifiers.finalKeyword != null) {
5435 reportError9(ParserErrorCode.FINAL_CONSTRUCTOR, modifiers.finalKeyword, [] );
5436 }
5437 if (modifiers.staticKeyword != null) {
5438 reportError9(ParserErrorCode.STATIC_CONSTRUCTOR, modifiers.staticKeyword, []);
5439 }
5440 if (modifiers.varKeyword != null) {
5441 reportError9(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, modifiers.varKe yword, []);
5442 }
5443 Token externalKeyword = modifiers.externalKeyword;
5444 Token constKeyword = modifiers.constKeyword;
5445 Token factoryKeyword = modifiers.factoryKeyword;
5446 if (externalKeyword != null && constKeyword != null && constKeyword.offset < externalKeyword.offset) {
5447 reportError9(ParserErrorCode.EXTERNAL_AFTER_CONST, externalKeyword, []);
5448 }
5449 if (externalKeyword != null && factoryKeyword != null && factoryKeyword.offs et < externalKeyword.offset) {
5450 reportError9(ParserErrorCode.EXTERNAL_AFTER_FACTORY, externalKeyword, []);
5451 }
5452 return constKeyword;
5453 }
5454
5455 /**
5456 * Validate that the given set of modifiers is appropriate for a field and ret urn the 'final',
5457 * 'const' or 'var' keyword if there is one.
5458 *
5459 * @param modifiers the modifiers being validated
5460 * @return the 'final', 'const' or 'var' keyword associated with the field
5461 */
5462 Token validateModifiersForField(Modifiers modifiers) {
5463 if (modifiers.abstractKeyword != null) {
5464 reportError8(ParserErrorCode.ABSTRACT_CLASS_MEMBER, []);
5465 }
5466 if (modifiers.externalKeyword != null) {
5467 reportError9(ParserErrorCode.EXTERNAL_FIELD, modifiers.externalKeyword, [] );
5468 }
5469 if (modifiers.factoryKeyword != null) {
5470 reportError9(ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.factoryKey word, []);
5471 }
5472 Token staticKeyword = modifiers.staticKeyword;
5473 Token constKeyword = modifiers.constKeyword;
5474 Token finalKeyword = modifiers.finalKeyword;
5475 Token varKeyword = modifiers.varKeyword;
5476 if (constKeyword != null) {
5477 if (finalKeyword != null) {
5478 reportError9(ParserErrorCode.CONST_AND_FINAL, finalKeyword, []);
5479 }
5480 if (varKeyword != null) {
5481 reportError9(ParserErrorCode.CONST_AND_VAR, varKeyword, []);
5482 }
5483 if (staticKeyword != null && constKeyword.offset < staticKeyword.offset) {
5484 reportError9(ParserErrorCode.STATIC_AFTER_CONST, staticKeyword, []);
5485 }
5486 } else if (finalKeyword != null) {
5487 if (varKeyword != null) {
5488 reportError9(ParserErrorCode.FINAL_AND_VAR, varKeyword, []);
5489 }
5490 if (staticKeyword != null && finalKeyword.offset < staticKeyword.offset) {
5491 reportError9(ParserErrorCode.STATIC_AFTER_FINAL, staticKeyword, []);
5492 }
5493 } else if (varKeyword != null && staticKeyword != null && varKeyword.offset < staticKeyword.offset) {
5494 reportError9(ParserErrorCode.STATIC_AFTER_VAR, staticKeyword, []);
5495 }
5496 return lexicallyFirst([constKeyword, finalKeyword, varKeyword]);
5497 }
5498
5499 /**
5500 * Validate that the given set of modifiers is appropriate for a local functio n.
5501 *
5502 * @param modifiers the modifiers being validated
5503 */
5504 void validateModifiersForFunctionDeclarationStatement(Modifiers modifiers) {
5505 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) {
5506 reportError8(ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER, []);
5507 }
5508 }
5509
5510 /**
5511 * Validate that the given set of modifiers is appropriate for a getter, sette r, or method.
5512 *
5513 * @param modifiers the modifiers being validated
5514 */
5515 void validateModifiersForGetterOrSetterOrMethod(Modifiers modifiers) {
5516 if (modifiers.abstractKeyword != null) {
5517 reportError8(ParserErrorCode.ABSTRACT_CLASS_MEMBER, []);
5518 }
5519 if (modifiers.constKeyword != null) {
5520 reportError9(ParserErrorCode.CONST_METHOD, modifiers.constKeyword, []);
5521 }
5522 if (modifiers.factoryKeyword != null) {
5523 reportError9(ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.factoryKey word, []);
5524 }
5525 if (modifiers.finalKeyword != null) {
5526 reportError9(ParserErrorCode.FINAL_METHOD, modifiers.finalKeyword, []);
5527 }
5528 if (modifiers.varKeyword != null) {
5529 reportError9(ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword, []);
5530 }
5531 Token externalKeyword = modifiers.externalKeyword;
5532 Token staticKeyword = modifiers.staticKeyword;
5533 if (externalKeyword != null && staticKeyword != null && staticKeyword.offset < externalKeyword.offset) {
5534 reportError9(ParserErrorCode.EXTERNAL_AFTER_STATIC, externalKeyword, []);
5535 }
5536 }
5537
5538 /**
5539 * Validate that the given set of modifiers is appropriate for a getter, sette r, or method.
5540 *
5541 * @param modifiers the modifiers being validated
5542 */
5543 void validateModifiersForOperator(Modifiers modifiers) {
5544 if (modifiers.abstractKeyword != null) {
5545 reportError8(ParserErrorCode.ABSTRACT_CLASS_MEMBER, []);
5546 }
5547 if (modifiers.constKeyword != null) {
5548 reportError9(ParserErrorCode.CONST_METHOD, modifiers.constKeyword, []);
5549 }
5550 if (modifiers.factoryKeyword != null) {
5551 reportError9(ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.factoryKey word, []);
5552 }
5553 if (modifiers.finalKeyword != null) {
5554 reportError9(ParserErrorCode.FINAL_METHOD, modifiers.finalKeyword, []);
5555 }
5556 if (modifiers.staticKeyword != null) {
5557 reportError9(ParserErrorCode.STATIC_OPERATOR, modifiers.staticKeyword, []) ;
5558 }
5559 if (modifiers.varKeyword != null) {
5560 reportError9(ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword, []);
5561 }
5562 }
5563
5564 /**
5565 * Validate that the given set of modifiers is appropriate for a top-level dec laration.
5566 *
5567 * @param modifiers the modifiers being validated
5568 */
5569 void validateModifiersForTopLevelDeclaration(Modifiers modifiers) {
5570 if (modifiers.factoryKeyword != null) {
5571 reportError9(ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION, modifiers.fact oryKeyword, []);
5572 }
5573 if (modifiers.staticKeyword != null) {
5574 reportError9(ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION, modifiers.stati cKeyword, []);
5575 }
5576 }
5577
5578 /**
5579 * Validate that the given set of modifiers is appropriate for a top-level fun ction.
5580 *
5581 * @param modifiers the modifiers being validated
5582 */
5583 void validateModifiersForTopLevelFunction(Modifiers modifiers) {
5584 validateModifiersForTopLevelDeclaration(modifiers);
5585 if (modifiers.abstractKeyword != null) {
5586 reportError8(ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION, []);
5587 }
5588 if (modifiers.constKeyword != null) {
5589 reportError9(ParserErrorCode.CONST_CLASS, modifiers.constKeyword, []);
5590 }
5591 if (modifiers.finalKeyword != null) {
5592 reportError9(ParserErrorCode.FINAL_CLASS, modifiers.finalKeyword, []);
5593 }
5594 if (modifiers.varKeyword != null) {
5595 reportError9(ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword, []);
5596 }
5597 }
5598
5599 /**
5600 * Validate that the given set of modifiers is appropriate for a field and ret urn the 'final',
5601 * 'const' or 'var' keyword if there is one.
5602 *
5603 * @param modifiers the modifiers being validated
5604 * @return the 'final', 'const' or 'var' keyword associated with the field
5605 */
5606 Token validateModifiersForTopLevelVariable(Modifiers modifiers) {
5607 validateModifiersForTopLevelDeclaration(modifiers);
5608 if (modifiers.abstractKeyword != null) {
5609 reportError8(ParserErrorCode.ABSTRACT_TOP_LEVEL_VARIABLE, []);
5610 }
5611 if (modifiers.externalKeyword != null) {
5612 reportError9(ParserErrorCode.EXTERNAL_FIELD, modifiers.externalKeyword, [] );
5613 }
5614 Token constKeyword = modifiers.constKeyword;
5615 Token finalKeyword = modifiers.finalKeyword;
5616 Token varKeyword = modifiers.varKeyword;
5617 if (constKeyword != null) {
5618 if (finalKeyword != null) {
5619 reportError9(ParserErrorCode.CONST_AND_FINAL, finalKeyword, []);
5620 }
5621 if (varKeyword != null) {
5622 reportError9(ParserErrorCode.CONST_AND_VAR, varKeyword, []);
5623 }
5624 } else if (finalKeyword != null) {
5625 if (varKeyword != null) {
5626 reportError9(ParserErrorCode.FINAL_AND_VAR, varKeyword, []);
5627 }
5628 }
5629 return lexicallyFirst([constKeyword, finalKeyword, varKeyword]);
5630 }
5631
5632 /**
5633 * Validate that the given set of modifiers is appropriate for a class and ret urn the 'abstract'
5634 * keyword if there is one.
5635 *
5636 * @param modifiers the modifiers being validated
5637 */
5638 void validateModifiersForTypedef(Modifiers modifiers) {
5639 validateModifiersForTopLevelDeclaration(modifiers);
5640 if (modifiers.abstractKeyword != null) {
5641 reportError9(ParserErrorCode.ABSTRACT_TYPEDEF, modifiers.abstractKeyword, []);
5642 }
5643 if (modifiers.constKeyword != null) {
5644 reportError9(ParserErrorCode.CONST_TYPEDEF, modifiers.constKeyword, []);
5645 }
5646 if (modifiers.externalKeyword != null) {
5647 reportError9(ParserErrorCode.EXTERNAL_TYPEDEF, modifiers.externalKeyword, []);
5648 }
5649 if (modifiers.finalKeyword != null) {
5650 reportError9(ParserErrorCode.FINAL_TYPEDEF, modifiers.finalKeyword, []);
5651 }
5652 if (modifiers.varKeyword != null) {
5653 reportError9(ParserErrorCode.VAR_TYPEDEF, modifiers.varKeyword, []);
5654 }
5655 }
5656 }
5657 /**
5658 * Instances of the class `SyntheticKeywordToken` implement a synthetic keyword token.
5659 */
5660 class Parser_SyntheticKeywordToken extends KeywordToken {
5661
5662 /**
5663 * Initialize a newly created token to represent the given keyword.
5664 *
5665 * @param keyword the keyword being represented by this token
5666 * @param offset the offset from the beginning of the file to the first charac ter in the token
5667 */
5668 Parser_SyntheticKeywordToken(Keyword keyword, int offset) : super(keyword, off set);
5669 Token copy() => new Parser_SyntheticKeywordToken(keyword, offset);
5670 int get length => 0;
5671 }
5672 class AnalysisErrorListener_15 implements AnalysisErrorListener {
5673 List<bool> errorFound;
5674 AnalysisErrorListener_15(this.errorFound);
5675 void onError(AnalysisError error) {
5676 errorFound[0] = true;
5677 }
5678 }
5679 /**
5680 * The enumeration `ParserErrorCode` defines the error codes used for errors det ected by the
5681 * parser. The convention for this class is for the name of the error code to in dicate the problem
5682 * that caused the error to be generated and for the error message to explain wh at is wrong and,
5683 * when appropriate, how the problem can be corrected.
5684 *
5685 * @coverage dart.engine.parser
5686 */
5687 class ParserErrorCode extends Enum<ParserErrorCode> implements ErrorCode {
5688 static final ParserErrorCode ABSTRACT_CLASS_MEMBER = new ParserErrorCode.con3( 'ABSTRACT_CLASS_MEMBER', 0, "Members of classes cannot be declared to be 'abstra ct'");
5689 static final ParserErrorCode ABSTRACT_STATIC_METHOD = new ParserErrorCode.con3 ('ABSTRACT_STATIC_METHOD', 1, "Static methods cannot be declared to be 'abstract '");
5690 static final ParserErrorCode ABSTRACT_TOP_LEVEL_FUNCTION = new ParserErrorCode .con3('ABSTRACT_TOP_LEVEL_FUNCTION', 2, "Top-level functions cannot be declared to be 'abstract'");
5691 static final ParserErrorCode ABSTRACT_TOP_LEVEL_VARIABLE = new ParserErrorCode .con3('ABSTRACT_TOP_LEVEL_VARIABLE', 3, "Top-level variables cannot be declared to be 'abstract'");
5692 static final ParserErrorCode ABSTRACT_TYPEDEF = new ParserErrorCode.con3('ABST RACT_TYPEDEF', 4, "Type aliases cannot be declared to be 'abstract'");
5693 static final ParserErrorCode ASSERT_DOES_NOT_TAKE_ASSIGNMENT = new ParserError Code.con3('ASSERT_DOES_NOT_TAKE_ASSIGNMENT', 5, "Assert cannot be called on an a ssignment");
5694 static final ParserErrorCode ASSERT_DOES_NOT_TAKE_CASCADE = new ParserErrorCod e.con3('ASSERT_DOES_NOT_TAKE_CASCADE', 6, "Assert cannot be called on cascade");
5695 static final ParserErrorCode ASSERT_DOES_NOT_TAKE_THROW = new ParserErrorCode. con3('ASSERT_DOES_NOT_TAKE_THROW', 7, "Assert cannot be called on throws");
5696 static final ParserErrorCode ASSERT_DOES_NOT_TAKE_RETHROW = new ParserErrorCod e.con3('ASSERT_DOES_NOT_TAKE_RETHROW', 8, "Assert cannot be called on rethrows") ;
5697 static final ParserErrorCode BREAK_OUTSIDE_OF_LOOP = new ParserErrorCode.con3( 'BREAK_OUTSIDE_OF_LOOP', 9, "A break statement cannot be used outside of a loop or switch statement");
5698 static final ParserErrorCode CONST_AND_FINAL = new ParserErrorCode.con3('CONST _AND_FINAL', 10, "Members cannot be declared to be both 'const' and 'final'");
5699 static final ParserErrorCode CONST_AND_VAR = new ParserErrorCode.con3('CONST_A ND_VAR', 11, "Members cannot be declared to be both 'const' and 'var'");
5700 static final ParserErrorCode CONST_CLASS = new ParserErrorCode.con3('CONST_CLA SS', 12, "Classes cannot be declared to be 'const'");
5701 static final ParserErrorCode CONST_CONSTRUCTOR_WITH_BODY = new ParserErrorCode .con3('CONST_CONSTRUCTOR_WITH_BODY', 13, "'const' constructors cannot have a bod y");
5702 static final ParserErrorCode CONST_FACTORY = new ParserErrorCode.con3('CONST_F ACTORY', 14, "Only redirecting factory constructors can be declared to be 'const '");
5703 static final ParserErrorCode CONST_METHOD = new ParserErrorCode.con3('CONST_ME THOD', 15, "Getters, setters and methods cannot be declared to be 'const'");
5704 static final ParserErrorCode CONST_TYPEDEF = new ParserErrorCode.con3('CONST_T YPEDEF', 16, "Type aliases cannot be declared to be 'const'");
5705 static final ParserErrorCode CONSTRUCTOR_WITH_RETURN_TYPE = new ParserErrorCod e.con3('CONSTRUCTOR_WITH_RETURN_TYPE', 17, "Constructors cannot have a return ty pe");
5706 static final ParserErrorCode CONTINUE_OUTSIDE_OF_LOOP = new ParserErrorCode.co n3('CONTINUE_OUTSIDE_OF_LOOP', 18, "A continue statement cannot be used outside of a loop or switch statement");
5707 static final ParserErrorCode CONTINUE_WITHOUT_LABEL_IN_CASE = new ParserErrorC ode.con3('CONTINUE_WITHOUT_LABEL_IN_CASE', 19, "A continue statement in a switch statement must have a label as a target");
5708 static final ParserErrorCode DEPRECATED_ARGUMENT_DEFINITION_TEST = new ParserE rrorCode.con3('DEPRECATED_ARGUMENT_DEFINITION_TEST', 20, "The argument definitio n test ('?' operator) has been deprecated");
5709 static final ParserErrorCode DEPRECATED_CLASS_TYPE_ALIAS = new ParserErrorCode .con3('DEPRECATED_CLASS_TYPE_ALIAS', 21, "The 'typedef' mixin application was re placed with 'class'");
5710 static final ParserErrorCode DIRECTIVE_AFTER_DECLARATION = new ParserErrorCode .con3('DIRECTIVE_AFTER_DECLARATION', 22, "Directives must appear before any decl arations");
5711 static final ParserErrorCode DUPLICATE_LABEL_IN_SWITCH_STATEMENT = new ParserE rrorCode.con3('DUPLICATE_LABEL_IN_SWITCH_STATEMENT', 23, "The label %s was alrea dy used in this switch statement");
5712 static final ParserErrorCode DUPLICATED_MODIFIER = new ParserErrorCode.con3('D UPLICATED_MODIFIER', 24, "The modifier '%s' was already specified.");
5713 static final ParserErrorCode EQUALITY_CANNOT_BE_EQUALITY_OPERAND = new ParserE rrorCode.con3('EQUALITY_CANNOT_BE_EQUALITY_OPERAND', 25, "Equality expression ca nnot be operand of another equality expression.");
5714 static final ParserErrorCode EXPECTED_CASE_OR_DEFAULT = new ParserErrorCode.co n3('EXPECTED_CASE_OR_DEFAULT', 26, "Expected 'case' or 'default'");
5715 static final ParserErrorCode EXPECTED_CLASS_MEMBER = new ParserErrorCode.con3( 'EXPECTED_CLASS_MEMBER', 27, "Expected a class member");
5716 static final ParserErrorCode EXPECTED_EXECUTABLE = new ParserErrorCode.con3('E XPECTED_EXECUTABLE', 28, "Expected a method, getter, setter or operator declarat ion");
5717 static final ParserErrorCode EXPECTED_LIST_OR_MAP_LITERAL = new ParserErrorCod e.con3('EXPECTED_LIST_OR_MAP_LITERAL', 29, "Expected a list or map literal");
5718 static final ParserErrorCode EXPECTED_STRING_LITERAL = new ParserErrorCode.con 3('EXPECTED_STRING_LITERAL', 30, "Expected a string literal");
5719 static final ParserErrorCode EXPECTED_TOKEN = new ParserErrorCode.con3('EXPECT ED_TOKEN', 31, "Expected to find '%s'");
5720 static final ParserErrorCode EXPECTED_TYPE_NAME = new ParserErrorCode.con3('EX PECTED_TYPE_NAME', 32, "Expected a type name");
5721 static final ParserErrorCode EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE = new Parse rErrorCode.con3('EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE', 33, "Export directives must preceed part directives");
5722 static final ParserErrorCode EXTERNAL_AFTER_CONST = new ParserErrorCode.con3(' EXTERNAL_AFTER_CONST', 34, "The modifier 'external' should be before the modifie r 'const'");
5723 static final ParserErrorCode EXTERNAL_AFTER_FACTORY = new ParserErrorCode.con3 ('EXTERNAL_AFTER_FACTORY', 35, "The modifier 'external' should be before the mod ifier 'factory'");
5724 static final ParserErrorCode EXTERNAL_AFTER_STATIC = new ParserErrorCode.con3( 'EXTERNAL_AFTER_STATIC', 36, "The modifier 'external' should be before the modif ier 'static'");
5725 static final ParserErrorCode EXTERNAL_CLASS = new ParserErrorCode.con3('EXTERN AL_CLASS', 37, "Classes cannot be declared to be 'external'");
5726 static final ParserErrorCode EXTERNAL_CONSTRUCTOR_WITH_BODY = new ParserErrorC ode.con3('EXTERNAL_CONSTRUCTOR_WITH_BODY', 38, "External constructors cannot hav e a body");
5727 static final ParserErrorCode EXTERNAL_FIELD = new ParserErrorCode.con3('EXTERN AL_FIELD', 39, "Fields cannot be declared to be 'external'");
5728 static final ParserErrorCode EXTERNAL_GETTER_WITH_BODY = new ParserErrorCode.c on3('EXTERNAL_GETTER_WITH_BODY', 40, "External getters cannot have a body");
5729 static final ParserErrorCode EXTERNAL_METHOD_WITH_BODY = new ParserErrorCode.c on3('EXTERNAL_METHOD_WITH_BODY', 41, "External methods cannot have a body");
5730 static final ParserErrorCode EXTERNAL_OPERATOR_WITH_BODY = new ParserErrorCode .con3('EXTERNAL_OPERATOR_WITH_BODY', 42, "External operators cannot have a body" );
5731 static final ParserErrorCode EXTERNAL_SETTER_WITH_BODY = new ParserErrorCode.c on3('EXTERNAL_SETTER_WITH_BODY', 43, "External setters cannot have a body");
5732 static final ParserErrorCode EXTERNAL_TYPEDEF = new ParserErrorCode.con3('EXTE RNAL_TYPEDEF', 44, "Type aliases cannot be declared to be 'external'");
5733 static final ParserErrorCode FACTORY_TOP_LEVEL_DECLARATION = new ParserErrorCo de.con3('FACTORY_TOP_LEVEL_DECLARATION', 45, "Top-level declarations cannot be d eclared to be 'factory'");
5734 static final ParserErrorCode FACTORY_WITHOUT_BODY = new ParserErrorCode.con3(' FACTORY_WITHOUT_BODY', 46, "A non-redirecting 'factory' constructor must have a body");
5735 static final ParserErrorCode FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR = new Parse rErrorCode.con3('FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR', 47, "Field initializers can only be used in a constructor");
5736 static final ParserErrorCode FINAL_AND_VAR = new ParserErrorCode.con3('FINAL_A ND_VAR', 48, "Members cannot be declared to be both 'final' and 'var'");
5737 static final ParserErrorCode FINAL_CLASS = new ParserErrorCode.con3('FINAL_CLA SS', 49, "Classes cannot be declared to be 'final'");
5738 static final ParserErrorCode FINAL_CONSTRUCTOR = new ParserErrorCode.con3('FIN AL_CONSTRUCTOR', 50, "A constructor cannot be declared to be 'final'");
5739 static final ParserErrorCode FINAL_METHOD = new ParserErrorCode.con3('FINAL_ME THOD', 51, "Getters, setters and methods cannot be declared to be 'final'");
5740 static final ParserErrorCode FINAL_TYPEDEF = new ParserErrorCode.con3('FINAL_T YPEDEF', 52, "Type aliases cannot be declared to be 'final'");
5741 static final ParserErrorCode FUNCTION_TYPED_PARAMETER_VAR = new ParserErrorCod e.con3('FUNCTION_TYPED_PARAMETER_VAR', 53, "Function typed parameters cannot spe cify 'const', 'final' or 'var' instead of return type");
5742 static final ParserErrorCode GETTER_IN_FUNCTION = new ParserErrorCode.con3('GE TTER_IN_FUNCTION', 54, "Getters cannot be defined within methods or functions");
5743 static final ParserErrorCode GETTER_WITH_PARAMETERS = new ParserErrorCode.con3 ('GETTER_WITH_PARAMETERS', 55, "Getter should be declared without a parameter li st");
5744 static final ParserErrorCode ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE = new Parser ErrorCode.con3('ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE', 56, "Illegal assignment t o non-assignable expression");
5745 static final ParserErrorCode IMPLEMENTS_BEFORE_EXTENDS = new ParserErrorCode.c on3('IMPLEMENTS_BEFORE_EXTENDS', 57, "The extends clause must be before the impl ements clause");
5746 static final ParserErrorCode IMPLEMENTS_BEFORE_WITH = new ParserErrorCode.con3 ('IMPLEMENTS_BEFORE_WITH', 58, "The with clause must be before the implements cl ause");
5747 static final ParserErrorCode IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE = new Parse rErrorCode.con3('IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE', 59, "Import directives must preceed part directives");
5748 static final ParserErrorCode INITIALIZED_VARIABLE_IN_FOR_EACH = new ParserErro rCode.con3('INITIALIZED_VARIABLE_IN_FOR_EACH', 60, "The loop variable in a for-e ach loop cannot be initialized");
5749 static final ParserErrorCode INVALID_CODE_POINT = new ParserErrorCode.con3('IN VALID_CODE_POINT', 61, "The escape sequence '%s' is not a valid code point");
5750 static final ParserErrorCode INVALID_COMMENT_REFERENCE = new ParserErrorCode.c on3('INVALID_COMMENT_REFERENCE', 62, "Comment references should contain a possib ly prefixed identifier and can start with 'new', but should not contain anything else");
5751 static final ParserErrorCode INVALID_HEX_ESCAPE = new ParserErrorCode.con3('IN VALID_HEX_ESCAPE', 63, "An escape sequence starting with '\\x' must be followed by 2 hexidecimal digits");
5752 static final ParserErrorCode INVALID_OPERATOR = new ParserErrorCode.con3('INVA LID_OPERATOR', 64, "The string '%s' is not a valid operator");
5753 static final ParserErrorCode INVALID_OPERATOR_FOR_SUPER = new ParserErrorCode. con3('INVALID_OPERATOR_FOR_SUPER', 65, "The operator '%s' cannot be used with 's uper'");
5754 static final ParserErrorCode INVALID_UNICODE_ESCAPE = new ParserErrorCode.con3 ('INVALID_UNICODE_ESCAPE', 66, "An escape sequence starting with '\\u' must be f ollowed by 4 hexidecimal digits or from 1 to 6 digits between '{' and '}'");
5755 static final ParserErrorCode LIBRARY_DIRECTIVE_NOT_FIRST = new ParserErrorCode .con3('LIBRARY_DIRECTIVE_NOT_FIRST', 67, "The library directive must appear befo re all other directives");
5756 static final ParserErrorCode LOCAL_FUNCTION_DECLARATION_MODIFIER = new ParserE rrorCode.con3('LOCAL_FUNCTION_DECLARATION_MODIFIER', 68, "Local function declara tions cannot specify any modifier");
5757 static final ParserErrorCode MISSING_ASSIGNABLE_SELECTOR = new ParserErrorCode .con3('MISSING_ASSIGNABLE_SELECTOR', 69, "Missing selector such as \".<identifie r>\" or \"[0]\"");
5758 static final ParserErrorCode MISSING_CATCH_OR_FINALLY = new ParserErrorCode.co n3('MISSING_CATCH_OR_FINALLY', 70, "A try statement must have either a catch or finally clause");
5759 static final ParserErrorCode MISSING_CLASS_BODY = new ParserErrorCode.con3('MI SSING_CLASS_BODY', 71, "A class definition must have a body, even if it is empty ");
5760 static final ParserErrorCode MISSING_CLOSING_PARENTHESIS = new ParserErrorCode .con3('MISSING_CLOSING_PARENTHESIS', 72, "The closing parenthesis is missing");
5761 static final ParserErrorCode MISSING_CONST_FINAL_VAR_OR_TYPE = new ParserError Code.con3('MISSING_CONST_FINAL_VAR_OR_TYPE', 73, "Variables must be declared usi ng the keywords 'const', 'final', 'var' or a type name");
5762 static final ParserErrorCode MISSING_EXPRESSION_IN_THROW = new ParserErrorCode .con3('MISSING_EXPRESSION_IN_THROW', 74, "Throw expressions must compute the obj ect to be thrown");
5763 static final ParserErrorCode MISSING_FUNCTION_BODY = new ParserErrorCode.con3( 'MISSING_FUNCTION_BODY', 75, "A function body must be provided");
5764 static final ParserErrorCode MISSING_FUNCTION_PARAMETERS = new ParserErrorCode .con3('MISSING_FUNCTION_PARAMETERS', 76, "Functions must have an explicit list o f parameters");
5765 static final ParserErrorCode MISSING_IDENTIFIER = new ParserErrorCode.con3('MI SSING_IDENTIFIER', 77, "Expected an identifier");
5766 static final ParserErrorCode MISSING_KEYWORD_OPERATOR = new ParserErrorCode.co n3('MISSING_KEYWORD_OPERATOR', 78, "Operator declarations must be preceeded by t he keyword 'operator'");
5767 static final ParserErrorCode MISSING_NAME_IN_LIBRARY_DIRECTIVE = new ParserErr orCode.con3('MISSING_NAME_IN_LIBRARY_DIRECTIVE', 79, "Library directives must in clude a library name");
5768 static final ParserErrorCode MISSING_NAME_IN_PART_OF_DIRECTIVE = new ParserErr orCode.con3('MISSING_NAME_IN_PART_OF_DIRECTIVE', 80, "Library directives must in clude a library name");
5769 static final ParserErrorCode MISSING_STATEMENT = new ParserErrorCode.con3('MIS SING_STATEMENT', 81, "Expected a statement");
5770 static final ParserErrorCode MISSING_TERMINATOR_FOR_PARAMETER_GROUP = new Pars erErrorCode.con3('MISSING_TERMINATOR_FOR_PARAMETER_GROUP', 82, "There is no '%s' to close the parameter group");
5771 static final ParserErrorCode MISSING_TYPEDEF_PARAMETERS = new ParserErrorCode. con3('MISSING_TYPEDEF_PARAMETERS', 83, "Type aliases for functions must have an explicit list of parameters");
5772 static final ParserErrorCode MISSING_VARIABLE_IN_FOR_EACH = new ParserErrorCod e.con3('MISSING_VARIABLE_IN_FOR_EACH', 84, "A loop variable must be declared in a for-each loop before the 'in', but none were found");
5773 static final ParserErrorCode MIXED_PARAMETER_GROUPS = new ParserErrorCode.con3 ('MIXED_PARAMETER_GROUPS', 85, "Cannot have both positional and named parameters in a single parameter list");
5774 static final ParserErrorCode MULTIPLE_EXTENDS_CLAUSES = new ParserErrorCode.co n3('MULTIPLE_EXTENDS_CLAUSES', 86, "Each class definition can have at most one e xtends clause");
5775 static final ParserErrorCode MULTIPLE_IMPLEMENTS_CLAUSES = new ParserErrorCode .con3('MULTIPLE_IMPLEMENTS_CLAUSES', 87, "Each class definition can have at most one implements clause");
5776 static final ParserErrorCode MULTIPLE_LIBRARY_DIRECTIVES = new ParserErrorCode .con3('MULTIPLE_LIBRARY_DIRECTIVES', 88, "Only one library directive may be decl ared in a file");
5777 static final ParserErrorCode MULTIPLE_NAMED_PARAMETER_GROUPS = new ParserError Code.con3('MULTIPLE_NAMED_PARAMETER_GROUPS', 89, "Cannot have multiple groups of named parameters in a single parameter list");
5778 static final ParserErrorCode MULTIPLE_PART_OF_DIRECTIVES = new ParserErrorCode .con3('MULTIPLE_PART_OF_DIRECTIVES', 90, "Only one part-of directive may be decl ared in a file");
5779 static final ParserErrorCode MULTIPLE_POSITIONAL_PARAMETER_GROUPS = new Parser ErrorCode.con3('MULTIPLE_POSITIONAL_PARAMETER_GROUPS', 91, "Cannot have multiple groups of positional parameters in a single parameter list");
5780 static final ParserErrorCode MULTIPLE_VARIABLES_IN_FOR_EACH = new ParserErrorC ode.con3('MULTIPLE_VARIABLES_IN_FOR_EACH', 92, "A single loop variable must be d eclared in a for-each loop before the 'in', but %s were found");
5781 static final ParserErrorCode MULTIPLE_WITH_CLAUSES = new ParserErrorCode.con3( 'MULTIPLE_WITH_CLAUSES', 93, "Each class definition can have at most one with cl ause");
5782 static final ParserErrorCode NAMED_FUNCTION_EXPRESSION = new ParserErrorCode.c on3('NAMED_FUNCTION_EXPRESSION', 94, "Function expressions cannot be named");
5783 static final ParserErrorCode NAMED_PARAMETER_OUTSIDE_GROUP = new ParserErrorCo de.con3('NAMED_PARAMETER_OUTSIDE_GROUP', 95, "Named parameters must be enclosed in curly braces ('{' and '}')");
5784 static final ParserErrorCode NATIVE_CLAUSE_IN_NON_SDK_CODE = new ParserErrorCo de.con3('NATIVE_CLAUSE_IN_NON_SDK_CODE', 96, "Native clause can only be used in the SDK and code that is loaded through native extensions");
5785 static final ParserErrorCode NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE = new Parser ErrorCode.con3('NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE', 97, "Native functions can only be declared in the SDK and code that is loaded through native extensions") ;
5786 static final ParserErrorCode NON_CONSTRUCTOR_FACTORY = new ParserErrorCode.con 3('NON_CONSTRUCTOR_FACTORY', 98, "Only constructors can be declared to be a 'fac tory'");
5787 static final ParserErrorCode NON_IDENTIFIER_LIBRARY_NAME = new ParserErrorCode .con3('NON_IDENTIFIER_LIBRARY_NAME', 99, "The name of a library must be an ident ifier");
5788 static final ParserErrorCode NON_PART_OF_DIRECTIVE_IN_PART = new ParserErrorCo de.con3('NON_PART_OF_DIRECTIVE_IN_PART', 100, "The part-of directive must be the only directive in a part");
5789 static final ParserErrorCode NON_USER_DEFINABLE_OPERATOR = new ParserErrorCode .con3('NON_USER_DEFINABLE_OPERATOR', 101, "The operator '%s' is not user definab le");
5790 static final ParserErrorCode NORMAL_BEFORE_OPTIONAL_PARAMETERS = new ParserErr orCode.con3('NORMAL_BEFORE_OPTIONAL_PARAMETERS', 102, "Normal parameters must oc cur before optional parameters");
5791 static final ParserErrorCode POSITIONAL_AFTER_NAMED_ARGUMENT = new ParserError Code.con3('POSITIONAL_AFTER_NAMED_ARGUMENT', 103, "Positional arguments must occ ur before named arguments");
5792 static final ParserErrorCode POSITIONAL_PARAMETER_OUTSIDE_GROUP = new ParserEr rorCode.con3('POSITIONAL_PARAMETER_OUTSIDE_GROUP', 104, "Positional parameters m ust be enclosed in square brackets ('[' and ']')");
5793 static final ParserErrorCode REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR = new Pars erErrorCode.con3('REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR', 105, "Only factory co nstructor can specify '=' redirection.");
5794 static final ParserErrorCode SETTER_IN_FUNCTION = new ParserErrorCode.con3('SE TTER_IN_FUNCTION', 106, "Setters cannot be defined within methods or functions") ;
5795 static final ParserErrorCode STATIC_AFTER_CONST = new ParserErrorCode.con3('ST ATIC_AFTER_CONST', 107, "The modifier 'static' should be before the modifier 'co nst'");
5796 static final ParserErrorCode STATIC_AFTER_FINAL = new ParserErrorCode.con3('ST ATIC_AFTER_FINAL', 108, "The modifier 'static' should be before the modifier 'fi nal'");
5797 static final ParserErrorCode STATIC_AFTER_VAR = new ParserErrorCode.con3('STAT IC_AFTER_VAR', 109, "The modifier 'static' should be before the modifier 'var'") ;
5798 static final ParserErrorCode STATIC_CONSTRUCTOR = new ParserErrorCode.con3('ST ATIC_CONSTRUCTOR', 110, "Constructors cannot be static");
5799 static final ParserErrorCode STATIC_GETTER_WITHOUT_BODY = new ParserErrorCode. con3('STATIC_GETTER_WITHOUT_BODY', 111, "A 'static' getter must have a body");
5800 static final ParserErrorCode STATIC_OPERATOR = new ParserErrorCode.con3('STATI C_OPERATOR', 112, "Operators cannot be static");
5801 static final ParserErrorCode STATIC_SETTER_WITHOUT_BODY = new ParserErrorCode. con3('STATIC_SETTER_WITHOUT_BODY', 113, "A 'static' setter must have a body");
5802 static final ParserErrorCode STATIC_TOP_LEVEL_DECLARATION = new ParserErrorCod e.con3('STATIC_TOP_LEVEL_DECLARATION', 114, "Top-level declarations cannot be de clared to be 'static'");
5803 static final ParserErrorCode SWITCH_HAS_CASE_AFTER_DEFAULT_CASE = new ParserEr rorCode.con3('SWITCH_HAS_CASE_AFTER_DEFAULT_CASE', 115, "The 'default' case shou ld be the last case in a switch statement");
5804 static final ParserErrorCode SWITCH_HAS_MULTIPLE_DEFAULT_CASES = new ParserErr orCode.con3('SWITCH_HAS_MULTIPLE_DEFAULT_CASES', 116, "The 'default' case can on ly be declared once");
5805 static final ParserErrorCode TOP_LEVEL_OPERATOR = new ParserErrorCode.con3('TO P_LEVEL_OPERATOR', 117, "Operators must be declared within a class");
5806 static final ParserErrorCode UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP = new P arserErrorCode.con3('UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP', 118, "There is no '%s' to open a parameter group");
5807 static final ParserErrorCode UNEXPECTED_TOKEN = new ParserErrorCode.con3('UNEX PECTED_TOKEN', 119, "Unexpected token '%s'");
5808 static final ParserErrorCode WITH_BEFORE_EXTENDS = new ParserErrorCode.con3('W ITH_BEFORE_EXTENDS', 120, "The extends clause must be before the with clause");
5809 static final ParserErrorCode WITH_WITHOUT_EXTENDS = new ParserErrorCode.con3(' WITH_WITHOUT_EXTENDS', 121, "The with clause cannot be used without an extends c lause");
5810 static final ParserErrorCode WRONG_SEPARATOR_FOR_NAMED_PARAMETER = new ParserE rrorCode.con3('WRONG_SEPARATOR_FOR_NAMED_PARAMETER', 122, "The default value of a named parameter should be preceeded by ':'");
5811 static final ParserErrorCode WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER = new Pa rserErrorCode.con3('WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER', 123, "The default value of a positional parameter should be preceeded by '='");
5812 static final ParserErrorCode WRONG_TERMINATOR_FOR_PARAMETER_GROUP = new Parser ErrorCode.con3('WRONG_TERMINATOR_FOR_PARAMETER_GROUP', 124, "Expected '%s' to cl ose parameter group");
5813 static final ParserErrorCode VAR_AND_TYPE = new ParserErrorCode.con3('VAR_AND_ TYPE', 125, "Variables cannot be declared using both 'var' and a type name; remo ve the 'var'");
5814 static final ParserErrorCode VAR_AS_TYPE_NAME = new ParserErrorCode.con3('VAR_ AS_TYPE_NAME', 126, "The keyword 'var' cannot be used as a type name");
5815 static final ParserErrorCode VAR_CLASS = new ParserErrorCode.con3('VAR_CLASS', 127, "Classes cannot be declared to be 'var'");
5816 static final ParserErrorCode VAR_RETURN_TYPE = new ParserErrorCode.con3('VAR_R ETURN_TYPE', 128, "The return type cannot be 'var'");
5817 static final ParserErrorCode VAR_TYPEDEF = new ParserErrorCode.con3('VAR_TYPED EF', 129, "Type aliases cannot be declared to be 'var'");
5818 static final ParserErrorCode VOID_PARAMETER = new ParserErrorCode.con3('VOID_P ARAMETER', 130, "Parameters cannot have a type of 'void'");
5819 static final ParserErrorCode VOID_VARIABLE = new ParserErrorCode.con3('VOID_VA RIABLE', 131, "Variables cannot have a type of 'void'");
5820 static final List<ParserErrorCode> values = [
5821 ABSTRACT_CLASS_MEMBER,
5822 ABSTRACT_STATIC_METHOD,
5823 ABSTRACT_TOP_LEVEL_FUNCTION,
5824 ABSTRACT_TOP_LEVEL_VARIABLE,
5825 ABSTRACT_TYPEDEF,
5826 ASSERT_DOES_NOT_TAKE_ASSIGNMENT,
5827 ASSERT_DOES_NOT_TAKE_CASCADE,
5828 ASSERT_DOES_NOT_TAKE_THROW,
5829 ASSERT_DOES_NOT_TAKE_RETHROW,
5830 BREAK_OUTSIDE_OF_LOOP,
5831 CONST_AND_FINAL,
5832 CONST_AND_VAR,
5833 CONST_CLASS,
5834 CONST_CONSTRUCTOR_WITH_BODY,
5835 CONST_FACTORY,
5836 CONST_METHOD,
5837 CONST_TYPEDEF,
5838 CONSTRUCTOR_WITH_RETURN_TYPE,
5839 CONTINUE_OUTSIDE_OF_LOOP,
5840 CONTINUE_WITHOUT_LABEL_IN_CASE,
5841 DEPRECATED_ARGUMENT_DEFINITION_TEST,
5842 DEPRECATED_CLASS_TYPE_ALIAS,
5843 DIRECTIVE_AFTER_DECLARATION,
5844 DUPLICATE_LABEL_IN_SWITCH_STATEMENT,
5845 DUPLICATED_MODIFIER,
5846 EQUALITY_CANNOT_BE_EQUALITY_OPERAND,
5847 EXPECTED_CASE_OR_DEFAULT,
5848 EXPECTED_CLASS_MEMBER,
5849 EXPECTED_EXECUTABLE,
5850 EXPECTED_LIST_OR_MAP_LITERAL,
5851 EXPECTED_STRING_LITERAL,
5852 EXPECTED_TOKEN,
5853 EXPECTED_TYPE_NAME,
5854 EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE,
5855 EXTERNAL_AFTER_CONST,
5856 EXTERNAL_AFTER_FACTORY,
5857 EXTERNAL_AFTER_STATIC,
5858 EXTERNAL_CLASS,
5859 EXTERNAL_CONSTRUCTOR_WITH_BODY,
5860 EXTERNAL_FIELD,
5861 EXTERNAL_GETTER_WITH_BODY,
5862 EXTERNAL_METHOD_WITH_BODY,
5863 EXTERNAL_OPERATOR_WITH_BODY,
5864 EXTERNAL_SETTER_WITH_BODY,
5865 EXTERNAL_TYPEDEF,
5866 FACTORY_TOP_LEVEL_DECLARATION,
5867 FACTORY_WITHOUT_BODY,
5868 FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR,
5869 FINAL_AND_VAR,
5870 FINAL_CLASS,
5871 FINAL_CONSTRUCTOR,
5872 FINAL_METHOD,
5873 FINAL_TYPEDEF,
5874 FUNCTION_TYPED_PARAMETER_VAR,
5875 GETTER_IN_FUNCTION,
5876 GETTER_WITH_PARAMETERS,
5877 ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE,
5878 IMPLEMENTS_BEFORE_EXTENDS,
5879 IMPLEMENTS_BEFORE_WITH,
5880 IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE,
5881 INITIALIZED_VARIABLE_IN_FOR_EACH,
5882 INVALID_CODE_POINT,
5883 INVALID_COMMENT_REFERENCE,
5884 INVALID_HEX_ESCAPE,
5885 INVALID_OPERATOR,
5886 INVALID_OPERATOR_FOR_SUPER,
5887 INVALID_UNICODE_ESCAPE,
5888 LIBRARY_DIRECTIVE_NOT_FIRST,
5889 LOCAL_FUNCTION_DECLARATION_MODIFIER,
5890 MISSING_ASSIGNABLE_SELECTOR,
5891 MISSING_CATCH_OR_FINALLY,
5892 MISSING_CLASS_BODY,
5893 MISSING_CLOSING_PARENTHESIS,
5894 MISSING_CONST_FINAL_VAR_OR_TYPE,
5895 MISSING_EXPRESSION_IN_THROW,
5896 MISSING_FUNCTION_BODY,
5897 MISSING_FUNCTION_PARAMETERS,
5898 MISSING_IDENTIFIER,
5899 MISSING_KEYWORD_OPERATOR,
5900 MISSING_NAME_IN_LIBRARY_DIRECTIVE,
5901 MISSING_NAME_IN_PART_OF_DIRECTIVE,
5902 MISSING_STATEMENT,
5903 MISSING_TERMINATOR_FOR_PARAMETER_GROUP,
5904 MISSING_TYPEDEF_PARAMETERS,
5905 MISSING_VARIABLE_IN_FOR_EACH,
5906 MIXED_PARAMETER_GROUPS,
5907 MULTIPLE_EXTENDS_CLAUSES,
5908 MULTIPLE_IMPLEMENTS_CLAUSES,
5909 MULTIPLE_LIBRARY_DIRECTIVES,
5910 MULTIPLE_NAMED_PARAMETER_GROUPS,
5911 MULTIPLE_PART_OF_DIRECTIVES,
5912 MULTIPLE_POSITIONAL_PARAMETER_GROUPS,
5913 MULTIPLE_VARIABLES_IN_FOR_EACH,
5914 MULTIPLE_WITH_CLAUSES,
5915 NAMED_FUNCTION_EXPRESSION,
5916 NAMED_PARAMETER_OUTSIDE_GROUP,
5917 NATIVE_CLAUSE_IN_NON_SDK_CODE,
5918 NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE,
5919 NON_CONSTRUCTOR_FACTORY,
5920 NON_IDENTIFIER_LIBRARY_NAME,
5921 NON_PART_OF_DIRECTIVE_IN_PART,
5922 NON_USER_DEFINABLE_OPERATOR,
5923 NORMAL_BEFORE_OPTIONAL_PARAMETERS,
5924 POSITIONAL_AFTER_NAMED_ARGUMENT,
5925 POSITIONAL_PARAMETER_OUTSIDE_GROUP,
5926 REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR,
5927 SETTER_IN_FUNCTION,
5928 STATIC_AFTER_CONST,
5929 STATIC_AFTER_FINAL,
5930 STATIC_AFTER_VAR,
5931 STATIC_CONSTRUCTOR,
5932 STATIC_GETTER_WITHOUT_BODY,
5933 STATIC_OPERATOR,
5934 STATIC_SETTER_WITHOUT_BODY,
5935 STATIC_TOP_LEVEL_DECLARATION,
5936 SWITCH_HAS_CASE_AFTER_DEFAULT_CASE,
5937 SWITCH_HAS_MULTIPLE_DEFAULT_CASES,
5938 TOP_LEVEL_OPERATOR,
5939 UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP,
5940 UNEXPECTED_TOKEN,
5941 WITH_BEFORE_EXTENDS,
5942 WITH_WITHOUT_EXTENDS,
5943 WRONG_SEPARATOR_FOR_NAMED_PARAMETER,
5944 WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER,
5945 WRONG_TERMINATOR_FOR_PARAMETER_GROUP,
5946 VAR_AND_TYPE,
5947 VAR_AS_TYPE_NAME,
5948 VAR_CLASS,
5949 VAR_RETURN_TYPE,
5950 VAR_TYPEDEF,
5951 VOID_PARAMETER,
5952 VOID_VARIABLE];
5953
5954 /**
5955 * The severity of this error.
5956 */
5957 ErrorSeverity _severity;
5958
5959 /**
5960 * The template used to create the message to be displayed for this error.
5961 */
5962 String _message;
5963
5964 /**
5965 * The template used to create the correction to be displayed for this error, or `null` if
5966 * there is no correction information for this error.
5967 */
5968 String correction8;
5969
5970 /**
5971 * Initialize a newly created error code to have the given severity and messag e.
5972 *
5973 * @param severity the severity of the error
5974 * @param message the message template used to create the message to be displa yed for the error
5975 */
5976 ParserErrorCode.con1(String name, int ordinal, ErrorSeverity severity, String message) : super(name, ordinal) {
5977 this._severity = severity;
5978 this._message = message;
5979 }
5980
5981 /**
5982 * Initialize a newly created error code to have the given severity, message a nd correction.
5983 *
5984 * @param severity the severity of the error
5985 * @param message the template used to create the message to be displayed for the error
5986 * @param correction the template used to create the correction to be displaye d for the error
5987 */
5988 ParserErrorCode.con2(String name, int ordinal, ErrorSeverity severity, String message, String correction) : super(name, ordinal) {
5989 this._severity = severity;
5990 this._message = message;
5991 this.correction8 = correction;
5992 }
5993
5994 /**
5995 * Initialize a newly created error code to have the given message and a sever ity of ERROR.
5996 *
5997 * @param message the message template used to create the message to be displa yed for the error
5998 */
5999 ParserErrorCode.con3(String name, int ordinal, String message) : this.con1(nam e, ordinal, ErrorSeverity.ERROR, message);
6000 String get correction => correction8;
6001 ErrorSeverity get errorSeverity => _severity;
6002 String get message => _message;
6003 ErrorType get type => ErrorType.SYNTACTIC_ERROR;
6004 }
6005 /**
6006 * Instances of the class {link ToFormattedSourceVisitor} write a source represe ntation of a visited
6007 * AST node (and all of it's children) to a writer.
6008 */
6009 class ToFormattedSourceVisitor implements ASTVisitor<Object> {
6010
6011 /**
6012 * The writer to which the source is to be written.
6013 */
6014 PrintWriter _writer;
6015 int _indentLevel = 0;
6016 String _indentString = "";
6017
6018 /**
6019 * Initialize a newly created visitor to write source code representing the vi sited nodes to the
6020 * given writer.
6021 *
6022 * @param writer the writer to which the source is to be written
6023 */
6024 ToFormattedSourceVisitor(PrintWriter writer) {
6025 this._writer = writer;
6026 }
6027 Object visitAdjacentStrings(AdjacentStrings node) {
6028 visitList5(node.strings, " ");
6029 return null;
6030 }
6031 Object visitAnnotation(Annotation node) {
6032 _writer.print('@');
6033 visit(node.name);
6034 visit7(".", node.constructorName);
6035 visit(node.arguments);
6036 return null;
6037 }
6038 Object visitArgumentDefinitionTest(ArgumentDefinitionTest node) {
6039 _writer.print('?');
6040 visit(node.identifier);
6041 return null;
6042 }
6043 Object visitArgumentList(ArgumentList node) {
6044 _writer.print('(');
6045 visitList5(node.arguments, ", ");
6046 _writer.print(')');
6047 return null;
6048 }
6049 Object visitAsExpression(AsExpression node) {
6050 visit(node.expression);
6051 _writer.print(" as ");
6052 visit(node.type);
6053 return null;
6054 }
6055 Object visitAssertStatement(AssertStatement node) {
6056 _writer.print("assert(");
6057 visit(node.condition);
6058 _writer.print(");");
6059 return null;
6060 }
6061 Object visitAssignmentExpression(AssignmentExpression node) {
6062 visit(node.leftHandSide);
6063 _writer.print(' ');
6064 _writer.print(node.operator.lexeme);
6065 _writer.print(' ');
6066 visit(node.rightHandSide);
6067 return null;
6068 }
6069 Object visitBinaryExpression(BinaryExpression node) {
6070 visit(node.leftOperand);
6071 _writer.print(' ');
6072 _writer.print(node.operator.lexeme);
6073 _writer.print(' ');
6074 visit(node.rightOperand);
6075 return null;
6076 }
6077 Object visitBlock(Block node) {
6078 _writer.print('{');
6079 {
6080 indentInc();
6081 visitList5(node.statements, "\n");
6082 indentDec();
6083 }
6084 nl2();
6085 _writer.print('}');
6086 return null;
6087 }
6088 Object visitBlockFunctionBody(BlockFunctionBody node) {
6089 visit(node.block);
6090 return null;
6091 }
6092 Object visitBooleanLiteral(BooleanLiteral node) {
6093 _writer.print(node.literal.lexeme);
6094 return null;
6095 }
6096 Object visitBreakStatement(BreakStatement node) {
6097 _writer.print("break");
6098 visit7(" ", node.label);
6099 _writer.print(";");
6100 return null;
6101 }
6102 Object visitCascadeExpression(CascadeExpression node) {
6103 visit(node.target);
6104 visitList(node.cascadeSections);
6105 return null;
6106 }
6107 Object visitCatchClause(CatchClause node) {
6108 visit7("on ", node.exceptionType);
6109 if (node.catchKeyword != null) {
6110 if (node.exceptionType != null) {
6111 _writer.print(' ');
6112 }
6113 _writer.print("catch (");
6114 visit(node.exceptionParameter);
6115 visit7(", ", node.stackTraceParameter);
6116 _writer.print(") ");
6117 } else {
6118 _writer.print(" ");
6119 }
6120 visit(node.body);
6121 return null;
6122 }
6123 Object visitClassDeclaration(ClassDeclaration node) {
6124 visit(node.documentationComment);
6125 visit8(node.abstractKeyword, " ");
6126 _writer.print("class ");
6127 visit(node.name);
6128 visit(node.typeParameters);
6129 visit7(" ", node.extendsClause);
6130 visit7(" ", node.withClause);
6131 visit7(" ", node.implementsClause);
6132 _writer.print(" {");
6133 {
6134 indentInc();
6135 visitList5(node.members, "\n");
6136 indentDec();
6137 }
6138 nl2();
6139 _writer.print("}");
6140 return null;
6141 }
6142 Object visitClassTypeAlias(ClassTypeAlias node) {
6143 _writer.print("typedef ");
6144 visit(node.name);
6145 visit(node.typeParameters);
6146 _writer.print(" = ");
6147 if (node.abstractKeyword != null) {
6148 _writer.print("abstract ");
6149 }
6150 visit(node.superclass);
6151 visit7(" ", node.withClause);
6152 visit7(" ", node.implementsClause);
6153 _writer.print(";");
6154 return null;
6155 }
6156 Object visitComment(Comment node) {
6157 Token token = node.beginToken;
6158 while (token != null) {
6159 bool firstLine = true;
6160 for (String line in StringUtils.split(token.lexeme, "\n")) {
6161 if (firstLine) {
6162 firstLine = false;
6163 if (node.isDocumentation) {
6164 nl2();
6165 }
6166 } else {
6167 line = " ${line.trim()}";
6168 line = StringUtils.replace(line, "/*", "/ *");
6169 }
6170 _writer.print(line);
6171 nl2();
6172 }
6173 if (identical(token, node.endToken)) {
6174 break;
6175 }
6176 }
6177 return null;
6178 }
6179 Object visitCommentReference(CommentReference node) => null;
6180 Object visitCompilationUnit(CompilationUnit node) {
6181 ScriptTag scriptTag = node.scriptTag;
6182 NodeList<Directive> directives = node.directives;
6183 visit(scriptTag);
6184 String prefix = scriptTag == null ? "" : " ";
6185 visitList7(prefix, directives, "\n");
6186 prefix = scriptTag == null && directives.isEmpty ? "" : "\n\n";
6187 visitList7(prefix, node.declarations, "\n");
6188 return null;
6189 }
6190 Object visitConditionalExpression(ConditionalExpression node) {
6191 visit(node.condition);
6192 _writer.print(" ? ");
6193 visit(node.thenExpression);
6194 _writer.print(" : ");
6195 visit(node.elseExpression);
6196 return null;
6197 }
6198 Object visitConstructorDeclaration(ConstructorDeclaration node) {
6199 visit(node.documentationComment);
6200 visit8(node.externalKeyword, " ");
6201 visit8(node.constKeyword, " ");
6202 visit8(node.factoryKeyword, " ");
6203 visit(node.returnType);
6204 visit7(".", node.name);
6205 visit(node.parameters);
6206 visitList7(" : ", node.initializers, ", ");
6207 visit7(" = ", node.redirectedConstructor);
6208 if (node.body is! EmptyFunctionBody) {
6209 _writer.print(' ');
6210 }
6211 visit(node.body);
6212 return null;
6213 }
6214 Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
6215 visit8(node.keyword, ".");
6216 visit(node.fieldName);
6217 _writer.print(" = ");
6218 visit(node.expression);
6219 return null;
6220 }
6221 Object visitConstructorName(ConstructorName node) {
6222 visit(node.type);
6223 visit7(".", node.name);
6224 return null;
6225 }
6226 Object visitContinueStatement(ContinueStatement node) {
6227 _writer.print("continue");
6228 visit7(" ", node.label);
6229 _writer.print(";");
6230 return null;
6231 }
6232 Object visitDeclaredIdentifier(DeclaredIdentifier node) {
6233 visit8(node.keyword, " ");
6234 visit6(node.type, " ");
6235 visit(node.identifier);
6236 return null;
6237 }
6238 Object visitDefaultFormalParameter(DefaultFormalParameter node) {
6239 visit(node.parameter);
6240 if (node.separator != null) {
6241 _writer.print(" ");
6242 _writer.print(node.separator.lexeme);
6243 visit7(" ", node.defaultValue);
6244 }
6245 return null;
6246 }
6247 Object visitDoStatement(DoStatement node) {
6248 _writer.print("do ");
6249 visit(node.body);
6250 _writer.print(" while (");
6251 visit(node.condition);
6252 _writer.print(");");
6253 return null;
6254 }
6255 Object visitDoubleLiteral(DoubleLiteral node) {
6256 _writer.print(node.literal.lexeme);
6257 return null;
6258 }
6259 Object visitEmptyFunctionBody(EmptyFunctionBody node) {
6260 _writer.print(';');
6261 return null;
6262 }
6263 Object visitEmptyStatement(EmptyStatement node) {
6264 _writer.print(';');
6265 return null;
6266 }
6267 Object visitExportDirective(ExportDirective node) {
6268 _writer.print("export ");
6269 visit(node.uri);
6270 visitList7(" ", node.combinators, " ");
6271 _writer.print(';');
6272 return null;
6273 }
6274 Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
6275 _writer.print("=> ");
6276 visit(node.expression);
6277 if (node.semicolon != null) {
6278 _writer.print(';');
6279 }
6280 return null;
6281 }
6282 Object visitExpressionStatement(ExpressionStatement node) {
6283 visit(node.expression);
6284 _writer.print(';');
6285 return null;
6286 }
6287 Object visitExtendsClause(ExtendsClause node) {
6288 _writer.print("extends ");
6289 visit(node.superclass);
6290 return null;
6291 }
6292 Object visitFieldDeclaration(FieldDeclaration node) {
6293 visit(node.documentationComment);
6294 visit8(node.staticKeyword, " ");
6295 visit(node.fields);
6296 _writer.print(";");
6297 return null;
6298 }
6299 Object visitFieldFormalParameter(FieldFormalParameter node) {
6300 visit8(node.keyword, " ");
6301 visit6(node.type, " ");
6302 _writer.print("this.");
6303 visit(node.identifier);
6304 visit(node.parameters);
6305 return null;
6306 }
6307 Object visitForEachStatement(ForEachStatement node) {
6308 DeclaredIdentifier loopVariable = node.loopVariable;
6309 _writer.print("for (");
6310 if (loopVariable == null) {
6311 visit(node.identifier);
6312 } else {
6313 visit(loopVariable);
6314 }
6315 _writer.print(" in ");
6316 visit(node.iterator);
6317 _writer.print(") ");
6318 visit(node.body);
6319 return null;
6320 }
6321 Object visitFormalParameterList(FormalParameterList node) {
6322 String groupEnd = null;
6323 _writer.print('(');
6324 NodeList<FormalParameter> parameters = node.parameters;
6325 int size = parameters.length;
6326 for (int i = 0; i < size; i++) {
6327 FormalParameter parameter = parameters[i];
6328 if (i > 0) {
6329 _writer.print(", ");
6330 }
6331 if (groupEnd == null && parameter is DefaultFormalParameter) {
6332 if (identical(parameter.kind, ParameterKind.NAMED)) {
6333 groupEnd = "}";
6334 _writer.print('{');
6335 } else {
6336 groupEnd = "]";
6337 _writer.print('[');
6338 }
6339 }
6340 parameter.accept(this);
6341 }
6342 if (groupEnd != null) {
6343 _writer.print(groupEnd);
6344 }
6345 _writer.print(')');
6346 return null;
6347 }
6348 Object visitForStatement(ForStatement node) {
6349 Expression initialization = node.initialization;
6350 _writer.print("for (");
6351 if (initialization != null) {
6352 visit(initialization);
6353 } else {
6354 visit(node.variables);
6355 }
6356 _writer.print(";");
6357 visit7(" ", node.condition);
6358 _writer.print(";");
6359 visitList7(" ", node.updaters, ", ");
6360 _writer.print(") ");
6361 visit(node.body);
6362 return null;
6363 }
6364 Object visitFunctionDeclaration(FunctionDeclaration node) {
6365 visit6(node.returnType, " ");
6366 visit8(node.propertyKeyword, " ");
6367 visit(node.name);
6368 visit(node.functionExpression);
6369 return null;
6370 }
6371 Object visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
6372 visit(node.functionDeclaration);
6373 _writer.print(';');
6374 return null;
6375 }
6376 Object visitFunctionExpression(FunctionExpression node) {
6377 visit(node.parameters);
6378 _writer.print(' ');
6379 visit(node.body);
6380 return null;
6381 }
6382 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
6383 visit(node.function);
6384 visit(node.argumentList);
6385 return null;
6386 }
6387 Object visitFunctionTypeAlias(FunctionTypeAlias node) {
6388 _writer.print("typedef ");
6389 visit6(node.returnType, " ");
6390 visit(node.name);
6391 visit(node.typeParameters);
6392 visit(node.parameters);
6393 _writer.print(";");
6394 return null;
6395 }
6396 Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
6397 visit6(node.returnType, " ");
6398 visit(node.identifier);
6399 visit(node.parameters);
6400 return null;
6401 }
6402 Object visitHideCombinator(HideCombinator node) {
6403 _writer.print("hide ");
6404 visitList5(node.hiddenNames, ", ");
6405 return null;
6406 }
6407 Object visitIfStatement(IfStatement node) {
6408 _writer.print("if (");
6409 visit(node.condition);
6410 _writer.print(") ");
6411 visit(node.thenStatement);
6412 visit7(" else ", node.elseStatement);
6413 return null;
6414 }
6415 Object visitImplementsClause(ImplementsClause node) {
6416 _writer.print("implements ");
6417 visitList5(node.interfaces, ", ");
6418 return null;
6419 }
6420 Object visitImportDirective(ImportDirective node) {
6421 _writer.print("import ");
6422 visit(node.uri);
6423 visit7(" as ", node.prefix);
6424 visitList7(" ", node.combinators, " ");
6425 _writer.print(';');
6426 return null;
6427 }
6428 Object visitIndexExpression(IndexExpression node) {
6429 if (node.isCascaded) {
6430 _writer.print("..");
6431 } else {
6432 visit(node.target);
6433 }
6434 _writer.print('[');
6435 visit(node.index);
6436 _writer.print(']');
6437 return null;
6438 }
6439 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
6440 visit8(node.keyword, " ");
6441 visit(node.constructorName);
6442 visit(node.argumentList);
6443 return null;
6444 }
6445 Object visitIntegerLiteral(IntegerLiteral node) {
6446 _writer.print(node.literal.lexeme);
6447 return null;
6448 }
6449 Object visitInterpolationExpression(InterpolationExpression node) {
6450 if (node.rightBracket != null) {
6451 _writer.print("\${");
6452 visit(node.expression);
6453 _writer.print("}");
6454 } else {
6455 _writer.print("\$");
6456 visit(node.expression);
6457 }
6458 return null;
6459 }
6460 Object visitInterpolationString(InterpolationString node) {
6461 _writer.print(node.contents.lexeme);
6462 return null;
6463 }
6464 Object visitIsExpression(IsExpression node) {
6465 visit(node.expression);
6466 if (node.notOperator == null) {
6467 _writer.print(" is ");
6468 } else {
6469 _writer.print(" is! ");
6470 }
6471 visit(node.type);
6472 return null;
6473 }
6474 Object visitLabel(Label node) {
6475 visit(node.label);
6476 _writer.print(":");
6477 return null;
6478 }
6479 Object visitLabeledStatement(LabeledStatement node) {
6480 visitList6(node.labels, " ", " ");
6481 visit(node.statement);
6482 return null;
6483 }
6484 Object visitLibraryDirective(LibraryDirective node) {
6485 _writer.print("library ");
6486 visit(node.name);
6487 _writer.print(';');
6488 nl();
6489 return null;
6490 }
6491 Object visitLibraryIdentifier(LibraryIdentifier node) {
6492 _writer.print(node.name);
6493 return null;
6494 }
6495 Object visitListLiteral(ListLiteral node) {
6496 if (node.constKeyword != null) {
6497 _writer.print(node.constKeyword.lexeme);
6498 _writer.print(' ');
6499 }
6500 visit6(node.typeArguments, " ");
6501 _writer.print("[");
6502 {
6503 NodeList<Expression> elements = node.elements;
6504 if (elements.length < 2 || elements.toString().length < 60) {
6505 visitList5(elements, ", ");
6506 } else {
6507 String elementIndent = "${_indentString} ";
6508 _writer.print("\n");
6509 _writer.print(elementIndent);
6510 visitList5(elements, ",\n${elementIndent}");
6511 }
6512 }
6513 _writer.print("]");
6514 return null;
6515 }
6516 Object visitMapLiteral(MapLiteral node) {
6517 if (node.constKeyword != null) {
6518 _writer.print(node.constKeyword.lexeme);
6519 _writer.print(' ');
6520 }
6521 visit6(node.typeArguments, " ");
6522 _writer.print("{");
6523 visitList5(node.entries, ", ");
6524 _writer.print("}");
6525 return null;
6526 }
6527 Object visitMapLiteralEntry(MapLiteralEntry node) {
6528 visit(node.key);
6529 _writer.print(" : ");
6530 visit(node.value);
6531 return null;
6532 }
6533 Object visitMethodDeclaration(MethodDeclaration node) {
6534 visit(node.documentationComment);
6535 visit8(node.externalKeyword, " ");
6536 visit8(node.modifierKeyword, " ");
6537 visit6(node.returnType, " ");
6538 visit8(node.propertyKeyword, " ");
6539 visit8(node.operatorKeyword, " ");
6540 visit(node.name);
6541 if (!node.isGetter) {
6542 visit(node.parameters);
6543 }
6544 if (node.body is! EmptyFunctionBody) {
6545 _writer.print(' ');
6546 }
6547 visit(node.body);
6548 return null;
6549 }
6550 Object visitMethodInvocation(MethodInvocation node) {
6551 if (node.isCascaded) {
6552 _writer.print("..");
6553 } else {
6554 visit6(node.target, ".");
6555 }
6556 visit(node.methodName);
6557 visit(node.argumentList);
6558 return null;
6559 }
6560 Object visitNamedExpression(NamedExpression node) {
6561 visit(node.name);
6562 visit7(" ", node.expression);
6563 return null;
6564 }
6565 Object visitNativeClause(NativeClause node) {
6566 _writer.print("native ");
6567 visit(node.name);
6568 return null;
6569 }
6570 Object visitNativeFunctionBody(NativeFunctionBody node) {
6571 _writer.print("native ");
6572 visit(node.stringLiteral);
6573 _writer.print(';');
6574 return null;
6575 }
6576 Object visitNullLiteral(NullLiteral node) {
6577 _writer.print("null");
6578 return null;
6579 }
6580 Object visitParenthesizedExpression(ParenthesizedExpression node) {
6581 _writer.print('(');
6582 visit(node.expression);
6583 _writer.print(')');
6584 return null;
6585 }
6586 Object visitPartDirective(PartDirective node) {
6587 _writer.print("part ");
6588 visit(node.uri);
6589 _writer.print(';');
6590 return null;
6591 }
6592 Object visitPartOfDirective(PartOfDirective node) {
6593 _writer.print("part of ");
6594 visit(node.libraryName);
6595 _writer.print(';');
6596 return null;
6597 }
6598 Object visitPostfixExpression(PostfixExpression node) {
6599 visit(node.operand);
6600 _writer.print(node.operator.lexeme);
6601 return null;
6602 }
6603 Object visitPrefixedIdentifier(PrefixedIdentifier node) {
6604 visit(node.prefix);
6605 _writer.print('.');
6606 visit(node.identifier);
6607 return null;
6608 }
6609 Object visitPrefixExpression(PrefixExpression node) {
6610 _writer.print(node.operator.lexeme);
6611 visit(node.operand);
6612 return null;
6613 }
6614 Object visitPropertyAccess(PropertyAccess node) {
6615 if (node.isCascaded) {
6616 _writer.print("..");
6617 } else {
6618 visit6(node.target, ".");
6619 }
6620 visit(node.propertyName);
6621 return null;
6622 }
6623 Object visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
6624 _writer.print("this");
6625 visit7(".", node.constructorName);
6626 visit(node.argumentList);
6627 return null;
6628 }
6629 Object visitRethrowExpression(RethrowExpression node) {
6630 _writer.print("rethrow");
6631 return null;
6632 }
6633 Object visitReturnStatement(ReturnStatement node) {
6634 Expression expression = node.expression;
6635 if (expression == null) {
6636 _writer.print("return;");
6637 } else {
6638 _writer.print("return ");
6639 expression.accept(this);
6640 _writer.print(";");
6641 }
6642 return null;
6643 }
6644 Object visitScriptTag(ScriptTag node) {
6645 _writer.print(node.scriptTag.lexeme);
6646 return null;
6647 }
6648 Object visitShowCombinator(ShowCombinator node) {
6649 _writer.print("show ");
6650 visitList5(node.shownNames, ", ");
6651 return null;
6652 }
6653 Object visitSimpleFormalParameter(SimpleFormalParameter node) {
6654 visit8(node.keyword, " ");
6655 visit6(node.type, " ");
6656 visit(node.identifier);
6657 return null;
6658 }
6659 Object visitSimpleIdentifier(SimpleIdentifier node) {
6660 _writer.print(node.token.lexeme);
6661 return null;
6662 }
6663 Object visitSimpleStringLiteral(SimpleStringLiteral node) {
6664 _writer.print(node.literal.lexeme);
6665 return null;
6666 }
6667 Object visitStringInterpolation(StringInterpolation node) {
6668 visitList(node.elements);
6669 return null;
6670 }
6671 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
6672 _writer.print("super");
6673 visit7(".", node.constructorName);
6674 visit(node.argumentList);
6675 return null;
6676 }
6677 Object visitSuperExpression(SuperExpression node) {
6678 _writer.print("super");
6679 return null;
6680 }
6681 Object visitSwitchCase(SwitchCase node) {
6682 visitList6(node.labels, " ", " ");
6683 _writer.print("case ");
6684 visit(node.expression);
6685 _writer.print(": ");
6686 {
6687 indentInc();
6688 visitList5(node.statements, "\n");
6689 indentDec();
6690 }
6691 return null;
6692 }
6693 Object visitSwitchDefault(SwitchDefault node) {
6694 visitList6(node.labels, " ", " ");
6695 _writer.print("default: ");
6696 {
6697 indentInc();
6698 visitList5(node.statements, "\n");
6699 indentDec();
6700 }
6701 return null;
6702 }
6703 Object visitSwitchStatement(SwitchStatement node) {
6704 _writer.print("switch (");
6705 visit(node.expression);
6706 _writer.print(") {");
6707 {
6708 indentInc();
6709 visitList5(node.members, "\n");
6710 indentDec();
6711 }
6712 nl2();
6713 _writer.print('}');
6714 return null;
6715 }
6716 Object visitSymbolLiteral(SymbolLiteral node) {
6717 _writer.print("#");
6718 visitList8(node.components, ".");
6719 return null;
6720 }
6721 Object visitThisExpression(ThisExpression node) {
6722 _writer.print("this");
6723 return null;
6724 }
6725 Object visitThrowExpression(ThrowExpression node) {
6726 _writer.print("throw ");
6727 visit(node.expression);
6728 return null;
6729 }
6730 Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
6731 visit6(node.variables, ";");
6732 return null;
6733 }
6734 Object visitTryStatement(TryStatement node) {
6735 _writer.print("try ");
6736 visit(node.body);
6737 visitList7(" ", node.catchClauses, " ");
6738 visit7(" finally ", node.finallyBlock);
6739 return null;
6740 }
6741 Object visitTypeArgumentList(TypeArgumentList node) {
6742 _writer.print('<');
6743 visitList5(node.arguments, ", ");
6744 _writer.print('>');
6745 return null;
6746 }
6747 Object visitTypeName(TypeName node) {
6748 visit(node.name);
6749 visit(node.typeArguments);
6750 return null;
6751 }
6752 Object visitTypeParameter(TypeParameter node) {
6753 visit(node.name);
6754 visit7(" extends ", node.bound);
6755 return null;
6756 }
6757 Object visitTypeParameterList(TypeParameterList node) {
6758 _writer.print('<');
6759 visitList5(node.typeParameters, ", ");
6760 _writer.print('>');
6761 return null;
6762 }
6763 Object visitVariableDeclaration(VariableDeclaration node) {
6764 visit(node.name);
6765 visit7(" = ", node.initializer);
6766 return null;
6767 }
6768 Object visitVariableDeclarationList(VariableDeclarationList node) {
6769 visit8(node.keyword, " ");
6770 visit6(node.type, " ");
6771 visitList5(node.variables, ", ");
6772 return null;
6773 }
6774 Object visitVariableDeclarationStatement(VariableDeclarationStatement node) {
6775 visit(node.variables);
6776 _writer.print(";");
6777 return null;
6778 }
6779 Object visitWhileStatement(WhileStatement node) {
6780 _writer.print("while (");
6781 visit(node.condition);
6782 _writer.print(") ");
6783 visit(node.body);
6784 return null;
6785 }
6786 Object visitWithClause(WithClause node) {
6787 _writer.print("with ");
6788 visitList5(node.mixinTypes, ", ");
6789 return null;
6790 }
6791 void indent() {
6792 _writer.print(_indentString);
6793 }
6794 void indentDec() {
6795 _indentLevel -= 2;
6796 _indentString = StringUtils.repeat(" ", _indentLevel);
6797 }
6798 void indentInc() {
6799 _indentLevel += 2;
6800 _indentString = StringUtils.repeat(" ", _indentLevel);
6801 }
6802 void nl() {
6803 _writer.print("\n");
6804 }
6805 void nl2() {
6806 nl();
6807 indent();
6808 }
6809
6810 /**
6811 * Safely visit the given node.
6812 *
6813 * @param node the node to be visited
6814 */
6815 void visit(ASTNode node) {
6816 if (node != null) {
6817 node.accept(this);
6818 }
6819 }
6820
6821 /**
6822 * Safely visit the given node, printing the suffix after the node if it is no n-<code>null</code>.
6823 *
6824 * @param suffix the suffix to be printed if there is a node to visit
6825 * @param node the node to be visited
6826 */
6827 void visit6(ASTNode node, String suffix) {
6828 if (node != null) {
6829 node.accept(this);
6830 _writer.print(suffix);
6831 }
6832 }
6833
6834 /**
6835 * Safely visit the given node, printing the prefix before the node if it is n on-<code>null</code>
6836 * .
6837 *
6838 * @param prefix the prefix to be printed if there is a node to visit
6839 * @param node the node to be visited
6840 */
6841 void visit7(String prefix, ASTNode node) {
6842 if (node != null) {
6843 _writer.print(prefix);
6844 node.accept(this);
6845 }
6846 }
6847
6848 /**
6849 * Safely visit the given node, printing the suffix after the node if it is no n-<code>null</code>.
6850 *
6851 * @param suffix the suffix to be printed if there is a node to visit
6852 * @param node the node to be visited
6853 */
6854 void visit8(Token token, String suffix) {
6855 if (token != null) {
6856 _writer.print(token.lexeme);
6857 _writer.print(suffix);
6858 }
6859 }
6860
6861 /**
6862 * Print a list of nodes without any separation.
6863 *
6864 * @param nodes the nodes to be printed
6865 * @param separator the separator to be printed between adjacent nodes
6866 */
6867 void visitList(NodeList<ASTNode> nodes) {
6868 visitList5(nodes, "");
6869 }
6870
6871 /**
6872 * Print a list of nodes, separated by the given separator.
6873 *
6874 * @param nodes the nodes to be printed
6875 * @param separator the separator to be printed between adjacent nodes
6876 */
6877 void visitList5(NodeList<ASTNode> nodes, String separator) {
6878 if (nodes != null) {
6879 int size = nodes.length;
6880 for (int i = 0; i < size; i++) {
6881 if ("\n" == separator) {
6882 _writer.print("\n");
6883 indent();
6884 } else if (i > 0) {
6885 _writer.print(separator);
6886 }
6887 nodes[i].accept(this);
6888 }
6889 }
6890 }
6891
6892 /**
6893 * Print a list of nodes, separated by the given separator.
6894 *
6895 * @param nodes the nodes to be printed
6896 * @param separator the separator to be printed between adjacent nodes
6897 * @param suffix the suffix to be printed if the list is not empty
6898 */
6899 void visitList6(NodeList<ASTNode> nodes, String separator, String suffix) {
6900 if (nodes != null) {
6901 int size = nodes.length;
6902 if (size > 0) {
6903 for (int i = 0; i < size; i++) {
6904 if (i > 0) {
6905 _writer.print(separator);
6906 }
6907 nodes[i].accept(this);
6908 }
6909 _writer.print(suffix);
6910 }
6911 }
6912 }
6913
6914 /**
6915 * Print a list of nodes, separated by the given separator.
6916 *
6917 * @param prefix the prefix to be printed if the list is not empty
6918 * @param nodes the nodes to be printed
6919 * @param separator the separator to be printed between adjacent nodes
6920 */
6921 void visitList7(String prefix, NodeList<ASTNode> nodes, String separator) {
6922 if (nodes != null) {
6923 int size = nodes.length;
6924 if (size > 0) {
6925 _writer.print(prefix);
6926 for (int i = 0; i < size; i++) {
6927 if (i > 0) {
6928 _writer.print(separator);
6929 }
6930 nodes[i].accept(this);
6931 }
6932 }
6933 }
6934 }
6935
6936 /**
6937 * Print a list of tokens, separated by the given separator.
6938 *
6939 * @param tokens the tokens to be printed
6940 * @param separator the separator to be printed between adjacent tokens
6941 */
6942 void visitList8(List<Token> tokens, String separator) {
6943 int size = tokens.length;
6944 for (int i = 0; i < size; i++) {
6945 if ("\n" == separator) {
6946 _writer.print("\n");
6947 indent();
6948 } else if (i > 0) {
6949 _writer.print(separator);
6950 }
6951 _writer.print(tokens[i].lexeme);
6952 }
6953 }
6954 }
OLDNEW
« no previous file with comments | « pkg/analyzer_experimental/lib/src/generated/java_junit.dart ('k') | pkg/analyzer_experimental/lib/src/generated/resolver.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698