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

Side by Side Diff: pkg/analyzer-experimental/lib/src/generated/parser.dart

Issue 12838003: Rename analyzer-experimental to analyzer_experimental. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | 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
4 library engine.parser;
5
6 import 'dart:collection';
7 import 'java_core.dart';
8 import 'java_engine.dart';
9 import 'error.dart';
10 import 'source.dart';
11 import 'scanner.dart';
12 import 'ast.dart';
13 import 'package:analyzer-experimental/src/generated/utilities_dart.dart';
14
15 /**
16 * Instances of the class {@code CommentAndMetadata} implement a simple data-hol der for a method
17 * that needs to return multiple values.
18 * @coverage dart.engine.parser
19 */
20 class CommentAndMetadata {
21 /**
22 * The documentation comment that was parsed, or {@code null} if none was give n.
23 */
24 Comment _comment;
25 /**
26 * The metadata that was parsed.
27 */
28 List<Annotation> _metadata;
29 /**
30 * Initialize a newly created holder with the given data.
31 * @param comment the documentation comment that was parsed
32 * @param metadata the metadata that was parsed
33 */
34 CommentAndMetadata(Comment comment, List<Annotation> metadata) {
35 this._comment = comment;
36 this._metadata = metadata;
37 }
38 /**
39 * Return the documentation comment that was parsed, or {@code null} if none w as given.
40 * @return the documentation comment that was parsed
41 */
42 Comment get comment => _comment;
43 /**
44 * Return the metadata that was parsed. If there was no metadata, then the lis t will be empty.
45 * @return the metadata that was parsed
46 */
47 List<Annotation> get metadata => _metadata;
48 }
49 /**
50 * Instances of the class {@code FinalConstVarOrType} implement a simple data-ho lder for a method
51 * that needs to return multiple values.
52 * @coverage dart.engine.parser
53 */
54 class FinalConstVarOrType {
55 /**
56 * The 'final', 'const' or 'var' keyword, or {@code null} if none was given.
57 */
58 Token _keyword;
59 /**
60 * The type, of {@code null} if no type was specified.
61 */
62 TypeName _type;
63 /**
64 * Initialize a newly created holder with the given data.
65 * @param keyword the 'final', 'const' or 'var' keyword
66 * @param type the type
67 */
68 FinalConstVarOrType(Token keyword, TypeName type) {
69 this._keyword = keyword;
70 this._type = type;
71 }
72 /**
73 * Return the 'final', 'const' or 'var' keyword, or {@code null} if none was g iven.
74 * @return the 'final', 'const' or 'var' keyword
75 */
76 Token get keyword => _keyword;
77 /**
78 * Return the type, of {@code null} if no type was specified.
79 * @return the type
80 */
81 TypeName get type => _type;
82 }
83 /**
84 * Instances of the class {@code Modifiers} implement a simple data-holder for a method that needs
85 * to return multiple values.
86 * @coverage dart.engine.parser
87 */
88 class Modifiers {
89 /**
90 * The token representing the keyword 'abstract', or {@code null} if the keywo rd was not found.
91 */
92 Token _abstractKeyword;
93 /**
94 * The token representing the keyword 'const', or {@code null} if the keyword was not found.
95 */
96 Token _constKeyword;
97 /**
98 * The token representing the keyword 'external', or {@code null} if the keywo rd was not found.
99 */
100 Token _externalKeyword;
101 /**
102 * The token representing the keyword 'factory', or {@code null} if the keywor d was not found.
103 */
104 Token _factoryKeyword;
105 /**
106 * The token representing the keyword 'final', or {@code null} if the keyword was not found.
107 */
108 Token _finalKeyword;
109 /**
110 * The token representing the keyword 'static', or {@code null} if the keyword was not found.
111 */
112 Token _staticKeyword;
113 /**
114 * The token representing the keyword 'var', or {@code null} if the keyword wa s not found.
115 */
116 Token _varKeyword;
117 /**
118 * Initialize a newly created and empty set of modifiers.
119 */
120 Modifiers() : super() {
121 }
122 /**
123 * Return the token representing the keyword 'abstract', or {@code null} if th e keyword was not
124 * found.
125 * @return the token representing the keyword 'abstract'
126 */
127 Token get abstractKeyword => _abstractKeyword;
128 /**
129 * Return the token representing the keyword 'const', or {@code null} if the k eyword was not
130 * found.
131 * @return the token representing the keyword 'const'
132 */
133 Token get constKeyword => _constKeyword;
134 /**
135 * Return the token representing the keyword 'external', or {@code null} if th e keyword was not
136 * found.
137 * @return the token representing the keyword 'external'
138 */
139 Token get externalKeyword => _externalKeyword;
140 /**
141 * Return the token representing the keyword 'factory', or {@code null} if the keyword was not
142 * found.
143 * @return the token representing the keyword 'factory'
144 */
145 Token get factoryKeyword => _factoryKeyword;
146 /**
147 * Return the token representing the keyword 'final', or {@code null} if the k eyword was not
148 * found.
149 * @return the token representing the keyword 'final'
150 */
151 Token get finalKeyword => _finalKeyword;
152 /**
153 * Return the token representing the keyword 'static', or {@code null} if the keyword was not
154 * found.
155 * @return the token representing the keyword 'static'
156 */
157 Token get staticKeyword => _staticKeyword;
158 /**
159 * Return the token representing the keyword 'var', or {@code null} if the key word was not found.
160 * @return the token representing the keyword 'var'
161 */
162 Token get varKeyword => _varKeyword;
163 /**
164 * Set the token representing the keyword 'abstract' to the given token.
165 * @param abstractKeyword the token representing the keyword 'abstract'
166 */
167 void set abstractKeyword(Token abstractKeyword4) {
168 this._abstractKeyword = abstractKeyword4;
169 }
170 /**
171 * Set the token representing the keyword 'const' to the given token.
172 * @param constKeyword the token representing the keyword 'const'
173 */
174 void set constKeyword(Token constKeyword3) {
175 this._constKeyword = constKeyword3;
176 }
177 /**
178 * Set the token representing the keyword 'external' to the given token.
179 * @param externalKeyword the token representing the keyword 'external'
180 */
181 void set externalKeyword(Token externalKeyword5) {
182 this._externalKeyword = externalKeyword5;
183 }
184 /**
185 * Set the token representing the keyword 'factory' to the given token.
186 * @param factoryKeyword the token representing the keyword 'factory'
187 */
188 void set factoryKeyword(Token factoryKeyword3) {
189 this._factoryKeyword = factoryKeyword3;
190 }
191 /**
192 * Set the token representing the keyword 'final' to the given token.
193 * @param finalKeyword the token representing the keyword 'final'
194 */
195 void set finalKeyword(Token finalKeyword2) {
196 this._finalKeyword = finalKeyword2;
197 }
198 /**
199 * Set the token representing the keyword 'static' to the given token.
200 * @param staticKeyword the token representing the keyword 'static'
201 */
202 void set staticKeyword(Token staticKeyword2) {
203 this._staticKeyword = staticKeyword2;
204 }
205 /**
206 * Set the token representing the keyword 'var' to the given token.
207 * @param varKeyword the token representing the keyword 'var'
208 */
209 void set varKeyword(Token varKeyword2) {
210 this._varKeyword = varKeyword2;
211 }
212 String toString() {
213 JavaStringBuilder builder = new JavaStringBuilder();
214 bool needsSpace = appendKeyword(builder, false, _abstractKeyword);
215 needsSpace = appendKeyword(builder, needsSpace, _constKeyword);
216 needsSpace = appendKeyword(builder, needsSpace, _externalKeyword);
217 needsSpace = appendKeyword(builder, needsSpace, _factoryKeyword);
218 needsSpace = appendKeyword(builder, needsSpace, _finalKeyword);
219 needsSpace = appendKeyword(builder, needsSpace, _staticKeyword);
220 appendKeyword(builder, needsSpace, _varKeyword);
221 return builder.toString();
222 }
223 /**
224 * If the given keyword is not {@code null}, append it to the given builder, p refixing it with a
225 * space if needed.
226 * @param builder the builder to which the keyword will be appended
227 * @param needsSpace {@code true} if the keyword needs to be prefixed with a s pace
228 * @param keyword the keyword to be appended
229 * @return {@code true} if subsequent keywords need to be prefixed with a spac e
230 */
231 bool appendKeyword(JavaStringBuilder builder, bool needsSpace, Token keyword) {
232 if (keyword != null) {
233 if (needsSpace) {
234 builder.appendChar(0x20);
235 }
236 builder.append(keyword.lexeme);
237 return true;
238 }
239 return needsSpace;
240 }
241 }
242 /**
243 * Instances of the class {@code Parser} are used to parse tokens into an AST st ructure.
244 * @coverage dart.engine.parser
245 */
246 class Parser {
247 /**
248 * The source being parsed.
249 */
250 Source _source;
251 /**
252 * The error listener that will be informed of any errors that are found durin g the parse.
253 */
254 AnalysisErrorListener _errorListener;
255 /**
256 * The next token to be parsed.
257 */
258 Token _currentToken;
259 /**
260 * A flag indicating whether the parser is currently in the body of a loop.
261 */
262 bool _inLoop = false;
263 /**
264 * A flag indicating whether the parser is currently in a switch statement.
265 */
266 bool _inSwitch = false;
267 static String _HIDE = "hide";
268 static String _OF = "of";
269 static String _ON = "on";
270 static String _SHOW = "show";
271 /**
272 * Initialize a newly created parser.
273 * @param source the source being parsed
274 * @param errorListener the error listener that will be informed of any errors that are found
275 * during the parse
276 */
277 Parser(Source source, AnalysisErrorListener errorListener) {
278 this._source = source;
279 this._errorListener = errorListener;
280 }
281 /**
282 * Parse a compilation unit, starting with the given token.
283 * @param token the first token of the compilation unit
284 * @return the compilation unit that was parsed
285 */
286 CompilationUnit parseCompilationUnit(Token token) {
287 _currentToken = token;
288 return parseCompilationUnit2();
289 }
290 /**
291 * Parse an expression, starting with the given token.
292 * @param token the first token of the expression
293 * @return the expression that was parsed, or {@code null} if the tokens do no t represent a
294 * recognizable expression
295 */
296 Expression parseExpression(Token token) {
297 _currentToken = token;
298 return parseExpression2();
299 }
300 /**
301 * Parse a statement, starting with the given token.
302 * @param token the first token of the statement
303 * @return the statement that was parsed, or {@code null} if the tokens do not represent a
304 * recognizable statement
305 */
306 Statement parseStatement(Token token) {
307 _currentToken = token;
308 return parseStatement2();
309 }
310 /**
311 * Parse a sequence of statements, starting with the given token.
312 * @param token the first token of the sequence of statement
313 * @return the statements that were parsed, or {@code null} if the tokens do n ot represent a
314 * recognizable sequence of statements
315 */
316 List<Statement> parseStatements(Token token) {
317 _currentToken = token;
318 return parseStatements2();
319 }
320 void set currentToken(Token currentToken2) {
321 this._currentToken = currentToken2;
322 }
323 /**
324 * Advance to the next token in the token stream.
325 */
326 void advance() {
327 _currentToken = _currentToken.next;
328 }
329 /**
330 * Append the character equivalent of the given scalar value to the given buil der. Use the start
331 * and end indices to report an error, and don't append anything to the builde r, if the scalar
332 * value is invalid.
333 * @param builder the builder to which the scalar value is to be appended
334 * @param escapeSequence the escape sequence that was parsed to produce the sc alar value
335 * @param scalarValue the value to be appended
336 * @param startIndex the index of the first character representing the scalar value
337 * @param endIndex the index of the last character representing the scalar val ue
338 */
339 void appendScalarValue(JavaStringBuilder builder, String escapeSequence, int s calarValue, int startIndex, int endIndex) {
340 if (scalarValue < 0 || scalarValue > Character.MAX_CODE_POINT || (scalarValu e >= 0xD800 && scalarValue <= 0xDFFF)) {
341 reportError4(ParserErrorCode.INVALID_CODE_POINT, [escapeSequence]);
342 return;
343 }
344 if (scalarValue < Character.MAX_VALUE) {
345 builder.appendChar((scalarValue as int));
346 } else {
347 builder.append(Character.toChars(scalarValue));
348 }
349 }
350 /**
351 * Compute the content of a string with the given literal representation.
352 * @param lexeme the literal representation of the string
353 * @return the actual value of the string
354 */
355 String computeStringValue(String lexeme) {
356 if (lexeme.startsWith("r\"\"\"") || lexeme.startsWith("r'''")) {
357 if (lexeme.length > 4) {
358 return lexeme.substring(4, lexeme.length - 3);
359 }
360 } else if (lexeme.startsWith("r\"") || lexeme.startsWith("r'")) {
361 if (lexeme.length > 2) {
362 return lexeme.substring(2, lexeme.length - 1);
363 }
364 }
365 int start = 0;
366 if (lexeme.startsWith("\"\"\"") || lexeme.startsWith("'''")) {
367 start += 3;
368 } else if (lexeme.startsWith("\"") || lexeme.startsWith("'")) {
369 start += 1;
370 }
371 int end = lexeme.length;
372 if (end > 3 && (lexeme.endsWith("\"\"\"") || lexeme.endsWith("'''"))) {
373 end -= 3;
374 } else if (end > 1 && (lexeme.endsWith("\"") || lexeme.endsWith("'"))) {
375 end -= 1;
376 }
377 JavaStringBuilder builder = new JavaStringBuilder();
378 int index = start;
379 while (index < end) {
380 index = translateCharacter(builder, lexeme, index);
381 }
382 return builder.toString();
383 }
384 /**
385 * Create a synthetic identifier.
386 * @return the synthetic identifier that was created
387 */
388 SimpleIdentifier createSyntheticIdentifier() => new SimpleIdentifier.full(crea teSyntheticToken(TokenType.IDENTIFIER));
389 /**
390 * Create a synthetic string literal.
391 * @return the synthetic string literal that was created
392 */
393 SimpleStringLiteral createSyntheticStringLiteral() => new SimpleStringLiteral. full(createSyntheticToken(TokenType.STRING), "");
394 /**
395 * Create a synthetic token with the given type.
396 * @return the synthetic token that was created
397 */
398 Token createSyntheticToken(TokenType type) => new StringToken(type, "", _curre ntToken.offset);
399 /**
400 * Check that the given expression is assignable and report an error if it isn 't.
401 * <pre>
402 * assignableExpression ::=
403 * primary (arguments* assignableSelector)+
404 * | 'super' assignableSelector
405 * | identifier
406 * assignableSelector ::=
407 * '[' expression ']'
408 * | '.' identifier
409 * </pre>
410 * @param expression the expression being checked
411 */
412 void ensureAssignable(Expression expression) {
413 if (expression != null && !expression.isAssignable()) {
414 reportError4(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, []);
415 }
416 }
417 /**
418 * If the current token is a keyword matching the given string, return it afte r advancing to the
419 * next token. Otherwise report an error and return the current token without advancing.
420 * @param keyword the keyword that is expected
421 * @return the token that matched the given type
422 */
423 Token expect(Keyword keyword) {
424 if (matches(keyword)) {
425 return andAdvance;
426 }
427 reportError4(ParserErrorCode.EXPECTED_TOKEN, [keyword.syntax]);
428 return _currentToken;
429 }
430 /**
431 * If the current token has the expected type, return it after advancing to th e next token.
432 * Otherwise report an error and return the current token without advancing.
433 * @param type the type of token that is expected
434 * @return the token that matched the given type
435 */
436 Token expect2(TokenType type) {
437 if (matches5(type)) {
438 return andAdvance;
439 }
440 if (identical(type, TokenType.SEMICOLON)) {
441 reportError5(ParserErrorCode.EXPECTED_TOKEN, _currentToken.previous, [type .lexeme]);
442 } else {
443 reportError4(ParserErrorCode.EXPECTED_TOKEN, [type.lexeme]);
444 }
445 return _currentToken;
446 }
447 /**
448 * Advance to the next token in the token stream, making it the new current to ken.
449 * @return the token that was current before this method was invoked
450 */
451 Token get andAdvance {
452 Token token = _currentToken;
453 advance();
454 return token;
455 }
456 /**
457 * Return {@code true} if the current token is the first token of a return typ e that is followed
458 * by an identifier, possibly followed by a list of type parameters, followed by a
459 * left-parenthesis. This is used by parseTypeAlias to determine whether or no t to parse a return
460 * type.
461 * @return {@code true} if we can successfully parse the rest of a type alias if we first parse a
462 * return type.
463 */
464 bool hasReturnTypeInTypeAlias() {
465 Token next = skipReturnType(_currentToken);
466 if (next == null) {
467 return false;
468 }
469 return matchesIdentifier2(next);
470 }
471 /**
472 * Return {@code true} if the current token appears to be the beginning of a f unction declaration.
473 * @return {@code true} if the current token appears to be the beginning of a function declaration
474 */
475 bool isFunctionDeclaration() {
476 if (matches(Keyword.VOID)) {
477 return true;
478 }
479 Token afterReturnType = skipTypeName(_currentToken);
480 if (afterReturnType == null) {
481 afterReturnType = _currentToken;
482 }
483 Token afterIdentifier = skipSimpleIdentifier(afterReturnType);
484 if (afterIdentifier == null) {
485 afterIdentifier = skipSimpleIdentifier(_currentToken);
486 }
487 if (afterIdentifier == null) {
488 return false;
489 }
490 return isFunctionExpression(afterIdentifier);
491 }
492 /**
493 * Return {@code true} if the given token appears to be the beginning of a fun ction expression.
494 * @param startToken the token that might be the start of a function expressio n
495 * @return {@code true} if the given token appears to be the beginning of a fu nction expression
496 */
497 bool isFunctionExpression(Token startToken) {
498 Token afterParameters = skipFormalParameterList(startToken);
499 if (afterParameters == null) {
500 return false;
501 }
502 return matchesAny(afterParameters, [TokenType.OPEN_CURLY_BRACKET, TokenType. FUNCTION]);
503 }
504 /**
505 * Return {@code true} if the given character is a valid hexadecimal digit.
506 * @param character the character being tested
507 * @return {@code true} if the character is a valid hexadecimal digit
508 */
509 bool isHexDigit(int character) => (0x30 <= character && character <= 0x39) || (0x41 <= character && character <= 0x46) || (0x61 <= character && character <= 0 x66);
510 /**
511 * Return {@code true} if the current token is the first token in an initializ ed variable
512 * declaration rather than an expression. This method assumes that we have alr eady skipped past
513 * any metadata that might be associated with the declaration.
514 * <pre>
515 * initializedVariableDeclaration ::=
516 * declaredIdentifier ('=' expression)? (',' initializedIdentifier)
517 * declaredIdentifier ::=
518 * metadata finalConstVarOrType identifier
519 * finalConstVarOrType ::=
520 * 'final' type?
521 * | 'const' type?
522 * | 'var'
523 * | type
524 * type ::=
525 * qualified typeArguments?
526 * initializedIdentifier ::=
527 * identifier ('=' expression)?
528 * </pre>
529 * @return {@code true} if the current token is the first token in an initiali zed variable
530 * declaration
531 */
532 bool isInitializedVariableDeclaration() {
533 if (matches(Keyword.FINAL) || matches(Keyword.CONST) || matches(Keyword.VAR) ) {
534 return true;
535 }
536 Token token = skipTypeName(_currentToken);
537 if (token == null) {
538 return false;
539 }
540 token = skipSimpleIdentifier(token);
541 if (token == null) {
542 return false;
543 }
544 TokenType type21 = token.type;
545 return identical(type21, TokenType.EQ) || identical(type21, TokenType.COMMA) || identical(type21, TokenType.SEMICOLON) || matches3(token, Keyword.IN);
546 }
547 /**
548 * Return {@code true} if the current token appears to be the beginning of a s witch member.
549 * @return {@code true} if the current token appears to be the beginning of a switch member
550 */
551 bool isSwitchMember() {
552 Token token = _currentToken;
553 while (matches4(token, TokenType.IDENTIFIER) && matches4(token.next, TokenTy pe.COLON)) {
554 token = token.next.next;
555 }
556 if (identical(token.type, TokenType.KEYWORD)) {
557 Keyword keyword29 = ((token as KeywordToken)).keyword;
558 return identical(keyword29, Keyword.CASE) || identical(keyword29, Keyword. DEFAULT);
559 }
560 return false;
561 }
562 /**
563 * Compare the given tokens to find the token that appears first in the source being parsed. That
564 * is, return the left-most of all of the tokens. The arguments are allowed to be {@code null}.
565 * Return the token with the smallest offset, or {@code null} if there are no arguments or if all
566 * of the arguments are {@code null}.
567 * @param tokens the tokens being compared
568 * @return the token with the smallest offset
569 */
570 Token lexicallyFirst(List<Token> tokens) {
571 Token first = null;
572 int firstOffset = 2147483647;
573 for (Token token in tokens) {
574 if (token != null) {
575 int offset5 = token.offset;
576 if (offset5 < firstOffset) {
577 first = token;
578 }
579 }
580 }
581 return first;
582 }
583 /**
584 * Return {@code true} if the current token matches the given keyword.
585 * @param keyword the keyword that can optionally appear in the current locati on
586 * @return {@code true} if the current token matches the given keyword
587 */
588 bool matches(Keyword keyword) => matches3(_currentToken, keyword);
589 /**
590 * Return {@code true} if the current token matches the given identifier.
591 * @param identifier the identifier that can optionally appear in the current location
592 * @return {@code true} if the current token matches the given identifier
593 */
594 bool matches2(String identifier) => identical(_currentToken.type, TokenType.ID ENTIFIER) && _currentToken.lexeme == identifier;
595 /**
596 * Return {@code true} if the given token matches the given keyword.
597 * @param token the token being tested
598 * @param keyword the keyword that is being tested for
599 * @return {@code true} if the given token matches the given keyword
600 */
601 bool matches3(Token token, Keyword keyword37) => identical(token.type, TokenTy pe.KEYWORD) && identical(((token as KeywordToken)).keyword, keyword37);
602 /**
603 * Return {@code true} if the given token has the given type.
604 * @param token the token being tested
605 * @param type the type of token that is being tested for
606 * @return {@code true} if the given token has the given type
607 */
608 bool matches4(Token token, TokenType type30) => identical(token.type, type30);
609 /**
610 * Return {@code true} if the current token has the given type. Note that this method, unlike
611 * other variants, will modify the token stream if possible to match a wider r ange of tokens. In
612 * particular, if we are attempting to match a '>' and the next token is eithe r a '>>' or '>>>',
613 * the token stream will be re-written and {@code true} will be returned.
614 * @param type the type of token that can optionally appear in the current loc ation
615 * @return {@code true} if the current token has the given type
616 */
617 bool matches5(TokenType type31) {
618 TokenType currentType = _currentToken.type;
619 if (currentType != type31) {
620 if (identical(type31, TokenType.GT)) {
621 if (identical(currentType, TokenType.GT_GT)) {
622 int offset6 = _currentToken.offset;
623 Token first = new Token(TokenType.GT, offset6);
624 Token second = new Token(TokenType.GT, offset6 + 1);
625 second.setNext(_currentToken.next);
626 first.setNext(second);
627 _currentToken.previous.setNext(first);
628 _currentToken = first;
629 return true;
630 } else if (identical(currentType, TokenType.GT_EQ)) {
631 int offset7 = _currentToken.offset;
632 Token first = new Token(TokenType.GT, offset7);
633 Token second = new Token(TokenType.EQ, offset7 + 1);
634 second.setNext(_currentToken.next);
635 first.setNext(second);
636 _currentToken.previous.setNext(first);
637 _currentToken = first;
638 return true;
639 } else if (identical(currentType, TokenType.GT_GT_EQ)) {
640 int offset8 = _currentToken.offset;
641 Token first = new Token(TokenType.GT, offset8);
642 Token second = new Token(TokenType.GT, offset8 + 1);
643 Token third = new Token(TokenType.EQ, offset8 + 2);
644 third.setNext(_currentToken.next);
645 second.setNext(third);
646 first.setNext(second);
647 _currentToken.previous.setNext(first);
648 _currentToken = first;
649 return true;
650 }
651 }
652 return false;
653 }
654 return true;
655 }
656 /**
657 * Return {@code true} if the given token has any one of the given types.
658 * @param token the token being tested
659 * @param types the types of token that are being tested for
660 * @return {@code true} if the given token has any of the given types
661 */
662 bool matchesAny(Token token, List<TokenType> types) {
663 TokenType actualType = token.type;
664 for (TokenType type in types) {
665 if (identical(actualType, type)) {
666 return true;
667 }
668 }
669 return false;
670 }
671 /**
672 * Return {@code true} if the current token is a valid identifier. Valid ident ifiers include
673 * built-in identifiers (pseudo-keywords).
674 * @return {@code true} if the current token is a valid identifier
675 */
676 bool matchesIdentifier() => matchesIdentifier2(_currentToken);
677 /**
678 * Return {@code true} if the given token is a valid identifier. Valid identif iers include
679 * built-in identifiers (pseudo-keywords).
680 * @return {@code true} if the given token is a valid identifier
681 */
682 bool matchesIdentifier2(Token token) => matches4(token, TokenType.IDENTIFIER) || (matches4(token, TokenType.KEYWORD) && ((token as KeywordToken)).keyword.isPs eudoKeyword());
683 /**
684 * If the current token has the given type, then advance to the next token and return {@code true}. Otherwise, return {@code false} without advancing.
685 * @param type the type of token that can optionally appear in the current loc ation
686 * @return {@code true} if the current token has the given type
687 */
688 bool optional(TokenType type) {
689 if (matches5(type)) {
690 advance();
691 return true;
692 }
693 return false;
694 }
695 /**
696 * Parse an additive expression.
697 * <pre>
698 * additiveExpression ::=
699 * multiplicativeExpression (additiveOperator multiplicativeExpression)
700 * | 'super' (additiveOperator multiplicativeExpression)+
701 * </pre>
702 * @return the additive expression that was parsed
703 */
704 Expression parseAdditiveExpression() {
705 Expression expression;
706 if (matches(Keyword.SUPER) && _currentToken.next.type.isAdditiveOperator()) {
707 expression = new SuperExpression.full(andAdvance);
708 } else {
709 expression = parseMultiplicativeExpression();
710 }
711 while (_currentToken.type.isAdditiveOperator()) {
712 Token operator = andAdvance;
713 expression = new BinaryExpression.full(expression, operator, parseMultipli cativeExpression());
714 }
715 return expression;
716 }
717 /**
718 * Parse an annotation.
719 * <pre>
720 * annotation ::=
721 * '@' qualified (‘.’ identifier)? arguments?
722 * </pre>
723 * @return the annotation that was parsed
724 */
725 Annotation parseAnnotation() {
726 Token atSign = expect2(TokenType.AT);
727 Identifier name = parsePrefixedIdentifier();
728 Token period = null;
729 SimpleIdentifier constructorName = null;
730 if (matches5(TokenType.PERIOD)) {
731 period = andAdvance;
732 constructorName = parseSimpleIdentifier();
733 }
734 ArgumentList arguments = null;
735 if (matches5(TokenType.OPEN_PAREN)) {
736 arguments = parseArgumentList();
737 }
738 return new Annotation.full(atSign, name, period, constructorName, arguments) ;
739 }
740 /**
741 * Parse an argument.
742 * <pre>
743 * argument ::=
744 * namedArgument
745 * | expression
746 * namedArgument ::=
747 * label expression
748 * </pre>
749 * @return the argument that was parsed
750 */
751 Expression parseArgument() {
752 if (matchesIdentifier() && matches4(peek(), TokenType.COLON)) {
753 SimpleIdentifier label = new SimpleIdentifier.full(andAdvance);
754 Label name = new Label.full(label, andAdvance);
755 return new NamedExpression.full(name, parseExpression2());
756 } else {
757 return parseExpression2();
758 }
759 }
760 /**
761 * Parse an argument definition test.
762 * <pre>
763 * argumentDefinitionTest ::=
764 * '?' identifier
765 * </pre>
766 * @return the argument definition test that was parsed
767 */
768 ArgumentDefinitionTest parseArgumentDefinitionTest() {
769 Token question = expect2(TokenType.QUESTION);
770 SimpleIdentifier identifier = parseSimpleIdentifier();
771 return new ArgumentDefinitionTest.full(question, identifier);
772 }
773 /**
774 * Parse a list of arguments.
775 * <pre>
776 * arguments ::=
777 * '(' argumentList? ')'
778 * argumentList ::=
779 * namedArgument (',' namedArgument)
780 * | expressionList (',' namedArgument)
781 * </pre>
782 * @return the argument list that was parsed
783 */
784 ArgumentList parseArgumentList() {
785 Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
786 List<Expression> arguments = new List<Expression>();
787 if (matches5(TokenType.CLOSE_PAREN)) {
788 return new ArgumentList.full(leftParenthesis, arguments, andAdvance);
789 }
790 Expression argument = parseArgument();
791 arguments.add(argument);
792 bool foundNamedArgument = argument is NamedExpression;
793 bool generatedError = false;
794 while (optional(TokenType.COMMA)) {
795 argument = parseArgument();
796 arguments.add(argument);
797 if (foundNamedArgument) {
798 if (!generatedError && argument is! NamedExpression) {
799 reportError4(ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT, []);
800 generatedError = true;
801 }
802 } else if (argument is NamedExpression) {
803 foundNamedArgument = true;
804 }
805 }
806 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
807 return new ArgumentList.full(leftParenthesis, arguments, rightParenthesis);
808 }
809 /**
810 * Parse an assert statement.
811 * <pre>
812 * assertStatement ::=
813 * 'assert' '(' conditionalExpression ')' ';'
814 * </pre>
815 * @return the assert statement
816 */
817 AssertStatement parseAssertStatement() {
818 Token keyword = expect(Keyword.ASSERT);
819 Token leftParen = expect2(TokenType.OPEN_PAREN);
820 Expression expression = parseConditionalExpression();
821 Token rightParen = expect2(TokenType.CLOSE_PAREN);
822 Token semicolon = expect2(TokenType.SEMICOLON);
823 return new AssertStatement.full(keyword, leftParen, expression, rightParen, semicolon);
824 }
825 /**
826 * Parse an assignable expression.
827 * <pre>
828 * assignableExpression ::=
829 * primary (arguments* assignableSelector)+
830 * | 'super' assignableSelector
831 * | identifier
832 * </pre>
833 * @param primaryAllowed {@code true} if the expression is allowed to be a pri mary without any
834 * assignable selector
835 * @return the assignable expression that was parsed
836 */
837 Expression parseAssignableExpression(bool primaryAllowed) {
838 if (matches(Keyword.SUPER)) {
839 return parseAssignableSelector(new SuperExpression.full(andAdvance), false );
840 }
841 Expression expression = parsePrimaryExpression();
842 bool isOptional = primaryAllowed || expression is SimpleIdentifier;
843 while (true) {
844 while (matches5(TokenType.OPEN_PAREN)) {
845 ArgumentList argumentList = parseArgumentList();
846 if (expression is SimpleIdentifier) {
847 expression = new MethodInvocation.full(null, null, (expression as Simp leIdentifier), argumentList);
848 } else if (expression is PrefixedIdentifier) {
849 PrefixedIdentifier identifier = expression as PrefixedIdentifier;
850 expression = new MethodInvocation.full(identifier.prefix, identifier.p eriod, identifier.identifier, argumentList);
851 } else if (expression is PropertyAccess) {
852 PropertyAccess access = expression as PropertyAccess;
853 expression = new MethodInvocation.full(access.target, access.operator, access.propertyName, argumentList);
854 } else {
855 expression = new FunctionExpressionInvocation.full(expression, argumen tList);
856 }
857 if (!primaryAllowed) {
858 isOptional = false;
859 }
860 }
861 Expression selectorExpression = parseAssignableSelector(expression, isOpti onal || (expression is PrefixedIdentifier));
862 if (identical(selectorExpression, expression)) {
863 if (!isOptional && (expression is PrefixedIdentifier)) {
864 PrefixedIdentifier identifier = expression as PrefixedIdentifier;
865 expression = new PropertyAccess.full(identifier.prefix, identifier.per iod, identifier.identifier);
866 }
867 return expression;
868 }
869 expression = selectorExpression;
870 isOptional = true;
871 }
872 }
873 /**
874 * Parse an assignable selector.
875 * <pre>
876 * assignableSelector ::=
877 * '[' expression ']'
878 * | '.' identifier
879 * </pre>
880 * @param prefix the expression preceding the selector
881 * @param optional {@code true} if the selector is optional
882 * @return the assignable selector that was parsed
883 */
884 Expression parseAssignableSelector(Expression prefix, bool optional) {
885 if (matches5(TokenType.OPEN_SQUARE_BRACKET)) {
886 Token leftBracket = andAdvance;
887 Expression index = parseExpression2();
888 Token rightBracket = expect2(TokenType.CLOSE_SQUARE_BRACKET);
889 return new IndexExpression.forTarget_full(prefix, leftBracket, index, righ tBracket);
890 } else if (matches5(TokenType.PERIOD)) {
891 Token period = andAdvance;
892 return new PropertyAccess.full(prefix, period, parseSimpleIdentifier());
893 } else {
894 if (!optional) {
895 reportError4(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, []);
896 }
897 return prefix;
898 }
899 }
900 /**
901 * Parse a bitwise and expression.
902 * <pre>
903 * bitwiseAndExpression ::=
904 * equalityExpression ('&' equalityExpression)
905 * | 'super' ('&' equalityExpression)+
906 * </pre>
907 * @return the bitwise and expression that was parsed
908 */
909 Expression parseBitwiseAndExpression() {
910 Expression expression;
911 if (matches(Keyword.SUPER) && matches4(peek(), TokenType.AMPERSAND)) {
912 expression = new SuperExpression.full(andAdvance);
913 } else {
914 expression = parseEqualityExpression();
915 }
916 while (matches5(TokenType.AMPERSAND)) {
917 Token operator = andAdvance;
918 expression = new BinaryExpression.full(expression, operator, parseEquality Expression());
919 }
920 return expression;
921 }
922 /**
923 * Parse a bitwise or expression.
924 * <pre>
925 * bitwiseOrExpression ::=
926 * bitwiseXorExpression ('|' bitwiseXorExpression)
927 * | 'super' ('|' bitwiseXorExpression)+
928 * </pre>
929 * @return the bitwise or expression that was parsed
930 */
931 Expression parseBitwiseOrExpression() {
932 Expression expression;
933 if (matches(Keyword.SUPER) && matches4(peek(), TokenType.BAR)) {
934 expression = new SuperExpression.full(andAdvance);
935 } else {
936 expression = parseBitwiseXorExpression();
937 }
938 while (matches5(TokenType.BAR)) {
939 Token operator = andAdvance;
940 expression = new BinaryExpression.full(expression, operator, parseBitwiseX orExpression());
941 }
942 return expression;
943 }
944 /**
945 * Parse a bitwise exclusive-or expression.
946 * <pre>
947 * bitwiseXorExpression ::=
948 * bitwiseAndExpression ('^' bitwiseAndExpression)
949 * | 'super' ('^' bitwiseAndExpression)+
950 * </pre>
951 * @return the bitwise exclusive-or expression that was parsed
952 */
953 Expression parseBitwiseXorExpression() {
954 Expression expression;
955 if (matches(Keyword.SUPER) && matches4(peek(), TokenType.CARET)) {
956 expression = new SuperExpression.full(andAdvance);
957 } else {
958 expression = parseBitwiseAndExpression();
959 }
960 while (matches5(TokenType.CARET)) {
961 Token operator = andAdvance;
962 expression = new BinaryExpression.full(expression, operator, parseBitwiseA ndExpression());
963 }
964 return expression;
965 }
966 /**
967 * Parse a block.
968 * <pre>
969 * block ::=
970 * '{' statements '}'
971 * </pre>
972 * @return the block that was parsed
973 */
974 Block parseBlock() {
975 Token leftBracket = expect2(TokenType.OPEN_CURLY_BRACKET);
976 List<Statement> statements = new List<Statement>();
977 Token statementStart = _currentToken;
978 while (!matches5(TokenType.EOF) && !matches5(TokenType.CLOSE_CURLY_BRACKET)) {
979 Statement statement = parseStatement2();
980 if (statement != null) {
981 statements.add(statement);
982 }
983 if (identical(_currentToken, statementStart)) {
984 reportError5(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_currentT oken.lexeme]);
985 advance();
986 }
987 statementStart = _currentToken;
988 }
989 Token rightBracket = expect2(TokenType.CLOSE_CURLY_BRACKET);
990 return new Block.full(leftBracket, statements, rightBracket);
991 }
992 /**
993 * Parse a break statement.
994 * <pre>
995 * breakStatement ::=
996 * 'break' identifier? ';'
997 * </pre>
998 * @return the break statement that was parsed
999 */
1000 Statement parseBreakStatement() {
1001 Token breakKeyword = expect(Keyword.BREAK);
1002 SimpleIdentifier label = null;
1003 if (matchesIdentifier()) {
1004 label = parseSimpleIdentifier();
1005 }
1006 if (!_inLoop && !_inSwitch && label == null) {
1007 reportError5(ParserErrorCode.BREAK_OUTSIDE_OF_LOOP, breakKeyword, []);
1008 }
1009 Token semicolon = expect2(TokenType.SEMICOLON);
1010 return new BreakStatement.full(breakKeyword, label, semicolon);
1011 }
1012 /**
1013 * Parse a cascade section.
1014 * <pre>
1015 * cascadeSection ::=
1016 * '..' (cascadeSelector arguments*) (assignableSelector arguments*)* cascadeA ssignment?
1017 * cascadeSelector ::=
1018 * '[' expression ']'
1019 * | identifier
1020 * cascadeAssignment ::=
1021 * assignmentOperator expressionWithoutCascade
1022 * </pre>
1023 * @return the expression representing the cascaded method invocation
1024 */
1025 Expression parseCascadeSection() {
1026 Token period = expect2(TokenType.PERIOD_PERIOD);
1027 Expression expression = null;
1028 SimpleIdentifier functionName = null;
1029 if (matchesIdentifier()) {
1030 functionName = parseSimpleIdentifier();
1031 } else if (identical(_currentToken.type, TokenType.OPEN_SQUARE_BRACKET)) {
1032 Token leftBracket = andAdvance;
1033 Expression index = parseExpression2();
1034 Token rightBracket = expect2(TokenType.CLOSE_SQUARE_BRACKET);
1035 expression = new IndexExpression.forCascade_full(period, leftBracket, inde x, rightBracket);
1036 period = null;
1037 } else {
1038 reportError5(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_currentTok en.lexeme]);
1039 return expression;
1040 }
1041 if (identical(_currentToken.type, TokenType.OPEN_PAREN)) {
1042 while (identical(_currentToken.type, TokenType.OPEN_PAREN)) {
1043 if (functionName != null) {
1044 expression = new MethodInvocation.full(expression, period, functionNam e, parseArgumentList());
1045 period = null;
1046 functionName = null;
1047 } else if (expression == null) {
1048 return null;
1049 } else {
1050 expression = new FunctionExpressionInvocation.full(expression, parseAr gumentList());
1051 }
1052 }
1053 } else if (functionName != null) {
1054 expression = new PropertyAccess.full(expression, period, functionName);
1055 period = null;
1056 }
1057 bool progress = true;
1058 while (progress) {
1059 progress = false;
1060 Expression selector = parseAssignableSelector(expression, true);
1061 if (selector != expression) {
1062 expression = selector;
1063 progress = true;
1064 while (identical(_currentToken.type, TokenType.OPEN_PAREN)) {
1065 expression = new FunctionExpressionInvocation.full(expression, parseAr gumentList());
1066 }
1067 }
1068 }
1069 if (_currentToken.type.isAssignmentOperator()) {
1070 Token operator = andAdvance;
1071 ensureAssignable(expression);
1072 expression = new AssignmentExpression.full(expression, operator, parseExpr essionWithoutCascade());
1073 }
1074 return expression;
1075 }
1076 /**
1077 * Parse a class declaration.
1078 * <pre>
1079 * classDeclaration ::=
1080 * metadata 'abstract'? 'class' name typeParameterList? (extendsClause withCla use?)? implementsClause? '{' classMembers '}'
1081 * </pre>
1082 * @param commentAndMetadata the metadata to be associated with the member
1083 * @param abstractKeyword the token for the keyword 'abstract', or {@code null } if the keyword was
1084 * not given
1085 * @return the class declaration that was parsed
1086 */
1087 ClassDeclaration parseClassDeclaration(CommentAndMetadata commentAndMetadata, Token abstractKeyword) {
1088 Token keyword = expect(Keyword.CLASS);
1089 SimpleIdentifier name = parseSimpleIdentifier();
1090 String className = name.name;
1091 TypeParameterList typeParameters = null;
1092 if (matches5(TokenType.LT)) {
1093 typeParameters = parseTypeParameterList();
1094 }
1095 ExtendsClause extendsClause = null;
1096 WithClause withClause = null;
1097 ImplementsClause implementsClause = null;
1098 bool foundClause = true;
1099 while (foundClause) {
1100 if (matches(Keyword.EXTENDS)) {
1101 if (extendsClause == null) {
1102 extendsClause = parseExtendsClause();
1103 if (withClause != null) {
1104 reportError5(ParserErrorCode.WITH_BEFORE_EXTENDS, withClause.withKey word, []);
1105 } else if (implementsClause != null) {
1106 reportError5(ParserErrorCode.IMPLEMENTS_BEFORE_EXTENDS, implementsCl ause.keyword, []);
1107 }
1108 } else {
1109 reportError5(ParserErrorCode.MULTIPLE_EXTENDS_CLAUSES, extendsClause.k eyword, []);
1110 parseExtendsClause();
1111 }
1112 } else if (matches(Keyword.WITH)) {
1113 if (withClause == null) {
1114 withClause = parseWithClause();
1115 if (implementsClause != null) {
1116 reportError5(ParserErrorCode.IMPLEMENTS_BEFORE_WITH, implementsClaus e.keyword, []);
1117 }
1118 } else {
1119 reportError5(ParserErrorCode.MULTIPLE_WITH_CLAUSES, withClause.withKey word, []);
1120 parseWithClause();
1121 }
1122 } else if (matches(Keyword.IMPLEMENTS)) {
1123 if (implementsClause == null) {
1124 implementsClause = parseImplementsClause();
1125 } else {
1126 reportError5(ParserErrorCode.MULTIPLE_IMPLEMENTS_CLAUSES, implementsCl ause.keyword, []);
1127 parseImplementsClause();
1128 }
1129 } else {
1130 foundClause = false;
1131 }
1132 }
1133 if (withClause != null && extendsClause == null) {
1134 reportError5(ParserErrorCode.WITH_WITHOUT_EXTENDS, withClause.withKeyword, []);
1135 }
1136 Token leftBracket = null;
1137 List<ClassMember> members = null;
1138 Token rightBracket = null;
1139 if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
1140 leftBracket = expect2(TokenType.OPEN_CURLY_BRACKET);
1141 members = parseClassMembers(className, ((leftBracket as BeginToken)).endTo ken != null);
1142 rightBracket = expect2(TokenType.CLOSE_CURLY_BRACKET);
1143 } else {
1144 leftBracket = createSyntheticToken(TokenType.OPEN_CURLY_BRACKET);
1145 rightBracket = createSyntheticToken(TokenType.CLOSE_CURLY_BRACKET);
1146 reportError4(ParserErrorCode.MISSING_CLASS_BODY, []);
1147 }
1148 return new ClassDeclaration.full(commentAndMetadata.comment, commentAndMetad ata.metadata, abstractKeyword, keyword, name, typeParameters, extendsClause, wit hClause, implementsClause, leftBracket, members, rightBracket);
1149 }
1150 /**
1151 * Parse a class member.
1152 * <pre>
1153 * classMemberDefinition ::=
1154 * declaration ';'
1155 * | methodSignature functionBody
1156 * </pre>
1157 * @param className the name of the class containing the member being parsed
1158 * @return the class member that was parsed
1159 */
1160 ClassMember parseClassMember(String className) {
1161 CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
1162 Modifiers modifiers = parseModifiers();
1163 if (matches(Keyword.VOID)) {
1164 TypeName returnType = parseReturnType();
1165 if (matches(Keyword.GET) && matchesIdentifier2(peek())) {
1166 validateModifiersForGetterOrSetterOrMethod(modifiers);
1167 return parseGetter(commentAndMetadata, modifiers.externalKeyword, modifi ers.staticKeyword, returnType);
1168 } else if (matches(Keyword.SET) && matchesIdentifier2(peek())) {
1169 validateModifiersForGetterOrSetterOrMethod(modifiers);
1170 return parseSetter(commentAndMetadata, modifiers.externalKeyword, modifi ers.staticKeyword, returnType);
1171 } else if (matches(Keyword.OPERATOR) && peek().isOperator()) {
1172 validateModifiersForOperator(modifiers);
1173 return parseOperator(commentAndMetadata, modifiers.externalKeyword, retu rnType);
1174 } else if (matchesIdentifier() && matchesAny(peek(), [TokenType.OPEN_PAREN , TokenType.OPEN_CURLY_BRACKET, TokenType.FUNCTION])) {
1175 validateModifiersForGetterOrSetterOrMethod(modifiers);
1176 return parseMethodDeclaration(commentAndMetadata, modifiers.externalKeyw ord, modifiers.staticKeyword, returnType);
1177 } else {
1178 if (matchesIdentifier()) {
1179 if (matchesAny(peek(), [TokenType.EQ, TokenType.COMMA, TokenType.SEMIC OLON])) {
1180 reportError(ParserErrorCode.VOID_VARIABLE, returnType, []);
1181 return parseInitializedIdentifierList(commentAndMetadata, modifiers. staticKeyword, validateModifiersForField(modifiers), returnType);
1182 }
1183 }
1184 return null;
1185 }
1186 } else if (matches(Keyword.GET) && matchesIdentifier2(peek())) {
1187 validateModifiersForGetterOrSetterOrMethod(modifiers);
1188 return parseGetter(commentAndMetadata, modifiers.externalKeyword, modifier s.staticKeyword, null);
1189 } else if (matches(Keyword.SET) && matchesIdentifier2(peek())) {
1190 validateModifiersForGetterOrSetterOrMethod(modifiers);
1191 return parseSetter(commentAndMetadata, modifiers.externalKeyword, modifier s.staticKeyword, null);
1192 } else if (matches(Keyword.OPERATOR) && peek().isOperator() && matches4(peek 2(2), TokenType.OPEN_PAREN)) {
1193 validateModifiersForOperator(modifiers);
1194 return parseOperator(commentAndMetadata, modifiers.externalKeyword, null);
1195 } else if (!matchesIdentifier()) {
1196 return null;
1197 } else if (matches4(peek(), TokenType.PERIOD) && matchesIdentifier2(peek2(2) ) && matches4(peek2(3), TokenType.OPEN_PAREN)) {
1198 return parseConstructor(commentAndMetadata, modifiers.externalKeyword, val idateModifiersForConstructor(modifiers), modifiers.factoryKeyword, parseSimpleId entifier(), andAdvance, parseSimpleIdentifier(), parseFormalParameterList());
1199 } else if (matches4(peek(), TokenType.OPEN_PAREN)) {
1200 SimpleIdentifier methodName = parseSimpleIdentifier();
1201 FormalParameterList parameters = parseFormalParameterList();
1202 if (matches5(TokenType.COLON) || modifiers.factoryKeyword != null || metho dName.name == className) {
1203 return parseConstructor(commentAndMetadata, modifiers.externalKeyword, v alidateModifiersForConstructor(modifiers), modifiers.factoryKeyword, methodName, null, null, parameters);
1204 }
1205 validateModifiersForGetterOrSetterOrMethod(modifiers);
1206 validateFormalParameterList(parameters);
1207 return parseMethodDeclaration2(commentAndMetadata, modifiers.externalKeywo rd, modifiers.staticKeyword, null, methodName, parameters);
1208 } else if (matchesAny(peek(), [TokenType.EQ, TokenType.COMMA, TokenType.SEMI COLON])) {
1209 return parseInitializedIdentifierList(commentAndMetadata, modifiers.static Keyword, validateModifiersForField(modifiers), null);
1210 }
1211 TypeName type = parseTypeName();
1212 if (matches(Keyword.GET) && matchesIdentifier2(peek())) {
1213 validateModifiersForGetterOrSetterOrMethod(modifiers);
1214 return parseGetter(commentAndMetadata, modifiers.externalKeyword, modifier s.staticKeyword, type);
1215 } else if (matches(Keyword.SET) && matchesIdentifier2(peek())) {
1216 validateModifiersForGetterOrSetterOrMethod(modifiers);
1217 return parseSetter(commentAndMetadata, modifiers.externalKeyword, modifier s.staticKeyword, type);
1218 } else if (matches(Keyword.OPERATOR) && peek().isOperator() && matches4(peek 2(2), TokenType.OPEN_PAREN)) {
1219 validateModifiersForOperator(modifiers);
1220 return parseOperator(commentAndMetadata, modifiers.externalKeyword, type);
1221 } else if (!matchesIdentifier()) {
1222 } else if (matches4(peek(), TokenType.OPEN_PAREN)) {
1223 validateModifiersForGetterOrSetterOrMethod(modifiers);
1224 return parseMethodDeclaration(commentAndMetadata, modifiers.externalKeywor d, modifiers.staticKeyword, type);
1225 }
1226 return parseInitializedIdentifierList(commentAndMetadata, modifiers.staticKe yword, validateModifiersForField(modifiers), type);
1227 }
1228 /**
1229 * Parse a list of class members.
1230 * <pre>
1231 * classMembers ::=
1232 * (metadata memberDefinition)
1233 * </pre>
1234 * @param className the name of the class whose members are being parsed
1235 * @param balancedBrackets {@code true} if the opening and closing brackets fo r the class are
1236 * balanced
1237 * @return the list of class members that were parsed
1238 */
1239 List<ClassMember> parseClassMembers(String className, bool balancedBrackets) {
1240 List<ClassMember> members = new List<ClassMember>();
1241 Token memberStart = _currentToken;
1242 while (!matches5(TokenType.EOF) && !matches5(TokenType.CLOSE_CURLY_BRACKET) && (balancedBrackets || (!matches(Keyword.CLASS) && !matches(Keyword.TYPEDEF)))) {
1243 if (matches5(TokenType.SEMICOLON)) {
1244 reportError5(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_currentT oken.lexeme]);
1245 advance();
1246 } else {
1247 ClassMember member = parseClassMember(className);
1248 if (member != null) {
1249 members.add(member);
1250 }
1251 }
1252 if (identical(_currentToken, memberStart)) {
1253 reportError5(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_currentT oken.lexeme]);
1254 advance();
1255 }
1256 memberStart = _currentToken;
1257 }
1258 return members;
1259 }
1260 /**
1261 * Parse a class type alias.
1262 * <pre>
1263 * classTypeAlias ::=
1264 * identifier typeParameters? '=' 'abstract'? mixinApplication
1265 * mixinApplication ::=
1266 * type withClause implementsClause? ';'
1267 * </pre>
1268 * @param commentAndMetadata the metadata to be associated with the member
1269 * @param keyword the token representing the 'typedef' keyword
1270 * @return the class type alias that was parsed
1271 */
1272 ClassTypeAlias parseClassTypeAlias(CommentAndMetadata commentAndMetadata, Toke n keyword) {
1273 SimpleIdentifier name = parseSimpleIdentifier();
1274 TypeParameterList typeParameters = null;
1275 if (matches5(TokenType.LT)) {
1276 typeParameters = parseTypeParameterList();
1277 }
1278 Token equals = expect2(TokenType.EQ);
1279 Token abstractKeyword = null;
1280 if (matches(Keyword.ABSTRACT)) {
1281 abstractKeyword = andAdvance;
1282 }
1283 TypeName superclass = parseTypeName();
1284 WithClause withClause = parseWithClause();
1285 ImplementsClause implementsClause = null;
1286 if (matches(Keyword.IMPLEMENTS)) {
1287 implementsClause = parseImplementsClause();
1288 }
1289 Token semicolon = expect2(TokenType.SEMICOLON);
1290 return new ClassTypeAlias.full(commentAndMetadata.comment, commentAndMetadat a.metadata, keyword, name, typeParameters, equals, abstractKeyword, superclass, withClause, implementsClause, semicolon);
1291 }
1292 /**
1293 * Parse a list of combinators in a directive.
1294 * <pre>
1295 * combinator ::=
1296 * 'show' identifier (',' identifier)
1297 * | 'hide' identifier (',' identifier)
1298 * </pre>
1299 * @return the combinators that were parsed
1300 */
1301 List<Combinator> parseCombinators() {
1302 List<Combinator> combinators = new List<Combinator>();
1303 while (matches2(_SHOW) || matches2(_HIDE)) {
1304 Token keyword = expect2(TokenType.IDENTIFIER);
1305 if (keyword.lexeme == _SHOW) {
1306 List<SimpleIdentifier> shownNames = parseIdentifierList();
1307 combinators.add(new ShowCombinator.full(keyword, shownNames));
1308 } else {
1309 List<SimpleIdentifier> hiddenNames = parseIdentifierList();
1310 combinators.add(new HideCombinator.full(keyword, hiddenNames));
1311 }
1312 }
1313 return combinators;
1314 }
1315 /**
1316 * Parse the documentation comment and metadata preceeding a declaration. This method allows any
1317 * number of documentation comments to occur before, after or between the meta data, but only
1318 * returns the last (right-most) documentation comment that is found.
1319 * <pre>
1320 * metadata ::=
1321 * annotation
1322 * </pre>
1323 * @return the documentation comment and metadata that were parsed
1324 */
1325 CommentAndMetadata parseCommentAndMetadata() {
1326 Comment comment = parseDocumentationComment();
1327 List<Annotation> metadata = new List<Annotation>();
1328 while (matches5(TokenType.AT)) {
1329 metadata.add(parseAnnotation());
1330 Comment optionalComment = parseDocumentationComment();
1331 if (optionalComment != null) {
1332 comment = optionalComment;
1333 }
1334 }
1335 return new CommentAndMetadata(comment, metadata);
1336 }
1337 /**
1338 * Parse a comment reference from the source between square brackets.
1339 * <pre>
1340 * commentReference ::=
1341 * 'new'? prefixedIdentifier
1342 * </pre>
1343 * @param referenceSource the source occurring between the square brackets wit hin a documentation
1344 * comment
1345 * @param sourceOffset the offset of the first character of the reference sour ce
1346 * @return the comment reference that was parsed
1347 */
1348 CommentReference parseCommentReference(String referenceSource, int sourceOffse t) {
1349 if (referenceSource.length == 0) {
1350 return null;
1351 }
1352 try {
1353 List<bool> errorFound = [false];
1354 AnalysisErrorListener listener = new AnalysisErrorListener_7(errorFound);
1355 StringScanner scanner = new StringScanner(null, referenceSource, listener) ;
1356 scanner.setSourceStart(1, 1, sourceOffset);
1357 Token firstToken = scanner.tokenize();
1358 if (!errorFound[0]) {
1359 Token newKeyword = null;
1360 if (matches3(firstToken, Keyword.NEW)) {
1361 newKeyword = firstToken;
1362 firstToken = firstToken.next;
1363 }
1364 if (matchesIdentifier2(firstToken)) {
1365 Token secondToken = firstToken.next;
1366 Token thirdToken = secondToken.next;
1367 Token nextToken;
1368 Identifier identifier;
1369 if (matches4(secondToken, TokenType.PERIOD) && matchesIdentifier2(thir dToken)) {
1370 identifier = new PrefixedIdentifier.full(new SimpleIdentifier.full(f irstToken), secondToken, new SimpleIdentifier.full(thirdToken));
1371 nextToken = thirdToken.next;
1372 } else {
1373 identifier = new SimpleIdentifier.full(firstToken);
1374 nextToken = firstToken.next;
1375 }
1376 if (nextToken.type != TokenType.EOF) {
1377 }
1378 return new CommentReference.full(newKeyword, identifier);
1379 } else if (matches3(firstToken, Keyword.THIS) || matches3(firstToken, Ke yword.NULL) || matches3(firstToken, Keyword.TRUE) || matches3(firstToken, Keywor d.FALSE)) {
1380 return null;
1381 } else if (matches4(firstToken, TokenType.STRING)) {
1382 } else {
1383 }
1384 }
1385 } on JavaException catch (exception) {
1386 }
1387 return null;
1388 }
1389 /**
1390 * Parse all of the comment references occurring in the given array of documen tation comments.
1391 * <pre>
1392 * commentReference ::=
1393 * '[' 'new'? qualified ']' libraryReference?
1394 * libraryReference ::=
1395 * '(' stringLiteral ')'
1396 * </pre>
1397 * @param tokens the comment tokens representing the documentation comments to be parsed
1398 * @return the comment references that were parsed
1399 */
1400 List<CommentReference> parseCommentReferences(List<Token> tokens) {
1401 List<CommentReference> references = new List<CommentReference>();
1402 for (Token token in tokens) {
1403 String comment = token.lexeme;
1404 int leftIndex = comment.indexOf('[');
1405 while (leftIndex >= 0) {
1406 int rightIndex = comment.indexOf(']', leftIndex);
1407 if (rightIndex >= 0) {
1408 int firstChar = comment.codeUnitAt(leftIndex + 1);
1409 if (firstChar != 0x27 && firstChar != 0x22 && firstChar != 0x3A) {
1410 CommentReference reference = parseCommentReference(comment.substring (leftIndex + 1, rightIndex), token.offset + leftIndex + 1);
1411 if (reference != null) {
1412 references.add(reference);
1413 }
1414 }
1415 } else {
1416 rightIndex = leftIndex + 1;
1417 }
1418 leftIndex = comment.indexOf('[', rightIndex);
1419 }
1420 }
1421 return references;
1422 }
1423 /**
1424 * Parse a compilation unit.
1425 * <p>
1426 * Specified:
1427 * <pre>
1428 * compilationUnit ::=
1429 * scriptTag? directive* topLevelDeclaration
1430 * </pre>
1431 * Actual:
1432 * <pre>
1433 * compilationUnit ::=
1434 * scriptTag? topLevelElement
1435 * topLevelElement ::=
1436 * directive
1437 * | topLevelDeclaration
1438 * </pre>
1439 * @return the compilation unit that was parsed
1440 */
1441 CompilationUnit parseCompilationUnit2() {
1442 Token firstToken = _currentToken;
1443 ScriptTag scriptTag = null;
1444 if (matches5(TokenType.SCRIPT_TAG)) {
1445 scriptTag = new ScriptTag.full(andAdvance);
1446 }
1447 bool libraryDirectiveFound = false;
1448 bool partOfDirectiveFound = false;
1449 bool partDirectiveFound = false;
1450 bool directiveFoundAfterDeclaration = false;
1451 List<Directive> directives = new List<Directive>();
1452 List<CompilationUnitMember> declarations = new List<CompilationUnitMember>() ;
1453 Token memberStart = _currentToken;
1454 while (!matches5(TokenType.EOF)) {
1455 CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
1456 if ((matches(Keyword.IMPORT) || matches(Keyword.EXPORT) || matches(Keyword .LIBRARY) || matches(Keyword.PART)) && !matches4(peek(), TokenType.PERIOD) && !m atches4(peek(), TokenType.LT)) {
1457 Directive directive = parseDirective(commentAndMetadata);
1458 if (declarations.length > 0 && !directiveFoundAfterDeclaration) {
1459 reportError4(ParserErrorCode.DIRECTIVE_AFTER_DECLARATION, []);
1460 directiveFoundAfterDeclaration = true;
1461 }
1462 if (directive is LibraryDirective) {
1463 if (libraryDirectiveFound) {
1464 reportError4(ParserErrorCode.MULTIPLE_LIBRARY_DIRECTIVES, []);
1465 } else {
1466 if (directives.length > 0) {
1467 reportError4(ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST, []);
1468 }
1469 libraryDirectiveFound = true;
1470 }
1471 } else if (directive is PartDirective) {
1472 partDirectiveFound = true;
1473 } else if (partDirectiveFound) {
1474 if (directive is ExportDirective) {
1475 reportError4(ParserErrorCode.EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE, []);
1476 } else if (directive is ImportDirective) {
1477 reportError4(ParserErrorCode.IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE, []);
1478 }
1479 }
1480 if (directive is PartOfDirective) {
1481 if (partOfDirectiveFound) {
1482 reportError4(ParserErrorCode.MULTIPLE_PART_OF_DIRECTIVES, []);
1483 } else {
1484 for (Directive preceedingDirective in directives) {
1485 reportError5(ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART, precee dingDirective.keyword, []);
1486 }
1487 partOfDirectiveFound = true;
1488 }
1489 } else {
1490 if (partOfDirectiveFound) {
1491 reportError5(ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART, directiv e.keyword, []);
1492 }
1493 }
1494 directives.add(directive);
1495 } else if (matches5(TokenType.SEMICOLON)) {
1496 reportError5(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_currentT oken.lexeme]);
1497 advance();
1498 } else {
1499 CompilationUnitMember member = parseCompilationUnitMember(commentAndMeta data);
1500 if (member != null) {
1501 declarations.add(member);
1502 }
1503 }
1504 if (identical(_currentToken, memberStart)) {
1505 reportError5(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_currentT oken.lexeme]);
1506 advance();
1507 }
1508 memberStart = _currentToken;
1509 }
1510 return new CompilationUnit.full(firstToken, scriptTag, directives, declarati ons, _currentToken);
1511 }
1512 /**
1513 * Parse a compilation unit member.
1514 * <pre>
1515 * compilationUnitMember ::=
1516 * classDefinition
1517 * | functionTypeAlias
1518 * | external functionSignature
1519 * | external getterSignature
1520 * | external setterSignature
1521 * | functionSignature functionBody
1522 * | returnType? getOrSet identifier formalParameterList functionBody
1523 * | (final | const) type? staticFinalDeclarationList ';'
1524 * | variableDeclaration ';'
1525 * </pre>
1526 * @param commentAndMetadata the metadata to be associated with the member
1527 * @return the compilation unit member that was parsed
1528 */
1529 CompilationUnitMember parseCompilationUnitMember(CommentAndMetadata commentAnd Metadata) {
1530 Modifiers modifiers = parseModifiers();
1531 if (matches(Keyword.CLASS)) {
1532 return parseClassDeclaration(commentAndMetadata, validateModifiersForClass (modifiers));
1533 } else if (matches(Keyword.TYPEDEF) && !matches4(peek(), TokenType.PERIOD) & & !matches4(peek(), TokenType.LT)) {
1534 validateModifiersForTypedef(modifiers);
1535 return parseTypeAlias(commentAndMetadata);
1536 }
1537 if (matches(Keyword.VOID)) {
1538 TypeName returnType = parseReturnType();
1539 if ((matches(Keyword.GET) || matches(Keyword.SET)) && matchesIdentifier2(p eek())) {
1540 validateModifiersForTopLevelFunction(modifiers);
1541 return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKe yword, null);
1542 } else if (matches(Keyword.OPERATOR) && peek().isOperator()) {
1543 return null;
1544 } else if (matchesIdentifier() && matchesAny(peek(), [TokenType.OPEN_PAREN , TokenType.OPEN_CURLY_BRACKET, TokenType.FUNCTION])) {
1545 validateModifiersForTopLevelFunction(modifiers);
1546 return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKe yword, null);
1547 } else {
1548 if (matchesIdentifier()) {
1549 if (matchesAny(peek(), [TokenType.EQ, TokenType.COMMA, TokenType.SEMIC OLON])) {
1550 reportError(ParserErrorCode.VOID_VARIABLE, returnType, []);
1551 return new TopLevelVariableDeclaration.full(commentAndMetadata.comme nt, commentAndMetadata.metadata, parseVariableDeclarationList2(validateModifiers ForTopLevelVariable(modifiers), null), expect2(TokenType.SEMICOLON));
1552 }
1553 }
1554 return null;
1555 }
1556 } else if ((matches(Keyword.GET) || matches(Keyword.SET)) && matchesIdentifi er2(peek())) {
1557 validateModifiersForTopLevelFunction(modifiers);
1558 return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKeyw ord, null);
1559 } else if (matches(Keyword.OPERATOR) && peek().isOperator() && matches4(peek 2(2), TokenType.OPEN_PAREN)) {
1560 return null;
1561 } else if (!matchesIdentifier()) {
1562 return null;
1563 } else if (matches4(peek(), TokenType.OPEN_PAREN)) {
1564 validateModifiersForTopLevelFunction(modifiers);
1565 return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKeyw ord, null);
1566 } else if (matchesAny(peek(), [TokenType.EQ, TokenType.COMMA, TokenType.SEMI COLON])) {
1567 return new TopLevelVariableDeclaration.full(commentAndMetadata.comment, co mmentAndMetadata.metadata, parseVariableDeclarationList2(validateModifiersForTop LevelVariable(modifiers), null), expect2(TokenType.SEMICOLON));
1568 }
1569 TypeName returnType = parseReturnType();
1570 if (matches(Keyword.GET) || matches(Keyword.SET)) {
1571 validateModifiersForTopLevelFunction(modifiers);
1572 return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKeyw ord, returnType);
1573 } else if (!matchesIdentifier()) {
1574 return null;
1575 }
1576 if (matchesAny(peek(), [TokenType.OPEN_PAREN, TokenType.FUNCTION, TokenType. OPEN_CURLY_BRACKET])) {
1577 validateModifiersForTopLevelFunction(modifiers);
1578 return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKeyw ord, returnType);
1579 }
1580 return new TopLevelVariableDeclaration.full(commentAndMetadata.comment, comm entAndMetadata.metadata, parseVariableDeclarationList2(validateModifiersForTopLe velVariable(modifiers), returnType), expect2(TokenType.SEMICOLON));
1581 }
1582 /**
1583 * Parse a conditional expression.
1584 * <pre>
1585 * conditionalExpression ::=
1586 * logicalOrExpression ('?' expressionWithoutCascade ':' expressionWithoutCasc ade)?
1587 * </pre>
1588 * @return the conditional expression that was parsed
1589 */
1590 Expression parseConditionalExpression() {
1591 Expression condition = parseLogicalOrExpression();
1592 if (!matches5(TokenType.QUESTION)) {
1593 return condition;
1594 }
1595 Token question = andAdvance;
1596 Expression thenExpression = parseExpressionWithoutCascade();
1597 Token colon = expect2(TokenType.COLON);
1598 Expression elseExpression = parseExpressionWithoutCascade();
1599 return new ConditionalExpression.full(condition, question, thenExpression, c olon, elseExpression);
1600 }
1601 /**
1602 * Parse a const expression.
1603 * <pre>
1604 * constExpression ::=
1605 * instanceCreationExpression
1606 * | listLiteral
1607 * | mapLiteral
1608 * </pre>
1609 * @return the const expression that was parsed
1610 */
1611 Expression parseConstExpression() {
1612 Token keyword = expect(Keyword.CONST);
1613 if (matches5(TokenType.OPEN_SQUARE_BRACKET) || matches5(TokenType.INDEX)) {
1614 return parseListLiteral(keyword, null);
1615 } else if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
1616 return parseMapLiteral(keyword, null);
1617 } else if (matches5(TokenType.LT)) {
1618 return parseListOrMapLiteral(keyword);
1619 }
1620 return parseInstanceCreationExpression(keyword);
1621 }
1622 ConstructorDeclaration parseConstructor(CommentAndMetadata commentAndMetadata, Token externalKeyword, Token constKeyword, Token factoryKeyword, SimpleIdentifi er returnType, Token period, SimpleIdentifier name, FormalParameterList paramete rs) {
1623 bool bodyAllowed = externalKeyword == null;
1624 Token separator = null;
1625 List<ConstructorInitializer> initializers = null;
1626 if (matches5(TokenType.COLON)) {
1627 separator = andAdvance;
1628 initializers = new List<ConstructorInitializer>();
1629 do {
1630 if (matches(Keyword.THIS)) {
1631 if (matches4(peek(), TokenType.OPEN_PAREN)) {
1632 bodyAllowed = false;
1633 initializers.add(parseRedirectingConstructorInvocation());
1634 } else if (matches4(peek(), TokenType.PERIOD) && matches4(peek2(3), To kenType.OPEN_PAREN)) {
1635 bodyAllowed = false;
1636 initializers.add(parseRedirectingConstructorInvocation());
1637 } else {
1638 initializers.add(parseConstructorFieldInitializer());
1639 }
1640 } else if (matches(Keyword.SUPER)) {
1641 initializers.add(parseSuperConstructorInvocation());
1642 } else {
1643 initializers.add(parseConstructorFieldInitializer());
1644 }
1645 } while (optional(TokenType.COMMA));
1646 }
1647 ConstructorName redirectedConstructor = null;
1648 FunctionBody body;
1649 if (matches5(TokenType.EQ)) {
1650 separator = andAdvance;
1651 redirectedConstructor = parseConstructorName();
1652 body = new EmptyFunctionBody.full(expect2(TokenType.SEMICOLON));
1653 } else {
1654 body = parseFunctionBody(true, false);
1655 if (!bodyAllowed && body is! EmptyFunctionBody) {
1656 reportError4(ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_BODY, []);
1657 }
1658 }
1659 return new ConstructorDeclaration.full(commentAndMetadata.comment, commentAn dMetadata.metadata, externalKeyword, constKeyword, factoryKeyword, returnType, p eriod, name, parameters, separator, initializers, redirectedConstructor, body);
1660 }
1661 /**
1662 * Parse a field initializer within a constructor.
1663 * <pre>
1664 * fieldInitializer:
1665 * ('this' '.')? identifier '=' conditionalExpression cascadeSection
1666 * </pre>
1667 * @return the field initializer that was parsed
1668 */
1669 ConstructorFieldInitializer parseConstructorFieldInitializer() {
1670 Token keyword = null;
1671 Token period = null;
1672 if (matches(Keyword.THIS)) {
1673 keyword = andAdvance;
1674 period = expect2(TokenType.PERIOD);
1675 }
1676 SimpleIdentifier fieldName = parseSimpleIdentifier();
1677 Token equals = expect2(TokenType.EQ);
1678 Expression expression = parseConditionalExpression();
1679 TokenType tokenType = _currentToken.type;
1680 if (identical(tokenType, TokenType.PERIOD_PERIOD)) {
1681 List<Expression> cascadeSections = new List<Expression>();
1682 while (identical(tokenType, TokenType.PERIOD_PERIOD)) {
1683 Expression section = parseCascadeSection();
1684 if (section != null) {
1685 cascadeSections.add(section);
1686 }
1687 tokenType = _currentToken.type;
1688 }
1689 expression = new CascadeExpression.full(expression, cascadeSections);
1690 }
1691 return new ConstructorFieldInitializer.full(keyword, period, fieldName, equa ls, expression);
1692 }
1693 /**
1694 * Parse the name of a constructor.
1695 * <pre>
1696 * constructorName:
1697 * type ('.' identifier)?
1698 * </pre>
1699 * @return the constructor name that was parsed
1700 */
1701 ConstructorName parseConstructorName() {
1702 TypeName type = parseTypeName();
1703 Token period = null;
1704 SimpleIdentifier name = null;
1705 if (matches5(TokenType.PERIOD)) {
1706 period = andAdvance;
1707 name = parseSimpleIdentifier();
1708 }
1709 return new ConstructorName.full(type, period, name);
1710 }
1711 /**
1712 * Parse a continue statement.
1713 * <pre>
1714 * continueStatement ::=
1715 * 'continue' identifier? ';'
1716 * </pre>
1717 * @return the continue statement that was parsed
1718 */
1719 Statement parseContinueStatement() {
1720 Token continueKeyword = expect(Keyword.CONTINUE);
1721 if (!_inLoop && !_inSwitch) {
1722 reportError5(ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP, continueKeyword, [] );
1723 }
1724 SimpleIdentifier label = null;
1725 if (matchesIdentifier()) {
1726 label = parseSimpleIdentifier();
1727 }
1728 if (_inSwitch && !_inLoop && label == null) {
1729 reportError5(ParserErrorCode.CONTINUE_WITHOUT_LABEL_IN_CASE, continueKeywo rd, []);
1730 }
1731 Token semicolon = expect2(TokenType.SEMICOLON);
1732 return new ContinueStatement.full(continueKeyword, label, semicolon);
1733 }
1734 /**
1735 * Parse a directive.
1736 * <pre>
1737 * directive ::=
1738 * exportDirective
1739 * | libraryDirective
1740 * | importDirective
1741 * | partDirective
1742 * </pre>
1743 * @param commentAndMetadata the metadata to be associated with the directive
1744 * @return the directive that was parsed
1745 */
1746 Directive parseDirective(CommentAndMetadata commentAndMetadata) {
1747 if (matches(Keyword.IMPORT)) {
1748 return parseImportDirective(commentAndMetadata);
1749 } else if (matches(Keyword.EXPORT)) {
1750 return parseExportDirective(commentAndMetadata);
1751 } else if (matches(Keyword.LIBRARY)) {
1752 return parseLibraryDirective(commentAndMetadata);
1753 } else if (matches(Keyword.PART)) {
1754 return parsePartDirective(commentAndMetadata);
1755 } else {
1756 return null;
1757 }
1758 }
1759 /**
1760 * Parse a documentation comment.
1761 * <pre>
1762 * documentationComment ::=
1763 * multiLineComment?
1764 * | singleLineComment
1765 * </pre>
1766 * @return the documentation comment that was parsed, or {@code null} if there was no comment
1767 */
1768 Comment parseDocumentationComment() {
1769 List<Token> commentTokens = new List<Token>();
1770 Token commentToken = _currentToken.precedingComments;
1771 while (commentToken != null) {
1772 if (identical(commentToken.type, TokenType.SINGLE_LINE_COMMENT)) {
1773 if (commentToken.lexeme.startsWith("///")) {
1774 if (commentTokens.length == 1 && commentTokens[0].lexeme.startsWith("/ **")) {
1775 commentTokens.clear();
1776 }
1777 commentTokens.add(commentToken);
1778 }
1779 } else {
1780 if (commentToken.lexeme.startsWith("/**")) {
1781 commentTokens.clear();
1782 commentTokens.add(commentToken);
1783 }
1784 }
1785 commentToken = commentToken.next;
1786 }
1787 if (commentTokens.isEmpty) {
1788 return null;
1789 }
1790 List<Token> tokens = new List.from(commentTokens);
1791 List<CommentReference> references = parseCommentReferences(tokens);
1792 return Comment.createDocumentationComment2(tokens, references);
1793 }
1794 /**
1795 * Parse a do statement.
1796 * <pre>
1797 * doStatement ::=
1798 * 'do' statement 'while' '(' expression ')' ';'
1799 * </pre>
1800 * @return the do statement that was parsed
1801 */
1802 Statement parseDoStatement() {
1803 bool wasInLoop = _inLoop;
1804 _inLoop = true;
1805 try {
1806 Token doKeyword = expect(Keyword.DO);
1807 Statement body = parseStatement2();
1808 Token whileKeyword = expect(Keyword.WHILE);
1809 Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
1810 Expression condition = parseExpression2();
1811 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
1812 Token semicolon = expect2(TokenType.SEMICOLON);
1813 return new DoStatement.full(doKeyword, body, whileKeyword, leftParenthesis , condition, rightParenthesis, semicolon);
1814 } finally {
1815 _inLoop = wasInLoop;
1816 }
1817 }
1818 /**
1819 * Parse an empty statement.
1820 * <pre>
1821 * emptyStatement ::=
1822 * ';'
1823 * </pre>
1824 * @return the empty statement that was parsed
1825 */
1826 Statement parseEmptyStatement() => new EmptyStatement.full(andAdvance);
1827 /**
1828 * Parse an equality expression.
1829 * <pre>
1830 * equalityExpression ::=
1831 * relationalExpression (equalityOperator relationalExpression)?
1832 * | 'super' equalityOperator relationalExpression
1833 * </pre>
1834 * @return the equality expression that was parsed
1835 */
1836 Expression parseEqualityExpression() {
1837 Expression expression;
1838 if (matches(Keyword.SUPER) && _currentToken.next.type.isEqualityOperator()) {
1839 expression = new SuperExpression.full(andAdvance);
1840 } else {
1841 expression = parseRelationalExpression();
1842 }
1843 while (_currentToken.type.isEqualityOperator()) {
1844 Token operator = andAdvance;
1845 expression = new BinaryExpression.full(expression, operator, parseRelation alExpression());
1846 }
1847 return expression;
1848 }
1849 /**
1850 * Parse an export directive.
1851 * <pre>
1852 * exportDirective ::=
1853 * metadata 'export' stringLiteral combinator*';'
1854 * </pre>
1855 * @param commentAndMetadata the metadata to be associated with the directive
1856 * @return the export directive that was parsed
1857 */
1858 ExportDirective parseExportDirective(CommentAndMetadata commentAndMetadata) {
1859 Token exportKeyword = expect(Keyword.EXPORT);
1860 StringLiteral libraryUri = parseStringLiteral();
1861 List<Combinator> combinators = parseCombinators();
1862 Token semicolon = expect2(TokenType.SEMICOLON);
1863 return new ExportDirective.full(commentAndMetadata.comment, commentAndMetada ta.metadata, exportKeyword, libraryUri, combinators, semicolon);
1864 }
1865 /**
1866 * Parse an expression that does not contain any cascades.
1867 * <pre>
1868 * expression ::=
1869 * assignableExpression assignmentOperator expression
1870 * | conditionalExpression cascadeSection
1871 * | throwExpression
1872 * </pre>
1873 * @return the expression that was parsed
1874 */
1875 Expression parseExpression2() {
1876 if (matches(Keyword.THROW)) {
1877 return parseThrowExpression();
1878 }
1879 Expression expression = parseConditionalExpression();
1880 TokenType tokenType = _currentToken.type;
1881 if (identical(tokenType, TokenType.PERIOD_PERIOD)) {
1882 List<Expression> cascadeSections = new List<Expression>();
1883 while (identical(tokenType, TokenType.PERIOD_PERIOD)) {
1884 Expression section = parseCascadeSection();
1885 if (section != null) {
1886 cascadeSections.add(section);
1887 }
1888 tokenType = _currentToken.type;
1889 }
1890 return new CascadeExpression.full(expression, cascadeSections);
1891 } else if (tokenType.isAssignmentOperator()) {
1892 Token operator = andAdvance;
1893 ensureAssignable(expression);
1894 return new AssignmentExpression.full(expression, operator, parseExpression 2());
1895 }
1896 return expression;
1897 }
1898 /**
1899 * Parse a list of expressions.
1900 * <pre>
1901 * expressionList ::=
1902 * expression (',' expression)
1903 * </pre>
1904 * @return the expression that was parsed
1905 */
1906 List<Expression> parseExpressionList() {
1907 List<Expression> expressions = new List<Expression>();
1908 expressions.add(parseExpression2());
1909 while (optional(TokenType.COMMA)) {
1910 expressions.add(parseExpression2());
1911 }
1912 return expressions;
1913 }
1914 /**
1915 * Parse an expression that does not contain any cascades.
1916 * <pre>
1917 * expressionWithoutCascade ::=
1918 * assignableExpression assignmentOperator expressionWithoutCascade
1919 * | conditionalExpression
1920 * | throwExpressionWithoutCascade
1921 * </pre>
1922 * @return the expression that was parsed
1923 */
1924 Expression parseExpressionWithoutCascade() {
1925 if (matches(Keyword.THROW)) {
1926 return parseThrowExpressionWithoutCascade();
1927 }
1928 Expression expression = parseConditionalExpression();
1929 if (_currentToken.type.isAssignmentOperator()) {
1930 Token operator = andAdvance;
1931 ensureAssignable(expression);
1932 expression = new AssignmentExpression.full(expression, operator, parseExpr essionWithoutCascade());
1933 }
1934 return expression;
1935 }
1936 /**
1937 * Parse a class extends clause.
1938 * <pre>
1939 * classExtendsClause ::=
1940 * 'extends' type
1941 * </pre>
1942 * @return the class extends clause that was parsed
1943 */
1944 ExtendsClause parseExtendsClause() {
1945 Token keyword = expect(Keyword.EXTENDS);
1946 TypeName superclass = parseTypeName();
1947 return new ExtendsClause.full(keyword, superclass);
1948 }
1949 /**
1950 * Parse the 'final', 'const', 'var' or type preceding a variable declaration.
1951 * <pre>
1952 * finalConstVarOrType ::=
1953 * | 'final' type?
1954 * | 'const' type?
1955 * | 'var'
1956 * | type
1957 * </pre>
1958 * @param optional {@code true} if the keyword and type are optional
1959 * @return the 'final', 'const', 'var' or type that was parsed
1960 */
1961 FinalConstVarOrType parseFinalConstVarOrType(bool optional) {
1962 Token keyword = null;
1963 TypeName type = null;
1964 if (matches(Keyword.FINAL) || matches(Keyword.CONST)) {
1965 keyword = andAdvance;
1966 if (matchesIdentifier2(peek()) || matches4(peek(), TokenType.LT) || matche s3(peek(), Keyword.THIS)) {
1967 type = parseTypeName();
1968 }
1969 } else if (matches(Keyword.VAR)) {
1970 keyword = andAdvance;
1971 } else {
1972 if (matchesIdentifier2(peek()) || matches4(peek(), TokenType.LT) || matche s3(peek(), Keyword.THIS) || (matches4(peek(), TokenType.PERIOD) && matchesIdenti fier2(peek2(2)) && (matchesIdentifier2(peek2(3)) || matches4(peek2(3), TokenType .LT) || matches3(peek2(3), Keyword.THIS)))) {
1973 type = parseReturnType();
1974 } else if (!optional) {
1975 reportError4(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, []);
1976 }
1977 }
1978 return new FinalConstVarOrType(keyword, type);
1979 }
1980 /**
1981 * Parse a formal parameter. At most one of {@code isOptional} and {@code isNa med} can be{@code true}.
1982 * <pre>
1983 * defaultFormalParameter ::=
1984 * normalFormalParameter ('=' expression)?
1985 * defaultNamedParameter ::=
1986 * normalFormalParameter (':' expression)?
1987 * </pre>
1988 * @param kind the kind of parameter being expected based on the presence or a bsence of group
1989 * delimiters
1990 * @return the formal parameter that was parsed
1991 */
1992 FormalParameter parseFormalParameter(ParameterKind kind) {
1993 NormalFormalParameter parameter = parseNormalFormalParameter();
1994 if (matches5(TokenType.EQ)) {
1995 Token seperator = andAdvance;
1996 Expression defaultValue = parseExpression2();
1997 if (identical(kind, ParameterKind.NAMED)) {
1998 reportError5(ParserErrorCode.WRONG_SEPARATOR_FOR_NAMED_PARAMETER, sepera tor, []);
1999 } else if (identical(kind, ParameterKind.REQUIRED)) {
2000 reportError(ParserErrorCode.POSITIONAL_PARAMETER_OUTSIDE_GROUP, paramete r, []);
2001 }
2002 return new DefaultFormalParameter.full(parameter, kind, seperator, default Value);
2003 } else if (matches5(TokenType.COLON)) {
2004 Token seperator = andAdvance;
2005 Expression defaultValue = parseExpression2();
2006 if (identical(kind, ParameterKind.POSITIONAL)) {
2007 reportError5(ParserErrorCode.WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER, s eperator, []);
2008 } else if (identical(kind, ParameterKind.REQUIRED)) {
2009 reportError(ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP, parameter, [] );
2010 }
2011 return new DefaultFormalParameter.full(parameter, kind, seperator, default Value);
2012 } else if (kind != ParameterKind.REQUIRED) {
2013 return new DefaultFormalParameter.full(parameter, kind, null, null);
2014 }
2015 return parameter;
2016 }
2017 /**
2018 * Parse a list of formal parameters.
2019 * <pre>
2020 * formalParameterList ::=
2021 * '(' ')'
2022 * | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
2023 * | '(' optionalFormalParameters ')'
2024 * normalFormalParameters ::=
2025 * normalFormalParameter (',' normalFormalParameter)
2026 * optionalFormalParameters ::=
2027 * optionalPositionalFormalParameters
2028 * | namedFormalParameters
2029 * optionalPositionalFormalParameters ::=
2030 * '[' defaultFormalParameter (',' defaultFormalParameter)* ']'
2031 * namedFormalParameters ::=
2032 * '{' defaultNamedParameter (',' defaultNamedParameter)* '}'
2033 * </pre>
2034 * @return the formal parameters that were parsed
2035 */
2036 FormalParameterList parseFormalParameterList() {
2037 if (matches5(TokenType.EQ) && matches4(peek(), TokenType.OPEN_PAREN)) {
2038 Token previous4 = _currentToken.previous;
2039 if ((matches4(previous4, TokenType.EQ_EQ) || matches4(previous4, TokenType .BANG_EQ)) && _currentToken.offset == previous4.offset + 2) {
2040 advance();
2041 }
2042 }
2043 Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
2044 if (matches5(TokenType.CLOSE_PAREN)) {
2045 return new FormalParameterList.full(leftParenthesis, null, null, null, and Advance);
2046 }
2047 List<FormalParameter> parameters = new List<FormalParameter>();
2048 List<FormalParameter> normalParameters = new List<FormalParameter>();
2049 List<FormalParameter> positionalParameters = new List<FormalParameter>();
2050 List<FormalParameter> namedParameters = new List<FormalParameter>();
2051 List<FormalParameter> currentParameters = normalParameters;
2052 Token leftSquareBracket = null;
2053 Token rightSquareBracket = null;
2054 Token leftCurlyBracket = null;
2055 Token rightCurlyBracket = null;
2056 ParameterKind kind = ParameterKind.REQUIRED;
2057 bool firstParameter = true;
2058 bool reportedMuliplePositionalGroups = false;
2059 bool reportedMulipleNamedGroups = false;
2060 bool reportedMixedGroups = false;
2061 Token initialToken = null;
2062 do {
2063 if (firstParameter) {
2064 firstParameter = false;
2065 } else if (!optional(TokenType.COMMA)) {
2066 if (((leftParenthesis as BeginToken)).endToken != null) {
2067 reportError4(ParserErrorCode.EXPECTED_TOKEN, [TokenType.COMMA.lexeme]) ;
2068 } else {
2069 break;
2070 }
2071 }
2072 initialToken = _currentToken;
2073 if (matches5(TokenType.OPEN_SQUARE_BRACKET)) {
2074 if (leftSquareBracket != null && !reportedMuliplePositionalGroups) {
2075 reportError4(ParserErrorCode.MULTIPLE_POSITIONAL_PARAMETER_GROUPS, []) ;
2076 reportedMuliplePositionalGroups = true;
2077 }
2078 if (leftCurlyBracket != null && !reportedMixedGroups) {
2079 reportError4(ParserErrorCode.MIXED_PARAMETER_GROUPS, []);
2080 reportedMixedGroups = true;
2081 }
2082 leftSquareBracket = andAdvance;
2083 currentParameters = positionalParameters;
2084 kind = ParameterKind.POSITIONAL;
2085 } else if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
2086 if (leftCurlyBracket != null && !reportedMulipleNamedGroups) {
2087 reportError4(ParserErrorCode.MULTIPLE_NAMED_PARAMETER_GROUPS, []);
2088 reportedMulipleNamedGroups = true;
2089 }
2090 if (leftSquareBracket != null && !reportedMixedGroups) {
2091 reportError4(ParserErrorCode.MIXED_PARAMETER_GROUPS, []);
2092 reportedMixedGroups = true;
2093 }
2094 leftCurlyBracket = andAdvance;
2095 currentParameters = namedParameters;
2096 kind = ParameterKind.NAMED;
2097 }
2098 FormalParameter parameter = parseFormalParameter(kind);
2099 parameters.add(parameter);
2100 currentParameters.add(parameter);
2101 if (matches5(TokenType.CLOSE_SQUARE_BRACKET)) {
2102 rightSquareBracket = andAdvance;
2103 currentParameters = normalParameters;
2104 if (leftSquareBracket == null) {
2105 if (leftCurlyBracket != null) {
2106 reportError4(ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP, [ "}"]);
2107 rightCurlyBracket = rightSquareBracket;
2108 rightSquareBracket = null;
2109 } else {
2110 reportError4(ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GRO UP, ["["]);
2111 }
2112 }
2113 kind = ParameterKind.REQUIRED;
2114 } else if (matches5(TokenType.CLOSE_CURLY_BRACKET)) {
2115 rightCurlyBracket = andAdvance;
2116 currentParameters = normalParameters;
2117 if (leftCurlyBracket == null) {
2118 if (leftSquareBracket != null) {
2119 reportError4(ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP, [ "]"]);
2120 rightSquareBracket = rightCurlyBracket;
2121 rightCurlyBracket = null;
2122 } else {
2123 reportError4(ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GRO UP, ["{"]);
2124 }
2125 }
2126 kind = ParameterKind.REQUIRED;
2127 }
2128 } while (!matches5(TokenType.CLOSE_PAREN) && initialToken != _currentToken);
2129 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
2130 if (leftSquareBracket != null && rightSquareBracket == null) {
2131 reportError4(ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP, ["]"] );
2132 }
2133 if (leftCurlyBracket != null && rightCurlyBracket == null) {
2134 reportError4(ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP, ["}"] );
2135 }
2136 if (leftSquareBracket == null) {
2137 leftSquareBracket = leftCurlyBracket;
2138 }
2139 if (rightSquareBracket == null) {
2140 rightSquareBracket = rightCurlyBracket;
2141 }
2142 return new FormalParameterList.full(leftParenthesis, parameters, leftSquareB racket, rightSquareBracket, rightParenthesis);
2143 }
2144 /**
2145 * Parse a for statement.
2146 * <pre>
2147 * forStatement ::=
2148 * 'for' '(' forLoopParts ')' statement
2149 * forLoopParts ::=
2150 * forInitializerStatement expression? ';' expressionList?
2151 * | declaredIdentifier 'in' expression
2152 * | identifier 'in' expression
2153 * forInitializerStatement ::=
2154 * variableDeclarationList ';'
2155 * | expression? ';'
2156 * </pre>
2157 * @return the for statement that was parsed
2158 */
2159 Statement parseForStatement() {
2160 bool wasInLoop = _inLoop;
2161 _inLoop = true;
2162 try {
2163 Token forKeyword = expect(Keyword.FOR);
2164 Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
2165 VariableDeclarationList variableList = null;
2166 Expression initialization = null;
2167 if (!matches5(TokenType.SEMICOLON)) {
2168 if (matchesIdentifier() && matches3(peek(), Keyword.IN)) {
2169 List<VariableDeclaration> variables = new List<VariableDeclaration>();
2170 SimpleIdentifier variableName = parseSimpleIdentifier();
2171 variables.add(new VariableDeclaration.full(null, null, variableName, n ull, null));
2172 variableList = new VariableDeclarationList.full(null, null, variables) ;
2173 } else if (isInitializedVariableDeclaration()) {
2174 variableList = parseVariableDeclarationList();
2175 } else {
2176 initialization = parseExpression2();
2177 }
2178 if (matches(Keyword.IN)) {
2179 DeclaredIdentifier loopVariable = null;
2180 if (variableList == null) {
2181 reportError4(ParserErrorCode.MISSING_VARIABLE_IN_FOR_EACH, []);
2182 } else {
2183 NodeList<VariableDeclaration> variables3 = variableList.variables;
2184 if (variables3.length > 1) {
2185 reportError4(ParserErrorCode.MULTIPLE_VARIABLES_IN_FOR_EACH, [vari ables3.length.toString()]);
2186 }
2187 VariableDeclaration variable = variables3[0];
2188 if (variable.initializer != null) {
2189 reportError4(ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH, []) ;
2190 }
2191 loopVariable = new DeclaredIdentifier.full(null, null, variableList. keyword, variableList.type, variable.name);
2192 }
2193 Token inKeyword = expect(Keyword.IN);
2194 Expression iterator = parseExpression2();
2195 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
2196 Statement body = parseStatement2();
2197 return new ForEachStatement.full(forKeyword, leftParenthesis, loopVari able, inKeyword, iterator, rightParenthesis, body);
2198 }
2199 }
2200 Token leftSeparator = expect2(TokenType.SEMICOLON);
2201 Expression condition = null;
2202 if (!matches5(TokenType.SEMICOLON)) {
2203 condition = parseExpression2();
2204 }
2205 Token rightSeparator = expect2(TokenType.SEMICOLON);
2206 List<Expression> updaters = null;
2207 if (!matches5(TokenType.CLOSE_PAREN)) {
2208 updaters = parseExpressionList();
2209 }
2210 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
2211 Statement body = parseStatement2();
2212 return new ForStatement.full(forKeyword, leftParenthesis, variableList, in itialization, leftSeparator, condition, rightSeparator, updaters, rightParenthes is, body);
2213 } finally {
2214 _inLoop = wasInLoop;
2215 }
2216 }
2217 /**
2218 * Parse a function body.
2219 * <pre>
2220 * functionBody ::=
2221 * '=>' expression ';'
2222 * | block
2223 * functionExpressionBody ::=
2224 * '=>' expression
2225 * | block
2226 * </pre>
2227 * @param mayBeEmpty {@code true} if the function body is allowed to be empty
2228 * @param inExpression {@code true} if the function body is being parsed as pa rt of an expression
2229 * and therefore does not have a terminating semicolon
2230 * @return the function body that was parsed
2231 */
2232 FunctionBody parseFunctionBody(bool mayBeEmpty, bool inExpression) {
2233 bool wasInLoop = _inLoop;
2234 bool wasInSwitch = _inSwitch;
2235 _inLoop = false;
2236 _inSwitch = false;
2237 try {
2238 if (matches5(TokenType.SEMICOLON)) {
2239 if (!mayBeEmpty) {
2240 reportError4(ParserErrorCode.MISSING_FUNCTION_BODY, []);
2241 }
2242 return new EmptyFunctionBody.full(andAdvance);
2243 } else if (matches5(TokenType.FUNCTION)) {
2244 Token functionDefinition = andAdvance;
2245 Expression expression = parseExpression2();
2246 Token semicolon = null;
2247 if (!inExpression) {
2248 semicolon = expect2(TokenType.SEMICOLON);
2249 }
2250 return new ExpressionFunctionBody.full(functionDefinition, expression, s emicolon);
2251 } else if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
2252 return new BlockFunctionBody.full(parseBlock());
2253 } else if (matches2("native")) {
2254 advance();
2255 parseStringLiteral();
2256 return new EmptyFunctionBody.full(andAdvance);
2257 } else {
2258 reportError4(ParserErrorCode.MISSING_FUNCTION_BODY, []);
2259 return new EmptyFunctionBody.full(createSyntheticToken(TokenType.SEMICOL ON));
2260 }
2261 } finally {
2262 _inLoop = wasInLoop;
2263 _inSwitch = wasInSwitch;
2264 }
2265 }
2266 /**
2267 * Parse a function declaration.
2268 * <pre>
2269 * functionDeclaration ::=
2270 * functionSignature functionBody
2271 * | returnType? getOrSet identifier formalParameterList functionBody
2272 * </pre>
2273 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
2274 * declaration
2275 * @param externalKeyword the 'external' keyword, or {@code null} if the funct ion is not external
2276 * @param returnType the return type, or {@code null} if there is no return ty pe
2277 * @param isStatement {@code true} if the function declaration is being parsed as a statement
2278 * @return the function declaration that was parsed
2279 */
2280 FunctionDeclaration parseFunctionDeclaration(CommentAndMetadata commentAndMeta data, Token externalKeyword, TypeName returnType) {
2281 Token keyword = null;
2282 bool isGetter = false;
2283 if (matches(Keyword.GET) && !matches4(peek(), TokenType.OPEN_PAREN)) {
2284 keyword = andAdvance;
2285 isGetter = true;
2286 } else if (matches(Keyword.SET) && !matches4(peek(), TokenType.OPEN_PAREN)) {
2287 keyword = andAdvance;
2288 }
2289 SimpleIdentifier name = parseSimpleIdentifier();
2290 FormalParameterList parameters = null;
2291 if (!isGetter) {
2292 if (matches5(TokenType.OPEN_PAREN)) {
2293 parameters = parseFormalParameterList();
2294 validateFormalParameterList(parameters);
2295 } else {
2296 reportError4(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, []);
2297 }
2298 } else if (matches5(TokenType.OPEN_PAREN)) {
2299 reportError4(ParserErrorCode.GETTER_WITH_PARAMETERS, []);
2300 parseFormalParameterList();
2301 }
2302 FunctionBody body;
2303 if (externalKeyword == null) {
2304 body = parseFunctionBody(false, false);
2305 } else {
2306 body = new EmptyFunctionBody.full(expect2(TokenType.SEMICOLON));
2307 }
2308 return new FunctionDeclaration.full(commentAndMetadata.comment, commentAndMe tadata.metadata, externalKeyword, returnType, keyword, name, new FunctionExpress ion.full(parameters, body));
2309 }
2310 /**
2311 * Parse a function declaration statement.
2312 * <pre>
2313 * functionDeclarationStatement ::=
2314 * functionSignature functionBody
2315 * </pre>
2316 * @return the function declaration statement that was parsed
2317 */
2318 Statement parseFunctionDeclarationStatement() => parseFunctionDeclarationState ment2(parseCommentAndMetadata(), parseOptionalReturnType());
2319 /**
2320 * Parse a function declaration statement.
2321 * <pre>
2322 * functionDeclarationStatement ::=
2323 * functionSignature functionBody
2324 * </pre>
2325 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
2326 * declaration
2327 * @param returnType the return type, or {@code null} if there is no return ty pe
2328 * @return the function declaration statement that was parsed
2329 */
2330 Statement parseFunctionDeclarationStatement2(CommentAndMetadata commentAndMeta data, TypeName returnType) => new FunctionDeclarationStatement.full(parseFunctio nDeclaration(commentAndMetadata, null, returnType));
2331 /**
2332 * Parse a function expression.
2333 * <pre>
2334 * functionExpression ::=
2335 * (returnType? identifier)? formalParameterList functionExpressionBody
2336 * </pre>
2337 * @return the function expression that was parsed
2338 */
2339 FunctionExpression parseFunctionExpression() {
2340 FormalParameterList parameters = parseFormalParameterList();
2341 validateFormalParameterList(parameters);
2342 FunctionBody body = parseFunctionBody(false, true);
2343 return new FunctionExpression.full(parameters, body);
2344 }
2345 /**
2346 * Parse a function type alias.
2347 * <pre>
2348 * functionTypeAlias ::=
2349 * functionPrefix typeParameterList? formalParameterList ';'
2350 * functionPrefix ::=
2351 * returnType? name
2352 * </pre>
2353 * @param commentAndMetadata the metadata to be associated with the member
2354 * @param keyword the token representing the 'typedef' keyword
2355 * @return the function type alias that was parsed
2356 */
2357 FunctionTypeAlias parseFunctionTypeAlias(CommentAndMetadata commentAndMetadata , Token keyword) {
2358 TypeName returnType = null;
2359 if (hasReturnTypeInTypeAlias()) {
2360 returnType = parseReturnType();
2361 }
2362 SimpleIdentifier name = parseSimpleIdentifier();
2363 TypeParameterList typeParameters = null;
2364 if (matches5(TokenType.LT)) {
2365 typeParameters = parseTypeParameterList();
2366 }
2367 if (matches5(TokenType.SEMICOLON) || matches5(TokenType.EOF)) {
2368 reportError4(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, []);
2369 FormalParameterList parameters = new FormalParameterList.full(createSynthe ticToken(TokenType.OPEN_PAREN), null, null, null, createSyntheticToken(TokenType .CLOSE_PAREN));
2370 Token semicolon = expect2(TokenType.SEMICOLON);
2371 return new FunctionTypeAlias.full(commentAndMetadata.comment, commentAndMe tadata.metadata, keyword, returnType, name, typeParameters, parameters, semicolo n);
2372 } else if (!matches5(TokenType.OPEN_PAREN)) {
2373 return null;
2374 }
2375 FormalParameterList parameters = parseFormalParameterList();
2376 validateFormalParameterList(parameters);
2377 Token semicolon = expect2(TokenType.SEMICOLON);
2378 return new FunctionTypeAlias.full(commentAndMetadata.comment, commentAndMeta data.metadata, keyword, returnType, name, typeParameters, parameters, semicolon) ;
2379 }
2380 /**
2381 * Parse a getter.
2382 * <pre>
2383 * getter ::=
2384 * getterSignature functionBody?
2385 * getterSignature ::=
2386 * 'external'? 'static'? returnType? 'get' identifier
2387 * </pre>
2388 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
2389 * declaration
2390 * @param externalKeyword the 'external' token
2391 * @param staticKeyword the static keyword, or {@code null} if the getter is n ot static
2392 * @param the return type that has already been parsed, or {@code null} if the re was no return
2393 * type
2394 * @return the getter that was parsed
2395 */
2396 MethodDeclaration parseGetter(CommentAndMetadata commentAndMetadata, Token ext ernalKeyword, Token staticKeyword, TypeName returnType) {
2397 Token propertyKeyword = expect(Keyword.GET);
2398 SimpleIdentifier name = parseSimpleIdentifier();
2399 if (matches5(TokenType.OPEN_PAREN) && matches4(peek(), TokenType.CLOSE_PAREN )) {
2400 reportError4(ParserErrorCode.GETTER_WITH_PARAMETERS, []);
2401 advance();
2402 advance();
2403 }
2404 FunctionBody body = parseFunctionBody(true, false);
2405 if (externalKeyword != null && body is! EmptyFunctionBody) {
2406 reportError4(ParserErrorCode.EXTERNAL_GETTER_WITH_BODY, []);
2407 }
2408 return new MethodDeclaration.full(commentAndMetadata.comment, commentAndMeta data.metadata, externalKeyword, staticKeyword, returnType, propertyKeyword, null , name, null, body);
2409 }
2410 /**
2411 * Parse a list of identifiers.
2412 * <pre>
2413 * identifierList ::=
2414 * identifier (',' identifier)
2415 * </pre>
2416 * @return the list of identifiers that were parsed
2417 */
2418 List<SimpleIdentifier> parseIdentifierList() {
2419 List<SimpleIdentifier> identifiers = new List<SimpleIdentifier>();
2420 identifiers.add(parseSimpleIdentifier());
2421 while (matches5(TokenType.COMMA)) {
2422 advance();
2423 identifiers.add(parseSimpleIdentifier());
2424 }
2425 return identifiers;
2426 }
2427 /**
2428 * Parse an if statement.
2429 * <pre>
2430 * ifStatement ::=
2431 * 'if' '(' expression ')' statement ('else' statement)?
2432 * </pre>
2433 * @return the if statement that was parsed
2434 */
2435 Statement parseIfStatement() {
2436 Token ifKeyword = expect(Keyword.IF);
2437 Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
2438 Expression condition = parseExpression2();
2439 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
2440 Statement thenStatement = parseStatement2();
2441 Token elseKeyword = null;
2442 Statement elseStatement = null;
2443 if (matches(Keyword.ELSE)) {
2444 elseKeyword = andAdvance;
2445 elseStatement = parseStatement2();
2446 }
2447 return new IfStatement.full(ifKeyword, leftParenthesis, condition, rightPare nthesis, thenStatement, elseKeyword, elseStatement);
2448 }
2449 /**
2450 * Parse an implements clause.
2451 * <pre>
2452 * implementsClause ::=
2453 * 'implements' type (',' type)
2454 * </pre>
2455 * @return the implements clause that was parsed
2456 */
2457 ImplementsClause parseImplementsClause() {
2458 Token keyword = expect(Keyword.IMPLEMENTS);
2459 List<TypeName> interfaces = new List<TypeName>();
2460 interfaces.add(parseTypeName());
2461 while (optional(TokenType.COMMA)) {
2462 interfaces.add(parseTypeName());
2463 }
2464 return new ImplementsClause.full(keyword, interfaces);
2465 }
2466 /**
2467 * Parse an import directive.
2468 * <pre>
2469 * importDirective ::=
2470 * metadata 'import' stringLiteral ('as' identifier)? combinator*';'
2471 * </pre>
2472 * @param commentAndMetadata the metadata to be associated with the directive
2473 * @return the import directive that was parsed
2474 */
2475 ImportDirective parseImportDirective(CommentAndMetadata commentAndMetadata) {
2476 Token importKeyword = expect(Keyword.IMPORT);
2477 StringLiteral libraryUri = parseStringLiteral();
2478 Token asToken = null;
2479 SimpleIdentifier prefix = null;
2480 if (matches(Keyword.AS)) {
2481 asToken = andAdvance;
2482 prefix = parseSimpleIdentifier();
2483 }
2484 List<Combinator> combinators = parseCombinators();
2485 Token semicolon = expect2(TokenType.SEMICOLON);
2486 return new ImportDirective.full(commentAndMetadata.comment, commentAndMetada ta.metadata, importKeyword, libraryUri, asToken, prefix, combinators, semicolon) ;
2487 }
2488 /**
2489 * Parse a list of initialized identifiers.
2490 * <pre>
2491 * ?? ::=
2492 * 'static'? ('var' | type) initializedIdentifierList ';'
2493 * | 'final' type? initializedIdentifierList ';'
2494 * initializedIdentifierList ::=
2495 * initializedIdentifier (',' initializedIdentifier)
2496 * initializedIdentifier ::=
2497 * identifier ('=' expression)?
2498 * </pre>
2499 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
2500 * declaration
2501 * @param staticKeyword the static keyword, or {@code null} if the getter is n ot static
2502 * @param keyword the token representing the 'final', 'const' or 'var' keyword , or {@code null} if
2503 * there is no keyword
2504 * @param type the type that has already been parsed, or {@code null} if 'var' was provided
2505 * @return the getter that was parsed
2506 */
2507 FieldDeclaration parseInitializedIdentifierList(CommentAndMetadata commentAndM etadata, Token staticKeyword, Token keyword, TypeName type) {
2508 VariableDeclarationList fieldList = parseVariableDeclarationList2(keyword, t ype);
2509 return new FieldDeclaration.full(commentAndMetadata.comment, commentAndMetad ata.metadata, staticKeyword, fieldList, expect2(TokenType.SEMICOLON));
2510 }
2511 /**
2512 * Parse an instance creation expression.
2513 * <pre>
2514 * instanceCreationExpression ::=
2515 * ('new' | 'const') type ('.' identifier)? argumentList
2516 * </pre>
2517 * @param keyword the 'new' or 'const' keyword that introduces the expression
2518 * @return the instance creation expression that was parsed
2519 */
2520 InstanceCreationExpression parseInstanceCreationExpression(Token keyword) {
2521 ConstructorName constructorName = parseConstructorName();
2522 ArgumentList argumentList = parseArgumentList();
2523 return new InstanceCreationExpression.full(keyword, constructorName, argumen tList);
2524 }
2525 /**
2526 * Parse a library directive.
2527 * <pre>
2528 * libraryDirective ::=
2529 * metadata 'library' identifier ';'
2530 * </pre>
2531 * @param commentAndMetadata the metadata to be associated with the directive
2532 * @return the library directive that was parsed
2533 */
2534 LibraryDirective parseLibraryDirective(CommentAndMetadata commentAndMetadata) {
2535 Token keyword = expect(Keyword.LIBRARY);
2536 LibraryIdentifier libraryName = parseLibraryName(ParserErrorCode.MISSING_NAM E_IN_LIBRARY_DIRECTIVE, keyword);
2537 Token semicolon = expect2(TokenType.SEMICOLON);
2538 return new LibraryDirective.full(commentAndMetadata.comment, commentAndMetad ata.metadata, keyword, libraryName, semicolon);
2539 }
2540 /**
2541 * Parse a library identifier.
2542 * <pre>
2543 * libraryIdentifier ::=
2544 * identifier ('.' identifier)
2545 * </pre>
2546 * @return the library identifier that was parsed
2547 */
2548 LibraryIdentifier parseLibraryIdentifier() {
2549 List<SimpleIdentifier> components = new List<SimpleIdentifier>();
2550 components.add(parseSimpleIdentifier());
2551 while (matches5(TokenType.PERIOD)) {
2552 advance();
2553 components.add(parseSimpleIdentifier());
2554 }
2555 return new LibraryIdentifier.full(components);
2556 }
2557 /**
2558 * Parse a library name.
2559 * <pre>
2560 * libraryName ::=
2561 * libraryIdentifier
2562 * </pre>
2563 * @param missingNameError the error code to be used if the library name is mi ssing
2564 * @param missingNameToken the token associated with the error produced if the library name is
2565 * missing
2566 * @return the library name that was parsed
2567 */
2568 LibraryIdentifier parseLibraryName(ParserErrorCode missingNameError, Token mis singNameToken) {
2569 if (matchesIdentifier()) {
2570 return parseLibraryIdentifier();
2571 } else if (matches5(TokenType.STRING)) {
2572 StringLiteral string = parseStringLiteral();
2573 reportError(ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME, string, []);
2574 } else {
2575 reportError5(missingNameError, missingNameToken, []);
2576 }
2577 List<SimpleIdentifier> components = new List<SimpleIdentifier>();
2578 components.add(createSyntheticIdentifier());
2579 return new LibraryIdentifier.full(components);
2580 }
2581 /**
2582 * Parse a list literal.
2583 * <pre>
2584 * listLiteral ::=
2585 * 'const'? typeArguments? '[' (expressionList ','?)? ']'
2586 * </pre>
2587 * @param modifier the 'const' modifier appearing before the literal, or {@cod e null} if there is
2588 * no modifier
2589 * @param typeArguments the type arguments appearing before the literal, or {@ code null} if there
2590 * are no type arguments
2591 * @return the list literal that was parsed
2592 */
2593 ListLiteral parseListLiteral(Token modifier, TypeArgumentList typeArguments) {
2594 if (matches5(TokenType.INDEX)) {
2595 BeginToken leftBracket = new BeginToken(TokenType.OPEN_SQUARE_BRACKET, _cu rrentToken.offset);
2596 Token rightBracket = new Token(TokenType.CLOSE_SQUARE_BRACKET, _currentTok en.offset + 1);
2597 leftBracket.endToken = rightBracket;
2598 rightBracket.setNext(_currentToken.next);
2599 leftBracket.setNext(rightBracket);
2600 _currentToken.previous.setNext(leftBracket);
2601 _currentToken = _currentToken.next;
2602 return new ListLiteral.full(modifier, typeArguments, leftBracket, null, ri ghtBracket);
2603 }
2604 Token leftBracket = expect2(TokenType.OPEN_SQUARE_BRACKET);
2605 if (matches5(TokenType.CLOSE_SQUARE_BRACKET)) {
2606 return new ListLiteral.full(modifier, typeArguments, leftBracket, null, an dAdvance);
2607 }
2608 List<Expression> elements = new List<Expression>();
2609 elements.add(parseExpression2());
2610 while (optional(TokenType.COMMA)) {
2611 if (matches5(TokenType.CLOSE_SQUARE_BRACKET)) {
2612 return new ListLiteral.full(modifier, typeArguments, leftBracket, elemen ts, andAdvance);
2613 }
2614 elements.add(parseExpression2());
2615 }
2616 Token rightBracket = expect2(TokenType.CLOSE_SQUARE_BRACKET);
2617 return new ListLiteral.full(modifier, typeArguments, leftBracket, elements, rightBracket);
2618 }
2619 /**
2620 * Parse a list or map literal.
2621 * <pre>
2622 * listOrMapLiteral ::=
2623 * listLiteral
2624 * | mapLiteral
2625 * </pre>
2626 * @param modifier the 'const' modifier appearing before the literal, or {@cod e null} if there is
2627 * no modifier
2628 * @return the list or map literal that was parsed
2629 */
2630 TypedLiteral parseListOrMapLiteral(Token modifier) {
2631 TypeArgumentList typeArguments = null;
2632 if (matches5(TokenType.LT)) {
2633 typeArguments = parseTypeArgumentList();
2634 }
2635 if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
2636 return parseMapLiteral(modifier, typeArguments);
2637 } else if (matches5(TokenType.OPEN_SQUARE_BRACKET) || matches5(TokenType.IND EX)) {
2638 return parseListLiteral(modifier, typeArguments);
2639 }
2640 reportError4(ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL, []);
2641 return new ListLiteral.full(modifier, typeArguments, createSyntheticToken(To kenType.OPEN_SQUARE_BRACKET), null, createSyntheticToken(TokenType.CLOSE_SQUARE_ BRACKET));
2642 }
2643 /**
2644 * Parse a logical and expression.
2645 * <pre>
2646 * logicalAndExpression ::=
2647 * bitwiseOrExpression ('&&' bitwiseOrExpression)
2648 * </pre>
2649 * @return the logical and expression that was parsed
2650 */
2651 Expression parseLogicalAndExpression() {
2652 Expression expression = parseBitwiseOrExpression();
2653 while (matches5(TokenType.AMPERSAND_AMPERSAND)) {
2654 Token operator = andAdvance;
2655 expression = new BinaryExpression.full(expression, operator, parseBitwiseO rExpression());
2656 }
2657 return expression;
2658 }
2659 /**
2660 * Parse a logical or expression.
2661 * <pre>
2662 * logicalOrExpression ::=
2663 * logicalAndExpression ('||' logicalAndExpression)
2664 * </pre>
2665 * @return the logical or expression that was parsed
2666 */
2667 Expression parseLogicalOrExpression() {
2668 Expression expression = parseLogicalAndExpression();
2669 while (matches5(TokenType.BAR_BAR)) {
2670 Token operator = andAdvance;
2671 expression = new BinaryExpression.full(expression, operator, parseLogicalA ndExpression());
2672 }
2673 return expression;
2674 }
2675 /**
2676 * Parse a map literal.
2677 * <pre>
2678 * mapLiteral ::=
2679 * 'const'? typeArguments? '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}'
2680 * </pre>
2681 * @param modifier the 'const' modifier appearing before the literal, or {@cod e null} if there is
2682 * no modifier
2683 * @param typeArguments the type arguments that were declared, or {@code null} if there are no
2684 * type arguments
2685 * @return the map literal that was parsed
2686 */
2687 MapLiteral parseMapLiteral(Token modifier, TypeArgumentList typeArguments) {
2688 Token leftBracket = expect2(TokenType.OPEN_CURLY_BRACKET);
2689 List<MapLiteralEntry> entries = new List<MapLiteralEntry>();
2690 if (matches5(TokenType.CLOSE_CURLY_BRACKET)) {
2691 return new MapLiteral.full(modifier, typeArguments, leftBracket, entries, andAdvance);
2692 }
2693 entries.add(parseMapLiteralEntry());
2694 while (optional(TokenType.COMMA)) {
2695 if (matches5(TokenType.CLOSE_CURLY_BRACKET)) {
2696 return new MapLiteral.full(modifier, typeArguments, leftBracket, entries , andAdvance);
2697 }
2698 entries.add(parseMapLiteralEntry());
2699 }
2700 Token rightBracket = expect2(TokenType.CLOSE_CURLY_BRACKET);
2701 return new MapLiteral.full(modifier, typeArguments, leftBracket, entries, ri ghtBracket);
2702 }
2703 /**
2704 * Parse a map literal entry.
2705 * <pre>
2706 * mapLiteralEntry ::=
2707 * stringLiteral ':' expression
2708 * </pre>
2709 * @return the map literal entry that was parsed
2710 */
2711 MapLiteralEntry parseMapLiteralEntry() {
2712 StringLiteral key = parseStringLiteral();
2713 Token separator = expect2(TokenType.COLON);
2714 Expression value = parseExpression2();
2715 return new MapLiteralEntry.full(key, separator, value);
2716 }
2717 /**
2718 * Parse a method declaration.
2719 * <pre>
2720 * functionDeclaration ::=
2721 * 'external'? 'static'? functionSignature functionBody
2722 * | 'external'? functionSignature ';'
2723 * </pre>
2724 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
2725 * declaration
2726 * @param externalKeyword the 'external' token
2727 * @param staticKeyword the static keyword, or {@code null} if the getter is n ot static
2728 * @param returnType the return type of the method
2729 * @return the method declaration that was parsed
2730 */
2731 MethodDeclaration parseMethodDeclaration(CommentAndMetadata commentAndMetadata , Token externalKeyword, Token staticKeyword, TypeName returnType) {
2732 SimpleIdentifier methodName = parseSimpleIdentifier();
2733 FormalParameterList parameters = parseFormalParameterList();
2734 validateFormalParameterList(parameters);
2735 return parseMethodDeclaration2(commentAndMetadata, externalKeyword, staticKe yword, returnType, methodName, parameters);
2736 }
2737 /**
2738 * Parse a method declaration.
2739 * <pre>
2740 * functionDeclaration ::=
2741 * ('external' 'static'?)? functionSignature functionBody
2742 * | 'external'? functionSignature ';'
2743 * </pre>
2744 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
2745 * declaration
2746 * @param externalKeyword the 'external' token
2747 * @param staticKeyword the static keyword, or {@code null} if the getter is n ot static
2748 * @param returnType the return type of the method
2749 * @param name the name of the method
2750 * @param parameters the parameters to the method
2751 * @return the method declaration that was parsed
2752 */
2753 MethodDeclaration parseMethodDeclaration2(CommentAndMetadata commentAndMetadat a, Token externalKeyword, Token staticKeyword, TypeName returnType, SimpleIdenti fier name, FormalParameterList parameters) {
2754 FunctionBody body = parseFunctionBody(externalKeyword != null || staticKeywo rd == null, false);
2755 if (externalKeyword != null) {
2756 if (body is! EmptyFunctionBody) {
2757 reportError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, body, []);
2758 }
2759 } else if (staticKeyword != null) {
2760 if (body is EmptyFunctionBody) {
2761 reportError(ParserErrorCode.ABSTRACT_STATIC_METHOD, body, []);
2762 }
2763 }
2764 return new MethodDeclaration.full(commentAndMetadata.comment, commentAndMeta data.metadata, externalKeyword, staticKeyword, returnType, null, null, name, par ameters, body);
2765 }
2766 /**
2767 * Parse the modifiers preceding a declaration. This method allows the modifie rs to appear in any
2768 * order but does generate errors for duplicated modifiers. Checks for other p roblems, such as
2769 * having the modifiers appear in the wrong order or specifying both 'const' a nd 'final', are
2770 * reported in one of the methods whose name is prefixed with {@code validateM odifiersFor}.
2771 * <pre>
2772 * modifiers ::=
2773 * ('abstract' | 'const' | 'external' | 'factory' | 'final' | 'static' | 'var' )
2774 * </pre>
2775 * @return the modifiers that were parsed
2776 */
2777 Modifiers parseModifiers() {
2778 Modifiers modifiers = new Modifiers();
2779 bool progress = true;
2780 while (progress) {
2781 if (matches(Keyword.ABSTRACT) && !matches4(peek(), TokenType.PERIOD) && !m atches4(peek(), TokenType.LT)) {
2782 if (modifiers.abstractKeyword != null) {
2783 reportError4(ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexem e]);
2784 advance();
2785 } else {
2786 modifiers.abstractKeyword = andAdvance;
2787 }
2788 } else if (matches(Keyword.CONST)) {
2789 if (modifiers.constKeyword != null) {
2790 reportError4(ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexem e]);
2791 advance();
2792 } else {
2793 modifiers.constKeyword = andAdvance;
2794 }
2795 } else if (matches(Keyword.EXTERNAL) && !matches4(peek(), TokenType.PERIOD ) && !matches4(peek(), TokenType.LT)) {
2796 if (modifiers.externalKeyword != null) {
2797 reportError4(ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexem e]);
2798 advance();
2799 } else {
2800 modifiers.externalKeyword = andAdvance;
2801 }
2802 } else if (matches(Keyword.FACTORY) && !matches4(peek(), TokenType.PERIOD) && !matches4(peek(), TokenType.LT)) {
2803 if (modifiers.factoryKeyword != null) {
2804 reportError4(ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexem e]);
2805 advance();
2806 } else {
2807 modifiers.factoryKeyword = andAdvance;
2808 }
2809 } else if (matches(Keyword.FINAL)) {
2810 if (modifiers.finalKeyword != null) {
2811 reportError4(ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexem e]);
2812 advance();
2813 } else {
2814 modifiers.finalKeyword = andAdvance;
2815 }
2816 } else if (matches(Keyword.STATIC) && !matches4(peek(), TokenType.PERIOD) && !matches4(peek(), TokenType.LT)) {
2817 if (modifiers.staticKeyword != null) {
2818 reportError4(ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexem e]);
2819 advance();
2820 } else {
2821 modifiers.staticKeyword = andAdvance;
2822 }
2823 } else if (matches(Keyword.VAR)) {
2824 if (modifiers.varKeyword != null) {
2825 reportError4(ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexem e]);
2826 advance();
2827 } else {
2828 modifiers.varKeyword = andAdvance;
2829 }
2830 } else {
2831 progress = false;
2832 }
2833 }
2834 return modifiers;
2835 }
2836 /**
2837 * Parse a multiplicative expression.
2838 * <pre>
2839 * multiplicativeExpression ::=
2840 * unaryExpression (multiplicativeOperator unaryExpression)
2841 * | 'super' (multiplicativeOperator unaryExpression)+
2842 * </pre>
2843 * @return the multiplicative expression that was parsed
2844 */
2845 Expression parseMultiplicativeExpression() {
2846 Expression expression;
2847 if (matches(Keyword.SUPER) && _currentToken.next.type.isMultiplicativeOperat or()) {
2848 expression = new SuperExpression.full(andAdvance);
2849 } else {
2850 expression = parseUnaryExpression();
2851 }
2852 while (_currentToken.type.isMultiplicativeOperator()) {
2853 Token operator = andAdvance;
2854 expression = new BinaryExpression.full(expression, operator, parseUnaryExp ression());
2855 }
2856 return expression;
2857 }
2858 /**
2859 * Parse a new expression.
2860 * <pre>
2861 * newExpression ::=
2862 * instanceCreationExpression
2863 * </pre>
2864 * @return the new expression that was parsed
2865 */
2866 InstanceCreationExpression parseNewExpression() => parseInstanceCreationExpres sion(expect(Keyword.NEW));
2867 /**
2868 * Parse a non-labeled statement.
2869 * <pre>
2870 * nonLabeledStatement ::=
2871 * block
2872 * | assertStatement
2873 * | breakStatement
2874 * | continueStatement
2875 * | doStatement
2876 * | forStatement
2877 * | ifStatement
2878 * | returnStatement
2879 * | switchStatement
2880 * | tryStatement
2881 * | whileStatement
2882 * | variableDeclarationList ';'
2883 * | expressionStatement
2884 * | functionSignature functionBody
2885 * </pre>
2886 * @return the non-labeled statement that was parsed
2887 */
2888 Statement parseNonLabeledStatement() {
2889 CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
2890 if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
2891 if (matches4(peek(), TokenType.STRING)) {
2892 Token afterString = skipStringLiteral(_currentToken.next);
2893 if (afterString != null && identical(afterString.type, TokenType.COLON)) {
2894 return new ExpressionStatement.full(parseExpression2(), expect2(TokenT ype.SEMICOLON));
2895 }
2896 }
2897 return parseBlock();
2898 } else if (matches5(TokenType.KEYWORD) && !((_currentToken as KeywordToken)) .keyword.isPseudoKeyword()) {
2899 Keyword keyword30 = ((_currentToken as KeywordToken)).keyword;
2900 if (identical(keyword30, Keyword.ASSERT)) {
2901 return parseAssertStatement();
2902 } else if (identical(keyword30, Keyword.BREAK)) {
2903 return parseBreakStatement();
2904 } else if (identical(keyword30, Keyword.CONTINUE)) {
2905 return parseContinueStatement();
2906 } else if (identical(keyword30, Keyword.DO)) {
2907 return parseDoStatement();
2908 } else if (identical(keyword30, Keyword.FOR)) {
2909 return parseForStatement();
2910 } else if (identical(keyword30, Keyword.IF)) {
2911 return parseIfStatement();
2912 } else if (identical(keyword30, Keyword.RETURN)) {
2913 return parseReturnStatement();
2914 } else if (identical(keyword30, Keyword.SWITCH)) {
2915 return parseSwitchStatement();
2916 } else if (identical(keyword30, Keyword.THROW)) {
2917 return new ExpressionStatement.full(parseThrowExpression(), expect2(Toke nType.SEMICOLON));
2918 } else if (identical(keyword30, Keyword.TRY)) {
2919 return parseTryStatement();
2920 } else if (identical(keyword30, Keyword.WHILE)) {
2921 return parseWhileStatement();
2922 } else if (identical(keyword30, Keyword.VAR) || identical(keyword30, Keywo rd.FINAL)) {
2923 return parseVariableDeclarationStatement();
2924 } else if (identical(keyword30, Keyword.VOID)) {
2925 TypeName returnType = parseReturnType();
2926 if (matchesIdentifier() && matchesAny(peek(), [TokenType.OPEN_PAREN, Tok enType.OPEN_CURLY_BRACKET, TokenType.FUNCTION])) {
2927 return parseFunctionDeclarationStatement2(commentAndMetadata, returnTy pe);
2928 } else {
2929 if (matchesIdentifier()) {
2930 if (matchesAny(peek(), [TokenType.EQ, TokenType.COMMA, TokenType.SEM ICOLON])) {
2931 reportError(ParserErrorCode.VOID_VARIABLE, returnType, []);
2932 return parseVariableDeclarationStatement();
2933 }
2934 }
2935 return null;
2936 }
2937 } else if (identical(keyword30, Keyword.CONST)) {
2938 if (matchesAny(peek(), [TokenType.LT, TokenType.OPEN_CURLY_BRACKET, Toke nType.OPEN_SQUARE_BRACKET, TokenType.INDEX])) {
2939 return new ExpressionStatement.full(parseExpression2(), expect2(TokenT ype.SEMICOLON));
2940 } else if (matches4(peek(), TokenType.IDENTIFIER)) {
2941 Token afterType = skipTypeName(peek());
2942 if (afterType != null) {
2943 if (matches4(afterType, TokenType.OPEN_PAREN) || (matches4(afterType , TokenType.PERIOD) && matches4(afterType.next, TokenType.IDENTIFIER) && matches 4(afterType.next.next, TokenType.OPEN_PAREN))) {
2944 return new ExpressionStatement.full(parseExpression2(), expect2(To kenType.SEMICOLON));
2945 }
2946 }
2947 }
2948 return parseVariableDeclarationStatement();
2949 } else if (identical(keyword30, Keyword.NEW) || identical(keyword30, Keywo rd.TRUE) || identical(keyword30, Keyword.FALSE) || identical(keyword30, Keyword. NULL) || identical(keyword30, Keyword.SUPER) || identical(keyword30, Keyword.THI S)) {
2950 return new ExpressionStatement.full(parseExpression2(), expect2(TokenTyp e.SEMICOLON));
2951 } else {
2952 return null;
2953 }
2954 } else if (matches5(TokenType.SEMICOLON)) {
2955 return parseEmptyStatement();
2956 } else if (isInitializedVariableDeclaration()) {
2957 return parseVariableDeclarationStatement();
2958 } else if (isFunctionDeclaration()) {
2959 return parseFunctionDeclarationStatement();
2960 } else {
2961 return new ExpressionStatement.full(parseExpression2(), expect2(TokenType. SEMICOLON));
2962 }
2963 }
2964 /**
2965 * Parse a normal formal parameter.
2966 * <pre>
2967 * normalFormalParameter ::=
2968 * functionSignature
2969 * | fieldFormalParameter
2970 * | simpleFormalParameter
2971 * functionSignature:
2972 * metadata returnType? identifier formalParameterList
2973 * fieldFormalParameter ::=
2974 * metadata finalConstVarOrType? 'this' '.' identifier
2975 * simpleFormalParameter ::=
2976 * declaredIdentifier
2977 * | metadata identifier
2978 * </pre>
2979 * @return the normal formal parameter that was parsed
2980 */
2981 NormalFormalParameter parseNormalFormalParameter() {
2982 CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
2983 FinalConstVarOrType holder = parseFinalConstVarOrType(true);
2984 Token thisKeyword = null;
2985 Token period = null;
2986 if (matches(Keyword.THIS)) {
2987 thisKeyword = andAdvance;
2988 period = expect2(TokenType.PERIOD);
2989 }
2990 SimpleIdentifier identifier = parseSimpleIdentifier();
2991 if (matches5(TokenType.OPEN_PAREN)) {
2992 if (thisKeyword != null) {
2993 }
2994 FormalParameterList parameters = parseFormalParameterList();
2995 return new FunctionTypedFormalParameter.full(commentAndMetadata.comment, c ommentAndMetadata.metadata, holder.type, identifier, parameters);
2996 }
2997 TypeName type22 = holder.type;
2998 if (type22 != null && matches3(type22.name.beginToken, Keyword.VOID)) {
2999 reportError5(ParserErrorCode.VOID_PARAMETER, type22.name.beginToken, []);
3000 }
3001 if (thisKeyword != null) {
3002 return new FieldFormalParameter.full(commentAndMetadata.comment, commentAn dMetadata.metadata, holder.keyword, holder.type, thisKeyword, period, identifier );
3003 }
3004 return new SimpleFormalParameter.full(commentAndMetadata.comment, commentAnd Metadata.metadata, holder.keyword, holder.type, identifier);
3005 }
3006 /**
3007 * Parse an operator declaration.
3008 * <pre>
3009 * operatorDeclaration ::=
3010 * operatorSignature (';' | functionBody)
3011 * operatorSignature ::=
3012 * 'external'? returnType? 'operator' operator formalParameterList
3013 * </pre>
3014 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
3015 * declaration
3016 * @param externalKeyword the 'external' token
3017 * @param the return type that has already been parsed, or {@code null} if the re was no return
3018 * type
3019 * @return the operator declaration that was parsed
3020 */
3021 MethodDeclaration parseOperator(CommentAndMetadata commentAndMetadata, Token e xternalKeyword, TypeName returnType) {
3022 Token operatorKeyword = expect(Keyword.OPERATOR);
3023 if (!_currentToken.isUserDefinableOperator()) {
3024 reportError4(ParserErrorCode.NON_USER_DEFINABLE_OPERATOR, [_currentToken.l exeme]);
3025 }
3026 SimpleIdentifier name = new SimpleIdentifier.full(andAdvance);
3027 FormalParameterList parameters = parseFormalParameterList();
3028 validateFormalParameterList(parameters);
3029 FunctionBody body = parseFunctionBody(true, false);
3030 if (externalKeyword != null && body is! EmptyFunctionBody) {
3031 reportError4(ParserErrorCode.EXTERNAL_OPERATOR_WITH_BODY, []);
3032 }
3033 return new MethodDeclaration.full(commentAndMetadata.comment, commentAndMeta data.metadata, externalKeyword, null, returnType, null, operatorKeyword, name, p arameters, body);
3034 }
3035 /**
3036 * Parse a return type if one is given, otherwise return {@code null} without advancing.
3037 * @return the return type that was parsed
3038 */
3039 TypeName parseOptionalReturnType() {
3040 if (matches(Keyword.VOID)) {
3041 return parseReturnType();
3042 } else if (matchesIdentifier() && !matches(Keyword.GET) && !matches(Keyword. SET) && !matches(Keyword.OPERATOR) && (matchesIdentifier2(peek()) || matches4(pe ek(), TokenType.LT))) {
3043 return parseReturnType();
3044 } else if (matchesIdentifier() && matches4(peek(), TokenType.PERIOD) && matc hesIdentifier2(peek2(2)) && (matchesIdentifier2(peek2(3)) || matches4(peek2(3), TokenType.LT))) {
3045 return parseReturnType();
3046 }
3047 return null;
3048 }
3049 /**
3050 * Parse a part or part-of directive.
3051 * <pre>
3052 * partDirective ::=
3053 * metadata 'part' stringLiteral ';'
3054 * partOfDirective ::=
3055 * metadata 'part' 'of' identifier ';'
3056 * </pre>
3057 * @param commentAndMetadata the metadata to be associated with the directive
3058 * @return the part or part-of directive that was parsed
3059 */
3060 Directive parsePartDirective(CommentAndMetadata commentAndMetadata) {
3061 Token partKeyword = expect(Keyword.PART);
3062 if (matches2(_OF)) {
3063 Token ofKeyword = andAdvance;
3064 LibraryIdentifier libraryName = parseLibraryName(ParserErrorCode.MISSING_N AME_IN_PART_OF_DIRECTIVE, ofKeyword);
3065 Token semicolon = expect2(TokenType.SEMICOLON);
3066 return new PartOfDirective.full(commentAndMetadata.comment, commentAndMeta data.metadata, partKeyword, ofKeyword, libraryName, semicolon);
3067 }
3068 StringLiteral partUri = parseStringLiteral();
3069 Token semicolon = expect2(TokenType.SEMICOLON);
3070 return new PartDirective.full(commentAndMetadata.comment, commentAndMetadata .metadata, partKeyword, partUri, semicolon);
3071 }
3072 /**
3073 * Parse a postfix expression.
3074 * <pre>
3075 * postfixExpression ::=
3076 * assignableExpression postfixOperator
3077 * | primary selector
3078 * selector ::=
3079 * assignableSelector
3080 * | argumentList
3081 * </pre>
3082 * @return the postfix expression that was parsed
3083 */
3084 Expression parsePostfixExpression() {
3085 Expression operand = parseAssignableExpression(true);
3086 if (matches5(TokenType.OPEN_SQUARE_BRACKET) || matches5(TokenType.PERIOD) || matches5(TokenType.OPEN_PAREN)) {
3087 do {
3088 if (matches5(TokenType.OPEN_PAREN)) {
3089 ArgumentList argumentList = parseArgumentList();
3090 if (operand is PropertyAccess) {
3091 PropertyAccess access = operand as PropertyAccess;
3092 operand = new MethodInvocation.full(access.target, access.operator, access.propertyName, argumentList);
3093 } else {
3094 operand = new FunctionExpressionInvocation.full(operand, argumentLis t);
3095 }
3096 } else {
3097 operand = parseAssignableSelector(operand, true);
3098 }
3099 } while (matches5(TokenType.OPEN_SQUARE_BRACKET) || matches5(TokenType.PER IOD) || matches5(TokenType.OPEN_PAREN));
3100 return operand;
3101 }
3102 if (!_currentToken.type.isIncrementOperator()) {
3103 return operand;
3104 }
3105 if (operand is FunctionExpressionInvocation) {
3106 reportError4(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, []);
3107 }
3108 Token operator = andAdvance;
3109 return new PostfixExpression.full(operand, operator);
3110 }
3111 /**
3112 * Parse a prefixed identifier.
3113 * <pre>
3114 * prefixedIdentifier ::=
3115 * identifier ('.' identifier)?
3116 * </pre>
3117 * @return the prefixed identifier that was parsed
3118 */
3119 Identifier parsePrefixedIdentifier() {
3120 SimpleIdentifier qualifier = parseSimpleIdentifier();
3121 if (!matches5(TokenType.PERIOD)) {
3122 return qualifier;
3123 }
3124 Token period = andAdvance;
3125 SimpleIdentifier qualified = parseSimpleIdentifier();
3126 return new PrefixedIdentifier.full(qualifier, period, qualified);
3127 }
3128 /**
3129 * Parse a primary expression.
3130 * <pre>
3131 * primary ::=
3132 * thisExpression
3133 * | 'super' assignableSelector
3134 * | functionExpression
3135 * | literal
3136 * | identifier
3137 * | newExpression
3138 * | constObjectExpression
3139 * | '(' expression ')'
3140 * | argumentDefinitionTest
3141 * literal ::=
3142 * nullLiteral
3143 * | booleanLiteral
3144 * | numericLiteral
3145 * | stringLiteral
3146 * | mapLiteral
3147 * | listLiteral
3148 * </pre>
3149 * @return the primary expression that was parsed
3150 */
3151 Expression parsePrimaryExpression() {
3152 if (matches(Keyword.THIS)) {
3153 return new ThisExpression.full(andAdvance);
3154 } else if (matches(Keyword.SUPER)) {
3155 return parseAssignableSelector(new SuperExpression.full(andAdvance), false );
3156 } else if (matches(Keyword.NULL)) {
3157 return new NullLiteral.full(andAdvance);
3158 } else if (matches(Keyword.FALSE)) {
3159 return new BooleanLiteral.full(andAdvance, false);
3160 } else if (matches(Keyword.TRUE)) {
3161 return new BooleanLiteral.full(andAdvance, true);
3162 } else if (matches5(TokenType.DOUBLE)) {
3163 Token token = andAdvance;
3164 double value = 0.0;
3165 try {
3166 value = double.parse(token.lexeme);
3167 } on NumberFormatException catch (exception) {
3168 }
3169 return new DoubleLiteral.full(token, value);
3170 } else if (matches5(TokenType.HEXADECIMAL)) {
3171 Token token = andAdvance;
3172 int value = null;
3173 try {
3174 value = int.parse(token.lexeme.substring(2), radix: 16);
3175 } on NumberFormatException catch (exception) {
3176 }
3177 return new IntegerLiteral.full(token, value);
3178 } else if (matches5(TokenType.INT)) {
3179 Token token = andAdvance;
3180 int value = null;
3181 try {
3182 value = int.parse(token.lexeme);
3183 } on NumberFormatException catch (exception) {
3184 }
3185 return new IntegerLiteral.full(token, value);
3186 } else if (matches5(TokenType.STRING)) {
3187 return parseStringLiteral();
3188 } else if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
3189 return parseMapLiteral(null, null);
3190 } else if (matches5(TokenType.OPEN_SQUARE_BRACKET) || matches5(TokenType.IND EX)) {
3191 return parseListLiteral(null, null);
3192 } else if (matchesIdentifier()) {
3193 return parsePrefixedIdentifier();
3194 } else if (matches(Keyword.NEW)) {
3195 return parseNewExpression();
3196 } else if (matches(Keyword.CONST)) {
3197 return parseConstExpression();
3198 } else if (matches5(TokenType.OPEN_PAREN)) {
3199 if (isFunctionExpression(_currentToken)) {
3200 return parseFunctionExpression();
3201 }
3202 Token leftParenthesis = andAdvance;
3203 Expression expression = parseExpression2();
3204 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
3205 return new ParenthesizedExpression.full(leftParenthesis, expression, right Parenthesis);
3206 } else if (matches5(TokenType.LT)) {
3207 return parseListOrMapLiteral(null);
3208 } else if (matches5(TokenType.QUESTION)) {
3209 return parseArgumentDefinitionTest();
3210 } else if (matches(Keyword.VOID)) {
3211 reportError4(ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken.lexeme]);
3212 advance();
3213 return parsePrimaryExpression();
3214 } else {
3215 return createSyntheticIdentifier();
3216 }
3217 }
3218 /**
3219 * Parse a redirecting constructor invocation.
3220 * <pre>
3221 * redirectingConstructorInvocation ::=
3222 * 'this' ('.' identifier)? arguments
3223 * </pre>
3224 * @return the redirecting constructor invocation that was parsed
3225 */
3226 RedirectingConstructorInvocation parseRedirectingConstructorInvocation() {
3227 Token keyword = expect(Keyword.THIS);
3228 Token period = null;
3229 SimpleIdentifier constructorName = null;
3230 if (matches5(TokenType.PERIOD)) {
3231 period = andAdvance;
3232 constructorName = parseSimpleIdentifier();
3233 }
3234 ArgumentList argumentList = parseArgumentList();
3235 return new RedirectingConstructorInvocation.full(keyword, period, constructo rName, argumentList);
3236 }
3237 /**
3238 * Parse a relational expression.
3239 * <pre>
3240 * relationalExpression ::=
3241 * shiftExpression ('is' type | 'as' type | relationalOperator shiftExpression )?
3242 * | 'super' relationalOperator shiftExpression
3243 * </pre>
3244 * @return the relational expression that was parsed
3245 */
3246 Expression parseRelationalExpression() {
3247 if (matches(Keyword.SUPER) && _currentToken.next.type.isRelationalOperator() ) {
3248 Expression expression = new SuperExpression.full(andAdvance);
3249 Token operator = andAdvance;
3250 expression = new BinaryExpression.full(expression, operator, parseShiftExp ression());
3251 return expression;
3252 }
3253 Expression expression = parseShiftExpression();
3254 if (matches(Keyword.AS)) {
3255 Token asOperator = andAdvance;
3256 expression = new AsExpression.full(expression, asOperator, parseTypeName() );
3257 } else if (matches(Keyword.IS)) {
3258 Token isOperator = andAdvance;
3259 Token notOperator = null;
3260 if (matches5(TokenType.BANG)) {
3261 notOperator = andAdvance;
3262 }
3263 expression = new IsExpression.full(expression, isOperator, notOperator, pa rseTypeName());
3264 } else if (_currentToken.type.isRelationalOperator()) {
3265 Token operator = andAdvance;
3266 expression = new BinaryExpression.full(expression, operator, parseShiftExp ression());
3267 }
3268 return expression;
3269 }
3270 /**
3271 * Parse a return statement.
3272 * <pre>
3273 * returnStatement ::=
3274 * 'return' expression? ';'
3275 * </pre>
3276 * @return the return statement that was parsed
3277 */
3278 Statement parseReturnStatement() {
3279 Token returnKeyword = expect(Keyword.RETURN);
3280 if (matches5(TokenType.SEMICOLON)) {
3281 return new ReturnStatement.full(returnKeyword, null, andAdvance);
3282 }
3283 Expression expression = parseExpression2();
3284 Token semicolon = expect2(TokenType.SEMICOLON);
3285 return new ReturnStatement.full(returnKeyword, expression, semicolon);
3286 }
3287 /**
3288 * Parse a return type.
3289 * <pre>
3290 * returnType ::=
3291 * 'void'
3292 * | type
3293 * </pre>
3294 * @return the return type that was parsed
3295 */
3296 TypeName parseReturnType() {
3297 if (matches(Keyword.VOID)) {
3298 return new TypeName.full(new SimpleIdentifier.full(andAdvance), null);
3299 } else {
3300 return parseTypeName();
3301 }
3302 }
3303 /**
3304 * Parse a setter.
3305 * <pre>
3306 * setter ::=
3307 * setterSignature functionBody?
3308 * setterSignature ::=
3309 * 'external'? 'static'? returnType? 'set' identifier formalParameterList
3310 * </pre>
3311 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
3312 * declaration
3313 * @param externalKeyword the 'external' token
3314 * @param staticKeyword the static keyword, or {@code null} if the setter is n ot static
3315 * @param the return type that has already been parsed, or {@code null} if the re was no return
3316 * type
3317 * @return the setter that was parsed
3318 */
3319 MethodDeclaration parseSetter(CommentAndMetadata commentAndMetadata, Token ext ernalKeyword, Token staticKeyword, TypeName returnType) {
3320 Token propertyKeyword = expect(Keyword.SET);
3321 SimpleIdentifier name = parseSimpleIdentifier();
3322 FormalParameterList parameters = parseFormalParameterList();
3323 validateFormalParameterList(parameters);
3324 FunctionBody body = parseFunctionBody(true, false);
3325 if (externalKeyword != null && body is! EmptyFunctionBody) {
3326 reportError4(ParserErrorCode.EXTERNAL_SETTER_WITH_BODY, []);
3327 }
3328 return new MethodDeclaration.full(commentAndMetadata.comment, commentAndMeta data.metadata, externalKeyword, staticKeyword, returnType, propertyKeyword, null , name, parameters, body);
3329 }
3330 /**
3331 * Parse a shift expression.
3332 * <pre>
3333 * shiftExpression ::=
3334 * additiveExpression (shiftOperator additiveExpression)
3335 * | 'super' (shiftOperator additiveExpression)+
3336 * </pre>
3337 * @return the shift expression that was parsed
3338 */
3339 Expression parseShiftExpression() {
3340 Expression expression;
3341 if (matches(Keyword.SUPER) && _currentToken.next.type.isShiftOperator()) {
3342 expression = new SuperExpression.full(andAdvance);
3343 } else {
3344 expression = parseAdditiveExpression();
3345 }
3346 while (_currentToken.type.isShiftOperator()) {
3347 Token operator = andAdvance;
3348 expression = new BinaryExpression.full(expression, operator, parseAdditive Expression());
3349 }
3350 return expression;
3351 }
3352 /**
3353 * Parse a simple identifier.
3354 * <pre>
3355 * identifier ::=
3356 * IDENTIFIER
3357 * </pre>
3358 * @return the simple identifier that was parsed
3359 */
3360 SimpleIdentifier parseSimpleIdentifier() {
3361 if (matchesIdentifier()) {
3362 return new SimpleIdentifier.full(andAdvance);
3363 }
3364 reportError4(ParserErrorCode.MISSING_IDENTIFIER, []);
3365 return createSyntheticIdentifier();
3366 }
3367 /**
3368 * Parse a statement.
3369 * <pre>
3370 * statement ::=
3371 * label* nonLabeledStatement
3372 * </pre>
3373 * @return the statement that was parsed
3374 */
3375 Statement parseStatement2() {
3376 List<Label> labels = new List<Label>();
3377 while (matchesIdentifier() && matches4(peek(), TokenType.COLON)) {
3378 SimpleIdentifier label = parseSimpleIdentifier();
3379 Token colon = expect2(TokenType.COLON);
3380 labels.add(new Label.full(label, colon));
3381 }
3382 Statement statement = parseNonLabeledStatement();
3383 if (labels.isEmpty) {
3384 return statement;
3385 }
3386 return new LabeledStatement.full(labels, statement);
3387 }
3388 /**
3389 * Parse a list of statements within a switch statement.
3390 * <pre>
3391 * statements ::=
3392 * statement
3393 * </pre>
3394 * @return the statements that were parsed
3395 */
3396 List<Statement> parseStatements2() {
3397 List<Statement> statements = new List<Statement>();
3398 Token statementStart = _currentToken;
3399 while (!matches5(TokenType.EOF) && !matches5(TokenType.CLOSE_CURLY_BRACKET) && !isSwitchMember()) {
3400 statements.add(parseStatement2());
3401 if (identical(_currentToken, statementStart)) {
3402 reportError5(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_currentT oken.lexeme]);
3403 advance();
3404 }
3405 statementStart = _currentToken;
3406 }
3407 return statements;
3408 }
3409 /**
3410 * Parse a string literal that contains interpolations.
3411 * @return the string literal that was parsed
3412 */
3413 StringInterpolation parseStringInterpolation(Token string) {
3414 List<InterpolationElement> elements = new List<InterpolationElement>();
3415 elements.add(new InterpolationString.full(string, computeStringValue(string. lexeme)));
3416 while (matches5(TokenType.STRING_INTERPOLATION_EXPRESSION) || matches5(Token Type.STRING_INTERPOLATION_IDENTIFIER)) {
3417 if (matches5(TokenType.STRING_INTERPOLATION_EXPRESSION)) {
3418 Token openToken = andAdvance;
3419 Expression expression = parseExpression2();
3420 Token rightBracket = expect2(TokenType.CLOSE_CURLY_BRACKET);
3421 elements.add(new InterpolationExpression.full(openToken, expression, rig htBracket));
3422 } else {
3423 Token openToken = andAdvance;
3424 Expression expression = null;
3425 if (matches(Keyword.THIS)) {
3426 expression = new ThisExpression.full(andAdvance);
3427 } else {
3428 expression = parseSimpleIdentifier();
3429 }
3430 elements.add(new InterpolationExpression.full(openToken, expression, nul l));
3431 }
3432 if (matches5(TokenType.STRING)) {
3433 string = andAdvance;
3434 elements.add(new InterpolationString.full(string, computeStringValue(str ing.lexeme)));
3435 }
3436 }
3437 return new StringInterpolation.full(elements);
3438 }
3439 /**
3440 * Parse a string literal.
3441 * <pre>
3442 * stringLiteral ::=
3443 * MULTI_LINE_STRING+
3444 * | SINGLE_LINE_STRING+
3445 * </pre>
3446 * @return the string literal that was parsed
3447 */
3448 StringLiteral parseStringLiteral() {
3449 List<StringLiteral> strings = new List<StringLiteral>();
3450 while (matches5(TokenType.STRING)) {
3451 Token string = andAdvance;
3452 if (matches5(TokenType.STRING_INTERPOLATION_EXPRESSION) || matches5(TokenT ype.STRING_INTERPOLATION_IDENTIFIER)) {
3453 strings.add(parseStringInterpolation(string));
3454 } else {
3455 strings.add(new SimpleStringLiteral.full(string, computeStringValue(stri ng.lexeme)));
3456 }
3457 }
3458 if (strings.length < 1) {
3459 reportError4(ParserErrorCode.EXPECTED_STRING_LITERAL, []);
3460 return createSyntheticStringLiteral();
3461 } else if (strings.length == 1) {
3462 return strings[0];
3463 } else {
3464 return new AdjacentStrings.full(strings);
3465 }
3466 }
3467 /**
3468 * Parse a super constructor invocation.
3469 * <pre>
3470 * superConstructorInvocation ::=
3471 * 'super' ('.' identifier)? arguments
3472 * </pre>
3473 * @return the super constructor invocation that was parsed
3474 */
3475 SuperConstructorInvocation parseSuperConstructorInvocation() {
3476 Token keyword = expect(Keyword.SUPER);
3477 Token period = null;
3478 SimpleIdentifier constructorName = null;
3479 if (matches5(TokenType.PERIOD)) {
3480 period = andAdvance;
3481 constructorName = parseSimpleIdentifier();
3482 }
3483 ArgumentList argumentList = parseArgumentList();
3484 return new SuperConstructorInvocation.full(keyword, period, constructorName, argumentList);
3485 }
3486 /**
3487 * Parse a switch statement.
3488 * <pre>
3489 * switchStatement ::=
3490 * 'switch' '(' expression ')' '{' switchCase* defaultCase? '}'
3491 * switchCase ::=
3492 * label* ('case' expression ':') statements
3493 * defaultCase ::=
3494 * label* 'default' ':' statements
3495 * </pre>
3496 * @return the switch statement that was parsed
3497 */
3498 SwitchStatement parseSwitchStatement() {
3499 bool wasInSwitch = _inSwitch;
3500 _inSwitch = true;
3501 try {
3502 Set<String> definedLabels = new Set<String>();
3503 Token keyword = expect(Keyword.SWITCH);
3504 Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
3505 Expression expression = parseExpression2();
3506 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
3507 Token leftBracket = expect2(TokenType.OPEN_CURLY_BRACKET);
3508 List<SwitchMember> members = new List<SwitchMember>();
3509 while (!matches5(TokenType.EOF) && !matches5(TokenType.CLOSE_CURLY_BRACKET )) {
3510 List<Label> labels = new List<Label>();
3511 while (matchesIdentifier() && matches4(peek(), TokenType.COLON)) {
3512 SimpleIdentifier identifier = parseSimpleIdentifier();
3513 String label = identifier.token.lexeme;
3514 if (definedLabels.contains(label)) {
3515 reportError5(ParserErrorCode.DUPLICATE_LABEL_IN_SWITCH_STATEMENT, id entifier.token, [label]);
3516 } else {
3517 javaSetAdd(definedLabels, label);
3518 }
3519 Token colon = expect2(TokenType.COLON);
3520 labels.add(new Label.full(identifier, colon));
3521 }
3522 if (matches(Keyword.CASE)) {
3523 Token caseKeyword = andAdvance;
3524 Expression caseExpression = parseExpression2();
3525 Token colon = expect2(TokenType.COLON);
3526 members.add(new SwitchCase.full(labels, caseKeyword, caseExpression, c olon, parseStatements2()));
3527 } else if (matches(Keyword.DEFAULT)) {
3528 Token defaultKeyword = andAdvance;
3529 Token colon = expect2(TokenType.COLON);
3530 members.add(new SwitchDefault.full(labels, defaultKeyword, colon, pars eStatements2()));
3531 } else {
3532 reportError4(ParserErrorCode.EXPECTED_CASE_OR_DEFAULT, []);
3533 while (!matches5(TokenType.EOF) && !matches5(TokenType.CLOSE_CURLY_BRA CKET) && !matches(Keyword.CASE) && !matches(Keyword.DEFAULT)) {
3534 advance();
3535 }
3536 }
3537 }
3538 Token rightBracket = expect2(TokenType.CLOSE_CURLY_BRACKET);
3539 return new SwitchStatement.full(keyword, leftParenthesis, expression, righ tParenthesis, leftBracket, members, rightBracket);
3540 } finally {
3541 _inSwitch = wasInSwitch;
3542 }
3543 }
3544 /**
3545 * Parse a throw expression.
3546 * <pre>
3547 * throwExpression ::=
3548 * 'throw' expression? ';'
3549 * </pre>
3550 * @return the throw expression that was parsed
3551 */
3552 Expression parseThrowExpression() {
3553 Token keyword = expect(Keyword.THROW);
3554 if (matches5(TokenType.SEMICOLON) || matches5(TokenType.CLOSE_PAREN)) {
3555 return new ThrowExpression.full(keyword, null);
3556 }
3557 Expression expression = parseExpression2();
3558 return new ThrowExpression.full(keyword, expression);
3559 }
3560 /**
3561 * Parse a throw expression.
3562 * <pre>
3563 * throwExpressionWithoutCascade ::=
3564 * 'throw' expressionWithoutCascade? ';'
3565 * </pre>
3566 * @return the throw expression that was parsed
3567 */
3568 Expression parseThrowExpressionWithoutCascade() {
3569 Token keyword = expect(Keyword.THROW);
3570 if (matches5(TokenType.SEMICOLON) || matches5(TokenType.CLOSE_PAREN)) {
3571 return new ThrowExpression.full(keyword, null);
3572 }
3573 Expression expression = parseExpressionWithoutCascade();
3574 return new ThrowExpression.full(keyword, expression);
3575 }
3576 /**
3577 * Parse a try statement.
3578 * <pre>
3579 * tryStatement ::=
3580 * 'try' block (onPart+ finallyPart? | finallyPart)
3581 * onPart ::=
3582 * catchPart block
3583 * | 'on' qualified catchPart? block
3584 * catchPart ::=
3585 * 'catch' '(' identifier (',' identifier)? ')'
3586 * finallyPart ::=
3587 * 'finally' block
3588 * </pre>
3589 * @return the try statement that was parsed
3590 */
3591 Statement parseTryStatement() {
3592 Token tryKeyword = expect(Keyword.TRY);
3593 Block body = parseBlock();
3594 List<CatchClause> catchClauses = new List<CatchClause>();
3595 Block finallyClause = null;
3596 while (matches2(_ON) || matches(Keyword.CATCH)) {
3597 Token onKeyword = null;
3598 TypeName exceptionType = null;
3599 if (matches2(_ON)) {
3600 onKeyword = andAdvance;
3601 exceptionType = new TypeName.full(parsePrefixedIdentifier(), null);
3602 }
3603 Token catchKeyword = null;
3604 Token leftParenthesis = null;
3605 SimpleIdentifier exceptionParameter = null;
3606 Token comma = null;
3607 SimpleIdentifier stackTraceParameter = null;
3608 Token rightParenthesis = null;
3609 if (matches(Keyword.CATCH)) {
3610 catchKeyword = andAdvance;
3611 leftParenthesis = expect2(TokenType.OPEN_PAREN);
3612 exceptionParameter = parseSimpleIdentifier();
3613 if (matches5(TokenType.COMMA)) {
3614 comma = andAdvance;
3615 stackTraceParameter = parseSimpleIdentifier();
3616 }
3617 rightParenthesis = expect2(TokenType.CLOSE_PAREN);
3618 }
3619 Block catchBody = parseBlock();
3620 catchClauses.add(new CatchClause.full(onKeyword, exceptionType, catchKeywo rd, leftParenthesis, exceptionParameter, comma, stackTraceParameter, rightParent hesis, catchBody));
3621 }
3622 Token finallyKeyword = null;
3623 if (matches(Keyword.FINALLY)) {
3624 finallyKeyword = andAdvance;
3625 finallyClause = parseBlock();
3626 } else {
3627 if (catchClauses.isEmpty) {
3628 reportError4(ParserErrorCode.MISSING_CATCH_OR_FINALLY, []);
3629 }
3630 }
3631 return new TryStatement.full(tryKeyword, body, catchClauses, finallyKeyword, finallyClause);
3632 }
3633 /**
3634 * Parse a type alias.
3635 * <pre>
3636 * typeAlias ::=
3637 * 'typedef' typeAliasBody
3638 * typeAliasBody ::=
3639 * classTypeAlias
3640 * | functionTypeAlias
3641 * classTypeAlias ::=
3642 * identifier typeParameters? '=' 'abstract'? mixinApplication
3643 * mixinApplication ::=
3644 * qualified withClause implementsClause? ';'
3645 * functionTypeAlias ::=
3646 * functionPrefix typeParameterList? formalParameterList ';'
3647 * functionPrefix ::=
3648 * returnType? name
3649 * </pre>
3650 * @param commentAndMetadata the metadata to be associated with the member
3651 * @return the type alias that was parsed
3652 */
3653 TypeAlias parseTypeAlias(CommentAndMetadata commentAndMetadata) {
3654 Token keyword = expect(Keyword.TYPEDEF);
3655 if (matchesIdentifier()) {
3656 Token next = peek();
3657 if (matches4(next, TokenType.LT)) {
3658 next = skipTypeParameterList(next);
3659 if (next != null && matches4(next, TokenType.EQ)) {
3660 return parseClassTypeAlias(commentAndMetadata, keyword);
3661 }
3662 } else if (matches4(next, TokenType.EQ)) {
3663 return parseClassTypeAlias(commentAndMetadata, keyword);
3664 }
3665 }
3666 return parseFunctionTypeAlias(commentAndMetadata, keyword);
3667 }
3668 /**
3669 * Parse a list of type arguments.
3670 * <pre>
3671 * typeArguments ::=
3672 * '<' typeList '>'
3673 * typeList ::=
3674 * type (',' type)
3675 * </pre>
3676 * @return the type argument list that was parsed
3677 */
3678 TypeArgumentList parseTypeArgumentList() {
3679 Token leftBracket = expect2(TokenType.LT);
3680 List<TypeName> arguments = new List<TypeName>();
3681 arguments.add(parseTypeName());
3682 while (optional(TokenType.COMMA)) {
3683 arguments.add(parseTypeName());
3684 }
3685 Token rightBracket = expect2(TokenType.GT);
3686 return new TypeArgumentList.full(leftBracket, arguments, rightBracket);
3687 }
3688 /**
3689 * Parse a type name.
3690 * <pre>
3691 * type ::=
3692 * qualified typeArguments?
3693 * </pre>
3694 * @return the type name that was parsed
3695 */
3696 TypeName parseTypeName() {
3697 Identifier typeName = parsePrefixedIdentifier();
3698 TypeArgumentList typeArguments = null;
3699 if (matches5(TokenType.LT)) {
3700 typeArguments = parseTypeArgumentList();
3701 }
3702 return new TypeName.full(typeName, typeArguments);
3703 }
3704 /**
3705 * Parse a type parameter.
3706 * <pre>
3707 * typeParameter ::=
3708 * metadata name ('extends' bound)?
3709 * </pre>
3710 * @return the type parameter that was parsed
3711 */
3712 TypeParameter parseTypeParameter() {
3713 CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
3714 SimpleIdentifier name = parseSimpleIdentifier();
3715 if (matches(Keyword.EXTENDS)) {
3716 Token keyword = andAdvance;
3717 TypeName bound = parseTypeName();
3718 return new TypeParameter.full(commentAndMetadata.comment, commentAndMetada ta.metadata, name, keyword, bound);
3719 }
3720 return new TypeParameter.full(commentAndMetadata.comment, commentAndMetadata .metadata, name, null, null);
3721 }
3722 /**
3723 * Parse a list of type parameters.
3724 * <pre>
3725 * typeParameterList ::=
3726 * '<' typeParameter (',' typeParameter)* '>'
3727 * </pre>
3728 * @return the list of type parameters that were parsed
3729 */
3730 TypeParameterList parseTypeParameterList() {
3731 Token leftBracket = expect2(TokenType.LT);
3732 List<TypeParameter> typeParameters = new List<TypeParameter>();
3733 typeParameters.add(parseTypeParameter());
3734 while (optional(TokenType.COMMA)) {
3735 typeParameters.add(parseTypeParameter());
3736 }
3737 Token rightBracket = expect2(TokenType.GT);
3738 return new TypeParameterList.full(leftBracket, typeParameters, rightBracket) ;
3739 }
3740 /**
3741 * Parse a unary expression.
3742 * <pre>
3743 * unaryExpression ::=
3744 * prefixOperator unaryExpression
3745 * | postfixExpression
3746 * | unaryOperator 'super'
3747 * | '-' 'super'
3748 * | incrementOperator assignableExpression
3749 * </pre>
3750 * @return the unary expression that was parsed
3751 */
3752 Expression parseUnaryExpression() {
3753 if (matches5(TokenType.MINUS) || matches5(TokenType.BANG) || matches5(TokenT ype.TILDE)) {
3754 Token operator = andAdvance;
3755 if (matches(Keyword.SUPER)) {
3756 if (matches4(peek(), TokenType.OPEN_SQUARE_BRACKET) || matches4(peek(), TokenType.PERIOD)) {
3757 return new PrefixExpression.full(operator, parseUnaryExpression());
3758 }
3759 return new PrefixExpression.full(operator, new SuperExpression.full(andA dvance));
3760 }
3761 return new PrefixExpression.full(operator, parseUnaryExpression());
3762 } else if (_currentToken.type.isIncrementOperator()) {
3763 Token operator = andAdvance;
3764 if (matches(Keyword.SUPER)) {
3765 if (identical(operator.type, TokenType.MINUS_MINUS)) {
3766 int offset9 = operator.offset;
3767 Token firstOperator = new Token(TokenType.MINUS, offset9);
3768 Token secondOperator = new Token(TokenType.MINUS, offset9 + 1);
3769 secondOperator.setNext(_currentToken);
3770 firstOperator.setNext(secondOperator);
3771 operator.previous.setNext(firstOperator);
3772 return new PrefixExpression.full(firstOperator, new PrefixExpression.f ull(secondOperator, new SuperExpression.full(andAdvance)));
3773 } else {
3774 reportError4(ParserErrorCode.INVALID_OPERATOR_FOR_SUPER, [operator.lex eme]);
3775 return new PrefixExpression.full(operator, new SuperExpression.full(an dAdvance));
3776 }
3777 }
3778 return new PrefixExpression.full(operator, parseAssignableExpression(false ));
3779 } else if (matches5(TokenType.PLUS)) {
3780 reportError4(ParserErrorCode.USE_OF_UNARY_PLUS_OPERATOR, []);
3781 }
3782 return parsePostfixExpression();
3783 }
3784 /**
3785 * Parse a variable declaration.
3786 * <pre>
3787 * variableDeclaration ::=
3788 * identifier ('=' expression)?
3789 * </pre>
3790 * @return the variable declaration that was parsed
3791 */
3792 VariableDeclaration parseVariableDeclaration() {
3793 CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
3794 SimpleIdentifier name = parseSimpleIdentifier();
3795 Token equals = null;
3796 Expression initializer = null;
3797 if (matches5(TokenType.EQ)) {
3798 equals = andAdvance;
3799 initializer = parseExpression2();
3800 }
3801 return new VariableDeclaration.full(commentAndMetadata.comment, commentAndMe tadata.metadata, name, equals, initializer);
3802 }
3803 /**
3804 * Parse a variable declaration list.
3805 * <pre>
3806 * variableDeclarationList ::=
3807 * finalConstVarOrType variableDeclaration (',' variableDeclaration)
3808 * </pre>
3809 * @return the variable declaration list that was parsed
3810 */
3811 VariableDeclarationList parseVariableDeclarationList() {
3812 FinalConstVarOrType holder = parseFinalConstVarOrType(false);
3813 return parseVariableDeclarationList2(holder.keyword, holder.type);
3814 }
3815 /**
3816 * Parse a variable declaration list.
3817 * <pre>
3818 * variableDeclarationList ::=
3819 * finalConstVarOrType variableDeclaration (',' variableDeclaration)
3820 * </pre>
3821 * @param keyword the token representing the 'final', 'const' or 'var' keyword , or {@code null} if
3822 * there is no keyword
3823 * @param type the type of the variables in the list
3824 * @return the variable declaration list that was parsed
3825 */
3826 VariableDeclarationList parseVariableDeclarationList2(Token keyword, TypeName type) {
3827 List<VariableDeclaration> variables = new List<VariableDeclaration>();
3828 variables.add(parseVariableDeclaration());
3829 while (matches5(TokenType.COMMA)) {
3830 advance();
3831 variables.add(parseVariableDeclaration());
3832 }
3833 return new VariableDeclarationList.full(keyword, type, variables);
3834 }
3835 /**
3836 * Parse a variable declaration statement.
3837 * <pre>
3838 * variableDeclarationStatement ::=
3839 * variableDeclarationList ';'
3840 * </pre>
3841 * @return the variable declaration statement that was parsed
3842 */
3843 VariableDeclarationStatement parseVariableDeclarationStatement() {
3844 VariableDeclarationList variableList = parseVariableDeclarationList();
3845 Token semicolon = expect2(TokenType.SEMICOLON);
3846 return new VariableDeclarationStatement.full(variableList, semicolon);
3847 }
3848 /**
3849 * Parse a while statement.
3850 * <pre>
3851 * whileStatement ::=
3852 * 'while' '(' expression ')' statement
3853 * </pre>
3854 * @return the while statement that was parsed
3855 */
3856 Statement parseWhileStatement() {
3857 bool wasInLoop = _inLoop;
3858 _inLoop = true;
3859 try {
3860 Token keyword = expect(Keyword.WHILE);
3861 Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
3862 Expression condition = parseExpression2();
3863 Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
3864 Statement body = parseStatement2();
3865 return new WhileStatement.full(keyword, leftParenthesis, condition, rightP arenthesis, body);
3866 } finally {
3867 _inLoop = wasInLoop;
3868 }
3869 }
3870 /**
3871 * Parse a with clause.
3872 * <pre>
3873 * withClause ::=
3874 * 'with' typeName (',' typeName)
3875 * </pre>
3876 * @return the with clause that was parsed
3877 */
3878 WithClause parseWithClause() {
3879 Token with2 = expect(Keyword.WITH);
3880 List<TypeName> types = new List<TypeName>();
3881 types.add(parseTypeName());
3882 while (optional(TokenType.COMMA)) {
3883 types.add(parseTypeName());
3884 }
3885 return new WithClause.full(with2, types);
3886 }
3887 /**
3888 * Return the token that is immediately after the current token. This is equiv alent to{@link #peek(int) peek(1)}.
3889 * @return the token that is immediately after the current token
3890 */
3891 Token peek() => _currentToken.next;
3892 /**
3893 * Return the token that is the given distance after the current token.
3894 * @param distance the number of tokens to look ahead, where {@code 0} is the current token,{@code 1} is the next token, etc.
3895 * @return the token that is the given distance after the current token
3896 */
3897 Token peek2(int distance) {
3898 Token token = _currentToken;
3899 for (int i = 0; i < distance; i++) {
3900 token = token.next;
3901 }
3902 return token;
3903 }
3904 /**
3905 * Report an error with the given error code and arguments.
3906 * @param errorCode the error code of the error to be reported
3907 * @param node the node specifying the location of the error
3908 * @param arguments the arguments to the error, used to compose the error mess age
3909 */
3910 void reportError(ParserErrorCode errorCode, ASTNode node, List<Object> argumen ts) {
3911 _errorListener.onError(new AnalysisError.con2(_source, node.offset, node.len gth, errorCode, [arguments]));
3912 }
3913 /**
3914 * Report an error with the given error code and arguments.
3915 * @param errorCode the error code of the error to be reported
3916 * @param arguments the arguments to the error, used to compose the error mess age
3917 */
3918 void reportError4(ParserErrorCode errorCode, List<Object> arguments) {
3919 reportError5(errorCode, _currentToken, arguments);
3920 }
3921 /**
3922 * Report an error with the given error code and arguments.
3923 * @param errorCode the error code of the error to be reported
3924 * @param token the token specifying the location of the error
3925 * @param arguments the arguments to the error, used to compose the error mess age
3926 */
3927 void reportError5(ParserErrorCode errorCode, Token token, List<Object> argumen ts) {
3928 _errorListener.onError(new AnalysisError.con2(_source, token.offset, token.l ength, errorCode, [arguments]));
3929 }
3930 /**
3931 * Parse the 'final', 'const', 'var' or type preceding a variable declaration, starting at the
3932 * given token, without actually creating a type or changing the current token . Return the token
3933 * following the type that was parsed, or {@code null} if the given token is n ot the first token
3934 * in a valid type.
3935 * <pre>
3936 * finalConstVarOrType ::=
3937 * | 'final' type?
3938 * | 'const' type?
3939 * | 'var'
3940 * | type
3941 * </pre>
3942 * @param startToken the token at which parsing is to begin
3943 * @return the token following the type that was parsed
3944 */
3945 Token skipFinalConstVarOrType(Token startToken) {
3946 if (matches3(startToken, Keyword.FINAL) || matches3(startToken, Keyword.CONS T)) {
3947 Token next3 = startToken.next;
3948 if (matchesIdentifier2(next3.next) || matches4(next3.next, TokenType.LT) | | matches3(next3.next, Keyword.THIS)) {
3949 return skipTypeName(next3);
3950 }
3951 } else if (matches3(startToken, Keyword.VAR)) {
3952 return startToken.next;
3953 } else if (matchesIdentifier2(startToken)) {
3954 Token next4 = startToken.next;
3955 if (matchesIdentifier2(next4) || matches4(next4, TokenType.LT) || matches3 (next4, Keyword.THIS) || (matches4(next4, TokenType.PERIOD) && matchesIdentifier 2(next4.next) && (matchesIdentifier2(next4.next.next) || matches4(next4.next.nex t, TokenType.LT) || matches3(next4.next.next, Keyword.THIS)))) {
3956 return skipReturnType(startToken);
3957 }
3958 }
3959 return null;
3960 }
3961 /**
3962 * Parse a list of formal parameters, starting at the given token, without act ually creating a
3963 * formal parameter list or changing the current token. Return the token follo wing the formal
3964 * parameter list that was parsed, or {@code null} if the given token is not t he first token in a
3965 * valid list of formal parameter.
3966 * <p>
3967 * Note that unlike other skip methods, this method uses a heuristic. In the w orst case, the
3968 * parameters could be prefixed by metadata, which would require us to be able to skip arbitrary
3969 * expressions. Rather than duplicate the logic of most of the parse methods w e simply look for
3970 * something that is likely to be a list of parameters and then skip to return ing the token after
3971 * the closing parenthesis.
3972 * <p>
3973 * This method must be kept in sync with {@link #parseFormalParameterList()}.
3974 * <pre>
3975 * formalParameterList ::=
3976 * '(' ')'
3977 * | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
3978 * | '(' optionalFormalParameters ')'
3979 * normalFormalParameters ::=
3980 * normalFormalParameter (',' normalFormalParameter)
3981 * optionalFormalParameters ::=
3982 * optionalPositionalFormalParameters
3983 * | namedFormalParameters
3984 * optionalPositionalFormalParameters ::=
3985 * '[' defaultFormalParameter (',' defaultFormalParameter)* ']'
3986 * namedFormalParameters ::=
3987 * '{' defaultNamedParameter (',' defaultNamedParameter)* '}'
3988 * </pre>
3989 * @param startToken the token at which parsing is to begin
3990 * @return the token following the formal parameter list that was parsed
3991 */
3992 Token skipFormalParameterList(Token startToken) {
3993 if (!matches4(startToken, TokenType.OPEN_PAREN)) {
3994 return null;
3995 }
3996 Token next5 = startToken.next;
3997 if (matches4(next5, TokenType.CLOSE_PAREN)) {
3998 return next5.next;
3999 }
4000 if (matchesAny(next5, [TokenType.AT, TokenType.OPEN_SQUARE_BRACKET, TokenTyp e.OPEN_CURLY_BRACKET]) || matches3(next5, Keyword.VOID) || (matchesIdentifier2(n ext5) && (matchesAny(next5.next, [TokenType.COMMA, TokenType.CLOSE_PAREN])))) {
4001 return skipPastMatchingToken(startToken);
4002 }
4003 if (matchesIdentifier2(next5) && matches4(next5.next, TokenType.OPEN_PAREN)) {
4004 Token afterParameters = skipFormalParameterList(next5.next);
4005 if (afterParameters != null && (matchesAny(afterParameters, [TokenType.COM MA, TokenType.CLOSE_PAREN]))) {
4006 return skipPastMatchingToken(startToken);
4007 }
4008 }
4009 Token afterType = skipFinalConstVarOrType(next5);
4010 if (afterType == null) {
4011 return null;
4012 }
4013 if (skipSimpleIdentifier(afterType) == null) {
4014 return null;
4015 }
4016 return skipPastMatchingToken(startToken);
4017 }
4018 /**
4019 * If the given token is a begin token with an associated end token, then retu rn the token
4020 * following the end token. Otherwise, return {@code null}.
4021 * @param startToken the token that is assumed to be a being token
4022 * @return the token following the matching end token
4023 */
4024 Token skipPastMatchingToken(Token startToken) {
4025 if (startToken is! BeginToken) {
4026 return null;
4027 }
4028 Token closeParen = ((startToken as BeginToken)).endToken;
4029 if (closeParen == null) {
4030 return null;
4031 }
4032 return closeParen.next;
4033 }
4034 /**
4035 * Parse a prefixed identifier, starting at the given token, without actually creating a prefixed
4036 * identifier or changing the current token. Return the token following the pr efixed identifier
4037 * that was parsed, or {@code null} if the given token is not the first token in a valid prefixed
4038 * identifier.
4039 * <p>
4040 * This method must be kept in sync with {@link #parsePrefixedIdentifier()}.
4041 * <pre>
4042 * prefixedIdentifier ::=
4043 * identifier ('.' identifier)?
4044 * </pre>
4045 * @param startToken the token at which parsing is to begin
4046 * @return the token following the prefixed identifier that was parsed
4047 */
4048 Token skipPrefixedIdentifier(Token startToken) {
4049 Token token = skipSimpleIdentifier(startToken);
4050 if (token == null) {
4051 return null;
4052 } else if (!matches4(token, TokenType.PERIOD)) {
4053 return token;
4054 }
4055 return skipSimpleIdentifier(token.next);
4056 }
4057 /**
4058 * Parse a return type, starting at the given token, without actually creating a return type or
4059 * changing the current token. Return the token following the return type that was parsed, or{@code null} if the given token is not the first token in a valid return type.
4060 * <p>
4061 * This method must be kept in sync with {@link #parseReturnType()}.
4062 * <pre>
4063 * returnType ::=
4064 * 'void'
4065 * | type
4066 * </pre>
4067 * @param startToken the token at which parsing is to begin
4068 * @return the token following the return type that was parsed
4069 */
4070 Token skipReturnType(Token startToken) {
4071 if (matches3(startToken, Keyword.VOID)) {
4072 return startToken.next;
4073 } else {
4074 return skipTypeName(startToken);
4075 }
4076 }
4077 /**
4078 * Parse a simple identifier, starting at the given token, without actually cr eating a simple
4079 * identifier or changing the current token. Return the token following the si mple identifier that
4080 * was parsed, or {@code null} if the given token is not the first token in a valid simple
4081 * identifier.
4082 * <p>
4083 * This method must be kept in sync with {@link #parseSimpleIdentifier()}.
4084 * <pre>
4085 * identifier ::=
4086 * IDENTIFIER
4087 * </pre>
4088 * @param startToken the token at which parsing is to begin
4089 * @return the token following the simple identifier that was parsed
4090 */
4091 Token skipSimpleIdentifier(Token startToken) {
4092 if (matches4(startToken, TokenType.IDENTIFIER) || (matches4(startToken, Toke nType.KEYWORD) && ((startToken as KeywordToken)).keyword.isPseudoKeyword())) {
4093 return startToken.next;
4094 }
4095 return null;
4096 }
4097 /**
4098 * Parse a string literal that contains interpolations, starting at the given token, without
4099 * actually creating a string literal or changing the current token. Return th e token following
4100 * the string literal that was parsed, or {@code null} if the given token is n ot the first token
4101 * in a valid string literal.
4102 * <p>
4103 * This method must be kept in sync with {@link #parseStringInterpolation(Toke n)}.
4104 * @param startToken the token at which parsing is to begin
4105 * @return the string literal that was parsed
4106 */
4107 Token skipStringInterpolation(Token startToken) {
4108 Token token = startToken;
4109 TokenType type23 = token.type;
4110 while (identical(type23, TokenType.STRING_INTERPOLATION_EXPRESSION) || ident ical(type23, TokenType.STRING_INTERPOLATION_IDENTIFIER)) {
4111 if (identical(type23, TokenType.STRING_INTERPOLATION_EXPRESSION)) {
4112 token = token.next;
4113 type23 = token.type;
4114 int bracketNestingLevel = 1;
4115 while (bracketNestingLevel > 0) {
4116 if (identical(type23, TokenType.EOF)) {
4117 return null;
4118 } else if (identical(type23, TokenType.OPEN_CURLY_BRACKET)) {
4119 bracketNestingLevel++;
4120 } else if (identical(type23, TokenType.CLOSE_CURLY_BRACKET)) {
4121 bracketNestingLevel--;
4122 } else if (identical(type23, TokenType.STRING)) {
4123 token = skipStringLiteral(token);
4124 if (token == null) {
4125 return null;
4126 }
4127 } else {
4128 token = token.next;
4129 }
4130 type23 = token.type;
4131 }
4132 token = token.next;
4133 type23 = token.type;
4134 } else {
4135 token = token.next;
4136 if (token.type != TokenType.IDENTIFIER) {
4137 return null;
4138 }
4139 token = token.next;
4140 }
4141 type23 = token.type;
4142 if (identical(type23, TokenType.STRING)) {
4143 token = token.next;
4144 type23 = token.type;
4145 }
4146 }
4147 return token;
4148 }
4149 /**
4150 * Parse a string literal, starting at the given token, without actually creat ing a string literal
4151 * or changing the current token. Return the token following the string litera l that was parsed,
4152 * or {@code null} if the given token is not the first token in a valid string literal.
4153 * <p>
4154 * This method must be kept in sync with {@link #parseStringLiteral()}.
4155 * <pre>
4156 * stringLiteral ::=
4157 * MULTI_LINE_STRING+
4158 * | SINGLE_LINE_STRING+
4159 * </pre>
4160 * @param startToken the token at which parsing is to begin
4161 * @return the token following the string literal that was parsed
4162 */
4163 Token skipStringLiteral(Token startToken) {
4164 Token token = startToken;
4165 while (token != null && matches4(token, TokenType.STRING)) {
4166 token = token.next;
4167 TokenType type24 = token.type;
4168 if (identical(type24, TokenType.STRING_INTERPOLATION_EXPRESSION) || identi cal(type24, TokenType.STRING_INTERPOLATION_IDENTIFIER)) {
4169 token = skipStringInterpolation(token);
4170 }
4171 }
4172 if (identical(token, startToken)) {
4173 return null;
4174 }
4175 return token;
4176 }
4177 /**
4178 * Parse a list of type arguments, starting at the given token, without actual ly creating a type argument list
4179 * or changing the current token. Return the token following the type argument list that was parsed,
4180 * or {@code null} if the given token is not the first token in a valid type a rgument list.
4181 * <p>
4182 * This method must be kept in sync with {@link #parseTypeArgumentList()}.
4183 * <pre>
4184 * typeArguments ::=
4185 * '<' typeList '>'
4186 * typeList ::=
4187 * type (',' type)
4188 * </pre>
4189 * @param startToken the token at which parsing is to begin
4190 * @return the token following the type argument list that was parsed
4191 */
4192 Token skipTypeArgumentList(Token startToken) {
4193 Token token = startToken;
4194 if (!matches4(token, TokenType.LT)) {
4195 return null;
4196 }
4197 token = skipTypeName(token.next);
4198 if (token == null) {
4199 return null;
4200 }
4201 while (matches4(token, TokenType.COMMA)) {
4202 token = skipTypeName(token.next);
4203 if (token == null) {
4204 return null;
4205 }
4206 }
4207 if (identical(token.type, TokenType.GT)) {
4208 return token.next;
4209 } else if (identical(token.type, TokenType.GT_GT)) {
4210 Token second = new Token(TokenType.GT, token.offset + 1);
4211 second.setNextWithoutSettingPrevious(token.next);
4212 return second;
4213 }
4214 return null;
4215 }
4216 /**
4217 * Parse a type name, starting at the given token, without actually creating a type name or
4218 * changing the current token. Return the token following the type name that w as parsed, or{@code null} if the given token is not the first token in a valid t ype name.
4219 * <p>
4220 * This method must be kept in sync with {@link #parseTypeName()}.
4221 * <pre>
4222 * type ::=
4223 * qualified typeArguments?
4224 * </pre>
4225 * @param startToken the token at which parsing is to begin
4226 * @return the token following the type name that was parsed
4227 */
4228 Token skipTypeName(Token startToken) {
4229 Token token = skipPrefixedIdentifier(startToken);
4230 if (token == null) {
4231 return null;
4232 }
4233 if (matches4(token, TokenType.LT)) {
4234 token = skipTypeArgumentList(token);
4235 }
4236 return token;
4237 }
4238 /**
4239 * Parse a list of type parameters, starting at the given token, without actua lly creating a type
4240 * parameter list or changing the current token. Return the token following th e type parameter
4241 * list that was parsed, or {@code null} if the given token is not the first t oken in a valid type
4242 * parameter list.
4243 * <p>
4244 * This method must be kept in sync with {@link #parseTypeParameterList()}.
4245 * <pre>
4246 * typeParameterList ::=
4247 * '<' typeParameter (',' typeParameter)* '>'
4248 * </pre>
4249 * @param startToken the token at which parsing is to begin
4250 * @return the token following the type parameter list that was parsed
4251 */
4252 Token skipTypeParameterList(Token startToken) {
4253 if (!matches4(startToken, TokenType.LT)) {
4254 return null;
4255 }
4256 int depth = 1;
4257 Token next6 = startToken.next;
4258 while (depth > 0) {
4259 if (matches4(next6, TokenType.EOF)) {
4260 return null;
4261 } else if (matches4(next6, TokenType.LT)) {
4262 depth++;
4263 } else if (matches4(next6, TokenType.GT)) {
4264 depth--;
4265 } else if (matches4(next6, TokenType.GT_EQ)) {
4266 if (depth == 1) {
4267 Token fakeEquals = new Token(TokenType.EQ, next6.offset + 2);
4268 fakeEquals.setNextWithoutSettingPrevious(next6.next);
4269 return fakeEquals;
4270 }
4271 depth--;
4272 } else if (matches4(next6, TokenType.GT_GT)) {
4273 depth -= 2;
4274 } else if (matches4(next6, TokenType.GT_GT_EQ)) {
4275 if (depth < 2) {
4276 return null;
4277 } else if (depth == 2) {
4278 Token fakeEquals = new Token(TokenType.EQ, next6.offset + 2);
4279 fakeEquals.setNextWithoutSettingPrevious(next6.next);
4280 return fakeEquals;
4281 }
4282 depth -= 2;
4283 }
4284 next6 = next6.next;
4285 }
4286 return next6;
4287 }
4288 /**
4289 * Translate the characters at the given index in the given string, appending the translated
4290 * character to the given builder. The index is assumed to be valid.
4291 * @param builder the builder to which the translated character is to be appen ded
4292 * @param lexeme the string containing the character(s) to be translated
4293 * @param index the index of the character to be translated
4294 * @return the index of the next character to be translated
4295 */
4296 int translateCharacter(JavaStringBuilder builder, String lexeme, int index) {
4297 int currentChar = lexeme.codeUnitAt(index);
4298 if (currentChar != 0x5C) {
4299 builder.appendChar(currentChar);
4300 return index + 1;
4301 }
4302 int length8 = lexeme.length;
4303 int currentIndex = index + 1;
4304 if (currentIndex >= length8) {
4305 return length8;
4306 }
4307 currentChar = lexeme.codeUnitAt(currentIndex);
4308 if (currentChar == 0x6E) {
4309 builder.appendChar(0xA);
4310 } else if (currentChar == 0x72) {
4311 builder.appendChar(0xD);
4312 } else if (currentChar == 0x66) {
4313 builder.appendChar(0xC);
4314 } else if (currentChar == 0x62) {
4315 builder.appendChar(0x8);
4316 } else if (currentChar == 0x74) {
4317 builder.appendChar(0x9);
4318 } else if (currentChar == 0x76) {
4319 builder.appendChar(0xB);
4320 } else if (currentChar == 0x78) {
4321 if (currentIndex + 2 >= length8) {
4322 reportError4(ParserErrorCode.INVALID_HEX_ESCAPE, []);
4323 return length8;
4324 }
4325 int firstDigit = lexeme.codeUnitAt(currentIndex + 1);
4326 int secondDigit = lexeme.codeUnitAt(currentIndex + 2);
4327 if (!isHexDigit(firstDigit) || !isHexDigit(secondDigit)) {
4328 reportError4(ParserErrorCode.INVALID_HEX_ESCAPE, []);
4329 } else {
4330 builder.appendChar((((Character.digit(firstDigit, 16) << 4) + Character. digit(secondDigit, 16)) as int));
4331 }
4332 return currentIndex + 3;
4333 } else if (currentChar == 0x75) {
4334 currentIndex++;
4335 if (currentIndex >= length8) {
4336 reportError4(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
4337 return length8;
4338 }
4339 currentChar = lexeme.codeUnitAt(currentIndex);
4340 if (currentChar == 0x7B) {
4341 currentIndex++;
4342 if (currentIndex >= length8) {
4343 reportError4(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
4344 return length8;
4345 }
4346 currentChar = lexeme.codeUnitAt(currentIndex);
4347 int digitCount = 0;
4348 int value = 0;
4349 while (currentChar != 0x7D) {
4350 if (!isHexDigit(currentChar)) {
4351 reportError4(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
4352 currentIndex++;
4353 while (currentIndex < length8 && lexeme.codeUnitAt(currentIndex) != 0x7D) {
4354 currentIndex++;
4355 }
4356 return currentIndex + 1;
4357 }
4358 digitCount++;
4359 value = (value << 4) + Character.digit(currentChar, 16);
4360 currentIndex++;
4361 if (currentIndex >= length8) {
4362 reportError4(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
4363 return length8;
4364 }
4365 currentChar = lexeme.codeUnitAt(currentIndex);
4366 }
4367 if (digitCount < 1 || digitCount > 6) {
4368 reportError4(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
4369 }
4370 appendScalarValue(builder, lexeme.substring(index, currentIndex + 1), va lue, index, currentIndex);
4371 return currentIndex + 1;
4372 } else {
4373 if (currentIndex + 3 >= length8) {
4374 reportError4(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
4375 return length8;
4376 }
4377 int firstDigit = currentChar;
4378 int secondDigit = lexeme.codeUnitAt(currentIndex + 1);
4379 int thirdDigit = lexeme.codeUnitAt(currentIndex + 2);
4380 int fourthDigit = lexeme.codeUnitAt(currentIndex + 3);
4381 if (!isHexDigit(firstDigit) || !isHexDigit(secondDigit) || !isHexDigit(t hirdDigit) || !isHexDigit(fourthDigit)) {
4382 reportError4(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
4383 } else {
4384 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);
4385 }
4386 return currentIndex + 4;
4387 }
4388 } else {
4389 builder.appendChar(currentChar);
4390 }
4391 return currentIndex + 1;
4392 }
4393 /**
4394 * Validate that the given parameter list does not contain any field initializ ers.
4395 * @param parameterList the parameter list to be validated
4396 */
4397 void validateFormalParameterList(FormalParameterList parameterList) {
4398 for (FormalParameter parameter in parameterList.parameters) {
4399 if (parameter is FieldFormalParameter) {
4400 reportError(ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR, ((par ameter as FieldFormalParameter)).identifier, []);
4401 }
4402 }
4403 }
4404 /**
4405 * Validate that the given set of modifiers is appropriate for a class and ret urn the 'abstract'
4406 * keyword if there is one.
4407 * @param modifiers the modifiers being validated
4408 */
4409 Token validateModifiersForClass(Modifiers modifiers) {
4410 validateModifiersForTopLevelDeclaration(modifiers);
4411 if (modifiers.constKeyword != null) {
4412 reportError5(ParserErrorCode.CONST_CLASS, modifiers.constKeyword, []);
4413 }
4414 if (modifiers.externalKeyword != null) {
4415 reportError5(ParserErrorCode.EXTERNAL_CLASS, modifiers.externalKeyword, [] );
4416 }
4417 if (modifiers.finalKeyword != null) {
4418 reportError5(ParserErrorCode.FINAL_CLASS, modifiers.finalKeyword, []);
4419 }
4420 if (modifiers.varKeyword != null) {
4421 reportError5(ParserErrorCode.VAR_CLASS, modifiers.varKeyword, []);
4422 }
4423 return modifiers.abstractKeyword;
4424 }
4425 /**
4426 * Validate that the given set of modifiers is appropriate for a constructor a nd return the
4427 * 'const' keyword if there is one.
4428 * @param modifiers the modifiers being validated
4429 * @return the 'const' or 'final' keyword associated with the constructor
4430 */
4431 Token validateModifiersForConstructor(Modifiers modifiers) {
4432 if (modifiers.abstractKeyword != null) {
4433 reportError4(ParserErrorCode.ABSTRACT_CLASS_MEMBER, []);
4434 }
4435 if (modifiers.finalKeyword != null) {
4436 reportError5(ParserErrorCode.FINAL_CONSTRUCTOR, modifiers.finalKeyword, [] );
4437 }
4438 if (modifiers.staticKeyword != null) {
4439 reportError5(ParserErrorCode.STATIC_CONSTRUCTOR, modifiers.staticKeyword, []);
4440 }
4441 if (modifiers.varKeyword != null) {
4442 reportError5(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, modifiers.varKe yword, []);
4443 }
4444 Token externalKeyword6 = modifiers.externalKeyword;
4445 Token constKeyword4 = modifiers.constKeyword;
4446 Token factoryKeyword4 = modifiers.factoryKeyword;
4447 if (externalKeyword6 != null && constKeyword4 != null && constKeyword4.offse t < externalKeyword6.offset) {
4448 reportError5(ParserErrorCode.EXTERNAL_AFTER_CONST, externalKeyword6, []);
4449 }
4450 if (externalKeyword6 != null && factoryKeyword4 != null && factoryKeyword4.o ffset < externalKeyword6.offset) {
4451 reportError5(ParserErrorCode.EXTERNAL_AFTER_FACTORY, externalKeyword6, []) ;
4452 }
4453 return constKeyword4;
4454 }
4455 /**
4456 * Validate that the given set of modifiers is appropriate for a field and ret urn the 'final',
4457 * 'const' or 'var' keyword if there is one.
4458 * @param modifiers the modifiers being validated
4459 * @return the 'final', 'const' or 'var' keyword associated with the field
4460 */
4461 Token validateModifiersForField(Modifiers modifiers) {
4462 if (modifiers.abstractKeyword != null) {
4463 reportError4(ParserErrorCode.ABSTRACT_CLASS_MEMBER, []);
4464 }
4465 if (modifiers.externalKeyword != null) {
4466 reportError5(ParserErrorCode.EXTERNAL_FIELD, modifiers.externalKeyword, [] );
4467 }
4468 if (modifiers.factoryKeyword != null) {
4469 reportError5(ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.factoryKey word, []);
4470 }
4471 Token staticKeyword3 = modifiers.staticKeyword;
4472 Token constKeyword5 = modifiers.constKeyword;
4473 Token finalKeyword3 = modifiers.finalKeyword;
4474 Token varKeyword3 = modifiers.varKeyword;
4475 if (constKeyword5 != null) {
4476 if (finalKeyword3 != null) {
4477 reportError5(ParserErrorCode.CONST_AND_FINAL, finalKeyword3, []);
4478 }
4479 if (varKeyword3 != null) {
4480 reportError5(ParserErrorCode.CONST_AND_VAR, varKeyword3, []);
4481 }
4482 if (staticKeyword3 != null && constKeyword5.offset < staticKeyword3.offset ) {
4483 reportError5(ParserErrorCode.STATIC_AFTER_CONST, staticKeyword3, []);
4484 }
4485 } else if (finalKeyword3 != null) {
4486 if (varKeyword3 != null) {
4487 reportError5(ParserErrorCode.FINAL_AND_VAR, varKeyword3, []);
4488 }
4489 if (staticKeyword3 != null && finalKeyword3.offset < staticKeyword3.offset ) {
4490 reportError5(ParserErrorCode.STATIC_AFTER_FINAL, staticKeyword3, []);
4491 }
4492 } else if (varKeyword3 != null && staticKeyword3 != null && varKeyword3.offs et < staticKeyword3.offset) {
4493 reportError5(ParserErrorCode.STATIC_AFTER_VAR, staticKeyword3, []);
4494 }
4495 return lexicallyFirst([constKeyword5, finalKeyword3, varKeyword3]);
4496 }
4497 /**
4498 * Validate that the given set of modifiers is appropriate for a getter, sette r, or method.
4499 * @param modifiers the modifiers being validated
4500 */
4501 void validateModifiersForGetterOrSetterOrMethod(Modifiers modifiers) {
4502 if (modifiers.abstractKeyword != null) {
4503 reportError4(ParserErrorCode.ABSTRACT_CLASS_MEMBER, []);
4504 }
4505 if (modifiers.constKeyword != null) {
4506 reportError5(ParserErrorCode.CONST_METHOD, modifiers.constKeyword, []);
4507 }
4508 if (modifiers.factoryKeyword != null) {
4509 reportError5(ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.factoryKey word, []);
4510 }
4511 if (modifiers.finalKeyword != null) {
4512 reportError5(ParserErrorCode.FINAL_METHOD, modifiers.finalKeyword, []);
4513 }
4514 if (modifiers.varKeyword != null) {
4515 reportError5(ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword, []);
4516 }
4517 Token externalKeyword7 = modifiers.externalKeyword;
4518 Token staticKeyword4 = modifiers.staticKeyword;
4519 if (externalKeyword7 != null && staticKeyword4 != null && staticKeyword4.off set < externalKeyword7.offset) {
4520 reportError5(ParserErrorCode.EXTERNAL_AFTER_STATIC, externalKeyword7, []);
4521 }
4522 }
4523 /**
4524 * Validate that the given set of modifiers is appropriate for a getter, sette r, or method.
4525 * @param modifiers the modifiers being validated
4526 */
4527 void validateModifiersForOperator(Modifiers modifiers) {
4528 if (modifiers.abstractKeyword != null) {
4529 reportError4(ParserErrorCode.ABSTRACT_CLASS_MEMBER, []);
4530 }
4531 if (modifiers.constKeyword != null) {
4532 reportError5(ParserErrorCode.CONST_METHOD, modifiers.constKeyword, []);
4533 }
4534 if (modifiers.factoryKeyword != null) {
4535 reportError5(ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.factoryKey word, []);
4536 }
4537 if (modifiers.finalKeyword != null) {
4538 reportError5(ParserErrorCode.FINAL_METHOD, modifiers.finalKeyword, []);
4539 }
4540 if (modifiers.staticKeyword != null) {
4541 reportError5(ParserErrorCode.STATIC_OPERATOR, modifiers.staticKeyword, []) ;
4542 }
4543 if (modifiers.varKeyword != null) {
4544 reportError5(ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword, []);
4545 }
4546 }
4547 /**
4548 * Validate that the given set of modifiers is appropriate for a top-level dec laration.
4549 * @param modifiers the modifiers being validated
4550 */
4551 void validateModifiersForTopLevelDeclaration(Modifiers modifiers) {
4552 if (modifiers.factoryKeyword != null) {
4553 reportError5(ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION, modifiers.fact oryKeyword, []);
4554 }
4555 if (modifiers.staticKeyword != null) {
4556 reportError5(ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION, modifiers.stati cKeyword, []);
4557 }
4558 }
4559 /**
4560 * Validate that the given set of modifiers is appropriate for a top-level fun ction.
4561 * @param modifiers the modifiers being validated
4562 */
4563 void validateModifiersForTopLevelFunction(Modifiers modifiers) {
4564 validateModifiersForTopLevelDeclaration(modifiers);
4565 if (modifiers.abstractKeyword != null) {
4566 reportError4(ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION, []);
4567 }
4568 if (modifiers.constKeyword != null) {
4569 reportError5(ParserErrorCode.CONST_CLASS, modifiers.constKeyword, []);
4570 }
4571 if (modifiers.finalKeyword != null) {
4572 reportError5(ParserErrorCode.FINAL_CLASS, modifiers.finalKeyword, []);
4573 }
4574 if (modifiers.varKeyword != null) {
4575 reportError5(ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword, []);
4576 }
4577 }
4578 /**
4579 * Validate that the given set of modifiers is appropriate for a field and ret urn the 'final',
4580 * 'const' or 'var' keyword if there is one.
4581 * @param modifiers the modifiers being validated
4582 * @return the 'final', 'const' or 'var' keyword associated with the field
4583 */
4584 Token validateModifiersForTopLevelVariable(Modifiers modifiers) {
4585 validateModifiersForTopLevelDeclaration(modifiers);
4586 if (modifiers.abstractKeyword != null) {
4587 reportError4(ParserErrorCode.ABSTRACT_TOP_LEVEL_VARIABLE, []);
4588 }
4589 if (modifiers.externalKeyword != null) {
4590 reportError5(ParserErrorCode.EXTERNAL_FIELD, modifiers.externalKeyword, [] );
4591 }
4592 Token constKeyword6 = modifiers.constKeyword;
4593 Token finalKeyword4 = modifiers.finalKeyword;
4594 Token varKeyword4 = modifiers.varKeyword;
4595 if (constKeyword6 != null) {
4596 if (finalKeyword4 != null) {
4597 reportError5(ParserErrorCode.CONST_AND_FINAL, finalKeyword4, []);
4598 }
4599 if (varKeyword4 != null) {
4600 reportError5(ParserErrorCode.CONST_AND_VAR, varKeyword4, []);
4601 }
4602 } else if (finalKeyword4 != null) {
4603 if (varKeyword4 != null) {
4604 reportError5(ParserErrorCode.FINAL_AND_VAR, varKeyword4, []);
4605 }
4606 }
4607 return lexicallyFirst([constKeyword6, finalKeyword4, varKeyword4]);
4608 }
4609 /**
4610 * Validate that the given set of modifiers is appropriate for a class and ret urn the 'abstract'
4611 * keyword if there is one.
4612 * @param modifiers the modifiers being validated
4613 */
4614 void validateModifiersForTypedef(Modifiers modifiers) {
4615 validateModifiersForTopLevelDeclaration(modifiers);
4616 if (modifiers.abstractKeyword != null) {
4617 reportError5(ParserErrorCode.ABSTRACT_TYPEDEF, modifiers.abstractKeyword, []);
4618 }
4619 if (modifiers.constKeyword != null) {
4620 reportError5(ParserErrorCode.CONST_TYPEDEF, modifiers.constKeyword, []);
4621 }
4622 if (modifiers.externalKeyword != null) {
4623 reportError5(ParserErrorCode.EXTERNAL_TYPEDEF, modifiers.externalKeyword, []);
4624 }
4625 if (modifiers.finalKeyword != null) {
4626 reportError5(ParserErrorCode.FINAL_TYPEDEF, modifiers.finalKeyword, []);
4627 }
4628 if (modifiers.varKeyword != null) {
4629 reportError5(ParserErrorCode.VAR_TYPEDEF, modifiers.varKeyword, []);
4630 }
4631 }
4632 }
4633 class AnalysisErrorListener_7 implements AnalysisErrorListener {
4634 List<bool> errorFound;
4635 AnalysisErrorListener_7(this.errorFound);
4636 void onError(AnalysisError error) {
4637 errorFound[0] = true;
4638 }
4639 }
4640 /**
4641 * The enumeration {@code ParserErrorCode} defines the error codes used for erro rs detected by the
4642 * parser. The convention for this class is for the name of the error code to in dicate the problem
4643 * that caused the error to be generated and for the error message to explain wh at is wrong and,
4644 * when appropriate, how the problem can be corrected.
4645 * @coverage dart.engine.parser
4646 */
4647 class ParserErrorCode implements ErrorCode {
4648 static final ParserErrorCode ABSTRACT_CLASS_MEMBER = new ParserErrorCode.con2( 'ABSTRACT_CLASS_MEMBER', 0, "Members of classes cannot be declared to be 'abstra ct'");
4649 static final ParserErrorCode ABSTRACT_STATIC_METHOD = new ParserErrorCode.con2 ('ABSTRACT_STATIC_METHOD', 1, "Static methods cannot be declared to be 'abstract '");
4650 static final ParserErrorCode ABSTRACT_TOP_LEVEL_FUNCTION = new ParserErrorCode .con2('ABSTRACT_TOP_LEVEL_FUNCTION', 2, "Top-level functions cannot be declared to be 'abstract'");
4651 static final ParserErrorCode ABSTRACT_TOP_LEVEL_VARIABLE = new ParserErrorCode .con2('ABSTRACT_TOP_LEVEL_VARIABLE', 3, "Top-level variables cannot be declared to be 'abstract'");
4652 static final ParserErrorCode ABSTRACT_TYPEDEF = new ParserErrorCode.con2('ABST RACT_TYPEDEF', 4, "Type aliases cannot be declared to be 'abstract'");
4653 static final ParserErrorCode BREAK_OUTSIDE_OF_LOOP = new ParserErrorCode.con2( 'BREAK_OUTSIDE_OF_LOOP', 5, "A break statement cannot be used outside of a loop or switch statement");
4654 static final ParserErrorCode CONST_AND_FINAL = new ParserErrorCode.con2('CONST _AND_FINAL', 6, "Members cannot be declared to be both 'const' and 'final'");
4655 static final ParserErrorCode CONST_AND_VAR = new ParserErrorCode.con2('CONST_A ND_VAR', 7, "Members cannot be declared to be both 'const' and 'var'");
4656 static final ParserErrorCode CONST_CLASS = new ParserErrorCode.con2('CONST_CLA SS', 8, "Classes cannot be declared to be 'const'");
4657 static final ParserErrorCode CONST_METHOD = new ParserErrorCode.con2('CONST_ME THOD', 9, "Getters, setters and methods cannot be declared to be 'const'");
4658 static final ParserErrorCode CONST_TYPEDEF = new ParserErrorCode.con2('CONST_T YPEDEF', 10, "Type aliases cannot be declared to be 'const'");
4659 static final ParserErrorCode CONSTRUCTOR_WITH_RETURN_TYPE = new ParserErrorCod e.con2('CONSTRUCTOR_WITH_RETURN_TYPE', 11, "Constructors cannot have a return ty pe");
4660 static final ParserErrorCode CONTINUE_OUTSIDE_OF_LOOP = new ParserErrorCode.co n2('CONTINUE_OUTSIDE_OF_LOOP', 12, "A continue statement cannot be used outside of a loop or switch statement");
4661 static final ParserErrorCode CONTINUE_WITHOUT_LABEL_IN_CASE = new ParserErrorC ode.con2('CONTINUE_WITHOUT_LABEL_IN_CASE', 13, "A continue statement in a switch statement must have a label as a target");
4662 static final ParserErrorCode DIRECTIVE_AFTER_DECLARATION = new ParserErrorCode .con2('DIRECTIVE_AFTER_DECLARATION', 14, "Directives must appear before any decl arations");
4663 static final ParserErrorCode DUPLICATE_LABEL_IN_SWITCH_STATEMENT = new ParserE rrorCode.con2('DUPLICATE_LABEL_IN_SWITCH_STATEMENT', 15, "The label %s was alrea dy used in this switch statement");
4664 static final ParserErrorCode DUPLICATED_MODIFIER = new ParserErrorCode.con2('D UPLICATED_MODIFIER', 16, "The modifier '%s' was already specified.");
4665 static final ParserErrorCode EXPECTED_CASE_OR_DEFAULT = new ParserErrorCode.co n2('EXPECTED_CASE_OR_DEFAULT', 17, "Expected 'case' or 'default'");
4666 static final ParserErrorCode EXPECTED_LIST_OR_MAP_LITERAL = new ParserErrorCod e.con2('EXPECTED_LIST_OR_MAP_LITERAL', 18, "Expected a list or map literal");
4667 static final ParserErrorCode EXPECTED_STRING_LITERAL = new ParserErrorCode.con 2('EXPECTED_STRING_LITERAL', 19, "Expected a string literal");
4668 static final ParserErrorCode EXPECTED_TOKEN = new ParserErrorCode.con2('EXPECT ED_TOKEN', 20, "Expected to find: %s");
4669 static final ParserErrorCode EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE = new Parse rErrorCode.con2('EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE', 21, "Export directives must preceed part directives");
4670 static final ParserErrorCode EXTERNAL_AFTER_CONST = new ParserErrorCode.con2(' EXTERNAL_AFTER_CONST', 22, "The modifier 'external' should be before the modifie r 'const'");
4671 static final ParserErrorCode EXTERNAL_AFTER_FACTORY = new ParserErrorCode.con2 ('EXTERNAL_AFTER_FACTORY', 23, "The modifier 'external' should be before the mod ifier 'factory'");
4672 static final ParserErrorCode EXTERNAL_AFTER_STATIC = new ParserErrorCode.con2( 'EXTERNAL_AFTER_STATIC', 24, "The modifier 'external' should be before the modif ier 'static'");
4673 static final ParserErrorCode EXTERNAL_CLASS = new ParserErrorCode.con2('EXTERN AL_CLASS', 25, "Classes cannot be declared to be 'external'");
4674 static final ParserErrorCode EXTERNAL_CONSTRUCTOR_WITH_BODY = new ParserErrorC ode.con2('EXTERNAL_CONSTRUCTOR_WITH_BODY', 26, "External constructors cannot hav e a body");
4675 static final ParserErrorCode EXTERNAL_FIELD = new ParserErrorCode.con2('EXTERN AL_FIELD', 27, "Fields cannot be declared to be 'external'");
4676 static final ParserErrorCode EXTERNAL_GETTER_WITH_BODY = new ParserErrorCode.c on2('EXTERNAL_GETTER_WITH_BODY', 28, "External getters cannot have a body");
4677 static final ParserErrorCode EXTERNAL_METHOD_WITH_BODY = new ParserErrorCode.c on2('EXTERNAL_METHOD_WITH_BODY', 29, "External methods cannot have a body");
4678 static final ParserErrorCode EXTERNAL_OPERATOR_WITH_BODY = new ParserErrorCode .con2('EXTERNAL_OPERATOR_WITH_BODY', 30, "External operators cannot have a body" );
4679 static final ParserErrorCode EXTERNAL_SETTER_WITH_BODY = new ParserErrorCode.c on2('EXTERNAL_SETTER_WITH_BODY', 31, "External setters cannot have a body");
4680 static final ParserErrorCode EXTERNAL_TYPEDEF = new ParserErrorCode.con2('EXTE RNAL_TYPEDEF', 32, "Type aliases cannot be declared to be 'external'");
4681 static final ParserErrorCode FACTORY_TOP_LEVEL_DECLARATION = new ParserErrorCo de.con2('FACTORY_TOP_LEVEL_DECLARATION', 33, "Top-level declarations cannot be d eclared to be 'factory'");
4682 static final ParserErrorCode FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR = new Parse rErrorCode.con2('FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR', 34, "Field initializers can only be used in a constructor");
4683 static final ParserErrorCode FINAL_AND_VAR = new ParserErrorCode.con2('FINAL_A ND_VAR', 35, "Members cannot be declared to be both 'final' and 'var'");
4684 static final ParserErrorCode FINAL_CLASS = new ParserErrorCode.con2('FINAL_CLA SS', 36, "Classes cannot be declared to be 'final'");
4685 static final ParserErrorCode FINAL_CONSTRUCTOR = new ParserErrorCode.con2('FIN AL_CONSTRUCTOR', 37, "A constructor cannot be declared to be 'final'");
4686 static final ParserErrorCode FINAL_METHOD = new ParserErrorCode.con2('FINAL_ME THOD', 38, "Getters, setters and methods cannot be declared to be 'final'");
4687 static final ParserErrorCode FINAL_TYPEDEF = new ParserErrorCode.con2('FINAL_T YPEDEF', 39, "Type aliases cannot be declared to be 'final'");
4688 static final ParserErrorCode GETTER_WITH_PARAMETERS = new ParserErrorCode.con2 ('GETTER_WITH_PARAMETERS', 40, "Getter should be declared without a parameter li st");
4689 static final ParserErrorCode ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE = new Parser ErrorCode.con2('ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE', 41, "Illegal assignment t o non-assignable expression");
4690 static final ParserErrorCode IMPLEMENTS_BEFORE_EXTENDS = new ParserErrorCode.c on2('IMPLEMENTS_BEFORE_EXTENDS', 42, "The extends clause must be before the impl ements clause");
4691 static final ParserErrorCode IMPLEMENTS_BEFORE_WITH = new ParserErrorCode.con2 ('IMPLEMENTS_BEFORE_WITH', 43, "The with clause must be before the implements cl ause");
4692 static final ParserErrorCode IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE = new Parse rErrorCode.con2('IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE', 44, "Import directives must preceed part directives");
4693 static final ParserErrorCode INITIALIZED_VARIABLE_IN_FOR_EACH = new ParserErro rCode.con2('INITIALIZED_VARIABLE_IN_FOR_EACH', 45, "The loop variable in a for-e ach loop cannot be initialized");
4694 static final ParserErrorCode INVALID_CODE_POINT = new ParserErrorCode.con2('IN VALID_CODE_POINT', 46, "The escape sequence '%s' is not a valid code point");
4695 static final ParserErrorCode INVALID_COMMENT_REFERENCE = new ParserErrorCode.c on2('INVALID_COMMENT_REFERENCE', 47, "Comment references should contain a possib ly prefixed identifier and can start with 'new', but should not contain anything else");
4696 static final ParserErrorCode INVALID_HEX_ESCAPE = new ParserErrorCode.con2('IN VALID_HEX_ESCAPE', 48, "An escape sequence starting with '\\x' must be followed by 2 hexidecimal digits");
4697 static final ParserErrorCode INVALID_OPERATOR_FOR_SUPER = new ParserErrorCode. con2('INVALID_OPERATOR_FOR_SUPER', 49, "The operator '%s' cannot be used with 's uper'");
4698 static final ParserErrorCode INVALID_UNICODE_ESCAPE = new ParserErrorCode.con2 ('INVALID_UNICODE_ESCAPE', 50, "An escape sequence starting with '\\u' must be f ollowed by 4 hexidecimal digits or from 1 to 6 digits between '{' and '}'");
4699 static final ParserErrorCode LIBRARY_DIRECTIVE_NOT_FIRST = new ParserErrorCode .con2('LIBRARY_DIRECTIVE_NOT_FIRST', 51, "The library directive must appear befo re all other directives");
4700 static final ParserErrorCode MISSING_ASSIGNABLE_SELECTOR = new ParserErrorCode .con2('MISSING_ASSIGNABLE_SELECTOR', 52, "Missing selector such as \".<identifie r>\" or \"[0]\"");
4701 static final ParserErrorCode MISSING_CATCH_OR_FINALLY = new ParserErrorCode.co n2('MISSING_CATCH_OR_FINALLY', 53, "A try statement must have either a catch or finally clause");
4702 static final ParserErrorCode MISSING_CLASS_BODY = new ParserErrorCode.con2('MI SSING_CLASS_BODY', 54, "A class definition must have a body, even if it is empty ");
4703 static final ParserErrorCode MISSING_CONST_FINAL_VAR_OR_TYPE = new ParserError Code.con2('MISSING_CONST_FINAL_VAR_OR_TYPE', 55, "Variables must be declared usi ng the keywords 'const', 'final', 'var' or a type name");
4704 static final ParserErrorCode MISSING_FUNCTION_BODY = new ParserErrorCode.con2( 'MISSING_FUNCTION_BODY', 56, "A function body must be provided");
4705 static final ParserErrorCode MISSING_FUNCTION_PARAMETERS = new ParserErrorCode .con2('MISSING_FUNCTION_PARAMETERS', 57, "Functions must have an explicit list o f parameters");
4706 static final ParserErrorCode MISSING_IDENTIFIER = new ParserErrorCode.con2('MI SSING_IDENTIFIER', 58, "Expected an identifier");
4707 static final ParserErrorCode MISSING_NAME_IN_LIBRARY_DIRECTIVE = new ParserErr orCode.con2('MISSING_NAME_IN_LIBRARY_DIRECTIVE', 59, "Library directives must in clude a library name");
4708 static final ParserErrorCode MISSING_NAME_IN_PART_OF_DIRECTIVE = new ParserErr orCode.con2('MISSING_NAME_IN_PART_OF_DIRECTIVE', 60, "Library directives must in clude a library name");
4709 static final ParserErrorCode MISSING_TERMINATOR_FOR_PARAMETER_GROUP = new Pars erErrorCode.con2('MISSING_TERMINATOR_FOR_PARAMETER_GROUP', 61, "There is no '%s' to close the parameter group");
4710 static final ParserErrorCode MISSING_TYPEDEF_PARAMETERS = new ParserErrorCode. con2('MISSING_TYPEDEF_PARAMETERS', 62, "Type aliases for functions must have an explicit list of parameters");
4711 static final ParserErrorCode MISSING_VARIABLE_IN_FOR_EACH = new ParserErrorCod e.con2('MISSING_VARIABLE_IN_FOR_EACH', 63, "A loop variable must be declared in a for-each loop before the 'in', but none were found");
4712 static final ParserErrorCode MIXED_PARAMETER_GROUPS = new ParserErrorCode.con2 ('MIXED_PARAMETER_GROUPS', 64, "Cannot have both positional and named parameters in a single parameter list");
4713 static final ParserErrorCode MULTIPLE_EXTENDS_CLAUSES = new ParserErrorCode.co n2('MULTIPLE_EXTENDS_CLAUSES', 65, "Each class definition can have at most one e xtends clause");
4714 static final ParserErrorCode MULTIPLE_IMPLEMENTS_CLAUSES = new ParserErrorCode .con2('MULTIPLE_IMPLEMENTS_CLAUSES', 66, "Each class definition can have at most one implements clause");
4715 static final ParserErrorCode MULTIPLE_LIBRARY_DIRECTIVES = new ParserErrorCode .con2('MULTIPLE_LIBRARY_DIRECTIVES', 67, "Only one library directive may be decl ared in a file");
4716 static final ParserErrorCode MULTIPLE_NAMED_PARAMETER_GROUPS = new ParserError Code.con2('MULTIPLE_NAMED_PARAMETER_GROUPS', 68, "Cannot have multiple groups of named parameters in a single parameter list");
4717 static final ParserErrorCode MULTIPLE_PART_OF_DIRECTIVES = new ParserErrorCode .con2('MULTIPLE_PART_OF_DIRECTIVES', 69, "Only one part-of directive may be decl ared in a file");
4718 static final ParserErrorCode MULTIPLE_POSITIONAL_PARAMETER_GROUPS = new Parser ErrorCode.con2('MULTIPLE_POSITIONAL_PARAMETER_GROUPS', 70, "Cannot have multiple groups of positional parameters in a single parameter list");
4719 static final ParserErrorCode MULTIPLE_VARIABLES_IN_FOR_EACH = new ParserErrorC ode.con2('MULTIPLE_VARIABLES_IN_FOR_EACH', 71, "A single loop variable must be d eclared in a for-each loop before the 'in', but %s were found");
4720 static final ParserErrorCode MULTIPLE_WITH_CLAUSES = new ParserErrorCode.con2( 'MULTIPLE_WITH_CLAUSES', 72, "Each class definition can have at most one with cl ause");
4721 static final ParserErrorCode NAMED_PARAMETER_OUTSIDE_GROUP = new ParserErrorCo de.con2('NAMED_PARAMETER_OUTSIDE_GROUP', 73, "Named parameters must be enclosed in curly braces ('{' and '}')");
4722 static final ParserErrorCode NON_CONSTRUCTOR_FACTORY = new ParserErrorCode.con 2('NON_CONSTRUCTOR_FACTORY', 74, "Only constructors can be declared to be a 'fac tory'");
4723 static final ParserErrorCode NON_IDENTIFIER_LIBRARY_NAME = new ParserErrorCode .con2('NON_IDENTIFIER_LIBRARY_NAME', 75, "The name of a library must be an ident ifier");
4724 static final ParserErrorCode NON_PART_OF_DIRECTIVE_IN_PART = new ParserErrorCo de.con2('NON_PART_OF_DIRECTIVE_IN_PART', 76, "The part-of directive must be the only directive in a part");
4725 static final ParserErrorCode NON_USER_DEFINABLE_OPERATOR = new ParserErrorCode .con2('NON_USER_DEFINABLE_OPERATOR', 77, "The operator '%s' is not user definabl e");
4726 static final ParserErrorCode POSITIONAL_AFTER_NAMED_ARGUMENT = new ParserError Code.con2('POSITIONAL_AFTER_NAMED_ARGUMENT', 78, "Positional arguments must occu r before named arguments");
4727 static final ParserErrorCode POSITIONAL_PARAMETER_OUTSIDE_GROUP = new ParserEr rorCode.con2('POSITIONAL_PARAMETER_OUTSIDE_GROUP', 79, "Positional parameters mu st be enclosed in square brackets ('[' and ']')");
4728 static final ParserErrorCode STATIC_AFTER_CONST = new ParserErrorCode.con2('ST ATIC_AFTER_CONST', 80, "The modifier 'static' should be before the modifier 'con st'");
4729 static final ParserErrorCode STATIC_AFTER_FINAL = new ParserErrorCode.con2('ST ATIC_AFTER_FINAL', 81, "The modifier 'static' should be before the modifier 'fin al'");
4730 static final ParserErrorCode STATIC_AFTER_VAR = new ParserErrorCode.con2('STAT IC_AFTER_VAR', 82, "The modifier 'static' should be before the modifier 'var'");
4731 static final ParserErrorCode STATIC_CONSTRUCTOR = new ParserErrorCode.con2('ST ATIC_CONSTRUCTOR', 83, "Constructors cannot be static");
4732 static final ParserErrorCode STATIC_OPERATOR = new ParserErrorCode.con2('STATI C_OPERATOR', 84, "Operators cannot be static");
4733 static final ParserErrorCode STATIC_TOP_LEVEL_DECLARATION = new ParserErrorCod e.con2('STATIC_TOP_LEVEL_DECLARATION', 85, "Top-level declarations cannot be dec lared to be 'static'");
4734 static final ParserErrorCode UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP = new P arserErrorCode.con2('UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP', 86, "There is n o '%s' to open a parameter group");
4735 static final ParserErrorCode UNEXPECTED_TOKEN = new ParserErrorCode.con2('UNEX PECTED_TOKEN', 87, "Unexpected token '%s'");
4736 static final ParserErrorCode USE_OF_UNARY_PLUS_OPERATOR = new ParserErrorCode. con2('USE_OF_UNARY_PLUS_OPERATOR', 88, "There is no unary plus operator in Dart" );
4737 static final ParserErrorCode WITH_BEFORE_EXTENDS = new ParserErrorCode.con2('W ITH_BEFORE_EXTENDS', 89, "The extends clause must be before the with clause");
4738 static final ParserErrorCode WITH_WITHOUT_EXTENDS = new ParserErrorCode.con2(' WITH_WITHOUT_EXTENDS', 90, "The with clause cannot be used without an extends cl ause");
4739 static final ParserErrorCode WRONG_SEPARATOR_FOR_NAMED_PARAMETER = new ParserE rrorCode.con2('WRONG_SEPARATOR_FOR_NAMED_PARAMETER', 91, "The default value of a named parameter should be preceeded by ':'");
4740 static final ParserErrorCode WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER = new Pa rserErrorCode.con2('WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER', 92, "The default value of a positional parameter should be preceeded by '='");
4741 static final ParserErrorCode WRONG_TERMINATOR_FOR_PARAMETER_GROUP = new Parser ErrorCode.con2('WRONG_TERMINATOR_FOR_PARAMETER_GROUP', 93, "Expected '%s' to clo se parameter group");
4742 static final ParserErrorCode VAR_CLASS = new ParserErrorCode.con2('VAR_CLASS', 94, "Classes cannot be declared to be 'var'");
4743 static final ParserErrorCode VAR_RETURN_TYPE = new ParserErrorCode.con2('VAR_R ETURN_TYPE', 95, "The return type cannot be 'var'");
4744 static final ParserErrorCode VAR_TYPEDEF = new ParserErrorCode.con2('VAR_TYPED EF', 96, "Type aliases cannot be declared to be 'var'");
4745 static final ParserErrorCode VOID_PARAMETER = new ParserErrorCode.con2('VOID_P ARAMETER', 97, "Parameters cannot have a type of 'void'");
4746 static final ParserErrorCode VOID_VARIABLE = new ParserErrorCode.con2('VOID_VA RIABLE', 98, "Variables cannot have a type of 'void'");
4747 static final List<ParserErrorCode> values = [ABSTRACT_CLASS_MEMBER, ABSTRACT_S TATIC_METHOD, ABSTRACT_TOP_LEVEL_FUNCTION, ABSTRACT_TOP_LEVEL_VARIABLE, ABSTRACT _TYPEDEF, BREAK_OUTSIDE_OF_LOOP, CONST_AND_FINAL, CONST_AND_VAR, CONST_CLASS, CO NST_METHOD, CONST_TYPEDEF, CONSTRUCTOR_WITH_RETURN_TYPE, CONTINUE_OUTSIDE_OF_LOO P, CONTINUE_WITHOUT_LABEL_IN_CASE, DIRECTIVE_AFTER_DECLARATION, DUPLICATE_LABEL_ IN_SWITCH_STATEMENT, DUPLICATED_MODIFIER, EXPECTED_CASE_OR_DEFAULT, EXPECTED_LIS T_OR_MAP_LITERAL, EXPECTED_STRING_LITERAL, EXPECTED_TOKEN, EXPORT_DIRECTIVE_AFTE R_PART_DIRECTIVE, EXTERNAL_AFTER_CONST, EXTERNAL_AFTER_FACTORY, EXTERNAL_AFTER_S TATIC, EXTERNAL_CLASS, EXTERNAL_CONSTRUCTOR_WITH_BODY, EXTERNAL_FIELD, EXTERNAL_ GETTER_WITH_BODY, EXTERNAL_METHOD_WITH_BODY, EXTERNAL_OPERATOR_WITH_BODY, EXTERN AL_SETTER_WITH_BODY, EXTERNAL_TYPEDEF, FACTORY_TOP_LEVEL_DECLARATION, FIELD_INIT IALIZER_OUTSIDE_CONSTRUCTOR, FINAL_AND_VAR, FINAL_CLASS, FINAL_CONSTRUCTOR, FINA L_METHOD, FINAL_TYPEDEF, GETTER_WITH_PARAMETERS, ILLEGAL_ASSIGNMENT_TO_NON_ASSIG NABLE, IMPLEMENTS_BEFORE_EXTENDS, IMPLEMENTS_BEFORE_WITH, IMPORT_DIRECTIVE_AFTER _PART_DIRECTIVE, INITIALIZED_VARIABLE_IN_FOR_EACH, INVALID_CODE_POINT, INVALID_C OMMENT_REFERENCE, INVALID_HEX_ESCAPE, INVALID_OPERATOR_FOR_SUPER, INVALID_UNICOD E_ESCAPE, LIBRARY_DIRECTIVE_NOT_FIRST, MISSING_ASSIGNABLE_SELECTOR, MISSING_CATC H_OR_FINALLY, MISSING_CLASS_BODY, MISSING_CONST_FINAL_VAR_OR_TYPE, MISSING_FUNCT ION_BODY, MISSING_FUNCTION_PARAMETERS, MISSING_IDENTIFIER, MISSING_NAME_IN_LIBRA RY_DIRECTIVE, MISSING_NAME_IN_PART_OF_DIRECTIVE, MISSING_TERMINATOR_FOR_PARAMETE R_GROUP, MISSING_TYPEDEF_PARAMETERS, MISSING_VARIABLE_IN_FOR_EACH, MIXED_PARAMET ER_GROUPS, MULTIPLE_EXTENDS_CLAUSES, MULTIPLE_IMPLEMENTS_CLAUSES, MULTIPLE_LIBRA RY_DIRECTIVES, MULTIPLE_NAMED_PARAMETER_GROUPS, MULTIPLE_PART_OF_DIRECTIVES, MUL TIPLE_POSITIONAL_PARAMETER_GROUPS, MULTIPLE_VARIABLES_IN_FOR_EACH, MULTIPLE_WITH _CLAUSES, NAMED_PARAMETER_OUTSIDE_GROUP, NON_CONSTRUCTOR_FACTORY, NON_IDENTIFIER _LIBRARY_NAME, NON_PART_OF_DIRECTIVE_IN_PART, NON_USER_DEFINABLE_OPERATOR, POSIT IONAL_AFTER_NAMED_ARGUMENT, POSITIONAL_PARAMETER_OUTSIDE_GROUP, STATIC_AFTER_CON ST, STATIC_AFTER_FINAL, STATIC_AFTER_VAR, STATIC_CONSTRUCTOR, STATIC_OPERATOR, S TATIC_TOP_LEVEL_DECLARATION, UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP, UNEXPECT ED_TOKEN, USE_OF_UNARY_PLUS_OPERATOR, WITH_BEFORE_EXTENDS, WITH_WITHOUT_EXTENDS, WRONG_SEPARATOR_FOR_NAMED_PARAMETER, WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER, WRONG_TERMINATOR_FOR_PARAMETER_GROUP, VAR_CLASS, VAR_RETURN_TYPE, VAR_TYPEDEF, V OID_PARAMETER, VOID_VARIABLE];
4748 String __name;
4749 int __ordinal = 0;
4750 int get ordinal => __ordinal;
4751 /**
4752 * The severity of this error.
4753 */
4754 ErrorSeverity _severity;
4755 /**
4756 * The message template used to create the message to be displayed for this er ror.
4757 */
4758 String _message;
4759 /**
4760 * Initialize a newly created error code to have the given severity and messag e.
4761 * @param severity the severity of the error
4762 * @param message the message template used to create the message to be displa yed for the error
4763 */
4764 ParserErrorCode.con1(String ___name, int ___ordinal, ErrorSeverity severity2, String message2) {
4765 _jtd_constructor_258_impl(___name, ___ordinal, severity2, message2);
4766 }
4767 _jtd_constructor_258_impl(String ___name, int ___ordinal, ErrorSeverity severi ty2, String message2) {
4768 __name = ___name;
4769 __ordinal = ___ordinal;
4770 this._severity = severity2;
4771 this._message = message2;
4772 }
4773 /**
4774 * Initialize a newly created error code to have the given message and a sever ity of ERROR.
4775 * @param message the message template used to create the message to be displa yed for the error
4776 */
4777 ParserErrorCode.con2(String ___name, int ___ordinal, String message) {
4778 _jtd_constructor_259_impl(___name, ___ordinal, message);
4779 }
4780 _jtd_constructor_259_impl(String ___name, int ___ordinal, String message) {
4781 _jtd_constructor_258_impl(___name, ___ordinal, ErrorSeverity.ERROR, message) ;
4782 }
4783 ErrorSeverity get errorSeverity => _severity;
4784 String get message => _message;
4785 ErrorType get type => ErrorType.SYNTACTIC_ERROR;
4786 bool needsRecompilation() => true;
4787 String toString() => __name;
4788 }
4789 /**
4790 * Instances of the class {link ToFormattedSourceVisitor} write a source represe ntation of a visited
4791 * AST node (and all of it's children) to a writer.
4792 */
4793 class ToFormattedSourceVisitor implements ASTVisitor<Object> {
4794 /**
4795 * The writer to which the source is to be written.
4796 */
4797 PrintWriter _writer;
4798 int _indentLevel = 0;
4799 String _indentString = "";
4800 /**
4801 * Initialize a newly created visitor to write source code representing the vi sited nodes to the
4802 * given writer.
4803 * @param writer the writer to which the source is to be written
4804 */
4805 ToFormattedSourceVisitor(PrintWriter writer) {
4806 this._writer = writer;
4807 }
4808 Object visitAdjacentStrings(AdjacentStrings node) {
4809 visitList5(node.strings, " ");
4810 return null;
4811 }
4812 Object visitAnnotation(Annotation node) {
4813 _writer.print('@');
4814 visit(node.name);
4815 visit7(".", node.constructorName);
4816 visit(node.arguments);
4817 return null;
4818 }
4819 Object visitArgumentDefinitionTest(ArgumentDefinitionTest node) {
4820 _writer.print('?');
4821 visit(node.identifier);
4822 return null;
4823 }
4824 Object visitArgumentList(ArgumentList node) {
4825 _writer.print('(');
4826 visitList5(node.arguments, ", ");
4827 _writer.print(')');
4828 return null;
4829 }
4830 Object visitAsExpression(AsExpression node) {
4831 visit(node.expression);
4832 _writer.print(" as ");
4833 visit(node.type);
4834 return null;
4835 }
4836 Object visitAssertStatement(AssertStatement node) {
4837 _writer.print("assert(");
4838 visit(node.condition);
4839 _writer.print(");");
4840 return null;
4841 }
4842 Object visitAssignmentExpression(AssignmentExpression node) {
4843 visit(node.leftHandSide);
4844 _writer.print(' ');
4845 _writer.print(node.operator.lexeme);
4846 _writer.print(' ');
4847 visit(node.rightHandSide);
4848 return null;
4849 }
4850 Object visitBinaryExpression(BinaryExpression node) {
4851 visit(node.leftOperand);
4852 _writer.print(' ');
4853 _writer.print(node.operator.lexeme);
4854 _writer.print(' ');
4855 visit(node.rightOperand);
4856 return null;
4857 }
4858 Object visitBlock(Block node) {
4859 _writer.print('{');
4860 {
4861 indentInc();
4862 visitList5(node.statements, "\n");
4863 indentDec();
4864 }
4865 nl2();
4866 _writer.print('}');
4867 return null;
4868 }
4869 Object visitBlockFunctionBody(BlockFunctionBody node) {
4870 visit(node.block);
4871 return null;
4872 }
4873 Object visitBooleanLiteral(BooleanLiteral node) {
4874 _writer.print(node.literal.lexeme);
4875 return null;
4876 }
4877 Object visitBreakStatement(BreakStatement node) {
4878 _writer.print("break");
4879 visit7(" ", node.label);
4880 _writer.print(";");
4881 return null;
4882 }
4883 Object visitCascadeExpression(CascadeExpression node) {
4884 visit(node.target);
4885 visitList(node.cascadeSections);
4886 return null;
4887 }
4888 Object visitCatchClause(CatchClause node) {
4889 visit7("on ", node.exceptionType);
4890 if (node.catchKeyword != null) {
4891 if (node.exceptionType != null) {
4892 _writer.print(' ');
4893 }
4894 _writer.print("catch (");
4895 visit(node.exceptionParameter);
4896 visit7(", ", node.stackTraceParameter);
4897 _writer.print(") ");
4898 } else {
4899 _writer.print(" ");
4900 }
4901 visit(node.body);
4902 return null;
4903 }
4904 Object visitClassDeclaration(ClassDeclaration node) {
4905 visit(node.documentationComment);
4906 visit8(node.abstractKeyword, " ");
4907 _writer.print("class ");
4908 visit(node.name);
4909 visit(node.typeParameters);
4910 visit7(" ", node.extendsClause);
4911 visit7(" ", node.withClause);
4912 visit7(" ", node.implementsClause);
4913 _writer.print(" {");
4914 {
4915 indentInc();
4916 visitList5(node.members, "\n");
4917 indentDec();
4918 }
4919 nl2();
4920 _writer.print("}");
4921 return null;
4922 }
4923 Object visitClassTypeAlias(ClassTypeAlias node) {
4924 _writer.print("typedef ");
4925 visit(node.name);
4926 visit(node.typeParameters);
4927 _writer.print(" = ");
4928 if (node.abstractKeyword != null) {
4929 _writer.print("abstract ");
4930 }
4931 visit(node.superclass);
4932 visit7(" ", node.withClause);
4933 visit7(" ", node.implementsClause);
4934 _writer.print(";");
4935 return null;
4936 }
4937 Object visitComment(Comment node) {
4938 Token token = node.beginToken;
4939 while (token != null) {
4940 bool firstLine = true;
4941 for (String line in StringUtils.split(token.lexeme, "\n")) {
4942 if (firstLine) {
4943 firstLine = false;
4944 } else {
4945 line = " ${line.trim()}";
4946 line = StringUtils.replace(line, "/*", "/ *");
4947 }
4948 _writer.print(line);
4949 nl2();
4950 }
4951 if (identical(token, node.endToken)) {
4952 break;
4953 }
4954 }
4955 return null;
4956 }
4957 Object visitCommentReference(CommentReference node) => null;
4958 Object visitCompilationUnit(CompilationUnit node) {
4959 ScriptTag scriptTag7 = node.scriptTag;
4960 NodeList<Directive> directives4 = node.directives;
4961 visit(scriptTag7);
4962 String prefix = scriptTag7 == null ? "" : " ";
4963 visitList7(prefix, directives4, "\n");
4964 prefix = scriptTag7 == null && directives4.isEmpty ? "" : "\n\n";
4965 visitList7(prefix, node.declarations, "\n");
4966 return null;
4967 }
4968 Object visitConditionalExpression(ConditionalExpression node) {
4969 visit(node.condition);
4970 _writer.print(" ? ");
4971 visit(node.thenExpression);
4972 _writer.print(" : ");
4973 visit(node.elseExpression);
4974 return null;
4975 }
4976 Object visitConstructorDeclaration(ConstructorDeclaration node) {
4977 visit(node.documentationComment);
4978 visit8(node.externalKeyword, " ");
4979 visit8(node.constKeyword, " ");
4980 visit8(node.factoryKeyword, " ");
4981 visit(node.returnType);
4982 visit7(".", node.name);
4983 visit(node.parameters);
4984 visitList7(" : ", node.initializers, ", ");
4985 visit7(" = ", node.redirectedConstructor);
4986 if (node.body is! EmptyFunctionBody) {
4987 _writer.print(' ');
4988 }
4989 visit(node.body);
4990 return null;
4991 }
4992 Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
4993 visit8(node.keyword, ".");
4994 visit(node.fieldName);
4995 _writer.print(" = ");
4996 visit(node.expression);
4997 return null;
4998 }
4999 Object visitConstructorName(ConstructorName node) {
5000 visit(node.type);
5001 visit7(".", node.name);
5002 return null;
5003 }
5004 Object visitContinueStatement(ContinueStatement node) {
5005 _writer.print("continue");
5006 visit7(" ", node.label);
5007 _writer.print(";");
5008 return null;
5009 }
5010 Object visitDeclaredIdentifier(DeclaredIdentifier node) {
5011 visit8(node.keyword, " ");
5012 visit6(node.type, " ");
5013 visit(node.identifier);
5014 return null;
5015 }
5016 Object visitDefaultFormalParameter(DefaultFormalParameter node) {
5017 visit(node.parameter);
5018 if (node.separator != null) {
5019 _writer.print(" ");
5020 _writer.print(node.separator.lexeme);
5021 visit7(" ", node.defaultValue);
5022 }
5023 return null;
5024 }
5025 Object visitDoStatement(DoStatement node) {
5026 _writer.print("do ");
5027 visit(node.body);
5028 _writer.print(" while (");
5029 visit(node.condition);
5030 _writer.print(");");
5031 return null;
5032 }
5033 Object visitDoubleLiteral(DoubleLiteral node) {
5034 _writer.print(node.literal.lexeme);
5035 return null;
5036 }
5037 Object visitEmptyFunctionBody(EmptyFunctionBody node) {
5038 _writer.print(';');
5039 return null;
5040 }
5041 Object visitEmptyStatement(EmptyStatement node) {
5042 _writer.print(';');
5043 return null;
5044 }
5045 Object visitExportDirective(ExportDirective node) {
5046 _writer.print("export ");
5047 visit(node.uri);
5048 visitList7(" ", node.combinators, " ");
5049 _writer.print(';');
5050 return null;
5051 }
5052 Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
5053 _writer.print("=> ");
5054 visit(node.expression);
5055 if (node.semicolon != null) {
5056 _writer.print(';');
5057 }
5058 return null;
5059 }
5060 Object visitExpressionStatement(ExpressionStatement node) {
5061 visit(node.expression);
5062 _writer.print(';');
5063 return null;
5064 }
5065 Object visitExtendsClause(ExtendsClause node) {
5066 _writer.print("extends ");
5067 visit(node.superclass);
5068 return null;
5069 }
5070 Object visitFieldDeclaration(FieldDeclaration node) {
5071 visit(node.documentationComment);
5072 visit8(node.keyword, " ");
5073 visit(node.fields);
5074 _writer.print(";");
5075 return null;
5076 }
5077 Object visitFieldFormalParameter(FieldFormalParameter node) {
5078 visit8(node.keyword, " ");
5079 visit6(node.type, " ");
5080 _writer.print("this.");
5081 visit(node.identifier);
5082 return null;
5083 }
5084 Object visitForEachStatement(ForEachStatement node) {
5085 _writer.print("for (");
5086 visit(node.loopVariable);
5087 _writer.print(" in ");
5088 visit(node.iterator);
5089 _writer.print(") ");
5090 visit(node.body);
5091 return null;
5092 }
5093 Object visitFormalParameterList(FormalParameterList node) {
5094 String groupEnd = null;
5095 _writer.print('(');
5096 NodeList<FormalParameter> parameters13 = node.parameters;
5097 int size7 = parameters13.length;
5098 for (int i = 0; i < size7; i++) {
5099 FormalParameter parameter = parameters13[i];
5100 if (i > 0) {
5101 _writer.print(", ");
5102 }
5103 if (groupEnd == null && parameter is DefaultFormalParameter) {
5104 if (identical(parameter.kind, ParameterKind.NAMED)) {
5105 groupEnd = "}";
5106 _writer.print('{');
5107 } else {
5108 groupEnd = "]";
5109 _writer.print('[');
5110 }
5111 }
5112 parameter.accept(this);
5113 }
5114 if (groupEnd != null) {
5115 _writer.print(groupEnd);
5116 }
5117 _writer.print(')');
5118 return null;
5119 }
5120 Object visitForStatement(ForStatement node) {
5121 Expression initialization4 = node.initialization;
5122 _writer.print("for (");
5123 if (initialization4 != null) {
5124 visit(initialization4);
5125 } else {
5126 visit(node.variables);
5127 }
5128 _writer.print(";");
5129 visit7(" ", node.condition);
5130 _writer.print(";");
5131 visitList7(" ", node.updaters, ", ");
5132 _writer.print(") ");
5133 visit(node.body);
5134 return null;
5135 }
5136 Object visitFunctionDeclaration(FunctionDeclaration node) {
5137 visit6(node.returnType, " ");
5138 visit8(node.propertyKeyword, " ");
5139 visit(node.name);
5140 visit(node.functionExpression);
5141 return null;
5142 }
5143 Object visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
5144 visit(node.functionDeclaration);
5145 _writer.print(';');
5146 return null;
5147 }
5148 Object visitFunctionExpression(FunctionExpression node) {
5149 visit(node.parameters);
5150 _writer.print(' ');
5151 visit(node.body);
5152 return null;
5153 }
5154 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
5155 visit(node.function);
5156 visit(node.argumentList);
5157 return null;
5158 }
5159 Object visitFunctionTypeAlias(FunctionTypeAlias node) {
5160 _writer.print("typedef ");
5161 visit6(node.returnType, " ");
5162 visit(node.name);
5163 visit(node.typeParameters);
5164 visit(node.parameters);
5165 _writer.print(";");
5166 return null;
5167 }
5168 Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
5169 visit6(node.returnType, " ");
5170 visit(node.identifier);
5171 visit(node.parameters);
5172 return null;
5173 }
5174 Object visitHideCombinator(HideCombinator node) {
5175 _writer.print("hide ");
5176 visitList5(node.hiddenNames, ", ");
5177 return null;
5178 }
5179 Object visitIfStatement(IfStatement node) {
5180 _writer.print("if (");
5181 visit(node.condition);
5182 _writer.print(") ");
5183 visit(node.thenStatement);
5184 visit7(" else ", node.elseStatement);
5185 return null;
5186 }
5187 Object visitImplementsClause(ImplementsClause node) {
5188 _writer.print("implements ");
5189 visitList5(node.interfaces, ", ");
5190 return null;
5191 }
5192 Object visitImportDirective(ImportDirective node) {
5193 _writer.print("import ");
5194 visit(node.uri);
5195 visit7(" as ", node.prefix);
5196 visitList7(" ", node.combinators, " ");
5197 _writer.print(';');
5198 return null;
5199 }
5200 Object visitIndexExpression(IndexExpression node) {
5201 if (node.isCascaded()) {
5202 _writer.print("..");
5203 } else {
5204 visit(node.array);
5205 }
5206 _writer.print('[');
5207 visit(node.index);
5208 _writer.print(']');
5209 return null;
5210 }
5211 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
5212 visit8(node.keyword, " ");
5213 visit(node.constructorName);
5214 visit(node.argumentList);
5215 return null;
5216 }
5217 Object visitIntegerLiteral(IntegerLiteral node) {
5218 _writer.print(node.literal.lexeme);
5219 return null;
5220 }
5221 Object visitInterpolationExpression(InterpolationExpression node) {
5222 if (node.rightBracket != null) {
5223 _writer.print("\${");
5224 visit(node.expression);
5225 _writer.print("}");
5226 } else {
5227 _writer.print("\$");
5228 visit(node.expression);
5229 }
5230 return null;
5231 }
5232 Object visitInterpolationString(InterpolationString node) {
5233 _writer.print(node.contents.lexeme);
5234 return null;
5235 }
5236 Object visitIsExpression(IsExpression node) {
5237 visit(node.expression);
5238 if (node.notOperator == null) {
5239 _writer.print(" is ");
5240 } else {
5241 _writer.print(" is! ");
5242 }
5243 visit(node.type);
5244 return null;
5245 }
5246 Object visitLabel(Label node) {
5247 visit(node.label);
5248 _writer.print(":");
5249 return null;
5250 }
5251 Object visitLabeledStatement(LabeledStatement node) {
5252 visitList6(node.labels, " ", " ");
5253 visit(node.statement);
5254 return null;
5255 }
5256 Object visitLibraryDirective(LibraryDirective node) {
5257 _writer.print("library ");
5258 visit(node.name);
5259 _writer.print(';');
5260 nl();
5261 return null;
5262 }
5263 Object visitLibraryIdentifier(LibraryIdentifier node) {
5264 _writer.print(node.name);
5265 return null;
5266 }
5267 Object visitListLiteral(ListLiteral node) {
5268 if (node.modifier != null) {
5269 _writer.print(node.modifier.lexeme);
5270 _writer.print(' ');
5271 }
5272 visit6(node.typeArguments, " ");
5273 _writer.print("[");
5274 visitList5(node.elements, ", ");
5275 _writer.print("]");
5276 return null;
5277 }
5278 Object visitMapLiteral(MapLiteral node) {
5279 if (node.modifier != null) {
5280 _writer.print(node.modifier.lexeme);
5281 _writer.print(' ');
5282 }
5283 visit6(node.typeArguments, " ");
5284 _writer.print("{");
5285 visitList5(node.entries, ", ");
5286 _writer.print("}");
5287 return null;
5288 }
5289 Object visitMapLiteralEntry(MapLiteralEntry node) {
5290 visit(node.key);
5291 _writer.print(" : ");
5292 visit(node.value);
5293 return null;
5294 }
5295 Object visitMethodDeclaration(MethodDeclaration node) {
5296 visit(node.documentationComment);
5297 visit8(node.externalKeyword, " ");
5298 visit8(node.modifierKeyword, " ");
5299 visit6(node.returnType, " ");
5300 visit8(node.propertyKeyword, " ");
5301 visit8(node.operatorKeyword, " ");
5302 visit(node.name);
5303 if (!node.isGetter()) {
5304 visit(node.parameters);
5305 }
5306 if (node.body is! EmptyFunctionBody) {
5307 _writer.print(' ');
5308 }
5309 visit(node.body);
5310 return null;
5311 }
5312 Object visitMethodInvocation(MethodInvocation node) {
5313 if (node.isCascaded()) {
5314 _writer.print("..");
5315 } else {
5316 visit6(node.target, ".");
5317 }
5318 visit(node.methodName);
5319 visit(node.argumentList);
5320 return null;
5321 }
5322 Object visitNamedExpression(NamedExpression node) {
5323 visit(node.name);
5324 visit7(" ", node.expression);
5325 return null;
5326 }
5327 Object visitNullLiteral(NullLiteral node) {
5328 _writer.print("null");
5329 return null;
5330 }
5331 Object visitParenthesizedExpression(ParenthesizedExpression node) {
5332 _writer.print('(');
5333 visit(node.expression);
5334 _writer.print(')');
5335 return null;
5336 }
5337 Object visitPartDirective(PartDirective node) {
5338 _writer.print("part ");
5339 visit(node.uri);
5340 _writer.print(';');
5341 return null;
5342 }
5343 Object visitPartOfDirective(PartOfDirective node) {
5344 _writer.print("part of ");
5345 visit(node.libraryName);
5346 _writer.print(';');
5347 return null;
5348 }
5349 Object visitPostfixExpression(PostfixExpression node) {
5350 visit(node.operand);
5351 _writer.print(node.operator.lexeme);
5352 return null;
5353 }
5354 Object visitPrefixedIdentifier(PrefixedIdentifier node) {
5355 visit(node.prefix);
5356 _writer.print('.');
5357 visit(node.identifier);
5358 return null;
5359 }
5360 Object visitPrefixExpression(PrefixExpression node) {
5361 _writer.print(node.operator.lexeme);
5362 visit(node.operand);
5363 return null;
5364 }
5365 Object visitPropertyAccess(PropertyAccess node) {
5366 if (node.isCascaded()) {
5367 _writer.print("..");
5368 } else {
5369 visit6(node.target, ".");
5370 }
5371 visit(node.propertyName);
5372 return null;
5373 }
5374 Object visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
5375 _writer.print("this");
5376 visit7(".", node.constructorName);
5377 visit(node.argumentList);
5378 return null;
5379 }
5380 Object visitReturnStatement(ReturnStatement node) {
5381 Expression expression17 = node.expression;
5382 if (expression17 == null) {
5383 _writer.print("return;");
5384 } else {
5385 _writer.print("return ");
5386 expression17.accept(this);
5387 _writer.print(";");
5388 }
5389 return null;
5390 }
5391 Object visitScriptTag(ScriptTag node) {
5392 _writer.print(node.scriptTag.lexeme);
5393 return null;
5394 }
5395 Object visitShowCombinator(ShowCombinator node) {
5396 _writer.print("show ");
5397 visitList5(node.shownNames, ", ");
5398 return null;
5399 }
5400 Object visitSimpleFormalParameter(SimpleFormalParameter node) {
5401 visit8(node.keyword, " ");
5402 visit6(node.type, " ");
5403 visit(node.identifier);
5404 return null;
5405 }
5406 Object visitSimpleIdentifier(SimpleIdentifier node) {
5407 _writer.print(node.token.lexeme);
5408 return null;
5409 }
5410 Object visitSimpleStringLiteral(SimpleStringLiteral node) {
5411 _writer.print(node.literal.lexeme);
5412 return null;
5413 }
5414 Object visitStringInterpolation(StringInterpolation node) {
5415 visitList(node.elements);
5416 return null;
5417 }
5418 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
5419 _writer.print("super");
5420 visit7(".", node.constructorName);
5421 visit(node.argumentList);
5422 return null;
5423 }
5424 Object visitSuperExpression(SuperExpression node) {
5425 _writer.print("super");
5426 return null;
5427 }
5428 Object visitSwitchCase(SwitchCase node) {
5429 visitList6(node.labels, " ", " ");
5430 _writer.print("case ");
5431 visit(node.expression);
5432 _writer.print(": ");
5433 {
5434 indentInc();
5435 visitList5(node.statements, "\n");
5436 indentDec();
5437 }
5438 return null;
5439 }
5440 Object visitSwitchDefault(SwitchDefault node) {
5441 visitList6(node.labels, " ", " ");
5442 _writer.print("default: ");
5443 {
5444 indentInc();
5445 visitList5(node.statements, "\n");
5446 indentDec();
5447 }
5448 return null;
5449 }
5450 Object visitSwitchStatement(SwitchStatement node) {
5451 _writer.print("switch (");
5452 visit(node.expression);
5453 _writer.print(") {");
5454 {
5455 indentInc();
5456 visitList5(node.members, "\n");
5457 indentDec();
5458 }
5459 nl2();
5460 _writer.print('}');
5461 return null;
5462 }
5463 Object visitThisExpression(ThisExpression node) {
5464 _writer.print("this");
5465 return null;
5466 }
5467 Object visitThrowExpression(ThrowExpression node) {
5468 _writer.print("throw ");
5469 visit(node.expression);
5470 return null;
5471 }
5472 Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
5473 visit6(node.variables, ";");
5474 return null;
5475 }
5476 Object visitTryStatement(TryStatement node) {
5477 _writer.print("try ");
5478 visit(node.body);
5479 visitList7(" ", node.catchClauses, " ");
5480 visit7(" finally ", node.finallyClause);
5481 return null;
5482 }
5483 Object visitTypeArgumentList(TypeArgumentList node) {
5484 _writer.print('<');
5485 visitList5(node.arguments, ", ");
5486 _writer.print('>');
5487 return null;
5488 }
5489 Object visitTypeName(TypeName node) {
5490 visit(node.name);
5491 visit(node.typeArguments);
5492 return null;
5493 }
5494 Object visitTypeParameter(TypeParameter node) {
5495 visit(node.name);
5496 visit7(" extends ", node.bound);
5497 return null;
5498 }
5499 Object visitTypeParameterList(TypeParameterList node) {
5500 _writer.print('<');
5501 visitList5(node.typeParameters, ", ");
5502 _writer.print('>');
5503 return null;
5504 }
5505 Object visitVariableDeclaration(VariableDeclaration node) {
5506 visit(node.name);
5507 visit7(" = ", node.initializer);
5508 return null;
5509 }
5510 Object visitVariableDeclarationList(VariableDeclarationList node) {
5511 visit8(node.keyword, " ");
5512 visit6(node.type, " ");
5513 visitList5(node.variables, ", ");
5514 return null;
5515 }
5516 Object visitVariableDeclarationStatement(VariableDeclarationStatement node) {
5517 visit(node.variables);
5518 _writer.print(";");
5519 return null;
5520 }
5521 Object visitWhileStatement(WhileStatement node) {
5522 _writer.print("while (");
5523 visit(node.condition);
5524 _writer.print(") ");
5525 visit(node.body);
5526 return null;
5527 }
5528 Object visitWithClause(WithClause node) {
5529 _writer.print("with ");
5530 visitList5(node.mixinTypes, ", ");
5531 return null;
5532 }
5533 void indent() {
5534 _writer.print(_indentString);
5535 }
5536 void indentDec() {
5537 _indentLevel -= 2;
5538 _indentString = StringUtils.repeat(" ", _indentLevel);
5539 }
5540 void indentInc() {
5541 _indentLevel += 2;
5542 _indentString = StringUtils.repeat(" ", _indentLevel);
5543 }
5544 void nl() {
5545 _writer.print("\n");
5546 }
5547 void nl2() {
5548 nl();
5549 indent();
5550 }
5551 /**
5552 * Safely visit the given node.
5553 * @param node the node to be visited
5554 */
5555 void visit(ASTNode node) {
5556 if (node != null) {
5557 node.accept(this);
5558 }
5559 }
5560 /**
5561 * Safely visit the given node, printing the suffix after the node if it is no n-<code>null</code>.
5562 * @param suffix the suffix to be printed if there is a node to visit
5563 * @param node the node to be visited
5564 */
5565 void visit6(ASTNode node, String suffix) {
5566 if (node != null) {
5567 node.accept(this);
5568 _writer.print(suffix);
5569 }
5570 }
5571 /**
5572 * Safely visit the given node, printing the prefix before the node if it is n on-<code>null</code>
5573 * .
5574 * @param prefix the prefix to be printed if there is a node to visit
5575 * @param node the node to be visited
5576 */
5577 void visit7(String prefix, ASTNode node) {
5578 if (node != null) {
5579 _writer.print(prefix);
5580 node.accept(this);
5581 }
5582 }
5583 /**
5584 * Safely visit the given node, printing the suffix after the node if it is no n-<code>null</code>.
5585 * @param suffix the suffix to be printed if there is a node to visit
5586 * @param node the node to be visited
5587 */
5588 void visit8(Token token, String suffix) {
5589 if (token != null) {
5590 _writer.print(token.lexeme);
5591 _writer.print(suffix);
5592 }
5593 }
5594 /**
5595 * Print a list of nodes without any separation.
5596 * @param nodes the nodes to be printed
5597 * @param separator the separator to be printed between adjacent nodes
5598 */
5599 void visitList(NodeList<ASTNode> nodes) {
5600 visitList5(nodes, "");
5601 }
5602 /**
5603 * Print a list of nodes, separated by the given separator.
5604 * @param nodes the nodes to be printed
5605 * @param separator the separator to be printed between adjacent nodes
5606 */
5607 void visitList5(NodeList<ASTNode> nodes, String separator) {
5608 if (nodes != null) {
5609 int size8 = nodes.length;
5610 for (int i = 0; i < size8; i++) {
5611 if ("\n" == separator) {
5612 _writer.print("\n");
5613 indent();
5614 } else if (i > 0) {
5615 _writer.print(separator);
5616 }
5617 nodes[i].accept(this);
5618 }
5619 }
5620 }
5621 /**
5622 * Print a list of nodes, separated by the given separator.
5623 * @param nodes the nodes to be printed
5624 * @param separator the separator to be printed between adjacent nodes
5625 * @param suffix the suffix to be printed if the list is not empty
5626 */
5627 void visitList6(NodeList<ASTNode> nodes, String separator, String suffix) {
5628 if (nodes != null) {
5629 int size9 = nodes.length;
5630 if (size9 > 0) {
5631 for (int i = 0; i < size9; i++) {
5632 if (i > 0) {
5633 _writer.print(separator);
5634 }
5635 nodes[i].accept(this);
5636 }
5637 _writer.print(suffix);
5638 }
5639 }
5640 }
5641 /**
5642 * Print a list of nodes, separated by the given separator.
5643 * @param prefix the prefix to be printed if the list is not empty
5644 * @param nodes the nodes to be printed
5645 * @param separator the separator to be printed between adjacent nodes
5646 */
5647 void visitList7(String prefix, NodeList<ASTNode> nodes, String separator) {
5648 if (nodes != null) {
5649 int size10 = nodes.length;
5650 if (size10 > 0) {
5651 _writer.print(prefix);
5652 for (int i = 0; i < size10; i++) {
5653 if (i > 0) {
5654 _writer.print(separator);
5655 }
5656 nodes[i].accept(this);
5657 }
5658 }
5659 }
5660 }
5661 }
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