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