| 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 3a5f1a42c5604ef109070690ef52415d59365e9a..31904554db31c9b8144ec8fa313653ea64ccefc1 100644
|
| --- a/compiler/java/com/google/dart/compiler/parser/DartParser.java
|
| +++ b/compiler/java/com/google/dart/compiler/parser/DartParser.java
|
| @@ -665,17 +665,7 @@ public class DartParser extends CompletionHooksParserBase {
|
|
|
| // Parse the members.
|
| List<DartNode> members = new ArrayList<DartNode>();
|
| - if (optional(Token.LBRACE)) {
|
| - while (!match(Token.RBRACE) && !EOS() && !looksLikeTopLevelKeyword()) {
|
| - DartNode member = parseFieldOrMethod(true);
|
| - if (member != null) {
|
| - members.add(member);
|
| - }
|
| - }
|
| - expectCloseBrace();
|
| - } else {
|
| - reportErrorWithoutAdvancing(ParserErrorCode.EXPECTED_CLASS_DECLARATION_LBRACE);
|
| - }
|
| + parseClassOrInterfaceBody(members);
|
|
|
| if (isParsingInterface) {
|
| return done(new DartClass(name, superType, interfaces, members, typeParameters, defaultClass));
|
| @@ -690,6 +680,31 @@ public class DartParser extends CompletionHooksParserBase {
|
| }
|
| }
|
|
|
| + /**
|
| + * Helper for {@link #parseClass()}.
|
| + *
|
| + * '{' classMemberDefinition* '}'
|
| + *
|
| + */
|
| + @Terminals(tokens={Token.RBRACE, Token.SEMICOLON})
|
| + private void parseClassOrInterfaceBody(List<DartNode> members) {
|
| + if (optional(Token.LBRACE)) {
|
| + while (!match(Token.RBRACE) && !EOS() && !looksLikeTopLevelKeyword()) {
|
| + DartNode member = parseFieldOrMethod(true);
|
| + if (member != null) {
|
| + members.add(member);
|
| + }
|
| + // Recover at a semicolon
|
| + if (optional(Token.SEMICOLON)) {
|
| + reportUnexpectedToken(position(), null, Token.SEMICOLON);
|
| + }
|
| + }
|
| + expectCloseBrace(true);
|
| + } else {
|
| + reportErrorWithoutAdvancing(ParserErrorCode.EXPECTED_CLASS_DECLARATION_LBRACE);
|
| + }
|
| + }
|
| +
|
| private boolean optionalDeprecatedFactory() {
|
| if (optionalPseudoKeyword(FACTORY_KEYWORD)) {
|
| reportError(position(), ParserErrorCode.DEPRECATED_USE_OF_FACTORY_KEYWORD);
|
| @@ -2256,7 +2271,7 @@ public class DartParser extends CompletionHooksParserBase {
|
| @Terminals(tokens={Token.RBRACE, Token.COMMA})
|
| private DartExpression parseMapLiteral(boolean isConst, List<DartTypeNode> typeArguments) {
|
| beginMapLiteral();
|
| - expect(Token.LBRACE);
|
| + boolean foundOpenBrace = expect(Token.LBRACE);
|
| boolean save = setAllowFunctionExpression(true);
|
| List<DartMapLiteralEntry> entries = new ArrayList<DartMapLiteralEntry>();
|
|
|
| @@ -2300,7 +2315,7 @@ public class DartParser extends CompletionHooksParserBase {
|
| }
|
| }
|
|
|
| - expectCloseBrace();
|
| + expectCloseBrace(foundOpenBrace);
|
| setAllowFunctionExpression(save);
|
| return done(new DartMapLiteral(isConst, typeArguments, entries));
|
| }
|
| @@ -3010,7 +3025,7 @@ public class DartParser extends CompletionHooksParserBase {
|
| }
|
| beginBlock();
|
| List<DartStatement> statements = new ArrayList<DartStatement>();
|
| - expect(Token.LBRACE);
|
| + boolean foundOpenBrace = expect(Token.LBRACE);
|
| while (!match(Token.RBRACE) && !EOS()) {
|
| if (looksLikeTopLevelKeyword()) {
|
| reportErrorWithoutAdvancing(ParserErrorCode.UNEXPECTED_TOKEN);
|
| @@ -3022,7 +3037,7 @@ public class DartParser extends CompletionHooksParserBase {
|
| }
|
| statements.add(newStatement);
|
| }
|
| - expectCloseBrace();
|
| + expectCloseBrace(foundOpenBrace);
|
| return done(new DartBlock(statements));
|
| }
|
| }
|
| @@ -3496,33 +3511,30 @@ public class DartParser extends CompletionHooksParserBase {
|
| * Expect a close brace, reporting an error and consuming tokens until a
|
| * plausible continuation is found if it isn't present.
|
| */
|
| - private void expectCloseBrace() {
|
| + private void expectCloseBrace(boolean foundOpenBrace) {
|
| // If a top level keyword is seen, bail out to recover.
|
| if (looksLikeTopLevelKeyword()) {
|
| - reportErrorWithoutAdvancing(ParserErrorCode.UNEXPECTED_TOKEN);
|
| + reportUnexpectedToken(position(), Token.RBRACE, peek(0));
|
| return;
|
| }
|
| - int braceCount = 1;
|
| - switch (peek(0)) {
|
| - case RBRACE:
|
| - expect(Token.RBRACE);
|
| - return;
|
|
|
| - case EOS:
|
| - case SEMICOLON:
|
| - reportErrorWithoutAdvancing(ParserErrorCode.UNEXPECTED_TOKEN);
|
| - return;
|
| -
|
| - case LBRACE:
|
| - ++braceCount;
|
| - //$FALL-THROUGH$
|
| - default:
|
| - reportErrorWithoutAdvancing(ParserErrorCode.UNEXPECTED_TOKEN);
|
| - break;
|
| + int braceCount = 0;
|
| + if (foundOpenBrace) {
|
| + braceCount++;
|
| + }
|
| + Token nextToken = peek(0);
|
| + if (expect(Token.RBRACE)) {
|
| + return;
|
| + }
|
| + if (nextToken == Token.LBRACE) {
|
| + braceCount++;
|
| }
|
|
|
| // eat tokens until we get a matching close brace or end of stream
|
| while (braceCount > 0) {
|
| + if (looksLikeTopLevelKeyword()) {
|
| + return;
|
| + }
|
| switch (next()) {
|
| case RBRACE:
|
| braceCount--;
|
| @@ -3888,7 +3900,7 @@ public class DartParser extends CompletionHooksParserBase {
|
| expectCloseParen();
|
|
|
| List<DartSwitchMember> members = new ArrayList<DartSwitchMember>();
|
| - expect(Token.LBRACE);
|
| + boolean foundOpenBrace = expect(Token.LBRACE);
|
|
|
| boolean done = optional(Token.RBRACE);
|
| while (!done) {
|
| @@ -3913,7 +3925,7 @@ public class DartParser extends CompletionHooksParserBase {
|
| if (peek(0) != Token.EOS) {
|
| members.add(parseDefaultMember(label));
|
| }
|
| - expectCloseBrace();
|
| + expectCloseBrace(foundOpenBrace);
|
| done = true; // Ensure termination.
|
| }
|
| }
|
|
|