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

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

Issue 2567133002: Add support for the new function-type syntax. (Closed)
Patch Set: Add new test and remove generated tests for this CL. Created 3 years, 10 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 '../scanner.dart' show 7 import '../scanner.dart' show
8 ErrorToken; 8 ErrorToken;
9 9
10 import '../scanner/recover.dart' show 10 import '../scanner/recover.dart' show
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 /** 93 /**
94 * An event generating parser of Dart programs. This parser expects 94 * An event generating parser of Dart programs. This parser expects
95 * all tokens in a linked list (aka a token stream). 95 * all tokens in a linked list (aka a token stream).
96 * 96 *
97 * The class [Scanner] is used to generate a token stream. See the 97 * The class [Scanner] is used to generate a token stream. See the
98 * file scanner.dart. 98 * file scanner.dart.
99 * 99 *
100 * Subclasses of the class [Listener] are used to listen to events. 100 * Subclasses of the class [Listener] are used to listen to events.
101 * 101 *
102 * Most methods of this class belong in one of two major categories: 102 * Most methods of this class belong in one of two major categories:
103 * parse metods and peek methods. Parse methods all have the prefix 103 * parse methods and peek methods. Parse methods all have the prefix
104 * parse, and peek methods all have the prefix peek. 104 * parse, and peek methods all have the prefix peek.
105 * 105 *
106 * Parse methods generate events (by calling methods on [listener]) 106 * Parse methods generate events (by calling methods on [listener])
107 * and return the next token to parse. Peek methods do not generate 107 * and return the next token to parse. Peek methods do not generate
108 * events (except for errors) and may return null. 108 * events (except for errors) and may return null.
109 * 109 *
110 * Parse methods are generally named parseGrammarProductionSuffix. The 110 * Parse methods are generally named parseGrammarProductionSuffix. The
111 * suffix can be one of "opt", or "star". "opt" means zero or one 111 * suffix can be one of "opt", or "star". "opt" means zero or one
112 * matches, "star" means zero or more matches. For example, 112 * matches, "star" means zero or more matches. For example,
113 * [parseMetadataStar] corresponds to this grammar snippet: [: 113 * [parseMetadataStar] corresponds to this grammar snippet: [:
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 period = token; 377 period = token;
378 token = parseIdentifier(token.next); 378 token = parseIdentifier(token.next);
379 } 379 }
380 token = parseArgumentsOpt(token); 380 token = parseArgumentsOpt(token);
381 listener.endMetadata(atToken, period, token); 381 listener.endMetadata(atToken, period, token);
382 return token; 382 return token;
383 } 383 }
384 384
385 Token parseTypedef(Token token) { 385 Token parseTypedef(Token token) {
386 Token typedefKeyword = token; 386 Token typedefKeyword = token;
387 listener.beginFunctionTypeAlias(token); 387 listener.beginTypedef(token);
388 token = parseReturnTypeOpt(token.next); 388 Token equals;
389 token = parseIdentifier(token); 389 if (optional('=', peekAfterNominalType(token.next))) {
390 token = parseTypeVariablesOpt(token); 390 token = parseIdentifier(token.next);
391 token = parseFormalParameters(token); 391 token = parseTypeVariablesOpt(token);
392 listener.endFunctionTypeAlias(typedefKeyword, token); 392 equals = token;
393 token = expect('=', token);
394 token = parseType(token);
395 } else {
396 token = parseReturnTypeOpt(token.next);
397 token = parseIdentifier(token);
398 token = parseTypeVariablesOpt(token);
399 token = parseFormalParameters(token);
400 }
401 listener.endTypedef(typedefKeyword, equals, token);
393 return expect(';', token); 402 return expect(';', token);
394 } 403 }
395 404
396 Token parseMixinApplication(Token token) { 405 Token parseMixinApplication(Token token) {
397 listener.beginMixinApplication(token); 406 listener.beginMixinApplication(token);
398 token = parseType(token); 407 token = parseType(token);
399 token = expect('with', token); 408 token = expect('with', token);
400 token = parseTypeList(token); 409 token = parseTypeList(token);
401 listener.endMixinApplication(); 410 listener.endMixinApplication();
402 return token; 411 return token;
(...skipping 27 matching lines...) Expand all
430 } 439 }
431 return reportUnrecoverableError( 440 return reportUnrecoverableError(
432 token, ErrorKind.ExpectedButGot, {"expected": "("}); 441 token, ErrorKind.ExpectedButGot, {"expected": "("});
433 } 442 }
434 BeginGroupToken beginGroupToken = token; 443 BeginGroupToken beginGroupToken = token;
435 Token endToken = beginGroupToken.endGroup; 444 Token endToken = beginGroupToken.endGroup;
436 listener.endFormalParameters(0, token, endToken); 445 listener.endFormalParameters(0, token, endToken);
437 return endToken.next; 446 return endToken.next;
438 } 447 }
439 448
440 Token parseFormalParameters(Token token) { 449 /// Parses the formal parameter list of a function.
450 ///
451 /// If [inFunctionType] is true, then the names may be omitted (except for
452 /// named arguments). If it is false, then the types may be omitted.
453 Token parseFormalParameters(Token token, {bool inFunctionType: false}) {
441 Token begin = token; 454 Token begin = token;
442 listener.beginFormalParameters(begin); 455 listener.beginFormalParameters(begin);
443 expect('(', token); 456 expect('(', token);
444 int parameterCount = 0; 457 int parameterCount = 0;
445 do { 458 do {
446 token = token.next; 459 token = token.next;
447 if (optional(')', token)) { 460 if (optional(')', token)) {
448 break; 461 break;
449 } 462 }
450 ++parameterCount; 463 ++parameterCount;
451 String value = token.stringValue; 464 String value = token.stringValue;
452 if (identical(value, '[')) { 465 if (identical(value, '[')) {
453 token = parseOptionalFormalParameters(token, false); 466 token = parseOptionalFormalParameters(
467 token, false, inFunctionType: inFunctionType);
454 break; 468 break;
455 } else if (identical(value, '{')) { 469 } else if (identical(value, '{')) {
456 token = parseOptionalFormalParameters(token, true); 470 token = parseOptionalFormalParameters(
471 token, true, inFunctionType: inFunctionType);
457 break; 472 break;
458 } 473 }
459 token = parseFormalParameter(token, FormalParameterType.REQUIRED); 474 token = parseFormalParameter(token, FormalParameterType.REQUIRED,
475 inFunctionType: inFunctionType);
460 } while (optional(',', token)); 476 } while (optional(',', token));
461 listener.endFormalParameters(parameterCount, begin, token); 477 listener.endFormalParameters(parameterCount, begin, token);
462 return expect(')', token); 478 return expect(')', token);
463 } 479 }
464 480
465 Token parseFormalParameter(Token token, FormalParameterType type) { 481 Token parseFormalParameter(Token token, FormalParameterType type,
482 {bool inFunctionType}) {
466 token = parseMetadataStar(token, forParameter: true); 483 token = parseMetadataStar(token, forParameter: true);
467 listener.beginFormalParameter(token); 484 listener.beginFormalParameter(token);
468 485
469 // Skip over `covariant` token, if the next token is an identifier or 486 // Skip over `covariant` token, if the next token is an identifier or
470 // modifier. 487 // modifier.
471 // This enables the case where `covariant` is the name of the parameter: 488 // This enables the case where `covariant` is the name of the parameter:
472 // void foo(covariant); 489 // void foo(covariant);
473 if (identical(token.stringValue, 'covariant') && 490 if (identical(token.stringValue, 'covariant') &&
474 (token.next.isIdentifier() || isModifier(token.next))) { 491 (token.next.isIdentifier() || isModifier(token.next))) {
475 token = token.next; 492 token = token.next;
476 } 493 }
477 token = parseModifiers(token); 494 token = parseModifiers(token);
478 // TODO(ahe): Validate that there are formal parameters if void. 495 bool isNamedParameter = type == FormalParameterType.NAMED;
479 token = parseReturnTypeOpt(token); 496
480 Token thisKeyword = null; 497 Token thisKeyword = null;
481 if (optional('this', token)) { 498 if (inFunctionType && isNamedParameter) {
482 thisKeyword = token; 499 token = parseType(token);
483 // TODO(ahe): Validate field initializers are only used in 500 token = parseIdentifier(token);
484 // constructors, and not for function-typed arguments. 501 } else if (inFunctionType) {
485 token = expect('.', token.next); 502 token = parseType(token);
503 if (token.isIdentifier()) {
504 token = parseIdentifier(token);
505 } else {
506 listener.handleNoName(token);
507 }
508 } else {
509 token = parseReturnTypeOpt(token);
510 if (optional('this', token)) {
511 thisKeyword = token;
512 token = expect('.', token.next);
513 }
514 token = parseIdentifier(token);
486 } 515 }
487 token = parseIdentifier(token); 516
517 // Generalized function types don't allow inline function types.
518 // The following isn't allowed:
519 // int Function(int bar(String x)).
488 if (optional('(', token)) { 520 if (optional('(', token)) {
521 Token inlineFunctionTypeStart = token;
489 listener.beginFunctionTypedFormalParameter(token); 522 listener.beginFunctionTypedFormalParameter(token);
490 listener.handleNoTypeVariables(token); 523 listener.handleNoTypeVariables(token);
491 token = parseFormalParameters(token); 524 token = parseFormalParameters(token);
492 listener.endFunctionTypedFormalParameter(token); 525 listener.endFunctionTypedFormalParameter(token);
526 if (inFunctionType) {
527 reportRecoverableError(
528 inlineFunctionTypeStart, ErrorKind.InvalidInlineFunctionType);
529 }
493 } else if (optional('<', token)) { 530 } else if (optional('<', token)) {
531 Token inlineFunctionTypeStart = token;
494 listener.beginFunctionTypedFormalParameter(token); 532 listener.beginFunctionTypedFormalParameter(token);
495 token = parseTypeVariablesOpt(token); 533 token = parseTypeVariablesOpt(token);
496 token = parseFormalParameters(token); 534 token = parseFormalParameters(token);
497 listener.endFunctionTypedFormalParameter(token); 535 listener.endFunctionTypedFormalParameter(token);
536 if (inFunctionType) {
537 reportRecoverableError(
538 inlineFunctionTypeStart, ErrorKind.InvalidInlineFunctionType);
539 }
498 } 540 }
499 String value = token.stringValue; 541 String value = token.stringValue;
500 if ((identical('=', value)) || (identical(':', value))) { 542 if ((identical('=', value)) || (identical(':', value))) {
501 // TODO(ahe): Validate that these are only used for optional parameters. 543 // TODO(ahe): Validate that these are only used for optional parameters.
502 Token equal = token; 544 Token equal = token;
503 token = parseExpression(token.next); 545 token = parseExpression(token.next);
504 listener.handleValuedFormalParameter(equal, token); 546 listener.handleValuedFormalParameter(equal, token);
505 if (type.isRequired) { 547 if (type.isRequired) {
506 reportRecoverableError( 548 reportRecoverableError(
507 equal, ErrorKind.RequiredParameterWithDefault); 549 equal, ErrorKind.RequiredParameterWithDefault);
508 } else if (type.isPositional && identical(':', value)) { 550 } else if (type.isPositional && identical(':', value)) {
509 reportRecoverableError( 551 reportRecoverableError(
510 equal, ErrorKind.PositionalParameterWithEquals); 552 equal, ErrorKind.PositionalParameterWithEquals);
511 } 553 }
512 } 554 }
513 listener.endFormalParameter(thisKeyword); 555 listener.endFormalParameter(thisKeyword);
514 return token; 556 return token;
515 } 557 }
516 558
517 Token parseOptionalFormalParameters(Token token, bool isNamed) { 559 Token parseOptionalFormalParameters(Token token, bool isNamed,
560 {bool inFunctionType}) {
518 Token begin = token; 561 Token begin = token;
519 listener.beginOptionalFormalParameters(begin); 562 listener.beginOptionalFormalParameters(begin);
520 assert((isNamed && optional('{', token)) || optional('[', token)); 563 assert((isNamed && optional('{', token)) || optional('[', token));
521 int parameterCount = 0; 564 int parameterCount = 0;
522 do { 565 do {
523 token = token.next; 566 token = token.next;
524 if (isNamed && optional('}', token)) { 567 if (isNamed && optional('}', token)) {
525 break; 568 break;
526 } else if (!isNamed && optional(']', token)) { 569 } else if (!isNamed && optional(']', token)) {
527 break; 570 break;
528 } 571 }
529 var type = 572 var type =
530 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; 573 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL;
531 token = parseFormalParameter(token, type); 574 token =
575 parseFormalParameter(token, type, inFunctionType: inFunctionType);
532 ++parameterCount; 576 ++parameterCount;
533 } while (optional(',', token)); 577 } while (optional(',', token));
534 if (parameterCount == 0) { 578 if (parameterCount == 0) {
535 reportRecoverableError( 579 reportRecoverableError(
536 token, 580 token,
537 isNamed 581 isNamed
538 ? ErrorKind.EmptyNamedParameterList 582 ? ErrorKind.EmptyNamedParameterList
539 : ErrorKind.EmptyOptionalParameterList); 583 : ErrorKind.EmptyOptionalParameterList);
540 } 584 }
541 listener.endOptionalFormalParameters(parameterCount, begin, token); 585 listener.endOptionalFormalParameters(parameterCount, begin, token);
542 if (isNamed) { 586 if (isNamed) {
543 return expect('}', token); 587 return expect('}', token);
544 } else { 588 } else {
545 return expect(']', token); 589 return expect(']', token);
546 } 590 }
547 } 591 }
548 592
549 Token parseTypeOpt(Token token) { 593 Token parseTypeOpt(Token token) {
594 if (isGeneralizedFunctionType(token)) {
595 // Function type without return type.
596 return parseType(token);
597 }
550 Token peek = peekAfterIfType(token); 598 Token peek = peekAfterIfType(token);
551 if (peek != null && (peek.isIdentifier() || optional('this', peek))) { 599 if (peek != null && (peek.isIdentifier() || optional('this', peek))) {
552 return parseType(token); 600 return parseType(token);
553 } 601 }
554 listener.handleNoType(token); 602 listener.handleNoType(token);
555 return token; 603 return token;
556 } 604 }
557 605
558 bool isValidTypeReference(Token token) { 606 bool isValidTypeReference(Token token) {
559 final kind = token.kind; 607 final kind = token.kind;
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 } 754 }
707 755
708 Token parseClassOrNamedMixinApplication(Token token) { 756 Token parseClassOrNamedMixinApplication(Token token) {
709 Token begin = token; 757 Token begin = token;
710 Token abstractKeyword; 758 Token abstractKeyword;
711 if (optional('abstract', token)) { 759 if (optional('abstract', token)) {
712 abstractKeyword = token; 760 abstractKeyword = token;
713 token = token.next; 761 token = token.next;
714 } 762 }
715 Token classKeyword = token; 763 Token classKeyword = token;
716 var isMixinApplication = optional('=', peekAfterType(token.next)); 764 var isMixinApplication = optional('=', peekAfterNominalType(token.next));
717 if (isMixinApplication) { 765 if (isMixinApplication) {
718 listener.beginNamedMixinApplication(begin); 766 listener.beginNamedMixinApplication(begin);
719 } else { 767 } else {
720 listener.beginClassDeclaration(begin); 768 listener.beginClassDeclaration(begin);
721 } 769 }
722 770
723 int modifierCount = 0; 771 int modifierCount = 0;
724 if (abstractKeyword != null) { 772 if (abstractKeyword != null) {
725 parseModifier(abstractKeyword); 773 parseModifier(abstractKeyword);
726 modifierCount++; 774 modifierCount++;
(...skipping 20 matching lines...) Expand all
747 listener.endNamedMixinApplication(classKeyword, implementsKeyword, token); 795 listener.endNamedMixinApplication(classKeyword, implementsKeyword, token);
748 return expect(';', token); 796 return expect(';', token);
749 } 797 }
750 798
751 Token parseClass(Token begin, Token classKeyword) { 799 Token parseClass(Token begin, Token classKeyword) {
752 Token token = parseIdentifier(classKeyword.next); 800 Token token = parseIdentifier(classKeyword.next);
753 token = parseTypeVariablesOpt(token); 801 token = parseTypeVariablesOpt(token);
754 Token extendsKeyword; 802 Token extendsKeyword;
755 if (optional('extends', token)) { 803 if (optional('extends', token)) {
756 extendsKeyword = token; 804 extendsKeyword = token;
757 if (optional('with', peekAfterType(token.next))) { 805 if (optional('with', peekAfterNominalType(token.next))) {
758 token = parseMixinApplication(token.next); 806 token = parseMixinApplication(token.next);
759 } else { 807 } else {
760 token = parseType(token.next); 808 token = parseType(token.next);
761 } 809 }
762 } else { 810 } else {
763 extendsKeyword = null; 811 extendsKeyword = null;
764 listener.handleNoType(token); 812 listener.handleNoType(token);
765 } 813 }
766 Token implementsKeyword; 814 Token implementsKeyword;
767 int interfacesCount = 0; 815 int interfacesCount = 0;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 value2 == stringValue || 886 value2 == stringValue ||
839 value3 == stringValue || 887 value3 == stringValue ||
840 value4 == stringValue; 888 value4 == stringValue;
841 } 889 }
842 890
843 bool notEofOrValue(String value, Token token) { 891 bool notEofOrValue(String value, Token token) {
844 return !identical(token.kind, EOF_TOKEN) && 892 return !identical(token.kind, EOF_TOKEN) &&
845 !identical(value, token.stringValue); 893 !identical(value, token.stringValue);
846 } 894 }
847 895
896 bool isGeneralizedFunctionType(Token token) {
897 return optional('Function', token) &&
898 (optional('<', token.next) || optional('(', token.next));
899 }
900
848 Token parseType(Token token) { 901 Token parseType(Token token) {
849 Token begin = token; 902 Token begin = token;
850 if (isValidTypeReference(token)) { 903 if (isGeneralizedFunctionType(token)) {
851 token = parseIdentifier(token); 904 // A function type without return type.
852 token = parseQualifiedRestOpt(token); 905 // Push the non-existing return type first. The loop below will
906 // generate the full type.
907 listener.handleNoType(token);
853 } else { 908 } else {
854 token = reportUnrecoverableError(token, ErrorKind.ExpectedType); 909 if (isValidTypeReference(token)) {
855 listener.handleInvalidTypeReference(token); 910 token = parseIdentifier(token);
911 token = parseQualifiedRestOpt(token);
912 } else {
913 token = reportUnrecoverableError(token, ErrorKind.ExpectedType);
914 listener.handleInvalidTypeReference(token);
915 }
916 token = parseTypeArgumentsOpt(token);
917 listener.endType(begin, token);
856 } 918 }
857 token = parseTypeArgumentsOpt(token); 919
858 listener.endType(begin, token); 920 // While we see a `Function(` treat the pushed type as return type.
921 // For example: `int Function() Function(int) Function(String x)`.
922 while (isGeneralizedFunctionType(token)) {
923 token = parseFunctionType(token);
924 }
859 return token; 925 return token;
860 } 926 }
861 927
928 /// Parses a generalized function type.
929 ///
930 /// The return type must already be pushed.
931 Token parseFunctionType(Token token) {
932 assert(optional('Function', token));
933 Token functionToken = token;
934 token = token.next;
935 token = parseTypeVariablesOpt(token);
936 token = parseFormalParameters(token, inFunctionType: true);
937 listener.endFunctionType(functionToken, token);
938 return token;
939 }
940
862 Token parseTypeArgumentsOpt(Token token) { 941 Token parseTypeArgumentsOpt(Token token) {
863 return parseStuff( 942 return parseStuff(
864 token, 943 token,
865 (t) => listener.beginTypeArguments(t), 944 (t) => listener.beginTypeArguments(t),
866 (t) => parseType(t), 945 (t) => parseType(t),
867 (c, bt, et) => listener.endTypeArguments(c, bt, et), 946 (c, bt, et) => listener.endTypeArguments(c, bt, et),
868 (t) => listener.handleNoTypeArguments(t)); 947 (t) => listener.handleNoTypeArguments(t));
869 } 948 }
870 949
871 Token parseTypeVariablesOpt(Token token) { 950 Token parseTypeVariablesOpt(Token token) {
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
1203 return listener.handleMemberName(identifiers); 1282 return listener.handleMemberName(identifiers);
1204 } else if (optional("=", token) || optional(";", token) || 1283 } else if (optional("=", token) || optional(";", token) ||
1205 optional(",", token)) { 1284 optional(",", token)) {
1206 // A field or abstract getter. 1285 // A field or abstract getter.
1207 identifiers = identifiers.prepend(token); 1286 identifiers = identifiers.prepend(token);
1208 return listener.handleMemberName(identifiers); 1287 return listener.handleMemberName(identifiers);
1209 } else if (isGetter) { 1288 } else if (isGetter) {
1210 hasName = true; 1289 hasName = true;
1211 } 1290 }
1212 identifiers = identifiers.prepend(token); 1291 identifiers = identifiers.prepend(token);
1213 if (isValidTypeReference(token)) { 1292
1214 // type ... 1293 if (!isGeneralizedFunctionType(token)) {
1215 if (optional('.', token.next)) { 1294 // Read a potential return type.
1216 // type '.' ... 1295 if (isValidTypeReference(token)) {
1217 if (token.next.next.isIdentifier()) { 1296 // type ...
1218 // type '.' identifier 1297 if (optional('.', token.next)) {
1219 token = token.next.next; 1298 // type '.' ...
1299 if (token.next.next.isIdentifier()) {
1300 // type '.' identifier
1301 token = token.next.next;
1302 }
1303 }
1304 if (optional('<', token.next)) {
1305 if (token.next is BeginGroupToken) {
1306 BeginGroupToken beginGroup = token.next;
1307 if (beginGroup.endGroup == null) {
1308 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken);
1309 } else {
1310 token = beginGroup.endGroup;
1311 }
1312 }
1220 } 1313 }
1221 } 1314 }
1222 if (optional('<', token.next)) { 1315 token = token.next;
1223 if (token.next is BeginGroupToken) { 1316 }
1224 BeginGroupToken beginGroup = token.next; 1317 while (isGeneralizedFunctionType(token)) {
1318 token = token.next;
1319 if (optional('<', token)) {
1320 if (token is BeginGroupToken) {
1321 BeginGroupToken beginGroup = token;
1225 if (beginGroup.endGroup == null) { 1322 if (beginGroup.endGroup == null) {
1226 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken); 1323 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken);
1227 } else { 1324 } else {
1228 token = beginGroup.endGroup; 1325 token = beginGroup.endGroup.next;
1229 } 1326 }
1230 } 1327 }
1231 } 1328 }
1329 if (!optional('(', token)) {
1330 if (optional(';', token)) {
1331 reportRecoverableError(token, ErrorKind.ExpectedOpenParens);
1332 }
1333 token = expect("(", token);
1334 }
1335 if (token is BeginGroupToken) {
1336 BeginGroupToken beginGroup = token;
1337 if (beginGroup.endGroup == null) {
1338 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken);
1339 } else {
1340 token = beginGroup.endGroup.next;
1341 }
1342 }
1232 } 1343 }
1233 token = token.next;
1234 } 1344 }
1235 return listener.handleMemberName(const Link<Token>()); 1345 return listener.handleMemberName(const Link<Token>());
1236 } 1346 }
1237 1347
1238 Token parseFieldInitializerOpt(Token token) { 1348 Token parseFieldInitializerOpt(Token token) {
1239 if (optional('=', token)) { 1349 if (optional('=', token)) {
1240 Token assignment = token; 1350 Token assignment = token;
1241 listener.beginFieldInitializer(token); 1351 listener.beginFieldInitializer(token);
1242 token = parseExpression(token.next); 1352 token = parseExpression(token.next);
1243 listener.endFieldInitializer(assignment); 1353 listener.endFieldInitializer(assignment);
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
1336 if (!isModifier(token)) break; 1446 if (!isModifier(token)) break;
1337 token = parseModifier(token); 1447 token = parseModifier(token);
1338 count++; 1448 count++;
1339 } 1449 }
1340 listener.handleModifiers(count); 1450 listener.handleModifiers(count);
1341 return token; 1451 return token;
1342 } 1452 }
1343 1453
1344 /** 1454 /**
1345 * Returns the first token after the type starting at [token]. 1455 * Returns the first token after the type starting at [token].
1456 *
1346 * This method assumes that [token] is an identifier (or void). 1457 * This method assumes that [token] is an identifier (or void).
1347 * Use [peekAfterIfType] if [token] isn't known to be an identifier. 1458 * Use [peekAfterIfType] if [token] isn't known to be an identifier.
1348 */ 1459 */
1349 Token peekAfterType(Token token) { 1460 Token peekAfterType(Token token) {
1350 // We are looking at "identifier ...". 1461 // We are looking at "identifier ...".
1462 Token peek = token;
1463 if (!isGeneralizedFunctionType(token)) {
1464 peek = peekAfterNominalType(token);
1465 }
1466
1467 // We might have just skipped over the return value of the function type.
1468 // Check again, if we are now at a function type position.
1469 while (isGeneralizedFunctionType(peek)) {
1470 peek = peekAfterFunctionType(peek);
1471 }
1472 return peek;
1473 }
1474
1475 /**
1476 * Returns the first token after the nominal type starting at [token].
1477 *
1478 * This method assumes that [token] is an identifier (or void).
1479 */
1480 Token peekAfterNominalType(Token token) {
1351 Token peek = token.next; 1481 Token peek = token.next;
1352 if (identical(peek.kind, PERIOD_TOKEN)) { 1482 if (identical(peek.kind, PERIOD_TOKEN)) {
1353 if (peek.next.isIdentifier()) { 1483 if (peek.next.isIdentifier()) {
1354 // Look past a library prefix. 1484 // Look past a library prefix.
1355 peek = peek.next.next; 1485 peek = peek.next.next;
1356 } 1486 }
1357 } 1487 }
1358 // We are looking at "qualified ...". 1488 // We are looking at "qualified ...".
1359 if (identical(peek.kind, LT_TOKEN)) { 1489 if (identical(peek.kind, LT_TOKEN)) {
1360 // Possibly generic type. 1490 // Possibly generic type.
1361 // We are looking at "qualified '<'". 1491 // We are looking at "qualified '<'".
1362 BeginGroupToken beginGroupToken = peek; 1492 BeginGroupToken beginGroupToken = peek;
1363 Token gtToken = beginGroupToken.endGroup; 1493 Token gtToken = beginGroupToken.endGroup;
1364 if (gtToken != null) { 1494 if (gtToken != null) {
1365 // We are looking at "qualified '<' ... '>' ...". 1495 // We are looking at "qualified '<' ... '>' ...".
1366 return gtToken.next; 1496 peek = gtToken.next;
1367 } 1497 }
1368 } 1498 }
1369 return peek; 1499 return peek;
1370 } 1500 }
1371 1501
1372 /** 1502 /**
1503 * Returns the first token after the function type starting at [token].
1504 *
1505 * The token must be at the `Function` token position. That is, the return
1506 * type must have already been skipped.
1507 *
1508 * This function only skips over one function type syntax.
1509 * If necessary, this function must be called multiple times.
1510 *
1511 * Example:
1512 * ```
1513 * int Function() Function<T>(int)
1514 * ^ ^
1515 * A call to this function must be at one of the `Function` tokens.
1516 * If `token` pointed to the first `Function` token, then the returned
1517 * token points to the second `Function` token.
1518 */
1519 Token peekAfterFunctionType(Token token) {
1520 // Possible inputs are:
1521 // Function( ... )
1522 // Function< ... >( ... )
1523
1524 Token peek = token.next; // Skip over the Function token.
1525 // If there is a generic argument to the function, skip over that one first.
1526 if (identical(peek.kind, LT_TOKEN)) {
1527 BeginGroupToken beginGroupToken = peek;
1528 Token closeToken = beginGroupToken.endGroup;
1529 if (closeToken != null) {
1530 peek = closeToken.next;
1531 }
1532 }
1533
1534 // Now we just need to skip over the formals.
1535 expect('(', peek);
1536
1537 BeginGroupToken beginGroupToken = peek;
1538 Token closeToken = beginGroupToken.endGroup;
1539 if (closeToken != null) {
1540 peek = closeToken.next;
1541 }
1542
1543 return peek;
1544 }
1545
1546 /**
1373 * If [token] is the start of a type, returns the token after that type. 1547 * If [token] is the start of a type, returns the token after that type.
1374 * If [token] is not the start of a type, null is returned. 1548 * If [token] is not the start of a type, null is returned.
1375 */ 1549 */
1376 Token peekAfterIfType(Token token) { 1550 Token peekAfterIfType(Token token) {
1377 if (!optional('void', token) && !token.isIdentifier()) { 1551 if (!optional('void', token) && !token.isIdentifier()) {
1378 return null; 1552 return null;
1379 } 1553 }
1380 return peekAfterType(token); 1554 return peekAfterType(token);
1381 } 1555 }
1382 1556
(...skipping 1929 matching lines...) Expand 10 before | Expand all | Expand 10 after
3312 break; 3486 break;
3313 } 3487 }
3314 if (isRecoverable) { 3488 if (isRecoverable) {
3315 listener.handleRecoverableError(token, kind, arguments); 3489 listener.handleRecoverableError(token, kind, arguments);
3316 return null; 3490 return null;
3317 } else { 3491 } else {
3318 return listener.handleUnrecoverableError(token, kind, arguments); 3492 return listener.handleUnrecoverableError(token, kind, arguments);
3319 } 3493 }
3320 } 3494 }
3321 } 3495 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698