Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(340)

Side by Side Diff: frog/leg/tree/nodes.dart

Issue 9642001: Make string juxtaposition combine properly with string interpolations. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Remove last bugs and clean up builder. Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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.
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;
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),
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
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;
1565 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698