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

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

Issue 10021013: Improve error recovery in formal parameter lists (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Added unit tests for expression lists Created 8 years, 8 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 2d6611da1b9b651a53283303c6cb90cc49d17a93..e281614ddddb747df33c0b92732b7d50982e61dc 100644
--- a/compiler/java/com/google/dart/compiler/parser/DartParser.java
+++ b/compiler/java/com/google/dart/compiler/parser/DartParser.java
@@ -113,7 +113,7 @@ public class DartParser extends CompletionHooksParserBase {
private final boolean isDietParse;
private final Set<String> prefixes;
private final boolean corelibParse;
- private Set<Integer> errorHistory = new HashSet<Integer>();
+ private final Set<Integer> errorHistory = new HashSet<Integer>();
private boolean isParsingInterface;
private boolean isTopLevelAbstract;
private DartScanner.Position topLevelAbstractModifierPosition;
@@ -161,7 +161,7 @@ public class DartParser extends CompletionHooksParserBase {
STATIC_KEYWORD,
TYPEDEF_KEYWORD
};
-
+
public DartParser(Source source,
String sourceCode,
DartCompilerListener listener) {
@@ -278,12 +278,12 @@ public class DartParser extends CompletionHooksParserBase {
if (optional(Token.CLASS)) {
isParsingClass = true;
node = done(parseClass());
- } else if (peekPseudoKeyword(0, INTERFACE_KEYWORD)
+ } else if (peekPseudoKeyword(0, INTERFACE_KEYWORD)
&& peek(1).equals(Token.IDENTIFIER)) {
consume(Token.IDENTIFIER);
isParsingInterface = true;
node = done(parseClass());
- } else if (peekPseudoKeyword(0, TYPEDEF_KEYWORD)
+ } else if (peekPseudoKeyword(0, TYPEDEF_KEYWORD)
&& (peek(1).equals(Token.IDENTIFIER) || peek(1).equals(Token.VOID))) {
consume(Token.IDENTIFIER);
node = done(parseFunctionTypeAlias());
@@ -329,7 +329,7 @@ public class DartParser extends CompletionHooksParserBase {
|| peekPseudoKeyword(n, INTERFACE_KEYWORD)
|| peekPseudoKeyword(n, TYPEDEF_KEYWORD);
}
-
+
/**
* 'interface' and 'typedef' are valid to use as names of fields and methods, so you can't
* just blindly recover when you see them in any context. This does a further test to make
@@ -340,10 +340,10 @@ public class DartParser extends CompletionHooksParserBase {
if (peek(0).equals(Token.CLASS)) {
return true;
}
- if (peekPseudoKeyword(0, INTERFACE_KEYWORD)
+ if (peekPseudoKeyword(0, INTERFACE_KEYWORD)
&& peek(1).equals(Token.IDENTIFIER)) {
return true;
- } else if (peekPseudoKeyword(0, TYPEDEF_KEYWORD)
+ } else if (peekPseudoKeyword(0, TYPEDEF_KEYWORD)
&& (peek(1).equals(Token.IDENTIFIER) || peek(1).equals(Token.VOID))) {
return true;
}
@@ -518,6 +518,7 @@ public class DartParser extends CompletionHooksParserBase {
do {
DartTypeParameter typeParameter = parseTypeParameter();
types.add(typeParameter);
+
} while (optional(Token.COMMA));
expect(Token.GT);
return types;
@@ -958,7 +959,7 @@ public class DartParser extends CompletionHooksParserBase {
member = parseMethodOrAccessor(modifiers, null);
break;
}
-
+
member = parseFieldDeclaration(modifiers, null);
expectStatmentTerminator();
break;
@@ -990,13 +991,13 @@ public class DartParser extends CompletionHooksParserBase {
&& peek(1) != Token.ASSIGN
&& peek(1) != Token.SEMICOLON) {
type = parseTypeAnnotation();
-
+
// Check again for malformed method starting with 'final': final String ^ foo() { }
if (peek(0).equals(Token.IDENTIFIER) && looksLikeMethodOrAccessorDefinition()) {
reportError(position(), ParserErrorCode.FINAL_IS_NOT_ALLOWED_ON_A_METHOD_DEFINITION);
member = parseMethodOrAccessor(modifiers, null);
break;
- }
+ }
}
member = parseFieldDeclaration(modifiers, type);
expectStatmentTerminator();
@@ -1061,8 +1062,8 @@ public class DartParser extends CompletionHooksParserBase {
* | set identifier (
* | operator (
* | operator <op> (
- * | identifier (
- * | identifier DOT identifier (
+ * | identifier (
+ * | identifier DOT identifier (
* | identifier DOT identifier DOT identifier (
*
* @return <code>true</code> if the signature of a method has been found. No tokens are consumed.
@@ -1085,40 +1086,40 @@ public class DartParser extends CompletionHooksParserBase {
if (peekPseudoKeyword(0, NEGATE_KEYWORD) && peek(1).equals(Token.LPAREN)) {
return true;
}
- // TODO(zundel): Look for valid operator overload tokens. For now just assuming
+ // TODO(zundel): Look for valid operator overload tokens. For now just assuming
// non-idents are good enough
// operator ??? (
if (!(peek(0).equals(Token.IDENTIFIER) && peek(1).equals(Token.LPAREN))) {
return true;
}
if (peek(0).equals(Token.LBRACK) && peek(1).equals(Token.RBRACK)) {
- // operator [] (
+ // operator [] (
if (peek(2).equals(Token.LPAREN)) {
return true;
}
- // operator []= (
+ // operator []= (
if (peek(2).equals(Token.ASSIGN) && peek(3).equals(Token.LPAREN)) {
return true;
}
}
return false;
}
-
+
if (peekPseudoKeyword(0, GETTER_KEYWORD)
|| peekPseudoKeyword(0, SETTER_KEYWORD)) {
next();
// Using 'get' or 'set' as a field name is valid
if (peek(0).equals(Token.SEMICOLON) || peek(0).equals(Token.ASSIGN)) {
return false;
- }
+ }
// Using 'get' or 'set' as a method name is valid (but discouraged)
if (peek(0).equals(Token.LPAREN)) {
return true;
- }
+ }
// normal case: get foo (
if (peek(0).equals(Token.IDENTIFIER) && peek(1).equals(Token.LPAREN)) {
return true;
- }
+ }
return false;
}
@@ -1227,7 +1228,7 @@ public class DartParser extends CompletionHooksParserBase {
found = true;
break;
}
- }
+ }
StringBuilder buf = new StringBuilder();
buf.append(operation.getSyntax());
if (found) {
@@ -1578,6 +1579,7 @@ public class DartParser extends CompletionHooksParserBase {
* ;
* </pre>
*/
+ @Terminals(tokens = {Token.RBRACK, Token.COMMA, Token.RPAREN})
private List<DartParameter> parseFormalParameterList() {
beginFormalParameterList();
List<DartParameter> params = new ArrayList<DartParameter>();
@@ -1592,15 +1594,18 @@ public class DartParser extends CompletionHooksParserBase {
DartParameter param = parseFormalParameter(isNamed);
params.add(param);
+ // Must keep in sync with @Terminals above
done = optional(Token.RBRACK);
if (done) {
expectCloseParen();
} else {
+ // Must keep in sync with @Terminals above
done = optional(Token.RPAREN);
}
if (!done) {
// Ensure termination if token is anything other than COMMA.
+ // Must keep in sync with @Terminals above
done = !expect(Token.COMMA);
}
}
@@ -1791,6 +1796,7 @@ public class DartParser extends CompletionHooksParserBase {
private DartExpression parseExpressionList() {
beginExpressionList();
DartExpression result = parseExpression();
+ // Must keep in sync with @Terminals above
while (optional(Token.COMMA)) {
result = new DartBinaryExpression(Token.COMMA, result, parseExpression());
if (match(Token.COMMA)) {
@@ -1858,9 +1864,9 @@ public class DartParser extends CompletionHooksParserBase {
Position prevPositionStart = ctx.getTokenLocation().getBegin();
Position prevPositionEnd = ctx.getTokenLocation().getEnd();
Token token = next();
- if (lastResult instanceof DartSuperExpression
+ if (lastResult instanceof DartSuperExpression
&& (token == Token.AND || token == Token.OR)) {
- reportErrorAtPosition(prevPositionStart, prevPositionEnd,
+ reportErrorAtPosition(prevPositionStart, prevPositionEnd,
ParserErrorCode.SUPER_IS_NOT_VALID_AS_A_BOOLEAN_OPERAND);
}
DartExpression right;
@@ -1879,7 +1885,7 @@ public class DartParser extends CompletionHooksParserBase {
if (right instanceof DartSuperExpression) {
reportError(position(), ParserErrorCode.SUPER_CANNOT_BE_USED_AS_THE_SECOND_OPERAND);
}
-
+
lastResult = right;
result = doneWithoutConsuming(new DartBinaryExpression(token, result, right));
if ((token == Token.IS)
@@ -1940,9 +1946,11 @@ public class DartParser extends CompletionHooksParserBase {
}
arguments.add(done(expression));
switch(peek(0)) {
+ // Must keep in sync with @Terminals above
case COMMA:
consume(Token.COMMA);
break;
+ // Must keep in sync with @Terminals above
case RPAREN:
break;
default:
@@ -1972,9 +1980,9 @@ public class DartParser extends CompletionHooksParserBase {
private DartExpression parseConditionalExpression() {
beginConditionalExpression();
DartExpression result = parseBinaryExpression(4);
- if (result instanceof DartSuperExpression) {
+ if (result instanceof DartSuperExpression) {
reportError(position(), ParserErrorCode.SUPER_IS_NOT_VALID_ALONE_OR_AS_A_BOOLEAN_OPERAND);
- }
+ }
if (peek(0) != Token.CONDITIONAL) {
return done(result);
}
@@ -2078,7 +2086,7 @@ public class DartParser extends CompletionHooksParserBase {
case STRING_SEGMENT:
case STRING_EMBED_EXP_START:
return parseStringInterpolation();
-
+
default:
DartExpression expression = parseExpression();
reportError(position(), ParserErrorCode.EXPECTED_STRING_LITERAL);
@@ -2324,7 +2332,7 @@ public class DartParser extends CompletionHooksParserBase {
ensureAssignable(result);
consume(token);
result = doneWithoutConsuming(new DartUnaryExpression(token, result, false));
- }
+ }
return done(result);
}
@@ -2368,8 +2376,8 @@ public class DartParser extends CompletionHooksParserBase {
private class DartStringInterpolationBuilder {
- private List<DartStringLiteral> strings = new ArrayList<DartStringLiteral>();
- private List<DartExpression> expressions = new ArrayList<DartExpression>();
+ private final List<DartStringLiteral> strings = new ArrayList<DartStringLiteral>();
+ private final List<DartExpression> expressions = new ArrayList<DartExpression>();
private LastSeenNode lastSeen = LastSeenNode.NONE;
DartStringInterpolationBuilder() {
@@ -2971,7 +2979,7 @@ public class DartParser extends CompletionHooksParserBase {
// Allow recovery back to the top level.
reportErrorWithoutAdvancing(ParserErrorCode.UNEXPECTED_TOKEN);
return done(new DartBlock(new ArrayList<DartStatement>()));
- }
+ }
expect(Token.LBRACE);
while (!match(Token.RBRACE) && !EOS()) {
if (looksLikeTopLevelKeyword()) {
@@ -3266,12 +3274,12 @@ public class DartParser extends CompletionHooksParserBase {
// Things that we know can't be valid statements get a synthetic error statement
case RBRACE:
- case CLASS:
+ case CLASS:
// no need to create a separate parser event as the AST node is enough
beginEmptyStatement();
// TODO(jat): other tokens that should be caught here?
return done(parseErrorStatement());
-
+
case IDENTIFIER:
// We have already eliminated function declarations earlier, so check for:
// a) variable declarations;

Powered by Google App Engine
This is Rietveld 408576698