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

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: Fixes after rebase. Created 3 years, 9 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 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 /** 95 /**
96 * An event generating parser of Dart programs. This parser expects 96 * An event generating parser of Dart programs. This parser expects
97 * all tokens in a linked list (aka a token stream). 97 * all tokens in a linked list (aka a token stream).
98 * 98 *
99 * The class [Scanner] is used to generate a token stream. See the 99 * The class [Scanner] is used to generate a token stream. See the
100 * file scanner.dart. 100 * file scanner.dart.
101 * 101 *
102 * Subclasses of the class [Listener] are used to listen to events. 102 * Subclasses of the class [Listener] are used to listen to events.
103 * 103 *
104 * Most methods of this class belong in one of two major categories: 104 * Most methods of this class belong in one of two major categories:
105 * parse metods and peek methods. Parse methods all have the prefix 105 * parse methods and peek methods. Parse methods all have the prefix
106 * parse, and peek methods all have the prefix peek. 106 * parse, and peek methods all have the prefix peek.
107 * 107 *
108 * Parse methods generate events (by calling methods on [listener]) 108 * Parse methods generate events (by calling methods on [listener])
109 * and return the next token to parse. Peek methods do not generate 109 * and return the next token to parse. Peek methods do not generate
110 * events (except for errors) and may return null. 110 * events (except for errors) and may return null.
111 * 111 *
112 * Parse methods are generally named parseGrammarProductionSuffix. The 112 * Parse methods are generally named parseGrammarProductionSuffix. The
113 * suffix can be one of "opt", or "star". "opt" means zero or one 113 * suffix can be one of "opt", or "star". "opt" means zero or one
114 * matches, "star" means zero or more matches. For example, 114 * matches, "star" means zero or more matches. For example,
115 * [parseMetadataStar] corresponds to this grammar snippet: [: 115 * [parseMetadataStar] corresponds to this grammar snippet: [:
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 token.next, IdentifierContext.metadataContinuationAfterTypeArguments); 386 token.next, IdentifierContext.metadataContinuationAfterTypeArguments);
387 } 387 }
388 token = parseArgumentsOpt(token); 388 token = parseArgumentsOpt(token);
389 listener.endMetadata(atToken, period, token); 389 listener.endMetadata(atToken, period, token);
390 return token; 390 return token;
391 } 391 }
392 392
393 Token parseTypedef(Token token) { 393 Token parseTypedef(Token token) {
394 Token typedefKeyword = token; 394 Token typedefKeyword = token;
395 listener.beginFunctionTypeAlias(token); 395 listener.beginFunctionTypeAlias(token);
396 token = parseReturnTypeOpt(token.next); 396 Token equals;
397 token = parseIdentifier(token, IdentifierContext.typedefDeclaration); 397 if (optional('=', peekAfterNominalType(token.next))) {
398 token = parseTypeVariablesOpt(token); 398 token = parseIdentifier(token.next, IdentifierContext.typedefDeclaration);
399 token = parseFormalParameters(token); 399 token = parseTypeVariablesOpt(token);
400 listener.endFunctionTypeAlias(typedefKeyword, token); 400 equals = token;
401 token = expect('=', token);
402 token = parseType(token);
403 } else {
404 token = parseReturnTypeOpt(token.next);
405 token = parseIdentifier(token, IdentifierContext.typedefDeclaration);
406 token = parseTypeVariablesOpt(token);
407 token = parseFormalParameters(token);
408 }
409 listener.endFunctionTypeAlias(typedefKeyword, equals, token);
401 return expect(';', token); 410 return expect(';', token);
402 } 411 }
403 412
404 Token parseMixinApplication(Token token) { 413 Token parseMixinApplication(Token token) {
405 listener.beginMixinApplication(token); 414 listener.beginMixinApplication(token);
406 token = parseType(token); 415 token = parseType(token);
407 token = expect('with', token); 416 token = expect('with', token);
408 token = parseTypeList(token); 417 token = parseTypeList(token);
409 listener.endMixinApplication(); 418 listener.endMixinApplication();
410 return token; 419 return token;
411 } 420 }
412 421
413 Token parseReturnTypeOpt(Token token) { 422 Token parseReturnTypeOpt(Token token) {
414 if (identical(token.stringValue, 'void')) { 423 if (identical(token.stringValue, 'void')) {
415 listener.handleVoidKeyword(token); 424 if (isGeneralizedFunctionType(token.next)) {
416 return token.next; 425 return parseType(token);
426 } else {
427 listener.handleVoidKeyword(token);
428 return token.next;
429 }
417 } else { 430 } else {
418 return parseTypeOpt(token); 431 return parseTypeOpt(token);
419 } 432 }
420 } 433 }
421 434
422 Token parseFormalParametersOpt(Token token) { 435 Token parseFormalParametersOpt(Token token) {
423 if (optional('(', token)) { 436 if (optional('(', token)) {
424 return parseFormalParameters(token); 437 return parseFormalParameters(token);
425 } else { 438 } else {
426 listener.handleNoFormalParameters(token); 439 listener.handleNoFormalParameters(token);
(...skipping 11 matching lines...) Expand all
438 } 451 }
439 return reportUnrecoverableError( 452 return reportUnrecoverableError(
440 token, ErrorKind.ExpectedButGot, {"expected": "("}); 453 token, ErrorKind.ExpectedButGot, {"expected": "("});
441 } 454 }
442 BeginGroupToken beginGroupToken = token; 455 BeginGroupToken beginGroupToken = token;
443 Token endToken = beginGroupToken.endGroup; 456 Token endToken = beginGroupToken.endGroup;
444 listener.endFormalParameters(0, token, endToken); 457 listener.endFormalParameters(0, token, endToken);
445 return endToken.next; 458 return endToken.next;
446 } 459 }
447 460
448 Token parseFormalParameters(Token token) { 461 /// Parses the formal parameter list of a function.
462 ///
463 /// If [inFunctionType] is true, then the names may be omitted (except for
464 /// named arguments). If it is false, then the types may be omitted.
465 Token parseFormalParameters(Token token, {bool inFunctionType: false}) {
449 Token begin = token; 466 Token begin = token;
450 listener.beginFormalParameters(begin); 467 listener.beginFormalParameters(begin);
451 expect('(', token); 468 expect('(', token);
452 int parameterCount = 0; 469 int parameterCount = 0;
453 do { 470 do {
454 token = token.next; 471 token = token.next;
455 if (optional(')', token)) { 472 if (optional(')', token)) {
456 break; 473 break;
457 } 474 }
458 ++parameterCount; 475 ++parameterCount;
459 String value = token.stringValue; 476 String value = token.stringValue;
460 if (identical(value, '[')) { 477 if (identical(value, '[')) {
461 token = parseOptionalFormalParameters(token, false); 478 token = parseOptionalFormalParameters(
479 token, false, inFunctionType: inFunctionType);
462 break; 480 break;
463 } else if (identical(value, '{')) { 481 } else if (identical(value, '{')) {
464 token = parseOptionalFormalParameters(token, true); 482 token = parseOptionalFormalParameters(
483 token, true, inFunctionType: inFunctionType);
465 break; 484 break;
466 } 485 }
467 token = parseFormalParameter(token, FormalParameterType.REQUIRED); 486 token = parseFormalParameter(token, FormalParameterType.REQUIRED,
487 inFunctionType: inFunctionType);
468 } while (optional(',', token)); 488 } while (optional(',', token));
469 listener.endFormalParameters(parameterCount, begin, token); 489 listener.endFormalParameters(parameterCount, begin, token);
470 return expect(')', token); 490 return expect(')', token);
471 } 491 }
472 492
473 Token parseFormalParameter(Token token, FormalParameterType type) { 493 Token parseFormalParameter(Token token, FormalParameterType type,
494 {bool inFunctionType: false}) {
474 token = parseMetadataStar(token, forParameter: true); 495 token = parseMetadataStar(token, forParameter: true);
475 listener.beginFormalParameter(token); 496 listener.beginFormalParameter(token);
476 497
477 // Skip over `covariant` token, if the next token is an identifier or 498 // Skip over `covariant` token, if the next token is an identifier or
478 // modifier. 499 // modifier.
479 // This enables the case where `covariant` is the name of the parameter: 500 // This enables the case where `covariant` is the name of the parameter:
480 // void foo(covariant); 501 // void foo(covariant);
481 if (identical(token.stringValue, 'covariant') && 502 if (identical(token.stringValue, 'covariant') &&
482 (token.next.isIdentifier() || isModifier(token.next))) { 503 (token.next.isIdentifier() || isModifier(token.next))) {
483 token = token.next; 504 token = token.next;
484 } 505 }
485 token = parseModifiers(token); 506 token = parseModifiers(token);
486 // TODO(ahe): Validate that there are formal parameters if void. 507 bool isNamedParameter = type == FormalParameterType.NAMED;
487 token = parseReturnTypeOpt(token); 508
488 Token thisKeyword = null; 509 Token thisKeyword = null;
489 if (optional('this', token)) { 510 if (inFunctionType && isNamedParameter) {
490 thisKeyword = token; 511 token = parseType(token);
491 // TODO(ahe): Validate field initializers are only used in
492 // constructors, and not for function-typed arguments.
493 token = expect('.', token.next);
494 token = parseIdentifier(token, IdentifierContext.fieldInitializer);
495 } else {
496 token = 512 token =
497 parseIdentifier(token, IdentifierContext.formalParameterDeclaration); 513 parseIdentifier(token, IdentifierContext.formalParameterDeclaration);
514 } else if (inFunctionType) {
515 token = parseType(token);
516 if (token.isIdentifier()) {
517 token = parseIdentifier(
518 token, IdentifierContext.formalParameterDeclaration);
519 } else {
520 listener.handleNoName(token);
521 }
522 } else {
523 token = parseReturnTypeOpt(token);
524 if (optional('this', token)) {
525 thisKeyword = token;
526 token = expect('.', token.next);
527 token = parseIdentifier(token, IdentifierContext.fieldInitializer);
528 } else {
529 token = parseIdentifier(
530 token, IdentifierContext.formalParameterDeclaration);
531 }
498 } 532 }
533
534 // Generalized function types don't allow inline function types.
535 // The following isn't allowed:
536 // int Function(int bar(String x)).
499 if (optional('(', token)) { 537 if (optional('(', token)) {
538 Token inlineFunctionTypeStart = token;
500 listener.beginFunctionTypedFormalParameter(token); 539 listener.beginFunctionTypedFormalParameter(token);
501 listener.handleNoTypeVariables(token); 540 listener.handleNoTypeVariables(token);
502 token = parseFormalParameters(token); 541 token = parseFormalParameters(token);
503 listener.endFunctionTypedFormalParameter(token); 542 listener.endFunctionTypedFormalParameter(token);
543 if (inFunctionType) {
544 reportRecoverableError(
545 inlineFunctionTypeStart, ErrorKind.InvalidInlineFunctionType);
546 }
504 } else if (optional('<', token)) { 547 } else if (optional('<', token)) {
548 Token inlineFunctionTypeStart = token;
505 listener.beginFunctionTypedFormalParameter(token); 549 listener.beginFunctionTypedFormalParameter(token);
506 token = parseTypeVariablesOpt(token); 550 token = parseTypeVariablesOpt(token);
507 token = parseFormalParameters(token); 551 token = parseFormalParameters(token);
508 listener.endFunctionTypedFormalParameter(token); 552 listener.endFunctionTypedFormalParameter(token);
553 if (inFunctionType) {
554 reportRecoverableError(
555 inlineFunctionTypeStart, ErrorKind.InvalidInlineFunctionType);
556 }
509 } 557 }
510 String value = token.stringValue; 558 String value = token.stringValue;
511 if ((identical('=', value)) || (identical(':', value))) { 559 if ((identical('=', value)) || (identical(':', value))) {
512 // TODO(ahe): Validate that these are only used for optional parameters. 560 // TODO(ahe): Validate that these are only used for optional parameters.
513 Token equal = token; 561 Token equal = token;
514 token = parseExpression(token.next); 562 token = parseExpression(token.next);
515 listener.handleValuedFormalParameter(equal, token); 563 listener.handleValuedFormalParameter(equal, token);
516 if (type.isRequired) { 564 if (type.isRequired) {
517 reportRecoverableError( 565 reportRecoverableError(
518 equal, ErrorKind.RequiredParameterWithDefault); 566 equal, ErrorKind.RequiredParameterWithDefault);
519 } else if (type.isPositional && identical(':', value)) { 567 } else if (type.isPositional && identical(':', value)) {
520 reportRecoverableError( 568 reportRecoverableError(
521 equal, ErrorKind.PositionalParameterWithEquals); 569 equal, ErrorKind.PositionalParameterWithEquals);
522 } 570 }
523 } 571 }
524 listener.endFormalParameter(thisKeyword); 572 listener.endFormalParameter(thisKeyword);
525 return token; 573 return token;
526 } 574 }
527 575
528 Token parseOptionalFormalParameters(Token token, bool isNamed) { 576 Token parseOptionalFormalParameters(Token token, bool isNamed,
577 {bool inFunctionType: false}) {
529 Token begin = token; 578 Token begin = token;
530 listener.beginOptionalFormalParameters(begin); 579 listener.beginOptionalFormalParameters(begin);
531 assert((isNamed && optional('{', token)) || optional('[', token)); 580 assert((isNamed && optional('{', token)) || optional('[', token));
532 int parameterCount = 0; 581 int parameterCount = 0;
533 do { 582 do {
534 token = token.next; 583 token = token.next;
535 if (isNamed && optional('}', token)) { 584 if (isNamed && optional('}', token)) {
536 break; 585 break;
537 } else if (!isNamed && optional(']', token)) { 586 } else if (!isNamed && optional(']', token)) {
538 break; 587 break;
539 } 588 }
540 var type = 589 var type =
541 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; 590 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL;
542 token = parseFormalParameter(token, type); 591 token =
592 parseFormalParameter(token, type, inFunctionType: inFunctionType);
543 ++parameterCount; 593 ++parameterCount;
544 } while (optional(',', token)); 594 } while (optional(',', token));
545 if (parameterCount == 0) { 595 if (parameterCount == 0) {
546 reportRecoverableError( 596 reportRecoverableError(
547 token, 597 token,
548 isNamed 598 isNamed
549 ? ErrorKind.EmptyNamedParameterList 599 ? ErrorKind.EmptyNamedParameterList
550 : ErrorKind.EmptyOptionalParameterList); 600 : ErrorKind.EmptyOptionalParameterList);
551 } 601 }
552 listener.endOptionalFormalParameters(parameterCount, begin, token); 602 listener.endOptionalFormalParameters(parameterCount, begin, token);
553 if (isNamed) { 603 if (isNamed) {
554 return expect('}', token); 604 return expect('}', token);
555 } else { 605 } else {
556 return expect(']', token); 606 return expect(']', token);
557 } 607 }
558 } 608 }
559 609
560 Token parseTypeOpt(Token token) { 610 Token parseTypeOpt(Token token) {
611 if (isGeneralizedFunctionType(token)) {
612 // Function type without return type.
613 return parseType(token);
614 }
561 Token peek = peekAfterIfType(token); 615 Token peek = peekAfterIfType(token);
562 if (peek != null && (peek.isIdentifier() || optional('this', peek))) { 616 if (peek != null && (peek.isIdentifier() || optional('this', peek))) {
563 return parseType(token); 617 return parseType(token);
564 } 618 }
565 listener.handleNoType(token); 619 listener.handleNoType(token);
566 return token; 620 return token;
567 } 621 }
568 622
569 bool isValidTypeReference(Token token) { 623 bool isValidTypeReference(Token token) {
570 final kind = token.kind; 624 final kind = token.kind;
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
727 token = token.next; 781 token = token.next;
728 classKeyword = token; 782 classKeyword = token;
729 } 783 }
730 assert(optional('class', classKeyword)); 784 assert(optional('class', classKeyword));
731 int modifierCount = 0; 785 int modifierCount = 0;
732 if (abstractKeyword != null) { 786 if (abstractKeyword != null) {
733 parseModifier(abstractKeyword); 787 parseModifier(abstractKeyword);
734 modifierCount++; 788 modifierCount++;
735 } 789 }
736 listener.handleModifiers(modifierCount); 790 listener.handleModifiers(modifierCount);
737 bool isMixinApplication = optional('=', peekAfterType(token)); 791 bool isMixinApplication = optional('=', peekAfterNominalType(token));
738 Token name = token.next; 792 Token name = token.next;
739 793
740 if (isMixinApplication) { 794 if (isMixinApplication) {
741 token = parseIdentifier(name, IdentifierContext.namedMixinDeclaration); 795 token = parseIdentifier(name, IdentifierContext.namedMixinDeclaration);
742 listener.beginNamedMixinApplication(begin, name); 796 listener.beginNamedMixinApplication(begin, name);
743 } else { 797 } else {
744 token = parseIdentifier(name, IdentifierContext.classDeclaration); 798 token = parseIdentifier(name, IdentifierContext.classDeclaration);
745 listener.beginClassDeclaration(begin, name); 799 listener.beginClassDeclaration(begin, name);
746 } 800 }
747 801
(...skipping 19 matching lines...) Expand all
767 } 821 }
768 listener.endNamedMixinApplication(begin, classKeyword, equals, 822 listener.endNamedMixinApplication(begin, classKeyword, equals,
769 implementsKeyword, token); 823 implementsKeyword, token);
770 return expect(';', token); 824 return expect(';', token);
771 } 825 }
772 826
773 Token parseClass(Token token, Token begin, Token classKeyword, Token name) { 827 Token parseClass(Token token, Token begin, Token classKeyword, Token name) {
774 Token extendsKeyword; 828 Token extendsKeyword;
775 if (optional('extends', token)) { 829 if (optional('extends', token)) {
776 extendsKeyword = token; 830 extendsKeyword = token;
777 if (optional('with', peekAfterType(token.next))) { 831 if (optional('with', peekAfterNominalType(token.next))) {
778 token = parseMixinApplication(token.next); 832 token = parseMixinApplication(token.next);
779 } else { 833 } else {
780 token = parseType(token.next); 834 token = parseType(token.next);
781 } 835 }
782 } else { 836 } else {
783 extendsKeyword = null; 837 extendsKeyword = null;
784 listener.handleNoType(token); 838 listener.handleNoType(token);
785 } 839 }
786 Token implementsKeyword; 840 Token implementsKeyword;
787 int interfacesCount = 0; 841 int interfacesCount = 0;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
859 value2 == stringValue || 913 value2 == stringValue ||
860 value3 == stringValue || 914 value3 == stringValue ||
861 value4 == stringValue; 915 value4 == stringValue;
862 } 916 }
863 917
864 bool notEofOrValue(String value, Token token) { 918 bool notEofOrValue(String value, Token token) {
865 return !identical(token.kind, EOF_TOKEN) && 919 return !identical(token.kind, EOF_TOKEN) &&
866 !identical(value, token.stringValue); 920 !identical(value, token.stringValue);
867 } 921 }
868 922
923 bool isGeneralizedFunctionType(Token token) {
924 return optional('Function', token) &&
925 (optional('<', token.next) || optional('(', token.next));
926 }
927
869 Token parseType(Token token) { 928 Token parseType(Token token) {
870 Token begin = token; 929 Token begin = token;
871 if (isValidTypeReference(token)) { 930 if (isGeneralizedFunctionType(token)) {
872 token = parseIdentifier(token, IdentifierContext.typeReference); 931 // A function type without return type.
873 token = parseQualifiedRestOpt( 932 // Push the non-existing return type first. The loop below will
874 token, IdentifierContext.typeReferenceContinuation); 933 // generate the full type.
934 listener.handleNoType(token);
935 } else if (identical(token.stringValue, 'void') &&
936 isGeneralizedFunctionType(token.next)) {
937 listener.handleVoidKeyword(token);
938 token = token.next;
875 } else { 939 } else {
876 token = reportUnrecoverableError(token, ErrorKind.ExpectedType); 940 if (isValidTypeReference(token)) {
877 listener.handleInvalidTypeReference(token); 941 token = parseIdentifier(token, IdentifierContext.typeReference);
942 token = parseQualifiedRestOpt(
943 token, IdentifierContext.typeReferenceContinuation);
944 } else {
945 token = reportUnrecoverableError(token, ErrorKind.ExpectedType);
946 listener.handleInvalidTypeReference(token);
947 }
948 token = parseTypeArgumentsOpt(token);
949 listener.handleType(begin, token);
878 } 950 }
879 token = parseTypeArgumentsOpt(token); 951
880 listener.endType(begin, token); 952 // While we see a `Function(` treat the pushed type as return type.
953 // For example: `int Function() Function(int) Function(String x)`.
954 while (isGeneralizedFunctionType(token)) {
955 token = parseFunctionType(token);
956 }
881 return token; 957 return token;
882 } 958 }
883 959
960 /// Parses a generalized function type.
961 ///
962 /// The return type must already be pushed.
963 Token parseFunctionType(Token token) {
964 assert(optional('Function', token));
965 Token functionToken = token;
966 token = token.next;
967 token = parseTypeVariablesOpt(token);
968 token = parseFormalParameters(token, inFunctionType: true);
969 listener.handleFunctionType(functionToken, token);
970 return token;
971 }
972
884 Token parseTypeArgumentsOpt(Token token) { 973 Token parseTypeArgumentsOpt(Token token) {
885 return parseStuff( 974 return parseStuff(
886 token, 975 token,
887 (t) => listener.beginTypeArguments(t), 976 (t) => listener.beginTypeArguments(t),
888 (t) => parseType(t), 977 (t) => parseType(t),
889 (c, bt, et) => listener.endTypeArguments(c, bt, et), 978 (c, bt, et) => listener.endTypeArguments(c, bt, et),
890 (t) => listener.handleNoTypeArguments(t)); 979 (t) => listener.handleNoTypeArguments(t));
891 } 980 }
892 981
893 Token parseTypeVariablesOpt(Token token) { 982 Token parseTypeVariablesOpt(Token token) {
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
1090 1179
1091 if (getOrSet != null) { 1180 if (getOrSet != null) {
1092 var kind = (hasModifier || hasType) 1181 var kind = (hasModifier || hasType)
1093 ? ErrorKind.ExtraneousModifier 1182 ? ErrorKind.ExtraneousModifier
1094 : ErrorKind.ExtraneousModifierReplace; 1183 : ErrorKind.ExtraneousModifierReplace;
1095 reportRecoverableError(getOrSet, kind, {'modifier': getOrSet}); 1184 reportRecoverableError(getOrSet, kind, {'modifier': getOrSet});
1096 } 1185 }
1097 1186
1098 if (!hasType) { 1187 if (!hasType) {
1099 listener.handleNoType(name); 1188 listener.handleNoType(name);
1100 } else if (optional('void', type)) { 1189 } else if (optional('void', type) &&
1190 !isGeneralizedFunctionType(type.next)) {
1101 listener.handleNoType(name); 1191 listener.handleNoType(name);
1102 // TODO(ahe): This error is reported twice, second time is from 1192 // TODO(ahe): This error is reported twice, second time is from
1103 // [parseVariablesDeclarationMaybeSemicolon] via 1193 // [parseVariablesDeclarationMaybeSemicolon] via
1104 // [PartialFieldListElement.parseNode]. 1194 // [PartialFieldListElement.parseNode].
1105 reportRecoverableError(type, ErrorKind.InvalidVoid); 1195 reportRecoverableError(type, ErrorKind.InvalidVoid);
1106 } else { 1196 } else {
1107 parseType(type); 1197 parseType(type);
1108 if (isVar) { 1198 if (isVar) {
1109 reportRecoverableError(modifiers.head, ErrorKind.ExtraneousModifier, 1199 reportRecoverableError(modifiers.head, ErrorKind.ExtraneousModifier,
1110 {'modifier': modifiers.head}); 1200 {'modifier': modifiers.head});
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
1230 return listener.handleMemberName(identifiers); 1320 return listener.handleMemberName(identifiers);
1231 } else if (optional("=", token) || optional(";", token) || 1321 } else if (optional("=", token) || optional(";", token) ||
1232 optional(",", token)) { 1322 optional(",", token)) {
1233 // A field or abstract getter. 1323 // A field or abstract getter.
1234 identifiers = identifiers.prepend(token); 1324 identifiers = identifiers.prepend(token);
1235 return listener.handleMemberName(identifiers); 1325 return listener.handleMemberName(identifiers);
1236 } else if (isGetter) { 1326 } else if (isGetter) {
1237 hasName = true; 1327 hasName = true;
1238 } 1328 }
1239 identifiers = identifiers.prepend(token); 1329 identifiers = identifiers.prepend(token);
1240 if (isValidTypeReference(token)) { 1330
1241 // type ... 1331 if (!isGeneralizedFunctionType(token)) {
1242 if (optional('.', token.next)) { 1332 // Read a potential return type.
1243 // type '.' ... 1333 if (isValidTypeReference(token)) {
1244 if (token.next.next.isIdentifier()) { 1334 // type ...
1245 // type '.' identifier 1335 if (optional('.', token.next)) {
1246 token = token.next.next; 1336 // type '.' ...
1337 if (token.next.next.isIdentifier()) {
1338 // type '.' identifier
1339 token = token.next.next;
1340 }
1341 }
1342 if (optional('<', token.next)) {
1343 if (token.next is BeginGroupToken) {
1344 BeginGroupToken beginGroup = token.next;
1345 if (beginGroup.endGroup == null) {
1346 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken);
1347 } else {
1348 token = beginGroup.endGroup;
1349 }
1350 }
1247 } 1351 }
1248 } 1352 }
1249 if (optional('<', token.next)) { 1353 token = token.next;
1250 if (token.next is BeginGroupToken) { 1354 }
1251 BeginGroupToken beginGroup = token.next; 1355 while (isGeneralizedFunctionType(token)) {
1356 token = token.next;
1357 if (optional('<', token)) {
1358 if (token is BeginGroupToken) {
1359 BeginGroupToken beginGroup = token;
1252 if (beginGroup.endGroup == null) { 1360 if (beginGroup.endGroup == null) {
1253 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken); 1361 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken);
1254 } else { 1362 } else {
1255 token = beginGroup.endGroup; 1363 token = beginGroup.endGroup.next;
1256 } 1364 }
1257 } 1365 }
1258 } 1366 }
1367 if (!optional('(', token)) {
1368 if (optional(';', token)) {
1369 reportRecoverableError(token, ErrorKind.ExpectedOpenParens);
1370 }
1371 token = expect("(", token);
1372 }
1373 if (token is BeginGroupToken) {
1374 BeginGroupToken beginGroup = token;
1375 if (beginGroup.endGroup == null) {
1376 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken);
1377 } else {
1378 token = beginGroup.endGroup.next;
1379 }
1380 }
1259 } 1381 }
1260 token = token.next;
1261 } 1382 }
1262 return listener.handleMemberName(const Link<Token>()); 1383 return listener.handleMemberName(const Link<Token>());
1263 } 1384 }
1264 1385
1265 Token parseFieldInitializerOpt(Token token) { 1386 Token parseFieldInitializerOpt(Token token) {
1266 if (optional('=', token)) { 1387 if (optional('=', token)) {
1267 Token assignment = token; 1388 Token assignment = token;
1268 listener.beginFieldInitializer(token); 1389 listener.beginFieldInitializer(token);
1269 token = parseExpression(token.next); 1390 token = parseExpression(token.next);
1270 listener.endFieldInitializer(assignment); 1391 listener.endFieldInitializer(assignment);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1365 if (!isModifier(token)) break; 1486 if (!isModifier(token)) break;
1366 token = parseModifier(token); 1487 token = parseModifier(token);
1367 count++; 1488 count++;
1368 } 1489 }
1369 listener.handleModifiers(count); 1490 listener.handleModifiers(count);
1370 return token; 1491 return token;
1371 } 1492 }
1372 1493
1373 /** 1494 /**
1374 * Returns the first token after the type starting at [token]. 1495 * Returns the first token after the type starting at [token].
1496 *
1375 * This method assumes that [token] is an identifier (or void). 1497 * This method assumes that [token] is an identifier (or void).
1376 * Use [peekAfterIfType] if [token] isn't known to be an identifier. 1498 * Use [peekAfterIfType] if [token] isn't known to be an identifier.
1377 */ 1499 */
1378 Token peekAfterType(Token token) { 1500 Token peekAfterType(Token token) {
1379 // We are looking at "identifier ...". 1501 // We are looking at "identifier ...".
1502 Token peek = token;
1503 if (!isGeneralizedFunctionType(token)) {
1504 peek = peekAfterNominalType(token);
1505 }
1506
1507 // We might have just skipped over the return value of the function type.
1508 // Check again, if we are now at a function type position.
1509 while (isGeneralizedFunctionType(peek)) {
1510 peek = peekAfterFunctionType(peek.next);
1511 }
1512 return peek;
1513 }
1514
1515 /**
1516 * Returns the first token after the nominal type starting at [token].
1517 *
1518 * This method assumes that [token] is an identifier (or void).
1519 */
1520 Token peekAfterNominalType(Token token) {
1380 Token peek = token.next; 1521 Token peek = token.next;
1381 if (identical(peek.kind, PERIOD_TOKEN)) { 1522 if (identical(peek.kind, PERIOD_TOKEN)) {
1382 if (peek.next.isIdentifier()) { 1523 if (peek.next.isIdentifier()) {
1383 // Look past a library prefix. 1524 // Look past a library prefix.
1384 peek = peek.next.next; 1525 peek = peek.next.next;
1385 } 1526 }
1386 } 1527 }
1387 // We are looking at "qualified ...". 1528 // We are looking at "qualified ...".
1388 if (identical(peek.kind, LT_TOKEN)) { 1529 if (identical(peek.kind, LT_TOKEN)) {
1389 // Possibly generic type. 1530 // Possibly generic type.
1390 // We are looking at "qualified '<'". 1531 // We are looking at "qualified '<'".
1391 BeginGroupToken beginGroupToken = peek; 1532 BeginGroupToken beginGroupToken = peek;
1392 Token gtToken = beginGroupToken.endGroup; 1533 Token gtToken = beginGroupToken.endGroup;
1393 if (gtToken != null) { 1534 if (gtToken != null) {
1394 // We are looking at "qualified '<' ... '>' ...". 1535 // We are looking at "qualified '<' ... '>' ...".
1395 return gtToken.next; 1536 peek = gtToken.next;
1396 } 1537 }
1397 } 1538 }
1398 return peek; 1539 return peek;
1399 } 1540 }
1400 1541
1401 /** 1542 /**
1543 * Returns the first token after the function type starting at [token].
1544 *
1545 * The token must be at the token *after* the `Function` token position. That
1546 * is, the return type and the `Function` token must have already been
1547 * skipped.
1548 *
1549 * This function only skips over one function type syntax.
1550 * If necessary, this function must be called multiple times.
1551 *
1552 * Example:
1553 * ```
1554 * int Function() Function<T>(int)
1555 * ^ ^
1556 * A call to this function must be either at `(` or at `<`.
1557 * If `token` pointed to the first `(`, then the returned
1558 * token points to the second `Function` token.
1559 */
1560 Token peekAfterFunctionType(Token token) {
1561 // Possible inputs are:
1562 // ( ... )
1563 // < ... >( ... )
1564
1565 Token peek = token;
1566 // If there is a generic argument to the function, skip over that one first.
1567 if (identical(peek.kind, LT_TOKEN)) {
1568 BeginGroupToken beginGroupToken = peek;
1569 Token closeToken = beginGroupToken.endGroup;
1570 if (closeToken != null) {
1571 peek = closeToken.next;
1572 }
1573 }
1574
1575 // Now we just need to skip over the formals.
1576 expect('(', peek);
1577
1578 BeginGroupToken beginGroupToken = peek;
1579 Token closeToken = beginGroupToken.endGroup;
1580 if (closeToken != null) {
1581 peek = closeToken.next;
1582 }
1583
1584 return peek;
1585 }
1586
1587 /**
1402 * If [token] is the start of a type, returns the token after that type. 1588 * If [token] is the start of a type, returns the token after that type.
1403 * If [token] is not the start of a type, null is returned. 1589 * If [token] is not the start of a type, null is returned.
1404 */ 1590 */
1405 Token peekAfterIfType(Token token) { 1591 Token peekAfterIfType(Token token) {
1406 if (!optional('void', token) && !token.isIdentifier()) { 1592 if (!optional('void', token) && !token.isIdentifier()) {
1407 return null; 1593 return null;
1408 } 1594 }
1409 return peekAfterType(token); 1595 return peekAfterType(token);
1410 } 1596 }
1411 1597
(...skipping 1940 matching lines...) Expand 10 before | Expand all | Expand 10 after
3352 break; 3538 break;
3353 } 3539 }
3354 if (isRecoverable) { 3540 if (isRecoverable) {
3355 listener.handleRecoverableError(token, kind, arguments); 3541 listener.handleRecoverableError(token, kind, arguments);
3356 return null; 3542 return null;
3357 } else { 3543 } else {
3358 return listener.handleUnrecoverableError(token, kind, arguments); 3544 return listener.handleUnrecoverableError(token, kind, arguments);
3359 } 3545 }
3360 } 3546 }
3361 } 3547 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698