| 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 interface Scanner { | 5 interface Scanner { |
| 6 Token tokenize(); | 6 Token tokenize(); |
| 7 } | 7 } |
| 8 | 8 |
| 9 /** | 9 /** |
| 10 * Common base class for a Dart scanner. | 10 * Common base class for a Dart scanner. |
| 11 */ | 11 */ |
| 12 class AbstractScanner<T extends SourceString> implements Scanner { | 12 class AbstractScanner<T extends SourceString> implements Scanner { |
| 13 abstract int advance(); | 13 abstract int advance(); |
| 14 abstract int nextByte(); | 14 abstract int nextByte(); |
| 15 |
| 16 /** |
| 17 * Returns the current character or byte depending on the underlying input |
| 18 * kind. For example, [StringScanner] operates on [String] and thus returns |
| 19 * characters (Unicode codepoints represented as int) whereas |
| 20 * [ByteArrayScanner] operates on byte arrays and thus returns bytes. |
| 21 */ |
| 15 abstract int peek(); | 22 abstract int peek(); |
| 23 |
| 24 /** |
| 25 * Appends a fixed token based on whether the current char is [choice] or not. |
| 26 * If the current char is [choice] a fixed token whose kind and content |
| 27 * is determined by [yes] is appended, otherwise a fixed token whose kind |
| 28 * and content is determined by [no] is appended. |
| 29 */ |
| 16 abstract int select(int choice, PrecedenceInfo yes, PrecedenceInfo no); | 30 abstract int select(int choice, PrecedenceInfo yes, PrecedenceInfo no); |
| 31 |
| 32 /** |
| 33 * Appends a fixed token whose kind and content is determined by [info]. |
| 34 */ |
| 17 abstract void appendPrecedenceToken(PrecedenceInfo info); | 35 abstract void appendPrecedenceToken(PrecedenceInfo info); |
| 36 |
| 37 /** |
| 38 * Appends a token whose kind is determined by [info] and content is [value]. |
| 39 */ |
| 18 abstract void appendStringToken(PrecedenceInfo info, String value); | 40 abstract void appendStringToken(PrecedenceInfo info, String value); |
| 41 |
| 42 /** |
| 43 * Appends a token whose kind is determined by [info] and content is defined |
| 44 * by the SourceString [value]. |
| 45 */ |
| 19 abstract void appendByteStringToken(PrecedenceInfo info, T value); | 46 abstract void appendByteStringToken(PrecedenceInfo info, T value); |
| 47 |
| 48 /** |
| 49 * Appends a keyword token whose kind is determined by [keyword]. |
| 50 */ |
| 20 abstract void appendKeywordToken(Keyword keyword); | 51 abstract void appendKeywordToken(Keyword keyword); |
| 21 abstract void appendWhiteSpace(int next); | 52 abstract void appendWhiteSpace(int next); |
| 22 abstract void appendEofToken(); | 53 abstract void appendEofToken(); |
| 54 |
| 55 /** |
| 56 * Creates an ASCII SourceString whose content begins at the source byte |
| 57 * offset [start] and ends at [offset] bytes from the current byte offset of |
| 58 * the scanner. For example, if the current byte offset is 10, |
| 59 * [:asciiString(0,-1):] creates an ASCII SourceString whose content is found |
| 60 * at the [0,9[ byte interval of the source text. |
| 61 */ |
| 23 abstract T asciiString(int start, int offset); | 62 abstract T asciiString(int start, int offset); |
| 24 abstract T utf8String(int start, int offset); | 63 abstract T utf8String(int start, int offset); |
| 25 abstract Token firstToken(); | 64 abstract Token firstToken(); |
| 26 abstract Token previousToken(); | 65 abstract Token previousToken(); |
| 27 abstract void beginToken(); | 66 abstract void beginToken(); |
| 28 abstract void addToCharOffset(int offset); | 67 abstract void addToCharOffset(int offset); |
| 29 abstract int get charOffset(); | 68 abstract int get charOffset(); |
| 30 abstract int get byteOffset(); | 69 abstract int get byteOffset(); |
| 31 abstract void appendBeginGroup(PrecedenceInfo info, String value); | 70 abstract void appendBeginGroup(PrecedenceInfo info, String value); |
| 32 abstract int appendEndGroup(PrecedenceInfo info, String value, int openKind); | 71 abstract int appendEndGroup(PrecedenceInfo info, String value, int openKind); |
| 33 abstract void appendGt(PrecedenceInfo info, String value); | 72 abstract void appendGt(PrecedenceInfo info, String value); |
| 34 abstract void appendGtGt(PrecedenceInfo info, String value); | 73 abstract void appendGtGt(PrecedenceInfo info, String value); |
| 35 abstract void appendGtGtGt(PrecedenceInfo info, String value); | 74 abstract void appendGtGtGt(PrecedenceInfo info, String value); |
| 75 abstract void appendComment(); |
| 36 | 76 |
| 37 /** | 77 /** |
| 38 * We call this method to discard '<' from the "grouping" stack | 78 * We call this method to discard '<' from the "grouping" stack |
| 39 * (maintained by subclasses). | 79 * (maintained by subclasses). |
| 40 * | 80 * |
| 41 * [PartialParser.skipExpression] relies on the fact that we do not | 81 * [PartialParser.skipExpression] relies on the fact that we do not |
| 42 * create groups for stuff like: | 82 * create groups for stuff like: |
| 43 * [:a = b < c, d = e > f:]. | 83 * [:a = b < c, d = e > f:]. |
| 44 * | 84 * |
| 45 * In other words, this method is called when the scanner recognizes | 85 * In other words, this method is called when the scanner recognizes |
| (...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 536 } else { | 576 } else { |
| 537 appendPrecedenceToken(SLASH_INFO); | 577 appendPrecedenceToken(SLASH_INFO); |
| 538 return next; | 578 return next; |
| 539 } | 579 } |
| 540 } | 580 } |
| 541 | 581 |
| 542 int tokenizeSingleLineComment(int next) { | 582 int tokenizeSingleLineComment(int next) { |
| 543 while (true) { | 583 while (true) { |
| 544 next = advance(); | 584 next = advance(); |
| 545 if ($LF === next || $CR === next || $EOF === next) { | 585 if ($LF === next || $CR === next || $EOF === next) { |
| 586 appendComment(); |
| 546 return next; | 587 return next; |
| 547 } | 588 } |
| 548 } | 589 } |
| 549 } | 590 } |
| 550 | 591 |
| 551 int tokenizeMultiLineComment(int next) { | 592 int tokenizeMultiLineComment(int next) { |
| 552 int nesting = 1; | 593 int nesting = 1; |
| 553 next = advance(); | 594 next = advance(); |
| 554 while (true) { | 595 while (true) { |
| 555 if ($EOF === next) { | 596 if ($EOF === next) { |
| 556 // TODO(ahe): Report error. | 597 // TODO(ahe): Report error. |
| 557 return next; | 598 return next; |
| 558 } else if ($STAR === next) { | 599 } else if ($STAR === next) { |
| 559 next = advance(); | 600 next = advance(); |
| 560 if ($SLASH === next) { | 601 if ($SLASH === next) { |
| 561 --nesting; | 602 --nesting; |
| 562 if (0 === nesting) { | 603 if (0 === nesting) { |
| 563 return advance(); | 604 next = advance(); |
| 605 appendComment(); |
| 606 return next; |
| 564 } else { | 607 } else { |
| 565 next = advance(); | 608 next = advance(); |
| 566 } | 609 } |
| 567 } | 610 } |
| 568 } else if ($SLASH === next) { | 611 } else if ($SLASH === next) { |
| 569 next = advance(); | 612 next = advance(); |
| 570 if ($STAR === next) { | 613 if ($STAR === next) { |
| 571 next = advance(); | 614 next = advance(); |
| 572 ++nesting; | 615 ++nesting; |
| 573 } | 616 } |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 throw new MalformedInputException("unterminated string literal", | 722 throw new MalformedInputException("unterminated string literal", |
| 680 charOffset); | 723 charOffset); |
| 681 } | 724 } |
| 682 next = advance(); | 725 next = advance(); |
| 683 } | 726 } |
| 684 appendByteStringToken(STRING_INFO, utf8String(start, 0)); | 727 appendByteStringToken(STRING_INFO, utf8String(start, 0)); |
| 685 return advance(); | 728 return advance(); |
| 686 } | 729 } |
| 687 | 730 |
| 688 int tokenizeStringInterpolation(int start) { | 731 int tokenizeStringInterpolation(int start) { |
| 689 beginToken(); | 732 appendByteStringToken(STRING_INFO, utf8String(start, -1)); |
| 733 beginToken(); // $ starts here. |
| 690 int next = advance(); | 734 int next = advance(); |
| 691 if (next === $OPEN_CURLY_BRACKET) { | 735 if (next === $OPEN_CURLY_BRACKET) { |
| 692 return tokenizeInterpolatedExpression(next, start); | 736 return tokenizeInterpolatedExpression(next, start); |
| 693 } else { | 737 } else { |
| 694 return tokenizeInterpolatedIdentifier(next, start); | 738 return tokenizeInterpolatedIdentifier(next, start); |
| 695 } | 739 } |
| 696 } | 740 } |
| 697 | 741 |
| 698 int tokenizeInterpolatedExpression(int next, int start) { | 742 int tokenizeInterpolatedExpression(int next, int start) { |
| 699 appendByteStringToken(STRING_INFO, utf8String(start, -2)); | |
| 700 appendBeginGroup(STRING_INTERPOLATION_INFO, "\${"); | 743 appendBeginGroup(STRING_INTERPOLATION_INFO, "\${"); |
| 744 beginToken(); // The expression starts here. |
| 701 next = advance(); | 745 next = advance(); |
| 702 while (next !== $EOF && next !== $STX) { | 746 while (next !== $EOF && next !== $STX) { |
| 703 next = bigSwitch(next); | 747 next = bigSwitch(next); |
| 704 } | 748 } |
| 705 if (next === $EOF) return next; | 749 if (next === $EOF) return next; |
| 706 return advance(); | 750 next = advance(); |
| 751 beginToken(); // The string interpolation suffix starts here. |
| 752 return next; |
| 707 } | 753 } |
| 708 | 754 |
| 709 int tokenizeInterpolatedIdentifier(int next, int start) { | 755 int tokenizeInterpolatedIdentifier(int next, int start) { |
| 710 appendByteStringToken(STRING_INFO, utf8String(start, -2)); | 756 appendPrecedenceToken(STRING_INTERPOLATION_IDENTIFIER_INFO); |
| 711 appendBeginGroup(STRING_INTERPOLATION_INFO, "\${"); | 757 beginToken(); // The identifier starts here. |
| 712 next = tokenizeKeywordOrIdentifier(next, false); | 758 next = tokenizeKeywordOrIdentifier(next, false); |
| 713 appendEndGroup(CLOSE_CURLY_BRACKET_INFO, "}", OPEN_CURLY_BRACKET_TOKEN); | 759 beginToken(); // The string interpolation suffix starts here. |
| 714 return next; | 760 return next; |
| 715 } | 761 } |
| 716 | 762 |
| 717 int tokenizeSingleLineRawString(int next, int quoteChar, int start) { | 763 int tokenizeSingleLineRawString(int next, int quoteChar, int start) { |
| 718 next = advance(); | 764 next = advance(); |
| 719 while (next != $EOF) { | 765 while (next != $EOF) { |
| 720 if (next === quoteChar) { | 766 if (next === quoteChar) { |
| 721 appendByteStringToken(STRING_INFO, utf8String(start, 0)); | 767 appendByteStringToken(STRING_INFO, utf8String(start, 0)); |
| 722 return advance(); | 768 return advance(); |
| 723 } else if (next === $LF || next === $CR) { | 769 } else if (next === $LF || next === $CR) { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 780 charOffset); | 826 charOffset); |
| 781 } | 827 } |
| 782 } | 828 } |
| 783 | 829 |
| 784 class MalformedInputException { | 830 class MalformedInputException { |
| 785 final String message; | 831 final String message; |
| 786 final position; | 832 final position; |
| 787 MalformedInputException(this.message, this.position); | 833 MalformedInputException(this.message, this.position); |
| 788 toString() => message; | 834 toString() => message; |
| 789 } | 835 } |
| OLD | NEW |