Chromium Code Reviews| Index: frog/leg/scanner/listener.dart |
| diff --git a/frog/leg/scanner/listener.dart b/frog/leg/scanner/listener.dart |
| index 55904511798dcff819328d9f996d109b052f7ef2..27ddddfe846084dcdc5e9f2744f972af0d1a2ed5 100644 |
| --- a/frog/leg/scanner/listener.dart |
| +++ b/frog/leg/scanner/listener.dart |
| @@ -152,16 +152,16 @@ class Listener { |
| void endLabelledStatement(Token colon) { |
| } |
| - void beginLibraryTag(Token token) { |
| + void beginLiteralMapEntry(Token token) { |
| } |
| - void endLibraryTag(bool hasPrefix, Token beginToken, Token endToken) { |
| + void endLiteralMapEntry(Token colon, Token endToken) { |
| } |
| - void beginLiteralMapEntry(Token token) { |
| + void beginLiteralString(Token token) { |
| } |
| - void endLiteralMapEntry(Token colon, Token endToken) { |
| + void endLiteralString(int interpolationCount) { |
| } |
| void beginMember(Token token) { |
| @@ -184,6 +184,12 @@ class Listener { |
| Token beginToken, Token endToken) { |
| } |
| + void beginScriptTag(Token token) { |
| + } |
| + |
| + void endScriptTag(bool hasPrefix, Token beginToken, Token endToken) { |
| + } |
| + |
| void beginSend(Token token) { |
| } |
| @@ -335,9 +341,6 @@ class Listener { |
| void handleLiteralNull(Token token) { |
| } |
| - void handleLiteralString(Token token) { |
| - } |
| - |
| void handleModifier(Token token) { |
| } |
| @@ -371,7 +374,7 @@ class Listener { |
| void handleQualified(Token period) { |
| } |
| - void handleStringInterpolationParts(int count) { |
| + void handleStringPart(Token token) { |
| } |
| void handleSuperExpression(Token token) { |
| @@ -454,20 +457,44 @@ class ParserError { |
| class ElementListener extends Listener { |
| final Canceler canceler; |
| final CompilationUnitElement compilationUnitElement; |
| + final StringValidator stringValidator; |
| + Link<StringQuoting> interpolationScope; |
| Link<Node> nodes = const EmptyLink<Node>(); |
| - ElementListener(Canceler this.canceler, |
| - CompilationUnitElement this.compilationUnitElement); |
| + ElementListener(Canceler canceler, |
| + CompilationUnitElement this.compilationUnitElement) |
| + : this.canceler = canceler, |
| + stringValidator = new StringValidator(canceler), |
| + interpolationScope = const EmptyLink<StringQuoting>(); |
|
ahe
2012/01/27 12:12:37
FYI, you can initialize this in the field declarat
|
| + |
| + void pushQuoting(StringQuoting quoting) { |
| + interpolationScope = interpolationScope.prepend(quoting); |
| + } |
| + |
| + StringQuoting popQuoting() { |
| + StringQuoting result = interpolationScope.head; |
| + interpolationScope = interpolationScope.tail; |
| + return result; |
| + } |
| + |
| + LiteralString popLiteralString() { |
| + Node node = popNode(); |
| + if (node is !LiteralString) { |
| + canceler.cancel("String is not a compile time constant", node: node); |
| + return null; |
| + } |
| + return node; |
| + } |
| - void endLibraryTag(bool hasPrefix, Token beginToken, Token endToken) { |
| + void endScriptTag(bool hasPrefix, Token beginToken, Token endToken) { |
| LiteralString prefix = null; |
| Identifier argumentName = null; |
| if (hasPrefix) { |
| - prefix = popNode(); |
| + prefix = popLiteralString(); |
| argumentName = popNode(); |
| } |
| - LiteralString firstArgument = popNode(); |
| + LiteralString firstArgument = popLiteralString(); |
| Identifier tag = popNode(); |
| compilationUnitElement.addTag(new ScriptTag(tag, firstArgument, |
| argumentName, prefix, |
| @@ -672,8 +699,55 @@ class ElementListener extends Listener { |
| return new NodeList(beginToken, nodes, endToken, sourceDelimiter); |
| } |
| - void handleLiteralString(Token token) { |
| - pushNode(new LiteralString(token)); |
| + void beginLiteralString(Token token) { |
| + SourceString source = token.value; |
| + StringQuoting quoting = StringValidator.quotingFromString(source); |
| + pushQuoting(quoting); |
| + // Just wrap the token for now. At the end of the interpolation, |
| + // when we know how many there are, go back and validate the tokens. |
| + pushNode(new LiteralString(token, null)); |
| + } |
| + |
| + void handleStringPart(Token token) { |
| + // Just push an unvalidated token now, and replace it when we know the |
| + // end of the interpolation. |
| + pushNode(new LiteralString(token, null)); |
| + } |
| + |
| + void endLiteralString(int count) { |
| + StringQuoting quoting = popQuoting(); |
| + |
| + Link<StringInterpolationPart> parts = |
| + const EmptyLink<StringInterpolationPart>(); |
| + // Parts of the string interpolation are popped in reverse order, |
|
ahe
2012/01/27 12:12:37
Since all parts of the string interpolation is pop
|
| + // starting with the last literal string part. |
| + bool isLast = true; |
| + for (int i = 0; i < count; i++) { |
| + LiteralString string = popNode(); |
| + QuotedString validation = |
| + stringValidator.validateInterpolationPart(string.token, quoting, |
| + isFirst: false, |
| + isLast: isLast); |
| + // Replace the unvalidated LiteralString with a new LiteralString |
| + // object that has the validation result included. |
| + string = new LiteralString(string.token, validation); |
| + Expression expression = popNode(); |
| + parts = parts.prepend(new StringInterpolationPart(expression, string)); |
| + isLast = false; |
| + } |
| + |
| + LiteralString string = popNode(); |
| + QuotedString validation = |
| + stringValidator.validateInterpolationPart(string.token, quoting, |
| + isFirst: true, |
| + isLast: isLast); |
| + string = new LiteralString(string.token, validation); |
| + if (isLast) { |
| + pushNode(string); |
| + } else { |
| + NodeList nodes = new NodeList(null, parts, null, null); |
| + pushNode(new StringInterpolation(string, nodes)); |
| + } |
| } |
| } |
| @@ -1051,21 +1125,6 @@ class NodeListener extends ElementListener { |
| pushNode(new NamedArgument(name, colon, expression)); |
| } |
| - void handleStringInterpolationParts(int count) { |
| - Link<StringInterpolationPart> parts = |
| - const EmptyLink<StringInterpolationPart>(); |
| - for (int i = 0; i < count; i++) { |
| - LiteralString string = popNode(); |
| - Expression expression = popNode(); |
| - parts = parts.prepend(new StringInterpolationPart(expression, string)); |
| - } |
| - if (!parts.isEmpty()) { |
| - LiteralString string = popNode(); |
| - NodeList nodes = new NodeList(null, parts, null, null); |
| - pushNode(new StringInterpolation(string, nodes)); |
| - } |
| - } |
| - |
| void endOptionalFormalParameters(int count, |
| Token beginToken, Token endToken) { |
| pushNode(makeNodeList(count, beginToken, endToken, ',')); |