| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library dart_parser; | 5 library dart_parser; |
| 6 | 6 |
| 7 import 'package:dart_scanner/src/keyword.dart' show | 7 import 'package:dart_scanner/src/keyword.dart' show |
| 8 Keyword; | 8 Keyword; |
| 9 | 9 |
| 10 import 'package:dart_scanner/src/precedence.dart' show | 10 import 'package:dart_scanner/src/precedence.dart' show |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 * [parseMetadataStar] corresponds to this grammar snippet: [: | 108 * [parseMetadataStar] corresponds to this grammar snippet: [: |
| 109 * metadata* :], and [parseTypeOpt] corresponds to: [: type? :]. | 109 * metadata* :], and [parseTypeOpt] corresponds to: [: type? :]. |
| 110 */ | 110 */ |
| 111 class Parser { | 111 class Parser { |
| 112 final Listener listener; | 112 final Listener listener; |
| 113 | 113 |
| 114 bool mayParseFunctionExpressions = true; | 114 bool mayParseFunctionExpressions = true; |
| 115 | 115 |
| 116 bool asyncAwaitKeywordsEnabled; | 116 bool asyncAwaitKeywordsEnabled; |
| 117 | 117 |
| 118 final bool enableGenericMethodSyntax; | 118 Parser(this.listener, {this.asyncAwaitKeywordsEnabled: false}); |
| 119 | |
| 120 Parser(this.listener, | |
| 121 {this.asyncAwaitKeywordsEnabled: false, | |
| 122 this.enableGenericMethodSyntax: false}); | |
| 123 | 119 |
| 124 Token parseUnit(Token token) { | 120 Token parseUnit(Token token) { |
| 125 listener.beginCompilationUnit(token); | 121 listener.beginCompilationUnit(token); |
| 126 int count = 0; | 122 int count = 0; |
| 127 while (!identical(token.kind, EOF_TOKEN)) { | 123 while (!identical(token.kind, EOF_TOKEN)) { |
| 128 token = parseTopLevelDeclaration(token); | 124 token = parseTopLevelDeclaration(token); |
| 129 count++; | 125 count++; |
| 130 } | 126 } |
| 131 listener.endCompilationUnit(count, token); | 127 listener.endCompilationUnit(count, token); |
| 132 return token; | 128 return token; |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 376 period = token; | 372 period = token; |
| 377 token = parseIdentifier(token.next); | 373 token = parseIdentifier(token.next); |
| 378 } | 374 } |
| 379 token = parseArgumentsOpt(token); | 375 token = parseArgumentsOpt(token); |
| 380 listener.endMetadata(atToken, period, token); | 376 listener.endMetadata(atToken, period, token); |
| 381 return token; | 377 return token; |
| 382 } | 378 } |
| 383 | 379 |
| 384 Token parseTypedef(Token token) { | 380 Token parseTypedef(Token token) { |
| 385 Token typedefKeyword = token; | 381 Token typedefKeyword = token; |
| 386 if (optional('=', peekAfterType(token.next))) { | 382 listener.beginFunctionTypeAlias(token); |
| 387 // TODO(aprelev@gmail.com): Remove deprecated 'typedef' mixin application, | 383 token = parseReturnTypeOpt(token.next); |
| 388 // remove corresponding diagnostic from members.dart. | 384 token = parseIdentifier(token); |
| 389 listener.beginNamedMixinApplication(token); | 385 token = parseTypeVariablesOpt(token); |
| 390 token = parseIdentifier(token.next); | 386 token = parseFormalParameters(token); |
| 391 token = parseTypeVariablesOpt(token); | 387 listener.endFunctionTypeAlias(typedefKeyword, token); |
| 392 token = expect('=', token); | |
| 393 token = parseModifiers(token); | |
| 394 token = parseMixinApplication(token); | |
| 395 Token implementsKeyword = null; | |
| 396 if (optional('implements', token)) { | |
| 397 implementsKeyword = token; | |
| 398 token = parseTypeList(token.next); | |
| 399 } | |
| 400 listener.endNamedMixinApplication( | |
| 401 typedefKeyword, implementsKeyword, token); | |
| 402 } else { | |
| 403 listener.beginFunctionTypeAlias(token); | |
| 404 token = parseReturnTypeOpt(token.next); | |
| 405 token = parseIdentifier(token); | |
| 406 token = parseTypeVariablesOpt(token); | |
| 407 token = parseFormalParameters(token); | |
| 408 listener.endFunctionTypeAlias(typedefKeyword, token); | |
| 409 } | |
| 410 return expect(';', token); | 388 return expect(';', token); |
| 411 } | 389 } |
| 412 | 390 |
| 413 Token parseMixinApplication(Token token) { | 391 Token parseMixinApplication(Token token) { |
| 414 listener.beginMixinApplication(token); | 392 listener.beginMixinApplication(token); |
| 415 token = parseType(token); | 393 token = parseType(token); |
| 416 token = expect('with', token); | 394 token = expect('with', token); |
| 417 token = parseTypeList(token); | 395 token = parseTypeList(token); |
| 418 listener.endMixinApplication(); | 396 listener.endMixinApplication(); |
| 419 return token; | 397 return token; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 } | 436 } |
| 459 token = parseFormalParameter(token, FormalParameterType.REQUIRED); | 437 token = parseFormalParameter(token, FormalParameterType.REQUIRED); |
| 460 } while (optional(',', token)); | 438 } while (optional(',', token)); |
| 461 listener.endFormalParameters(parameterCount, begin, token); | 439 listener.endFormalParameters(parameterCount, begin, token); |
| 462 return expect(')', token); | 440 return expect(')', token); |
| 463 } | 441 } |
| 464 | 442 |
| 465 Token parseFormalParameter(Token token, FormalParameterType type) { | 443 Token parseFormalParameter(Token token, FormalParameterType type) { |
| 466 token = parseMetadataStar(token, forParameter: true); | 444 token = parseMetadataStar(token, forParameter: true); |
| 467 listener.beginFormalParameter(token); | 445 listener.beginFormalParameter(token); |
| 446 |
| 447 // Skip over `covariant` token, if the next token is an identifier or |
| 448 // modifier. |
| 449 // This enables the case where `covariant` is the name of the parameter: |
| 450 // void foo(covariant); |
| 451 if (identical(token.stringValue, 'covariant') && |
| 452 (token.next.isIdentifier() || isModifier(token.next))) { |
| 453 token = token.next; |
| 454 } |
| 468 token = parseModifiers(token); | 455 token = parseModifiers(token); |
| 469 // TODO(ahe): Validate that there are formal parameters if void. | 456 // TODO(ahe): Validate that there are formal parameters if void. |
| 470 token = parseReturnTypeOpt(token); | 457 token = parseReturnTypeOpt(token); |
| 471 Token thisKeyword = null; | 458 Token thisKeyword = null; |
| 472 if (optional('this', token)) { | 459 if (optional('this', token)) { |
| 473 thisKeyword = token; | 460 thisKeyword = token; |
| 474 // TODO(ahe): Validate field initializers are only used in | 461 // TODO(ahe): Validate field initializers are only used in |
| 475 // constructors, and not for function-typed arguments. | 462 // constructors, and not for function-typed arguments. |
| 476 token = expect('.', token.next); | 463 token = expect('.', token.next); |
| 477 } | 464 } |
| 478 token = parseIdentifier(token); | 465 token = parseIdentifier(token); |
| 479 if (optional('(', token)) { | 466 if (optional('(', token)) { |
| 480 listener.beginFunctionTypedFormalParameter(token); | 467 listener.beginFunctionTypedFormalParameter(token); |
| 481 listener.handleNoTypeVariables(token); | 468 listener.handleNoTypeVariables(token); |
| 482 token = parseFormalParameters(token); | 469 token = parseFormalParameters(token); |
| 483 listener.handleFunctionTypedFormalParameter(token); | 470 listener.handleFunctionTypedFormalParameter(token); |
| 484 } else if (enableGenericMethodSyntax && optional('<', token)) { | 471 } else if (optional('<', token)) { |
| 485 listener.beginFunctionTypedFormalParameter(token); | 472 listener.beginFunctionTypedFormalParameter(token); |
| 486 token = parseTypeVariablesOpt(token); | 473 token = parseTypeVariablesOpt(token); |
| 487 token = parseFormalParameters(token); | 474 token = parseFormalParameters(token); |
| 488 listener.handleFunctionTypedFormalParameter(token); | 475 listener.handleFunctionTypedFormalParameter(token); |
| 489 } | 476 } |
| 490 String value = token.stringValue; | 477 String value = token.stringValue; |
| 491 if ((identical('=', value)) || (identical(':', value))) { | 478 if ((identical('=', value)) || (identical(':', value))) { |
| 492 // TODO(ahe): Validate that these are only used for optional parameters. | 479 // TODO(ahe): Validate that these are only used for optional parameters. |
| 493 Token equal = token; | 480 Token equal = token; |
| 494 token = parseExpression(token.next); | 481 token = parseExpression(token.next); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 token = tryParseQualified(token); | 580 token = tryParseQualified(token); |
| 594 if (token == null) return null; | 581 if (token == null) return null; |
| 595 Token tokenAfterQualified = token; | 582 Token tokenAfterQualified = token; |
| 596 token = tryParseNestedTypeArguments(token); | 583 token = tryParseNestedTypeArguments(token); |
| 597 return token == null ? tokenAfterQualified : token; | 584 return token == null ? tokenAfterQualified : token; |
| 598 } | 585 } |
| 599 | 586 |
| 600 /// Returns token after match if [token] matches identifier ('.' identifier)?, | 587 /// Returns token after match if [token] matches identifier ('.' identifier)?, |
| 601 /// and otherwise returns null. Does not produce listener events. | 588 /// and otherwise returns null. Does not produce listener events. |
| 602 Token tryParseQualified(Token token) { | 589 Token tryParseQualified(Token token) { |
| 603 if (!identical(token.kind, IDENTIFIER_TOKEN)) return null; | 590 if (!isValidTypeReference(token)) return null; |
| 604 token = token.next; | 591 token = token.next; |
| 605 if (!identical(token.kind, PERIOD_TOKEN)) return token; | 592 if (!identical(token.kind, PERIOD_TOKEN)) return token; |
| 606 token = token.next; | 593 token = token.next; |
| 607 if (!identical(token.kind, IDENTIFIER_TOKEN)) return null; | 594 if (!identical(token.kind, IDENTIFIER_TOKEN)) return null; |
| 608 return token.next; | 595 return token.next; |
| 609 } | 596 } |
| 610 | 597 |
| 611 /// Returns token after match if [token] matches '<' type (',' type)* '>', | 598 /// Returns token after match if [token] matches '<' type (',' type)* '>', |
| 612 /// and otherwise returns null. Does not produce listener events. The final | 599 /// and otherwise returns null. Does not produce listener events. The final |
| 613 /// '>' may be the first character in a '>>' token, in which case a synthetic | 600 /// '>' may be the first character in a '>>' token, in which case a synthetic |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 698 Token begin = token; | 685 Token begin = token; |
| 699 Token abstractKeyword; | 686 Token abstractKeyword; |
| 700 if (optional('abstract', token)) { | 687 if (optional('abstract', token)) { |
| 701 abstractKeyword = token; | 688 abstractKeyword = token; |
| 702 token = token.next; | 689 token = token.next; |
| 703 } | 690 } |
| 704 Token classKeyword = token; | 691 Token classKeyword = token; |
| 705 var isMixinApplication = optional('=', peekAfterType(token.next)); | 692 var isMixinApplication = optional('=', peekAfterType(token.next)); |
| 706 if (isMixinApplication) { | 693 if (isMixinApplication) { |
| 707 listener.beginNamedMixinApplication(begin); | 694 listener.beginNamedMixinApplication(begin); |
| 708 token = parseIdentifier(token.next); | |
| 709 token = parseTypeVariablesOpt(token); | |
| 710 token = expect('=', token); | |
| 711 } else { | 695 } else { |
| 712 listener.beginClassDeclaration(begin); | 696 listener.beginClassDeclaration(begin); |
| 713 } | 697 } |
| 714 | 698 |
| 715 // TODO(aprelev@gmail.com): Once 'typedef' named mixin application is | |
| 716 // removed, move modifiers for named mixin application to the bottom of | |
| 717 // listener stack. This is so stacks for class declaration and named | |
| 718 // mixin application look similar. | |
| 719 int modifierCount = 0; | 699 int modifierCount = 0; |
| 720 if (abstractKeyword != null) { | 700 if (abstractKeyword != null) { |
| 721 parseModifier(abstractKeyword); | 701 parseModifier(abstractKeyword); |
| 722 modifierCount++; | 702 modifierCount++; |
| 723 } | 703 } |
| 724 listener.handleModifiers(modifierCount); | 704 listener.handleModifiers(modifierCount); |
| 725 | 705 |
| 726 if (isMixinApplication) { | 706 if (isMixinApplication) { |
| 707 token = parseIdentifier(token.next); |
| 708 token = parseTypeVariablesOpt(token); |
| 709 token = expect('=', token); |
| 727 return parseNamedMixinApplication(token, classKeyword); | 710 return parseNamedMixinApplication(token, classKeyword); |
| 728 } else { | 711 } else { |
| 729 return parseClass(begin, classKeyword); | 712 return parseClass(begin, classKeyword); |
| 730 } | 713 } |
| 731 } | 714 } |
| 732 | 715 |
| 733 Token parseNamedMixinApplication(Token token, Token classKeyword) { | 716 Token parseNamedMixinApplication(Token token, Token classKeyword) { |
| 734 token = parseMixinApplication(token); | 717 token = parseMixinApplication(token); |
| 735 Token implementsKeyword = null; | 718 Token implementsKeyword = null; |
| 736 if (optional('implements', token)) { | 719 if (optional('implements', token)) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 792 if (!identical(string, token.stringValue)) { | 775 if (!identical(string, token.stringValue)) { |
| 793 return listener.expected(string, token); | 776 return listener.expected(string, token); |
| 794 } | 777 } |
| 795 return token.next; | 778 return token.next; |
| 796 } | 779 } |
| 797 | 780 |
| 798 Token parseTypeVariable(Token token) { | 781 Token parseTypeVariable(Token token) { |
| 799 listener.beginTypeVariable(token); | 782 listener.beginTypeVariable(token); |
| 800 token = parseIdentifier(token); | 783 token = parseIdentifier(token); |
| 801 Token extendsOrSuper = null; | 784 Token extendsOrSuper = null; |
| 802 if (optional('extends', token) || | 785 if (optional('extends', token) || optional('super', token)) { |
| 803 (enableGenericMethodSyntax && optional('super', token))) { | |
| 804 extendsOrSuper = token; | 786 extendsOrSuper = token; |
| 805 token = parseType(token.next); | 787 token = parseType(token.next); |
| 806 } else { | 788 } else { |
| 807 listener.handleNoType(token); | 789 listener.handleNoType(token); |
| 808 } | 790 } |
| 809 listener.endTypeVariable(token, extendsOrSuper); | 791 listener.endTypeVariable(token, extendsOrSuper); |
| 810 return token; | 792 return token; |
| 811 } | 793 } |
| 812 | 794 |
| 813 /** | 795 /** |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1020 listener.handleModifiers(modifierCount); | 1002 listener.handleModifiers(modifierCount); |
| 1021 var kind = hasTypeOrModifier | 1003 var kind = hasTypeOrModifier |
| 1022 ? ErrorKind.EXTRANEOUS_MODIFIER | 1004 ? ErrorKind.EXTRANEOUS_MODIFIER |
| 1023 : ErrorKind.EXTRANEOUS_MODIFIER_REPLACE; | 1005 : ErrorKind.EXTRANEOUS_MODIFIER_REPLACE; |
| 1024 for (Token modifier in modifierList) { | 1006 for (Token modifier in modifierList) { |
| 1025 listener.reportError(modifier, kind, {'modifier': modifier}); | 1007 listener.reportError(modifier, kind, {'modifier': modifier}); |
| 1026 } | 1008 } |
| 1027 return null; | 1009 return null; |
| 1028 } | 1010 } |
| 1029 | 1011 |
| 1012 /// Removes the optional `covariant` token from the modifiers, if there |
| 1013 /// is no `static` in the list, and `covariant` is the first modifier. |
| 1014 Link<Token> removeOptCovariantTokenIfNotStatic(Link<Token> modifiers) { |
| 1015 if (modifiers.isEmpty || |
| 1016 !identical(modifiers.first.stringValue, 'covariant')) { |
| 1017 return modifiers; |
| 1018 } |
| 1019 for (Token modifier in modifiers.tail) { |
| 1020 if (identical(modifier.stringValue, 'static')) { |
| 1021 return modifiers; |
| 1022 } |
| 1023 } |
| 1024 return modifiers.tail; |
| 1025 } |
| 1026 |
| 1030 Token parseFields(Token start, Link<Token> modifiers, Token type, | 1027 Token parseFields(Token start, Link<Token> modifiers, Token type, |
| 1031 Token getOrSet, Token name, bool isTopLevel) { | 1028 Token getOrSet, Token name, bool isTopLevel) { |
| 1032 bool hasType = type != null; | 1029 bool hasType = type != null; |
| 1030 |
| 1031 if (getOrSet == null && !isTopLevel) { |
| 1032 modifiers = removeOptCovariantTokenIfNotStatic(modifiers); |
| 1033 } |
| 1034 |
| 1033 Token varFinalOrConst = | 1035 Token varFinalOrConst = |
| 1034 expectVarFinalOrConst(modifiers, hasType, !isTopLevel); | 1036 expectVarFinalOrConst(modifiers, hasType, !isTopLevel); |
| 1035 bool isVar = false; | 1037 bool isVar = false; |
| 1036 bool hasModifier = false; | 1038 bool hasModifier = false; |
| 1037 if (varFinalOrConst != null) { | 1039 if (varFinalOrConst != null) { |
| 1038 hasModifier = true; | 1040 hasModifier = true; |
| 1039 isVar = optional('var', varFinalOrConst); | 1041 isVar = optional('var', varFinalOrConst); |
| 1040 } | 1042 } |
| 1041 | 1043 |
| 1042 if (getOrSet != null) { | 1044 if (getOrSet != null) { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1101 listener.handleModifiers(0); | 1103 listener.handleModifiers(0); |
| 1102 } | 1104 } |
| 1103 | 1105 |
| 1104 if (type == null) { | 1106 if (type == null) { |
| 1105 listener.handleNoType(name); | 1107 listener.handleNoType(name); |
| 1106 } else { | 1108 } else { |
| 1107 parseReturnTypeOpt(type); | 1109 parseReturnTypeOpt(type); |
| 1108 } | 1110 } |
| 1109 Token token = parseIdentifier(name); | 1111 Token token = parseIdentifier(name); |
| 1110 | 1112 |
| 1111 if (enableGenericMethodSyntax && getOrSet == null) { | 1113 if (getOrSet == null) { |
| 1112 token = parseTypeVariablesOpt(token); | 1114 token = parseTypeVariablesOpt(token); |
| 1113 } else { | 1115 } else { |
| 1114 listener.handleNoTypeVariables(token); | 1116 listener.handleNoTypeVariables(token); |
| 1115 } | 1117 } |
| 1116 token = parseFormalParametersOpt(token); | 1118 token = parseFormalParametersOpt(token); |
| 1117 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; | 1119 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; |
| 1118 token = parseAsyncModifier(token); | 1120 token = parseAsyncModifier(token); |
| 1119 token = parseFunctionBody(token, false, externalModifier != null); | 1121 token = parseFunctionBody(token, false, externalModifier != null); |
| 1120 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; | 1122 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; |
| 1121 Token endToken = token; | 1123 Token endToken = token; |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1386 return optional('factory', token); | 1388 return optional('factory', token); |
| 1387 } | 1389 } |
| 1388 | 1390 |
| 1389 Token parseMember(Token token) { | 1391 Token parseMember(Token token) { |
| 1390 token = parseMetadataStar(token); | 1392 token = parseMetadataStar(token); |
| 1391 Token start = token; | 1393 Token start = token; |
| 1392 listener.beginMember(token); | 1394 listener.beginMember(token); |
| 1393 if (isFactoryDeclaration(token)) { | 1395 if (isFactoryDeclaration(token)) { |
| 1394 token = parseFactoryMethod(token); | 1396 token = parseFactoryMethod(token); |
| 1395 listener.endMember(); | 1397 listener.endMember(); |
| 1396 assert (token != null); | 1398 assert(token != null); |
| 1397 return token; | 1399 return token; |
| 1398 } | 1400 } |
| 1399 | 1401 |
| 1400 Link<Token> identifiers = findMemberName(token); | 1402 Link<Token> identifiers = findMemberName(token); |
| 1401 if (identifiers.isEmpty) { | 1403 if (identifiers.isEmpty) { |
| 1402 return listener.expectedDeclaration(start); | 1404 return listener.expectedDeclaration(start); |
| 1403 } | 1405 } |
| 1404 Token afterName = identifiers.head; | 1406 Token afterName = identifiers.head; |
| 1405 identifiers = identifiers.tail; | 1407 identifiers = identifiers.tail; |
| 1406 | 1408 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1433 token = afterName; | 1435 token = afterName; |
| 1434 bool isField; | 1436 bool isField; |
| 1435 while (true) { | 1437 while (true) { |
| 1436 // Loop to allow the listener to rewrite the token stream for | 1438 // Loop to allow the listener to rewrite the token stream for |
| 1437 // error handling. | 1439 // error handling. |
| 1438 final String value = token.stringValue; | 1440 final String value = token.stringValue; |
| 1439 if ((identical(value, '(')) || | 1441 if ((identical(value, '(')) || |
| 1440 (identical(value, '.')) || | 1442 (identical(value, '.')) || |
| 1441 (identical(value, '{')) || | 1443 (identical(value, '{')) || |
| 1442 (identical(value, '=>')) || | 1444 (identical(value, '=>')) || |
| 1443 (enableGenericMethodSyntax && identical(value, '<'))) { | 1445 (identical(value, '<'))) { |
| 1444 isField = false; | 1446 isField = false; |
| 1445 break; | 1447 break; |
| 1446 } else if (identical(value, ';')) { | 1448 } else if (identical(value, ';')) { |
| 1447 if (getOrSet != null) { | 1449 if (getOrSet != null) { |
| 1448 // If we found a "get" keyword, this must be an abstract | 1450 // If we found a "get" keyword, this must be an abstract |
| 1449 // getter. | 1451 // getter. |
| 1450 isField = (!identical(getOrSet.stringValue, 'get')); | 1452 isField = (!identical(getOrSet.stringValue, 'get')); |
| 1451 // TODO(ahe): This feels like a hack. | 1453 // TODO(ahe): This feels like a hack. |
| 1452 } else { | 1454 } else { |
| 1453 isField = true; | 1455 isField = true; |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1528 token = parseOperatorName(name); | 1530 token = parseOperatorName(name); |
| 1529 if (staticModifier != null) { | 1531 if (staticModifier != null) { |
| 1530 listener.reportError(staticModifier, ErrorKind.EXTRANEOUS_MODIFIER, | 1532 listener.reportError(staticModifier, ErrorKind.EXTRANEOUS_MODIFIER, |
| 1531 {'modifier': staticModifier}); | 1533 {'modifier': staticModifier}); |
| 1532 } | 1534 } |
| 1533 } else { | 1535 } else { |
| 1534 token = parseIdentifier(name); | 1536 token = parseIdentifier(name); |
| 1535 } | 1537 } |
| 1536 | 1538 |
| 1537 token = parseQualifiedRestOpt(token); | 1539 token = parseQualifiedRestOpt(token); |
| 1538 if (enableGenericMethodSyntax && getOrSet == null) { | 1540 if (getOrSet == null) { |
| 1539 token = parseTypeVariablesOpt(token); | 1541 token = parseTypeVariablesOpt(token); |
| 1540 } else { | 1542 } else { |
| 1541 listener.handleNoTypeVariables(token); | 1543 listener.handleNoTypeVariables(token); |
| 1542 } | 1544 } |
| 1543 token = parseFormalParametersOpt(token); | 1545 token = parseFormalParametersOpt(token); |
| 1544 token = parseInitializersOpt(token); | 1546 token = parseInitializersOpt(token); |
| 1545 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; | 1547 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; |
| 1546 token = parseAsyncModifier(token); | 1548 token = parseAsyncModifier(token); |
| 1547 if (optional('=', token)) { | 1549 if (optional('=', token)) { |
| 1548 token = parseRedirectingFactoryBody(token); | 1550 token = parseRedirectingFactoryBody(token); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1619 } | 1621 } |
| 1620 listener.beginFunctionName(token); | 1622 listener.beginFunctionName(token); |
| 1621 if (optional('operator', token)) { | 1623 if (optional('operator', token)) { |
| 1622 token = parseOperatorName(token); | 1624 token = parseOperatorName(token); |
| 1623 } else { | 1625 } else { |
| 1624 token = parseIdentifier(token); | 1626 token = parseIdentifier(token); |
| 1625 } | 1627 } |
| 1626 } | 1628 } |
| 1627 token = parseQualifiedRestOpt(token); | 1629 token = parseQualifiedRestOpt(token); |
| 1628 listener.endFunctionName(token); | 1630 listener.endFunctionName(token); |
| 1629 if (enableGenericMethodSyntax && getOrSet == null) { | 1631 if (getOrSet == null) { |
| 1630 token = parseTypeVariablesOpt(token); | 1632 token = parseTypeVariablesOpt(token); |
| 1631 } else { | 1633 } else { |
| 1632 listener.handleNoTypeVariables(token); | 1634 listener.handleNoTypeVariables(token); |
| 1633 } | 1635 } |
| 1634 token = parseFormalParametersOpt(token); | 1636 token = parseFormalParametersOpt(token); |
| 1635 token = parseInitializersOpt(token); | 1637 token = parseInitializersOpt(token); |
| 1636 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; | 1638 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; |
| 1637 token = parseAsyncModifier(token); | 1639 token = parseAsyncModifier(token); |
| 1638 if (optional('=', token)) { | 1640 if (optional('=', token)) { |
| 1639 token = parseRedirectingFactoryBody(token); | 1641 token = parseRedirectingFactoryBody(token); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1664 return token; | 1666 return token; |
| 1665 } | 1667 } |
| 1666 | 1668 |
| 1667 Token parseFunctionExpression(Token token) { | 1669 Token parseFunctionExpression(Token token) { |
| 1668 listener.beginFunction(token); | 1670 listener.beginFunction(token); |
| 1669 listener.handleModifiers(0); | 1671 listener.handleModifiers(0); |
| 1670 token = parseReturnTypeOpt(token); | 1672 token = parseReturnTypeOpt(token); |
| 1671 listener.beginFunctionName(token); | 1673 listener.beginFunctionName(token); |
| 1672 token = parseIdentifier(token); | 1674 token = parseIdentifier(token); |
| 1673 listener.endFunctionName(token); | 1675 listener.endFunctionName(token); |
| 1674 if (enableGenericMethodSyntax) { | 1676 token = parseTypeVariablesOpt(token); |
| 1675 token = parseTypeVariablesOpt(token); | |
| 1676 } else { | |
| 1677 listener.handleNoTypeVariables(token); | |
| 1678 } | |
| 1679 token = parseFormalParameters(token); | 1677 token = parseFormalParameters(token); |
| 1680 listener.handleNoInitializers(); | 1678 listener.handleNoInitializers(); |
| 1681 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; | 1679 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; |
| 1682 token = parseAsyncModifier(token); | 1680 token = parseAsyncModifier(token); |
| 1683 bool isBlock = optional('{', token); | 1681 bool isBlock = optional('{', token); |
| 1684 token = parseFunctionBody(token, true, false); | 1682 token = parseFunctionBody(token, true, false); |
| 1685 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; | 1683 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; |
| 1686 listener.endFunction(null, token); | 1684 listener.endFunction(null, token); |
| 1687 return isBlock ? token.next : token; | 1685 return isBlock ? token.next : token; |
| 1688 } | 1686 } |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1944 // TODO(eernst): Check for NPE as described in issue 26252. | 1942 // TODO(eernst): Check for NPE as described in issue 26252. |
| 1945 Token afterParens = endParen.next; | 1943 Token afterParens = endParen.next; |
| 1946 if (optional('{', afterParens) || | 1944 if (optional('{', afterParens) || |
| 1947 optional('=>', afterParens) || | 1945 optional('=>', afterParens) || |
| 1948 optional('async', afterParens) || | 1946 optional('async', afterParens) || |
| 1949 optional('sync', afterParens)) { | 1947 optional('sync', afterParens)) { |
| 1950 // We are looking at "type identifier '(' ... ')'" followed | 1948 // We are looking at "type identifier '(' ... ')'" followed |
| 1951 // by '{', '=>', 'async', or 'sync'. | 1949 // by '{', '=>', 'async', or 'sync'. |
| 1952 return parseFunctionDeclaration(token); | 1950 return parseFunctionDeclaration(token); |
| 1953 } | 1951 } |
| 1954 } else if (enableGenericMethodSyntax && | 1952 } else if (identical(afterIdKind, LT_TOKEN)) { |
| 1955 identical(afterIdKind, LT_TOKEN)) { | |
| 1956 // We are looking at "type identifier '<'". | 1953 // We are looking at "type identifier '<'". |
| 1957 BeginGroupToken beginAngle = afterId; | 1954 BeginGroupToken beginAngle = afterId; |
| 1958 Token endAngle = beginAngle.endGroup; | 1955 Token endAngle = beginAngle.endGroup; |
| 1959 if (endAngle != null && | 1956 if (endAngle != null && |
| 1960 identical(endAngle.next.kind, OPEN_PAREN_TOKEN)) { | 1957 identical(endAngle.next.kind, OPEN_PAREN_TOKEN)) { |
| 1961 BeginGroupToken beginParen = endAngle.next; | 1958 BeginGroupToken beginParen = endAngle.next; |
| 1962 Token endParen = beginParen.endGroup; | 1959 Token endParen = beginParen.endGroup; |
| 1963 if (endParen != null) { | 1960 if (endParen != null) { |
| 1964 Token afterParens = endParen.next; | 1961 Token afterParens = endParen.next; |
| 1965 if (optional('{', afterParens) || | 1962 if (optional('{', afterParens) || |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1980 } else if (optional('(', token.next)) { | 1977 } else if (optional('(', token.next)) { |
| 1981 BeginGroupToken begin = token.next; | 1978 BeginGroupToken begin = token.next; |
| 1982 // TODO(eernst): Check for NPE as described in issue 26252. | 1979 // TODO(eernst): Check for NPE as described in issue 26252. |
| 1983 String afterParens = begin.endGroup.next.stringValue; | 1980 String afterParens = begin.endGroup.next.stringValue; |
| 1984 if (identical(afterParens, '{') || | 1981 if (identical(afterParens, '{') || |
| 1985 identical(afterParens, '=>') || | 1982 identical(afterParens, '=>') || |
| 1986 identical(afterParens, 'async') || | 1983 identical(afterParens, 'async') || |
| 1987 identical(afterParens, 'sync')) { | 1984 identical(afterParens, 'sync')) { |
| 1988 return parseFunctionDeclaration(token); | 1985 return parseFunctionDeclaration(token); |
| 1989 } | 1986 } |
| 1990 } else if (enableGenericMethodSyntax && optional('<', token.next)) { | 1987 } else if (optional('<', token.next)) { |
| 1991 BeginGroupToken beginAngle = token.next; | 1988 BeginGroupToken beginAngle = token.next; |
| 1992 Token endAngle = beginAngle.endGroup; | 1989 Token endAngle = beginAngle.endGroup; |
| 1993 if (endAngle != null && | 1990 if (endAngle != null && |
| 1994 identical(endAngle.next.kind, OPEN_PAREN_TOKEN)) { | 1991 identical(endAngle.next.kind, OPEN_PAREN_TOKEN)) { |
| 1995 BeginGroupToken beginParen = endAngle.next; | 1992 BeginGroupToken beginParen = endAngle.next; |
| 1996 Token endParen = beginParen.endGroup; | 1993 Token endParen = beginParen.endGroup; |
| 1997 if (endParen != null) { | 1994 if (endParen != null) { |
| 1998 String afterParens = endParen.next.stringValue; | 1995 String afterParens = endParen.next.stringValue; |
| 1999 if (identical(afterParens, '{') || | 1996 if (identical(afterParens, '{') || |
| 2000 identical(afterParens, '=>') || | 1997 identical(afterParens, '=>') || |
| (...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2494 /// Where | 2491 /// Where |
| 2495 /// genericListLiteral ::= typeArguments '[' (expressionList ','?)? ']' | 2492 /// genericListLiteral ::= typeArguments '[' (expressionList ','?)? ']' |
| 2496 /// genericMapLiteral ::= | 2493 /// genericMapLiteral ::= |
| 2497 /// typeArguments '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}' | 2494 /// typeArguments '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}' |
| 2498 /// genericFunctionLiteral ::= | 2495 /// genericFunctionLiteral ::= |
| 2499 /// typeParameters formalParameterList functionBody | 2496 /// typeParameters formalParameterList functionBody |
| 2500 /// Provide token for [constKeyword] if preceded by 'const', null if not. | 2497 /// Provide token for [constKeyword] if preceded by 'const', null if not. |
| 2501 Token parseLiteralListOrMapOrFunction(Token token, Token constKeyword) { | 2498 Token parseLiteralListOrMapOrFunction(Token token, Token constKeyword) { |
| 2502 assert(optional('<', token)); | 2499 assert(optional('<', token)); |
| 2503 BeginGroupToken begin = token; | 2500 BeginGroupToken begin = token; |
| 2504 if (enableGenericMethodSyntax && | 2501 if (constKeyword == null && |
| 2505 constKeyword == null && | |
| 2506 begin.endGroup != null && | 2502 begin.endGroup != null && |
| 2507 identical(begin.endGroup.next.kind, OPEN_PAREN_TOKEN)) { | 2503 identical(begin.endGroup.next.kind, OPEN_PAREN_TOKEN)) { |
| 2508 token = parseTypeVariablesOpt(token); | 2504 token = parseTypeVariablesOpt(token); |
| 2509 return parseLiteralFunctionSuffix(token); | 2505 return parseLiteralFunctionSuffix(token); |
| 2510 } else { | 2506 } else { |
| 2511 token = parseTypeArgumentsOpt(token); | 2507 token = parseTypeArgumentsOpt(token); |
| 2512 if (optional('{', token)) { | 2508 if (optional('{', token)) { |
| 2513 return parseLiteralMapSuffix(token, constKeyword); | 2509 return parseLiteralMapSuffix(token, constKeyword); |
| 2514 } else if ((optional('[', token)) || (optional('[]', token))) { | 2510 } else if ((optional('[', token)) || (optional('[]', token))) { |
| 2515 return parseLiteralListSuffix(token, constKeyword); | 2511 return parseLiteralListSuffix(token, constKeyword); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2538 isFunctionDeclaration(peek.next)) { | 2534 isFunctionDeclaration(peek.next)) { |
| 2539 return parseFunctionExpression(token); | 2535 return parseFunctionExpression(token); |
| 2540 } else if (isFunctionDeclaration(token.next)) { | 2536 } else if (isFunctionDeclaration(token.next)) { |
| 2541 return parseFunctionExpression(token); | 2537 return parseFunctionExpression(token); |
| 2542 } else { | 2538 } else { |
| 2543 return parseSend(token); | 2539 return parseSend(token); |
| 2544 } | 2540 } |
| 2545 } | 2541 } |
| 2546 | 2542 |
| 2547 bool isFunctionDeclaration(Token token) { | 2543 bool isFunctionDeclaration(Token token) { |
| 2548 if (enableGenericMethodSyntax && optional('<', token)) { | 2544 if (optional('<', token)) { |
| 2549 BeginGroupToken begin = token; | 2545 BeginGroupToken begin = token; |
| 2550 if (begin.endGroup == null) return false; | 2546 if (begin.endGroup == null) return false; |
| 2551 token = begin.endGroup.next; | 2547 token = begin.endGroup.next; |
| 2552 } | 2548 } |
| 2553 if (optional('(', token)) { | 2549 if (optional('(', token)) { |
| 2554 BeginGroupToken begin = token; | 2550 BeginGroupToken begin = token; |
| 2555 // TODO(eernst): Check for NPE as described in issue 26252. | 2551 // TODO(eernst): Check for NPE as described in issue 26252. |
| 2556 String afterParens = begin.endGroup.next.stringValue; | 2552 String afterParens = begin.endGroup.next.stringValue; |
| 2557 if (identical(afterParens, '{') || | 2553 if (identical(afterParens, '{') || |
| 2558 identical(afterParens, '=>') || | 2554 identical(afterParens, '=>') || |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2687 } | 2683 } |
| 2688 | 2684 |
| 2689 Token parseLiteralNull(Token token) { | 2685 Token parseLiteralNull(Token token) { |
| 2690 listener.handleLiteralNull(token); | 2686 listener.handleLiteralNull(token); |
| 2691 return token.next; | 2687 return token.next; |
| 2692 } | 2688 } |
| 2693 | 2689 |
| 2694 Token parseSend(Token token) { | 2690 Token parseSend(Token token) { |
| 2695 listener.beginSend(token); | 2691 listener.beginSend(token); |
| 2696 token = parseIdentifier(token); | 2692 token = parseIdentifier(token); |
| 2697 if (enableGenericMethodSyntax && isValidMethodTypeArguments(token)) { | 2693 if (isValidMethodTypeArguments(token)) { |
| 2698 token = parseTypeArgumentsOpt(token); | 2694 token = parseTypeArgumentsOpt(token); |
| 2699 } else { | 2695 } else { |
| 2700 listener.handleNoTypeArguments(token); | 2696 listener.handleNoTypeArguments(token); |
| 2701 } | 2697 } |
| 2702 token = parseArgumentsOpt(token); | 2698 token = parseArgumentsOpt(token); |
| 2703 listener.endSend(token); | 2699 listener.endSend(token); |
| 2704 return token; | 2700 return token; |
| 2705 } | 2701 } |
| 2706 | 2702 |
| 2707 Token skipArgumentsOpt(Token token) { | 2703 Token skipArgumentsOpt(Token token) { |
| (...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3174 } | 3170 } |
| 3175 listener.handleContinueStatement(hasTarget, continueKeyword, token); | 3171 listener.handleContinueStatement(hasTarget, continueKeyword, token); |
| 3176 return expectSemicolon(token); | 3172 return expectSemicolon(token); |
| 3177 } | 3173 } |
| 3178 | 3174 |
| 3179 Token parseEmptyStatement(Token token) { | 3175 Token parseEmptyStatement(Token token) { |
| 3180 listener.handleEmptyStatement(token); | 3176 listener.handleEmptyStatement(token); |
| 3181 return expectSemicolon(token); | 3177 return expectSemicolon(token); |
| 3182 } | 3178 } |
| 3183 } | 3179 } |
| OLD | NEW |