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

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

Issue 2994973002: Implement type variables on local function declarations and expressions. (Closed)
Patch Set: Update expectation files after adding copyright. Created 3 years, 4 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 Code, Message, Template; 7 import '../fasta_codes.dart' show Code, Message, Template;
8 8
9 import '../fasta_codes.dart' as fasta; 9 import '../fasta_codes.dart' as fasta;
10 10
(...skipping 1119 matching lines...) Expand 10 before | Expand all | Expand 10 after
1130 } 1130 }
1131 1131
1132 /// Returns true if [token] could be the start of a function body. 1132 /// Returns true if [token] could be the start of a function body.
1133 bool looksLikeFunctionBody(Token token) { 1133 bool looksLikeFunctionBody(Token token) {
1134 return optional('{', token) || 1134 return optional('{', token) ||
1135 optional('=>', token) || 1135 optional('=>', token) ||
1136 optional('async', token) || 1136 optional('async', token) ||
1137 optional('sync', token); 1137 optional('sync', token);
1138 } 1138 }
1139 1139
1140 /// Returns true if [token] could be the start of a function declaration
1141 /// without a return type.
1142 bool looksLikeFunctionDeclaration(Token token) {
1143 if (!token.isIdentifier) {
1144 return false;
1145 }
1146 token = token.next;
1147 if (optional('<', token)) {
1148 Token closeBrace = closeBraceTokenFor(token);
1149 if (closeBrace == null) return false;
1150 token = closeBrace.next;
1151 }
1152 if (optional('(', token)) {
1153 return looksLikeFunctionBody(closeBraceTokenFor(token).next);
1154 }
1155 return false;
1156 }
1157
1140 FormalParameterKind parameterKind; 1158 FormalParameterKind parameterKind;
1141 switch (continuation) { 1159 switch (continuation) {
1142 case TypeContinuation.Required: 1160 case TypeContinuation.Required:
1143 return commitType(); 1161 return commitType();
1144 1162
1145 optional: 1163 optional:
1146 case TypeContinuation.Optional: 1164 case TypeContinuation.Optional:
1147 if (looksLikeType) { 1165 if (looksLikeType) {
1148 if (functionTypes > 0) { 1166 if (functionTypes > 0) {
1149 return commitType(); // Parse function type. 1167 return commitType(); // Parse function type.
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1196 // may get injected from a comment. 1214 // may get injected from a comment.
1197 Token formals = parseTypeVariablesOpt(afterId); 1215 Token formals = parseTypeVariablesOpt(afterId);
1198 1216
1199 listener.beginLocalFunctionDeclaration(begin); 1217 listener.beginLocalFunctionDeclaration(begin);
1200 listener.handleModifiers(0); 1218 listener.handleModifiers(0);
1201 if (voidToken != null) { 1219 if (voidToken != null) {
1202 listener.handleVoidKeyword(voidToken); 1220 listener.handleVoidKeyword(voidToken);
1203 } else { 1221 } else {
1204 commitType(); 1222 commitType();
1205 } 1223 }
1206 return parseLocalFunctionDeclarationRest(begin, token, formals); 1224 return parseNamedFunctionRest(begin, token, formals, false);
1207 } 1225 }
1208 } else if (identical(afterIdKind, LT_TOKEN)) { 1226 } else if (identical(afterIdKind, LT_TOKEN)) {
1209 // We are looking at `type identifier '<'`. 1227 // We are looking at `type identifier '<'`.
1210 Token formals = closeBraceTokenFor(afterId)?.next; 1228 Token formals = closeBraceTokenFor(afterId)?.next;
1211 if (formals != null && optional("(", formals)) { 1229 if (formals != null && optional("(", formals)) {
1212 if (looksLikeFunctionBody(closeBraceTokenFor(formals).next)) { 1230 if (looksLikeFunctionBody(closeBraceTokenFor(formals).next)) {
1213 // We are looking at "type identifier '<' ... '>' '(' ... ')'" 1231 // We are looking at "type identifier '<' ... '>' '(' ... ')'"
1214 // followed by '{', '=>', 'async', or 'sync'. 1232 // followed by '{', '=>', 'async', or 'sync'.
1215 parseTypeVariablesOpt(afterId); 1233 parseTypeVariablesOpt(afterId);
1216 listener.beginLocalFunctionDeclaration(begin); 1234 listener.beginLocalFunctionDeclaration(begin);
1217 listener.handleModifiers(0); 1235 listener.handleModifiers(0);
1218 if (voidToken != null) { 1236 if (voidToken != null) {
1219 listener.handleVoidKeyword(voidToken); 1237 listener.handleVoidKeyword(voidToken);
1220 } else { 1238 } else {
1221 commitType(); 1239 commitType();
1222 } 1240 }
1223 return parseLocalFunctionDeclarationRest(begin, token, formals); 1241 return parseNamedFunctionRest(begin, token, formals, false);
1224 } 1242 }
1225 } 1243 }
1226 } 1244 }
1227 // Fall-through to expression statement. 1245 // Fall-through to expression statement.
1228 } else { 1246 } else {
1229 token = begin; 1247 token = begin;
1230 if (optional(':', token.next)) { 1248 if (optional(':', token.next)) {
1231 return parseLabeledStatement(token); 1249 return parseLabeledStatement(token);
1232 } else if (optional('(', token.next)) { 1250 } else if (optional('(', token.next)) {
1233 if (looksLikeFunctionBody(closeBraceTokenFor(token.next).next)) { 1251 if (looksLikeFunctionBody(closeBraceTokenFor(token.next).next)) {
1234 // We are looking at `identifier '(' ... ')'` followed by `'{'`, 1252 // We are looking at `identifier '(' ... ')'` followed by `'{'`,
1235 // `'=>'`, `'async'`, or `'sync'`. 1253 // `'=>'`, `'async'`, or `'sync'`.
1236 1254
1237 // Although it looks like there are no type variables here, they 1255 // Although it looks like there are no type variables here, they
1238 // may get injected from a comment. 1256 // may get injected from a comment.
1239 Token formals = parseTypeVariablesOpt(token.next); 1257 Token formals = parseTypeVariablesOpt(token.next);
1240 1258
1241 listener.beginLocalFunctionDeclaration(token); 1259 listener.beginLocalFunctionDeclaration(token);
1242 listener.handleModifiers(0); 1260 listener.handleModifiers(0);
1243 listener.handleNoType(token); 1261 listener.handleNoType(token);
1244 return parseLocalFunctionDeclarationRest(begin, token, formals); 1262 return parseNamedFunctionRest(begin, token, formals, false);
1245 } 1263 }
1246 } else if (optional('<', token.next)) { 1264 } else if (optional('<', token.next)) {
1247 Token afterTypeVariables = closeBraceTokenFor(token.next)?.next; 1265 Token afterTypeVariables = closeBraceTokenFor(token.next)?.next;
1248 if (afterTypeVariables != null && 1266 if (afterTypeVariables != null &&
1249 optional("(", afterTypeVariables)) { 1267 optional("(", afterTypeVariables)) {
1250 if (looksLikeFunctionBody( 1268 if (looksLikeFunctionBody(
1251 closeBraceTokenFor(afterTypeVariables).next)) { 1269 closeBraceTokenFor(afterTypeVariables).next)) {
1252 // We are looking at `identifier '<' ... '>' '(' ... ')'` 1270 // We are looking at `identifier '<' ... '>' '(' ... ')'`
1253 // followed by `'{'`, `'=>'`, `'async'`, or `'sync'`. 1271 // followed by `'{'`, `'=>'`, `'async'`, or `'sync'`.
1254 parseTypeVariablesOpt(token.next); 1272 parseTypeVariablesOpt(token.next);
1255 listener.beginLocalFunctionDeclaration(token); 1273 listener.beginLocalFunctionDeclaration(token);
1256 listener.handleModifiers(0); 1274 listener.handleModifiers(0);
1257 listener.handleNoType(token); 1275 listener.handleNoType(token);
1258 return parseLocalFunctionDeclarationRest( 1276 return parseNamedFunctionRest(
1259 begin, token, afterTypeVariables); 1277 begin, token, afterTypeVariables, false);
1260 } 1278 }
1261 } 1279 }
1262 // Fall through to expression statement. 1280 // Fall through to expression statement.
1263 } 1281 }
1264 } 1282 }
1265 return parseExpressionStatement(begin); 1283 return parseExpressionStatement(begin);
1266 1284
1267 case TypeContinuation.ExpressionStatementOrConstDeclaration: 1285 case TypeContinuation.ExpressionStatementOrConstDeclaration:
1268 Token identifier; 1286 Token identifier;
1269 if (looksLikeType && token.isIdentifier) { 1287 if (looksLikeType && token.isIdentifier) {
1270 identifier = token; 1288 identifier = token;
1271 } else if (begin.next.isIdentifier) { 1289 } else if (begin.next.isIdentifier) {
1272 identifier = begin.next; 1290 identifier = begin.next;
1273 } 1291 }
1274 if (identifier != null) { 1292 if (identifier != null) {
1275 if (looksLikeVariableDeclarationEnd(identifier.next.kind)) { 1293 if (looksLikeVariableDeclarationEnd(identifier.next.kind)) {
1276 // We are looking at "const type identifier" followed by '=', ';', 1294 // We are looking at "const type identifier" followed by '=', ';',
1277 // or ','. 1295 // or ','.
1278 1296
1279 // TODO(ahe): Generate type events and call 1297 // TODO(ahe): Generate type events and call
1280 // parseVariablesDeclarationRest instead. 1298 // parseVariablesDeclarationRest instead.
1281 return parseVariablesDeclaration(begin); 1299 return parseVariablesDeclaration(begin);
1282 } 1300 }
1283 // Fall-through to expression statement. 1301 // Fall-through to expression statement.
1284 } 1302 }
1285 1303
1286 return parseExpressionStatement(begin); 1304 return parseExpressionStatement(begin);
1287 1305
1288 case TypeContinuation.SendOrFunctionLiteral: 1306 case TypeContinuation.SendOrFunctionLiteral:
1289 if (looksLikeType && 1307 Token name;
1290 token.isIdentifier && 1308 bool hasReturnType;
1291 isFunctionDeclaration(token.next)) { 1309 if (looksLikeType && looksLikeFunctionDeclaration(token)) {
1292 return parseNamedFunctionExpression(begin); 1310 name = token;
1293 } else if (isFunctionDeclaration(begin.next)) { 1311 hasReturnType = true;
1294 return parseNamedFunctionExpression(begin); 1312 // Fall-through to parseNamedFunctionRest below.
1313 } else if (looksLikeFunctionDeclaration(begin)) {
1314 name = begin;
1315 hasReturnType = false;
1316 // Fall-through to parseNamedFunctionRest below.
1317 } else {
1318 return parseSend(begin, continuationContext);
1295 } 1319 }
1296 return parseSend(begin, continuationContext); 1320
1321 Token formals = parseTypeVariablesOpt(name.next);
1322 listener.beginNamedFunctionExpression(begin);
1323 listener.handleModifiers(0);
1324 if (hasReturnType) {
1325 if (voidToken != null) {
1326 listener.handleVoidKeyword(voidToken);
1327 } else {
1328 commitType();
1329 }
1330 reportRecoverableError(
1331 begin, fasta.messageReturnTypeFunctionExpression);
1332 } else {
1333 listener.handleNoType(begin);
1334 }
1335
1336 return parseNamedFunctionRest(begin, name, formals, true);
1297 1337
1298 case TypeContinuation.VariablesDeclarationOrExpression: 1338 case TypeContinuation.VariablesDeclarationOrExpression:
1299 if (looksLikeType && 1339 if (looksLikeType &&
1300 token.isIdentifier && 1340 token.isIdentifier &&
1301 isOneOf4(token.next, '=', ';', ',', 'in')) { 1341 isOneOf4(token.next, '=', ';', ',', 'in')) {
1302 // TODO(ahe): Generate type events and call 1342 // TODO(ahe): Generate type events and call
1303 // parseVariablesDeclarationNoSemicolonRest instead. 1343 // parseVariablesDeclarationNoSemicolonRest instead.
1304 return parseVariablesDeclarationNoSemicolon(begin); 1344 return parseVariablesDeclarationNoSemicolon(begin);
1305 } 1345 }
1306 return parseExpression(begin); 1346 return parseExpression(begin);
(...skipping 1046 matching lines...) Expand 10 before | Expand all | Expand 10 after
2353 2393
2354 Token parseFunctionExpression(Token token) { 2394 Token parseFunctionExpression(Token token) {
2355 Token beginToken = token; 2395 Token beginToken = token;
2356 listener.beginFunctionExpression(token); 2396 listener.beginFunctionExpression(token);
2357 token = parseFormalParameters(token, MemberKind.Local); 2397 token = parseFormalParameters(token, MemberKind.Local);
2358 token = parseAsyncOptBody(token, true, false); 2398 token = parseAsyncOptBody(token, true, false);
2359 listener.endFunctionExpression(beginToken, token); 2399 listener.endFunctionExpression(beginToken, token);
2360 return token; 2400 return token;
2361 } 2401 }
2362 2402
2363 /// Parses the rest of a local function declaration starting from its [name] 2403 /// Parses the rest of a named function declaration starting from its [name]
2364 /// but then skips any type parameters and continue parsing from [formals] 2404 /// but then skips any type parameters and continue parsing from [formals]
2365 /// (the formal parameters). 2405 /// (the formal parameters).
2366 /// 2406 ///
2407 /// If [isFunctionExpression] is true, this method parses the rest of named
2408 /// function expression which isn't legal syntax in Dart. Useful for
2409 /// recovering from Javascript code being pasted into a Dart proram, as it
2410 /// will interpret `function foo() {}` as a named function expression with
2411 /// return type `function` and name `foo`.
2412 ///
2367 /// Precondition: the parser has previously generated these events: 2413 /// Precondition: the parser has previously generated these events:
2368 /// 2414 ///
2369 /// - Type variables. 2415 /// - Type variables.
2370 /// - beginLocalFunctionDeclaration. 2416 /// - `beginLocalFunctionDeclaration` if [isFunctionExpression] is false,
2417 /// otherwise `beginNamedFunctionExpression`.
2371 /// - Modifiers. 2418 /// - Modifiers.
2372 /// - Return type. 2419 /// - Return type.
2373 Token parseLocalFunctionDeclarationRest( 2420 Token parseNamedFunctionRest(
2374 Token begin, Token name, Token formals) { 2421 Token begin, Token name, Token formals, bool isFunctionExpression) {
2375 Token token = name; 2422 Token token = name;
2376 listener.beginFunctionName(token); 2423 listener.beginFunctionName(token);
2377 token = parseIdentifier(token, IdentifierContext.localFunctionDeclaration); 2424 token = parseIdentifier(token, IdentifierContext.localFunctionDeclaration);
2425 if (isFunctionExpression) {
2426 reportRecoverableError(name, fasta.messageNamedFunctionExpression);
2427 }
2378 listener.endFunctionName(begin, token); 2428 listener.endFunctionName(begin, token);
2379 token = parseFormalParametersOpt(formals, MemberKind.Local); 2429 token = parseFormalParametersOpt(formals, MemberKind.Local);
2380 token = parseInitializersOpt(token); 2430 token = parseInitializersOpt(token);
2381 token = parseAsyncOptBody(token, false, false); 2431 token = parseAsyncOptBody(token, isFunctionExpression, false);
2382 listener.endLocalFunctionDeclaration(token); 2432 if (isFunctionExpression) {
2383 return token.next; 2433 listener.endNamedFunctionExpression(token);
2384 } 2434 return token;
2385 2435 } else {
2386 /// Parses a named function expression which isn't legal syntax in Dart. 2436 listener.endLocalFunctionDeclaration(token);
2387 /// Useful for recovering from Javascript code being pasted into a Dart 2437 return token.next;
2388 /// proram, as it will interpret `function foo() {}` as a named function
2389 /// expression with return type `function` and name `foo`.
2390 Token parseNamedFunctionExpression(Token token) {
2391 Token beginToken = token;
2392 listener.beginNamedFunctionExpression(token);
2393 listener.handleModifiers(0);
2394 token = parseType(token, TypeContinuation.Optional);
2395 if (token != beginToken) {
2396 reportRecoverableError(token, fasta.messageReturnTypeFunctionExpression);
2397 } 2438 }
2398 listener.beginFunctionName(token);
2399 Token nameToken = token;
2400 token = parseIdentifier(token, IdentifierContext.functionExpressionName);
2401 reportRecoverableError(nameToken, fasta.messageNamedFunctionExpression);
2402 listener.endFunctionName(beginToken, token);
2403 token = parseTypeVariablesOpt(token);
2404 token = parseFormalParameters(token, MemberKind.Local);
2405 listener.handleNoInitializers();
2406 token = parseAsyncOptBody(token, true, false);
2407 listener.endNamedFunctionExpression(token);
2408 return token;
2409 } 2439 }
2410 2440
2411 /// Parses a function body optionally preceded by an async modifier (see 2441 /// Parses a function body optionally preceded by an async modifier (see
2412 /// [parseAsyncModifier]). This method is used in both expression context 2442 /// [parseAsyncModifier]). This method is used in both expression context
2413 /// (when [isExpression] is true) and statement context. In statement context 2443 /// (when [ofFunctionExpression] is true) and statement context. In statement
2414 /// (when [isExpression] is false), and if the function body is on the form 2444 /// context (when [ofFunctionExpression] is false), and if the function body
2415 /// `=> expression`, a trailing semicolon is required. 2445 /// is on the form `=> expression`, a trailing semicolon is required.
2416 /// 2446 ///
2417 /// It's an error if there's no function body unless [allowAbstract] is true. 2447 /// It's an error if there's no function body unless [allowAbstract] is true.
2418 Token parseAsyncOptBody(Token token, bool isExpression, bool allowAbstract) { 2448 Token parseAsyncOptBody(
2449 Token token, bool ofFunctionExpression, bool allowAbstract) {
2419 AsyncModifier savedAsyncModifier = asyncState; 2450 AsyncModifier savedAsyncModifier = asyncState;
2420 token = parseAsyncModifier(token); 2451 token = parseAsyncModifier(token);
2421 token = parseFunctionBody(token, isExpression, allowAbstract); 2452 token = parseFunctionBody(token, ofFunctionExpression, allowAbstract);
2422 asyncState = savedAsyncModifier; 2453 asyncState = savedAsyncModifier;
2423 return token; 2454 return token;
2424 } 2455 }
2425 2456
2426 Token parseConstructorReference(Token token) { 2457 Token parseConstructorReference(Token token) {
2427 Token start = token; 2458 Token start = token;
2428 listener.beginConstructorReference(start); 2459 listener.beginConstructorReference(start);
2429 token = parseIdentifier(token, IdentifierContext.constructorReference); 2460 token = parseIdentifier(token, IdentifierContext.constructorReference);
2430 token = parseQualifiedRestOpt( 2461 token = parseQualifiedRestOpt(
2431 token, IdentifierContext.constructorReferenceContinuation); 2462 token, IdentifierContext.constructorReferenceContinuation);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2475 listener.handleFunctionBodySkipped(token, true); 2506 listener.handleFunctionBodySkipped(token, true);
2476 } else { 2507 } else {
2477 token = skipBlock(token); 2508 token = skipBlock(token);
2478 listener.handleFunctionBodySkipped(token, false); 2509 listener.handleFunctionBodySkipped(token, false);
2479 } 2510 }
2480 } 2511 }
2481 return token; 2512 return token;
2482 } 2513 }
2483 2514
2484 /// Parses a function body. This method is used in both expression context 2515 /// Parses a function body. This method is used in both expression context
2485 /// (when [isExpression] is true) and statement context. In statement context 2516 /// (when [ofFunctionExpression] is true) and statement context. In statement
2486 /// (when [isExpression] is false), and if the function body is on the form 2517 /// context (when [ofFunctionExpression] is false), and if the function body
2487 /// `=> expression`, a trailing semicolon is required. 2518 /// is on the form `=> expression`, a trailing semicolon is required.
2488 /// 2519 ///
2489 /// It's an error if there's no function body unless [allowAbstract] is true. 2520 /// It's an error if there's no function body unless [allowAbstract] is true.
2490 Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) { 2521 Token parseFunctionBody(
2522 Token token, bool ofFunctionExpression, bool allowAbstract) {
2491 if (optional(';', token)) { 2523 if (optional(';', token)) {
2492 if (!allowAbstract) { 2524 if (!allowAbstract) {
2493 reportRecoverableError(token, fasta.messageExpectedBody); 2525 reportRecoverableError(token, fasta.messageExpectedBody);
2494 } 2526 }
2495 listener.handleEmptyFunctionBody(token); 2527 listener.handleEmptyFunctionBody(token);
2496 return token; 2528 return token;
2497 } else if (optional('=>', token)) { 2529 } else if (optional('=>', token)) {
2498 Token begin = token; 2530 Token begin = token;
2499 token = parseExpression(token.next); 2531 token = parseExpression(token.next);
2500 if (!isExpression) { 2532 if (!ofFunctionExpression) {
2501 expectSemicolon(token); 2533 expectSemicolon(token);
2502 listener.handleExpressionFunctionBody(begin, token); 2534 listener.handleExpressionFunctionBody(begin, token);
2503 } else { 2535 } else {
2504 listener.handleExpressionFunctionBody(begin, null); 2536 listener.handleExpressionFunctionBody(begin, null);
2505 } 2537 }
2506 return token; 2538 return token;
2507 } else if (optional('=', token)) { 2539 } else if (optional('=', token)) {
2508 Token begin = token; 2540 Token begin = token;
2509 // Recover from a bad factory method. 2541 // Recover from a bad factory method.
2510 reportRecoverableError(token, fasta.messageExpectedBody); 2542 reportRecoverableError(token, fasta.messageExpectedBody);
2511 token = parseExpression(token.next); 2543 token = parseExpression(token.next);
2512 if (!isExpression) { 2544 if (!ofFunctionExpression) {
2513 expectSemicolon(token); 2545 expectSemicolon(token);
2514 listener.handleExpressionFunctionBody(begin, token); 2546 listener.handleExpressionFunctionBody(begin, token);
2515 } else { 2547 } else {
2516 listener.handleExpressionFunctionBody(begin, null); 2548 listener.handleExpressionFunctionBody(begin, null);
2517 } 2549 }
2518 return token; 2550 return token;
2519 } 2551 }
2520 Token begin = token; 2552 Token begin = token;
2521 int statementCount = 0; 2553 int statementCount = 0;
2522 if (!optional('{', token)) { 2554 if (!optional('{', token)) {
2523 token = reportUnrecoverableErrorWithToken( 2555 token = reportUnrecoverableErrorWithToken(
2524 token, fasta.templateExpectedFunctionBody) 2556 token, fasta.templateExpectedFunctionBody)
2525 .next; 2557 .next;
2526 listener.handleInvalidFunctionBody(token); 2558 listener.handleInvalidFunctionBody(token);
2527 return token; 2559 return token;
2528 } 2560 }
2529 2561
2530 listener.beginBlockFunctionBody(begin); 2562 listener.beginBlockFunctionBody(begin);
2531 token = token.next; 2563 token = token.next;
2532 while (notEofOrValue('}', token)) { 2564 while (notEofOrValue('}', token)) {
2533 token = parseStatement(token); 2565 token = parseStatement(token);
2534 ++statementCount; 2566 ++statementCount;
2535 } 2567 }
2536 listener.endBlockFunctionBody(statementCount, begin, token); 2568 listener.endBlockFunctionBody(statementCount, begin, token);
2537 expect('}', token); 2569 expect('}', token);
2538 return isExpression ? token.next : token; 2570 return ofFunctionExpression ? token.next : token;
2539 } 2571 }
2540 2572
2541 Token skipAsyncModifier(Token token) { 2573 Token skipAsyncModifier(Token token) {
2542 String value = token.stringValue; 2574 String value = token.stringValue;
2543 if (identical(value, 'async')) { 2575 if (identical(value, 'async')) {
2544 token = token.next; 2576 token = token.next;
2545 value = token.stringValue; 2577 value = token.stringValue;
2546 2578
2547 if (identical(value, '*')) { 2579 if (identical(value, '*')) {
2548 token = token.next; 2580 token = token.next;
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after
3022 return parseLiteralNull(token); 3054 return parseLiteralNull(token);
3023 } else if (identical(value, "this")) { 3055 } else if (identical(value, "this")) {
3024 return parseThisExpression(token, context); 3056 return parseThisExpression(token, context);
3025 } else if (identical(value, "super")) { 3057 } else if (identical(value, "super")) {
3026 return parseSuperExpression(token, context); 3058 return parseSuperExpression(token, context);
3027 } else if (identical(value, "new")) { 3059 } else if (identical(value, "new")) {
3028 return parseNewExpression(token); 3060 return parseNewExpression(token);
3029 } else if (identical(value, "const")) { 3061 } else if (identical(value, "const")) {
3030 return parseConstExpression(token); 3062 return parseConstExpression(token);
3031 } else if (identical(value, "void")) { 3063 } else if (identical(value, "void")) {
3032 return parseNamedFunctionExpression(token); 3064 return parseSendOrFunctionLiteral(token, context);
3033 } else if (!inPlainSync && 3065 } else if (!inPlainSync &&
3034 (identical(value, "yield") || identical(value, "async"))) { 3066 (identical(value, "yield") || identical(value, "async"))) {
3035 return expressionExpected(token); 3067 return expressionExpected(token);
3036 } else if (identical(value, "assert")) { 3068 } else if (identical(value, "assert")) {
3037 return parseAssert(token, Assert.Expression); 3069 return parseAssert(token, Assert.Expression);
3038 } else if (token.isIdentifier) { 3070 } else if (token.isIdentifier) {
3039 return parseSendOrFunctionLiteral(token, context); 3071 return parseSendOrFunctionLiteral(token, context);
3040 } else { 3072 } else {
3041 return expressionExpected(token); 3073 return expressionExpected(token);
3042 } 3074 }
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
3240 } 3272 }
3241 3273
3242 Token parseSendOrFunctionLiteral(Token token, IdentifierContext context) { 3274 Token parseSendOrFunctionLiteral(Token token, IdentifierContext context) {
3243 if (!mayParseFunctionExpressions) { 3275 if (!mayParseFunctionExpressions) {
3244 return parseSend(token, context); 3276 return parseSend(token, context);
3245 } else { 3277 } else {
3246 return parseType(token, TypeContinuation.SendOrFunctionLiteral, context); 3278 return parseType(token, TypeContinuation.SendOrFunctionLiteral, context);
3247 } 3279 }
3248 } 3280 }
3249 3281
3250 bool isFunctionDeclaration(Token token) {
3251 if (optional('<', token)) {
3252 Token closeBrace = closeBraceTokenFor(token);
3253 if (closeBrace == null) return false;
3254 token = closeBrace.next;
3255 }
3256 if (optional('(', token)) {
3257 String afterParens = closeBraceTokenFor(token).next.stringValue;
3258 if (identical(afterParens, '{') ||
3259 identical(afterParens, '=>') ||
3260 identical(afterParens, 'async') ||
3261 identical(afterParens, 'sync')) {
3262 return true;
3263 }
3264 }
3265 return false;
3266 }
3267
3268 Token parseRequiredArguments(Token token) { 3282 Token parseRequiredArguments(Token token) {
3269 if (optional('(', token)) { 3283 if (optional('(', token)) {
3270 token = parseArguments(token); 3284 token = parseArguments(token);
3271 } else { 3285 } else {
3272 listener.handleNoArguments(token); 3286 listener.handleNoArguments(token);
3273 token = reportUnexpectedToken(token).next; 3287 token = reportUnexpectedToken(token).next;
3274 } 3288 }
3275 return token; 3289 return token;
3276 } 3290 }
3277 3291
(...skipping 769 matching lines...) Expand 10 before | Expand all | Expand 10 after
4047 } 4061 }
4048 4062
4049 Token reportUnexpectedToken(Token token) { 4063 Token reportUnexpectedToken(Token token) {
4050 return reportUnrecoverableErrorWithToken( 4064 return reportUnrecoverableErrorWithToken(
4051 token, fasta.templateUnexpectedToken); 4065 token, fasta.templateUnexpectedToken);
4052 } 4066 }
4053 } 4067 }
4054 4068
4055 // TODO(ahe): Remove when analyzer supports generalized function syntax. 4069 // TODO(ahe): Remove when analyzer supports generalized function syntax.
4056 typedef _MessageWithArgument<T> = Message Function(T); 4070 typedef _MessageWithArgument<T> = Message Function(T);
OLDNEW
« no previous file with comments | « pkg/front_end/lib/src/fasta/parser/listener.dart ('k') | pkg/front_end/lib/src/incremental/unlinked_unit.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698