| Index: pkg/dart_parser/lib/src/parser.dart
|
| diff --git a/pkg/dart_parser/lib/src/parser.dart b/pkg/dart_parser/lib/src/parser.dart
|
| index 78469d164539afaf7559f6c2b8bd184e308e2adc..f713fd02b2117ad32396f6add1b3f31e4f27ed98 100644
|
| --- a/pkg/dart_parser/lib/src/parser.dart
|
| +++ b/pkg/dart_parser/lib/src/parser.dart
|
| @@ -11,6 +11,7 @@ import 'package:dart_scanner/src/precedence.dart' show
|
| ASSIGNMENT_PRECEDENCE,
|
| AS_INFO,
|
| CASCADE_PRECEDENCE,
|
| + EOF_INFO,
|
| EQUALITY_PRECEDENCE,
|
| GT_INFO,
|
| IS_INFO,
|
| @@ -26,11 +27,14 @@ import 'package:dart_scanner/src/precedence.dart' show
|
| RELATIONAL_PRECEDENCE;
|
|
|
| import 'package:dart_scanner/src/token.dart' show
|
| + BadInputToken,
|
| BeginGroupToken,
|
| ErrorToken,
|
| KeywordToken,
|
| SymbolToken,
|
| Token,
|
| + UnmatchedToken,
|
| + UnterminatedToken,
|
| isUserDefinableOperator;
|
|
|
| import 'package:dart_scanner/src/token_constants.dart' show
|
| @@ -420,10 +424,11 @@ class Parser {
|
| listener.beginOptionalFormalParameters(token);
|
| if (!optional('(', token)) {
|
| if (optional(';', token)) {
|
| - listener.reportError(token, ErrorKind.ExpectedOpenParens);
|
| + reportRecoverableError(token, ErrorKind.ExpectedOpenParens);
|
| return token;
|
| }
|
| - return listener.unexpected(token);
|
| + return reportUnrecoverableError(
|
| + token, ErrorKind.ExpectedButGot, {"expected": "("});
|
| }
|
| BeginGroupToken beginGroupToken = token;
|
| Token endToken = beginGroupToken.endGroup;
|
| @@ -497,10 +502,10 @@ class Parser {
|
| token = parseExpression(token.next);
|
| listener.handleValuedFormalParameter(equal, token);
|
| if (type.isRequired) {
|
| - listener.reportError(
|
| + reportRecoverableError(
|
| equal, ErrorKind.RequiredParameterWithDefault);
|
| } else if (type.isPositional && identical(':', value)) {
|
| - listener.reportError(
|
| + reportRecoverableError(
|
| equal, ErrorKind.PositionalParameterWithEquals);
|
| }
|
| }
|
| @@ -526,7 +531,7 @@ class Parser {
|
| ++parameterCount;
|
| } while (optional(',', token));
|
| if (parameterCount == 0) {
|
| - listener.reportError(
|
| + reportRecoverableError(
|
| token,
|
| isNamed
|
| ? ErrorKind.EmptyNamedParameterList
|
| @@ -663,14 +668,16 @@ class Parser {
|
|
|
| Token skipBlock(Token token) {
|
| if (!optional('{', token)) {
|
| - return listener.expectedBlockToSkip(token);
|
| + return reportUnrecoverableError(token, ErrorKind.ExpectedBlockToSkip);
|
| }
|
| BeginGroupToken beginGroupToken = token;
|
| Token endGroup = beginGroupToken.endGroup;
|
| if (endGroup == null) {
|
| - return listener.unmatched(beginGroupToken);
|
| + return reportUnrecoverableError(
|
| + beginGroupToken, ErrorKind.UnmatchedToken);
|
| } else if (!identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) {
|
| - return listener.unmatched(beginGroupToken);
|
| + return reportUnrecoverableError(
|
| + beginGroupToken, ErrorKind.UnmatchedToken);
|
| }
|
| return beginGroupToken.endGroup;
|
| }
|
| @@ -775,13 +782,13 @@ class Parser {
|
| listener.handleStringPart(token);
|
| return token.next;
|
| } else {
|
| - return listener.expected('string', token);
|
| + return reportUnrecoverableError(token, ErrorKind.ExpectedString);
|
| }
|
| }
|
|
|
| Token parseIdentifier(Token token) {
|
| if (!token.isIdentifier()) {
|
| - token = listener.expectedIdentifier(token);
|
| + token = reportUnrecoverableError(token, ErrorKind.ExpectedIdentifier);
|
| }
|
| listener.handleIdentifier(token);
|
| return token.next;
|
| @@ -789,7 +796,8 @@ class Parser {
|
|
|
| Token expect(String string, Token token) {
|
| if (!identical(string, token.stringValue)) {
|
| - return listener.expected(string, token);
|
| + return reportUnrecoverableError(
|
| + token, ErrorKind.ExpectedButGot, {"expected": string});
|
| }
|
| return token.next;
|
| }
|
| @@ -843,7 +851,7 @@ class Parser {
|
| token = parseIdentifier(token);
|
| token = parseQualifiedRestOpt(token);
|
| } else {
|
| - token = listener.expectedType(token);
|
| + token = reportUnrecoverableError(token, ErrorKind.ExpectedType);
|
| }
|
| token = parseTypeArgumentsOpt(token);
|
| listener.endType(begin, token);
|
| @@ -898,13 +906,13 @@ class Parser {
|
|
|
| Link<Token> identifiers = findMemberName(token);
|
| if (identifiers.isEmpty) {
|
| - return listener.expectedDeclaration(start);
|
| + return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration);
|
| }
|
| Token afterName = identifiers.head;
|
| identifiers = identifiers.tail;
|
|
|
| if (identifiers.isEmpty) {
|
| - return listener.expectedDeclaration(start);
|
| + return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration);
|
| }
|
| Token name = identifiers.head;
|
| identifiers = identifiers.tail;
|
| @@ -949,7 +957,7 @@ class Parser {
|
| }
|
| break;
|
| } else {
|
| - token = listener.unexpected(token);
|
| + token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken);
|
| if (identical(token.kind, EOF_TOKEN)) return token;
|
| }
|
| }
|
| @@ -1020,7 +1028,7 @@ class Parser {
|
| ? ErrorKind.ExtraneousModifier
|
| : ErrorKind.ExtraneousModifierReplace;
|
| for (Token modifier in modifierList) {
|
| - listener.reportError(modifier, kind, {'modifier': modifier});
|
| + reportRecoverableError(modifier, kind, {'modifier': modifier});
|
| }
|
| return null;
|
| }
|
| @@ -1061,7 +1069,7 @@ class Parser {
|
| var kind = (hasModifier || hasType)
|
| ? ErrorKind.ExtraneousModifier
|
| : ErrorKind.ExtraneousModifierReplace;
|
| - listener.reportError(getOrSet, kind, {'modifier': getOrSet});
|
| + reportRecoverableError(getOrSet, kind, {'modifier': getOrSet});
|
| }
|
|
|
| if (!hasType) {
|
| @@ -1071,11 +1079,11 @@ class Parser {
|
| // TODO(ahe): This error is reported twice, second time is from
|
| // [parseVariablesDeclarationMaybeSemicolon] via
|
| // [PartialFieldListElement.parseNode].
|
| - listener.reportError(type, ErrorKind.InvalidVoid);
|
| + reportRecoverableError(type, ErrorKind.InvalidVoid);
|
| } else {
|
| parseType(type);
|
| if (isVar) {
|
| - listener.reportError(modifiers.head, ErrorKind.ExtraneousModifier,
|
| + reportRecoverableError(modifiers.head, ErrorKind.ExtraneousModifier,
|
| {'modifier': modifiers.head});
|
| }
|
| }
|
| @@ -1108,7 +1116,7 @@ class Parser {
|
| if (externalModifier == null && optional('external', modifier)) {
|
| externalModifier = modifier;
|
| } else {
|
| - listener.reportError(
|
| + reportRecoverableError(
|
| modifier, ErrorKind.ExtraneousModifier, {'modifier': modifier});
|
| }
|
| }
|
| @@ -1139,7 +1147,7 @@ class Parser {
|
| Token endToken = token;
|
| token = token.next;
|
| if (token.kind == BAD_INPUT_TOKEN) {
|
| - token = listener.unexpected(token);
|
| + token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken);
|
| }
|
| listener.endTopLevelMethod(start, getOrSet, endToken);
|
| return token;
|
| @@ -1216,7 +1224,7 @@ class Parser {
|
| if (token.next is BeginGroupToken) {
|
| BeginGroupToken beginGroup = token.next;
|
| if (beginGroup.endGroup == null) {
|
| - listener.unmatched(beginGroup);
|
| + reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken);
|
| }
|
| token = beginGroup.endGroup;
|
| }
|
| @@ -1279,7 +1287,7 @@ class Parser {
|
| if (identical(token.kind, STRING_TOKEN)) {
|
| return parseLiteralString(token);
|
| } else {
|
| - listener.reportError(token, ErrorKind.ExpectedString);
|
| + reportRecoverableError(token, ErrorKind.ExpectedString);
|
| return parseExpression(token);
|
| }
|
| }
|
| @@ -1311,7 +1319,7 @@ class Parser {
|
| if (isModifier(token)) {
|
| parseModifier(token);
|
| } else {
|
| - listener.unexpected(token);
|
| + reportUnrecoverableError(token, ErrorKind.UnexpectedToken);
|
| // Skip the remaining modifiers.
|
| break;
|
| }
|
| @@ -1372,14 +1380,16 @@ class Parser {
|
|
|
| Token skipClassBody(Token token) {
|
| if (!optional('{', token)) {
|
| - return listener.expectedClassBodyToSkip(token);
|
| + return reportUnrecoverableError(token, ErrorKind.ExpectedClassBodyToSkip);
|
| }
|
| BeginGroupToken beginGroupToken = token;
|
| Token endGroup = beginGroupToken.endGroup;
|
| if (endGroup == null) {
|
| - return listener.unmatched(beginGroupToken);
|
| + return reportUnrecoverableError(
|
| + beginGroupToken, ErrorKind.UnmatchedToken);
|
| } else if (!identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) {
|
| - return listener.unmatched(beginGroupToken);
|
| + return reportUnrecoverableError(
|
| + beginGroupToken, ErrorKind.UnmatchedToken);
|
| }
|
| return endGroup;
|
| }
|
| @@ -1388,7 +1398,7 @@ class Parser {
|
| Token begin = token;
|
| listener.beginClassBody(token);
|
| if (!optional('{', token)) {
|
| - token = listener.expectedClassBody(token);
|
| + token = reportUnrecoverableError(token, ErrorKind.ExpectedClassBody);
|
| }
|
| token = token.next;
|
| int count = 0;
|
| @@ -1425,13 +1435,13 @@ class Parser {
|
|
|
| Link<Token> identifiers = findMemberName(token);
|
| if (identifiers.isEmpty) {
|
| - return listener.expectedDeclaration(start);
|
| + return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration);
|
| }
|
| Token afterName = identifiers.head;
|
| identifiers = identifiers.tail;
|
|
|
| if (identifiers.isEmpty) {
|
| - return listener.expectedDeclaration(start);
|
| + return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration);
|
| }
|
| Token name = identifiers.head;
|
| identifiers = identifiers.tail;
|
| @@ -1483,7 +1493,7 @@ class Parser {
|
| isField = true;
|
| break;
|
| } else {
|
| - token = listener.unexpected(token);
|
| + token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken);
|
| if (identical(token.kind, EOF_TOKEN)) {
|
| // TODO(ahe): This is a hack, see parseTopLevelMember.
|
| listener.endFields(1, start, token);
|
| @@ -1515,7 +1525,7 @@ class Parser {
|
| modifierCount++;
|
| externalModifier = modifier;
|
| if (modifierCount != allowedModifierCount) {
|
| - listener.reportError(modifier, ErrorKind.ExtraneousModifier,
|
| + reportRecoverableError(modifier, ErrorKind.ExtraneousModifier,
|
| {'modifier': modifier});
|
| }
|
| allowedModifierCount++;
|
| @@ -1523,23 +1533,23 @@ class Parser {
|
| modifierCount++;
|
| staticModifier = modifier;
|
| if (modifierCount != allowedModifierCount) {
|
| - listener.reportError(modifier, ErrorKind.ExtraneousModifier,
|
| + reportRecoverableError(modifier, ErrorKind.ExtraneousModifier,
|
| {'modifier': modifier});
|
| }
|
| } else if (constModifier == null && optional('const', modifier)) {
|
| modifierCount++;
|
| constModifier = modifier;
|
| if (modifierCount != allowedModifierCount) {
|
| - listener.reportError(modifier, ErrorKind.ExtraneousModifier,
|
| + reportRecoverableError(modifier, ErrorKind.ExtraneousModifier,
|
| {'modifier': modifier});
|
| }
|
| } else {
|
| - listener.reportError(
|
| + reportRecoverableError(
|
| modifier, ErrorKind.ExtraneousModifier, {'modifier': modifier});
|
| }
|
| }
|
| if (getOrSet != null && constModifier != null) {
|
| - listener.reportError(constModifier, ErrorKind.ExtraneousModifier,
|
| + reportRecoverableError(constModifier, ErrorKind.ExtraneousModifier,
|
| {'modifier': constModifier});
|
| }
|
| parseModifierList(modifiers);
|
| @@ -1553,7 +1563,7 @@ class Parser {
|
| if (optional('operator', name)) {
|
| token = parseOperatorName(name);
|
| if (staticModifier != null) {
|
| - listener.reportError(staticModifier, ErrorKind.ExtraneousModifier,
|
| + reportRecoverableError(staticModifier, ErrorKind.ExtraneousModifier,
|
| {'modifier': staticModifier});
|
| }
|
| } else {
|
| @@ -1741,7 +1751,7 @@ class Parser {
|
| String value = token.stringValue;
|
| if (identical(value, ';')) {
|
| if (!allowAbstract) {
|
| - listener.reportError(token, ErrorKind.ExpectedBody);
|
| + reportRecoverableError(token, ErrorKind.ExpectedBody);
|
| }
|
| listener.handleNoFunctionBody(token);
|
| } else {
|
| @@ -1762,7 +1772,7 @@ class Parser {
|
| Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) {
|
| if (optional(';', token)) {
|
| if (!allowAbstract) {
|
| - listener.reportError(token, ErrorKind.ExpectedBody);
|
| + reportRecoverableError(token, ErrorKind.ExpectedBody);
|
| }
|
| listener.endFunctionBody(0, null, token);
|
| return token;
|
| @@ -1780,7 +1790,7 @@ class Parser {
|
| Token begin = token;
|
| int statementCount = 0;
|
| if (!optional('{', token)) {
|
| - return listener.expectedFunctionBody(token);
|
| + return reportUnrecoverableError(token, ErrorKind.ExpectedFunctionBody);
|
| }
|
|
|
| listener.beginFunctionBody(begin);
|
| @@ -1834,7 +1844,7 @@ class Parser {
|
| star = token;
|
| token = token.next;
|
| } else {
|
| - listener.reportError(async, ErrorKind.InvalidSyncModifier);
|
| + reportRecoverableError(async, ErrorKind.InvalidSyncModifier);
|
| }
|
| }
|
| listener.handleAsyncModifier(async, star);
|
| @@ -2139,7 +2149,7 @@ class Parser {
|
| BeginGroupToken begin = token;
|
| token = (begin.endGroup != null) ? begin.endGroup : token;
|
| } else if (token is ErrorToken) {
|
| - listener.reportErrorToken(token);
|
| + reportErrorToken(token, false);
|
| }
|
| token = token.next;
|
| }
|
| @@ -2209,7 +2219,7 @@ class Parser {
|
| listener.handleUnaryPostfixAssignmentExpression(token);
|
| token = token.next;
|
| } else {
|
| - token = listener.unexpected(token);
|
| + token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken);
|
| }
|
| } else if (identical(info, IS_INFO)) {
|
| token = parseIsOperatorRest(token);
|
| @@ -2249,7 +2259,7 @@ class Parser {
|
| token = parseSend(token);
|
| listener.handleBinaryExpression(cascadeOperator);
|
| } else {
|
| - return listener.unexpected(token);
|
| + return reportUnrecoverableError(token, ErrorKind.UnexpectedToken);
|
| }
|
| Token mark;
|
| do {
|
| @@ -2278,7 +2288,7 @@ class Parser {
|
| return parseAwaitExpression(token, allowCascades);
|
| } else if (identical(value, '+')) {
|
| // Dart no longer allows prefix-plus.
|
| - listener.reportError(token, ErrorKind.UnsupportedPrefixPlus);
|
| + reportRecoverableError(token, ErrorKind.UnsupportedPrefixPlus);
|
| return parseUnaryExpression(token.next, allowCascades);
|
| } else if ((identical(value, '!')) ||
|
| (identical(value, '-')) ||
|
| @@ -2354,11 +2364,11 @@ class Parser {
|
| return parseFunctionExpression(token);
|
| } else if (asyncAwaitKeywordsEnabled &&
|
| (value == 'yield' || value == 'async')) {
|
| - return listener.expectedExpression(token);
|
| + return reportUnrecoverableError(token, ErrorKind.ExpectedExpression);
|
| } else if (token.isIdentifier()) {
|
| return parseSendOrFunctionLiteral(token);
|
| } else {
|
| - return listener.expectedExpression(token);
|
| + return reportUnrecoverableError(token, ErrorKind.ExpectedExpression);
|
| }
|
| } else if (kind == OPEN_PAREN_TOKEN) {
|
| return parseParenthesizedExpressionOrFunctionLiteral(token);
|
| @@ -2371,7 +2381,7 @@ class Parser {
|
| } else if (kind == LT_TOKEN) {
|
| return parseLiteralListOrMapOrFunction(token, null);
|
| } else {
|
| - return listener.expectedExpression(token);
|
| + return reportUnrecoverableError(token, ErrorKind.ExpectedExpression);
|
| }
|
| }
|
|
|
| @@ -2404,7 +2414,7 @@ class Parser {
|
| // [begin] is now known to have type [BeginGroupToken].
|
| token = parseExpression(token);
|
| if (!identical(begin.endGroup, token)) {
|
| - listener.unexpected(token);
|
| + reportUnrecoverableError(token, ErrorKind.UnexpectedToken);
|
| token = begin.endGroup;
|
| }
|
| listener.handleParenthesizedExpression(begin);
|
| @@ -2506,7 +2516,7 @@ class Parser {
|
| }
|
| // Fall through.
|
| }
|
| - listener.unexpected(token);
|
| + reportUnrecoverableError(token, ErrorKind.UnexpectedToken);
|
| return null;
|
| }
|
|
|
| @@ -2534,7 +2544,7 @@ class Parser {
|
| } else if ((optional('[', token)) || (optional('[]', token))) {
|
| return parseLiteralListSuffix(token, constKeyword);
|
| }
|
| - listener.unexpected(token);
|
| + reportUnrecoverableError(token, ErrorKind.UnexpectedToken);
|
| return null;
|
| }
|
| }
|
| @@ -2589,7 +2599,7 @@ class Parser {
|
| token = parseArguments(token);
|
| } else {
|
| listener.handleNoArguments(token);
|
| - token = listener.unexpected(token);
|
| + token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken);
|
| }
|
| return token;
|
| }
|
| @@ -2787,7 +2797,7 @@ class Parser {
|
| if (identical(value, 'is') || identical(value, 'as')) {
|
| // The is- and as-operators cannot be chained, but they can take part of
|
| // expressions like: foo is Foo || foo is Bar.
|
| - listener.unexpected(token);
|
| + reportUnrecoverableError(token, ErrorKind.UnexpectedToken);
|
| }
|
| return token;
|
| }
|
| @@ -2800,7 +2810,7 @@ class Parser {
|
| String value = token.stringValue;
|
| if (identical(value, 'is') || identical(value, 'as')) {
|
| // The is- and as-operators cannot be chained.
|
| - listener.unexpected(token);
|
| + reportUnrecoverableError(token, ErrorKind.UnexpectedToken);
|
| }
|
| return token;
|
| }
|
| @@ -2873,7 +2883,7 @@ class Parser {
|
| return parseForInRest(awaitToken, forToken, token);
|
| } else {
|
| if (awaitToken != null) {
|
| - listener.reportError(awaitToken, ErrorKind.InvalidAwaitFor);
|
| + reportRecoverableError(awaitToken, ErrorKind.InvalidAwaitFor);
|
| }
|
| return parseForRest(forToken, token);
|
| }
|
| @@ -3125,7 +3135,9 @@ class Parser {
|
| peek = peekPastLabels(token);
|
| } else {
|
| if (expressionCount == 0) {
|
| - listener.expected("case", token);
|
| + // TODO(ahe): This is probably easy to recover from.
|
| + reportUnrecoverableError(
|
| + token, ErrorKind.ExpectedButGot, {"expected": "case"});
|
| }
|
| break;
|
| }
|
| @@ -3200,4 +3212,101 @@ class Parser {
|
| listener.handleEmptyStatement(token);
|
| return expectSemicolon(token);
|
| }
|
| +
|
| + /// Don't call this method. Should only be used as a last resort when there
|
| + /// is no feasible way to recover from a parser error.
|
| + Token reportUnrecoverableError(Token token, ErrorKind kind, [Map arguments]) {
|
| + Token next;
|
| + if (token is ErrorToken) {
|
| + next = reportErrorToken(token, false);
|
| + } else {
|
| + arguments ??= {};
|
| + arguments.putIfAbsent("actual", () => token.value);
|
| + next = listener.handleUnrecoverableError(token, kind, arguments);
|
| + }
|
| + return next ?? skipToEof(token);
|
| + }
|
| +
|
| + void reportRecoverableError(Token token, ErrorKind kind, [Map arguments]) {
|
| + if (token is ErrorToken) {
|
| + reportErrorToken(token, true);
|
| + } else {
|
| + arguments ??= {};
|
| + listener.handleRecoverableError(token, kind, arguments);
|
| + }
|
| + }
|
| +
|
| + Token reportErrorToken(ErrorToken token, bool isRecoverable) {
|
| + ErrorKind kind;
|
| + Map arguments = const {};
|
| + if (token is BadInputToken) {
|
| + String hex = token.character.toRadixString(16);
|
| + if (hex.length < 4) {
|
| + String padding = "0000".substring(hex.length);
|
| + hex = "$padding$hex";
|
| + }
|
| + kind = ErrorKind.InvalidInputCharacter;
|
| + arguments = {'characterHex': hex};
|
| + } else if (token is UnterminatedToken) {
|
| + switch (token.start) {
|
| + case '1e':
|
| + kind = ErrorKind.MissingExponent;
|
| + break;
|
| + case '"':
|
| + case "'":
|
| + case '"""':
|
| + case "'''":
|
| + case 'r"':
|
| + case "r'":
|
| + case 'r"""':
|
| + case "r'''":
|
| + kind = ErrorKind.UnterminatedString;
|
| + arguments = {'quote': token.start};
|
| + break;
|
| + case '0x':
|
| + kind = ErrorKind.ExpectedHexDigit;
|
| + break;
|
| + case r'$':
|
| + kind = ErrorKind.MalformedStringLiteral;
|
| + break;
|
| + case '/*':
|
| + kind = ErrorKind.UnterminatedComment;
|
| + break;
|
| + default:
|
| + kind = ErrorKind.UnterminatedToken;
|
| + break;
|
| + }
|
| + } else if (token is UnmatchedToken) {
|
| + String begin = token.begin.value;
|
| + String end = closeBraceFor(begin);
|
| + kind = ErrorKind.UnmatchedToken;
|
| + arguments = {'begin': begin, 'end': end};
|
| + } else {
|
| + return listener.handleUnrecoverableError(
|
| + token, ErrorKind.Unspecified, {"text": token.assertionMessage});
|
| + }
|
| + if (isRecoverable) {
|
| + listener.handleRecoverableError(token, kind, arguments);
|
| + return null;
|
| + } else {
|
| + return listener.handleUnrecoverableError(token, kind, arguments);
|
| + }
|
| + }
|
| +}
|
| +
|
| +String closeBraceFor(String openBrace) {
|
| + return const {
|
| + '(': ')',
|
| + '[': ']',
|
| + '{': '}',
|
| + '<': '>',
|
| + r'${': '}',
|
| + }[openBrace];
|
| +}
|
| +
|
| +Token skipToEof(Token token) {
|
| + while (!identical(token.info, EOF_INFO)) {
|
| + token = token.next;
|
| + }
|
| + return token;
|
| }
|
|
|