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

Side by Side Diff: pkg/compiler/lib/src/parser/parser.dart

Issue 2567133002: Add support for the new function-type syntax. (Closed)
Patch Set: Update status files and update test-generator for checked mode. Created 3 years, 11 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 dart2js.parser; 5 library dart2js.parser;
6 6
7 import '../common.dart'; 7 import '../common.dart';
8 import '../tokens/keyword.dart' show Keyword; 8 import '../tokens/keyword.dart' show Keyword;
9 import '../tokens/precedence.dart' show PrecedenceInfo; 9 import '../tokens/precedence.dart' show PrecedenceInfo;
10 import '../tokens/precedence_constants.dart' 10 import '../tokens/precedence_constants.dart'
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 period = token; 355 period = token;
356 token = parseIdentifier(token.next); 356 token = parseIdentifier(token.next);
357 } 357 }
358 token = parseArgumentsOpt(token); 358 token = parseArgumentsOpt(token);
359 listener.endMetadata(atToken, period, token); 359 listener.endMetadata(atToken, period, token);
360 return token; 360 return token;
361 } 361 }
362 362
363 Token parseTypedef(Token token) { 363 Token parseTypedef(Token token) {
364 Token typedefKeyword = token; 364 Token typedefKeyword = token;
365 listener.beginFunctionTypeAlias(token); 365 listener.beginTypedef(token);
366 token = parseReturnTypeOpt(token.next); 366 Token equals;
367 token = parseIdentifier(token); 367 if (optional('=', peekAfterType(token.next))) {
368 token = parseTypeVariablesOpt(token); 368 token = parseIdentifier(token.next);
369 token = parseFormalParameters(token); 369 token = parseTypeVariablesOpt(token);
370 listener.endFunctionTypeAlias(typedefKeyword, token); 370 equals = expect('=', token);
371 token = parseType(equals);
372 } else {
373 token = parseReturnTypeOpt(token.next);
374 token = parseIdentifier(token);
375 token = parseTypeVariablesOpt(token);
376 token = parseFormalParameters(token);
377 }
378 listener.endTypedef(typedefKeyword, equals, token);
371 return expect(';', token); 379 return expect(';', token);
372 } 380 }
373 381
374 Token parseMixinApplication(Token token) { 382 Token parseMixinApplication(Token token) {
375 listener.beginMixinApplication(token); 383 listener.beginMixinApplication(token);
376 token = parseType(token); 384 token = parseType(token);
377 token = expect('with', token); 385 token = expect('with', token);
378 token = parseTypeList(token); 386 token = parseTypeList(token);
379 listener.endMixinApplication(); 387 listener.endMixinApplication();
380 return token; 388 return token;
381 } 389 }
382 390
383 Token parseReturnTypeOpt(Token token) { 391 Token parseReturnTypeOpt(Token token, {bool allowFunctionType: true}) {
384 if (identical(token.stringValue, 'void')) { 392 if (identical(token.stringValue, 'void')) {
385 listener.handleVoidKeyword(token); 393 listener.handleVoidKeyword(token);
386 return token.next; 394 return token.next;
395 } else if (!allowFunctionType && isGeneralizedFunctionType(token)) {
396 listener.handleNoType(token);
397 return token;
387 } else { 398 } else {
388 return parseTypeOpt(token); 399 return parseTypeOpt(token);
389 } 400 }
390 } 401 }
391 402
392 Token parseFormalParametersOpt(Token token) { 403 Token parseFormalParametersOpt(Token token) {
393 if (optional('(', token)) { 404 if (optional('(', token)) {
394 return parseFormalParameters(token); 405 return parseFormalParameters(token);
395 } else { 406 } else {
396 listener.handleNoFormalParameters(token); 407 listener.handleNoFormalParameters(token);
397 return token; 408 return token;
398 } 409 }
399 } 410 }
400 411
401 Token parseFormalParameters(Token token) { 412 /// Parses the formal parameter list of a function.
413 ///
414 /// If [inFunctionType] is true, then the names may be omitted (except for
415 /// named arguments). If it is false, then the types may be omitted.
416 Token parseFormalParameters(Token token, {bool inFunctionType: false}) {
402 Token begin = token; 417 Token begin = token;
403 listener.beginFormalParameters(begin); 418 listener.beginFormalParameters(begin);
404 expect('(', token); 419 expect('(', token);
405 int parameterCount = 0; 420 int parameterCount = 0;
406 do { 421 do {
407 token = token.next; 422 token = token.next;
408 if (optional(')', token)) { 423 if (optional(')', token)) {
409 break; 424 break;
410 } 425 }
411 ++parameterCount; 426 ++parameterCount;
412 String value = token.stringValue; 427 String value = token.stringValue;
413 if (identical(value, '[')) { 428 if (identical(value, '[')) {
414 token = parseOptionalFormalParameters(token, false); 429 token = parseOptionalFormalParameters(
430 token, false, inFunctionType: inFunctionType);
415 break; 431 break;
416 } else if (identical(value, '{')) { 432 } else if (identical(value, '{')) {
417 token = parseOptionalFormalParameters(token, true); 433 token = parseOptionalFormalParameters(
434 token, true, inFunctionType: inFunctionType);
418 break; 435 break;
419 } 436 }
420 token = parseFormalParameter(token, FormalParameterType.REQUIRED); 437 token = parseFormalParameter(token, FormalParameterType.REQUIRED,
438 inFunctionType: inFunctionType);
421 } while (optional(',', token)); 439 } while (optional(',', token));
422 listener.endFormalParameters(parameterCount, begin, token); 440 listener.endFormalParameters(parameterCount, begin, token);
423 return expect(')', token); 441 return expect(')', token);
424 } 442 }
425 443
426 Token parseFormalParameter(Token token, FormalParameterType type) { 444 Token parseFormalParameter(Token token, FormalParameterType type,
445 {bool inFunctionType}) {
427 token = parseMetadataStar(token, forParameter: true); 446 token = parseMetadataStar(token, forParameter: true);
428 listener.beginFormalParameter(token); 447 listener.beginFormalParameter(token);
429 token = parseModifiers(token); 448 token = parseModifiers(token);
430 // TODO(ahe): Validate that there are formal parameters if void. 449 bool isNamedParameter = type == FormalParameterType.NAMED;
431 token = parseReturnTypeOpt(token); 450
432 Token thisKeyword = null; 451 Token thisKeyword = null;
433 if (optional('this', token)) { 452 if (inFunctionType && isNamedParameter) {
434 thisKeyword = token; 453 token = parseTypeOpt(token);
435 // TODO(ahe): Validate field initializers are only used in 454 token = parseIdentifier(token);
436 // constructors, and not for function-typed arguments. 455 } else if (inFunctionType) {
437 token = expect('.', token.next); 456 token = parseType(token);
457 if (token.isIdentifier()) {
458 token = parseIdentifier(token);
459 } else {
460 listener.handleNoName(token);
461 }
462 } else {
463 // TODO(ahe): Validate that there are formal parameters if void.
464 token = parseReturnTypeOpt(token);
465 if (optional('this', token)) {
466 thisKeyword = token;
467 // TODO(ahe): Validate field initializers are only used in
468 // constructors, and not for function-typed arguments.
469 token = expect('.', token.next);
470 }
471 token = parseIdentifier(token);
438 } 472 }
439 token = parseIdentifier(token); 473
440 if (optional('(', token)) { 474 // Generalized function types don't allow inline function types.
441 listener.handleNoTypeVariables(token); 475 // The following isn't allowed:
442 token = parseFormalParameters(token); 476 // int Function(int bar(String x)).
Siggi Cherem (dart-lang) 2016/12/29 22:46:57 should we report an error instead in that case? (
floitsch 2016/12/30 14:55:47 In some sense that's what's happening. Just automa
443 listener.handleFunctionTypedFormalParameter(token); 477 if (!inFunctionType) {
444 } else if (optional('<', token)) { 478 if (optional('(', token)) {
445 token = parseTypeVariablesOpt(token); 479 listener.handleNoTypeVariables(token);
446 token = parseFormalParameters(token); 480 token = parseFormalParameters(token);
447 listener.handleFunctionTypedFormalParameter(token); 481 listener.handleFunctionTypedFormalParameter(token);
482 } else if (optional('<', token)) {
483 token = parseTypeVariablesOpt(token);
484 token = parseFormalParameters(token);
485 listener.handleFunctionTypedFormalParameter(token);
486 }
448 } 487 }
449 String value = token.stringValue; 488 String value = token.stringValue;
450 if ((identical('=', value)) || (identical(':', value))) { 489 if ((identical('=', value)) || (identical(':', value))) {
451 // TODO(ahe): Validate that these are only used for optional parameters. 490 // TODO(ahe): Validate that these are only used for optional parameters.
452 Token equal = token; 491 Token equal = token;
453 token = parseExpression(token.next); 492 token = parseExpression(token.next);
454 listener.handleValuedFormalParameter(equal, token); 493 listener.handleValuedFormalParameter(equal, token);
455 if (type.isRequired) { 494 if (type.isRequired) {
456 listener.reportError( 495 listener.reportError(
457 equal, MessageKind.REQUIRED_PARAMETER_WITH_DEFAULT); 496 equal, MessageKind.REQUIRED_PARAMETER_WITH_DEFAULT);
458 } else if (type.isPositional && identical(':', value)) { 497 } else if (type.isPositional && identical(':', value)) {
459 listener.reportError( 498 listener.reportError(
460 equal, MessageKind.POSITIONAL_PARAMETER_WITH_EQUALS); 499 equal, MessageKind.POSITIONAL_PARAMETER_WITH_EQUALS);
461 } 500 }
462 } 501 }
463 listener.endFormalParameter(thisKeyword); 502 listener.endFormalParameter(thisKeyword);
464 return token; 503 return token;
465 } 504 }
466 505
467 Token parseOptionalFormalParameters(Token token, bool isNamed) { 506 Token parseOptionalFormalParameters(Token token, bool isNamed,
507 {bool inFunctionType}) {
468 Token begin = token; 508 Token begin = token;
469 listener.beginOptionalFormalParameters(begin); 509 listener.beginOptionalFormalParameters(begin);
470 assert((isNamed && optional('{', token)) || optional('[', token)); 510 assert((isNamed && optional('{', token)) || optional('[', token));
471 int parameterCount = 0; 511 int parameterCount = 0;
472 do { 512 do {
473 token = token.next; 513 token = token.next;
474 if (isNamed && optional('}', token)) { 514 if (isNamed && optional('}', token)) {
475 break; 515 break;
476 } else if (!isNamed && optional(']', token)) { 516 } else if (!isNamed && optional(']', token)) {
477 break; 517 break;
478 } 518 }
479 var type = 519 var type =
480 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; 520 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL;
481 token = parseFormalParameter(token, type); 521 token =
522 parseFormalParameter(token, type, inFunctionType: inFunctionType);
482 ++parameterCount; 523 ++parameterCount;
483 } while (optional(',', token)); 524 } while (optional(',', token));
484 if (parameterCount == 0) { 525 if (parameterCount == 0) {
485 listener.reportError( 526 listener.reportError(
486 token, 527 token,
487 isNamed 528 isNamed
488 ? MessageKind.EMPTY_NAMED_PARAMETER_LIST 529 ? MessageKind.EMPTY_NAMED_PARAMETER_LIST
489 : MessageKind.EMPTY_OPTIONAL_PARAMETER_LIST); 530 : MessageKind.EMPTY_OPTIONAL_PARAMETER_LIST);
490 } 531 }
491 listener.endOptionalFormalParameters(parameterCount, begin, token); 532 listener.endOptionalFormalParameters(parameterCount, begin, token);
492 if (isNamed) { 533 if (isNamed) {
493 return expect('}', token); 534 return expect('}', token);
494 } else { 535 } else {
495 return expect(']', token); 536 return expect(']', token);
496 } 537 }
497 } 538 }
498 539
499 Token parseTypeOpt(Token token) { 540 Token parseTypeOpt(Token token) {
541 if (isGeneralizedFunctionType(token)) {
542 // Function type without return type.
543 return parseType(token);
544 }
500 Token peek = peekAfterIfType(token); 545 Token peek = peekAfterIfType(token);
501 if (peek != null && (peek.isIdentifier() || optional('this', peek))) { 546 if (peek != null && (peek.isIdentifier() || optional('this', peek))) {
502 return parseType(token); 547 return parseType(token);
503 } 548 }
504 listener.handleNoType(token); 549 listener.handleNoType(token);
505 return token; 550 return token;
506 } 551 }
507 552
508 bool isValidTypeReference(Token token) { 553 bool isValidTypeReference(Token token) {
509 final kind = token.kind; 554 final kind = token.kind;
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
793 value2 == stringValue || 838 value2 == stringValue ||
794 value3 == stringValue || 839 value3 == stringValue ||
795 value4 == stringValue; 840 value4 == stringValue;
796 } 841 }
797 842
798 bool notEofOrValue(String value, Token token) { 843 bool notEofOrValue(String value, Token token) {
799 return !identical(token.kind, EOF_TOKEN) && 844 return !identical(token.kind, EOF_TOKEN) &&
800 !identical(value, token.stringValue); 845 !identical(value, token.stringValue);
801 } 846 }
802 847
848 bool isGeneralizedFunctionType(Token token) {
849 // TODO(floitsch): don't use string comparison, but the keyword-state
850 // table is currently not set up to deal with upper-case characters.
851 return (optional('<', token.next) || optional('(', token.next)) &&
852 token.value == "Function";
853 }
854
803 Token parseType(Token token) { 855 Token parseType(Token token) {
804 Token begin = token; 856 Token begin = token;
805 if (isValidTypeReference(token)) { 857 if (isGeneralizedFunctionType(token)) {
806 token = parseIdentifier(token); 858 // A function type without return type.
807 token = parseQualifiedRestOpt(token); 859 // Push the non-existing return type first. The loop below will
860 // generate the full type.
861 listener.handleNoType(token);
808 } else { 862 } else {
809 token = listener.expectedType(token); 863 if (isValidTypeReference(token)) {
864 if (isGeneralizedFunctionType(token)) {
Siggi Cherem (dart-lang) 2016/12/29 22:46:58 is this branch ever executed?
floitsch 2016/12/30 14:55:47 Nope. that was old code that I didn't clean up. Go
865 // A function type without return type.
866 return parseFunctionType(token);
867 } else {
868 token = parseIdentifier(token);
869 token = parseQualifiedRestOpt(token);
870 }
871 } else {
872 token = listener.expectedType(token);
873 }
874 token = parseTypeArgumentsOpt(token);
875 listener.endType(begin, token);
810 } 876 }
811 token = parseTypeArgumentsOpt(token); 877
812 listener.endType(begin, token); 878 // While we see a `Function(` treat the pushed type as return type.
879 // For example: `int Function() Function(int) Function(String x)`.
880 while (isGeneralizedFunctionType(token)) {
881 token = parseFunctionType(token);
882 }
813 return token; 883 return token;
814 } 884 }
815 885
886 /// Parses a generalized function type.
887 ///
888 /// The return type must already be pushed.
889 Token parseFunctionType(Token token) {
890 // TODO(floitsch): don't use string comparison, but the keyword-state
891 // table is currently not set up to deal with upper-case characters.
892 if (token.value != "Function") {
893 return listener.expected("Function", token);
894 }
895 Token functionToken = token;
896 token = token.next;
897 token = parseTypeVariablesOpt(token);
898 token = parseFormalParameters(token, inFunctionType: true);
899 listener.endFunctionType(functionToken, token);
900 return token;
901 }
902
816 Token parseTypeArgumentsOpt(Token token) { 903 Token parseTypeArgumentsOpt(Token token) {
817 return parseStuff( 904 return parseStuff(
818 token, 905 token,
819 (t) => listener.beginTypeArguments(t), 906 (t) => listener.beginTypeArguments(t),
820 (t) => parseType(t), 907 (t) => parseType(t),
821 (c, bt, et) => listener.endTypeArguments(c, bt, et), 908 (c, bt, et) => listener.endTypeArguments(c, bt, et),
822 (t) => listener.handleNoTypeArguments(t)); 909 (t) => listener.handleNoTypeArguments(t));
823 } 910 }
824 911
825 Token parseTypeVariablesOpt(Token token) { 912 Token parseTypeVariablesOpt(Token token) {
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
1139 identifiers = identifiers.prepend(token); 1226 identifiers = identifiers.prepend(token);
1140 return identifiers; 1227 return identifiers;
1141 } else if (value == '=' || value == ';' || value == ',') { 1228 } else if (value == '=' || value == ';' || value == ',') {
1142 // A field or abstract getter. 1229 // A field or abstract getter.
1143 identifiers = identifiers.prepend(token); 1230 identifiers = identifiers.prepend(token);
1144 return identifiers; 1231 return identifiers;
1145 } else if (isGetter) { 1232 } else if (isGetter) {
1146 hasName = true; 1233 hasName = true;
1147 } 1234 }
1148 identifiers = identifiers.prepend(token); 1235 identifiers = identifiers.prepend(token);
1149 if (isValidTypeReference(token)) { 1236
1150 // type ... 1237 if (!isGeneralizedFunctionType(token)) {
1151 if (optional('.', token.next)) { 1238 // Read a potential return type.
1152 // type '.' ... 1239 if (isValidTypeReference(token)) {
1153 if (token.next.next.isIdentifier()) { 1240 // type ...
1154 // type '.' identifier 1241 if (optional('.', token.next)) {
1155 token = token.next.next; 1242 // type '.' ...
1243 if (token.next.next.isIdentifier()) {
1244 // type '.' identifier
1245 token = token.next.next;
1246 }
1247 }
1248 if (optional('<', token.next)) {
1249 if (token.next is BeginGroupToken) {
1250 BeginGroupToken beginGroup = token.next;
1251 if (beginGroup.endGroup == null) {
1252 listener.unmatched(beginGroup);
1253 }
1254 token = beginGroup.endGroup;
1255 }
1156 } 1256 }
1157 } 1257 }
1158 if (optional('<', token.next)) { 1258 token = token.next;
1159 if (token.next is BeginGroupToken) { 1259 }
1160 BeginGroupToken beginGroup = token.next; 1260 while (isGeneralizedFunctionType(token)) {
1261 token = token.next;
1262 if (optional('<', token)) {
1263 if (token is BeginGroupToken) {
1264 BeginGroupToken beginGroup = token;
1161 if (beginGroup.endGroup == null) { 1265 if (beginGroup.endGroup == null) {
1162 listener.unmatched(beginGroup); 1266 listener.unmatched(beginGroup);
1163 } 1267 }
1164 token = beginGroup.endGroup; 1268 token = beginGroup.endGroup.next;
1165 } 1269 }
1166 } 1270 }
1271 if (!optional('(', token)) {
1272 if (optional(';', token)) {
1273 listener.recoverableError(token, "expected '('");
1274 }
1275 token = listener.unexpected(token);
1276 }
1277 if (token is BeginGroupToken) {
1278 BeginGroupToken beginGroup = token;
1279 if (beginGroup.endGroup == null) {
1280 listener.unmatched(beginGroup);
1281 }
1282 token = beginGroup.endGroup.next;
1283 }
1167 } 1284 }
1168 token = token.next;
1169 } 1285 }
1170 return const Link<Token>(); 1286 return const Link<Token>();
1171 } 1287 }
1172 1288
1173 Token parseVariableInitializerOpt(Token token) { 1289 Token parseVariableInitializerOpt(Token token) {
1174 if (optional('=', token)) { 1290 if (optional('=', token)) {
1175 Token assignment = token; 1291 Token assignment = token;
1176 listener.beginInitializer(token); 1292 listener.beginInitializer(token);
1177 token = parseExpression(token.next); 1293 token = parseExpression(token.next);
1178 listener.endInitializer(assignment); 1294 listener.endInitializer(assignment);
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1261 return token; 1377 return token;
1262 } 1378 }
1263 1379
1264 /** 1380 /**
1265 * Returns the first token after the type starting at [token]. 1381 * Returns the first token after the type starting at [token].
1266 * This method assumes that [token] is an identifier (or void). 1382 * This method assumes that [token] is an identifier (or void).
1267 * Use [peekAfterIfType] if [token] isn't known to be an identifier. 1383 * Use [peekAfterIfType] if [token] isn't known to be an identifier.
1268 */ 1384 */
1269 Token peekAfterType(Token token) { 1385 Token peekAfterType(Token token) {
1270 // We are looking at "identifier ...". 1386 // We are looking at "identifier ...".
1271 Token peek = token.next; 1387 Token peek = token;
1272 if (identical(peek.kind, PERIOD_TOKEN)) { 1388 if (!isGeneralizedFunctionType(token)) {
1273 if (peek.next.isIdentifier()) { 1389 peek = token.next;
Siggi Cherem (dart-lang) 2016/12/29 22:46:58 suggestion: consider introducing 2 functions to ma
floitsch 2016/12/30 14:55:48 Done.
1274 // Look past a library prefix. 1390 if (identical(peek.kind, PERIOD_TOKEN)) {
1275 peek = peek.next.next; 1391 if (peek.next.isIdentifier()) {
1392 // Look past a library prefix.
1393 peek = peek.next.next;
1394 }
1395 }
1396 // We are looking at "qualified ...".
1397 if (identical(peek.kind, LT_TOKEN)) {
1398 // Possibly generic type.
1399 // We are looking at "qualified '<'".
1400 BeginGroupToken beginGroupToken = peek;
1401 Token gtToken = beginGroupToken.endGroup;
1402 if (gtToken != null) {
1403 // We are looking at "qualified '<' ... '>' ...".
1404 peek = gtToken.next;
1405 }
1276 } 1406 }
1277 } 1407 }
1278 // We are looking at "qualified ...". 1408
1279 if (identical(peek.kind, LT_TOKEN)) { 1409 // We might have just skipped over the return value of the function type.
1280 // Possibly generic type. 1410 // Check again, if we are now at a function type position.
1281 // We are looking at "qualified '<'". 1411 if (isGeneralizedFunctionType(peek)) {
Siggi Cherem (dart-lang) 2016/12/29 22:46:58 do we need a loop here, like you had in parseType?
floitsch 2016/12/30 14:55:48 I'm not sure the loop is necessary, but I don't wa
1282 BeginGroupToken beginGroupToken = peek; 1412 peek = peek.next; // Skip over the Function.
Siggi Cherem (dart-lang) 2016/12/29 22:46:57 nit: reword "the Function" to "the `Function` toke
floitsch 2016/12/30 14:55:47 Done.
1283 Token gtToken = beginGroupToken.endGroup; 1413 if (identical(peek.kind, LT_TOKEN)) {
Siggi Cherem (dart-lang) 2016/12/29 22:46:58 consider adding here and below comments describing
floitsch 2016/12/30 14:55:48 Done.
1284 if (gtToken != null) { 1414 BeginGroupToken beginGroupToken = peek;
1285 // We are looking at "qualified '<' ... '>' ...". 1415 Token closeToken = beginGroupToken.endGroup;
1286 return gtToken.next; 1416 if (closeToken != null) {
1417 peek = closeToken.next;
1418 }
1419 }
1420
1421 // There must be an open paren to be valid, but we are not checking here.
1422 if (identical(peek.kind, OPEN_PAREN_TOKEN)) {
1423 BeginGroupToken beginGroupToken = peek;
1424 Token closeToken = beginGroupToken.endGroup;
1425 if (closeToken != null) {
1426 peek = closeToken.next;
1427 }
1287 } 1428 }
1288 } 1429 }
1289 return peek; 1430 return peek;
1290 } 1431 }
1291 1432
1292 /** 1433 /**
1293 * If [token] is the start of a type, returns the token after that type. 1434 * If [token] is the start of a type, returns the token after that type.
1294 * If [token] is not the start of a type, null is returned. 1435 * If [token] is not the start of a type, null is returned.
1295 */ 1436 */
1296 Token peekAfterIfType(Token token) { 1437 Token peekAfterIfType(Token token) {
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after
1821 1962
1822 Token parseExpressionStatementOrDeclaration(Token token) { 1963 Token parseExpressionStatementOrDeclaration(Token token) {
1823 assert(token.isIdentifier() || identical(token.stringValue, 'void')); 1964 assert(token.isIdentifier() || identical(token.stringValue, 'void'));
1824 Token identifier = peekIdentifierAfterType(token); 1965 Token identifier = peekIdentifierAfterType(token);
1825 if (identifier != null) { 1966 if (identifier != null) {
1826 assert(identifier.isIdentifier()); 1967 assert(identifier.isIdentifier());
1827 Token afterId = identifier.next; 1968 Token afterId = identifier.next;
1828 int afterIdKind = afterId.kind; 1969 int afterIdKind = afterId.kind;
1829 if (identical(afterIdKind, EQ_TOKEN) || 1970 if (identical(afterIdKind, EQ_TOKEN) ||
1830 identical(afterIdKind, SEMICOLON_TOKEN) || 1971 identical(afterIdKind, SEMICOLON_TOKEN) ||
1831 identical(afterIdKind, COMMA_TOKEN)) { 1972 identical(afterIdKind, COMMA_TOKEN) ||
1973 isGeneralizedFunctionType(identifier)) {
Siggi Cherem (dart-lang) 2016/12/29 22:46:58 why do we need this case? could this be handled by
floitsch 2016/12/30 14:55:48 Yes. thanks for figuring this out. I should have p
1832 // We are looking at "type identifier" followed by '=', ';', ','. 1974 // We are looking at "type identifier" followed by '=', ';', ','.
1833 return parseVariablesDeclaration(token); 1975 return parseVariablesDeclaration(token);
1834 } else if (identical(afterIdKind, OPEN_PAREN_TOKEN)) { 1976 } else if (identical(afterIdKind, OPEN_PAREN_TOKEN)) {
1835 // We are looking at "type identifier '('". 1977 // We are looking at "type identifier '('".
1836 BeginGroupToken beginParen = afterId; 1978 BeginGroupToken beginParen = afterId;
1837 Token endParen = beginParen.endGroup; 1979 Token endParen = beginParen.endGroup;
1838 // TODO(eernst): Check for NPE as described in issue 26252. 1980 // TODO(eernst): Check for NPE as described in issue 26252.
1839 Token afterParens = endParen.next; 1981 Token afterParens = endParen.next;
1840 if (optional('{', afterParens) || 1982 if (optional('{', afterParens) ||
1841 optional('=>', afterParens) || 1983 optional('=>', afterParens) ||
(...skipping 1127 matching lines...) Expand 10 before | Expand all | Expand 10 after
2969 } 3111 }
2970 listener.handleContinueStatement(hasTarget, continueKeyword, token); 3112 listener.handleContinueStatement(hasTarget, continueKeyword, token);
2971 return expectSemicolon(token); 3113 return expectSemicolon(token);
2972 } 3114 }
2973 3115
2974 Token parseEmptyStatement(Token token) { 3116 Token parseEmptyStatement(Token token) {
2975 listener.handleEmptyStatement(token); 3117 listener.handleEmptyStatement(token);
2976 return expectSemicolon(token); 3118 return expectSemicolon(token);
2977 } 3119 }
2978 } 3120 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698