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

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: Rebased up to current github master 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 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
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
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
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
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
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
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
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
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
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
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
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
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 }
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