Chromium Code Reviews| 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); |
| 11 R visitContinueStatement(ContinueStatement node); | 11 R visitContinueStatement(ContinueStatement node); |
| 12 R visitDoWhile(DoWhile node); | 12 R visitDoWhile(DoWhile node); |
| 13 R visitEmptyStatement(EmptyStatement node); | 13 R visitEmptyStatement(EmptyStatement node); |
| 14 R visitExpressionStatement(ExpressionStatement node); | 14 R visitExpressionStatement(ExpressionStatement node); |
| 15 R visitFor(For node); | 15 R visitFor(For node); |
| 16 R visitForInStatement(ForInStatement node); | 16 R visitForInStatement(ForInStatement node); |
| 17 R visitFunctionDeclaration(FunctionDeclaration node); | 17 R visitFunctionDeclaration(FunctionDeclaration node); |
| 18 R visitFunctionExpression(FunctionExpression node); | 18 R visitFunctionExpression(FunctionExpression node); |
| 19 R visitIdentifier(Identifier node); | 19 R visitIdentifier(Identifier node); |
| 20 R visitIf(If node); | 20 R visitIf(If node); |
| 21 R visitLabeledStatement(LabeledStatement node); | 21 R visitLabeledStatement(LabeledStatement node); |
| 22 R visitLiteralBool(LiteralBool node); | 22 R visitLiteralBool(LiteralBool node); |
| 23 R visitLiteralDouble(LiteralDouble node); | 23 R visitLiteralDouble(LiteralDouble node); |
| 24 R visitLiteralInt(LiteralInt node); | 24 R visitLiteralInt(LiteralInt node); |
| 25 R visitLiteralList(LiteralList node); | 25 R visitLiteralList(LiteralList node); |
| 26 R visitLiteralMap(LiteralMap node); | 26 R visitLiteralMap(LiteralMap node); |
| 27 R visitLiteralMapEntry(LiteralMapEntry node); | 27 R visitLiteralMapEntry(LiteralMapEntry node); |
| 28 R visitLiteralNull(LiteralNull node); | 28 R visitLiteralNull(LiteralNull node); |
| 29 R visitLiteralString(LiteralString node); | 29 R visitLiteralString(LiteralString node); |
| 30 R visitLiteralStringJuxtaposition(LiteralStringJuxtaposition node); | 30 R visitStringJuxtaposition(StringJuxtaposition node); |
| 31 R visitModifiers(Modifiers node); | 31 R visitModifiers(Modifiers node); |
| 32 R visitNamedArgument(NamedArgument node); | 32 R visitNamedArgument(NamedArgument node); |
| 33 R visitNewExpression(NewExpression node); | 33 R visitNewExpression(NewExpression node); |
| 34 R visitNodeList(NodeList node); | 34 R visitNodeList(NodeList node); |
| 35 R visitOperator(Operator node); | 35 R visitOperator(Operator node); |
| 36 R visitParenthesizedExpression(ParenthesizedExpression node); | 36 R visitParenthesizedExpression(ParenthesizedExpression node); |
| 37 R visitReturn(Return node); | 37 R visitReturn(Return node); |
| 38 R visitScriptTag(ScriptTag node); | 38 R visitScriptTag(ScriptTag node); |
| 39 R visitSend(Send node); | 39 R visitSend(Send node); |
| 40 R visitSendSet(SendSet node); | 40 R visitSendSet(SendSet node); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 129 NodeList asNodeList() => null; | 129 NodeList asNodeList() => null; |
| 130 Operator asOperator() => null; | 130 Operator asOperator() => null; |
| 131 ParenthesizedExpression asParenthesizedExpression() => null; | 131 ParenthesizedExpression asParenthesizedExpression() => null; |
| 132 Return asReturn() => null; | 132 Return asReturn() => null; |
| 133 ScriptTag asScriptTag() => null; | 133 ScriptTag asScriptTag() => null; |
| 134 Send asSend() => null; | 134 Send asSend() => null; |
| 135 SendSet asSendSet() => null; | 135 SendSet asSendSet() => null; |
| 136 Statement asStatement() => null; | 136 Statement asStatement() => null; |
| 137 StringInterpolation asStringInterpolation() => null; | 137 StringInterpolation asStringInterpolation() => null; |
| 138 StringInterpolationPart asStringInterpolationPart() => null; | 138 StringInterpolationPart asStringInterpolationPart() => null; |
| 139 StringJuxtaposition asStringJuxtaposition() => null; | |
| 139 SwitchCase asSwitchCase() => null; | 140 SwitchCase asSwitchCase() => null; |
| 140 SwitchStatement asSwitchStatement() => null; | 141 SwitchStatement asSwitchStatement() => null; |
| 141 Throw asThrow() => null; | 142 Throw asThrow() => null; |
| 142 TryStatement asTryStatement() => null; | 143 TryStatement asTryStatement() => null; |
| 143 TypeAnnotation asTypeAnnotation() => null; | 144 TypeAnnotation asTypeAnnotation() => null; |
| 144 Typedef asTypedef() => null; | 145 Typedef asTypedef() => null; |
| 145 VariableDefinitions asVariableDefinitions() => null; | 146 VariableDefinitions asVariableDefinitions() => null; |
| 146 While asWhile() => null; | 147 While asWhile() => null; |
| 147 | 148 |
| 148 bool isValidBreakTarget() => false; | 149 bool isValidBreakTarget() => false; |
| (...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 721 | 722 |
| 722 int get leftQuoteLength() => (raw ? 1 : 0) + leftQuoteCharCount; | 723 int get leftQuoteLength() => (raw ? 1 : 0) + leftQuoteCharCount; |
| 723 int get rightQuoteLength() => (leftQuoteCharCount > 2) ? 3 : 1; | 724 int get rightQuoteLength() => (leftQuoteCharCount > 2) ? 3 : 1; |
| 724 static StringQuoting getQuoting(int quote, bool raw, int quoteLength) { | 725 static StringQuoting getQuoting(int quote, bool raw, int quoteLength) { |
| 725 int index = quoteLength - 1; | 726 int index = quoteLength - 1; |
| 726 if (quoteLength > 2) index -= 1; | 727 if (quoteLength > 2) index -= 1; |
| 727 return mapping[(raw ? 1 : 0) + index * 2 + (quote === $SQ ? 8 : 0)]; | 728 return mapping[(raw ? 1 : 0) + index * 2 + (quote === $SQ ? 8 : 0)]; |
| 728 } | 729 } |
| 729 } | 730 } |
| 730 | 731 |
| 731 class DartString implements Iterable<int> { | |
| 732 // This is a convenience constructor. If you need a const literal DartString, | |
| 733 // use [const LiteralDartString(string)] directly. | |
| 734 factory DartString.literal(String string) => new LiteralDartString(string); | |
| 735 factory DartString.rawString(SourceString source, int length) => | |
| 736 new RawSourceDartString(source, length); | |
| 737 factory DartString.escapedString(SourceString source, int length) => | |
| 738 new EscapedSourceDartString(source, length); | |
| 739 const DartString(); | |
| 740 abstract int get length(); | |
| 741 bool isEmpty() => length == 0; | |
| 742 abstract Iterator<int> iterator(); | |
| 743 abstract String slowToString(); | |
| 744 | |
| 745 bool operator ==(var other) { | |
| 746 if (other is !DartString) return false; | |
| 747 DartString otherString = other; | |
| 748 if (length != otherString.length) return false; | |
| 749 Iterator it1 = iterator(); | |
| 750 Iterator it2 = otherString.iterator(); | |
| 751 while (it1.hasNext()) { | |
| 752 if (it1.next() != it2.next()) return false; | |
| 753 } | |
| 754 return true; | |
| 755 } | |
| 756 String toString() => "DartString#${length}:${slowToString()}"; | |
| 757 abstract SourceString get source(); | |
| 758 } | |
| 759 | |
| 760 class LiteralDartString extends DartString { | |
| 761 final String string; | |
| 762 const LiteralDartString(this.string); | |
| 763 int get length() => string.length; | |
| 764 Iterator<int> iterator() => new StringCodeIterator(string); | |
| 765 String slowToString() => string; | |
| 766 SourceString get source() => new StringWrapper(string); | |
| 767 } | |
| 768 | |
| 769 class SourceBasedDartString extends DartString { | |
| 770 String toStringCache = null; | |
| 771 final SourceString source; | |
| 772 final int length; | |
| 773 SourceBasedDartString(this.source, this.length); | |
| 774 abstract Iterator<int> iterator(); | |
| 775 } | |
| 776 | |
| 777 class RawSourceDartString extends SourceBasedDartString { | |
| 778 RawSourceDartString(source, length) : super(source, length); | |
| 779 Iterator<int> iterator() => source.iterator(); | |
| 780 String slowToString() { | |
| 781 if (toStringCache !== null) return toStringCache; | |
| 782 toStringCache = source.slowToString(); | |
| 783 return toStringCache; | |
| 784 } | |
| 785 } | |
| 786 | |
| 787 class EscapedSourceDartString extends SourceBasedDartString { | |
| 788 EscapedSourceDartString(source, length) : super(source, length); | |
| 789 Iterator<int> iterator() { | |
| 790 if (toStringCache !== null) return new StringCodeIterator(toStringCache); | |
| 791 return new StringEscapeIterator(source); | |
| 792 } | |
| 793 String slowToString() { | |
| 794 if (toStringCache !== null) return toStringCache; | |
| 795 StringBuffer buffer = new StringBuffer(); | |
| 796 StringEscapeIterator it = new StringEscapeIterator(source); | |
| 797 while (it.hasNext()) { | |
| 798 buffer.addCharCode(it.next()); | |
| 799 } | |
| 800 toStringCache = buffer.toString(); | |
| 801 return toStringCache; | |
| 802 } | |
| 803 } | |
| 804 | |
| 805 class ConsDartString extends DartString { | |
| 806 final DartString left; | |
| 807 final DartString right; | |
| 808 final int length; | |
| 809 int hashCache = null; | |
| 810 String toStringCache; | |
| 811 ConsDartString(DartString left, DartString right) | |
| 812 : this.left = left, | |
| 813 this.right = right, | |
| 814 length = left.length + right.length; | |
| 815 | |
| 816 Iterator<int> iterator() => new ConsDartStringIterator(this); | |
| 817 | |
| 818 String slowToString() { | |
| 819 if (toStringCache !== null) return toStringCache; | |
| 820 toStringCache = left.slowToString().concat(right.slowToString()); | |
| 821 return toStringCache; | |
| 822 } | |
| 823 SourceString get source() => new StringWrapper(slowToString()); | |
| 824 } | |
| 825 | |
| 826 class ConsDartStringIterator implements Iterator<int> { | |
| 827 Iterator<int> current; | |
| 828 DartString right; | |
| 829 bool hasNextLookAhead; | |
| 830 ConsDartStringIterator(ConsDartString cons) | |
| 831 : current = cons.left.iterator(), | |
| 832 right = cons.right { | |
| 833 hasNextLookAhead = current.hasNext(); | |
| 834 if (!hasNextLookAhead) { | |
| 835 nextPart(); | |
| 836 } | |
| 837 } | |
| 838 bool hasNext() { | |
| 839 return hasNextLookAhead; | |
| 840 } | |
| 841 int next() { | |
| 842 assert(hasNextLookAhead); | |
| 843 int result = current.next(); | |
| 844 hasNextLookAhead = current.hasNext(); | |
| 845 if (!hasNextLookAhead) { | |
| 846 nextPart(); | |
| 847 } | |
| 848 return result; | |
| 849 } | |
| 850 void nextPart() { | |
| 851 if (right !== null) { | |
| 852 current = right.iterator(); | |
| 853 right = null; | |
| 854 hasNextLookAhead = current.hasNext(); | |
| 855 } | |
| 856 } | |
| 857 } | |
| 858 | |
| 859 /** | |
| 860 *Iterator that returns the actual string contents of a string with escapes. | |
| 861 */ | |
| 862 class StringEscapeIterator implements Iterator<int>{ | |
| 863 final Iterator<int> source; | |
| 864 StringEscapeIterator(SourceString source) : this.source = source.iterator(); | |
| 865 bool hasNext() => source.hasNext(); | |
| 866 int next() { | |
| 867 int code = source.next(); | |
| 868 if (code !== $BACKSLASH) { | |
| 869 return code; | |
| 870 } | |
| 871 code = source.next(); | |
| 872 if (code === $n) return $LF; | |
| 873 if (code === $r) return $CR; | |
| 874 if (code === $t) return $TAB; | |
| 875 if (code === $b) return $BS; | |
| 876 if (code === $f) return $FF; | |
| 877 if (code === $v) return $VTAB; | |
| 878 if (code === $x) { | |
| 879 int value = hexDigitValue(source.next()); | |
| 880 value = value * 16 + hexDigitValue(source.next()); | |
| 881 return value; | |
| 882 } | |
| 883 if (code === $u) { | |
| 884 int value = 0; | |
| 885 code = source.next(); | |
| 886 if (code === $OPEN_CURLY_BRACKET) { | |
| 887 for (code = source.next(); | |
| 888 code != $CLOSE_CURLY_BRACKET; | |
| 889 code = source.next()) { | |
| 890 value = value * 16 + hexDigitValue(code); | |
| 891 } | |
| 892 return value; | |
| 893 } | |
| 894 // Four digit hex value. | |
| 895 value = hexDigitValue(code); | |
| 896 for (int i = 0; i < 3; i++) { | |
| 897 code = source.next(); | |
| 898 value = value * 16 + hexDigitValue(code); | |
| 899 } | |
| 900 return value; | |
| 901 } | |
| 902 return code; | |
| 903 } | |
| 904 } | |
| 905 | |
| 906 | |
| 907 class LiteralString extends Literal<SourceString> { | 732 class LiteralString extends Literal<SourceString> { |
| 908 /** Set on validated string literals. */ | 733 /** Set on validated string literals. */ |
| 909 final DartString dartString = null; | 734 final DartString dartString = null; |
| 910 | 735 |
| 911 LiteralString(Token token, this.dartString) : super(token, null); | 736 LiteralString(Token token, this.dartString) : super(token, null); |
| 912 | 737 |
| 913 LiteralString asLiteralString() => this; | 738 LiteralString asLiteralString() => this; |
| 914 | 739 |
| 915 bool isValidated() => dartString !== null; | 740 bool isValidated() => dartString !== null; |
| 916 | 741 |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1255 visitChildren(Visitor visitor) { | 1080 visitChildren(Visitor visitor) { |
| 1256 expression.accept(visitor); | 1081 expression.accept(visitor); |
| 1257 string.accept(visitor); | 1082 string.accept(visitor); |
| 1258 } | 1083 } |
| 1259 | 1084 |
| 1260 Token getBeginToken() => expression.getBeginToken(); | 1085 Token getBeginToken() => expression.getBeginToken(); |
| 1261 | 1086 |
| 1262 Token getEndToken() => string.getEndToken(); | 1087 Token getEndToken() => string.getEndToken(); |
| 1263 } | 1088 } |
| 1264 | 1089 |
| 1265 class LiteralStringJuxtaposition extends LiteralString { | 1090 // A class representing juxtaposed string literals. |
|
ahe
2012/03/15 09:02:56
Documentation comment.
Lasse Reichstein Nielsen
2012/03/19 07:15:32
Done.
| |
| 1266 // List of either StringLiteral or StringInterpolation. | 1091 // The string literals can be both plain literals and string interpolations. |
| 1267 final Link<Expression> literals; | 1092 class StringJuxtaposition extends Expression { |
| 1093 Expression first; | |
| 1094 Expression second; | |
| 1095 final DartString dartString; | |
| 1096 // TODO(lrn): is this redundant? After parsing, dartString will be set unless | |
| 1097 // one of first or second is a string interpolation (because any non- | |
| 1098 // validating literal string would end after parsing). | |
| 1099 final bool isInterpolation; | |
|
ahe
2012/03/15 09:02:56
My guess: it is redundant! ;-)
Lasse Reichstein Nielsen
2012/03/19 07:15:32
Refactored to be not redundant.
| |
| 1268 | 1100 |
| 1269 LiteralStringJuxtaposition(Link<Expression> literals) | 1101 StringJuxtaposition(Expression first, Expression second) |
| 1270 : this.literals = literals, | 1102 : this.first = first, |
| 1271 super(literals.head.getBeginToken(), concatenateLiterals(literals)); | 1103 this.second = second, |
| 1104 this.dartString = concatenateLiterals(first, second), | |
|
ahe
2012/03/15 09:02:56
As a matter of principle, doing this much work in
Lasse Reichstein Nielsen
2012/03/19 07:15:32
I have made the computation of dartString and isIn
| |
| 1105 this.isInterpolation = isEitherInterpolation(first, second); | |
| 1272 | 1106 |
| 1273 static DartString concatenateLiterals(Link<Expression> literals) { | 1107 StringJuxtaposition asStringJuxtaposition() => this; |
| 1274 assert(!literals.isEmpty()); | 1108 |
| 1275 LiteralString literal = literals.head; | 1109 static DartString concatenateLiterals(Expression first, Expression second) { |
| 1276 if (literals.tail.isEmpty()) { | 1110 DartString firstDartString = first.accept(const GetDartStringVisitor()); |
| 1277 return literal.dartString; | 1111 if (firstDartString === null) return null; |
| 1278 } | 1112 DartString secondDartString = second.accept(const GetDartStringVisitor()); |
| 1279 return new ConsDartString(literal.dartString, | 1113 if (secondDartString === null) return null; |
| 1280 concatenateLiterals(literals.tail)); | 1114 return new DartString.concat(firstDartString, |
| 1115 secondDartString); | |
| 1281 } | 1116 } |
| 1282 | 1117 |
| 1283 SourceString get value() => null; | 1118 // Extract the string interpolations from the juxtaposed strings. |
| 1284 | 1119 static bool isEitherInterpolation(Expression first, Expression second) { |
| 1285 accept(Visitor visitor) => visitor.visitLiteralStringJuxtaposition(this); | 1120 return first.accept(const IsInterpolationVisitor()) |
| 1286 | 1121 || second.accept(const IsInterpolationVisitor()); |
| 1287 visitChildren(Visitor visitor) { | |
| 1288 for (Expression literal in literals) { | |
| 1289 literal.accept(visitor); | |
| 1290 } | |
| 1291 } | 1122 } |
| 1292 | 1123 |
| 1293 Token getBeginToken() => literals.head.getBeginToken(); | 1124 accept(Visitor visitor) => visitor.visitStringJuxtaposition(this); |
| 1294 | 1125 |
| 1295 Token getEndToken() { | 1126 void visitChildren(Visitor visitor) { |
| 1296 Link<Expression> current = literals; | 1127 first.accept(visitor); |
| 1297 Expression lastExpression = null; | 1128 second.accept(visitor); |
| 1298 while (!current.isEmpty()) { | |
| 1299 lastExpression = current.head; | |
| 1300 current = current.tail; | |
| 1301 } | |
| 1302 return lastExpression.getEndToken(); | |
| 1303 } | 1129 } |
| 1130 | |
| 1131 Token getBeginToken() => first.getBeginToken(); | |
| 1132 | |
| 1133 Token getEndToken() => second.getEndToken(); | |
| 1304 } | 1134 } |
| 1305 | 1135 |
| 1306 class EmptyStatement extends Statement { | 1136 class EmptyStatement extends Statement { |
| 1307 final Token semicolonToken; | 1137 final Token semicolonToken; |
| 1308 | 1138 |
| 1309 EmptyStatement(this.semicolonToken); | 1139 EmptyStatement(this.semicolonToken); |
| 1310 | 1140 |
| 1311 EmptyStatement asEmptyStatement() => this; | 1141 EmptyStatement asEmptyStatement() => this; |
| 1312 | 1142 |
| 1313 accept(Visitor visitor) => visitor.visitEmptyStatement(this); | 1143 accept(Visitor visitor) => visitor.visitEmptyStatement(this); |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1708 static bool isConstructorRedirect(Send node) { | 1538 static bool isConstructorRedirect(Send node) { |
| 1709 return (node.receiver === null && | 1539 return (node.receiver === null && |
| 1710 node.selector.asIdentifier() !== null && | 1540 node.selector.asIdentifier() !== null && |
| 1711 node.selector.asIdentifier().isThis()) || | 1541 node.selector.asIdentifier().isThis()) || |
| 1712 (node.receiver !== null && | 1542 (node.receiver !== null && |
| 1713 node.receiver.asIdentifier() !== null && | 1543 node.receiver.asIdentifier() !== null && |
| 1714 node.receiver.asIdentifier().isThis() && | 1544 node.receiver.asIdentifier().isThis() && |
| 1715 node.selector.asIdentifier() !== null); | 1545 node.selector.asIdentifier() !== null); |
| 1716 } | 1546 } |
| 1717 } | 1547 } |
| 1548 | |
| 1549 class GetDartStringVisitor extends AbstractVisitor<DartString> { | |
| 1550 const GetDartStringVisitor(); | |
| 1551 DartString visitNode(Node node) => null; | |
| 1552 DartString visitStringInterpolation(StringInterpolation node) => null; | |
| 1553 DartString visitStringJuxtaposition(StringJuxtaposition node) | |
| 1554 => node.dartString; | |
| 1555 DartString visitLiteralString(LiteralString node) => node.dartString; | |
| 1556 } | |
| 1557 | |
| 1558 class IsInterpolationVisitor extends AbstractVisitor<bool> { | |
| 1559 const IsInterpolationVisitor(); | |
| 1560 bool visitNode(Node node) => false; | |
| 1561 bool visitStringInterpolation(StringInterpolation node) => true; | |
| 1562 bool visitStringJuxtaposition(StringJuxtaposition node) | |
| 1563 => node.isInterpolation; | |
| 1564 bool visitLiteralString(LiteralString node) => false; | |
|
ahe
2012/03/15 09:02:56
Why is this needed?
Lasse Reichstein Nielsen
2012/03/19 07:15:32
It's not.
This visitor is build to traverse sting-
| |
| 1565 } | |
| OLD | NEW |