Chromium Code Reviews

Side by Side Diff: pkg/front_end/lib/src/fasta/parser/parser.dart

Issue 2699073003: Support `void` as generic argument.
Patch Set: Add specialized messages for `void` for-ins. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
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 fasta.parser.parser; 5 library fasta.parser.parser;
6 6
7 import '../scanner.dart' show ErrorToken; 7 import '../scanner.dart' show ErrorToken;
8 8
9 import '../scanner/recover.dart' show closeBraceFor, skipToEof; 9 import '../scanner/recover.dart' show closeBraceFor, skipToEof;
10 10
(...skipping 383 matching lines...)
394 Token typedefKeyword = token; 394 Token typedefKeyword = token;
395 listener.beginFunctionTypeAlias(token); 395 listener.beginFunctionTypeAlias(token);
396 Token equals; 396 Token equals;
397 if (optional('=', peekAfterNominalType(token.next))) { 397 if (optional('=', peekAfterNominalType(token.next))) {
398 token = parseIdentifier(token.next, IdentifierContext.typedefDeclaration); 398 token = parseIdentifier(token.next, IdentifierContext.typedefDeclaration);
399 token = parseTypeVariablesOpt(token); 399 token = parseTypeVariablesOpt(token);
400 equals = token; 400 equals = token;
401 token = expect('=', token); 401 token = expect('=', token);
402 token = parseType(token); 402 token = parseType(token);
403 } else { 403 } else {
404 token = parseReturnTypeOpt(token.next); 404 token = parseTypeOpt(token.next);
405 token = parseIdentifier(token, IdentifierContext.typedefDeclaration); 405 token = parseIdentifier(token, IdentifierContext.typedefDeclaration);
406 token = parseTypeVariablesOpt(token); 406 token = parseTypeVariablesOpt(token);
407 token = parseFormalParameters(token); 407 token = parseFormalParameters(token);
408 } 408 }
409 listener.endFunctionTypeAlias(typedefKeyword, equals, token); 409 listener.endFunctionTypeAlias(typedefKeyword, equals, token);
410 return expect(';', token); 410 return expect(';', token);
411 } 411 }
412 412
413 Token parseMixinApplication(Token token) { 413 Token parseMixinApplication(Token token) {
414 listener.beginMixinApplication(token); 414 listener.beginMixinApplication(token);
415 token = parseType(token); 415 token = parseType(token);
416 token = expect('with', token); 416 token = expect('with', token);
417 token = parseTypeList(token); 417 token = parseTypeList(token);
418 listener.endMixinApplication(); 418 listener.endMixinApplication();
419 return token; 419 return token;
420 } 420 }
421 421
422 Token parseReturnTypeOpt(Token token) {
423 if (identical(token.stringValue, 'void')) {
424 if (isGeneralizedFunctionType(token.next)) {
425 return parseType(token);
426 } else {
427 listener.handleVoidKeyword(token);
428 return token.next;
429 }
430 } else {
431 return parseTypeOpt(token);
432 }
433 }
434
435 Token parseFormalParametersOpt(Token token) { 422 Token parseFormalParametersOpt(Token token) {
436 if (optional('(', token)) { 423 if (optional('(', token)) {
437 return parseFormalParameters(token); 424 return parseFormalParameters(token);
438 } else { 425 } else {
439 listener.handleNoFormalParameters(token); 426 listener.handleNoFormalParameters(token);
440 return token; 427 return token;
441 } 428 }
442 } 429 }
443 430
444 Token skipFormalParameters(Token token) { 431 Token skipFormalParameters(Token token) {
(...skipping 70 matching lines...)
515 parseIdentifier(token, IdentifierContext.formalParameterDeclaration); 502 parseIdentifier(token, IdentifierContext.formalParameterDeclaration);
516 } else if (inFunctionType) { 503 } else if (inFunctionType) {
517 token = parseType(token); 504 token = parseType(token);
518 if (token.isIdentifier()) { 505 if (token.isIdentifier()) {
519 token = parseIdentifier( 506 token = parseIdentifier(
520 token, IdentifierContext.formalParameterDeclaration); 507 token, IdentifierContext.formalParameterDeclaration);
521 } else { 508 } else {
522 listener.handleNoName(token); 509 listener.handleNoName(token);
523 } 510 }
524 } else { 511 } else {
525 token = parseReturnTypeOpt(token); 512 token = parseTypeOpt(token);
526 if (optional('this', token)) { 513 if (optional('this', token)) {
527 thisKeyword = token; 514 thisKeyword = token;
528 token = expect('.', token.next); 515 token = expect('.', token.next);
529 token = parseIdentifier(token, IdentifierContext.fieldInitializer); 516 token = parseIdentifier(token, IdentifierContext.fieldInitializer);
530 } else { 517 } else {
531 token = parseIdentifier( 518 token = parseIdentifier(
532 token, IdentifierContext.formalParameterDeclaration); 519 token, IdentifierContext.formalParameterDeclaration);
533 } 520 }
534 } 521 }
535 522
(...skipping 394 matching lines...)
930 (optional('<', token.next) || optional('(', token.next)); 917 (optional('<', token.next) || optional('(', token.next));
931 } 918 }
932 919
933 Token parseType(Token token) { 920 Token parseType(Token token) {
934 Token begin = token; 921 Token begin = token;
935 if (isGeneralizedFunctionType(token)) { 922 if (isGeneralizedFunctionType(token)) {
936 // A function type without return type. 923 // A function type without return type.
937 // Push the non-existing return type first. The loop below will 924 // Push the non-existing return type first. The loop below will
938 // generate the full type. 925 // generate the full type.
939 listener.handleNoType(token); 926 listener.handleNoType(token);
940 } else if (identical(token.stringValue, 'void') &&
941 isGeneralizedFunctionType(token.next)) {
942 listener.handleVoidKeyword(token);
943 token = token.next;
944 } else { 927 } else {
945 if (isValidTypeReference(token)) { 928 if (isValidTypeReference(token)) {
946 token = parseIdentifier(token, IdentifierContext.typeReference); 929 token = parseIdentifier(token, IdentifierContext.typeReference);
947 token = parseQualifiedRestOpt( 930 token = parseQualifiedRestOpt(
948 token, IdentifierContext.typeReferenceContinuation); 931 token, IdentifierContext.typeReferenceContinuation);
949 } else { 932 } else {
950 token = reportUnrecoverableError(token, ErrorKind.ExpectedType); 933 token = reportUnrecoverableError(token, ErrorKind.ExpectedType);
951 listener.handleInvalidTypeReference(token); 934 listener.handleInvalidTypeReference(token);
952 } 935 }
953 token = parseTypeArgumentsOpt(token); 936 token = parseTypeArgumentsOpt(token);
(...skipping 237 matching lines...)
1191 1174
1192 if (getOrSet != null) { 1175 if (getOrSet != null) {
1193 var kind = (hasModifier || hasType) 1176 var kind = (hasModifier || hasType)
1194 ? ErrorKind.ExtraneousModifier 1177 ? ErrorKind.ExtraneousModifier
1195 : ErrorKind.ExtraneousModifierReplace; 1178 : ErrorKind.ExtraneousModifierReplace;
1196 reportRecoverableError(getOrSet, kind, {'modifier': getOrSet}); 1179 reportRecoverableError(getOrSet, kind, {'modifier': getOrSet});
1197 } 1180 }
1198 1181
1199 if (!hasType) { 1182 if (!hasType) {
1200 listener.handleNoType(name); 1183 listener.handleNoType(name);
1201 } else if (optional('void', type) &&
1202 !isGeneralizedFunctionType(type.next)) {
1203 listener.handleNoType(name);
1204 // TODO(ahe): This error is reported twice, second time is from
1205 // [parseVariablesDeclarationMaybeSemicolon] via
1206 // [PartialFieldListElement.parseNode].
1207 reportRecoverableError(type, ErrorKind.InvalidVoid);
1208 } else { 1184 } else {
1209 parseType(type); 1185 parseType(type);
1210 if (isVar) { 1186 if (isVar) {
1211 reportRecoverableError(modifiers.head, ErrorKind.ExtraneousModifier, 1187 reportRecoverableError(modifiers.head, ErrorKind.ExtraneousModifier,
1212 {'modifier': modifiers.head}); 1188 {'modifier': modifiers.head});
1213 } 1189 }
1214 } 1190 }
1215 1191
1216 IdentifierContext context = isTopLevel 1192 IdentifierContext context = isTopLevel
1217 ? IdentifierContext.topLevelVariableDeclaration 1193 ? IdentifierContext.topLevelVariableDeclaration
(...skipping 34 matching lines...)
1252 if (externalModifier != null) { 1228 if (externalModifier != null) {
1253 parseModifier(externalModifier); 1229 parseModifier(externalModifier);
1254 listener.handleModifiers(1); 1230 listener.handleModifiers(1);
1255 } else { 1231 } else {
1256 listener.handleModifiers(0); 1232 listener.handleModifiers(0);
1257 } 1233 }
1258 1234
1259 if (type == null) { 1235 if (type == null) {
1260 listener.handleNoType(name); 1236 listener.handleNoType(name);
1261 } else { 1237 } else {
1262 parseReturnTypeOpt(type); 1238 parseTypeOpt(type);
1263 } 1239 }
1264 Token token = 1240 Token token =
1265 parseIdentifier(name, IdentifierContext.topLevelFunctionDeclaration); 1241 parseIdentifier(name, IdentifierContext.topLevelFunctionDeclaration);
1266 1242
1267 if (getOrSet == null) { 1243 if (getOrSet == null) {
1268 token = parseTypeVariablesOpt(token); 1244 token = parseTypeVariablesOpt(token);
1269 } else { 1245 } else {
1270 listener.handleNoTypeVariables(token); 1246 listener.handleNoTypeVariables(token);
1271 } 1247 }
1272 token = parseFormalParametersOpt(token); 1248 token = parseFormalParametersOpt(token);
(...skipping 323 matching lines...)
1596 } 1572 }
1597 1573
1598 return peek; 1574 return peek;
1599 } 1575 }
1600 1576
1601 /** 1577 /**
1602 * If [token] is the start of a type, returns the token after that type. 1578 * If [token] is the start of a type, returns the token after that type.
1603 * If [token] is not the start of a type, null is returned. 1579 * If [token] is not the start of a type, null is returned.
1604 */ 1580 */
1605 Token peekAfterIfType(Token token) { 1581 Token peekAfterIfType(Token token) {
1606 if (!optional('void', token) && !token.isIdentifier()) { 1582 if (!token.isIdentifier()) {
1607 return null; 1583 return null;
1608 } 1584 }
1609 return peekAfterType(token); 1585 return peekAfterType(token);
1610 } 1586 }
1611 1587
1612 Token skipClassBody(Token token) { 1588 Token skipClassBody(Token token) {
1613 if (!optional('{', token)) { 1589 if (!optional('{', token)) {
1614 return reportUnrecoverableError(token, ErrorKind.ExpectedClassBodyToSkip); 1590 return reportUnrecoverableError(token, ErrorKind.ExpectedClassBodyToSkip);
1615 } 1591 }
1616 BeginGroupToken beginGroupToken = token; 1592 BeginGroupToken beginGroupToken = token;
(...skipping 165 matching lines...)
1782 } 1758 }
1783 if (getOrSet != null && constModifier != null) { 1759 if (getOrSet != null && constModifier != null) {
1784 reportRecoverableError(constModifier, ErrorKind.ExtraneousModifier, 1760 reportRecoverableError(constModifier, ErrorKind.ExtraneousModifier,
1785 {'modifier': constModifier}); 1761 {'modifier': constModifier});
1786 } 1762 }
1787 parseModifierList(modifiers); 1763 parseModifierList(modifiers);
1788 1764
1789 if (type == null) { 1765 if (type == null) {
1790 listener.handleNoType(name); 1766 listener.handleNoType(name);
1791 } else { 1767 } else {
1792 parseReturnTypeOpt(type); 1768 parseTypeOpt(type);
1793 } 1769 }
1794 Token token; 1770 Token token;
1795 if (optional('operator', name)) { 1771 if (optional('operator', name)) {
1796 token = parseOperatorName(name); 1772 token = parseOperatorName(name);
1797 if (staticModifier != null) { 1773 if (staticModifier != null) {
1798 reportRecoverableError(staticModifier, ErrorKind.ExtraneousModifier, 1774 reportRecoverableError(staticModifier, ErrorKind.ExtraneousModifier,
1799 {'modifier': staticModifier}); 1775 {'modifier': staticModifier});
1800 } 1776 }
1801 } else { 1777 } else {
1802 token = parseIdentifier(name, IdentifierContext.methodDeclaration); 1778 token = parseIdentifier(name, IdentifierContext.methodDeclaration);
(...skipping 75 matching lines...)
1878 token = 1854 token =
1879 parseIdentifier(token, IdentifierContext.localAccessorDeclaration); 1855 parseIdentifier(token, IdentifierContext.localAccessorDeclaration);
1880 } 1856 }
1881 } else if (optional('operator', token)) { 1857 } else if (optional('operator', token)) {
1882 // operator <op> (... 1858 // operator <op> (...
1883 listener.handleNoType(token); 1859 listener.handleNoType(token);
1884 listener.beginFunctionName(token); 1860 listener.beginFunctionName(token);
1885 token = parseOperatorName(token); 1861 token = parseOperatorName(token);
1886 } else { 1862 } else {
1887 // <type>? <get>? <name> 1863 // <type>? <get>? <name>
1888 token = parseReturnTypeOpt(token); 1864 token = parseTypeOpt(token);
1889 if (identical(getOrSet, token)) { 1865 if (identical(getOrSet, token)) {
1890 token = token.next; 1866 token = token.next;
1891 } 1867 }
1892 listener.beginFunctionName(token); 1868 listener.beginFunctionName(token);
1893 if (optional('operator', token)) { 1869 if (optional('operator', token)) {
1894 token = parseOperatorName(token); 1870 token = parseOperatorName(token);
1895 } else { 1871 } else {
1896 token = 1872 token =
1897 parseIdentifier(token, IdentifierContext.localFunctionDeclaration); 1873 parseIdentifier(token, IdentifierContext.localFunctionDeclaration);
1898 } 1874 }
(...skipping 31 matching lines...)
1930 Token parseFunctionDeclaration(Token token) { 1906 Token parseFunctionDeclaration(Token token) {
1931 listener.beginFunctionDeclaration(token); 1907 listener.beginFunctionDeclaration(token);
1932 token = parseFunction(token, null); 1908 token = parseFunction(token, null);
1933 listener.endFunctionDeclaration(token); 1909 listener.endFunctionDeclaration(token);
1934 return token; 1910 return token;
1935 } 1911 }
1936 1912
1937 Token parseFunctionExpression(Token token) { 1913 Token parseFunctionExpression(Token token) {
1938 listener.beginFunction(token); 1914 listener.beginFunction(token);
1939 listener.handleModifiers(0); 1915 listener.handleModifiers(0);
1940 token = parseReturnTypeOpt(token); 1916 token = parseTypeOpt(token);
1941 listener.beginFunctionName(token); 1917 listener.beginFunctionName(token);
1942 token = parseIdentifier(token, IdentifierContext.functionExpressionName); 1918 token = parseIdentifier(token, IdentifierContext.functionExpressionName);
1943 listener.endFunctionName(token); 1919 listener.endFunctionName(token);
1944 token = parseTypeVariablesOpt(token); 1920 token = parseTypeVariablesOpt(token);
1945 token = parseFormalParameters(token); 1921 token = parseFormalParameters(token);
1946 listener.handleNoInitializers(); 1922 listener.handleNoInitializers();
1947 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; 1923 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled;
1948 token = parseAsyncModifier(token); 1924 token = parseAsyncModifier(token);
1949 bool isBlock = optional('{', token); 1925 bool isBlock = optional('{', token);
1950 token = parseFunctionBody(token, true, false); 1926 token = parseFunctionBody(token, true, false);
(...skipping 185 matching lines...)
2136 } else { 2112 } else {
2137 return parseExpressionStatement(token); 2113 return parseExpressionStatement(token);
2138 } 2114 }
2139 } else if (identical(value, 'for')) { 2115 } else if (identical(value, 'for')) {
2140 return parseForStatement(null, token); 2116 return parseForStatement(null, token);
2141 } else if (identical(value, 'rethrow')) { 2117 } else if (identical(value, 'rethrow')) {
2142 return parseRethrowStatement(token); 2118 return parseRethrowStatement(token);
2143 } else if (identical(value, 'throw') && optional(';', token.next)) { 2119 } else if (identical(value, 'throw') && optional(';', token.next)) {
2144 // TODO(kasperl): Stop dealing with throw here. 2120 // TODO(kasperl): Stop dealing with throw here.
2145 return parseRethrowStatement(token); 2121 return parseRethrowStatement(token);
2146 } else if (identical(value, 'void')) {
2147 return parseExpressionStatementOrDeclaration(token);
2148 } else if (identical(value, 'while')) { 2122 } else if (identical(value, 'while')) {
2149 return parseWhileStatement(token); 2123 return parseWhileStatement(token);
2150 } else if (identical(value, 'do')) { 2124 } else if (identical(value, 'do')) {
2151 return parseDoWhileStatement(token); 2125 return parseDoWhileStatement(token);
2152 } else if (identical(value, 'try')) { 2126 } else if (identical(value, 'try')) {
2153 return parseTryStatement(token); 2127 return parseTryStatement(token);
2154 } else if (identical(value, 'switch')) { 2128 } else if (identical(value, 'switch')) {
2155 return parseSwitchStatement(token); 2129 return parseSwitchStatement(token);
2156 } else if (identical(value, 'break')) { 2130 } else if (identical(value, 'break')) {
2157 return parseBreakStatement(token); 2131 return parseBreakStatement(token);
(...skipping 60 matching lines...)
2218 return peek; 2192 return peek;
2219 } else if (token.isIdentifier()) { 2193 } else if (token.isIdentifier()) {
2220 // We are looking at "identifier". 2194 // We are looking at "identifier".
2221 return token; 2195 return token;
2222 } else { 2196 } else {
2223 return null; 2197 return null;
2224 } 2198 }
2225 } 2199 }
2226 2200
2227 Token parseExpressionStatementOrDeclaration(Token token) { 2201 Token parseExpressionStatementOrDeclaration(Token token) {
2228 assert(token.isIdentifier() || identical(token.stringValue, 'void')); 2202 assert(token.isIdentifier());
2229 Token identifier = peekIdentifierAfterType(token); 2203 Token identifier = peekIdentifierAfterType(token);
2230 if (identifier != null) { 2204 if (identifier != null) {
2231 assert(identifier.isIdentifier()); 2205 assert(identifier.isIdentifier());
2232 Token afterId = identifier.next; 2206 Token afterId = identifier.next;
2233 int afterIdKind = afterId.kind; 2207 int afterIdKind = afterId.kind;
2234 if (identical(afterIdKind, EQ_TOKEN) || 2208 if (identical(afterIdKind, EQ_TOKEN) ||
2235 identical(afterIdKind, SEMICOLON_TOKEN) || 2209 identical(afterIdKind, SEMICOLON_TOKEN) ||
2236 identical(afterIdKind, COMMA_TOKEN)) { 2210 identical(afterIdKind, COMMA_TOKEN)) {
2237 // We are looking at "type identifier" followed by '=', ';', ','. 2211 // We are looking at "type identifier" followed by '=', ';', ','.
2238 return parseVariablesDeclaration(token); 2212 return parseVariablesDeclaration(token);
(...skipping 393 matching lines...)
2632 } else if (value == 'null') { 2606 } else if (value == 'null') {
2633 return parseLiteralNull(token); 2607 return parseLiteralNull(token);
2634 } else if (value == 'this') { 2608 } else if (value == 'this') {
2635 return parseThisExpression(token); 2609 return parseThisExpression(token);
2636 } else if (value == 'super') { 2610 } else if (value == 'super') {
2637 return parseSuperExpression(token); 2611 return parseSuperExpression(token);
2638 } else if (value == 'new') { 2612 } else if (value == 'new') {
2639 return parseNewExpression(token); 2613 return parseNewExpression(token);
2640 } else if (value == 'const') { 2614 } else if (value == 'const') {
2641 return parseConstExpression(token); 2615 return parseConstExpression(token);
2642 } else if (value == 'void') {
2643 return parseFunctionExpression(token);
2644 } else if (asyncAwaitKeywordsEnabled && 2616 } else if (asyncAwaitKeywordsEnabled &&
2645 (value == 'yield' || value == 'async')) { 2617 (value == 'yield' || value == 'async')) {
2646 return expressionExpected(token); 2618 return expressionExpected(token);
2647 } else if (token.isIdentifier()) { 2619 } else if (token.isIdentifier()) {
2648 return parseSendOrFunctionLiteral(token); 2620 return parseSendOrFunctionLiteral(token);
2649 } else { 2621 } else {
2650 return expressionExpected(token); 2622 return expressionExpected(token);
2651 } 2623 }
2652 } else if (kind == OPEN_PAREN_TOKEN) { 2624 } else if (kind == OPEN_PAREN_TOKEN) {
2653 return parseParenthesizedExpressionOrFunctionLiteral(token); 2625 return parseParenthesizedExpressionOrFunctionLiteral(token);
(...skipping 905 matching lines...)
3559 break; 3531 break;
3560 } 3532 }
3561 if (isRecoverable) { 3533 if (isRecoverable) {
3562 listener.handleRecoverableError(token, kind, arguments); 3534 listener.handleRecoverableError(token, kind, arguments);
3563 return null; 3535 return null;
3564 } else { 3536 } else {
3565 return listener.handleUnrecoverableError(token, kind, arguments); 3537 return listener.handleUnrecoverableError(token, kind, arguments);
3566 } 3538 }
3567 } 3539 }
3568 } 3540 }
OLDNEW

Powered by Google App Engine