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

Side by Side Diff: pkg/compiler/lib/src/parser/parser.dart

Issue 1863053003: Adds support for --generic-method-syntax (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 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
OLDNEW
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 7 import '../options.dart' show
8 ParserOptions; 8 ParserOptions;
9 import '../common.dart'; 9 import '../common.dart';
10 import '../tokens/keyword.dart' show 10 import '../tokens/keyword.dart' show
(...skipping 23 matching lines...) Expand all
34 KeywordToken, 34 KeywordToken,
35 SymbolToken, 35 SymbolToken,
36 Token; 36 Token;
37 import '../tokens/token_constants.dart' show 37 import '../tokens/token_constants.dart' 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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 * matches, "star" means zero or more matches. For example, 98 * matches, "star" means zero or more matches. For example,
97 * [parseMetadataStar] corresponds to this grammar snippet: [: 99 * [parseMetadataStar] corresponds to this grammar snippet: [:
98 * metadata* :], and [parseTypeOpt] corresponds to: [: type? :]. 100 * metadata* :], and [parseTypeOpt] corresponds to: [: type? :].
99 */ 101 */
100 class Parser { 102 class Parser {
101 final Listener listener; 103 final Listener listener;
102 final ParserOptions parserOptions; 104 final ParserOptions parserOptions;
103 bool mayParseFunctionExpressions = true; 105 bool mayParseFunctionExpressions = true;
104 bool asyncAwaitKeywordsEnabled; 106 bool asyncAwaitKeywordsEnabled;
105 107
106 Parser(this.listener, this.parserOptions, 108 final bool enableGenericMethodSyntax;
107 {this.asyncAwaitKeywordsEnabled: false}); 109
110 Parser(this.listener, ParserOptions parserOptions,
111 {this.asyncAwaitKeywordsEnabled: false}) :
112 parserOptions = parserOptions,
113 enableGenericMethodSyntax = parserOptions.enableGenericMethodSyntax;
108 114
109 Token parseUnit(Token token) { 115 Token parseUnit(Token token) {
110 listener.beginCompilationUnit(token); 116 listener.beginCompilationUnit(token);
111 int count = 0; 117 int count = 0;
112 while (!identical(token.kind, EOF_TOKEN)) { 118 while (!identical(token.kind, EOF_TOKEN)) {
113 token = parseTopLevelDeclaration(token); 119 token = parseTopLevelDeclaration(token);
114 listener.endTopLevelDeclaration(token); 120 listener.endTopLevelDeclaration(token);
115 count++; 121 count++;
116 } 122 }
117 listener.endCompilationUnit(count, token); 123 listener.endCompilationUnit(count, token);
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 if (identical(kind, KEYWORD_TOKEN)) { 524 if (identical(kind, KEYWORD_TOKEN)) {
519 Keyword keyword = (token as KeywordToken).keyword; 525 Keyword keyword = (token as KeywordToken).keyword;
520 String value = keyword.syntax; 526 String value = keyword.syntax;
521 return keyword.isPseudo 527 return keyword.isPseudo
522 || (identical(value, 'dynamic')) 528 || (identical(value, 'dynamic'))
523 || (identical(value, 'void')); 529 || (identical(value, 'void'));
524 } 530 }
525 return false; 531 return false;
526 } 532 }
527 533
534 /// Returns true if [token] matches '<' type (',' type)* '>' '(', and
535 /// otherwise returns false. The final '(' is not part of the grammar
536 /// construct `typeArguments`, but it is required here such that type
537 /// arguments in generic method invocations can be recognized, and as few as
538 /// possible other constructs will pass (e.g., 'a < C, D > 3').
539 bool isValidMethodTypeArguments(Token token) {
540 return tryParseMethodTypeArguments(token) != null;
541 }
542
543 /// Returns token after match if [token] matches '<' type (',' type)* '>' '(',
544 /// and otherwise returns null. Does not produce listener events. With respect
545 /// to the final '(', please see the description of
546 /// [isValidMethodTypeArguments].
547 Token tryParseMethodTypeArguments(Token token) {
548 if (!identical(token.kind, LT_TOKEN)) return null;
549 BeginGroupToken beginToken = token;
550 Token endToken = beginToken.endGroup;
551 if (endToken == null ||
552 !identical(endToken.next.kind, OPEN_PAREN_TOKEN)) return null;
Johnni Winther 2016/04/11 12:41:00 Nit: Add braces arround `return null;`
eernst 2016/04/11 12:55:30 Done.
553 token = tryParseType(token.next);
554 while (token != null && identical(token.kind, COMMA_TOKEN)) {
555 token = tryParseType(token.next);
556 }
557 if (token == null || !identical(token.kind, GT_TOKEN)) return null;
558 return token.next;
559 }
560
561 /// Returns token after match if [token] matches typeName typeArguments?, and
562 /// otherwise returns null. Does not produce listener events.
563 Token tryParseType(Token token) {
564 token = tryParseQualified(token);
565 if (token == null) return null;
566 Token tokenAfterQualified = token;
567 token = tryParseNestedTypeArguments(token);
568 return token == null ? tokenAfterQualified : token;
569 }
570
571 /// Returns token after match if [token] matches identifier ('.' identifier)?,
572 /// and otherwise returns null. Does not produce listener events.
573 Token tryParseQualified(Token token) {
574 if (!identical(token.kind, IDENTIFIER_TOKEN)) return null;
575 token = token.next;
576 if (!identical(token.kind, PERIOD_TOKEN)) return token;
577 token = token.next;
578 if (!identical(token.kind, IDENTIFIER_TOKEN)) return null;
579 return token.next;
580 }
581
582 /// Returns token after match if [token] matches '<' type (',' type)* '>',
583 /// and otherwise returns null. Does not produce listener events. The final
584 /// '>' may be the first character in a '>>' token, in which case a synthetic
585 /// '>' token is created and returned, representing the second '>' in the
586 /// '>>' token.
587 Token tryParseNestedTypeArguments(Token token) {
588 if (!identical(token.kind, LT_TOKEN)) return null;
589 // If the initial '<' matches the first '>' in a '>>' token, we will have
590 // `token.endGroup == null`, so we cannot rely on `token.endGroup == null`
591 // to imply that the match must fail. Hence no `token.endGroup == null`
592 // test here.
593 token = tryParseType(token.next);
594 while (token != null && identical(token.kind, COMMA_TOKEN)) {
595 token = tryParseType(token.next);
596 }
597 if (token == null) return null;
598 if (identical(token.kind, GT_TOKEN)) return token.next;
599 if (!identical(token.kind, GT_GT_TOKEN)) return null;
600 // [token] is '>>' of which the final '>' that we are parsing is the first
601 // character. In order to keep the parsing process on track we must return
602 // a synthetic '>' corresponding to the second character of that '>>'.
603 Token syntheticToken = new SymbolToken(GT_INFO, token.charOffset + 1);
604 syntheticToken.next = token.next;
605 return syntheticToken;
606 }
607
528 Token parseQualified(Token token) { 608 Token parseQualified(Token token) {
529 token = parseIdentifier(token); 609 token = parseIdentifier(token);
530 while (optional('.', token)) { 610 while (optional('.', token)) {
531 token = parseQualifiedRest(token); 611 token = parseQualifiedRest(token);
532 } 612 }
533 return token; 613 return token;
534 } 614 }
535 615
536 Token parseQualifiedRestOpt(Token token) { 616 Token parseQualifiedRestOpt(Token token) {
537 if (optional('.', token)) { 617 if (optional('.', token)) {
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after
1004 listener.handleModifiers(0); 1084 listener.handleModifiers(0);
1005 } 1085 }
1006 1086
1007 if (type == null) { 1087 if (type == null) {
1008 listener.handleNoType(name); 1088 listener.handleNoType(name);
1009 } else { 1089 } else {
1010 parseReturnTypeOpt(type); 1090 parseReturnTypeOpt(type);
1011 } 1091 }
1012 Token token = parseIdentifier(name); 1092 Token token = parseIdentifier(name);
1013 1093
1094 if (enableGenericMethodSyntax && getOrSet == null) {
1095 token = parseTypeVariablesOpt(token);
1096 } else {
1097 listener.handleNoTypeVariables(token);
1098 }
1014 token = parseFormalParametersOpt(token); 1099 token = parseFormalParametersOpt(token);
1015 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; 1100 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled;
1016 token = parseAsyncModifier(token); 1101 token = parseAsyncModifier(token);
1017 token = parseFunctionBody(token, false, externalModifier != null); 1102 token = parseFunctionBody(token, false, externalModifier != null);
1018 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; 1103 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled;
1019 Token endToken = token; 1104 Token endToken = token;
1020 token = token.next; 1105 token = token.next;
1021 if (token.kind == BAD_INPUT_TOKEN) { 1106 if (token.kind == BAD_INPUT_TOKEN) {
1022 token = listener.unexpected(token); 1107 token = listener.unexpected(token);
1023 } 1108 }
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
1312 } 1397 }
1313 } 1398 }
1314 1399
1315 token = afterName; 1400 token = afterName;
1316 bool isField; 1401 bool isField;
1317 while (true) { 1402 while (true) {
1318 // Loop to allow the listener to rewrite the token stream for 1403 // Loop to allow the listener to rewrite the token stream for
1319 // error handling. 1404 // error handling.
1320 final String value = token.stringValue; 1405 final String value = token.stringValue;
1321 if ((identical(value, '(')) || (identical(value, '.')) 1406 if ((identical(value, '(')) || (identical(value, '.'))
1322 || (identical(value, '{')) || (identical(value, '=>'))) { 1407 || (identical(value, '{')) || (identical(value, '=>'))
1408 || (enableGenericMethodSyntax && identical(value, '<'))) {
1323 isField = false; 1409 isField = false;
1324 break; 1410 break;
1325 } else if (identical(value, ';')) { 1411 } else if (identical(value, ';')) {
1326 if (getOrSet != null) { 1412 if (getOrSet != null) {
1327 // If we found a "get" keyword, this must be an abstract 1413 // If we found a "get" keyword, this must be an abstract
1328 // getter. 1414 // getter.
1329 isField = (!identical(getOrSet.stringValue, 'get')); 1415 isField = (!identical(getOrSet.stringValue, 'get'));
1330 // TODO(ahe): This feels like a hack. 1416 // TODO(ahe): This feels like a hack.
1331 } else { 1417 } else {
1332 isField = true; 1418 isField = true;
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1413 if (staticModifier != null) { 1499 if (staticModifier != null) {
1414 listener.reportError( 1500 listener.reportError(
1415 staticModifier, MessageKind.EXTRANEOUS_MODIFIER, 1501 staticModifier, MessageKind.EXTRANEOUS_MODIFIER,
1416 {'modifier': staticModifier}); 1502 {'modifier': staticModifier});
1417 } 1503 }
1418 } else { 1504 } else {
1419 token = parseIdentifier(name); 1505 token = parseIdentifier(name);
1420 } 1506 }
1421 1507
1422 token = parseQualifiedRestOpt(token); 1508 token = parseQualifiedRestOpt(token);
1509 if (enableGenericMethodSyntax && getOrSet == null) {
1510 token = parseTypeVariablesOpt(token);
1511 } else {
1512 listener.handleNoTypeVariables(token);
1513 }
1423 token = parseFormalParametersOpt(token); 1514 token = parseFormalParametersOpt(token);
1424 token = parseInitializersOpt(token); 1515 token = parseInitializersOpt(token);
1425 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; 1516 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled;
1426 token = parseAsyncModifier(token); 1517 token = parseAsyncModifier(token);
1427 if (optional('=', token)) { 1518 if (optional('=', token)) {
1428 token = parseRedirectingFactoryBody(token); 1519 token = parseRedirectingFactoryBody(token);
1429 } else { 1520 } else {
1430 token = parseFunctionBody( 1521 token = parseFunctionBody(
1431 token, false, staticModifier == null || externalModifier != null); 1522 token, false, staticModifier == null || externalModifier != null);
1432 } 1523 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1499 } 1590 }
1500 listener.beginFunctionName(token); 1591 listener.beginFunctionName(token);
1501 if (optional('operator', token)) { 1592 if (optional('operator', token)) {
1502 token = parseOperatorName(token); 1593 token = parseOperatorName(token);
1503 } else { 1594 } else {
1504 token = parseIdentifier(token); 1595 token = parseIdentifier(token);
1505 } 1596 }
1506 } 1597 }
1507 token = parseQualifiedRestOpt(token); 1598 token = parseQualifiedRestOpt(token);
1508 listener.endFunctionName(token); 1599 listener.endFunctionName(token);
1600 if (enableGenericMethodSyntax && getOrSet == null) {
1601 token = parseTypeVariablesOpt(token);
1602 } else {
1603 listener.handleNoTypeVariables(token);
1604 }
1509 token = parseFormalParametersOpt(token); 1605 token = parseFormalParametersOpt(token);
1510 token = parseInitializersOpt(token); 1606 token = parseInitializersOpt(token);
1511 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; 1607 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled;
1512 token = parseAsyncModifier(token); 1608 token = parseAsyncModifier(token);
1513 if (optional('=', token)) { 1609 if (optional('=', token)) {
1514 token = parseRedirectingFactoryBody(token); 1610 token = parseRedirectingFactoryBody(token);
1515 } else { 1611 } else {
1516 token = parseFunctionBody(token, false, true); 1612 token = parseFunctionBody(token, false, true);
1517 } 1613 }
1518 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; 1614 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled;
(...skipping 20 matching lines...) Expand all
1539 return token; 1635 return token;
1540 } 1636 }
1541 1637
1542 Token parseFunctionExpression(Token token) { 1638 Token parseFunctionExpression(Token token) {
1543 listener.beginFunction(token); 1639 listener.beginFunction(token);
1544 listener.handleModifiers(0); 1640 listener.handleModifiers(0);
1545 token = parseReturnTypeOpt(token); 1641 token = parseReturnTypeOpt(token);
1546 listener.beginFunctionName(token); 1642 listener.beginFunctionName(token);
1547 token = parseIdentifier(token); 1643 token = parseIdentifier(token);
1548 listener.endFunctionName(token); 1644 listener.endFunctionName(token);
1645 if (enableGenericMethodSyntax) {
1646 token = parseTypeVariablesOpt(token);
1647 } else {
1648 listener.handleNoTypeVariables(token);
1649 }
1549 token = parseFormalParameters(token); 1650 token = parseFormalParameters(token);
1550 listener.handleNoInitializers(); 1651 listener.handleNoInitializers();
1551 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; 1652 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled;
1552 token = parseAsyncModifier(token); 1653 token = parseAsyncModifier(token);
1553 bool isBlock = optional('{', token); 1654 bool isBlock = optional('{', token);
1554 token = parseFunctionBody(token, true, false); 1655 token = parseFunctionBody(token, true, false);
1555 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; 1656 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled;
1556 listener.endFunction(null, token); 1657 listener.endFunction(null, token);
1557 return isBlock ? token.next : token; 1658 return isBlock ? token.next : token;
1558 } 1659 }
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after
2004 while (true) { 2105 while (true) {
2005 if (optional('[', token)) { 2106 if (optional('[', token)) {
2006 Token openSquareBracket = token; 2107 Token openSquareBracket = token;
2007 bool old = mayParseFunctionExpressions; 2108 bool old = mayParseFunctionExpressions;
2008 mayParseFunctionExpressions = true; 2109 mayParseFunctionExpressions = true;
2009 token = parseExpression(token.next); 2110 token = parseExpression(token.next);
2010 mayParseFunctionExpressions = old; 2111 mayParseFunctionExpressions = old;
2011 listener.handleIndexedExpression(openSquareBracket, token); 2112 listener.handleIndexedExpression(openSquareBracket, token);
2012 token = expect(']', token); 2113 token = expect(']', token);
2013 } else if (optional('(', token)) { 2114 } else if (optional('(', token)) {
2115 listener.handleNoTypeArguments(token);
2014 token = parseArguments(token); 2116 token = parseArguments(token);
2015 listener.endSend(token); 2117 listener.endSend(token);
2016 } else { 2118 } else {
2017 break; 2119 break;
2018 } 2120 }
2019 } 2121 }
2020 return token; 2122 return token;
2021 } 2123 }
2022 2124
2023 Token parsePrimary(Token token) { 2125 Token parsePrimary(Token token) {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
2101 } 2203 }
2102 listener.handleParenthesizedExpression(begin); 2204 listener.handleParenthesizedExpression(begin);
2103 return expect(')', token); 2205 return expect(')', token);
2104 } 2206 }
2105 2207
2106 Token parseThisExpression(Token token) { 2208 Token parseThisExpression(Token token) {
2107 listener.handleThisExpression(token); 2209 listener.handleThisExpression(token);
2108 token = token.next; 2210 token = token.next;
2109 if (optional('(', token)) { 2211 if (optional('(', token)) {
2110 // Constructor forwarding. 2212 // Constructor forwarding.
2213 listener.handleNoTypeArguments(token);
2111 token = parseArguments(token); 2214 token = parseArguments(token);
2112 listener.endSend(token); 2215 listener.endSend(token);
2113 } 2216 }
2114 return token; 2217 return token;
2115 } 2218 }
2116 2219
2117 Token parseSuperExpression(Token token) { 2220 Token parseSuperExpression(Token token) {
2118 listener.handleSuperExpression(token); 2221 listener.handleSuperExpression(token);
2119 token = token.next; 2222 token = token.next;
2120 if (optional('(', token)) { 2223 if (optional('(', token)) {
2121 // Super constructor. 2224 // Super constructor.
2225 listener.handleNoTypeArguments(token);
2122 token = parseArguments(token); 2226 token = parseArguments(token);
2123 listener.endSend(token); 2227 listener.endSend(token);
2124 } 2228 }
2125 return token; 2229 return token;
2126 } 2230 }
2127 2231
2128 Token parseLiteralListOrMap(Token token) { 2232 Token parseLiteralListOrMap(Token token) {
2129 Token constKeyword = null; 2233 Token constKeyword = null;
2130 if (optional('const', token)) { 2234 if (optional('const', token)) {
2131 constKeyword = token; 2235 constKeyword = token;
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
2328 } 2432 }
2329 2433
2330 Token parseLiteralNull(Token token) { 2434 Token parseLiteralNull(Token token) {
2331 listener.handleLiteralNull(token); 2435 listener.handleLiteralNull(token);
2332 return token.next; 2436 return token.next;
2333 } 2437 }
2334 2438
2335 Token parseSend(Token token) { 2439 Token parseSend(Token token) {
2336 listener.beginSend(token); 2440 listener.beginSend(token);
2337 token = parseIdentifier(token); 2441 token = parseIdentifier(token);
2442 if (enableGenericMethodSyntax && isValidMethodTypeArguments(token)) {
2443 token = parseTypeArgumentsOpt(token);
2444 } else {
2445 listener.handleNoTypeArguments(token);
2446 }
2338 token = parseArgumentsOpt(token); 2447 token = parseArgumentsOpt(token);
2339 listener.endSend(token); 2448 listener.endSend(token);
2340 return token; 2449 return token;
2341 } 2450 }
2342 2451
2343 Token parseArgumentsOpt(Token token) { 2452 Token parseArgumentsOpt(Token token) {
2344 if (!optional('(', token)) { 2453 if (!optional('(', token)) {
2345 listener.handleNoArguments(token); 2454 listener.handleNoArguments(token);
2346 return token; 2455 return token;
2347 } else { 2456 } else {
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after
2779 } 2888 }
2780 listener.handleContinueStatement(hasTarget, continueKeyword, token); 2889 listener.handleContinueStatement(hasTarget, continueKeyword, token);
2781 return expectSemicolon(token); 2890 return expectSemicolon(token);
2782 } 2891 }
2783 2892
2784 Token parseEmptyStatement(Token token) { 2893 Token parseEmptyStatement(Token token) {
2785 listener.handleEmptyStatement(token); 2894 listener.handleEmptyStatement(token);
2786 return expectSemicolon(token); 2895 return expectSemicolon(token);
2787 } 2896 }
2788 } 2897 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/parser/node_listener.dart ('k') | tests/compiler/dart2js/backend_dart/dart_printer_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698