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