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

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

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

Powered by Google App Engine
This is Rietveld 408576698