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

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: Adjust fasta-analyzer. 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 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
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.beginFunctionTypeAlias(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.endFunctionTypeAlias(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;
403 } 412 }
404 413
405 Token parseReturnTypeOpt(Token token) { 414 Token parseReturnTypeOpt(Token token) {
406 if (identical(token.stringValue, 'void')) { 415 if (identical(token.stringValue, 'void')) {
407 listener.handleVoidKeyword(token); 416 if (isGeneralizedFunctionType(token.next)) {
408 return token.next; 417 return parseType(token);
418 } else {
419 listener.handleVoidKeyword(token);
420 return token.next;
421 }
409 } else { 422 } else {
410 return parseTypeOpt(token); 423 return parseTypeOpt(token);
411 } 424 }
412 } 425 }
413 426
414 Token parseFormalParametersOpt(Token token) { 427 Token parseFormalParametersOpt(Token token) {
415 if (optional('(', token)) { 428 if (optional('(', token)) {
416 return parseFormalParameters(token); 429 return parseFormalParameters(token);
417 } else { 430 } else {
418 listener.handleNoFormalParameters(token); 431 listener.handleNoFormalParameters(token);
(...skipping 11 matching lines...) Expand all
430 } 443 }
431 return reportUnrecoverableError( 444 return reportUnrecoverableError(
432 token, ErrorKind.ExpectedButGot, {"expected": "("}); 445 token, ErrorKind.ExpectedButGot, {"expected": "("});
433 } 446 }
434 BeginGroupToken beginGroupToken = token; 447 BeginGroupToken beginGroupToken = token;
435 Token endToken = beginGroupToken.endGroup; 448 Token endToken = beginGroupToken.endGroup;
436 listener.endFormalParameters(0, token, endToken); 449 listener.endFormalParameters(0, token, endToken);
437 return endToken.next; 450 return endToken.next;
438 } 451 }
439 452
440 Token parseFormalParameters(Token token) { 453 /// Parses the formal parameter list of a function.
454 ///
455 /// If [inFunctionType] is true, then the names may be omitted (except for
456 /// named arguments). If it is false, then the types may be omitted.
457 Token parseFormalParameters(Token token, {bool inFunctionType: false}) {
441 Token begin = token; 458 Token begin = token;
442 listener.beginFormalParameters(begin); 459 listener.beginFormalParameters(begin);
443 expect('(', token); 460 expect('(', token);
444 int parameterCount = 0; 461 int parameterCount = 0;
445 do { 462 do {
446 token = token.next; 463 token = token.next;
447 if (optional(')', token)) { 464 if (optional(')', token)) {
448 break; 465 break;
449 } 466 }
450 ++parameterCount; 467 ++parameterCount;
451 String value = token.stringValue; 468 String value = token.stringValue;
452 if (identical(value, '[')) { 469 if (identical(value, '[')) {
453 token = parseOptionalFormalParameters(token, false); 470 token = parseOptionalFormalParameters(
471 token, false, inFunctionType: inFunctionType);
454 break; 472 break;
455 } else if (identical(value, '{')) { 473 } else if (identical(value, '{')) {
456 token = parseOptionalFormalParameters(token, true); 474 token = parseOptionalFormalParameters(
475 token, true, inFunctionType: inFunctionType);
457 break; 476 break;
458 } 477 }
459 token = parseFormalParameter(token, FormalParameterType.REQUIRED); 478 token = parseFormalParameter(token, FormalParameterType.REQUIRED,
479 inFunctionType: inFunctionType);
460 } while (optional(',', token)); 480 } while (optional(',', token));
461 listener.endFormalParameters(parameterCount, begin, token); 481 listener.endFormalParameters(parameterCount, begin, token);
462 return expect(')', token); 482 return expect(')', token);
463 } 483 }
464 484
465 Token parseFormalParameter(Token token, FormalParameterType type) { 485 Token parseFormalParameter(Token token, FormalParameterType type,
486 {bool inFunctionType: false}) {
466 token = parseMetadataStar(token, forParameter: true); 487 token = parseMetadataStar(token, forParameter: true);
467 listener.beginFormalParameter(token); 488 listener.beginFormalParameter(token);
468 489
469 // Skip over `covariant` token, if the next token is an identifier or 490 // Skip over `covariant` token, if the next token is an identifier or
470 // modifier. 491 // modifier.
471 // This enables the case where `covariant` is the name of the parameter: 492 // This enables the case where `covariant` is the name of the parameter:
472 // void foo(covariant); 493 // void foo(covariant);
473 if (identical(token.stringValue, 'covariant') && 494 if (identical(token.stringValue, 'covariant') &&
474 (token.next.isIdentifier() || isModifier(token.next))) { 495 (token.next.isIdentifier() || isModifier(token.next))) {
475 token = token.next; 496 token = token.next;
476 } 497 }
477 token = parseModifiers(token); 498 token = parseModifiers(token);
478 // TODO(ahe): Validate that there are formal parameters if void. 499 bool isNamedParameter = type == FormalParameterType.NAMED;
479 token = parseReturnTypeOpt(token); 500
480 Token thisKeyword = null; 501 Token thisKeyword = null;
481 if (optional('this', token)) { 502 if (inFunctionType && isNamedParameter) {
482 thisKeyword = token; 503 token = parseType(token);
483 // TODO(ahe): Validate field initializers are only used in 504 token = parseIdentifier(token);
484 // constructors, and not for function-typed arguments. 505 } else if (inFunctionType) {
485 token = expect('.', token.next); 506 token = parseType(token);
507 if (token.isIdentifier()) {
508 token = parseIdentifier(token);
509 } else {
510 listener.handleNoName(token);
511 }
512 } else {
513 token = parseReturnTypeOpt(token);
514 if (optional('this', token)) {
515 thisKeyword = token;
516 token = expect('.', token.next);
517 }
518 token = parseIdentifier(token);
486 } 519 }
487 token = parseIdentifier(token); 520
521 // Generalized function types don't allow inline function types.
522 // The following isn't allowed:
523 // int Function(int bar(String x)).
488 if (optional('(', token)) { 524 if (optional('(', token)) {
525 Token inlineFunctionTypeStart = token;
489 listener.beginFunctionTypedFormalParameter(token); 526 listener.beginFunctionTypedFormalParameter(token);
490 listener.handleNoTypeVariables(token); 527 listener.handleNoTypeVariables(token);
491 token = parseFormalParameters(token); 528 token = parseFormalParameters(token);
492 listener.endFunctionTypedFormalParameter(token); 529 listener.endFunctionTypedFormalParameter(token);
530 if (inFunctionType) {
531 reportRecoverableError(
532 inlineFunctionTypeStart, ErrorKind.InvalidInlineFunctionType);
533 }
493 } else if (optional('<', token)) { 534 } else if (optional('<', token)) {
535 Token inlineFunctionTypeStart = token;
494 listener.beginFunctionTypedFormalParameter(token); 536 listener.beginFunctionTypedFormalParameter(token);
495 token = parseTypeVariablesOpt(token); 537 token = parseTypeVariablesOpt(token);
496 token = parseFormalParameters(token); 538 token = parseFormalParameters(token);
497 listener.endFunctionTypedFormalParameter(token); 539 listener.endFunctionTypedFormalParameter(token);
540 if (inFunctionType) {
541 reportRecoverableError(
542 inlineFunctionTypeStart, ErrorKind.InvalidInlineFunctionType);
543 }
498 } 544 }
499 String value = token.stringValue; 545 String value = token.stringValue;
500 if ((identical('=', value)) || (identical(':', value))) { 546 if ((identical('=', value)) || (identical(':', value))) {
501 // TODO(ahe): Validate that these are only used for optional parameters. 547 // TODO(ahe): Validate that these are only used for optional parameters.
502 Token equal = token; 548 Token equal = token;
503 token = parseExpression(token.next); 549 token = parseExpression(token.next);
504 listener.handleValuedFormalParameter(equal, token); 550 listener.handleValuedFormalParameter(equal, token);
505 if (type.isRequired) { 551 if (type.isRequired) {
506 reportRecoverableError( 552 reportRecoverableError(
507 equal, ErrorKind.RequiredParameterWithDefault); 553 equal, ErrorKind.RequiredParameterWithDefault);
508 } else if (type.isPositional && identical(':', value)) { 554 } else if (type.isPositional && identical(':', value)) {
509 reportRecoverableError( 555 reportRecoverableError(
510 equal, ErrorKind.PositionalParameterWithEquals); 556 equal, ErrorKind.PositionalParameterWithEquals);
511 } 557 }
512 } 558 }
513 listener.endFormalParameter(thisKeyword); 559 listener.endFormalParameter(thisKeyword);
514 return token; 560 return token;
515 } 561 }
516 562
517 Token parseOptionalFormalParameters(Token token, bool isNamed) { 563 Token parseOptionalFormalParameters(Token token, bool isNamed,
564 {bool inFunctionType: false}) {
518 Token begin = token; 565 Token begin = token;
519 listener.beginOptionalFormalParameters(begin); 566 listener.beginOptionalFormalParameters(begin);
520 assert((isNamed && optional('{', token)) || optional('[', token)); 567 assert((isNamed && optional('{', token)) || optional('[', token));
521 int parameterCount = 0; 568 int parameterCount = 0;
522 do { 569 do {
523 token = token.next; 570 token = token.next;
524 if (isNamed && optional('}', token)) { 571 if (isNamed && optional('}', token)) {
525 break; 572 break;
526 } else if (!isNamed && optional(']', token)) { 573 } else if (!isNamed && optional(']', token)) {
527 break; 574 break;
528 } 575 }
529 var type = 576 var type =
530 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; 577 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL;
531 token = parseFormalParameter(token, type); 578 token =
579 parseFormalParameter(token, type, inFunctionType: inFunctionType);
532 ++parameterCount; 580 ++parameterCount;
533 } while (optional(',', token)); 581 } while (optional(',', token));
534 if (parameterCount == 0) { 582 if (parameterCount == 0) {
535 reportRecoverableError( 583 reportRecoverableError(
536 token, 584 token,
537 isNamed 585 isNamed
538 ? ErrorKind.EmptyNamedParameterList 586 ? ErrorKind.EmptyNamedParameterList
539 : ErrorKind.EmptyOptionalParameterList); 587 : ErrorKind.EmptyOptionalParameterList);
540 } 588 }
541 listener.endOptionalFormalParameters(parameterCount, begin, token); 589 listener.endOptionalFormalParameters(parameterCount, begin, token);
542 if (isNamed) { 590 if (isNamed) {
543 return expect('}', token); 591 return expect('}', token);
544 } else { 592 } else {
545 return expect(']', token); 593 return expect(']', token);
546 } 594 }
547 } 595 }
548 596
549 Token parseTypeOpt(Token token) { 597 Token parseTypeOpt(Token token) {
598 if (isGeneralizedFunctionType(token)) {
599 // Function type without return type.
600 return parseType(token);
601 }
550 Token peek = peekAfterIfType(token); 602 Token peek = peekAfterIfType(token);
551 if (peek != null && (peek.isIdentifier() || optional('this', peek))) { 603 if (peek != null && (peek.isIdentifier() || optional('this', peek))) {
552 return parseType(token); 604 return parseType(token);
553 } 605 }
554 listener.handleNoType(token); 606 listener.handleNoType(token);
555 return token; 607 return token;
556 } 608 }
557 609
558 bool isValidTypeReference(Token token) { 610 bool isValidTypeReference(Token token) {
559 final kind = token.kind; 611 final kind = token.kind;
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 token = token.next; 766 token = token.next;
715 classKeyword = token; 767 classKeyword = token;
716 } 768 }
717 assert(optional('class', classKeyword)); 769 assert(optional('class', classKeyword));
718 int modifierCount = 0; 770 int modifierCount = 0;
719 if (abstractKeyword != null) { 771 if (abstractKeyword != null) {
720 parseModifier(abstractKeyword); 772 parseModifier(abstractKeyword);
721 modifierCount++; 773 modifierCount++;
722 } 774 }
723 listener.handleModifiers(modifierCount); 775 listener.handleModifiers(modifierCount);
724 bool isMixinApplication = optional('=', peekAfterType(token)); 776 bool isMixinApplication = optional('=', peekAfterNominalType(token));
725 Token name = token.next; 777 Token name = token.next;
726 token = parseIdentifier(name); 778 token = parseIdentifier(name);
727 779
728 if (isMixinApplication) { 780 if (isMixinApplication) {
729 listener.beginNamedMixinApplication(begin, name); 781 listener.beginNamedMixinApplication(begin, name);
730 } else { 782 } else {
731 listener.beginClassDeclaration(begin, name); 783 listener.beginClassDeclaration(begin, name);
732 } 784 }
733 785
734 token = parseTypeVariablesOpt(token); 786 token = parseTypeVariablesOpt(token);
(...skipping 18 matching lines...) Expand all
753 } 805 }
754 listener.endNamedMixinApplication(begin, classKeyword, equals, 806 listener.endNamedMixinApplication(begin, classKeyword, equals,
755 implementsKeyword, token); 807 implementsKeyword, token);
756 return expect(';', token); 808 return expect(';', token);
757 } 809 }
758 810
759 Token parseClass(Token token, Token begin, Token classKeyword, Token name) { 811 Token parseClass(Token token, Token begin, Token classKeyword, Token name) {
760 Token extendsKeyword; 812 Token extendsKeyword;
761 if (optional('extends', token)) { 813 if (optional('extends', token)) {
762 extendsKeyword = token; 814 extendsKeyword = token;
763 if (optional('with', peekAfterType(token.next))) { 815 if (optional('with', peekAfterNominalType(token.next))) {
764 token = parseMixinApplication(token.next); 816 token = parseMixinApplication(token.next);
765 } else { 817 } else {
766 token = parseType(token.next); 818 token = parseType(token.next);
767 } 819 }
768 } else { 820 } else {
769 extendsKeyword = null; 821 extendsKeyword = null;
770 listener.handleNoType(token); 822 listener.handleNoType(token);
771 } 823 }
772 Token implementsKeyword; 824 Token implementsKeyword;
773 int interfacesCount = 0; 825 int interfacesCount = 0;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
845 value2 == stringValue || 897 value2 == stringValue ||
846 value3 == stringValue || 898 value3 == stringValue ||
847 value4 == stringValue; 899 value4 == stringValue;
848 } 900 }
849 901
850 bool notEofOrValue(String value, Token token) { 902 bool notEofOrValue(String value, Token token) {
851 return !identical(token.kind, EOF_TOKEN) && 903 return !identical(token.kind, EOF_TOKEN) &&
852 !identical(value, token.stringValue); 904 !identical(value, token.stringValue);
853 } 905 }
854 906
907 bool isGeneralizedFunctionType(Token token) {
908 return optional('Function', token) &&
909 (optional('<', token.next) || optional('(', token.next));
910 }
911
855 Token parseType(Token token) { 912 Token parseType(Token token) {
856 Token begin = token; 913 Token begin = token;
857 if (isValidTypeReference(token)) { 914 if (isGeneralizedFunctionType(token)) {
858 token = parseIdentifier(token); 915 // A function type without return type.
859 token = parseQualifiedRestOpt(token); 916 // Push the non-existing return type first. The loop below will
917 // generate the full type.
918 listener.handleNoType(token);
919 } else if (identical(token.stringValue, 'void') &&
920 isGeneralizedFunctionType(token.next)) {
921 listener.handleVoidKeyword(token);
922 token = token.next;
860 } else { 923 } else {
861 token = reportUnrecoverableError(token, ErrorKind.ExpectedType); 924 if (isValidTypeReference(token)) {
862 listener.handleInvalidTypeReference(token); 925 token = parseIdentifier(token);
926 token = parseQualifiedRestOpt(token);
927 } else {
928 token = reportUnrecoverableError(token, ErrorKind.ExpectedType);
929 listener.handleInvalidTypeReference(token);
930 }
931 token = parseTypeArgumentsOpt(token);
932 listener.handleType(begin, token);
863 } 933 }
864 token = parseTypeArgumentsOpt(token); 934
865 listener.endType(begin, token); 935 // While we see a `Function(` treat the pushed type as return type.
936 // For example: `int Function() Function(int) Function(String x)`.
937 while (isGeneralizedFunctionType(token)) {
938 token = parseFunctionType(token);
939 }
866 return token; 940 return token;
867 } 941 }
868 942
943 /// Parses a generalized function type.
944 ///
945 /// The return type must already be pushed.
946 Token parseFunctionType(Token token) {
947 assert(optional('Function', token));
948 Token functionToken = token;
949 token = token.next;
950 token = parseTypeVariablesOpt(token);
951 token = parseFormalParameters(token, inFunctionType: true);
952 listener.handleFunctionType(functionToken, token);
953 return token;
954 }
955
869 Token parseTypeArgumentsOpt(Token token) { 956 Token parseTypeArgumentsOpt(Token token) {
870 return parseStuff( 957 return parseStuff(
871 token, 958 token,
872 (t) => listener.beginTypeArguments(t), 959 (t) => listener.beginTypeArguments(t),
873 (t) => parseType(t), 960 (t) => parseType(t),
874 (c, bt, et) => listener.endTypeArguments(c, bt, et), 961 (c, bt, et) => listener.endTypeArguments(c, bt, et),
875 (t) => listener.handleNoTypeArguments(t)); 962 (t) => listener.handleNoTypeArguments(t));
876 } 963 }
877 964
878 Token parseTypeVariablesOpt(Token token) { 965 Token parseTypeVariablesOpt(Token token) {
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
1075 1162
1076 if (getOrSet != null) { 1163 if (getOrSet != null) {
1077 var kind = (hasModifier || hasType) 1164 var kind = (hasModifier || hasType)
1078 ? ErrorKind.ExtraneousModifier 1165 ? ErrorKind.ExtraneousModifier
1079 : ErrorKind.ExtraneousModifierReplace; 1166 : ErrorKind.ExtraneousModifierReplace;
1080 reportRecoverableError(getOrSet, kind, {'modifier': getOrSet}); 1167 reportRecoverableError(getOrSet, kind, {'modifier': getOrSet});
1081 } 1168 }
1082 1169
1083 if (!hasType) { 1170 if (!hasType) {
1084 listener.handleNoType(name); 1171 listener.handleNoType(name);
1085 } else if (optional('void', type)) { 1172 } else if (optional('void', type) &&
1173 !isGeneralizedFunctionType(type.next)) {
1086 listener.handleNoType(name); 1174 listener.handleNoType(name);
1087 // TODO(ahe): This error is reported twice, second time is from 1175 // TODO(ahe): This error is reported twice, second time is from
1088 // [parseVariablesDeclarationMaybeSemicolon] via 1176 // [parseVariablesDeclarationMaybeSemicolon] via
1089 // [PartialFieldListElement.parseNode]. 1177 // [PartialFieldListElement.parseNode].
1090 reportRecoverableError(type, ErrorKind.InvalidVoid); 1178 reportRecoverableError(type, ErrorKind.InvalidVoid);
1091 } else { 1179 } else {
1092 parseType(type); 1180 parseType(type);
1093 if (isVar) { 1181 if (isVar) {
1094 reportRecoverableError(modifiers.head, ErrorKind.ExtraneousModifier, 1182 reportRecoverableError(modifiers.head, ErrorKind.ExtraneousModifier,
1095 {'modifier': modifiers.head}); 1183 {'modifier': modifiers.head});
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
1211 return listener.handleMemberName(identifiers); 1299 return listener.handleMemberName(identifiers);
1212 } else if (optional("=", token) || optional(";", token) || 1300 } else if (optional("=", token) || optional(";", token) ||
1213 optional(",", token)) { 1301 optional(",", token)) {
1214 // A field or abstract getter. 1302 // A field or abstract getter.
1215 identifiers = identifiers.prepend(token); 1303 identifiers = identifiers.prepend(token);
1216 return listener.handleMemberName(identifiers); 1304 return listener.handleMemberName(identifiers);
1217 } else if (isGetter) { 1305 } else if (isGetter) {
1218 hasName = true; 1306 hasName = true;
1219 } 1307 }
1220 identifiers = identifiers.prepend(token); 1308 identifiers = identifiers.prepend(token);
1221 if (isValidTypeReference(token)) { 1309
1222 // type ... 1310 if (!isGeneralizedFunctionType(token)) {
1223 if (optional('.', token.next)) { 1311 // Read a potential return type.
1224 // type '.' ... 1312 if (isValidTypeReference(token)) {
1225 if (token.next.next.isIdentifier()) { 1313 // type ...
1226 // type '.' identifier 1314 if (optional('.', token.next)) {
1227 token = token.next.next; 1315 // type '.' ...
1316 if (token.next.next.isIdentifier()) {
1317 // type '.' identifier
1318 token = token.next.next;
1319 }
1320 }
1321 if (optional('<', token.next)) {
1322 if (token.next is BeginGroupToken) {
1323 BeginGroupToken beginGroup = token.next;
1324 if (beginGroup.endGroup == null) {
1325 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken);
1326 } else {
1327 token = beginGroup.endGroup;
1328 }
1329 }
1228 } 1330 }
1229 } 1331 }
1230 if (optional('<', token.next)) { 1332 token = token.next;
1231 if (token.next is BeginGroupToken) { 1333 }
1232 BeginGroupToken beginGroup = token.next; 1334 while (isGeneralizedFunctionType(token)) {
1335 token = token.next;
1336 if (optional('<', token)) {
1337 if (token is BeginGroupToken) {
1338 BeginGroupToken beginGroup = token;
1233 if (beginGroup.endGroup == null) { 1339 if (beginGroup.endGroup == null) {
1234 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken); 1340 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken);
1235 } else { 1341 } else {
1236 token = beginGroup.endGroup; 1342 token = beginGroup.endGroup.next;
1237 } 1343 }
1238 } 1344 }
1239 } 1345 }
1346 if (!optional('(', token)) {
1347 if (optional(';', token)) {
1348 reportRecoverableError(token, ErrorKind.ExpectedOpenParens);
1349 }
1350 token = expect("(", token);
1351 }
1352 if (token is BeginGroupToken) {
1353 BeginGroupToken beginGroup = token;
1354 if (beginGroup.endGroup == null) {
1355 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken);
1356 } else {
1357 token = beginGroup.endGroup.next;
1358 }
1359 }
1240 } 1360 }
1241 token = token.next;
1242 } 1361 }
1243 return listener.handleMemberName(const Link<Token>()); 1362 return listener.handleMemberName(const Link<Token>());
1244 } 1363 }
1245 1364
1246 Token parseFieldInitializerOpt(Token token) { 1365 Token parseFieldInitializerOpt(Token token) {
1247 if (optional('=', token)) { 1366 if (optional('=', token)) {
1248 Token assignment = token; 1367 Token assignment = token;
1249 listener.beginFieldInitializer(token); 1368 listener.beginFieldInitializer(token);
1250 token = parseExpression(token.next); 1369 token = parseExpression(token.next);
1251 listener.endFieldInitializer(assignment); 1370 listener.endFieldInitializer(assignment);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1346 if (!isModifier(token)) break; 1465 if (!isModifier(token)) break;
1347 token = parseModifier(token); 1466 token = parseModifier(token);
1348 count++; 1467 count++;
1349 } 1468 }
1350 listener.handleModifiers(count); 1469 listener.handleModifiers(count);
1351 return token; 1470 return token;
1352 } 1471 }
1353 1472
1354 /** 1473 /**
1355 * Returns the first token after the type starting at [token]. 1474 * Returns the first token after the type starting at [token].
1475 *
1356 * This method assumes that [token] is an identifier (or void). 1476 * This method assumes that [token] is an identifier (or void).
1357 * Use [peekAfterIfType] if [token] isn't known to be an identifier. 1477 * Use [peekAfterIfType] if [token] isn't known to be an identifier.
1358 */ 1478 */
1359 Token peekAfterType(Token token) { 1479 Token peekAfterType(Token token) {
1360 // We are looking at "identifier ...". 1480 // We are looking at "identifier ...".
1481 Token peek = token;
1482 if (!isGeneralizedFunctionType(token)) {
1483 peek = peekAfterNominalType(token);
1484 }
1485
1486 // We might have just skipped over the return value of the function type.
1487 // Check again, if we are now at a function type position.
1488 while (isGeneralizedFunctionType(peek)) {
1489 peek = peekAfterFunctionType(peek.next);
1490 }
1491 return peek;
1492 }
1493
1494 /**
1495 * Returns the first token after the nominal type starting at [token].
1496 *
1497 * This method assumes that [token] is an identifier (or void).
1498 */
1499 Token peekAfterNominalType(Token token) {
1361 Token peek = token.next; 1500 Token peek = token.next;
1362 if (identical(peek.kind, PERIOD_TOKEN)) { 1501 if (identical(peek.kind, PERIOD_TOKEN)) {
1363 if (peek.next.isIdentifier()) { 1502 if (peek.next.isIdentifier()) {
1364 // Look past a library prefix. 1503 // Look past a library prefix.
1365 peek = peek.next.next; 1504 peek = peek.next.next;
1366 } 1505 }
1367 } 1506 }
1368 // We are looking at "qualified ...". 1507 // We are looking at "qualified ...".
1369 if (identical(peek.kind, LT_TOKEN)) { 1508 if (identical(peek.kind, LT_TOKEN)) {
1370 // Possibly generic type. 1509 // Possibly generic type.
1371 // We are looking at "qualified '<'". 1510 // We are looking at "qualified '<'".
1372 BeginGroupToken beginGroupToken = peek; 1511 BeginGroupToken beginGroupToken = peek;
1373 Token gtToken = beginGroupToken.endGroup; 1512 Token gtToken = beginGroupToken.endGroup;
1374 if (gtToken != null) { 1513 if (gtToken != null) {
1375 // We are looking at "qualified '<' ... '>' ...". 1514 // We are looking at "qualified '<' ... '>' ...".
1376 return gtToken.next; 1515 peek = gtToken.next;
1377 } 1516 }
1378 } 1517 }
1379 return peek; 1518 return peek;
1380 } 1519 }
1381 1520
1521 /**
1522 * Returns the first token after the function type starting at [token].
1523 *
1524 * The token must be at the token *after* the `Function` token position. That
1525 * is, the return type and the `Function` token must have already been
1526 * skipped.
1527 *
1528 * This function only skips over one function type syntax.
1529 * If necessary, this function must be called multiple times.
1530 *
1531 * Example:
1532 * ```
1533 * int Function() Function<T>(int)
1534 * ^ ^
1535 * A call to this function must be either at `(` or at `<`.
1536 * If `token` pointed to the first `(`, then the returned
1537 * token points to the second `Function` token.
1538 */
1539 Token peekAfterFunctionType(Token token) {
1540 // Possible inputs are:
1541 // ( ... )
1542 // < ... >( ... )
1543
1544 Token peek = token;
1545 // If there is a generic argument to the function, skip over that one first.
1546 if (identical(peek.kind, LT_TOKEN)) {
1547 BeginGroupToken beginGroupToken = peek;
1548 Token closeToken = beginGroupToken.endGroup;
1549 if (closeToken != null) {
1550 peek = closeToken.next;
1551 }
1552 }
1553
1554 // Now we just need to skip over the formals.
1555 expect('(', peek);
1556
1557 BeginGroupToken beginGroupToken = peek;
1558 Token closeToken = beginGroupToken.endGroup;
1559 if (closeToken != null) {
1560 peek = closeToken.next;
1561 }
1562
1563 return peek;
1564 }
1565
1382 /** 1566 /**
1383 * If [token] is the start of a type, returns the token after that type. 1567 * If [token] is the start of a type, returns the token after that type.
1384 * If [token] is not the start of a type, null is returned. 1568 * If [token] is not the start of a type, null is returned.
1385 */ 1569 */
1386 Token peekAfterIfType(Token token) { 1570 Token peekAfterIfType(Token token) {
1387 if (!optional('void', token) && !token.isIdentifier()) { 1571 if (!optional('void', token) && !token.isIdentifier()) {
1388 return null; 1572 return null;
1389 } 1573 }
1390 return peekAfterType(token); 1574 return peekAfterType(token);
1391 } 1575 }
(...skipping 1931 matching lines...) Expand 10 before | Expand all | Expand 10 after
3323 break; 3507 break;
3324 } 3508 }
3325 if (isRecoverable) { 3509 if (isRecoverable) {
3326 listener.handleRecoverableError(token, kind, arguments); 3510 listener.handleRecoverableError(token, kind, arguments);
3327 return null; 3511 return null;
3328 } else { 3512 } else {
3329 return listener.handleUnrecoverableError(token, kind, arguments); 3513 return listener.handleUnrecoverableError(token, kind, arguments);
3330 } 3514 }
3331 } 3515 }
3332 } 3516 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698