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 1185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1196 // may get injected from a comment. | 1196 // may get injected from a comment. |
1197 Token formals = parseTypeVariablesOpt(afterId); | 1197 Token formals = parseTypeVariablesOpt(afterId); |
1198 | 1198 |
1199 listener.beginLocalFunctionDeclaration(begin); | 1199 listener.beginLocalFunctionDeclaration(begin); |
1200 listener.handleModifiers(0); | 1200 listener.handleModifiers(0); |
1201 if (voidToken != null) { | 1201 if (voidToken != null) { |
1202 listener.handleVoidKeyword(voidToken); | 1202 listener.handleVoidKeyword(voidToken); |
1203 } else { | 1203 } else { |
1204 commitType(); | 1204 commitType(); |
1205 } | 1205 } |
1206 listener.beginFunctionName(token); | 1206 return parseLocalFunctionDeclarationRest(begin, token, formals); |
1207 token = parseIdentifier( | |
1208 token, IdentifierContext.localFunctionDeclaration); | |
1209 listener.endFunctionName(begin, token); | |
1210 return parseLocalFunctionDeclarationFromFormals(formals); | |
1211 } | 1207 } |
1212 } else if (identical(afterIdKind, LT_TOKEN)) { | 1208 } else if (identical(afterIdKind, LT_TOKEN)) { |
1213 // We are looking at `type identifier '<'`. | 1209 // We are looking at `type identifier '<'`. |
1214 Token formals = closeBraceTokenFor(afterId)?.next; | 1210 Token formals = closeBraceTokenFor(afterId)?.next; |
1215 if (formals != null && optional("(", formals)) { | 1211 if (formals != null && optional("(", formals)) { |
1216 if (looksLikeFunctionBody(closeBraceTokenFor(formals).next)) { | 1212 if (looksLikeFunctionBody(closeBraceTokenFor(formals).next)) { |
1217 // We are looking at "type identifier '<' ... '>' '(' ... ')'" | 1213 // We are looking at "type identifier '<' ... '>' '(' ... ')'" |
1218 // followed by '{', '=>', 'async', or 'sync'. | 1214 // followed by '{', '=>', 'async', or 'sync'. |
1219 parseTypeVariablesOpt(afterId); | 1215 parseTypeVariablesOpt(afterId); |
1220 listener.beginLocalFunctionDeclaration(begin); | 1216 listener.beginLocalFunctionDeclaration(begin); |
1221 listener.handleModifiers(0); | 1217 listener.handleModifiers(0); |
1222 if (voidToken != null) { | 1218 if (voidToken != null) { |
1223 listener.handleVoidKeyword(voidToken); | 1219 listener.handleVoidKeyword(voidToken); |
1224 } else { | 1220 } else { |
1225 commitType(); | 1221 commitType(); |
1226 } | 1222 } |
1227 listener.beginFunctionName(token); | 1223 return parseLocalFunctionDeclarationRest(begin, token, formals); |
1228 token = parseIdentifier( | |
1229 token, IdentifierContext.localFunctionDeclaration); | |
1230 listener.endFunctionName(begin, token); | |
1231 return parseLocalFunctionDeclarationFromFormals(formals); | |
1232 } | 1224 } |
1233 } | 1225 } |
1234 } | 1226 } |
1235 // Fall-through to expression statement. | 1227 // Fall-through to expression statement. |
1236 } else { | 1228 } else { |
1237 token = begin; | 1229 token = begin; |
1238 if (optional(':', token.next)) { | 1230 if (optional(':', token.next)) { |
1239 return parseLabeledStatement(token); | 1231 return parseLabeledStatement(token); |
1240 } else if (optional('(', token.next)) { | 1232 } else if (optional('(', token.next)) { |
1241 if (looksLikeFunctionBody(closeBraceTokenFor(token.next).next)) { | 1233 if (looksLikeFunctionBody(closeBraceTokenFor(token.next).next)) { |
1242 // We are looking at `identifier '(' ... ')'` followed by `'{'`, | 1234 // We are looking at `identifier '(' ... ')'` followed by `'{'`, |
1243 // `'=>'`, `'async'`, or `'sync'`. | 1235 // `'=>'`, `'async'`, or `'sync'`. |
1244 | 1236 |
1245 // Although it looks like there are no type variables here, they | 1237 // Although it looks like there are no type variables here, they |
1246 // may get injected from a comment. | 1238 // may get injected from a comment. |
1247 Token formals = parseTypeVariablesOpt(token.next); | 1239 Token formals = parseTypeVariablesOpt(token.next); |
1248 | 1240 |
1249 listener.beginLocalFunctionDeclaration(token); | 1241 listener.beginLocalFunctionDeclaration(token); |
1250 listener.handleModifiers(0); | 1242 listener.handleModifiers(0); |
1251 listener.handleNoType(token); | 1243 listener.handleNoType(token); |
1252 listener.beginFunctionName(token); | 1244 return parseLocalFunctionDeclarationRest(begin, token, formals); |
1253 token = parseIdentifier( | |
1254 token, IdentifierContext.localFunctionDeclaration); | |
1255 listener.endFunctionName(begin, token); | |
1256 return parseLocalFunctionDeclarationFromFormals(formals); | |
1257 } | 1245 } |
1258 } else if (optional('<', token.next)) { | 1246 } else if (optional('<', token.next)) { |
1259 Token afterTypeVariables = closeBraceTokenFor(token.next)?.next; | 1247 Token afterTypeVariables = closeBraceTokenFor(token.next)?.next; |
1260 if (afterTypeVariables != null && | 1248 if (afterTypeVariables != null && |
1261 optional("(", afterTypeVariables)) { | 1249 optional("(", afterTypeVariables)) { |
1262 if (looksLikeFunctionBody( | 1250 if (looksLikeFunctionBody( |
1263 closeBraceTokenFor(afterTypeVariables).next)) { | 1251 closeBraceTokenFor(afterTypeVariables).next)) { |
1264 // We are looking at `identifier '<' ... '>' '(' ... ')'` | 1252 // We are looking at `identifier '<' ... '>' '(' ... ')'` |
1265 // followed by `'{'`, `'=>'`, `'async'`, or `'sync'`. | 1253 // followed by `'{'`, `'=>'`, `'async'`, or `'sync'`. |
1266 parseTypeVariablesOpt(token.next); | 1254 parseTypeVariablesOpt(token.next); |
1267 listener.beginLocalFunctionDeclaration(token); | 1255 listener.beginLocalFunctionDeclaration(token); |
1268 listener.handleModifiers(0); | 1256 listener.handleModifiers(0); |
1269 listener.handleNoType(token); | 1257 listener.handleNoType(token); |
1270 listener.beginFunctionName(token); | 1258 return parseLocalFunctionDeclarationRest( |
1271 token = parseIdentifier( | 1259 begin, token, afterTypeVariables); |
1272 token, IdentifierContext.localFunctionDeclaration); | |
1273 listener.endFunctionName(begin, token); | |
1274 return parseLocalFunctionDeclarationFromFormals( | |
1275 afterTypeVariables); | |
1276 } | 1260 } |
1277 } | 1261 } |
1278 // Fall through to expression statement. | 1262 // Fall through to expression statement. |
1279 } | 1263 } |
1280 } | 1264 } |
1281 return parseExpressionStatement(begin); | 1265 return parseExpressionStatement(begin); |
1282 | 1266 |
1283 case TypeContinuation.ExpressionStatementOrConstDeclaration: | 1267 case TypeContinuation.ExpressionStatementOrConstDeclaration: |
1284 Token identifier; | 1268 Token identifier; |
1285 if (looksLikeType && token.isIdentifier) { | 1269 if (looksLikeType && token.isIdentifier) { |
(...skipping 1078 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2364 return token.next; | 2348 return token.next; |
2365 } else { | 2349 } else { |
2366 return parseIdentifier(token, IdentifierContext.operatorName); | 2350 return parseIdentifier(token, IdentifierContext.operatorName); |
2367 } | 2351 } |
2368 } | 2352 } |
2369 | 2353 |
2370 Token parseFunctionExpression(Token token) { | 2354 Token parseFunctionExpression(Token token) { |
2371 Token beginToken = token; | 2355 Token beginToken = token; |
2372 listener.beginFunctionExpression(token); | 2356 listener.beginFunctionExpression(token); |
2373 token = parseFormalParameters(token, MemberKind.Local); | 2357 token = parseFormalParameters(token, MemberKind.Local); |
2374 AsyncModifier savedAsyncModifier = asyncState; | 2358 token = parseAsyncOptBody(token, true, false); |
2375 token = parseAsyncModifier(token); | |
2376 bool isBlock = optional('{', token); | |
2377 token = parseFunctionBody(token, true, false); | |
2378 asyncState = savedAsyncModifier; | |
2379 listener.endFunctionExpression(beginToken, token); | 2359 listener.endFunctionExpression(beginToken, token); |
2380 return isBlock ? token.next : token; | 2360 return token; |
2381 } | 2361 } |
2382 | 2362 |
2383 /// Parses the rest of a local function declaration starting from formal | 2363 /// Parses the rest of a local function declaration starting from its [name] |
2384 /// parameters. | 2364 /// but then skips any type parameters and continue parsing from [formals] |
| 2365 /// (the formal parameters). |
2385 /// | 2366 /// |
2386 /// Precondition: the parser has previously generated these events: | 2367 /// Precondition: the parser has previously generated these events: |
2387 /// | 2368 /// |
2388 /// - Type variables. | 2369 /// - Type variables. |
2389 /// - beginLocalFunctionDeclaration. | 2370 /// - beginLocalFunctionDeclaration. |
2390 /// - Modifiers. | 2371 /// - Modifiers. |
2391 /// - Return type. | 2372 /// - Return type. |
2392 /// - Function name. | 2373 Token parseLocalFunctionDeclarationRest( |
2393 Token parseLocalFunctionDeclarationFromFormals(Token token) { | 2374 Token begin, Token name, Token formals) { |
2394 token = parseFormalParametersOpt(token, MemberKind.Local); | 2375 Token token = name; |
| 2376 listener.beginFunctionName(token); |
| 2377 token = parseIdentifier(token, IdentifierContext.localFunctionDeclaration); |
| 2378 listener.endFunctionName(begin, token); |
| 2379 token = parseFormalParametersOpt(formals, MemberKind.Local); |
2395 token = parseInitializersOpt(token); | 2380 token = parseInitializersOpt(token); |
2396 AsyncModifier savedAsyncModifier = asyncState; | 2381 token = parseAsyncOptBody(token, false, false); |
2397 token = parseAsyncModifier(token); | |
2398 token = parseFunctionBody(token, false, true); | |
2399 asyncState = savedAsyncModifier; | |
2400 token = token.next; | |
2401 listener.endLocalFunctionDeclaration(token); | 2382 listener.endLocalFunctionDeclaration(token); |
2402 return token; | 2383 return token.next; |
2403 } | 2384 } |
2404 | 2385 |
2405 /// Parses a named function expression which isn't legal syntax in Dart. | 2386 /// Parses a named function expression which isn't legal syntax in Dart. |
2406 /// Useful for recovering from Javascript code being pasted into a Dart | 2387 /// Useful for recovering from Javascript code being pasted into a Dart |
2407 /// proram, as it will interpret `function foo() {}` as a named function | 2388 /// proram, as it will interpret `function foo() {}` as a named function |
2408 /// expression with return type `function` and name `foo`. | 2389 /// expression with return type `function` and name `foo`. |
2409 Token parseNamedFunctionExpression(Token token) { | 2390 Token parseNamedFunctionExpression(Token token) { |
2410 Token beginToken = token; | 2391 Token beginToken = token; |
2411 listener.beginNamedFunctionExpression(token); | 2392 listener.beginNamedFunctionExpression(token); |
2412 listener.handleModifiers(0); | 2393 listener.handleModifiers(0); |
2413 token = parseType(token, TypeContinuation.Optional); | 2394 token = parseType(token, TypeContinuation.Optional); |
2414 if (token != beginToken) { | 2395 if (token != beginToken) { |
2415 reportRecoverableError(token, fasta.messageReturnTypeFunctionExpression); | 2396 reportRecoverableError(token, fasta.messageReturnTypeFunctionExpression); |
2416 } | 2397 } |
2417 listener.beginFunctionName(token); | 2398 listener.beginFunctionName(token); |
2418 Token nameToken = token; | 2399 Token nameToken = token; |
2419 token = parseIdentifier(token, IdentifierContext.functionExpressionName); | 2400 token = parseIdentifier(token, IdentifierContext.functionExpressionName); |
2420 reportRecoverableError(nameToken, fasta.messageNamedFunctionExpression); | 2401 reportRecoverableError(nameToken, fasta.messageNamedFunctionExpression); |
2421 listener.endFunctionName(beginToken, token); | 2402 listener.endFunctionName(beginToken, token); |
2422 token = parseTypeVariablesOpt(token); | 2403 token = parseTypeVariablesOpt(token); |
2423 token = parseFormalParameters(token, MemberKind.Local); | 2404 token = parseFormalParameters(token, MemberKind.Local); |
2424 listener.handleNoInitializers(); | 2405 listener.handleNoInitializers(); |
| 2406 token = parseAsyncOptBody(token, true, false); |
| 2407 listener.endNamedFunctionExpression(token); |
| 2408 return token; |
| 2409 } |
| 2410 |
| 2411 /// Parses a function body optionally preceded by an async modifier (see |
| 2412 /// [parseAsyncModifier]). This method is used in both expression context |
| 2413 /// (when [isExpression] is true) and statement context. In statement context |
| 2414 /// (when [isExpression] is false), and if the function body is on the form |
| 2415 /// `=> expression`, a trailing semicolon is required. |
| 2416 /// |
| 2417 /// It's an error if there's no function body unless [allowAbstract] is true. |
| 2418 Token parseAsyncOptBody(Token token, bool isExpression, bool allowAbstract) { |
2425 AsyncModifier savedAsyncModifier = asyncState; | 2419 AsyncModifier savedAsyncModifier = asyncState; |
2426 token = parseAsyncModifier(token); | 2420 token = parseAsyncModifier(token); |
2427 bool isBlock = optional('{', token); | 2421 token = parseFunctionBody(token, isExpression, allowAbstract); |
2428 token = parseFunctionBody(token, true, false); | |
2429 asyncState = savedAsyncModifier; | 2422 asyncState = savedAsyncModifier; |
2430 listener.endNamedFunctionExpression(token); | 2423 return token; |
2431 return isBlock ? token.next : token; | |
2432 } | 2424 } |
2433 | 2425 |
2434 Token parseConstructorReference(Token token) { | 2426 Token parseConstructorReference(Token token) { |
2435 Token start = token; | 2427 Token start = token; |
2436 listener.beginConstructorReference(start); | 2428 listener.beginConstructorReference(start); |
2437 token = parseIdentifier(token, IdentifierContext.constructorReference); | 2429 token = parseIdentifier(token, IdentifierContext.constructorReference); |
2438 token = parseQualifiedRestOpt( | 2430 token = parseQualifiedRestOpt( |
2439 token, IdentifierContext.constructorReferenceContinuation); | 2431 token, IdentifierContext.constructorReferenceContinuation); |
2440 token = parseTypeArgumentsOpt(token); | 2432 token = parseTypeArgumentsOpt(token); |
2441 Token period = null; | 2433 Token period = null; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2482 expectSemicolon(token); | 2474 expectSemicolon(token); |
2483 listener.handleFunctionBodySkipped(token, true); | 2475 listener.handleFunctionBodySkipped(token, true); |
2484 } else { | 2476 } else { |
2485 token = skipBlock(token); | 2477 token = skipBlock(token); |
2486 listener.handleFunctionBodySkipped(token, false); | 2478 listener.handleFunctionBodySkipped(token, false); |
2487 } | 2479 } |
2488 } | 2480 } |
2489 return token; | 2481 return token; |
2490 } | 2482 } |
2491 | 2483 |
| 2484 /// Parses a function body. This method is used in both expression context |
| 2485 /// (when [isExpression] is true) and statement context. In statement context |
| 2486 /// (when [isExpression] is false), and if the function body is on the form |
| 2487 /// `=> expression`, a trailing semicolon is required. |
| 2488 /// |
| 2489 /// It's an error if there's no function body unless [allowAbstract] is true. |
2492 Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) { | 2490 Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) { |
2493 if (optional(';', token)) { | 2491 if (optional(';', token)) { |
2494 if (!allowAbstract) { | 2492 if (!allowAbstract) { |
2495 reportRecoverableError(token, fasta.messageExpectedBody); | 2493 reportRecoverableError(token, fasta.messageExpectedBody); |
2496 } | 2494 } |
2497 listener.handleEmptyFunctionBody(token); | 2495 listener.handleEmptyFunctionBody(token); |
2498 return token; | 2496 return token; |
2499 } else if (optional('=>', token)) { | 2497 } else if (optional('=>', token)) { |
2500 Token begin = token; | 2498 Token begin = token; |
2501 token = parseExpression(token.next); | 2499 token = parseExpression(token.next); |
(...skipping 28 matching lines...) Expand all Loading... |
2530 } | 2528 } |
2531 | 2529 |
2532 listener.beginBlockFunctionBody(begin); | 2530 listener.beginBlockFunctionBody(begin); |
2533 token = token.next; | 2531 token = token.next; |
2534 while (notEofOrValue('}', token)) { | 2532 while (notEofOrValue('}', token)) { |
2535 token = parseStatement(token); | 2533 token = parseStatement(token); |
2536 ++statementCount; | 2534 ++statementCount; |
2537 } | 2535 } |
2538 listener.endBlockFunctionBody(statementCount, begin, token); | 2536 listener.endBlockFunctionBody(statementCount, begin, token); |
2539 expect('}', token); | 2537 expect('}', token); |
2540 return token; | 2538 return isExpression ? token.next : token; |
2541 } | 2539 } |
2542 | 2540 |
2543 Token skipAsyncModifier(Token token) { | 2541 Token skipAsyncModifier(Token token) { |
2544 String value = token.stringValue; | 2542 String value = token.stringValue; |
2545 if (identical(value, 'async')) { | 2543 if (identical(value, 'async')) { |
2546 token = token.next; | 2544 token = token.next; |
2547 value = token.stringValue; | 2545 value = token.stringValue; |
2548 | 2546 |
2549 if (identical(value, '*')) { | 2547 if (identical(value, '*')) { |
2550 token = token.next; | 2548 token = token.next; |
(...skipping 1498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4049 } | 4047 } |
4050 | 4048 |
4051 Token reportUnexpectedToken(Token token) { | 4049 Token reportUnexpectedToken(Token token) { |
4052 return reportUnrecoverableErrorWithToken( | 4050 return reportUnrecoverableErrorWithToken( |
4053 token, fasta.templateUnexpectedToken); | 4051 token, fasta.templateUnexpectedToken); |
4054 } | 4052 } |
4055 } | 4053 } |
4056 | 4054 |
4057 // TODO(ahe): Remove when analyzer supports generalized function syntax. | 4055 // TODO(ahe): Remove when analyzer supports generalized function syntax. |
4058 typedef _MessageWithArgument<T> = Message Function(T); | 4056 typedef _MessageWithArgument<T> = Message Function(T); |
OLD | NEW |