OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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); |
OLD | NEW |