| 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..debe508636c87cc45f25396eac87b468e05b2da7 100644
|
| --- a/lib/compiler/implementation/scanner/parser.dart
|
| +++ b/lib/compiler/implementation/scanner/parser.dart
|
| @@ -1573,48 +1573,68 @@ class Parser {
|
| 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);
|
| +
|
| + /**
|
| + * Peek ahead in the token stream to see what's after a sequence
|
| + * of labels. We don't parse the labels before we know whether we
|
| + * need to call [listener.beginLabeledStatement].
|
| + */
|
| + Token peekAfterLabels(Token token) {
|
| + while (isIdentifier(token) && optional(':', token.next)) {
|
| + token = token.next.next;
|
| + }
|
| + return 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);
|
| + int labelCount = 0;
|
| +
|
| + Token parseLabelsUntil(Token token, Token limit) {
|
| + while (token !== limit) {
|
| + token = parseLabel(token);
|
| + labelCount++;
|
| + }
|
| + return token;
|
| + }
|
| +
|
| + while (true) {
|
| + // Look-ahead to after a sequence of labels. The labels can belong to
|
| + // either a case or a following statement.
|
| + Token peek = peekAfterLabels(token);
|
| + // Loop until we find something that can't be part of a switch case.
|
| + String value = peek.stringValue;
|
| + if (value === 'default') {
|
| + token = parseLabelsUntil(token, peek);
|
| + defaultKeyword = token;
|
| + token = expect(':', token.next);
|
| + break;
|
| + } else if (value === 'case') {
|
| + token = parseLabelsUntil(token, peek);
|
| + Token caseKeyword = token;
|
| + token = parseExpression(token.next);
|
| + Token colon = token;
|
| token = expect(':', token);
|
| + listener.handleCaseMatch(caseKeyword, colon);
|
| expressionCount++;
|
| - value = token.stringValue;
|
| - } while (value === 'case' || value === 'default');
|
| + } else {
|
| + break;
|
| + }
|
| }
|
| // 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 === '}') {
|
| + Token peek = peekAfterLabels(token);
|
| + String value = peek.stringValue;
|
| + if (value === 'case' || value === 'default' ||
|
| + (value === '}' && peek === token)) {
|
| + // A label just before "}" will be handled as a statement error.
|
| break;
|
| } else {
|
| token = parseStatement(token);
|
| ++statementCount;
|
| }
|
| }
|
| - listener.handleSwitchCase(label, expressionCount, defaultKeyword,
|
| + listener.handleSwitchCase(labelCount, expressionCount, defaultKeyword,
|
| statementCount, begin, token);
|
| return token;
|
| }
|
|
|