Chromium Code Reviews| Index: frog/leg/scanner/listener.dart |
| diff --git a/frog/leg/scanner/listener.dart b/frog/leg/scanner/listener.dart |
| index 5b6dac4f983ada0282d0f70d25aa1ca455332b54..c7adc59219fb37c65f79ffb5d226c5423b7ae718 100644 |
| --- a/frog/leg/scanner/listener.dart |
| +++ b/frog/leg/scanner/listener.dart |
| @@ -837,13 +837,64 @@ class ElementListener extends Listener { |
| } |
| void handleLiteralStringJuxtaposition(int literalCount) { |
| - Link<Expression> literals = const EmptyLink<Expression>(); |
| + assert(literalCount != 0); |
| + if (literalCount == 1) { |
| + compiler.internalError("Unnecessary juxtaposition production"); |
| + } |
| + // A sequence of string literals may contain string interpolations. |
| + // Collect adjacent non-interpolations in [accumulator], and |
| + // collect interpolation parts in [interpolationParts], merging |
| + // adjacent literal string parts into one literal to build |
| + // a final StringInterpolation. |
| + Link<Node> interpolationParts = const EmptyLink<Node>(); |
| + Link<LiteralString> accumulator = const EmptyLink<LiteralString>(); |
| + |
| + // Traverse backwards through the parts of a StringInterpolation |
| + // and prepend them to [interpolationParts]. |
| + // Combine the last part's string with the accumulator. |
| + void prependParts(Link<Node> parts) { |
| + StringInterpolationPart part = parts.head; |
| + if (!parts.tail.isEmpty()) { |
| + prependParts(parts.tail); |
| + } else if (!accumulator.isEmpty()) { |
| + // Create a single StringLiteral from accumulator and the last |
| + // part's [string], and create a new part from that. |
| + LiteralString newString = |
| + new LiteralStringJuxtaposition(accumulator.prepend(part.string)); |
| + accumulator = const EmptyLink<LiteralString>(); |
| + part = new StringInterpolationPart(part.expression, newString); |
| + } |
| + interpolationParts = interpolationParts.prepend(part); |
| + } |
| + |
| while (literalCount > 0) { |
| Expression expression = popNode(); |
| - literals = literals.prepend(expression); |
| + if (expression is StringInterpolation) { |
|
ngeoffray
2012/03/08 10:37:09
expression is -> expression.asStringInterpolation(
Lasse Reichstein Nielsen
2012/03/08 11:17:49
As discussed offline, I'll keep this one.
|
| + StringInterpolation interpolation = expression; |
| + assert(!interpolation.parts.nodes.isEmpty()); |
| + prependParts(interpolation.parts.nodes); |
| + accumulator = accumulator.prepend(interpolation.string); |
| + } else { |
| + StringLiteral literal = expression; |
| + accumulator = accumulator.prepend(literal); |
| + } |
| literalCount -= 1; |
| } |
| - pushNode(new LiteralStringJuxtaposition(literals)); |
| + // Combine the accumulator into a single literal if necessary. |
| + LiteralString string; |
| + // Accumulator cannot be empty. Both a literal and in interpolation |
|
ngeoffray
2012/03/08 10:37:09
in interpolation -> a string part in the interpola
Lasse Reichstein Nielsen
2012/03/08 11:17:49
Here I'm talking about the expression, which is ei
|
| + // leaves something in the accumulator, and literalCount can't be zero. |
| + if (accumulator.tail.isEmpty()) { |
| + string = accumulator.head; |
| + } else { |
| + string = new LiteralStringJuxtaposition(accumulator); |
| + } |
| + Expression result = string; |
| + if (!interpolationParts.isEmpty()) { |
| + NodeList partList = new NodeList(null, interpolationParts, null, null); |
| + result = new StringInterpolation(string, partList); |
| + } |
| + pushNode(result); |
| } |
| } |