| 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);
|
| + }
|
| 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);
|
| }
|
|
|
|
|