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

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

Issue 2707933002: Tests for `void`.
Patch Set: More tests. 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 = parseTypeOpt(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) {
406 if (identical(token.stringValue, 'void')) {
407 listener.handleVoidKeyword(token);
408 return token.next;
409 } else {
410 return parseTypeOpt(token);
411 }
412 }
413
414 Token parseFormalParametersOpt(Token token) { 414 Token parseFormalParametersOpt(Token token) {
415 if (optional('(', token)) { 415 if (optional('(', token)) {
416 return parseFormalParameters(token); 416 return parseFormalParameters(token);
417 } else { 417 } else {
418 listener.handleNoFormalParameters(token); 418 listener.handleNoFormalParameters(token);
419 return token; 419 return token;
420 } 420 }
421 } 421 }
422 422
423 Token skipFormalParameters(Token token) { 423 Token skipFormalParameters(Token token) {
424 // TODO(ahe): Shouldn't this be `beginFormalParameters`? 424 // TODO(ahe): Shouldn't this be `beginFormalParameters`?
425 listener.beginOptionalFormalParameters(token); 425 listener.beginOptionalFormalParameters(token);
426 if (!optional('(', token)) { 426 if (!optional('(', token)) {
427 if (optional(';', token)) { 427 if (optional(';', token)) {
428 reportRecoverableError(token, ErrorKind.ExpectedOpenParens); 428 reportRecoverableError(token, ErrorKind.ExpectedOpenParens);
429 return token; 429 return token;
430 } 430 }
431 return reportUnrecoverableError( 431 return reportUnrecoverableError(
432 token, ErrorKind.ExpectedButGot, {"expected": "("}); 432 token, ErrorKind.ExpectedButGot, {"expected": "("});
433 } 433 }
434 BeginGroupToken beginGroupToken = token; 434 BeginGroupToken beginGroupToken = token;
435 Token endToken = beginGroupToken.endGroup; 435 Token endToken = beginGroupToken.endGroup;
436 listener.endFormalParameters(0, token, endToken); 436 listener.endFormalParameters(0, token, endToken);
437 return endToken.next; 437 return endToken.next;
438 } 438 }
439 439
440 Token parseFormalParameters(Token token) { 440 /// Parses the formal parameter list of a function.
441 ///
442 /// If [inFunctionType] is true, then the names may be omitted (except for
443 /// named arguments). If it is false, then the types may be omitted.
444 Token parseFormalParameters(Token token, {bool inFunctionType: false}) {
441 Token begin = token; 445 Token begin = token;
442 listener.beginFormalParameters(begin); 446 listener.beginFormalParameters(begin);
443 expect('(', token); 447 expect('(', token);
444 int parameterCount = 0; 448 int parameterCount = 0;
445 do { 449 do {
446 token = token.next; 450 token = token.next;
447 if (optional(')', token)) { 451 if (optional(')', token)) {
448 break; 452 break;
449 } 453 }
450 ++parameterCount; 454 ++parameterCount;
451 String value = token.stringValue; 455 String value = token.stringValue;
452 if (identical(value, '[')) { 456 if (identical(value, '[')) {
453 token = parseOptionalFormalParameters(token, false); 457 token = parseOptionalFormalParameters(
458 token, false, inFunctionType: inFunctionType);
454 break; 459 break;
455 } else if (identical(value, '{')) { 460 } else if (identical(value, '{')) {
456 token = parseOptionalFormalParameters(token, true); 461 token = parseOptionalFormalParameters(
462 token, true, inFunctionType: inFunctionType);
457 break; 463 break;
458 } 464 }
459 token = parseFormalParameter(token, FormalParameterType.REQUIRED); 465 token = parseFormalParameter(token, FormalParameterType.REQUIRED,
466 inFunctionType: inFunctionType);
460 } while (optional(',', token)); 467 } while (optional(',', token));
461 listener.endFormalParameters(parameterCount, begin, token); 468 listener.endFormalParameters(parameterCount, begin, token);
462 return expect(')', token); 469 return expect(')', token);
463 } 470 }
464 471
465 Token parseFormalParameter(Token token, FormalParameterType type) { 472 Token parseFormalParameter(Token token, FormalParameterType type,
473 {bool inFunctionType}) {
466 token = parseMetadataStar(token, forParameter: true); 474 token = parseMetadataStar(token, forParameter: true);
467 listener.beginFormalParameter(token); 475 listener.beginFormalParameter(token);
468 476
469 // Skip over `covariant` token, if the next token is an identifier or 477 // Skip over `covariant` token, if the next token is an identifier or
470 // modifier. 478 // modifier.
471 // This enables the case where `covariant` is the name of the parameter: 479 // This enables the case where `covariant` is the name of the parameter:
472 // void foo(covariant); 480 // void foo(covariant);
473 if (identical(token.stringValue, 'covariant') && 481 if (identical(token.stringValue, 'covariant') &&
474 (token.next.isIdentifier() || isModifier(token.next))) { 482 (token.next.isIdentifier() || isModifier(token.next))) {
475 token = token.next; 483 token = token.next;
476 } 484 }
477 token = parseModifiers(token); 485 token = parseModifiers(token);
478 // TODO(ahe): Validate that there are formal parameters if void. 486 bool isNamedParameter = type == FormalParameterType.NAMED;
479 token = parseReturnTypeOpt(token); 487
480 Token thisKeyword = null; 488 Token thisKeyword = null;
481 if (optional('this', token)) { 489 if (inFunctionType && isNamedParameter) {
482 thisKeyword = token; 490 token = parseType(token);
483 // TODO(ahe): Validate field initializers are only used in 491 token = parseIdentifier(token);
484 // constructors, and not for function-typed arguments. 492 } else if (inFunctionType) {
485 token = expect('.', token.next); 493 token = parseType(token);
494 if (token.isIdentifier()) {
495 token = parseIdentifier(token);
496 } else {
497 listener.handleNoName(token);
498 }
499 } else {
500 token = parseTypeOpt(token);
501 if (optional('this', token)) {
502 thisKeyword = token;
503 token = expect('.', token.next);
504 }
505 token = parseIdentifier(token);
486 } 506 }
487 token = parseIdentifier(token); 507
508 // Generalized function types don't allow inline function types.
509 // The following isn't allowed:
510 // int Function(int bar(String x)).
488 if (optional('(', token)) { 511 if (optional('(', token)) {
512 Token inlineFunctionTypeStart = token;
489 listener.beginFunctionTypedFormalParameter(token); 513 listener.beginFunctionTypedFormalParameter(token);
490 listener.handleNoTypeVariables(token); 514 listener.handleNoTypeVariables(token);
491 token = parseFormalParameters(token); 515 token = parseFormalParameters(token);
492 listener.endFunctionTypedFormalParameter(token); 516 listener.endFunctionTypedFormalParameter(token);
517 if (inFunctionType) {
518 reportRecoverableError(
519 inlineFunctionTypeStart, ErrorKind.InvalidInlineFunctionType);
520 }
493 } else if (optional('<', token)) { 521 } else if (optional('<', token)) {
522 Token inlineFunctionTypeStart = token;
494 listener.beginFunctionTypedFormalParameter(token); 523 listener.beginFunctionTypedFormalParameter(token);
495 token = parseTypeVariablesOpt(token); 524 token = parseTypeVariablesOpt(token);
496 token = parseFormalParameters(token); 525 token = parseFormalParameters(token);
497 listener.endFunctionTypedFormalParameter(token); 526 listener.endFunctionTypedFormalParameter(token);
527 if (inFunctionType) {
528 reportRecoverableError(
529 inlineFunctionTypeStart, ErrorKind.InvalidInlineFunctionType);
530 }
498 } 531 }
499 String value = token.stringValue; 532 String value = token.stringValue;
500 if ((identical('=', value)) || (identical(':', value))) { 533 if ((identical('=', value)) || (identical(':', value))) {
501 // TODO(ahe): Validate that these are only used for optional parameters. 534 // TODO(ahe): Validate that these are only used for optional parameters.
502 Token equal = token; 535 Token equal = token;
503 token = parseExpression(token.next); 536 token = parseExpression(token.next);
504 listener.handleValuedFormalParameter(equal, token); 537 listener.handleValuedFormalParameter(equal, token);
505 if (type.isRequired) { 538 if (type.isRequired) {
506 reportRecoverableError( 539 reportRecoverableError(
507 equal, ErrorKind.RequiredParameterWithDefault); 540 equal, ErrorKind.RequiredParameterWithDefault);
508 } else if (type.isPositional && identical(':', value)) { 541 } else if (type.isPositional && identical(':', value)) {
509 reportRecoverableError( 542 reportRecoverableError(
510 equal, ErrorKind.PositionalParameterWithEquals); 543 equal, ErrorKind.PositionalParameterWithEquals);
511 } 544 }
512 } 545 }
513 listener.endFormalParameter(thisKeyword); 546 listener.endFormalParameter(thisKeyword);
514 return token; 547 return token;
515 } 548 }
516 549
517 Token parseOptionalFormalParameters(Token token, bool isNamed) { 550 Token parseOptionalFormalParameters(Token token, bool isNamed,
551 {bool inFunctionType}) {
518 Token begin = token; 552 Token begin = token;
519 listener.beginOptionalFormalParameters(begin); 553 listener.beginOptionalFormalParameters(begin);
520 assert((isNamed && optional('{', token)) || optional('[', token)); 554 assert((isNamed && optional('{', token)) || optional('[', token));
521 int parameterCount = 0; 555 int parameterCount = 0;
522 do { 556 do {
523 token = token.next; 557 token = token.next;
524 if (isNamed && optional('}', token)) { 558 if (isNamed && optional('}', token)) {
525 break; 559 break;
526 } else if (!isNamed && optional(']', token)) { 560 } else if (!isNamed && optional(']', token)) {
527 break; 561 break;
528 } 562 }
529 var type = 563 var type =
530 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; 564 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL;
531 token = parseFormalParameter(token, type); 565 token =
566 parseFormalParameter(token, type, inFunctionType: inFunctionType);
532 ++parameterCount; 567 ++parameterCount;
533 } while (optional(',', token)); 568 } while (optional(',', token));
534 if (parameterCount == 0) { 569 if (parameterCount == 0) {
535 reportRecoverableError( 570 reportRecoverableError(
536 token, 571 token,
537 isNamed 572 isNamed
538 ? ErrorKind.EmptyNamedParameterList 573 ? ErrorKind.EmptyNamedParameterList
539 : ErrorKind.EmptyOptionalParameterList); 574 : ErrorKind.EmptyOptionalParameterList);
540 } 575 }
541 listener.endOptionalFormalParameters(parameterCount, begin, token); 576 listener.endOptionalFormalParameters(parameterCount, begin, token);
542 if (isNamed) { 577 if (isNamed) {
543 return expect('}', token); 578 return expect('}', token);
544 } else { 579 } else {
545 return expect(']', token); 580 return expect(']', token);
546 } 581 }
547 } 582 }
548 583
549 Token parseTypeOpt(Token token) { 584 Token parseTypeOpt(Token token) {
585 if (isGeneralizedFunctionType(token)) {
586 // Function type without return type.
587 return parseType(token);
588 }
550 Token peek = peekAfterIfType(token); 589 Token peek = peekAfterIfType(token);
551 if (peek != null && (peek.isIdentifier() || optional('this', peek))) { 590 if (peek != null && (peek.isIdentifier() || optional('this', peek))) {
552 return parseType(token); 591 return parseType(token);
553 } 592 }
554 listener.handleNoType(token); 593 listener.handleNoType(token);
555 return token; 594 return token;
556 } 595 }
557 596
558 bool isValidTypeReference(Token token) { 597 bool isValidTypeReference(Token token) {
559 final kind = token.kind; 598 final kind = token.kind;
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 } 745 }
707 746
708 Token parseClassOrNamedMixinApplication(Token token) { 747 Token parseClassOrNamedMixinApplication(Token token) {
709 Token begin = token; 748 Token begin = token;
710 Token abstractKeyword; 749 Token abstractKeyword;
711 if (optional('abstract', token)) { 750 if (optional('abstract', token)) {
712 abstractKeyword = token; 751 abstractKeyword = token;
713 token = token.next; 752 token = token.next;
714 } 753 }
715 Token classKeyword = token; 754 Token classKeyword = token;
716 var isMixinApplication = optional('=', peekAfterType(token.next)); 755 var isMixinApplication = optional('=', peekAfterNominalType(token.next));
717 if (isMixinApplication) { 756 if (isMixinApplication) {
718 listener.beginNamedMixinApplication(begin); 757 listener.beginNamedMixinApplication(begin);
719 } else { 758 } else {
720 listener.beginClassDeclaration(begin); 759 listener.beginClassDeclaration(begin);
721 } 760 }
722 761
723 int modifierCount = 0; 762 int modifierCount = 0;
724 if (abstractKeyword != null) { 763 if (abstractKeyword != null) {
725 parseModifier(abstractKeyword); 764 parseModifier(abstractKeyword);
726 modifierCount++; 765 modifierCount++;
(...skipping 20 matching lines...) Expand all
747 listener.endNamedMixinApplication(classKeyword, implementsKeyword, token); 786 listener.endNamedMixinApplication(classKeyword, implementsKeyword, token);
748 return expect(';', token); 787 return expect(';', token);
749 } 788 }
750 789
751 Token parseClass(Token begin, Token classKeyword) { 790 Token parseClass(Token begin, Token classKeyword) {
752 Token token = parseIdentifier(classKeyword.next); 791 Token token = parseIdentifier(classKeyword.next);
753 token = parseTypeVariablesOpt(token); 792 token = parseTypeVariablesOpt(token);
754 Token extendsKeyword; 793 Token extendsKeyword;
755 if (optional('extends', token)) { 794 if (optional('extends', token)) {
756 extendsKeyword = token; 795 extendsKeyword = token;
757 if (optional('with', peekAfterType(token.next))) { 796 if (optional('with', peekAfterNominalType(token.next))) {
758 token = parseMixinApplication(token.next); 797 token = parseMixinApplication(token.next);
759 } else { 798 } else {
760 token = parseType(token.next); 799 token = parseType(token.next);
761 } 800 }
762 } else { 801 } else {
763 extendsKeyword = null; 802 extendsKeyword = null;
764 listener.handleNoType(token); 803 listener.handleNoType(token);
765 } 804 }
766 Token implementsKeyword; 805 Token implementsKeyword;
767 int interfacesCount = 0; 806 int interfacesCount = 0;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 value2 == stringValue || 877 value2 == stringValue ||
839 value3 == stringValue || 878 value3 == stringValue ||
840 value4 == stringValue; 879 value4 == stringValue;
841 } 880 }
842 881
843 bool notEofOrValue(String value, Token token) { 882 bool notEofOrValue(String value, Token token) {
844 return !identical(token.kind, EOF_TOKEN) && 883 return !identical(token.kind, EOF_TOKEN) &&
845 !identical(value, token.stringValue); 884 !identical(value, token.stringValue);
846 } 885 }
847 886
887 bool isGeneralizedFunctionType(Token token) {
888 return optional('Function', token) &&
889 (optional('<', token.next) || optional('(', token.next));
890 }
891
848 Token parseType(Token token) { 892 Token parseType(Token token) {
849 Token begin = token; 893 Token begin = token;
850 if (isValidTypeReference(token)) { 894 if (isGeneralizedFunctionType(token)) {
851 token = parseIdentifier(token); 895 // A function type without return type.
852 token = parseQualifiedRestOpt(token); 896 // Push the non-existing return type first. The loop below will
897 // generate the full type.
898 listener.handleNoType(token);
853 } else { 899 } else {
854 token = reportUnrecoverableError(token, ErrorKind.ExpectedType); 900 if (isValidTypeReference(token)) {
855 listener.handleInvalidTypeReference(token); 901 token = parseIdentifier(token);
902 token = parseQualifiedRestOpt(token);
903 } else {
904 token = reportUnrecoverableError(token, ErrorKind.ExpectedType);
905 listener.handleInvalidTypeReference(token);
906 }
907 token = parseTypeArgumentsOpt(token);
908 listener.handleType(begin, token);
856 } 909 }
857 token = parseTypeArgumentsOpt(token); 910
858 listener.endType(begin, token); 911 // While we see a `Function(` treat the pushed type as return type.
912 // For example: `int Function() Function(int) Function(String x)`.
913 while (isGeneralizedFunctionType(token)) {
914 token = parseFunctionType(token);
915 }
859 return token; 916 return token;
860 } 917 }
861 918
919 /// Parses a generalized function type.
920 ///
921 /// The return type must already be pushed.
922 Token parseFunctionType(Token token) {
923 assert(optional('Function', token));
924 Token functionToken = token;
925 token = token.next;
926 token = parseTypeVariablesOpt(token);
927 token = parseFormalParameters(token, inFunctionType: true);
928 listener.handleFunctionType(functionToken, token);
929 return token;
930 }
931
862 Token parseTypeArgumentsOpt(Token token) { 932 Token parseTypeArgumentsOpt(Token token) {
863 return parseStuff( 933 return parseStuff(
864 token, 934 token,
865 (t) => listener.beginTypeArguments(t), 935 (t) => listener.beginTypeArguments(t),
866 (t) => parseType(t), 936 (t) => parseType(t),
867 (c, bt, et) => listener.endTypeArguments(c, bt, et), 937 (c, bt, et) => listener.endTypeArguments(c, bt, et),
868 (t) => listener.handleNoTypeArguments(t)); 938 (t) => listener.handleNoTypeArguments(t));
869 } 939 }
870 940
871 Token parseTypeVariablesOpt(Token token) { 941 Token parseTypeVariablesOpt(Token token) {
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
1068 1138
1069 if (getOrSet != null) { 1139 if (getOrSet != null) {
1070 var kind = (hasModifier || hasType) 1140 var kind = (hasModifier || hasType)
1071 ? ErrorKind.ExtraneousModifier 1141 ? ErrorKind.ExtraneousModifier
1072 : ErrorKind.ExtraneousModifierReplace; 1142 : ErrorKind.ExtraneousModifierReplace;
1073 reportRecoverableError(getOrSet, kind, {'modifier': getOrSet}); 1143 reportRecoverableError(getOrSet, kind, {'modifier': getOrSet});
1074 } 1144 }
1075 1145
1076 if (!hasType) { 1146 if (!hasType) {
1077 listener.handleNoType(name); 1147 listener.handleNoType(name);
1078 } else if (optional('void', type)) {
1079 listener.handleNoType(name);
1080 // TODO(ahe): This error is reported twice, second time is from
1081 // [parseVariablesDeclarationMaybeSemicolon] via
1082 // [PartialFieldListElement.parseNode].
1083 reportRecoverableError(type, ErrorKind.InvalidVoid);
1084 } else { 1148 } else {
1085 parseType(type); 1149 parseType(type);
1086 if (isVar) { 1150 if (isVar) {
1087 reportRecoverableError(modifiers.head, ErrorKind.ExtraneousModifier, 1151 reportRecoverableError(modifiers.head, ErrorKind.ExtraneousModifier,
1088 {'modifier': modifiers.head}); 1152 {'modifier': modifiers.head});
1089 } 1153 }
1090 } 1154 }
1091 1155
1092 Token token = parseIdentifier(name); 1156 Token token = parseIdentifier(name);
1093 1157
(...skipping 30 matching lines...) Expand all
1124 if (externalModifier != null) { 1188 if (externalModifier != null) {
1125 parseModifier(externalModifier); 1189 parseModifier(externalModifier);
1126 listener.handleModifiers(1); 1190 listener.handleModifiers(1);
1127 } else { 1191 } else {
1128 listener.handleModifiers(0); 1192 listener.handleModifiers(0);
1129 } 1193 }
1130 1194
1131 if (type == null) { 1195 if (type == null) {
1132 listener.handleNoType(name); 1196 listener.handleNoType(name);
1133 } else { 1197 } else {
1134 parseReturnTypeOpt(type); 1198 parseTypeOpt(type);
1135 } 1199 }
1136 Token token = parseIdentifier(name); 1200 Token token = parseIdentifier(name);
1137 1201
1138 if (getOrSet == null) { 1202 if (getOrSet == null) {
1139 token = parseTypeVariablesOpt(token); 1203 token = parseTypeVariablesOpt(token);
1140 } else { 1204 } else {
1141 listener.handleNoTypeVariables(token); 1205 listener.handleNoTypeVariables(token);
1142 } 1206 }
1143 token = parseFormalParametersOpt(token); 1207 token = parseFormalParametersOpt(token);
1144 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; 1208 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1203 return listener.handleMemberName(identifiers); 1267 return listener.handleMemberName(identifiers);
1204 } else if (optional("=", token) || optional(";", token) || 1268 } else if (optional("=", token) || optional(";", token) ||
1205 optional(",", token)) { 1269 optional(",", token)) {
1206 // A field or abstract getter. 1270 // A field or abstract getter.
1207 identifiers = identifiers.prepend(token); 1271 identifiers = identifiers.prepend(token);
1208 return listener.handleMemberName(identifiers); 1272 return listener.handleMemberName(identifiers);
1209 } else if (isGetter) { 1273 } else if (isGetter) {
1210 hasName = true; 1274 hasName = true;
1211 } 1275 }
1212 identifiers = identifiers.prepend(token); 1276 identifiers = identifiers.prepend(token);
1213 if (isValidTypeReference(token)) { 1277
1214 // type ... 1278 if (!isGeneralizedFunctionType(token)) {
1215 if (optional('.', token.next)) { 1279 // Read a potential return type.
1216 // type '.' ... 1280 if (isValidTypeReference(token)) {
1217 if (token.next.next.isIdentifier()) { 1281 // type ...
1218 // type '.' identifier 1282 if (optional('.', token.next)) {
1219 token = token.next.next; 1283 // type '.' ...
1284 if (token.next.next.isIdentifier()) {
1285 // type '.' identifier
1286 token = token.next.next;
1287 }
1288 }
1289 if (optional('<', token.next)) {
1290 if (token.next is BeginGroupToken) {
1291 BeginGroupToken beginGroup = token.next;
1292 if (beginGroup.endGroup == null) {
1293 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken);
1294 } else {
1295 token = beginGroup.endGroup;
1296 }
1297 }
1220 } 1298 }
1221 } 1299 }
1222 if (optional('<', token.next)) { 1300 token = token.next;
1223 if (token.next is BeginGroupToken) { 1301 }
1224 BeginGroupToken beginGroup = token.next; 1302 while (isGeneralizedFunctionType(token)) {
1303 token = token.next;
1304 if (optional('<', token)) {
1305 if (token is BeginGroupToken) {
1306 BeginGroupToken beginGroup = token;
1225 if (beginGroup.endGroup == null) { 1307 if (beginGroup.endGroup == null) {
1226 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken); 1308 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken);
1227 } else { 1309 } else {
1228 token = beginGroup.endGroup; 1310 token = beginGroup.endGroup.next;
1229 } 1311 }
1230 } 1312 }
1231 } 1313 }
1314 if (!optional('(', token)) {
1315 if (optional(';', token)) {
1316 reportRecoverableError(token, ErrorKind.ExpectedOpenParens);
1317 }
1318 token = expect("(", token);
1319 }
1320 if (token is BeginGroupToken) {
1321 BeginGroupToken beginGroup = token;
1322 if (beginGroup.endGroup == null) {
1323 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken);
1324 } else {
1325 token = beginGroup.endGroup.next;
1326 }
1327 }
1232 } 1328 }
1233 token = token.next;
1234 } 1329 }
1235 return listener.handleMemberName(const Link<Token>()); 1330 return listener.handleMemberName(const Link<Token>());
1236 } 1331 }
1237 1332
1238 Token parseFieldInitializerOpt(Token token) { 1333 Token parseFieldInitializerOpt(Token token) {
1239 if (optional('=', token)) { 1334 if (optional('=', token)) {
1240 Token assignment = token; 1335 Token assignment = token;
1241 listener.beginFieldInitializer(token); 1336 listener.beginFieldInitializer(token);
1242 token = parseExpression(token.next); 1337 token = parseExpression(token.next);
1243 listener.endFieldInitializer(assignment); 1338 listener.endFieldInitializer(assignment);
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
1336 if (!isModifier(token)) break; 1431 if (!isModifier(token)) break;
1337 token = parseModifier(token); 1432 token = parseModifier(token);
1338 count++; 1433 count++;
1339 } 1434 }
1340 listener.handleModifiers(count); 1435 listener.handleModifiers(count);
1341 return token; 1436 return token;
1342 } 1437 }
1343 1438
1344 /** 1439 /**
1345 * Returns the first token after the type starting at [token]. 1440 * Returns the first token after the type starting at [token].
1441 *
1346 * This method assumes that [token] is an identifier (or void). 1442 * This method assumes that [token] is an identifier (or void).
1347 * Use [peekAfterIfType] if [token] isn't known to be an identifier. 1443 * Use [peekAfterIfType] if [token] isn't known to be an identifier.
1348 */ 1444 */
1349 Token peekAfterType(Token token) { 1445 Token peekAfterType(Token token) {
1350 // We are looking at "identifier ...". 1446 // We are looking at "identifier ...".
1447 Token peek = token;
1448 if (!isGeneralizedFunctionType(token)) {
1449 peek = peekAfterNominalType(token);
1450 }
1451
1452 // We might have just skipped over the return value of the function type.
1453 // Check again, if we are now at a function type position.
1454 while (isGeneralizedFunctionType(peek)) {
1455 peek = peekAfterFunctionType(peek.next);
1456 }
1457 return peek;
1458 }
1459
1460 /**
1461 * Returns the first token after the nominal type starting at [token].
1462 *
1463 * This method assumes that [token] is an identifier (or void).
1464 */
1465 Token peekAfterNominalType(Token token) {
1351 Token peek = token.next; 1466 Token peek = token.next;
1352 if (identical(peek.kind, PERIOD_TOKEN)) { 1467 if (identical(peek.kind, PERIOD_TOKEN)) {
1353 if (peek.next.isIdentifier()) { 1468 if (peek.next.isIdentifier()) {
1354 // Look past a library prefix. 1469 // Look past a library prefix.
1355 peek = peek.next.next; 1470 peek = peek.next.next;
1356 } 1471 }
1357 } 1472 }
1358 // We are looking at "qualified ...". 1473 // We are looking at "qualified ...".
1359 if (identical(peek.kind, LT_TOKEN)) { 1474 if (identical(peek.kind, LT_TOKEN)) {
1360 // Possibly generic type. 1475 // Possibly generic type.
1361 // We are looking at "qualified '<'". 1476 // We are looking at "qualified '<'".
1362 BeginGroupToken beginGroupToken = peek; 1477 BeginGroupToken beginGroupToken = peek;
1363 Token gtToken = beginGroupToken.endGroup; 1478 Token gtToken = beginGroupToken.endGroup;
1364 if (gtToken != null) { 1479 if (gtToken != null) {
1365 // We are looking at "qualified '<' ... '>' ...". 1480 // We are looking at "qualified '<' ... '>' ...".
1366 return gtToken.next; 1481 peek = gtToken.next;
1367 } 1482 }
1368 } 1483 }
1369 return peek; 1484 return peek;
1370 } 1485 }
1371 1486
1372 /** 1487 /**
1488 * Returns the first token after the function type starting at [token].
1489 *
1490 * The token must be at the token *after* the `Function` token position. That
1491 * is, the return type and the `Function` token must have already been
1492 * skipped.
1493 *
1494 * This function only skips over one function type syntax.
1495 * If necessary, this function must be called multiple times.
1496 *
1497 * Example:
1498 * ```
1499 * int Function() Function<T>(int)
1500 * ^ ^
1501 * A call to this function must be either at `(` or at `<`.
1502 * If `token` pointed to the first `(`, then the returned
1503 * token points to the second `Function` token.
1504 */
1505 Token peekAfterFunctionType(Token token) {
1506 // Possible inputs are:
1507 // ( ... )
1508 // < ... >( ... )
1509
1510 Token peek = token;
1511 // If there is a generic argument to the function, skip over that one first.
1512 if (identical(peek.kind, LT_TOKEN)) {
1513 BeginGroupToken beginGroupToken = peek;
1514 Token closeToken = beginGroupToken.endGroup;
1515 if (closeToken != null) {
1516 peek = closeToken.next;
1517 }
1518 }
1519
1520 // Now we just need to skip over the formals.
1521 expect('(', peek);
1522
1523 BeginGroupToken beginGroupToken = peek;
1524 Token closeToken = beginGroupToken.endGroup;
1525 if (closeToken != null) {
1526 peek = closeToken.next;
1527 }
1528
1529 return peek;
1530 }
1531
1532 /**
1373 * If [token] is the start of a type, returns the token after that type. 1533 * If [token] is the start of a type, returns the token after that type.
1374 * If [token] is not the start of a type, null is returned. 1534 * If [token] is not the start of a type, null is returned.
1375 */ 1535 */
1376 Token peekAfterIfType(Token token) { 1536 Token peekAfterIfType(Token token) {
1377 if (!optional('void', token) && !token.isIdentifier()) { 1537 if (!token.isIdentifier()) {
1378 return null; 1538 return null;
1379 } 1539 }
1380 return peekAfterType(token); 1540 return peekAfterType(token);
1381 } 1541 }
1382 1542
1383 Token skipClassBody(Token token) { 1543 Token skipClassBody(Token token) {
1384 if (!optional('{', token)) { 1544 if (!optional('{', token)) {
1385 return reportUnrecoverableError(token, ErrorKind.ExpectedClassBodyToSkip); 1545 return reportUnrecoverableError(token, ErrorKind.ExpectedClassBodyToSkip);
1386 } 1546 }
1387 BeginGroupToken beginGroupToken = token; 1547 BeginGroupToken beginGroupToken = token;
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
1552 } 1712 }
1553 if (getOrSet != null && constModifier != null) { 1713 if (getOrSet != null && constModifier != null) {
1554 reportRecoverableError(constModifier, ErrorKind.ExtraneousModifier, 1714 reportRecoverableError(constModifier, ErrorKind.ExtraneousModifier,
1555 {'modifier': constModifier}); 1715 {'modifier': constModifier});
1556 } 1716 }
1557 parseModifierList(modifiers); 1717 parseModifierList(modifiers);
1558 1718
1559 if (type == null) { 1719 if (type == null) {
1560 listener.handleNoType(name); 1720 listener.handleNoType(name);
1561 } else { 1721 } else {
1562 parseReturnTypeOpt(type); 1722 parseTypeOpt(type);
1563 } 1723 }
1564 Token token; 1724 Token token;
1565 if (optional('operator', name)) { 1725 if (optional('operator', name)) {
1566 token = parseOperatorName(name); 1726 token = parseOperatorName(name);
1567 if (staticModifier != null) { 1727 if (staticModifier != null) {
1568 reportRecoverableError(staticModifier, ErrorKind.ExtraneousModifier, 1728 reportRecoverableError(staticModifier, ErrorKind.ExtraneousModifier,
1569 {'modifier': staticModifier}); 1729 {'modifier': staticModifier});
1570 } 1730 }
1571 } else { 1731 } else {
1572 token = parseIdentifier(name); 1732 token = parseIdentifier(name);
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1644 } else { 1804 } else {
1645 token = parseIdentifier(token); 1805 token = parseIdentifier(token);
1646 } 1806 }
1647 } else if (optional('operator', token)) { 1807 } else if (optional('operator', token)) {
1648 // operator <op> (... 1808 // operator <op> (...
1649 listener.handleNoType(token); 1809 listener.handleNoType(token);
1650 listener.beginFunctionName(token); 1810 listener.beginFunctionName(token);
1651 token = parseOperatorName(token); 1811 token = parseOperatorName(token);
1652 } else { 1812 } else {
1653 // <type>? <get>? <name> 1813 // <type>? <get>? <name>
1654 token = parseReturnTypeOpt(token); 1814 token = parseTypeOpt(token);
1655 if (identical(getOrSet, token)) { 1815 if (identical(getOrSet, token)) {
1656 token = token.next; 1816 token = token.next;
1657 } 1817 }
1658 listener.beginFunctionName(token); 1818 listener.beginFunctionName(token);
1659 if (optional('operator', token)) { 1819 if (optional('operator', token)) {
1660 token = parseOperatorName(token); 1820 token = parseOperatorName(token);
1661 } else { 1821 } else {
1662 token = parseIdentifier(token); 1822 token = parseIdentifier(token);
1663 } 1823 }
1664 } 1824 }
(...skipping 29 matching lines...) Expand all
1694 Token parseFunctionDeclaration(Token token) { 1854 Token parseFunctionDeclaration(Token token) {
1695 listener.beginFunctionDeclaration(token); 1855 listener.beginFunctionDeclaration(token);
1696 token = parseFunction(token, null); 1856 token = parseFunction(token, null);
1697 listener.endFunctionDeclaration(token); 1857 listener.endFunctionDeclaration(token);
1698 return token; 1858 return token;
1699 } 1859 }
1700 1860
1701 Token parseFunctionExpression(Token token) { 1861 Token parseFunctionExpression(Token token) {
1702 listener.beginFunction(token); 1862 listener.beginFunction(token);
1703 listener.handleModifiers(0); 1863 listener.handleModifiers(0);
1704 token = parseReturnTypeOpt(token); 1864 token = parseTypeOpt(token);
1705 listener.beginFunctionName(token); 1865 listener.beginFunctionName(token);
1706 token = parseIdentifier(token); 1866 token = parseIdentifier(token);
1707 listener.endFunctionName(token); 1867 listener.endFunctionName(token);
1708 token = parseTypeVariablesOpt(token); 1868 token = parseTypeVariablesOpt(token);
1709 token = parseFormalParameters(token); 1869 token = parseFormalParameters(token);
1710 listener.handleNoInitializers(); 1870 listener.handleNoInitializers();
1711 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; 1871 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled;
1712 token = parseAsyncModifier(token); 1872 token = parseAsyncModifier(token);
1713 bool isBlock = optional('{', token); 1873 bool isBlock = optional('{', token);
1714 token = parseFunctionBody(token, true, false); 1874 token = parseFunctionBody(token, true, false);
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
1895 } else { 2055 } else {
1896 return parseExpressionStatement(token); 2056 return parseExpressionStatement(token);
1897 } 2057 }
1898 } else if (identical(value, 'for')) { 2058 } else if (identical(value, 'for')) {
1899 return parseForStatement(null, token); 2059 return parseForStatement(null, token);
1900 } else if (identical(value, 'rethrow')) { 2060 } else if (identical(value, 'rethrow')) {
1901 return parseRethrowStatement(token); 2061 return parseRethrowStatement(token);
1902 } else if (identical(value, 'throw') && optional(';', token.next)) { 2062 } else if (identical(value, 'throw') && optional(';', token.next)) {
1903 // TODO(kasperl): Stop dealing with throw here. 2063 // TODO(kasperl): Stop dealing with throw here.
1904 return parseRethrowStatement(token); 2064 return parseRethrowStatement(token);
1905 } else if (identical(value, 'void')) {
1906 return parseExpressionStatementOrDeclaration(token);
1907 } else if (identical(value, 'while')) { 2065 } else if (identical(value, 'while')) {
1908 return parseWhileStatement(token); 2066 return parseWhileStatement(token);
1909 } else if (identical(value, 'do')) { 2067 } else if (identical(value, 'do')) {
1910 return parseDoWhileStatement(token); 2068 return parseDoWhileStatement(token);
1911 } else if (identical(value, 'try')) { 2069 } else if (identical(value, 'try')) {
1912 return parseTryStatement(token); 2070 return parseTryStatement(token);
1913 } else if (identical(value, 'switch')) { 2071 } else if (identical(value, 'switch')) {
1914 return parseSwitchStatement(token); 2072 return parseSwitchStatement(token);
1915 } else if (identical(value, 'break')) { 2073 } else if (identical(value, 'break')) {
1916 return parseBreakStatement(token); 2074 return parseBreakStatement(token);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1977 return peek; 2135 return peek;
1978 } else if (token.isIdentifier()) { 2136 } else if (token.isIdentifier()) {
1979 // We are looking at "identifier". 2137 // We are looking at "identifier".
1980 return token; 2138 return token;
1981 } else { 2139 } else {
1982 return null; 2140 return null;
1983 } 2141 }
1984 } 2142 }
1985 2143
1986 Token parseExpressionStatementOrDeclaration(Token token) { 2144 Token parseExpressionStatementOrDeclaration(Token token) {
1987 assert(token.isIdentifier() || identical(token.stringValue, 'void')); 2145 assert(token.isIdentifier());
1988 Token identifier = peekIdentifierAfterType(token); 2146 Token identifier = peekIdentifierAfterType(token);
1989 if (identifier != null) { 2147 if (identifier != null) {
1990 assert(identifier.isIdentifier()); 2148 assert(identifier.isIdentifier());
1991 Token afterId = identifier.next; 2149 Token afterId = identifier.next;
1992 int afterIdKind = afterId.kind; 2150 int afterIdKind = afterId.kind;
1993 if (identical(afterIdKind, EQ_TOKEN) || 2151 if (identical(afterIdKind, EQ_TOKEN) ||
1994 identical(afterIdKind, SEMICOLON_TOKEN) || 2152 identical(afterIdKind, SEMICOLON_TOKEN) ||
1995 identical(afterIdKind, COMMA_TOKEN)) { 2153 identical(afterIdKind, COMMA_TOKEN)) {
1996 // We are looking at "type identifier" followed by '=', ';', ','. 2154 // We are looking at "type identifier" followed by '=', ';', ','.
1997 return parseVariablesDeclaration(token); 2155 return parseVariablesDeclaration(token);
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
2389 } else if (value == 'null') { 2547 } else if (value == 'null') {
2390 return parseLiteralNull(token); 2548 return parseLiteralNull(token);
2391 } else if (value == 'this') { 2549 } else if (value == 'this') {
2392 return parseThisExpression(token); 2550 return parseThisExpression(token);
2393 } else if (value == 'super') { 2551 } else if (value == 'super') {
2394 return parseSuperExpression(token); 2552 return parseSuperExpression(token);
2395 } else if (value == 'new') { 2553 } else if (value == 'new') {
2396 return parseNewExpression(token); 2554 return parseNewExpression(token);
2397 } else if (value == 'const') { 2555 } else if (value == 'const') {
2398 return parseConstExpression(token); 2556 return parseConstExpression(token);
2399 } else if (value == 'void') {
2400 return parseFunctionExpression(token);
2401 } else if (asyncAwaitKeywordsEnabled && 2557 } else if (asyncAwaitKeywordsEnabled &&
2402 (value == 'yield' || value == 'async')) { 2558 (value == 'yield' || value == 'async')) {
2403 return expressionExpected(token); 2559 return expressionExpected(token);
2404 } else if (token.isIdentifier()) { 2560 } else if (token.isIdentifier()) {
2405 return parseSendOrFunctionLiteral(token); 2561 return parseSendOrFunctionLiteral(token);
2406 } else { 2562 } else {
2407 return expressionExpected(token); 2563 return expressionExpected(token);
2408 } 2564 }
2409 } else if (kind == OPEN_PAREN_TOKEN) { 2565 } else if (kind == OPEN_PAREN_TOKEN) {
2410 return parseParenthesizedExpressionOrFunctionLiteral(token); 2566 return parseParenthesizedExpressionOrFunctionLiteral(token);
(...skipping 901 matching lines...) Expand 10 before | Expand all | Expand 10 after
3312 break; 3468 break;
3313 } 3469 }
3314 if (isRecoverable) { 3470 if (isRecoverable) {
3315 listener.handleRecoverableError(token, kind, arguments); 3471 listener.handleRecoverableError(token, kind, arguments);
3316 return null; 3472 return null;
3317 } else { 3473 } else {
3318 return listener.handleUnrecoverableError(token, kind, arguments); 3474 return listener.handleUnrecoverableError(token, kind, arguments);
3319 } 3475 }
3320 } 3476 }
3321 } 3477 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698