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

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

Issue 2968093003: Improve parsing of function expressions. (Closed)
Patch Set: Created 3 years, 5 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 fasta.parser.parser; 5 library fasta.parser.parser;
6 6
7 import '../fasta_codes.dart' show FastaCode, FastaMessage; 7 import '../fasta_codes.dart' show FastaCode, FastaMessage;
8 8
9 import '../fasta_codes.dart' as fasta; 9 import '../fasta_codes.dart' as fasta;
10 10
(...skipping 1371 matching lines...) Expand 10 before | Expand all | Expand 10 after
1382 } 1382 }
1383 // Fall-through to expression statement. 1383 // Fall-through to expression statement.
1384 } 1384 }
1385 1385
1386 return parseExpressionStatement(begin); 1386 return parseExpressionStatement(begin);
1387 1387
1388 case TypeContinuation.SendOrFunctionLiteral: 1388 case TypeContinuation.SendOrFunctionLiteral:
1389 if (looksLikeType && 1389 if (looksLikeType &&
1390 token.isIdentifier && 1390 token.isIdentifier &&
1391 isFunctionDeclaration(token.next)) { 1391 isFunctionDeclaration(token.next)) {
1392 return parseFunctionExpression(begin); 1392 return parseNamedFunctionExpression(begin);
1393 } else if (isFunctionDeclaration(begin.next)) { 1393 } else if (isFunctionDeclaration(begin.next)) {
1394 return parseFunctionExpression(begin); 1394 return parseNamedFunctionExpression(begin);
1395 } 1395 }
1396 return parseSend(begin, continuationContext); 1396 return parseSend(begin, continuationContext);
1397 1397
1398 case TypeContinuation.VariablesDeclarationOrExpression: 1398 case TypeContinuation.VariablesDeclarationOrExpression:
1399 if (looksLikeType && 1399 if (looksLikeType &&
1400 token.isIdentifier && 1400 token.isIdentifier &&
1401 isOneOf4(token.next, '=', ';', ',', 'in')) { 1401 isOneOf4(token.next, '=', ';', ',', 'in')) {
1402 // TODO(ahe): Generate type events and call 1402 // TODO(ahe): Generate type events and call
1403 // parseVariablesDeclarationNoSemicolonRest instead. 1403 // parseVariablesDeclarationNoSemicolonRest instead.
1404 return parseVariablesDeclarationNoSemicolon(begin); 1404 return parseVariablesDeclarationNoSemicolon(begin);
(...skipping 1034 matching lines...) Expand 10 before | Expand all | Expand 10 after
2439 if (isUserDefinableOperator(token.next.stringValue)) { 2439 if (isUserDefinableOperator(token.next.stringValue)) {
2440 Token operator = token; 2440 Token operator = token;
2441 token = token.next; 2441 token = token.next;
2442 listener.handleOperatorName(operator, token); 2442 listener.handleOperatorName(operator, token);
2443 return token.next; 2443 return token.next;
2444 } else { 2444 } else {
2445 return parseIdentifier(token, IdentifierContext.operatorName); 2445 return parseIdentifier(token, IdentifierContext.operatorName);
2446 } 2446 }
2447 } 2447 }
2448 2448
2449 Token parseFunction(Token token) { 2449 Token parseFunctionExpression(Token token) {
2450 Token beginToken = token; 2450 Token beginToken = token;
2451 listener.beginFunction(token); 2451 listener.beginFunctionExpression(token);
2452 token = parseFormalParameters(token, MemberKind.Local);
2453 AsyncModifier savedAsyncModifier = asyncState;
2454 token = parseAsyncModifier(token);
2455 bool isBlock = optional('{', token);
2456 token = parseFunctionBody(token, true, false);
2457 asyncState = savedAsyncModifier;
2458 listener.endFunctionExpression(beginToken, token);
2459 return isBlock ? token.next : token;
2460 }
2461
2462 Token parseFunctionDeclaration(Token token) {
2463 listener.beginFunctionDeclaration(token);
2464 Token beginToken = token;
2452 token = parseModifiers(token, MemberKind.Local); 2465 token = parseModifiers(token, MemberKind.Local);
2453 listener.beginFunctionName(token); 2466 listener.beginFunctionName(token);
2454 token = parseIdentifier(token, IdentifierContext.localFunctionDeclaration); 2467 token = parseIdentifier(token, IdentifierContext.localFunctionDeclaration);
2455 token = parseQualifiedRestOpt( 2468 token = parseQualifiedRestOpt(
2456 token, IdentifierContext.localFunctionDeclarationContinuation); 2469 token, IdentifierContext.localFunctionDeclarationContinuation);
2457 listener.endFunctionName(beginToken, token); 2470 listener.endFunctionName(beginToken, token);
2458 token = parseTypeVariablesOpt(token); 2471 token = parseTypeVariablesOpt(token);
2459 token = parseFormalParametersOpt(token, MemberKind.Local); 2472 token = parseFormalParametersOpt(token, MemberKind.Local);
2460 token = parseInitializersOpt(token); 2473 token = parseInitializersOpt(token);
2461 AsyncModifier savedAsyncModifier = asyncState; 2474 AsyncModifier savedAsyncModifier = asyncState;
2462 token = parseAsyncModifier(token); 2475 token = parseAsyncModifier(token);
2463 token = parseFunctionBody(token, false, true); 2476 token = parseFunctionBody(token, false, true);
2464 asyncState = savedAsyncModifier; 2477 asyncState = savedAsyncModifier;
2465 listener.endFunction(null, token); 2478 token = token.next;
2466 return token.next;
2467 }
2468
2469 Token parseUnnamedFunction(Token token) {
2470 Token beginToken = token;
2471 listener.beginUnnamedFunction(token);
2472 token = parseFormalParameters(token, MemberKind.Local);
2473 AsyncModifier savedAsyncModifier = asyncState;
2474 token = parseAsyncModifier(token);
2475 bool isBlock = optional('{', token);
2476 token = parseFunctionBody(token, true, false);
2477 asyncState = savedAsyncModifier;
2478 listener.endUnnamedFunction(beginToken, token);
2479 return isBlock ? token.next : token;
2480 }
2481
2482 Token parseFunctionDeclaration(Token token) {
2483 listener.beginFunctionDeclaration(token);
2484 token = parseFunction(token);
2485 listener.endFunctionDeclaration(token); 2479 listener.endFunctionDeclaration(token);
2486 return token; 2480 return token;
2487 } 2481 }
2488 2482
2489 Token parseFunctionExpression(Token token) { 2483 /// Parses a named function expression which isn't legal syntax in Dart.
2484 /// Useful for recovering from Javascript code being pasted into a Dart
2485 /// proram, as it will interpret `function foo() {}` as a named function
2486 /// expression with return type `function` and name `foo`.
2487 Token parseNamedFunctionExpression(Token token) {
2490 Token beginToken = token; 2488 Token beginToken = token;
2491 listener.beginFunction(token); 2489 listener.beginNamedFunctionExpression(token);
2492 listener.handleModifiers(0); 2490 listener.handleModifiers(0);
2493 token = parseType(token, TypeContinuation.Optional); 2491 token = parseType(token, TypeContinuation.Optional);
2492 if (token != beginToken) {
2493 reportRecoverableErrorCode(token, fasta.codeReturnTypeFunctionExpression);
2494 }
2494 listener.beginFunctionName(token); 2495 listener.beginFunctionName(token);
2496 Token nameToken = token;
2495 token = parseIdentifier(token, IdentifierContext.functionExpressionName); 2497 token = parseIdentifier(token, IdentifierContext.functionExpressionName);
2498 reportRecoverableErrorCode(nameToken, fasta.codeNamedFunctionExpression);
2496 listener.endFunctionName(beginToken, token); 2499 listener.endFunctionName(beginToken, token);
2497 token = parseTypeVariablesOpt(token); 2500 token = parseTypeVariablesOpt(token);
2498 token = parseFormalParameters(token, MemberKind.Local); 2501 token = parseFormalParameters(token, MemberKind.Local);
2499 listener.handleNoInitializers(); 2502 listener.handleNoInitializers();
2500 AsyncModifier savedAsyncModifier = asyncState; 2503 AsyncModifier savedAsyncModifier = asyncState;
2501 token = parseAsyncModifier(token); 2504 token = parseAsyncModifier(token);
2502 bool isBlock = optional('{', token); 2505 bool isBlock = optional('{', token);
2503 token = parseFunctionBody(token, true, false); 2506 token = parseFunctionBody(token, true, false);
2504 asyncState = savedAsyncModifier; 2507 asyncState = savedAsyncModifier;
2505 listener.endFunction(null, token); 2508 listener.endNamedFunctionExpression(token);
2506 return isBlock ? token.next : token; 2509 return isBlock ? token.next : token;
2507 } 2510 }
2508 2511
2509 Token parseConstructorReference(Token token) { 2512 Token parseConstructorReference(Token token) {
2510 Token start = token; 2513 Token start = token;
2511 listener.beginConstructorReference(start); 2514 listener.beginConstructorReference(start);
2512 token = parseIdentifier(token, IdentifierContext.constructorReference); 2515 token = parseIdentifier(token, IdentifierContext.constructorReference);
2513 token = parseQualifiedRestOpt( 2516 token = parseQualifiedRestOpt(
2514 token, IdentifierContext.constructorReferenceContinuation); 2517 token, IdentifierContext.constructorReferenceContinuation);
2515 token = parseTypeArgumentsOpt(token); 2518 token = parseTypeArgumentsOpt(token);
(...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after
3106 return parseLiteralNull(token); 3109 return parseLiteralNull(token);
3107 } else if (identical(value, "this")) { 3110 } else if (identical(value, "this")) {
3108 return parseThisExpression(token, context); 3111 return parseThisExpression(token, context);
3109 } else if (identical(value, "super")) { 3112 } else if (identical(value, "super")) {
3110 return parseSuperExpression(token, context); 3113 return parseSuperExpression(token, context);
3111 } else if (identical(value, "new")) { 3114 } else if (identical(value, "new")) {
3112 return parseNewExpression(token); 3115 return parseNewExpression(token);
3113 } else if (identical(value, "const")) { 3116 } else if (identical(value, "const")) {
3114 return parseConstExpression(token); 3117 return parseConstExpression(token);
3115 } else if (identical(value, "void")) { 3118 } else if (identical(value, "void")) {
3116 return parseFunctionExpression(token); 3119 return parseNamedFunctionExpression(token);
3117 } else if (!inPlainSync && 3120 } else if (!inPlainSync &&
3118 (identical(value, "yield") || identical(value, "async"))) { 3121 (identical(value, "yield") || identical(value, "async"))) {
3119 return expressionExpected(token); 3122 return expressionExpected(token);
3120 } else if (identical(value, "assert")) { 3123 } else if (identical(value, "assert")) {
3121 return parseAssert(token, Assert.Expression); 3124 return parseAssert(token, Assert.Expression);
3122 } else if (token.isIdentifier) { 3125 } else if (token.isIdentifier) {
3123 return parseSendOrFunctionLiteral(token, context); 3126 return parseSendOrFunctionLiteral(token, context);
3124 } else { 3127 } else {
3125 return expressionExpected(token); 3128 return expressionExpected(token);
3126 } 3129 }
(...skipping 24 matching lines...) Expand all
3151 BeginToken beginGroup = token; 3154 BeginToken beginGroup = token;
3152 Token nextToken = beginGroup.endGroup.next; 3155 Token nextToken = beginGroup.endGroup.next;
3153 int kind = nextToken.kind; 3156 int kind = nextToken.kind;
3154 if (mayParseFunctionExpressions && 3157 if (mayParseFunctionExpressions &&
3155 (identical(kind, FUNCTION_TOKEN) || 3158 (identical(kind, FUNCTION_TOKEN) ||
3156 identical(kind, OPEN_CURLY_BRACKET_TOKEN) || 3159 identical(kind, OPEN_CURLY_BRACKET_TOKEN) ||
3157 (identical(kind, KEYWORD_TOKEN) && 3160 (identical(kind, KEYWORD_TOKEN) &&
3158 (optional('async', nextToken) || 3161 (optional('async', nextToken) ||
3159 optional('sync', nextToken))))) { 3162 optional('sync', nextToken))))) {
3160 listener.handleNoTypeVariables(token); 3163 listener.handleNoTypeVariables(token);
3161 return parseUnnamedFunction(token); 3164 return parseFunctionExpression(token);
3162 } else { 3165 } else {
3163 bool old = mayParseFunctionExpressions; 3166 bool old = mayParseFunctionExpressions;
3164 mayParseFunctionExpressions = true; 3167 mayParseFunctionExpressions = true;
3165 token = parseParenthesizedExpression(token); 3168 token = parseParenthesizedExpression(token);
3166 mayParseFunctionExpressions = old; 3169 mayParseFunctionExpressions = old;
3167 return token; 3170 return token;
3168 } 3171 }
3169 } 3172 }
3170 3173
3171 Token parseParenthesizedExpression(Token token) { 3174 Token parseParenthesizedExpression(Token token) {
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
3271 Token parseLiteralFunctionSuffix(Token token) { 3274 Token parseLiteralFunctionSuffix(Token token) {
3272 assert(optional('(', token)); 3275 assert(optional('(', token));
3273 BeginToken beginGroup = token; 3276 BeginToken beginGroup = token;
3274 if (beginGroup.endGroup != null) { 3277 if (beginGroup.endGroup != null) {
3275 Token nextToken = beginGroup.endGroup.next; 3278 Token nextToken = beginGroup.endGroup.next;
3276 int kind = nextToken.kind; 3279 int kind = nextToken.kind;
3277 if (identical(kind, FUNCTION_TOKEN) || 3280 if (identical(kind, FUNCTION_TOKEN) ||
3278 identical(kind, OPEN_CURLY_BRACKET_TOKEN) || 3281 identical(kind, OPEN_CURLY_BRACKET_TOKEN) ||
3279 (identical(kind, KEYWORD_TOKEN) && 3282 (identical(kind, KEYWORD_TOKEN) &&
3280 (optional('async', nextToken) || optional('sync', nextToken)))) { 3283 (optional('async', nextToken) || optional('sync', nextToken)))) {
3281 return parseUnnamedFunction(token); 3284 return parseFunctionExpression(token);
3282 } 3285 }
3283 // Fall through. 3286 // Fall through.
3284 } 3287 }
3285 return reportUnexpectedToken(token).next; 3288 return reportUnexpectedToken(token).next;
3286 } 3289 }
3287 3290
3288 /// genericListLiteral | genericMapLiteral | genericFunctionLiteral. 3291 /// genericListLiteral | genericMapLiteral | genericFunctionLiteral.
3289 /// 3292 ///
3290 /// Where 3293 /// Where
3291 /// genericListLiteral ::= typeArguments '[' (expressionList ','?)? ']' 3294 /// genericListLiteral ::= typeArguments '[' (expressionList ','?)? ']'
(...skipping 857 matching lines...) Expand 10 before | Expand all | Expand 10 after
4149 return reportUnrecoverableError( 4152 return reportUnrecoverableError(
4150 token, () => code.format(uri, token.charOffset, string)); 4153 token, () => code.format(uri, token.charOffset, string));
4151 } 4154 }
4152 } 4155 }
4153 4156
4154 typedef FastaMessage NoArgument(Uri uri, int charOffset); 4157 typedef FastaMessage NoArgument(Uri uri, int charOffset);
4155 4158
4156 typedef FastaMessage TokenArgument(Uri uri, int charOffset, Token token); 4159 typedef FastaMessage TokenArgument(Uri uri, int charOffset, Token token);
4157 4160
4158 typedef FastaMessage StringArgument(Uri uri, int charOffset, String string); 4161 typedef FastaMessage StringArgument(Uri uri, int charOffset, String string);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698