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