| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 Visitor<R> { | 5 interface Visitor<R> { |
| 6 R visitBlock(Block node); | 6 R visitBlock(Block node); |
| 7 R visitBreakStatement(BreakStatement node); | 7 R visitBreakStatement(BreakStatement node); |
| 8 R visitCatchBlock(CatchBlock node); | 8 R visitCatchBlock(CatchBlock node); |
| 9 R visitClassNode(ClassNode node); | 9 R visitClassNode(ClassNode node); |
| 10 R visitConditional(Conditional node); | 10 R visitConditional(Conditional node); |
| (...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 651 const StringQuoting(this.quote, [bool raw, bool multiline]) | 651 const StringQuoting(this.quote, [bool raw, bool multiline]) |
| 652 : this.raw = raw, this.multiline = multiline; | 652 : this.raw = raw, this.multiline = multiline; |
| 653 String get quoteChar() => quote === $DQ ? '"' : "'"; | 653 String get quoteChar() => quote === $DQ ? '"' : "'"; |
| 654 | 654 |
| 655 int get leftQuoteLength() => (raw ? 1 : 0) + (multiline ? 3 : 1); | 655 int get leftQuoteLength() => (raw ? 1 : 0) + (multiline ? 3 : 1); |
| 656 int get rightQuoteLength() => multiline ? 3 : 1; | 656 int get rightQuoteLength() => multiline ? 3 : 1; |
| 657 static StringQuoting get(int quote, bool raw, bool multiline) => | 657 static StringQuoting get(int quote, bool raw, bool multiline) => |
| 658 mapping[(raw ? 1 : 0) + (multiline ? 2 : 0) + (quote === $SQ ? 4 : 0)]; | 658 mapping[(raw ? 1 : 0) + (multiline ? 2 : 0) + (quote === $SQ ? 4 : 0)]; |
| 659 } | 659 } |
| 660 | 660 |
| 661 |
| 662 class DartString implements Iterable<int> { |
| 663 factory DartString.literal(String string) => new LiteralDartString(string); |
| 664 factory DartString.rawString(SourceString source, int length) => |
| 665 new RawSourceDartString(source, length); |
| 666 factory DartString.escapedString(SourceString source, int length) => |
| 667 new EscapedSourceDartString(source, length); |
| 668 DartString(); |
| 669 abstract int get length(); |
| 670 bool isEmpty() => length == 0; |
| 671 // TODO(lrn): Is this test too expensive? |
| 672 bool definitlyEquals(DartString other) => toString() == other.toString(); |
| 673 abstract String toString(); |
| 674 } |
| 675 |
| 676 class LiteralDartString extends DartString { |
| 677 final String string; |
| 678 LiteralDartString(this.string); |
| 679 int get length() => string.length; |
| 680 Iterator<int> iterator() => new StringCodeIterator(string); |
| 681 String toString() => string; |
| 682 } |
| 683 |
| 684 class SourceBasedDartString extends DartString { |
| 685 String toStringCache = null; |
| 686 final SourceString source; |
| 687 final int length; |
| 688 SourceBasedDartString(this.source, this.length); |
| 689 } |
| 690 |
| 691 class RawSourceDartString extends SourceBasedDartString { |
| 692 RawSourceDartString(source, length) : super(source, length); |
| 693 Iterator<int> iterator() => source.iterator(); |
| 694 String toString() { |
| 695 if (toStringCache !== null) return toStringCache; |
| 696 toStringCache = source.stringValue; |
| 697 return toStringCache; |
| 698 } |
| 699 } |
| 700 |
| 701 class EscapedSourceDartString extends SourceBasedDartString { |
| 702 EscapedSourceDartString(source, length) : super(source, length); |
| 703 Iterator<int> iterator() { |
| 704 if (toStringCache !== null) return new StringCodeIterator(toStringCache); |
| 705 return new StringEscapeIterator(source); |
| 706 } |
| 707 String toString() { |
| 708 if (toStringCache !== null) return toStringCache; |
| 709 StringBuffer buffer = new StringBuffer(); |
| 710 StringEscapeIterator iterator = new StringEscapeIterator(source); |
| 711 while (iterator.hasNext()) { |
| 712 buffer.add(new String.fromCharCodes(<int>[iterator.next()])); |
| 713 } |
| 714 toStringCache = buffer.toString(); |
| 715 return toStringCache; |
| 716 } |
| 717 } |
| 718 |
| 719 |
| 661 /** | 720 /** |
| 662 * A wrapper around a SourceString that stores extra information about | 721 *Iterator that returns the actual string contents of a string with escapes. |
| 663 * the (potentially implicit) quoting style of the original string. | |
| 664 * For most strings, the quotes are included in the [source], but | |
| 665 * parts of strings from a string interpolation might be missing one or | |
| 666 * both quotes. | |
| 667 */ | 722 */ |
| 668 class QuotedString { | 723 class StringEscapeIterator implements Iterator<int>{ |
| 669 // A source-backed string literal without the quotes. | 724 final Iterator<int> source; |
| 670 final SourceString source; | 725 StringEscapeIterator(SourceString source) : this.source = source.iterator(); |
| 671 // The quoting style of the original string literal. | 726 bool hasNext() => source.hasNext(); |
| 672 // Whether it's raw or multi-line impacts the interpretation of | 727 int next() { |
| 673 // the string literal content. Whether it's single- or double-quoted | 728 int code = source.next(); |
| 674 // is only used as a hint later. | 729 if (code !== $BACKSLASH) { |
| 675 final StringQuoting quoting; | 730 return code; |
| 676 /** Actual length of the corresponding, parsed, Dart string */ | 731 } |
| 677 final int length; | 732 code = source.next(); |
| 678 | 733 if (code === $n) return $LF; |
| 679 const QuotedString(this.source, this.quoting, this.length); | 734 if (code === $r) return $CR; |
| 680 /** | 735 if (code === $t) return $TAB; |
| 681 * Construct a [QuotedString] containing exactly the given string. | 736 if (code === $b) return $BS; |
| 682 * The choice of quoting ensures that all characters of the original | 737 if (code === $f) return $FF; |
| 683 * string are valid and has their exact meaning. | 738 if (code === $v) return $VTAB; |
| 684 */ | 739 if (code === $x) { |
| 685 QuotedString.literal(String string) | 740 int value = hexDigitValue(source.next()); |
| 686 : source = new SourceString(string), | 741 value = value * 16 + hexDigitValue(source.next()); |
| 687 quoting = StringQuoting.RAW_MULTILINE_DQ, | 742 return value; |
| 688 length = string.length; | 743 } |
| 689 | 744 if (code === $u) { |
| 690 bool isEmpty() => source.isEmpty(); | 745 int value = 0; |
| 691 Iterator<int> iterator() => source.iterator(); | 746 code = source.next(); |
| 692 | 747 if (code === $OPEN_CURLY_BRACKET) { |
| 693 bool definitlyEquals(QuotedString other) { | 748 for (code = source.next(); |
| 694 return source === other.source && quoting === other.quoting; | 749 code != $CLOSE_CURLY_BRACKET; |
| 750 code = source.next()) { |
| 751 value = value * 16 + hexDigitValue(code); |
| 752 } |
| 753 return value; |
| 754 } |
| 755 // Four digit hex value. |
| 756 value = hexDigitValue(code); |
| 757 for (int i = 0; i < 3; i++) { |
| 758 code = source.next(); |
| 759 value = value * 16 + hexDigitValue(code); |
| 760 } |
| 761 return value; |
| 762 } |
| 763 return code; |
| 695 } | 764 } |
| 696 } | 765 } |
| 697 | 766 |
| 698 | 767 |
| 699 class LiteralString extends Literal<SourceString> { | 768 class LiteralString extends Literal<SourceString> { |
| 700 /** Set on validated string literals. */ | 769 /** Set on validated string literals. */ |
| 701 final QuotedString quotedString = null; | 770 final DartString dartString = null; |
| 702 | 771 |
| 703 LiteralString(Token token, this.quotedString) : super(token, null); | 772 LiteralString(Token token, this.dartString) : super(token, null); |
| 704 | 773 |
| 705 LiteralString asLiteralString() => this; | 774 LiteralString asLiteralString() => this; |
| 706 | 775 |
| 707 bool isValidated() => quotedString !== null; | 776 bool isValidated() => dartString !== null; |
| 708 | 777 |
| 709 SourceString get value() => token.value; | 778 SourceString get value() => token.value; |
| 710 | 779 |
| 711 accept(Visitor visitor) => visitor.visitLiteralString(this); | 780 accept(Visitor visitor) => visitor.visitLiteralString(this); |
| 712 } | 781 } |
| 713 | 782 |
| 714 class LiteralNull extends Literal<SourceString> { | 783 class LiteralNull extends Literal<SourceString> { |
| 715 LiteralNull(Token token) : super(token, null); | 784 LiteralNull(Token token) : super(token, null); |
| 716 | 785 |
| 717 LiteralNull asLiteralNull() => this; | 786 LiteralNull asLiteralNull() => this; |
| (...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1344 | 1413 |
| 1345 visitChildren(Visitor visitor) { | 1414 visitChildren(Visitor visitor) { |
| 1346 formals.accept(visitor); | 1415 formals.accept(visitor); |
| 1347 block.accept(visitor); | 1416 block.accept(visitor); |
| 1348 } | 1417 } |
| 1349 | 1418 |
| 1350 Token getBeginToken() => catchKeyword; | 1419 Token getBeginToken() => catchKeyword; |
| 1351 | 1420 |
| 1352 Token getEndToken() => block.getEndToken(); | 1421 Token getEndToken() => block.getEndToken(); |
| 1353 } | 1422 } |
| OLD | NEW |