Chromium Code Reviews| Index: pkg/front_end/lib/src/fasta/parser/parser.dart |
| diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart |
| index 7d7f6513d61e5a2b12ddfb7d97c65cb5d6341256..f95b1edd485c2545dcf0ce01db269d3c473939b8 100644 |
| --- a/pkg/front_end/lib/src/fasta/parser/parser.dart |
| +++ b/pkg/front_end/lib/src/fasta/parser/parser.dart |
| @@ -10,6 +10,8 @@ import '../fasta_codes.dart' |
| FastaMessage, |
| codeAbstractNotSync, |
| codeAsciiControlCharacter, |
| + codeAssertAsExpression, |
| + codeAssertExtraneousArgument, |
| codeAsyncAsIdentifier, |
| codeAwaitAsIdentifier, |
| codeAwaitForNotAsync, |
| @@ -158,6 +160,17 @@ enum MemberKind { |
| TopLevelField, |
| } |
| +/// Syntactic forms of `assert`. |
| +/// |
| +/// An assertion can legally occur as a statement. However, assertions are also |
| +/// experimentally allowed in initializers. For improved error recovery, we |
| +/// also attempt to parse asserts as expressions. |
| +enum Assert { |
| + Expression, |
| + Initializer, |
| + Statement, |
| +} |
| + |
| /// An event generating parser of Dart programs. This parser expects all tokens |
| /// in a linked list (aka a token stream). |
| /// |
| @@ -1561,10 +1574,7 @@ class Parser { |
| bool old = mayParseFunctionExpressions; |
| mayParseFunctionExpressions = false; |
| do { |
| - token = token.next; |
| - listener.beginInitializer(token); |
| - token = parseExpression(token); |
| - listener.endInitializer(token); |
| + token = parseInitializer(token.next); |
| ++count; |
| } while (optional(',', token)); |
| mayParseFunctionExpressions = old; |
| @@ -1572,12 +1582,24 @@ class Parser { |
| return token; |
| } |
| + Token parseInitializer(Token token) { |
| + listener.beginInitializer(token); |
| + if (optional('assert', token)) { |
| + token = parseAssert(token, Assert.Initializer); |
| + } else { |
| + token = parseExpression(token); |
| + } |
| + listener.endInitializer(token); |
| + return token; |
| + } |
| + |
| Token parseLiteralStringOrRecoverExpression(Token token) { |
| if (identical(token.kind, STRING_TOKEN)) { |
| return parseLiteralString(token); |
| } else { |
| reportRecoverableErrorCodeWithToken(token, codeExpectedString); |
| - return parseRecoverExpression(token); |
| + return parseRecoverExpression( |
| + token, codeExpectedString.format(uri, token.charOffset, token)); |
| } |
| } |
| @@ -2686,7 +2708,8 @@ class Parser { |
| return token; |
| } |
| - Token parseRecoverExpression(Token token) => parseExpression(token); |
| + Token parseRecoverExpression(Token token, FastaMessage message) => |
| + parseExpression(token); |
| int expressionDepth = 0; |
| Token parseExpression(Token token) { |
| @@ -2915,6 +2938,8 @@ class Parser { |
| } else if (!inPlainSync && |
| (identical(value, "yield") || identical(value, "async"))) { |
| return expressionExpected(token); |
| + } else if (identical(value, "assert")) { |
| + return parseAssert(token, Assert.Expression); |
| } else if (token.isIdentifier) { |
| return parseSendOrFunctionLiteral(token, context); |
| } else { |
| @@ -3773,7 +3798,8 @@ class Parser { |
| return expectSemicolon(token); |
| } |
| - Token parseAssertStatement(Token token) { |
| + Token parseAssert(Token token, Assert kind) { |
| + listener.beginAssert(token, kind); |
| Token assertKeyword = token; |
| Token commaToken = null; |
| token = expect('assert', token); |
| @@ -3787,11 +3813,30 @@ class Parser { |
| token = token.next; |
| token = parseExpression(token); |
| } |
| + if (optional(',', token)) { |
| + Token firstExtra = token.next; |
| + while (optional(',', token)) { |
| + token = token.next; |
| + Token begin = token; |
| + token = parseExpression(token); |
| + listener.handleExtraneousExpression( |
| + begin, codeAssertExtraneousArgument.format(uri, token.charOffset)); |
| + } |
| + reportRecoverableErrorCode(firstExtra, codeAssertExtraneousArgument); |
|
kasperl
2017/06/08 10:23:14
Very nice to see the recoverable errors being deal
ahe
2017/06/08 11:04:33
Yes. At least these tests:
co19/Language/Statemen
|
| + } |
| Token rightParenthesis = token; |
| token = expect(')', token); |
| mayParseFunctionExpressions = old; |
| - listener.handleAssertStatement( |
| - assertKeyword, leftParenthesis, commaToken, rightParenthesis, token); |
| + listener.endAssert(assertKeyword, kind, leftParenthesis, commaToken, |
| + rightParenthesis, token); |
| + if (kind == Assert.Expression) { |
| + reportRecoverableErrorCode(assertKeyword, codeAssertAsExpression); |
| + } |
| + return token; |
| + } |
| + |
| + Token parseAssertStatement(Token token) { |
| + token = parseAssert(token, Assert.Statement); |
| return expectSemicolon(token); |
| } |