| 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 dart2js.parser; | 5 library dart2js.parser; |
| 6 | 6 |
| 7 import '../options.dart' show ParserOptions; | 7 import '../options.dart' show ParserOptions; |
| 8 import '../common.dart'; | 8 import '../common.dart'; |
| 9 import '../tokens/keyword.dart' show Keyword; | 9 import '../tokens/keyword.dart' show Keyword; |
| 10 import '../tokens/precedence.dart' show PrecedenceInfo; | 10 import '../tokens/precedence.dart' show PrecedenceInfo; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 SymbolToken, | 34 SymbolToken, |
| 35 Token; | 35 Token; |
| 36 import '../tokens/token_constants.dart' | 36 import '../tokens/token_constants.dart' |
| 37 show | 37 show |
| 38 BAD_INPUT_TOKEN, | 38 BAD_INPUT_TOKEN, |
| 39 COMMA_TOKEN, | 39 COMMA_TOKEN, |
| 40 DOUBLE_TOKEN, | 40 DOUBLE_TOKEN, |
| 41 EOF_TOKEN, | 41 EOF_TOKEN, |
| 42 EQ_TOKEN, | 42 EQ_TOKEN, |
| 43 FUNCTION_TOKEN, | 43 FUNCTION_TOKEN, |
| 44 GT_TOKEN, |
| 45 GT_GT_TOKEN, |
| 44 HASH_TOKEN, | 46 HASH_TOKEN, |
| 45 HEXADECIMAL_TOKEN, | 47 HEXADECIMAL_TOKEN, |
| 46 IDENTIFIER_TOKEN, | 48 IDENTIFIER_TOKEN, |
| 47 INT_TOKEN, | 49 INT_TOKEN, |
| 48 KEYWORD_TOKEN, | 50 KEYWORD_TOKEN, |
| 49 LT_TOKEN, | 51 LT_TOKEN, |
| 50 OPEN_CURLY_BRACKET_TOKEN, | 52 OPEN_CURLY_BRACKET_TOKEN, |
| 51 OPEN_PAREN_TOKEN, | 53 OPEN_PAREN_TOKEN, |
| 52 OPEN_SQUARE_BRACKET_TOKEN, | 54 OPEN_SQUARE_BRACKET_TOKEN, |
| 53 PERIOD_TOKEN, | 55 PERIOD_TOKEN, |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 * matches, "star" means zero or more matches. For example, | 95 * matches, "star" means zero or more matches. For example, |
| 94 * [parseMetadataStar] corresponds to this grammar snippet: [: | 96 * [parseMetadataStar] corresponds to this grammar snippet: [: |
| 95 * metadata* :], and [parseTypeOpt] corresponds to: [: type? :]. | 97 * metadata* :], and [parseTypeOpt] corresponds to: [: type? :]. |
| 96 */ | 98 */ |
| 97 class Parser { | 99 class Parser { |
| 98 final Listener listener; | 100 final Listener listener; |
| 99 final ParserOptions parserOptions; | 101 final ParserOptions parserOptions; |
| 100 bool mayParseFunctionExpressions = true; | 102 bool mayParseFunctionExpressions = true; |
| 101 bool asyncAwaitKeywordsEnabled; | 103 bool asyncAwaitKeywordsEnabled; |
| 102 | 104 |
| 103 Parser(this.listener, this.parserOptions, | 105 final bool enableGenericMethodSyntax; |
| 104 {this.asyncAwaitKeywordsEnabled: false}); | 106 |
| 107 Parser(this.listener, ParserOptions parserOptions, |
| 108 {this.asyncAwaitKeywordsEnabled: false}) : |
| 109 parserOptions = parserOptions, |
| 110 enableGenericMethodSyntax = parserOptions.enableGenericMethodSyntax; |
| 105 | 111 |
| 106 Token parseUnit(Token token) { | 112 Token parseUnit(Token token) { |
| 107 listener.beginCompilationUnit(token); | 113 listener.beginCompilationUnit(token); |
| 108 int count = 0; | 114 int count = 0; |
| 109 while (!identical(token.kind, EOF_TOKEN)) { | 115 while (!identical(token.kind, EOF_TOKEN)) { |
| 110 token = parseTopLevelDeclaration(token); | 116 token = parseTopLevelDeclaration(token); |
| 111 listener.endTopLevelDeclaration(token); | 117 listener.endTopLevelDeclaration(token); |
| 112 count++; | 118 count++; |
| 113 } | 119 } |
| 114 listener.endCompilationUnit(count, token); | 120 listener.endCompilationUnit(count, token); |
| (...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 515 if (identical(kind, KEYWORD_TOKEN)) { | 521 if (identical(kind, KEYWORD_TOKEN)) { |
| 516 Keyword keyword = (token as KeywordToken).keyword; | 522 Keyword keyword = (token as KeywordToken).keyword; |
| 517 String value = keyword.syntax; | 523 String value = keyword.syntax; |
| 518 return keyword.isPseudo || | 524 return keyword.isPseudo || |
| 519 (identical(value, 'dynamic')) || | 525 (identical(value, 'dynamic')) || |
| 520 (identical(value, 'void')); | 526 (identical(value, 'void')); |
| 521 } | 527 } |
| 522 return false; | 528 return false; |
| 523 } | 529 } |
| 524 | 530 |
| 531 /// Returns true if [token] matches '<' type (',' type)* '>' '(', and |
| 532 /// otherwise returns false. The final '(' is not part of the grammar |
| 533 /// construct `typeArguments`, but it is required here such that type |
| 534 /// arguments in generic method invocations can be recognized, and as few as |
| 535 /// possible other constructs will pass (e.g., 'a < C, D > 3'). |
| 536 bool isValidMethodTypeArguments(Token token) { |
| 537 return tryParseMethodTypeArguments(token) != null; |
| 538 } |
| 539 |
| 540 /// Returns token after match if [token] matches '<' type (',' type)* '>' '(', |
| 541 /// and otherwise returns null. Does not produce listener events. With respect |
| 542 /// to the final '(', please see the description of |
| 543 /// [isValidMethodTypeArguments]. |
| 544 Token tryParseMethodTypeArguments(Token token) { |
| 545 if (!identical(token.kind, LT_TOKEN)) return null; |
| 546 BeginGroupToken beginToken = token; |
| 547 Token endToken = beginToken.endGroup; |
| 548 if (endToken == null || !identical(endToken.next.kind, OPEN_PAREN_TOKEN)) { |
| 549 return null; |
| 550 } |
| 551 token = tryParseType(token.next); |
| 552 while (token != null && identical(token.kind, COMMA_TOKEN)) { |
| 553 token = tryParseType(token.next); |
| 554 } |
| 555 if (token == null || !identical(token.kind, GT_TOKEN)) return null; |
| 556 return token.next; |
| 557 } |
| 558 |
| 559 /// Returns token after match if [token] matches typeName typeArguments?, and |
| 560 /// otherwise returns null. Does not produce listener events. |
| 561 Token tryParseType(Token token) { |
| 562 token = tryParseQualified(token); |
| 563 if (token == null) return null; |
| 564 Token tokenAfterQualified = token; |
| 565 token = tryParseNestedTypeArguments(token); |
| 566 return token == null ? tokenAfterQualified : token; |
| 567 } |
| 568 |
| 569 /// Returns token after match if [token] matches identifier ('.' identifier)?, |
| 570 /// and otherwise returns null. Does not produce listener events. |
| 571 Token tryParseQualified(Token token) { |
| 572 if (!identical(token.kind, IDENTIFIER_TOKEN)) return null; |
| 573 token = token.next; |
| 574 if (!identical(token.kind, PERIOD_TOKEN)) return token; |
| 575 token = token.next; |
| 576 if (!identical(token.kind, IDENTIFIER_TOKEN)) return null; |
| 577 return token.next; |
| 578 } |
| 579 |
| 580 /// Returns token after match if [token] matches '<' type (',' type)* '>', |
| 581 /// and otherwise returns null. Does not produce listener events. The final |
| 582 /// '>' may be the first character in a '>>' token, in which case a synthetic |
| 583 /// '>' token is created and returned, representing the second '>' in the |
| 584 /// '>>' token. |
| 585 Token tryParseNestedTypeArguments(Token token) { |
| 586 if (!identical(token.kind, LT_TOKEN)) return null; |
| 587 // If the initial '<' matches the first '>' in a '>>' token, we will have |
| 588 // `token.endGroup == null`, so we cannot rely on `token.endGroup == null` |
| 589 // to imply that the match must fail. Hence no `token.endGroup == null` |
| 590 // test here. |
| 591 token = tryParseType(token.next); |
| 592 while (token != null && identical(token.kind, COMMA_TOKEN)) { |
| 593 token = tryParseType(token.next); |
| 594 } |
| 595 if (token == null) return null; |
| 596 if (identical(token.kind, GT_TOKEN)) return token.next; |
| 597 if (!identical(token.kind, GT_GT_TOKEN)) return null; |
| 598 // [token] is '>>' of which the final '>' that we are parsing is the first |
| 599 // character. In order to keep the parsing process on track we must return |
| 600 // a synthetic '>' corresponding to the second character of that '>>'. |
| 601 Token syntheticToken = new SymbolToken(GT_INFO, token.charOffset + 1); |
| 602 syntheticToken.next = token.next; |
| 603 return syntheticToken; |
| 604 } |
| 605 |
| 525 Token parseQualified(Token token) { | 606 Token parseQualified(Token token) { |
| 526 token = parseIdentifier(token); | 607 token = parseIdentifier(token); |
| 527 while (optional('.', token)) { | 608 while (optional('.', token)) { |
| 528 token = parseQualifiedRest(token); | 609 token = parseQualifiedRest(token); |
| 529 } | 610 } |
| 530 return token; | 611 return token; |
| 531 } | 612 } |
| 532 | 613 |
| 533 Token parseQualifiedRestOpt(Token token) { | 614 Token parseQualifiedRestOpt(Token token) { |
| 534 if (optional('.', token)) { | 615 if (optional('.', token)) { |
| (...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 993 listener.handleModifiers(0); | 1074 listener.handleModifiers(0); |
| 994 } | 1075 } |
| 995 | 1076 |
| 996 if (type == null) { | 1077 if (type == null) { |
| 997 listener.handleNoType(name); | 1078 listener.handleNoType(name); |
| 998 } else { | 1079 } else { |
| 999 parseReturnTypeOpt(type); | 1080 parseReturnTypeOpt(type); |
| 1000 } | 1081 } |
| 1001 Token token = parseIdentifier(name); | 1082 Token token = parseIdentifier(name); |
| 1002 | 1083 |
| 1084 if (enableGenericMethodSyntax && getOrSet == null) { |
| 1085 token = parseTypeVariablesOpt(token); |
| 1086 } else { |
| 1087 listener.handleNoTypeVariables(token); |
| 1088 } |
| 1003 token = parseFormalParametersOpt(token); | 1089 token = parseFormalParametersOpt(token); |
| 1004 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; | 1090 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; |
| 1005 token = parseAsyncModifier(token); | 1091 token = parseAsyncModifier(token); |
| 1006 token = parseFunctionBody(token, false, externalModifier != null); | 1092 token = parseFunctionBody(token, false, externalModifier != null); |
| 1007 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; | 1093 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; |
| 1008 Token endToken = token; | 1094 Token endToken = token; |
| 1009 token = token.next; | 1095 token = token.next; |
| 1010 if (token.kind == BAD_INPUT_TOKEN) { | 1096 if (token.kind == BAD_INPUT_TOKEN) { |
| 1011 token = listener.unexpected(token); | 1097 token = listener.unexpected(token); |
| 1012 } | 1098 } |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1297 | 1383 |
| 1298 token = afterName; | 1384 token = afterName; |
| 1299 bool isField; | 1385 bool isField; |
| 1300 while (true) { | 1386 while (true) { |
| 1301 // Loop to allow the listener to rewrite the token stream for | 1387 // Loop to allow the listener to rewrite the token stream for |
| 1302 // error handling. | 1388 // error handling. |
| 1303 final String value = token.stringValue; | 1389 final String value = token.stringValue; |
| 1304 if ((identical(value, '(')) || | 1390 if ((identical(value, '(')) || |
| 1305 (identical(value, '.')) || | 1391 (identical(value, '.')) || |
| 1306 (identical(value, '{')) || | 1392 (identical(value, '{')) || |
| 1307 (identical(value, '=>'))) { | 1393 (identical(value, '=>')) || |
| 1394 (enableGenericMethodSyntax && identical(value, '<'))) { |
| 1308 isField = false; | 1395 isField = false; |
| 1309 break; | 1396 break; |
| 1310 } else if (identical(value, ';')) { | 1397 } else if (identical(value, ';')) { |
| 1311 if (getOrSet != null) { | 1398 if (getOrSet != null) { |
| 1312 // If we found a "get" keyword, this must be an abstract | 1399 // If we found a "get" keyword, this must be an abstract |
| 1313 // getter. | 1400 // getter. |
| 1314 isField = (!identical(getOrSet.stringValue, 'get')); | 1401 isField = (!identical(getOrSet.stringValue, 'get')); |
| 1315 // TODO(ahe): This feels like a hack. | 1402 // TODO(ahe): This feels like a hack. |
| 1316 } else { | 1403 } else { |
| 1317 isField = true; | 1404 isField = true; |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1389 token = parseOperatorName(name); | 1476 token = parseOperatorName(name); |
| 1390 if (staticModifier != null) { | 1477 if (staticModifier != null) { |
| 1391 listener.reportError(staticModifier, MessageKind.EXTRANEOUS_MODIFIER, | 1478 listener.reportError(staticModifier, MessageKind.EXTRANEOUS_MODIFIER, |
| 1392 {'modifier': staticModifier}); | 1479 {'modifier': staticModifier}); |
| 1393 } | 1480 } |
| 1394 } else { | 1481 } else { |
| 1395 token = parseIdentifier(name); | 1482 token = parseIdentifier(name); |
| 1396 } | 1483 } |
| 1397 | 1484 |
| 1398 token = parseQualifiedRestOpt(token); | 1485 token = parseQualifiedRestOpt(token); |
| 1486 if (enableGenericMethodSyntax && getOrSet == null) { |
| 1487 token = parseTypeVariablesOpt(token); |
| 1488 } else { |
| 1489 listener.handleNoTypeVariables(token); |
| 1490 } |
| 1399 token = parseFormalParametersOpt(token); | 1491 token = parseFormalParametersOpt(token); |
| 1400 token = parseInitializersOpt(token); | 1492 token = parseInitializersOpt(token); |
| 1401 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; | 1493 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; |
| 1402 token = parseAsyncModifier(token); | 1494 token = parseAsyncModifier(token); |
| 1403 if (optional('=', token)) { | 1495 if (optional('=', token)) { |
| 1404 token = parseRedirectingFactoryBody(token); | 1496 token = parseRedirectingFactoryBody(token); |
| 1405 } else { | 1497 } else { |
| 1406 token = parseFunctionBody( | 1498 token = parseFunctionBody( |
| 1407 token, false, staticModifier == null || externalModifier != null); | 1499 token, false, staticModifier == null || externalModifier != null); |
| 1408 } | 1500 } |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1475 } | 1567 } |
| 1476 listener.beginFunctionName(token); | 1568 listener.beginFunctionName(token); |
| 1477 if (optional('operator', token)) { | 1569 if (optional('operator', token)) { |
| 1478 token = parseOperatorName(token); | 1570 token = parseOperatorName(token); |
| 1479 } else { | 1571 } else { |
| 1480 token = parseIdentifier(token); | 1572 token = parseIdentifier(token); |
| 1481 } | 1573 } |
| 1482 } | 1574 } |
| 1483 token = parseQualifiedRestOpt(token); | 1575 token = parseQualifiedRestOpt(token); |
| 1484 listener.endFunctionName(token); | 1576 listener.endFunctionName(token); |
| 1577 if (enableGenericMethodSyntax && getOrSet == null) { |
| 1578 token = parseTypeVariablesOpt(token); |
| 1579 } else { |
| 1580 listener.handleNoTypeVariables(token); |
| 1581 } |
| 1485 token = parseFormalParametersOpt(token); | 1582 token = parseFormalParametersOpt(token); |
| 1486 token = parseInitializersOpt(token); | 1583 token = parseInitializersOpt(token); |
| 1487 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; | 1584 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; |
| 1488 token = parseAsyncModifier(token); | 1585 token = parseAsyncModifier(token); |
| 1489 if (optional('=', token)) { | 1586 if (optional('=', token)) { |
| 1490 token = parseRedirectingFactoryBody(token); | 1587 token = parseRedirectingFactoryBody(token); |
| 1491 } else { | 1588 } else { |
| 1492 token = parseFunctionBody(token, false, true); | 1589 token = parseFunctionBody(token, false, true); |
| 1493 } | 1590 } |
| 1494 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; | 1591 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1515 return token; | 1612 return token; |
| 1516 } | 1613 } |
| 1517 | 1614 |
| 1518 Token parseFunctionExpression(Token token) { | 1615 Token parseFunctionExpression(Token token) { |
| 1519 listener.beginFunction(token); | 1616 listener.beginFunction(token); |
| 1520 listener.handleModifiers(0); | 1617 listener.handleModifiers(0); |
| 1521 token = parseReturnTypeOpt(token); | 1618 token = parseReturnTypeOpt(token); |
| 1522 listener.beginFunctionName(token); | 1619 listener.beginFunctionName(token); |
| 1523 token = parseIdentifier(token); | 1620 token = parseIdentifier(token); |
| 1524 listener.endFunctionName(token); | 1621 listener.endFunctionName(token); |
| 1622 if (enableGenericMethodSyntax) { |
| 1623 token = parseTypeVariablesOpt(token); |
| 1624 } else { |
| 1625 listener.handleNoTypeVariables(token); |
| 1626 } |
| 1525 token = parseFormalParameters(token); | 1627 token = parseFormalParameters(token); |
| 1526 listener.handleNoInitializers(); | 1628 listener.handleNoInitializers(); |
| 1527 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; | 1629 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; |
| 1528 token = parseAsyncModifier(token); | 1630 token = parseAsyncModifier(token); |
| 1529 bool isBlock = optional('{', token); | 1631 bool isBlock = optional('{', token); |
| 1530 token = parseFunctionBody(token, true, false); | 1632 token = parseFunctionBody(token, true, false); |
| 1531 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; | 1633 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; |
| 1532 listener.endFunction(null, token); | 1634 listener.endFunction(null, token); |
| 1533 return isBlock ? token.next : token; | 1635 return isBlock ? token.next : token; |
| 1534 } | 1636 } |
| (...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1978 while (true) { | 2080 while (true) { |
| 1979 if (optional('[', token)) { | 2081 if (optional('[', token)) { |
| 1980 Token openSquareBracket = token; | 2082 Token openSquareBracket = token; |
| 1981 bool old = mayParseFunctionExpressions; | 2083 bool old = mayParseFunctionExpressions; |
| 1982 mayParseFunctionExpressions = true; | 2084 mayParseFunctionExpressions = true; |
| 1983 token = parseExpression(token.next); | 2085 token = parseExpression(token.next); |
| 1984 mayParseFunctionExpressions = old; | 2086 mayParseFunctionExpressions = old; |
| 1985 listener.handleIndexedExpression(openSquareBracket, token); | 2087 listener.handleIndexedExpression(openSquareBracket, token); |
| 1986 token = expect(']', token); | 2088 token = expect(']', token); |
| 1987 } else if (optional('(', token)) { | 2089 } else if (optional('(', token)) { |
| 2090 listener.handleNoTypeArguments(token); |
| 1988 token = parseArguments(token); | 2091 token = parseArguments(token); |
| 1989 listener.endSend(token); | 2092 listener.endSend(token); |
| 1990 } else { | 2093 } else { |
| 1991 break; | 2094 break; |
| 1992 } | 2095 } |
| 1993 } | 2096 } |
| 1994 return token; | 2097 return token; |
| 1995 } | 2098 } |
| 1996 | 2099 |
| 1997 Token parsePrimary(Token token) { | 2100 Token parsePrimary(Token token) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2074 } | 2177 } |
| 2075 listener.handleParenthesizedExpression(begin); | 2178 listener.handleParenthesizedExpression(begin); |
| 2076 return expect(')', token); | 2179 return expect(')', token); |
| 2077 } | 2180 } |
| 2078 | 2181 |
| 2079 Token parseThisExpression(Token token) { | 2182 Token parseThisExpression(Token token) { |
| 2080 listener.handleThisExpression(token); | 2183 listener.handleThisExpression(token); |
| 2081 token = token.next; | 2184 token = token.next; |
| 2082 if (optional('(', token)) { | 2185 if (optional('(', token)) { |
| 2083 // Constructor forwarding. | 2186 // Constructor forwarding. |
| 2187 listener.handleNoTypeArguments(token); |
| 2084 token = parseArguments(token); | 2188 token = parseArguments(token); |
| 2085 listener.endSend(token); | 2189 listener.endSend(token); |
| 2086 } | 2190 } |
| 2087 return token; | 2191 return token; |
| 2088 } | 2192 } |
| 2089 | 2193 |
| 2090 Token parseSuperExpression(Token token) { | 2194 Token parseSuperExpression(Token token) { |
| 2091 listener.handleSuperExpression(token); | 2195 listener.handleSuperExpression(token); |
| 2092 token = token.next; | 2196 token = token.next; |
| 2093 if (optional('(', token)) { | 2197 if (optional('(', token)) { |
| 2094 // Super constructor. | 2198 // Super constructor. |
| 2199 listener.handleNoTypeArguments(token); |
| 2095 token = parseArguments(token); | 2200 token = parseArguments(token); |
| 2096 listener.endSend(token); | 2201 listener.endSend(token); |
| 2097 } | 2202 } |
| 2098 return token; | 2203 return token; |
| 2099 } | 2204 } |
| 2100 | 2205 |
| 2101 Token parseLiteralListOrMap(Token token) { | 2206 Token parseLiteralListOrMap(Token token) { |
| 2102 Token constKeyword = null; | 2207 Token constKeyword = null; |
| 2103 if (optional('const', token)) { | 2208 if (optional('const', token)) { |
| 2104 constKeyword = token; | 2209 constKeyword = token; |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2301 } | 2406 } |
| 2302 | 2407 |
| 2303 Token parseLiteralNull(Token token) { | 2408 Token parseLiteralNull(Token token) { |
| 2304 listener.handleLiteralNull(token); | 2409 listener.handleLiteralNull(token); |
| 2305 return token.next; | 2410 return token.next; |
| 2306 } | 2411 } |
| 2307 | 2412 |
| 2308 Token parseSend(Token token) { | 2413 Token parseSend(Token token) { |
| 2309 listener.beginSend(token); | 2414 listener.beginSend(token); |
| 2310 token = parseIdentifier(token); | 2415 token = parseIdentifier(token); |
| 2416 if (enableGenericMethodSyntax && isValidMethodTypeArguments(token)) { |
| 2417 token = parseTypeArgumentsOpt(token); |
| 2418 } else { |
| 2419 listener.handleNoTypeArguments(token); |
| 2420 } |
| 2311 token = parseArgumentsOpt(token); | 2421 token = parseArgumentsOpt(token); |
| 2312 listener.endSend(token); | 2422 listener.endSend(token); |
| 2313 return token; | 2423 return token; |
| 2314 } | 2424 } |
| 2315 | 2425 |
| 2316 Token parseArgumentsOpt(Token token) { | 2426 Token parseArgumentsOpt(Token token) { |
| 2317 if (!optional('(', token)) { | 2427 if (!optional('(', token)) { |
| 2318 listener.handleNoArguments(token); | 2428 listener.handleNoArguments(token); |
| 2319 return token; | 2429 return token; |
| 2320 } else { | 2430 } else { |
| (...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2751 } | 2861 } |
| 2752 listener.handleContinueStatement(hasTarget, continueKeyword, token); | 2862 listener.handleContinueStatement(hasTarget, continueKeyword, token); |
| 2753 return expectSemicolon(token); | 2863 return expectSemicolon(token); |
| 2754 } | 2864 } |
| 2755 | 2865 |
| 2756 Token parseEmptyStatement(Token token) { | 2866 Token parseEmptyStatement(Token token) { |
| 2757 listener.handleEmptyStatement(token); | 2867 listener.handleEmptyStatement(token); |
| 2758 return expectSemicolon(token); | 2868 return expectSemicolon(token); |
| 2759 } | 2869 } |
| 2760 } | 2870 } |
| OLD | NEW |