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

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

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

Powered by Google App Engine
This is Rietveld 408576698