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

Unified Diff: compiler/java/com/google/dart/compiler/parser/DartParser.java

Issue 10555034: Fix parse error on dead code in a switch statement (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: # Created 8 years, 6 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 side-by-side diff with in-line comments
Download patch
Index: compiler/java/com/google/dart/compiler/parser/DartParser.java
diff --git a/compiler/java/com/google/dart/compiler/parser/DartParser.java b/compiler/java/com/google/dart/compiler/parser/DartParser.java
index ee69b4128fad2b6b2026f0c1f1edea9424460fb8..d1d6c65d03226c4b12340581df6ca46d97d173df 100644
--- a/compiler/java/com/google/dart/compiler/parser/DartParser.java
+++ b/compiler/java/com/google/dart/compiler/parser/DartParser.java
@@ -3182,27 +3182,30 @@ public class DartParser extends CompletionHooksParserBase {
boolean oldInLoopStatement = inLoopStatement;
boolean oldInCaseStatement = inCaseStatement;
inLoopStatement = inCaseStatement = false;
- DartBlock result;
- if (isDietParse) {
- result = dietParseFunctionStatementBody();
- } else {
- beginFunctionStatementBody();
- if (optional(Token.ARROW)) {
- DartExpression expr = parseExpression();
- if (expr == null) {
- expr = new DartSyntheticErrorExpression();
- }
- if (requireSemicolonForArrow) {
- expect(Token.SEMICOLON);
- }
- result = done(makeReturnBlock(expr));
+ try {
+ DartBlock result;
+ if (isDietParse) {
+ result = dietParseFunctionStatementBody();
} else {
- result = done(parseBlock());
+ beginFunctionStatementBody();
+ if (optional(Token.ARROW)) {
+ DartExpression expr = parseExpression();
+ if (expr == null) {
+ expr = new DartSyntheticErrorExpression();
+ }
+ if (requireSemicolonForArrow) {
+ expect(Token.SEMICOLON);
+ }
+ result = done(makeReturnBlock(expr));
+ } else {
+ result = done(parseBlock());
+ }
}
+ return result;
+ } finally {
+ inLoopStatement = oldInLoopStatement;
+ inCaseStatement = oldInCaseStatement;
}
- inLoopStatement = oldInLoopStatement;
- inCaseStatement = oldInCaseStatement;
- return result;
}
private DartBlock dietParseFunctionStatementBody() {
@@ -3816,9 +3819,11 @@ public class DartParser extends CompletionHooksParserBase {
private DartStatement parseLoopStatement() {
boolean oldInLoop = inLoopStatement;
inLoopStatement = true;
- DartStatement stmt = parseStatement();
- inLoopStatement = oldInLoop;
- return stmt;
+ try {
+ return parseStatement();
+ } finally {
+ inLoopStatement = oldInLoop;
+ }
}
/**
@@ -3947,6 +3952,8 @@ public class DartParser extends CompletionHooksParserBase {
private List<DartStatement> parseCaseStatements() {
List<DartStatement> statements = new ArrayList<DartStatement>();
DartStatement statement = null;
+ boolean endOfCaseFound = false;
+ boolean warnedUnreachable = false;
while (true) {
switch (peek(0)) {
case CASE:
@@ -3955,27 +3962,33 @@ public class DartParser extends CompletionHooksParserBase {
case EOS:
return statements;
case IDENTIFIER:
- // Handle consecutively labelled case statements
- if (peek(1).equals(Token.COLON) && peek(2).equals(Token.CASE)) {
+ // Handle consecutively labeled case statements
+ if (peek(1).equals(Token.COLON)
+ && (peek(2).equals(Token.CASE) || peek(2).equals(Token.DEFAULT))) {
return statements;
}
default:
boolean oldInCaseStatement = inCaseStatement;
inCaseStatement = true;
- statement = parseStatement();
- inCaseStatement = oldInCaseStatement;
+ try {
+ if (endOfCaseFound && !warnedUnreachable) {
+ reportErrorWithoutAdvancing(ParserErrorCode.UNREACHABLE_CODE_IN_CASE);
+ warnedUnreachable = true;
+ }
+ statement = parseStatement();
+ } finally {
+ inCaseStatement = oldInCaseStatement;
+ }
if (statement == null) {
return statements;
}
- statements.add(statement);
- if (statement.isAbruptCompletingStatement()) {
- /*
- * TODO(jat): is this correct? It seems like we would get better
- * error messages if we parsed dead code as part of this case block
- * and gave an error for unreachable code
- */
- return statements;
+ // Don't add unreachable code to the list of statements.
+ if (!endOfCaseFound) {
+ statements.add(statement);
+ if (statement.isAbruptCompletingStatement()) {
+ endOfCaseFound = true;
+ }
}
}
}
@@ -4041,8 +4054,12 @@ public class DartParser extends CompletionHooksParserBase {
DartIdentifier identifier = parseIdentifier();
expect(Token.COLON);
label = done(new DartLabel(identifier, null));
+ if (peek(0) == Token.RBRACE) {
+ reportError(position(), ParserErrorCode.LABEL_NOT_FOLLOWED_BY_CASE_OR_DEFAULT);
+ expectCloseBrace(foundOpenBrace);
+ break;
+ }
}
-
if (peek(0) == Token.CASE) {
members.add(parseCaseMember(label));
} else if (optional(Token.RBRACE)) {
@@ -4062,7 +4079,39 @@ public class DartParser extends CompletionHooksParserBase {
return done(new DartSwitchStatement(expr, members));
}
- /**
+ private void parseDeadSwitchCode() {
+ boolean done = false;
+ boolean warned = false;
+ boolean oldInCaseStatement = inCaseStatement;
+ inCaseStatement = true;
+ try {
+ while (!done) {
+ if (peek(0) == Token.IDENTIFIER && peek(1) == Token.COLON) {
+ beginLabel();
+ DartIdentifier identifier = parseIdentifier();
+ expect(Token.COLON);
+ done(new DartLabel(identifier, null));
+
+ }
+
+ Token nextToken = peek(0);
+ switch(nextToken) {
+ case CASE:
+ case DEFAULT:
+ case EOS:
+ case RBRACE:
+ return;
+ default:
+ warned = true;
+ parseStatement();
+ }
+ }
+ } finally {
+ inCaseStatement = oldInCaseStatement;
+ }
+ }
+
+ /**
* <pre>
* catchParameter
* : FINAL type? identifier
« no previous file with comments | « no previous file | compiler/java/com/google/dart/compiler/parser/ParserErrorCode.java » ('j') | tests/co19/co19-compiler.status » ('J')

Powered by Google App Engine
This is Rietveld 408576698