Chromium Code Reviews| 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 /** | 5 /** |
| 6 * An event generating parser of Dart programs. This parser expects | 6 * An event generating parser of Dart programs. This parser expects |
| 7 * all tokens in a linked list (aka a token stream). | 7 * all tokens in a linked list (aka a token stream). |
| 8 * | 8 * |
| 9 * The class [Scanner] is used to generate a token stream. See the | 9 * The class [Scanner] is used to generate a token stream. See the |
| 10 * file scanner.dart. | 10 * file scanner.dart. |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 278 listener.endOptionalFormalParameters(parameterCount, begin, token); | 278 listener.endOptionalFormalParameters(parameterCount, begin, token); |
| 279 if (isNamed) { | 279 if (isNamed) { |
| 280 return expect('}', token); | 280 return expect('}', token); |
| 281 } else { | 281 } else { |
| 282 return expect(']', token); | 282 return expect(']', token); |
| 283 } | 283 } |
| 284 } | 284 } |
| 285 | 285 |
| 286 Token parseTypeOpt(Token token) { | 286 Token parseTypeOpt(Token token) { |
| 287 String value = token.stringValue; | 287 String value = token.stringValue; |
| 288 if (value === 'var') return parseType(token); | |
| 289 if (value !== 'this') { | 288 if (value !== 'this') { |
| 290 Token peek = peekAfterExpectedType(token); | 289 Token peek = peekAfterExpectedType(token); |
| 291 if (isIdentifier(peek) || optional('this', peek)) { | 290 if (isIdentifier(peek) || optional('this', peek)) { |
| 292 return parseType(token); | 291 return parseType(token); |
| 293 } | 292 } |
| 294 } | 293 } |
| 295 listener.handleNoType(token); | 294 listener.handleNoType(token); |
| 296 return token; | 295 return token; |
| 297 } | 296 } |
| 298 | 297 |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 499 endStuff(count, begin, token); | 498 endStuff(count, begin, token); |
| 500 return expect('>', token); | 499 return expect('>', token); |
| 501 } | 500 } |
| 502 handleNoStuff(token); | 501 handleNoStuff(token); |
| 503 return token; | 502 return token; |
| 504 } | 503 } |
| 505 | 504 |
| 506 Token parseTopLevelMember(Token token) { | 505 Token parseTopLevelMember(Token token) { |
| 507 Token start = token; | 506 Token start = token; |
| 508 listener.beginTopLevelMember(token); | 507 listener.beginTopLevelMember(token); |
| 509 token = parseModifiers(token); | 508 |
| 510 Token getOrSet = findGetOrSet(token); | 509 Link<Token> identifiers = findMemberName(token); |
| 511 if (token === getOrSet) token = token.next; | 510 if (identifiers.isEmpty()) { |
| 512 Token peek = peekAfterExpectedType(token); | 511 return listener.unexpected(start); |
| 513 if (isIdentifier(peek)) { | |
| 514 // Skip type. | |
| 515 token = peek; | |
| 516 } | 512 } |
| 517 if (token === getOrSet) token = token.next; | 513 Token name = identifiers.head; |
| 518 token = parseIdentifier(token); | 514 identifiers = identifiers.tail; |
| 515 if (!identifiers.isEmpty()) { | |
| 516 if (optional('operator', identifiers.head)) { | |
|
ngeoffray
2012/09/10 14:24:49
'operator' does not apply to top level methods.
ahe
2012/09/10 19:03:02
Done.
| |
| 517 name = identifiers.head; | |
| 518 identifiers = identifiers.tail; | |
| 519 } | |
| 520 } | |
| 521 Token getOrSet; | |
| 522 if (!identifiers.isEmpty()) { | |
| 523 String value = identifiers.head.stringValue; | |
| 524 if ((value === 'get') || (value === 'set')) { | |
| 525 getOrSet = identifiers.head; | |
| 526 identifiers = identifiers.tail; | |
| 527 } | |
| 528 } | |
| 529 Token type; | |
| 530 if (!identifiers.isEmpty()) { | |
| 531 if (isValidTypeReference(identifiers.head)) { | |
| 532 type = identifiers.head; | |
| 533 identifiers = identifiers.tail; | |
| 534 } | |
| 535 } | |
| 536 parseModifierList(identifiers.reverse()); | |
| 537 if (type === null) { | |
| 538 listener.handleNoType(token); | |
| 539 } else { | |
| 540 parseReturnTypeOpt(type); | |
| 541 } | |
| 542 token = parseIdentifier(name); | |
| 543 | |
| 519 bool isField; | 544 bool isField; |
| 520 while (true) { | 545 while (true) { |
| 521 // Loop to allow the listener to rewrite the token stream for | 546 // Loop to allow the listener to rewrite the token stream for |
| 522 // error handling. | 547 // error handling. |
| 523 final String value = token.stringValue; | 548 final String value = token.stringValue; |
| 524 if ((value === '(') || (value === '{') || (value === '=>')) { | 549 if ((value === '(') || (value === '{') || (value === '=>')) { |
| 525 isField = false; | 550 isField = false; |
| 526 break; | 551 break; |
| 527 } else if ((value === '=') || (value === ';') || (value === ',')) { | 552 } else if ((value === '=') || (value === ';') || (value === ',')) { |
| 528 isField = true; | 553 isField = true; |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 548 expectSemicolon(token); | 573 expectSemicolon(token); |
| 549 listener.endTopLevelFields(fieldCount, start, token); | 574 listener.endTopLevelFields(fieldCount, start, token); |
| 550 } else { | 575 } else { |
| 551 token = parseFormalParametersOpt(token); | 576 token = parseFormalParametersOpt(token); |
| 552 token = parseFunctionBody(token, false); | 577 token = parseFunctionBody(token, false); |
| 553 listener.endTopLevelMethod(start, getOrSet, token); | 578 listener.endTopLevelMethod(start, getOrSet, token); |
| 554 } | 579 } |
| 555 return token.next; | 580 return token.next; |
| 556 } | 581 } |
| 557 | 582 |
| 583 Link<Token> findMemberName(Token token) { | |
| 584 Link<Token> identifiers = const EmptyLink<Token>(); | |
| 585 while (token.kind !== EOF_TOKEN) { | |
| 586 String value = token.stringValue; | |
| 587 if ((value === '(') || (value === '{') || (value === '=>')) { | |
| 588 // A method. | |
| 589 return identifiers; | |
| 590 } else if ((value === '=') || (value === ';') || (value === ',')) { | |
| 591 // A field or abstract getter. | |
| 592 return identifiers; | |
| 593 } | |
| 594 identifiers = identifiers.prepend(token); | |
| 595 if (isValidTypeReference(token)) { | |
| 596 // type ... | |
| 597 if (optional('.', token.next)) { | |
| 598 // type '.' ... | |
| 599 if (isIdentifier(token.next.next)) { | |
| 600 // type '.' identifier | |
| 601 token = token.next.next; | |
| 602 } | |
| 603 } | |
| 604 if (optional('<', token.next)) { | |
| 605 if (token.next is BeginGroupToken) { | |
| 606 BeginGroupToken beginGroup = token.next; | |
| 607 token = beginGroup.endGroup; | |
| 608 } | |
| 609 } | |
| 610 } | |
| 611 token = token.next; | |
| 612 } | |
| 613 return listener.unexpected(token); | |
| 614 } | |
| 615 | |
| 558 Token parseVariableInitializerOpt(Token token) { | 616 Token parseVariableInitializerOpt(Token token) { |
| 559 if (optional('=', token)) { | 617 if (optional('=', token)) { |
| 560 Token assignment = token; | 618 Token assignment = token; |
| 561 listener.beginInitializer(token); | 619 listener.beginInitializer(token); |
| 562 token = parseExpression(token.next); | 620 token = parseExpression(token.next); |
| 563 listener.endInitializer(assignment); | 621 listener.endInitializer(assignment); |
| 564 } | 622 } |
| 565 return token; | 623 return token; |
| 566 } | 624 } |
| 567 | 625 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 630 ('static' === value) || | 688 ('static' === value) || |
| 631 ('external' === value); | 689 ('external' === value); |
| 632 } | 690 } |
| 633 | 691 |
| 634 Token parseModifier(Token token) { | 692 Token parseModifier(Token token) { |
| 635 assert(isModifier(token)); | 693 assert(isModifier(token)); |
| 636 listener.handleModifier(token); | 694 listener.handleModifier(token); |
| 637 return token.next; | 695 return token.next; |
| 638 } | 696 } |
| 639 | 697 |
| 698 void parseModifierList(Link<Token> tokens) { | |
| 699 int count = 0; | |
| 700 for (; !tokens.isEmpty(); tokens = tokens.tail) { | |
| 701 Token token = tokens.head; | |
| 702 if (isModifier(token)) { | |
| 703 parseModifier(token); | |
| 704 } else { | |
| 705 listener.unexpected(token); | |
| 706 } | |
| 707 count++; | |
| 708 } | |
| 709 listener.handleModifiers(count); | |
| 710 } | |
| 711 | |
| 640 Token parseModifiers(Token token) { | 712 Token parseModifiers(Token token) { |
| 641 int count = 0; | 713 int count = 0; |
| 642 while (token.kind === KEYWORD_TOKEN) { | 714 while (token.kind === KEYWORD_TOKEN) { |
| 643 if (!isModifier(token)) | 715 if (!isModifier(token)) |
| 644 break; | 716 break; |
| 645 token = parseModifier(token); | 717 token = parseModifier(token); |
| 646 count++; | 718 count++; |
| 647 } | 719 } |
| 648 listener.handleModifiers(count); | 720 listener.handleModifiers(count); |
| 649 return token; | 721 return token; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 698 } | 770 } |
| 699 listener.endClassBody(count, begin, token); | 771 listener.endClassBody(count, begin, token); |
| 700 return token; | 772 return token; |
| 701 } | 773 } |
| 702 | 774 |
| 703 bool isGetOrSet(Token token) { | 775 bool isGetOrSet(Token token) { |
| 704 final String value = token.stringValue; | 776 final String value = token.stringValue; |
| 705 return (value === 'get') || (value === 'set'); | 777 return (value === 'get') || (value === 'set'); |
| 706 } | 778 } |
| 707 | 779 |
| 708 Token findGetOrSet(Token token) { | |
| 709 if (isGetOrSet(token)) { | |
| 710 if (optional('<', token.next)) { | |
| 711 // For example: get<T> ... | |
| 712 final Token peek = peekAfterExpectedType(token); | |
| 713 if (isGetOrSet(peek) && isIdentifier(peek.next)) { | |
| 714 // For example: get<T> get identifier | |
| 715 return peek; | |
| 716 } | |
| 717 } else { | |
| 718 // For example: get ... | |
| 719 if (isGetOrSet(token.next) && isIdentifier(token.next.next)) { | |
| 720 // For example: get get identifier | |
| 721 return token.next; | |
| 722 } else { | |
| 723 // For example: get identifier | |
| 724 return token; | |
| 725 } | |
| 726 } | |
| 727 } else if (token.stringValue !== 'operator') { | |
| 728 final Token peek = peekAfterExpectedType(token); | |
| 729 if (isGetOrSet(peek) && isIdentifier(peek.next)) { | |
| 730 // type? get identifier | |
| 731 return peek; | |
| 732 } | |
| 733 } | |
| 734 return null; | |
| 735 } | |
| 736 | |
| 737 Token parseMember(Token token) { | 780 Token parseMember(Token token) { |
| 738 token = parseMetadataStar(token); | 781 token = parseMetadataStar(token); |
| 739 String value = token.stringValue; | 782 String value = token.stringValue; |
| 740 if (value === 'factory' || | 783 if (value === 'factory' || |
| 741 (value === 'external' && optional('factory', token.next))) { | 784 (value === 'external' && optional('factory', token.next))) { |
| 742 return parseFactoryMethod(token); | 785 return parseFactoryMethod(token); |
| 743 } | 786 } |
| 744 Token start = token; | 787 Token start = token; |
| 745 listener.beginMember(token); | 788 listener.beginMember(token); |
| 746 token = parseModifiers(token); | 789 |
| 747 Token getOrSet = findGetOrSet(token); | 790 Link<Token> identifiers = findMemberName(token); |
| 748 if (token === getOrSet) token = token.next; | 791 if (identifiers.isEmpty()) { |
| 749 Token peek = peekAfterExpectedType(token); | 792 return listener.unexpected(start); |
| 750 if (isIdentifier(peek) && token.stringValue !== 'operator') { | |
| 751 // Skip type. | |
| 752 token = peek; | |
| 753 } | 793 } |
| 754 if (token === getOrSet) token = token.next; | 794 Token name = identifiers.head; |
| 755 if (optional('operator', token)) { | 795 identifiers = identifiers.tail; |
| 756 token = parseOperatorName(token); | 796 if (!identifiers.isEmpty()) { |
| 797 if (optional('operator', identifiers.head)) { | |
| 798 name = identifiers.head; | |
| 799 identifiers = identifiers.tail; | |
| 800 } | |
| 801 } | |
| 802 Token getOrSet; | |
| 803 if (!identifiers.isEmpty()) { | |
| 804 if (isGetOrSet(identifiers.head)) { | |
| 805 getOrSet = identifiers.head; | |
| 806 identifiers = identifiers.tail; | |
| 807 } | |
| 808 } | |
| 809 Token type; | |
| 810 if (!identifiers.isEmpty()) { | |
| 811 if (isValidTypeReference(identifiers.head)) { | |
| 812 type = identifiers.head; | |
| 813 identifiers = identifiers.tail; | |
| 814 } | |
| 815 } | |
| 816 parseModifierList(identifiers.reverse()); | |
| 817 if (type === null) { | |
| 818 listener.handleNoType(token); | |
| 757 } else { | 819 } else { |
| 758 token = parseIdentifier(token); | 820 parseReturnTypeOpt(type); |
| 821 } | |
| 822 | |
| 823 if (optional('operator', name)) { | |
| 824 token = parseOperatorName(name); | |
| 825 } else { | |
| 826 token = parseIdentifier(name); | |
| 759 } | 827 } |
| 760 bool isField; | 828 bool isField; |
| 761 while (true) { | 829 while (true) { |
| 762 // Loop to allow the listener to rewrite the token stream for | 830 // Loop to allow the listener to rewrite the token stream for |
| 763 // error handling. | 831 // error handling. |
| 764 final String value = token.stringValue; | 832 final String value = token.stringValue; |
| 765 if ((value === '(') || (value === '.') || (value === '{') || | 833 if ((value === '(') || (value === '.') || (value === '{') || |
| 766 (value === '=>')) { | 834 (value === '=>')) { |
| 767 isField = false; | 835 isField = false; |
| 768 break; | 836 break; |
| (...skipping 1193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1962 } | 2030 } |
| 1963 listener.handleContinueStatement(hasTarget, continueKeyword, token); | 2031 listener.handleContinueStatement(hasTarget, continueKeyword, token); |
| 1964 return expectSemicolon(token); | 2032 return expectSemicolon(token); |
| 1965 } | 2033 } |
| 1966 | 2034 |
| 1967 Token parseEmptyStatement(Token token) { | 2035 Token parseEmptyStatement(Token token) { |
| 1968 listener.handleEmptyStatement(token); | 2036 listener.handleEmptyStatement(token); |
| 1969 return expectSemicolon(token); | 2037 return expectSemicolon(token); |
| 1970 } | 2038 } |
| 1971 } | 2039 } |
| OLD | NEW |