Chromium Code Reviews| Index: lib/compiler/implementation/scanner/parser.dart |
| diff --git a/lib/compiler/implementation/scanner/parser.dart b/lib/compiler/implementation/scanner/parser.dart |
| index c24ed64610a41cc6d9f619825bef173ec89626dd..5f4cd49d5bea9958e0a0ada3a67f404a8bcdce99 100644 |
| --- a/lib/compiler/implementation/scanner/parser.dart |
| +++ b/lib/compiler/implementation/scanner/parser.dart |
| @@ -851,10 +851,14 @@ class Parser { |
| } |
| Token parseLabeledStatement(Token token) { |
| - listener.beginLabeledStatement(token); |
| - token = parseLabel(token); |
| + int labelCount = 0; |
| + do { |
| + token = parseLabel(token); |
| + labelCount++; |
| + } while (isIdentifier(token) && optional(':', token.next)); |
| + listener.beginLabeledStatement(token, labelCount); |
| token = parseStatement(token); |
| - listener.endLabeledStatement(); |
| + listener.endLabeledStatement(labelCount); |
| return token; |
| } |
| @@ -1554,10 +1558,85 @@ class Parser { |
| } |
| Token parseSwitchBlock(Token token) { |
| + /** |
| + * Peek after the following labels (if any). The following token |
| + * is used to determine if the labels belong to a statement or a |
| + * switch case. |
| + */ |
| + Token peekPastLabels(Token peek) { |
|
ahe
2012/05/14 09:24:25
I would prefer if this function's argument was nam
Lasse Reichstein Nielsen
2012/05/14 10:34:58
It's now a top-level function. I'll rename "peek"
|
| + Token pre = peek; |
|
ahe
2012/05/14 09:24:25
Unused variable?
Lasse Reichstein Nielsen
2012/05/14 10:34:58
Done.
|
| + while (isIdentifier(peek) && optional(':', peek.next)) { |
| + peek = peek.next.next; |
| + } |
| + return peek; |
| + } |
| + |
| + // When entering or leaving [parseSwitchCase], peek points to the first |
| + // token that isn't a label. |
| + Token peek; |
|
ahe
2012/05/14 09:24:25
It is confusing that peekPastLabels has "peek" par
Lasse Reichstein Nielsen
2012/05/14 10:34:58
It was actually deliberate. Alas, parameter is now
|
| + |
| + /** |
| + * Parse a group of labels, cases and possibly a default keyword and |
| + * the statements that they select. |
| + */ |
| + Token parseSwitchCase(Token token) { |
|
ahe
2012/05/14 09:24:25
This method is definitely something that I think a
Lasse Reichstein Nielsen
2012/05/14 10:34:58
It's avoided, but at the cost of potentially peeki
|
| + Token begin = token; |
| + Token defaultKeyword = null; |
| + int expressionCount = 0; |
| + int labelCount = 0; |
| + |
| + while (true) { |
| + // Loop until we find something that can't be part of a switch case. |
| + String value = peek.stringValue; |
| + if (value === 'default') { |
| + while (token !== peek) { |
| + token = parseLabel(token); |
| + labelCount++; |
| + } |
| + defaultKeyword = token; |
| + token = expect(':', token.next); |
| + peek = token; |
| + break; |
| + } else if (value === 'case') { |
| + while (token !== peek) { |
| + token = parseLabel(token); |
| + labelCount++; |
| + } |
| + Token caseKeyword = token; |
| + token = parseExpression(token.next); |
| + Token colonToken = token; |
| + token = expect(':', token); |
| + listener.handleCaseMatch(caseKeyword, colonToken); |
| + expressionCount++; |
| + peek = peekPastLabels(token); |
| + } else { |
| + break; |
| + } |
| + } |
| + // Finally zero or more statements. |
| + int statementCount = 0; |
| + while (token.kind !== EOF_TOKEN) { |
| + String value = peek.stringValue; |
| + if (value === 'case' || value === 'default' || |
| + (value === '}' && token === peek)) { |
| + // A label just before "}" will be handled as a statement error. |
| + break; |
| + } else { |
| + token = parseStatement(token); |
| + } |
| + statementCount++; |
| + peek = peekPastLabels(token); |
| + } |
| + listener.handleSwitchCase(labelCount, expressionCount, defaultKeyword, |
| + statementCount, begin, token); |
| + return token; |
| + } |
| + |
| Token begin = token; |
| listener.beginSwitchBlock(begin); |
| token = expect('{', token); |
| int caseCount = 0; |
| + peek = peekPastLabels(token); |
| while (token.kind !== EOF_TOKEN) { |
| if (optional('}', token)) { |
| break; |
| @@ -1570,54 +1649,6 @@ class Parser { |
| return token; |
| } |
| - Token parseSwitchCase(Token token) { |
| - Token begin = token; |
| - Token defaultKeyword = null; |
| - Token label = null; |
| - // First an optional label. |
| - if (isIdentifier(token)) { |
| - label = token; |
| - token = parseLabel(token); |
| - } |
| - // Then one or more case expressions, the last of which may be |
| - // 'default' instead. |
| - int expressionCount = 0; |
| - { |
| - String value = token.stringValue; |
| - do { |
| - if (value === 'default') { |
| - defaultKeyword = token; |
| - token = expect(':', token.next); |
| - break; |
| - } |
| - token = expect('case', token); |
| - token = parseExpression(token); |
| - token = expect(':', token); |
| - expressionCount++; |
| - value = token.stringValue; |
| - } while (value === 'case' || value === 'default'); |
| - } |
| - // Finally zero or more statements. |
| - int statementCount = 0; |
| - while (token.kind !== EOF_TOKEN) { |
| - String value; |
| - if (isIdentifier(token) && optional(':', token.next)) { |
| - // Skip label. |
| - value = token.next.next.stringValue; |
| - } else { |
| - value = token.stringValue; |
| - } |
| - if (value === 'case' || value === 'default' || value === '}') { |
| - break; |
| - } else { |
| - token = parseStatement(token); |
| - ++statementCount; |
| - } |
| - } |
| - listener.handleSwitchCase(label, expressionCount, defaultKeyword, |
| - statementCount, begin, token); |
| - return token; |
| - } |
| Token parseBreakStatement(Token token) { |
| assert(optional('break', token)); |