// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library analyzer.src.generated.parser;

import 'dart:collection';
import "dart:math" as math;

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';

export 'package:analyzer/src/dart/ast/utilities.dart' show ResolutionCopier;
export 'package:analyzer/src/dart/error/syntactic_errors.dart';

/**
 * A simple data-holder for a method that needs to return multiple values.
 */
class CommentAndMetadata {
  /**
   * The documentation comment that was parsed, or `null` if none was given.
   */
  final Comment comment;

  /**
   * The metadata that was parsed, or `null` if none was given.
   */
  final List<Annotation> metadata;

  /**
   * Initialize a newly created holder with the given [comment] and [metadata].
   */
  CommentAndMetadata(this.comment, this.metadata);

  /**
   * Return `true` if some metadata was parsed.
   */
  bool get hasMetadata => metadata != null && metadata.isNotEmpty;
}

/**
 * A simple data-holder for a method that needs to return multiple values.
 */
class FinalConstVarOrType {
  /**
   * The 'final', 'const' or 'var' keyword, or `null` if none was given.
   */
  final Token keyword;

  /**
   * The type, or `null` if no type was specified.
   */
  final TypeAnnotation type;

  /**
   * Initialize a newly created holder with the given [keyword] and [type].
   */
  FinalConstVarOrType(this.keyword, this.type);
}

/**
 * A simple data-holder for a method that needs to return multiple values.
 */
class Modifiers {
  /**
   * The token representing the keyword 'abstract', or `null` if the keyword was
   * not found.
   */
  Token abstractKeyword;

  /**
   * The token representing the keyword 'const', or `null` if the keyword was
   * not found.
   */
  Token constKeyword;

  /**
   * The token representing the keyword 'covariant', or `null` if the keyword
   * was not found.
   */
  Token covariantKeyword;

  /**
   * The token representing the keyword 'external', or `null` if the keyword was
   * not found.
   */
  Token externalKeyword;

  /**
   * The token representing the keyword 'factory', or `null` if the keyword was
   * not found.
   */
  Token factoryKeyword;

  /**
   * The token representing the keyword 'final', or `null` if the keyword was
   * not found.
   */
  Token finalKeyword;

  /**
   * The token representing the keyword 'static', or `null` if the keyword was
   * not found.
   */
  Token staticKeyword;

  /**
   * The token representing the keyword 'var', or `null` if the keyword was not
   * found.
   */
  Token varKeyword;

  @override
  String toString() {
    StringBuffer buffer = new StringBuffer();
    bool needsSpace = _appendKeyword(buffer, false, abstractKeyword);
    needsSpace = _appendKeyword(buffer, needsSpace, constKeyword);
    needsSpace = _appendKeyword(buffer, needsSpace, externalKeyword);
    needsSpace = _appendKeyword(buffer, needsSpace, factoryKeyword);
    needsSpace = _appendKeyword(buffer, needsSpace, finalKeyword);
    needsSpace = _appendKeyword(buffer, needsSpace, staticKeyword);
    _appendKeyword(buffer, needsSpace, varKeyword);
    return buffer.toString();
  }

  /**
   * If the given [keyword] is not `null`, append it to the given [builder],
   * prefixing it with a space if [needsSpace] is `true`. Return `true` if
   * subsequent keywords need to be prefixed with a space.
   */
  bool _appendKeyword(StringBuffer buffer, bool needsSpace, Token keyword) {
    if (keyword != null) {
      if (needsSpace) {
        buffer.writeCharCode(0x20);
      }
      buffer.write(keyword.lexeme);
      return true;
    }
    return needsSpace;
  }
}

/**
 * A parser used to parse tokens into an AST structure.
 */
class Parser {
  static String ASYNC = Keyword.ASYNC.syntax;

  static String _AWAIT = Keyword.AWAIT.syntax;

  static String _HIDE = Keyword.HIDE.syntax;

  static String _SHOW = Keyword.SHOW.syntax;

  static String SYNC = Keyword.SYNC.syntax;

  static String _YIELD = Keyword.YIELD.syntax;

  static const int _MAX_TREE_DEPTH = 300;

  /**
   * The source being parsed.
   */
  final Source _source;

  /**
   * The error listener that will be informed of any errors that are found
   * during the parse.
   */
  final AnalysisErrorListener _errorListener;

  /**
   * An [_errorListener] lock, if more than `0`, then errors are not reported.
   */
  int _errorListenerLock = 0;

  /**
   * A flag indicating whether the parser is to parse asserts in the initializer
   * list of a constructor.
   */
  bool _enableAssertInitializer = false;

  /**
   * A flag indicating whether the parser is to parse the non-nullable modifier
   * in type names.
   */
  bool _enableNnbd = false;

  /**
   * A flag indicating whether the parser is to allow URI's in part-of
   * directives.
   */
  bool _enableUriInPartOf = true;

  /**
   * A flag indicating whether parser is to parse function bodies.
   */
  bool _parseFunctionBodies = true;

  /**
   * The next token to be parsed.
   */
  Token _currentToken;

  /**
   * The depth of the current AST. When this depth is too high, so we're at the
   * risk of overflowing the stack, we stop parsing and report an error.
   */
  int _treeDepth = 0;

  /**
   * A flag indicating whether the parser is currently in a function body marked
   * as being 'async'.
   */
  bool _inAsync = false;

  /**
   * A flag indicating whether the parser is currently in a function body marked
   * (by a star) as being a generator.
   */
  bool _inGenerator = false;

  /**
   * A flag indicating whether the parser is currently in the body of a loop.
   */
  bool _inLoop = false;

  /**
   * A flag indicating whether the parser is currently in a switch statement.
   */
  bool _inSwitch = false;

  /**
   * A flag indicating whether the parser is currently in a constructor field
   * initializer, with no intervening parentheses, braces, or brackets.
   */
  bool _inInitializer = false;

  /**
   * A flag indicating whether the parser is to parse generic method syntax.
   */
  @deprecated
  bool parseGenericMethods = false;

  /**
   * A flag indicating whether to parse generic method comments, of the form
   * `/*=T*/` and `/*<T>*/`.
   */
  bool parseGenericMethodComments = false;

  /**
   * Initialize a newly created parser to parse tokens in the given [_source]
   * and to report any errors that are found to the given [_errorListener].
   */
  Parser(this._source, this._errorListener);

  /**
   * Return the current token.
   */
  Token get currentToken => _currentToken;

  /**
   * Set the token with which the parse is to begin to the given [token].
   */
  void set currentToken(Token token) {
    this._currentToken = token;
  }

  /**
   * Return `true` if the parser is to parse asserts in the initializer list of
   * a constructor.
   */
  bool get enableAssertInitializer => _enableAssertInitializer;

  /**
   * Set whether the parser is to parse asserts in the initializer list of a
   * constructor to match the given [enable] flag.
   */
  void set enableAssertInitializer(bool enable) {
    _enableAssertInitializer = enable;
  }

  /**
   * Return `true` if the parser is to parse the non-nullable modifier in type
   * names.
   */
  bool get enableNnbd => _enableNnbd;

  /**
   * Set whether the parser is to parse the non-nullable modifier in type names
   * to match the given [enable] flag.
   */
  void set enableNnbd(bool enable) {
    _enableNnbd = enable;
  }

  /**
   * Return `true` if the parser is to allow URI's in part-of directives.
   */
  bool get enableUriInPartOf => _enableUriInPartOf;

  /**
   * Set whether the parser is to allow URI's in part-of directives to the given
   * [enable] flag.
   */
  void set enableUriInPartOf(bool enable) {
    _enableUriInPartOf = enable;
  }

  /**
   * Return `true` if the current token is the first token of a return type that
   * is followed by an identifier, possibly followed by a list of type
   * parameters, followed by a left-parenthesis. This is used by
   * [parseTypeAlias] to determine whether or not to parse a return type.
   */
  bool get hasReturnTypeInTypeAlias {
    // TODO(brianwilkerson) This is too expensive as implemented and needs to be
    // re-implemented or removed.
    Token next = skipReturnType(_currentToken);
    if (next == null) {
      return false;
    }
    return _tokenMatchesIdentifier(next);
  }

  /**
   * Set whether the parser is to parse the async support.
   *
   * Support for removing the 'async' library has been removed.
   */
  @deprecated
  void set parseAsync(bool parseAsync) {}

  @deprecated
  bool get parseConditionalDirectives => true;

  @deprecated
  void set parseConditionalDirectives(bool value) {}

  /**
   * Set whether parser is to parse function bodies.
   */
  void set parseFunctionBodies(bool parseFunctionBodies) {
    this._parseFunctionBodies = parseFunctionBodies;
  }

  /**
   * Return the content of a string with the given literal representation. The
   * [lexeme] is the literal representation of the string. The flag [isFirst] is
   * `true` if this is the first token in a string literal. The flag [isLast] is
   * `true` if this is the last token in a string literal.
   */
  String computeStringValue(String lexeme, bool isFirst, bool isLast) {
    StringLexemeHelper helper = new StringLexemeHelper(lexeme, isFirst, isLast);
    int start = helper.start;
    int end = helper.end;
    bool stringEndsAfterStart = end >= start;
    assert(stringEndsAfterStart);
    if (!stringEndsAfterStart) {
      AnalysisEngine.instance.logger.logError(
          "Internal error: computeStringValue($lexeme, $isFirst, $isLast)");
      return "";
    }
    if (helper.isRaw) {
      return lexeme.substring(start, end);
    }
    StringBuffer buffer = new StringBuffer();
    int index = start;
    while (index < end) {
      index = _translateCharacter(buffer, lexeme, index);
    }
    return buffer.toString();
  }

  /**
   * Return a synthetic identifier.
   */
  SimpleIdentifier createSyntheticIdentifier({bool isDeclaration: false}) {
    Token syntheticToken;
    if (_currentToken.type == TokenType.KEYWORD) {
      // Consider current keyword token as an identifier.
      // It is not always true, e.g. "^is T" where "^" is place the place for
      // synthetic identifier. By creating SyntheticStringToken we can
      // distinguish a real identifier from synthetic. In the code completion
      // behavior will depend on a cursor position - before or on "is".
      syntheticToken = _injectToken(new SyntheticStringToken(
          TokenType.IDENTIFIER, _currentToken.lexeme, _currentToken.offset));
    } else {
      syntheticToken = _createSyntheticToken(TokenType.IDENTIFIER);
    }
    return astFactory.simpleIdentifier(syntheticToken,
        isDeclaration: isDeclaration);
  }

  /**
   * Return a synthetic string literal.
   */
  SimpleStringLiteral createSyntheticStringLiteral() => astFactory
      .simpleStringLiteral(_createSyntheticToken(TokenType.STRING), "");

  /**
   * Advance to the next token in the token stream, making it the new current
   * token and return the token that was current before this method was invoked.
   */
  Token getAndAdvance() {
    Token token = _currentToken;
    _currentToken = _currentToken.next;
    return token;
  }

  /**
   * Return `true` if the current token appears to be the beginning of a
   * function declaration.
   */
  bool isFunctionDeclaration() {
    Keyword keyword = _currentToken.keyword;
    if (keyword == Keyword.VOID) {
      return true;
    }
    Token afterReturnType = skipTypeName(_currentToken);
    if (afterReturnType != null &&
        _tokenMatchesKeyword(afterReturnType, Keyword.FUNCTION)) {
      afterReturnType = skipGenericFunctionTypeAfterReturnType(afterReturnType);
    }
    if (afterReturnType == null) {
      // There was no return type, but it is optional, so go back to where we
      // started.
      afterReturnType = _currentToken;
    }
    Token afterIdentifier = skipSimpleIdentifier(afterReturnType);
    if (afterIdentifier == null) {
      // It's possible that we parsed the function name as if it were a type
      // name, so see whether it makes sense if we assume that there is no type.
      afterIdentifier = skipSimpleIdentifier(_currentToken);
    }
    if (afterIdentifier == null) {
      return false;
    }
    if (isFunctionExpression(afterIdentifier)) {
      return true;
    }
    // It's possible that we have found a getter. While this isn't valid at this
    // point we test for it in order to recover better.
    if (keyword == Keyword.GET) {
      Token afterName = skipSimpleIdentifier(_currentToken.next);
      if (afterName == null) {
        return false;
      }
      TokenType type = afterName.type;
      return type == TokenType.FUNCTION || type == TokenType.OPEN_CURLY_BRACKET;
    } else if (_tokenMatchesKeyword(afterReturnType, Keyword.GET)) {
      Token afterName = skipSimpleIdentifier(afterReturnType.next);
      if (afterName == null) {
        return false;
      }
      TokenType type = afterName.type;
      return type == TokenType.FUNCTION || type == TokenType.OPEN_CURLY_BRACKET;
    }
    return false;
  }

  /**
   * Return `true` if the given [token] appears to be the beginning of a
   * function expression.
   */
  bool isFunctionExpression(Token token) {
    // Function expressions aren't allowed in initializer lists.
    if (_inInitializer) {
      return false;
    }
    Token afterTypeParameters = _skipTypeParameterList(token);
    if (afterTypeParameters == null) {
      afterTypeParameters = token;
    }
    Token afterParameters = _skipFormalParameterList(afterTypeParameters);
    if (afterParameters == null) {
      return false;
    }
    if (afterParameters.matchesAny(
        const <TokenType>[TokenType.OPEN_CURLY_BRACKET, TokenType.FUNCTION])) {
      return true;
    }
    String lexeme = afterParameters.lexeme;
    return lexeme == ASYNC || lexeme == SYNC;
  }

  /**
   * Return `true` if the current token is the first token in an initialized
   * variable declaration rather than an expression. This method assumes that we
   * have already skipped past any metadata that might be associated with the
   * declaration.
   *
   *     initializedVariableDeclaration ::=
   *         declaredIdentifier ('=' expression)? (',' initializedIdentifier)*
   *
   *     declaredIdentifier ::=
   *         metadata finalConstVarOrType identifier
   *
   *     finalConstVarOrType ::=
   *         'final' type?
   *       | 'const' type?
   *       | 'var'
   *       | type
   *
   *     type ::=
   *         qualified typeArguments?
   *
   *     initializedIdentifier ::=
   *         identifier ('=' expression)?
   */
  bool isInitializedVariableDeclaration() {
    Keyword keyword = _currentToken.keyword;
    if (keyword == Keyword.FINAL || keyword == Keyword.VAR) {
      // An expression cannot start with a keyword other than 'const',
      // 'rethrow', or 'throw'.
      return true;
    }
    if (keyword == Keyword.CONST) {
      // Look to see whether we might be at the start of a list or map literal,
      // otherwise this should be the start of a variable declaration.
      return !_peek().matchesAny(const <TokenType>[
        TokenType.LT,
        TokenType.OPEN_CURLY_BRACKET,
        TokenType.OPEN_SQUARE_BRACKET,
        TokenType.INDEX
      ]);
    }
    bool allowAdditionalTokens = true;
    // We know that we have an identifier, and need to see whether it might be
    // a type name.
    if (_currentToken.type != TokenType.IDENTIFIER) {
      allowAdditionalTokens = false;
    }
    Token token = skipTypeName(_currentToken);
    if (token == null) {
      // There was no type name, so this can't be a declaration.
      return false;
    }
    while (_atGenericFunctionTypeAfterReturnType(token)) {
      token = skipGenericFunctionTypeAfterReturnType(token);
      if (token == null) {
        // There was no type name, so this can't be a declaration.
        return false;
      }
    }
    if (token.type != TokenType.IDENTIFIER) {
      allowAdditionalTokens = false;
    }
    token = skipSimpleIdentifier(token);
    if (token == null) {
      return false;
    }
    TokenType type = token.type;
    // Usual cases in valid code:
    //     String v = '';
    //     String v, v2;
    //     String v;
    //     for (String item in items) {}
    if (type == TokenType.EQ ||
        type == TokenType.COMMA ||
        type == TokenType.SEMICOLON ||
        token.keyword == Keyword.IN) {
      return true;
    }
    // It is OK to parse as a variable declaration in these cases:
    //     String v }
    //     String v if (true) print('OK');
    //     String v { print(42); }
    // ...but not in these cases:
    //     get getterName {
    //     String get getterName
    if (allowAdditionalTokens) {
      if (type == TokenType.CLOSE_CURLY_BRACKET ||
          type == TokenType.KEYWORD ||
          type == TokenType.IDENTIFIER ||
          type == TokenType.OPEN_CURLY_BRACKET) {
        return true;
      }
    }
    return false;
  }

  /**
   * Return `true` if the current token appears to be the beginning of a switch
   * member.
   */
  bool isSwitchMember() {
    Token token = _currentToken;
    while (_tokenMatches(token, TokenType.IDENTIFIER) &&
        _tokenMatches(token.next, TokenType.COLON)) {
      token = token.next.next;
    }
    Keyword keyword = token.keyword;
    return keyword == Keyword.CASE || keyword == Keyword.DEFAULT;
  }

  /**
   * Parse an additive expression. Return the additive expression that was
   * parsed.
   *
   *     additiveExpression ::=
   *         multiplicativeExpression (additiveOperator multiplicativeExpression)*
   *       | 'super' (additiveOperator multiplicativeExpression)+
   */
  Expression parseAdditiveExpression() {
    Expression expression;
    if (_currentToken.keyword == Keyword.SUPER &&
        _currentToken.next.type.isAdditiveOperator) {
      expression = astFactory.superExpression(getAndAdvance());
    } else {
      expression = parseMultiplicativeExpression();
    }
    while (_currentToken.type.isAdditiveOperator) {
      expression = astFactory.binaryExpression(
          expression, getAndAdvance(), parseMultiplicativeExpression());
    }
    return expression;
  }

  /**
   * Parse an annotation. Return the annotation that was parsed.
   *
   * This method assumes that the current token matches [TokenType.AT].
   *
   *     annotation ::=
   *         '@' qualified ('.' identifier)? arguments?
   */
  Annotation parseAnnotation() {
    Token atSign = getAndAdvance();
    Identifier name = parsePrefixedIdentifier();
    Token period = null;
    SimpleIdentifier constructorName = null;
    if (_matches(TokenType.PERIOD)) {
      period = getAndAdvance();
      constructorName = parseSimpleIdentifier();
    }
    ArgumentList arguments = null;
    if (_matches(TokenType.OPEN_PAREN)) {
      arguments = parseArgumentList();
    }
    return astFactory.annotation(
        atSign, name, period, constructorName, arguments);
  }

  /**
   * Parse an argument. Return the argument that was parsed.
   *
   *     argument ::=
   *         namedArgument
   *       | expression
   *
   *     namedArgument ::=
   *         label expression
   */
  Expression parseArgument() {
    // TODO(brianwilkerson) Consider returning a wrapper indicating whether the
    // expression is a named expression in order to remove the 'is' check in
    // 'parseArgumentList'.
    //
    // Both namedArgument and expression can start with an identifier, but only
    // namedArgument can have an identifier followed by a colon.
    //
    if (_matchesIdentifier() && _tokenMatches(_peek(), TokenType.COLON)) {
      return astFactory.namedExpression(parseLabel(), parseExpression2());
    } else {
      return parseExpression2();
    }
  }

  /**
   * Parse a list of arguments. Return the argument list that was parsed.
   *
   * This method assumes that the current token matches [TokenType.OPEN_PAREN].
   *
   *     arguments ::=
   *         '(' argumentList? ')'
   *
   *     argumentList ::=
   *         namedArgument (',' namedArgument)*
   *       | expressionList (',' namedArgument)*
   */
  ArgumentList parseArgumentList() {
    Token leftParenthesis = getAndAdvance();
    if (_matches(TokenType.CLOSE_PAREN)) {
      return astFactory.argumentList(leftParenthesis, null, getAndAdvance());
    }

    /**
     * Return `true` if the parser appears to be at the beginning of an argument
     * even though there was no comma. This is a special case of the more
     * general recovery technique described below.
     */
    bool isLikelyMissingComma() {
      if (_matchesIdentifier() &&
          _tokenMatches(_currentToken.next, TokenType.COLON) &&
          leftParenthesis is BeginToken &&
          leftParenthesis.endToken != null) {
        _reportErrorForToken(
            ParserErrorCode.EXPECTED_TOKEN, _currentToken.previous, [',']);
        return true;
      }
      return false;
    }

    //
    // Even though unnamed arguments must all appear before any named arguments,
    // we allow them to appear in any order so that we can recover faster.
    //
    bool wasInInitializer = _inInitializer;
    _inInitializer = false;
    try {
      Token previousStartOfArgument = _currentToken;
      Expression argument = parseArgument();
      List<Expression> arguments = <Expression>[argument];
      bool foundNamedArgument = argument is NamedExpression;
      bool generatedError = false;
      while (_optional(TokenType.COMMA) ||
          (isLikelyMissingComma() &&
              previousStartOfArgument != _currentToken)) {
        if (_matches(TokenType.CLOSE_PAREN)) {
          break;
        }
        previousStartOfArgument = _currentToken;
        argument = parseArgument();
        arguments.add(argument);
        if (argument is NamedExpression) {
          foundNamedArgument = true;
        } else if (foundNamedArgument) {
          if (!generatedError) {
            if (!argument.isSynthetic) {
              // Report the error, once, but allow the arguments to be in any
              // order in the AST.
              _reportErrorForCurrentToken(
                  ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT);
              generatedError = true;
            }
          }
        }
      }
      // Recovery: If the next token is not a right parenthesis, look at the
      // left parenthesis to see whether there is a matching right parenthesis.
      // If there is, then we're more likely missing a comma and should go back
      // to parsing arguments.
      Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
      return astFactory.argumentList(
          leftParenthesis, arguments, rightParenthesis);
    } finally {
      _inInitializer = wasInInitializer;
    }
  }

  /**
   * Parse an assert statement. Return the assert statement.
   *
   * This method assumes that the current token matches `Keyword.ASSERT`.
   *
   *     assertStatement ::=
   *         'assert' '(' expression [',' expression] ')' ';'
   */
  AssertStatement parseAssertStatement() {
    Token keyword = getAndAdvance();
    Token leftParen = _expect(TokenType.OPEN_PAREN);
    Expression expression = parseExpression2();
    Token comma;
    Expression message;
    if (_matches(TokenType.COMMA)) {
      comma = getAndAdvance();
      message = parseExpression2();
    }
    Token rightParen = _expect(TokenType.CLOSE_PAREN);
    Token semicolon = _expect(TokenType.SEMICOLON);
    return astFactory.assertStatement(
        keyword, leftParen, expression, comma, message, rightParen, semicolon);
  }

  /**
   * Parse an assignable expression. The [primaryAllowed] is `true` if the
   * expression is allowed to be a primary without any assignable selector.
   * Return the assignable expression that was parsed.
   *
   *     assignableExpression ::=
   *         primary (arguments* assignableSelector)+
   *       | 'super' unconditionalAssignableSelector
   *       | identifier
   */
  Expression parseAssignableExpression(bool primaryAllowed) {
    if (_matchesKeyword(Keyword.SUPER)) {
      return parseAssignableSelector(
          astFactory.superExpression(getAndAdvance()), false,
          allowConditional: false);
    }
    return _parseAssignableExpressionNotStartingWithSuper(primaryAllowed);
  }

  /**
   * Parse an assignable selector. The [prefix] is the expression preceding the
   * selector. The [optional] is `true` if the selector is optional. Return the
   * assignable selector that was parsed, or the original prefix if there was no
   * assignable selector.  If [allowConditional] is false, then the '?.'
   * operator will still be parsed, but a parse error will be generated.
   *
   *     unconditionalAssignableSelector ::=
   *         '[' expression ']'
   *       | '.' identifier
   *
   *     assignableSelector ::=
   *         unconditionalAssignableSelector
   *       | '?.' identifier
   */
  Expression parseAssignableSelector(Expression prefix, bool optional,
      {bool allowConditional: true}) {
    TokenType type = _currentToken.type;
    if (type == TokenType.OPEN_SQUARE_BRACKET) {
      Token leftBracket = getAndAdvance();
      bool wasInInitializer = _inInitializer;
      _inInitializer = false;
      try {
        Expression index = parseExpression2();
        Token rightBracket = _expect(TokenType.CLOSE_SQUARE_BRACKET);
        return astFactory.indexExpressionForTarget(
            prefix, leftBracket, index, rightBracket);
      } finally {
        _inInitializer = wasInInitializer;
      }
    } else {
      bool isQuestionPeriod = type == TokenType.QUESTION_PERIOD;
      if (type == TokenType.PERIOD || isQuestionPeriod) {
        if (isQuestionPeriod && !allowConditional) {
          _reportErrorForCurrentToken(
              ParserErrorCode.INVALID_OPERATOR_FOR_SUPER,
              [_currentToken.lexeme]);
        }
        Token operator = getAndAdvance();
        return astFactory.propertyAccess(
            prefix, operator, parseSimpleIdentifier());
      } else if (type == TokenType.INDEX) {
        _splitIndex();
        Token leftBracket = getAndAdvance();
        Expression index = parseSimpleIdentifier();
        Token rightBracket = getAndAdvance();
        return astFactory.indexExpressionForTarget(
            prefix, leftBracket, index, rightBracket);
      } else {
        if (!optional) {
          // Report the missing selector.
          _reportErrorForCurrentToken(
              ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR);
        }
        return prefix;
      }
    }
  }

  /**
   * Parse a await expression. Return the await expression that was parsed.
   *
   * This method assumes that the current token matches `_AWAIT`.
   *
   *     awaitExpression ::=
   *         'await' unaryExpression
   */
  AwaitExpression parseAwaitExpression() {
    Token awaitToken = getAndAdvance();
    Expression expression = parseUnaryExpression();
    return astFactory.awaitExpression(awaitToken, expression);
  }

  /**
   * Parse a bitwise and expression. Return the bitwise and expression that was
   * parsed.
   *
   *     bitwiseAndExpression ::=
   *         shiftExpression ('&' shiftExpression)*
   *       | 'super' ('&' shiftExpression)+
   */
  Expression parseBitwiseAndExpression() {
    Expression expression;
    if (_currentToken.keyword == Keyword.SUPER &&
        _currentToken.next.type == TokenType.AMPERSAND) {
      expression = astFactory.superExpression(getAndAdvance());
    } else {
      expression = parseShiftExpression();
    }
    while (_currentToken.type == TokenType.AMPERSAND) {
      expression = astFactory.binaryExpression(
          expression, getAndAdvance(), parseShiftExpression());
    }
    return expression;
  }

  /**
   * Parse a bitwise or expression. Return the bitwise or expression that was
   * parsed.
   *
   *     bitwiseOrExpression ::=
   *         bitwiseXorExpression ('|' bitwiseXorExpression)*
   *       | 'super' ('|' bitwiseXorExpression)+
   */
  Expression parseBitwiseOrExpression() {
    Expression expression;
    if (_currentToken.keyword == Keyword.SUPER &&
        _currentToken.next.type == TokenType.BAR) {
      expression = astFactory.superExpression(getAndAdvance());
    } else {
      expression = parseBitwiseXorExpression();
    }
    while (_currentToken.type == TokenType.BAR) {
      expression = astFactory.binaryExpression(
          expression, getAndAdvance(), parseBitwiseXorExpression());
    }
    return expression;
  }

  /**
   * Parse a bitwise exclusive-or expression. Return the bitwise exclusive-or
   * expression that was parsed.
   *
   *     bitwiseXorExpression ::=
   *         bitwiseAndExpression ('^' bitwiseAndExpression)*
   *       | 'super' ('^' bitwiseAndExpression)+
   */
  Expression parseBitwiseXorExpression() {
    Expression expression;
    if (_currentToken.keyword == Keyword.SUPER &&
        _currentToken.next.type == TokenType.CARET) {
      expression = astFactory.superExpression(getAndAdvance());
    } else {
      expression = parseBitwiseAndExpression();
    }
    while (_currentToken.type == TokenType.CARET) {
      expression = astFactory.binaryExpression(
          expression, getAndAdvance(), parseBitwiseAndExpression());
    }
    return expression;
  }

  /**
   * Parse a block. Return the block that was parsed.
   *
   * This method assumes that the current token matches
   * [TokenType.OPEN_CURLY_BRACKET].
   *
   *     block ::=
   *         '{' statements '}'
   */
  Block parseBlock() {
    bool isEndOfBlock() {
      TokenType type = _currentToken.type;
      return type == TokenType.EOF || type == TokenType.CLOSE_CURLY_BRACKET;
    }

    Token leftBracket = getAndAdvance();
    List<Statement> statements = <Statement>[];
    Token statementStart = _currentToken;
    while (!isEndOfBlock()) {
      Statement statement = parseStatement2();
      if (identical(_currentToken, statementStart)) {
        // Ensure that we are making progress and report an error if we're not.
        _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
            [_currentToken.lexeme]);
        _advance();
      } else if (statement != null) {
        statements.add(statement);
      }
      statementStart = _currentToken;
    }
    // Recovery: If the next token is not a right curly bracket, look at the
    // left curly bracket to see whether there is a matching right bracket. If
    // there is, then we're more likely missing a semi-colon and should go back
    // to parsing statements.
    Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
    return astFactory.block(leftBracket, statements, rightBracket);
  }

  /**
   * Parse a break statement. Return the break statement that was parsed.
   *
   * This method assumes that the current token matches `Keyword.BREAK`.
   *
   *     breakStatement ::=
   *         'break' identifier? ';'
   */
  Statement parseBreakStatement() {
    Token breakKeyword = getAndAdvance();
    SimpleIdentifier label = null;
    if (_matchesIdentifier()) {
      label = _parseSimpleIdentifierUnchecked();
    }
    if (!_inLoop && !_inSwitch && label == null) {
      _reportErrorForToken(ParserErrorCode.BREAK_OUTSIDE_OF_LOOP, breakKeyword);
    }
    Token semicolon = _expect(TokenType.SEMICOLON);
    return astFactory.breakStatement(breakKeyword, label, semicolon);
  }

  /**
   * Parse a cascade section. Return the expression representing the cascaded
   * method invocation.
   *
   * This method assumes that the current token matches
   * `TokenType.PERIOD_PERIOD`.
   *
   *     cascadeSection ::=
   *         '..' (cascadeSelector typeArguments? arguments*)
   *         (assignableSelector typeArguments? arguments*)* cascadeAssignment?
   *
   *     cascadeSelector ::=
   *         '[' expression ']'
   *       | identifier
   *
   *     cascadeAssignment ::=
   *         assignmentOperator expressionWithoutCascade
   */
  Expression parseCascadeSection() {
    Token period = getAndAdvance();
    Expression expression = null;
    SimpleIdentifier functionName = null;
    if (_matchesIdentifier()) {
      functionName = _parseSimpleIdentifierUnchecked();
    } else if (_currentToken.type == TokenType.OPEN_SQUARE_BRACKET) {
      Token leftBracket = getAndAdvance();
      bool wasInInitializer = _inInitializer;
      _inInitializer = false;
      try {
        Expression index = parseExpression2();
        Token rightBracket = _expect(TokenType.CLOSE_SQUARE_BRACKET);
        expression = astFactory.indexExpressionForCascade(
            period, leftBracket, index, rightBracket);
        period = null;
      } finally {
        _inInitializer = wasInInitializer;
      }
    } else {
      _reportErrorForToken(ParserErrorCode.MISSING_IDENTIFIER, _currentToken,
          [_currentToken.lexeme]);
      functionName = createSyntheticIdentifier();
    }
    assert((expression == null && functionName != null) ||
        (expression != null && functionName == null));
    if (_isLikelyArgumentList()) {
      do {
        TypeArgumentList typeArguments = _parseOptionalTypeArguments();
        if (functionName != null) {
          expression = astFactory.methodInvocation(expression, period,
              functionName, typeArguments, parseArgumentList());
          period = null;
          functionName = null;
        } else if (expression == null) {
          // It should not be possible to get here.
          expression = astFactory.methodInvocation(expression, period,
              createSyntheticIdentifier(), typeArguments, parseArgumentList());
        } else {
          expression = astFactory.functionExpressionInvocation(
              expression, typeArguments, parseArgumentList());
        }
      } while (_isLikelyArgumentList());
    } else if (functionName != null) {
      expression = astFactory.propertyAccess(expression, period, functionName);
      period = null;
    }
    assert(expression != null);
    bool progress = true;
    while (progress) {
      progress = false;
      Expression selector = parseAssignableSelector(expression, true);
      if (!identical(selector, expression)) {
        expression = selector;
        progress = true;
        while (_isLikelyArgumentList()) {
          TypeArgumentList typeArguments = _parseOptionalTypeArguments();
          Expression currentExpression = expression;
          if (currentExpression is PropertyAccess) {
            expression = astFactory.methodInvocation(
                currentExpression.target,
                currentExpression.operator,
                currentExpression.propertyName,
                typeArguments,
                parseArgumentList());
          } else {
            expression = astFactory.functionExpressionInvocation(
                expression, typeArguments, parseArgumentList());
          }
        }
      }
    }
    if (_currentToken.type.isAssignmentOperator) {
      Token operator = getAndAdvance();
      _ensureAssignable(expression);
      expression = astFactory.assignmentExpression(
          expression, operator, parseExpressionWithoutCascade());
    }
    return expression;
  }

  /**
   * Parse a class declaration. The [commentAndMetadata] is the metadata to be
   * associated with the member. The [abstractKeyword] is the token for the
   * keyword 'abstract', or `null` if the keyword was not given. Return the
   * class declaration that was parsed.
   *
   * This method assumes that the current token matches `Keyword.CLASS`.
   *
   *     classDeclaration ::=
   *         metadata 'abstract'? 'class' name typeParameterList? (extendsClause withClause?)? implementsClause? '{' classMembers '}' |
   *         metadata 'abstract'? 'class' mixinApplicationClass
   */
  CompilationUnitMember parseClassDeclaration(
      CommentAndMetadata commentAndMetadata, Token abstractKeyword) {
    //
    // Parse the name and type parameters.
    //
    Token keyword = getAndAdvance();
    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
    String className = name.name;
    TypeParameterList typeParameters = null;
    TokenType type = _currentToken.type;
    if (type == TokenType.LT) {
      typeParameters = parseTypeParameterList();
      type = _currentToken.type;
    }
    //
    // Check to see whether this might be a class type alias rather than a class
    // declaration.
    //
    if (type == TokenType.EQ) {
      return _parseClassTypeAliasAfterName(
          commentAndMetadata, abstractKeyword, keyword, name, typeParameters);
    }
    //
    // Parse the clauses. The parser accepts clauses in any order, but will
    // generate errors if they are not in the order required by the
    // specification.
    //
    ExtendsClause extendsClause = null;
    WithClause withClause = null;
    ImplementsClause implementsClause = null;
    bool foundClause = true;
    while (foundClause) {
      Keyword keyword = _currentToken.keyword;
      if (keyword == Keyword.EXTENDS) {
        if (extendsClause == null) {
          extendsClause = parseExtendsClause();
          if (withClause != null) {
            _reportErrorForToken(
                ParserErrorCode.WITH_BEFORE_EXTENDS, withClause.withKeyword);
          } else if (implementsClause != null) {
            _reportErrorForToken(ParserErrorCode.IMPLEMENTS_BEFORE_EXTENDS,
                implementsClause.implementsKeyword);
          }
        } else {
          _reportErrorForToken(ParserErrorCode.MULTIPLE_EXTENDS_CLAUSES,
              extendsClause.extendsKeyword);
          parseExtendsClause();
        }
      } else if (keyword == Keyword.WITH) {
        if (withClause == null) {
          withClause = parseWithClause();
          if (implementsClause != null) {
            _reportErrorForToken(ParserErrorCode.IMPLEMENTS_BEFORE_WITH,
                implementsClause.implementsKeyword);
          }
        } else {
          _reportErrorForToken(
              ParserErrorCode.MULTIPLE_WITH_CLAUSES, withClause.withKeyword);
          parseWithClause();
          // TODO(brianwilkerson) Should we merge the list of applied mixins
          // into a single list?
        }
      } else if (keyword == Keyword.IMPLEMENTS) {
        if (implementsClause == null) {
          implementsClause = parseImplementsClause();
        } else {
          _reportErrorForToken(ParserErrorCode.MULTIPLE_IMPLEMENTS_CLAUSES,
              implementsClause.implementsKeyword);
          parseImplementsClause();
          // TODO(brianwilkerson) Should we merge the list of implemented
          // classes into a single list?
        }
      } else {
        foundClause = false;
      }
    }
    if (withClause != null && extendsClause == null) {
      _reportErrorForToken(
          ParserErrorCode.WITH_WITHOUT_EXTENDS, withClause.withKeyword);
    }
    //
    // Look for and skip over the extra-lingual 'native' specification.
    //
    NativeClause nativeClause = null;
    if (_matchesKeyword(Keyword.NATIVE) &&
        _tokenMatches(_peek(), TokenType.STRING)) {
      nativeClause = _parseNativeClause();
    }
    //
    // Parse the body of the class.
    //
    Token leftBracket = null;
    List<ClassMember> members = null;
    Token rightBracket = null;
    if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
      leftBracket = getAndAdvance();
      members = _parseClassMembers(className, _getEndToken(leftBracket));
      rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
    } else {
      // Recovery: Check for an unmatched closing curly bracket and parse
      // members until it is reached.
      leftBracket = _createSyntheticToken(TokenType.OPEN_CURLY_BRACKET);
      rightBracket = _createSyntheticToken(TokenType.CLOSE_CURLY_BRACKET);
      _reportErrorForCurrentToken(ParserErrorCode.MISSING_CLASS_BODY);
    }
    ClassDeclaration classDeclaration = astFactory.classDeclaration(
        commentAndMetadata.comment,
        commentAndMetadata.metadata,
        abstractKeyword,
        keyword,
        name,
        typeParameters,
        extendsClause,
        withClause,
        implementsClause,
        leftBracket,
        members,
        rightBracket);
    classDeclaration.nativeClause = nativeClause;
    return classDeclaration;
  }

  /**
   * Parse a class member. The [className] is the name of the class containing
   * the member being parsed. Return the class member that was parsed, or `null`
   * if what was found was not a valid class member.
   *
   *     classMemberDefinition ::=
   *         declaration ';'
   *       | methodSignature functionBody
   */
  ClassMember parseClassMember(String className) {
    CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
    Modifiers modifiers = parseModifiers();
    Keyword keyword = _currentToken.keyword;
    if (keyword == Keyword.VOID ||
        _atGenericFunctionTypeAfterReturnType(_currentToken)) {
      TypeAnnotation returnType;
      if (keyword == Keyword.VOID) {
        if (_atGenericFunctionTypeAfterReturnType(_peek())) {
          returnType = parseTypeAnnotation(false);
        } else {
          returnType = astFactory.typeName(
              astFactory.simpleIdentifier(getAndAdvance()), null);
        }
      } else {
        returnType = parseTypeAnnotation(false);
      }
      keyword = _currentToken.keyword;
      Token next = _peek();
      bool isFollowedByIdentifier = _tokenMatchesIdentifier(next);
      if (keyword == Keyword.GET && isFollowedByIdentifier) {
        _validateModifiersForGetterOrSetterOrMethod(modifiers);
        return parseGetter(commentAndMetadata, modifiers.externalKeyword,
            modifiers.staticKeyword, returnType);
      } else if (keyword == Keyword.SET && isFollowedByIdentifier) {
        _validateModifiersForGetterOrSetterOrMethod(modifiers);
        return parseSetter(commentAndMetadata, modifiers.externalKeyword,
            modifiers.staticKeyword, returnType);
      } else if (keyword == Keyword.OPERATOR && _isOperator(next)) {
        _validateModifiersForOperator(modifiers);
        return _parseOperatorAfterKeyword(commentAndMetadata,
            modifiers.externalKeyword, returnType, getAndAdvance());
      } else if (_matchesIdentifier() &&
          _peek().matchesAny(const <TokenType>[
            TokenType.OPEN_PAREN,
            TokenType.OPEN_CURLY_BRACKET,
            TokenType.FUNCTION,
            TokenType.LT
          ])) {
        _validateModifiersForGetterOrSetterOrMethod(modifiers);
        return _parseMethodDeclarationAfterReturnType(commentAndMetadata,
            modifiers.externalKeyword, modifiers.staticKeyword, returnType);
      } else if (_matchesIdentifier() &&
          _peek().matchesAny(const <TokenType>[
            TokenType.EQ,
            TokenType.COMMA,
            TokenType.SEMICOLON
          ])) {
        if (returnType is! GenericFunctionType) {
          _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType);
        }
        return parseInitializedIdentifierList(
            commentAndMetadata,
            modifiers.staticKeyword,
            modifiers.covariantKeyword,
            _validateModifiersForField(modifiers),
            returnType);
      } else {
        //
        // We have found an error of some kind. Try to recover.
        //
        if (_isOperator(_currentToken)) {
          //
          // We appear to have found an operator declaration without the
          // 'operator' keyword.
          //
          _validateModifiersForOperator(modifiers);
          return parseOperator(
              commentAndMetadata, modifiers.externalKeyword, returnType);
        }
        _reportErrorForToken(
            ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken);
        return null;
      }
    }
    Token next = _peek();
    bool isFollowedByIdentifier = _tokenMatchesIdentifier(next);
    if (keyword == Keyword.GET && isFollowedByIdentifier) {
      _validateModifiersForGetterOrSetterOrMethod(modifiers);
      return parseGetter(commentAndMetadata, modifiers.externalKeyword,
          modifiers.staticKeyword, null);
    } else if (keyword == Keyword.SET && isFollowedByIdentifier) {
      _validateModifiersForGetterOrSetterOrMethod(modifiers);
      return parseSetter(commentAndMetadata, modifiers.externalKeyword,
          modifiers.staticKeyword, null);
    } else if (keyword == Keyword.OPERATOR && _isOperator(next)) {
      _validateModifiersForOperator(modifiers);
      return _parseOperatorAfterKeyword(
          commentAndMetadata, modifiers.externalKeyword, null, getAndAdvance());
    } else if (!_matchesIdentifier()) {
      //
      // Recover from an error.
      //
      if (_matchesKeyword(Keyword.CLASS)) {
        _reportErrorForCurrentToken(ParserErrorCode.CLASS_IN_CLASS);
        // TODO(brianwilkerson) We don't currently have any way to capture the
        // class that was parsed.
        parseClassDeclaration(commentAndMetadata, null);
        return null;
      } else if (_matchesKeyword(Keyword.ABSTRACT) &&
          _tokenMatchesKeyword(_peek(), Keyword.CLASS)) {
        _reportErrorForToken(ParserErrorCode.CLASS_IN_CLASS, _peek());
        // TODO(brianwilkerson) We don't currently have any way to capture the
        // class that was parsed.
        parseClassDeclaration(commentAndMetadata, getAndAdvance());
        return null;
      } else if (_matchesKeyword(Keyword.ENUM)) {
        _reportErrorForToken(ParserErrorCode.ENUM_IN_CLASS, _peek());
        // TODO(brianwilkerson) We don't currently have any way to capture the
        // enum that was parsed.
        parseEnumDeclaration(commentAndMetadata);
        return null;
      } else if (_isOperator(_currentToken)) {
        //
        // We appear to have found an operator declaration without the
        // 'operator' keyword.
        //
        _validateModifiersForOperator(modifiers);
        return parseOperator(
            commentAndMetadata, modifiers.externalKeyword, null);
      }
      Token keyword = modifiers.varKeyword ??
          modifiers.finalKeyword ??
          modifiers.constKeyword;
      if (keyword != null) {
        //
        // We appear to have found an incomplete field declaration.
        //
        _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
        VariableDeclaration variable = astFactory.variableDeclaration(
            createSyntheticIdentifier(), null, null);
        List<VariableDeclaration> variables = <VariableDeclaration>[variable];
        return astFactory.fieldDeclaration2(
            comment: commentAndMetadata.comment,
            metadata: commentAndMetadata.metadata,
            covariantKeyword: modifiers.covariantKeyword,
            fieldList: astFactory.variableDeclarationList(
                null, null, keyword, null, variables),
            semicolon: _expect(TokenType.SEMICOLON));
      }
      _reportErrorForToken(
          ParserErrorCode.EXPECTED_CLASS_MEMBER, _currentToken);
      if (commentAndMetadata.comment != null ||
          commentAndMetadata.hasMetadata) {
        //
        // We appear to have found an incomplete declaration at the end of the
        // class. At this point it consists of a metadata, which we don't want
        // to loose, so we'll treat it as a method declaration with a missing
        // name, parameters and empty body.
        //
        return astFactory.methodDeclaration(
            commentAndMetadata.comment,
            commentAndMetadata.metadata,
            null,
            null,
            null,
            null,
            null,
            createSyntheticIdentifier(isDeclaration: true),
            null,
            astFactory.formalParameterList(
                _createSyntheticToken(TokenType.OPEN_PAREN),
                <FormalParameter>[],
                null,
                null,
                _createSyntheticToken(TokenType.CLOSE_PAREN)),
            astFactory
                .emptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON)));
      }
      return null;
    } else if (_tokenMatches(next, TokenType.PERIOD) &&
        _tokenMatchesIdentifierOrKeyword(_peekAt(2)) &&
        _tokenMatches(_peekAt(3), TokenType.OPEN_PAREN)) {
      if (!_tokenMatchesIdentifier(_peekAt(2))) {
        _reportErrorForToken(ParserErrorCode.INVALID_CONSTRUCTOR_NAME,
            _peekAt(2), [_peekAt(2).lexeme]);
      }
      return _parseConstructor(
          commentAndMetadata,
          modifiers.externalKeyword,
          _validateModifiersForConstructor(modifiers),
          modifiers.factoryKeyword,
          parseSimpleIdentifier(),
          getAndAdvance(),
          parseSimpleIdentifier(allowKeyword: true, isDeclaration: true),
          parseFormalParameterList());
    } else if (_tokenMatches(next, TokenType.OPEN_PAREN)) {
      TypeName returnType = _parseOptionalTypeNameComment();
      SimpleIdentifier methodName = parseSimpleIdentifier(isDeclaration: true);
      TypeParameterList typeParameters = _parseGenericCommentTypeParameters();
      FormalParameterList parameters = parseFormalParameterList();
      if (_matches(TokenType.COLON) ||
          modifiers.factoryKeyword != null ||
          methodName.name == className) {
        return _parseConstructor(
            commentAndMetadata,
            modifiers.externalKeyword,
            _validateModifiersForConstructor(modifiers),
            modifiers.factoryKeyword,
            astFactory.simpleIdentifier(methodName.token, isDeclaration: false),
            null,
            null,
            parameters);
      }
      _validateModifiersForGetterOrSetterOrMethod(modifiers);
      _validateFormalParameterList(parameters);
      return _parseMethodDeclarationAfterParameters(
          commentAndMetadata,
          modifiers.externalKeyword,
          modifiers.staticKeyword,
          returnType,
          methodName,
          typeParameters,
          parameters);
    } else if (next.matchesAny(const <TokenType>[
      TokenType.EQ,
      TokenType.COMMA,
      TokenType.SEMICOLON
    ])) {
      if (modifiers.constKeyword == null &&
          modifiers.finalKeyword == null &&
          modifiers.varKeyword == null) {
        _reportErrorForCurrentToken(
            ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE);
      }
      return parseInitializedIdentifierList(
          commentAndMetadata,
          modifiers.staticKeyword,
          modifiers.covariantKeyword,
          _validateModifiersForField(modifiers),
          null);
    } else if (keyword == Keyword.TYPEDEF) {
      _reportErrorForCurrentToken(ParserErrorCode.TYPEDEF_IN_CLASS);
      // TODO(brianwilkerson) We don't currently have any way to capture the
      // function type alias that was parsed.
      _parseFunctionTypeAlias(commentAndMetadata, getAndAdvance());
      return null;
    } else {
      Token token = _skipTypeParameterList(_peek());
      if (token != null && _tokenMatches(token, TokenType.OPEN_PAREN)) {
        return _parseMethodDeclarationAfterReturnType(commentAndMetadata,
            modifiers.externalKeyword, modifiers.staticKeyword, null);
      }
    }
    TypeAnnotation type = _parseTypeAnnotationAfterIdentifier();
    keyword = _currentToken.keyword;
    next = _peek();
    isFollowedByIdentifier = _tokenMatchesIdentifier(next);
    if (keyword == Keyword.GET && isFollowedByIdentifier) {
      _validateModifiersForGetterOrSetterOrMethod(modifiers);
      return parseGetter(commentAndMetadata, modifiers.externalKeyword,
          modifiers.staticKeyword, type);
    } else if (keyword == Keyword.SET && isFollowedByIdentifier) {
      _validateModifiersForGetterOrSetterOrMethod(modifiers);
      return parseSetter(commentAndMetadata, modifiers.externalKeyword,
          modifiers.staticKeyword, type);
    } else if (keyword == Keyword.OPERATOR && _isOperator(next)) {
      _validateModifiersForOperator(modifiers);
      return _parseOperatorAfterKeyword(
          commentAndMetadata, modifiers.externalKeyword, type, getAndAdvance());
    } else if (!_matchesIdentifier()) {
      if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
        //
        // We appear to have found an incomplete declaration at the end of the
        // class. At this point it consists of a type name, so we'll treat it as
        // a field declaration with a missing field name and semicolon.
        //
        return parseInitializedIdentifierList(
            commentAndMetadata,
            modifiers.staticKeyword,
            modifiers.covariantKeyword,
            _validateModifiersForField(modifiers),
            type);
      }
      if (_isOperator(_currentToken)) {
        //
        // We appear to have found an operator declaration without the
        // 'operator' keyword.
        //
        _validateModifiersForOperator(modifiers);
        return parseOperator(
            commentAndMetadata, modifiers.externalKeyword, type);
      }
      //
      // We appear to have found an incomplete declaration before another
      // declaration. At this point it consists of a type name, so we'll treat
      // it as a field declaration with a missing field name and semicolon.
      //
      _reportErrorForToken(
          ParserErrorCode.EXPECTED_CLASS_MEMBER, _currentToken);
      try {
        _lockErrorListener();
        return parseInitializedIdentifierList(
            commentAndMetadata,
            modifiers.staticKeyword,
            modifiers.covariantKeyword,
            _validateModifiersForField(modifiers),
            type);
      } finally {
        _unlockErrorListener();
      }
    } else if (_tokenMatches(next, TokenType.OPEN_PAREN)) {
      SimpleIdentifier methodName =
          _parseSimpleIdentifierUnchecked(isDeclaration: true);
      TypeParameterList typeParameters = _parseGenericCommentTypeParameters();
      FormalParameterList parameters = parseFormalParameterList();
      if (methodName.name == className) {
        _reportErrorForNode(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, type);
        return _parseConstructor(
            commentAndMetadata,
            modifiers.externalKeyword,
            _validateModifiersForConstructor(modifiers),
            modifiers.factoryKeyword,
            astFactory.simpleIdentifier(methodName.token, isDeclaration: true),
            null,
            null,
            parameters);
      }
      _validateModifiersForGetterOrSetterOrMethod(modifiers);
      _validateFormalParameterList(parameters);
      return _parseMethodDeclarationAfterParameters(
          commentAndMetadata,
          modifiers.externalKeyword,
          modifiers.staticKeyword,
          type,
          methodName,
          typeParameters,
          parameters);
    } else if (_tokenMatches(next, TokenType.LT)) {
      return _parseMethodDeclarationAfterReturnType(commentAndMetadata,
          modifiers.externalKeyword, modifiers.staticKeyword, type);
    } else if (_tokenMatches(next, TokenType.OPEN_CURLY_BRACKET)) {
      // We have found "TypeName identifier {", and are guessing that this is a
      // getter without the keyword 'get'.
      _validateModifiersForGetterOrSetterOrMethod(modifiers);
      _reportErrorForCurrentToken(ParserErrorCode.MISSING_GET);
      _currentToken = _injectToken(
          new SyntheticKeywordToken(Keyword.GET, _currentToken.offset));
      return parseGetter(commentAndMetadata, modifiers.externalKeyword,
          modifiers.staticKeyword, type);
    }
    return parseInitializedIdentifierList(
        commentAndMetadata,
        modifiers.staticKeyword,
        modifiers.covariantKeyword,
        _validateModifiersForField(modifiers),
        type);
  }

  /**
   * Parse a single combinator. Return the combinator that was parsed, or `null`
   * if no combinator is found.
   *
   *     combinator ::=
   *         'show' identifier (',' identifier)*
   *       | 'hide' identifier (',' identifier)*
   */
  Combinator parseCombinator() {
    if (_matchesKeyword(Keyword.SHOW)) {
      return astFactory.showCombinator(getAndAdvance(), parseIdentifierList());
    } else if (_matchesKeyword(Keyword.HIDE)) {
      return astFactory.hideCombinator(getAndAdvance(), parseIdentifierList());
    }
    return null;
  }

  /**
   * Parse a list of combinators in a directive. Return the combinators that
   * were parsed, or `null` if there are no combinators.
   *
   *     combinator ::=
   *         'show' identifier (',' identifier)*
   *       | 'hide' identifier (',' identifier)*
   */
  List<Combinator> parseCombinators() {
    List<Combinator> combinators = null;
    while (true) {
      Combinator combinator = parseCombinator();
      if (combinator == null) {
        break;
      }
      combinators ??= <Combinator>[];
      combinators.add(combinator);
    }
    return combinators;
  }

  /**
   * Parse the documentation comment and metadata preceding a declaration. This
   * method allows any number of documentation comments to occur before, after
   * or between the metadata, but only returns the last (right-most)
   * documentation comment that is found. Return the documentation comment and
   * metadata that were parsed.
   *
   *     metadata ::=
   *         annotation*
   */
  CommentAndMetadata parseCommentAndMetadata() {
    // TODO(brianwilkerson) Consider making the creation of documentation
    // comments be lazy.
    List<DocumentationCommentToken> tokens = parseDocumentationCommentTokens();
    List<Annotation> metadata = null;
    while (_matches(TokenType.AT)) {
      metadata ??= <Annotation>[];
      metadata.add(parseAnnotation());
      List<DocumentationCommentToken> optionalTokens =
          parseDocumentationCommentTokens();
      if (optionalTokens != null) {
        tokens = optionalTokens;
      }
    }
    return new CommentAndMetadata(parseDocumentationComment(tokens), metadata);
  }

  /**
   * Parse a comment reference from the source between square brackets. The
   * [referenceSource] is the source occurring between the square brackets
   * within a documentation comment. The [sourceOffset] is the offset of the
   * first character of the reference source. Return the comment reference that
   * was parsed, or `null` if no reference could be found.
   *
   *     commentReference ::=
   *         'new'? prefixedIdentifier
   */
  CommentReference parseCommentReference(
      String referenceSource, int sourceOffset) {
    // TODO(brianwilkerson) The errors are not getting the right offset/length
    // and are being duplicated.
    try {
      BooleanErrorListener listener = new BooleanErrorListener();
      Scanner scanner = new Scanner(
          null, new SubSequenceReader(referenceSource, sourceOffset), listener);
      scanner.setSourceStart(1, 1);
      Token firstToken = scanner.tokenize();
      if (listener.errorReported) {
        return null;
      }
      if (firstToken.type == TokenType.EOF) {
        Token syntheticToken =
            new SyntheticStringToken(TokenType.IDENTIFIER, "", sourceOffset);
        syntheticToken.setNext(firstToken);
        return astFactory.commentReference(
            null, astFactory.simpleIdentifier(syntheticToken));
      }
      Token newKeyword = null;
      if (_tokenMatchesKeyword(firstToken, Keyword.NEW)) {
        newKeyword = firstToken;
        firstToken = firstToken.next;
      }
      if (firstToken.isUserDefinableOperator) {
        if (firstToken.next.type != TokenType.EOF) {
          return null;
        }
        Identifier identifier = astFactory.simpleIdentifier(firstToken);
        return astFactory.commentReference(null, identifier);
      } else if (_tokenMatchesKeyword(firstToken, Keyword.OPERATOR)) {
        Token secondToken = firstToken.next;
        if (secondToken.isUserDefinableOperator) {
          if (secondToken.next.type != TokenType.EOF) {
            return null;
          }
          Identifier identifier = astFactory.simpleIdentifier(secondToken);
          return astFactory.commentReference(null, identifier);
        }
        return null;
      } else if (_tokenMatchesIdentifier(firstToken)) {
        Token secondToken = firstToken.next;
        Token thirdToken = secondToken.next;
        Token nextToken;
        Identifier identifier;
        if (_tokenMatches(secondToken, TokenType.PERIOD)) {
          if (thirdToken.isUserDefinableOperator) {
            identifier = astFactory.prefixedIdentifier(
                astFactory.simpleIdentifier(firstToken),
                secondToken,
                astFactory.simpleIdentifier(thirdToken));
            nextToken = thirdToken.next;
          } else if (_tokenMatchesKeyword(thirdToken, Keyword.OPERATOR)) {
            Token fourthToken = thirdToken.next;
            if (fourthToken.isUserDefinableOperator) {
              identifier = astFactory.prefixedIdentifier(
                  astFactory.simpleIdentifier(firstToken),
                  secondToken,
                  astFactory.simpleIdentifier(fourthToken));
              nextToken = fourthToken.next;
            } else {
              return null;
            }
          } else if (_tokenMatchesIdentifier(thirdToken)) {
            identifier = astFactory.prefixedIdentifier(
                astFactory.simpleIdentifier(firstToken),
                secondToken,
                astFactory.simpleIdentifier(thirdToken));
            nextToken = thirdToken.next;
          }
        } else {
          identifier = astFactory.simpleIdentifier(firstToken);
          nextToken = firstToken.next;
        }
        if (nextToken.type != TokenType.EOF) {
          return null;
        }
        return astFactory.commentReference(newKeyword, identifier);
      } else {
        Keyword keyword = firstToken.keyword;
        if (keyword == Keyword.THIS ||
            keyword == Keyword.NULL ||
            keyword == Keyword.TRUE ||
            keyword == Keyword.FALSE) {
          // TODO(brianwilkerson) If we want to support this we will need to
          // extend the definition of CommentReference to take an expression
          // rather than an identifier. For now we just ignore it to reduce the
          // number of errors produced, but that's probably not a valid long term
          // approach.
          return null;
        }
      }
    } catch (exception) {
      // Ignored because we assume that it wasn't a real comment reference.
    }
    return null;
  }

  /**
   * Parse all of the comment references occurring in the given array of
   * documentation comments. The [tokens] are the comment tokens representing
   * the documentation comments to be parsed. Return the comment references that
   * were parsed.
   *
   *     commentReference ::=
   *         '[' 'new'? qualified ']' libraryReference?
   *
   *     libraryReference ::=
   *          '(' stringLiteral ')'
   */
  List<CommentReference> parseCommentReferences(
      List<DocumentationCommentToken> tokens) {
    List<CommentReference> references = <CommentReference>[];
    bool isInGitHubCodeBlock = false;
    for (DocumentationCommentToken token in tokens) {
      String comment = token.lexeme;
      // Skip GitHub code blocks.
      // https://help.github.com/articles/creating-and-highlighting-code-blocks/
      if (tokens.length != 1) {
        if (comment.indexOf('```') != -1) {
          isInGitHubCodeBlock = !isInGitHubCodeBlock;
        }
        if (isInGitHubCodeBlock) {
          continue;
        }
      }
      // Remove GitHub include code.
      comment = _removeGitHubInlineCode(comment);
      // Find references.
      int length = comment.length;
      List<List<int>> codeBlockRanges = _getCodeBlockRanges(comment);
      int leftIndex = comment.indexOf('[');
      while (leftIndex >= 0 && leftIndex + 1 < length) {
        List<int> range = _findRange(codeBlockRanges, leftIndex);
        if (range == null) {
          int nameOffset = token.offset + leftIndex + 1;
          int rightIndex = comment.indexOf(']', leftIndex);
          if (rightIndex >= 0) {
            int firstChar = comment.codeUnitAt(leftIndex + 1);
            if (firstChar != 0x27 && firstChar != 0x22) {
              if (_isLinkText(comment, rightIndex)) {
                // TODO(brianwilkerson) Handle the case where there's a library
                // URI in the link text.
              } else {
                CommentReference reference = parseCommentReference(
                    comment.substring(leftIndex + 1, rightIndex), nameOffset);
                if (reference != null) {
                  references.add(reference);
                  token.references.add(reference.beginToken);
                }
              }
            }
          } else {
            // terminating ']' is not typed yet
            int charAfterLeft = comment.codeUnitAt(leftIndex + 1);
            Token nameToken;
            if (Character.isLetterOrDigit(charAfterLeft)) {
              int nameEnd = StringUtilities.indexOfFirstNotLetterDigit(
                  comment, leftIndex + 1);
              String name = comment.substring(leftIndex + 1, nameEnd);
              nameToken =
                  new StringToken(TokenType.IDENTIFIER, name, nameOffset);
            } else {
              nameToken = new SyntheticStringToken(
                  TokenType.IDENTIFIER, '', nameOffset);
            }
            nameToken.setNext(new SimpleToken(TokenType.EOF, nameToken.end));
            references.add(astFactory.commentReference(
                null, astFactory.simpleIdentifier(nameToken)));
            token.references.add(nameToken);
            // next character
            rightIndex = leftIndex + 1;
          }
          leftIndex = comment.indexOf('[', rightIndex);
        } else {
          leftIndex = comment.indexOf('[', range[1]);
        }
      }
    }
    return references;
  }

  /**
   * Parse a compilation unit, starting with the given [token]. Return the
   * compilation unit that was parsed.
   */
  CompilationUnit parseCompilationUnit(Token token) {
    _currentToken = token;
    return parseCompilationUnit2();
  }

  /**
   * Parse a compilation unit. Return the compilation unit that was parsed.
   *
   * Specified:
   *
   *     compilationUnit ::=
   *         scriptTag? directive* topLevelDeclaration*
   *
   * Actual:
   *
   *     compilationUnit ::=
   *         scriptTag? topLevelElement*
   *
   *     topLevelElement ::=
   *         directive
   *       | topLevelDeclaration
   */
  CompilationUnit parseCompilationUnit2() {
    Token firstToken = _currentToken;
    ScriptTag scriptTag = null;
    if (_matches(TokenType.SCRIPT_TAG)) {
      scriptTag = astFactory.scriptTag(getAndAdvance());
    }
    //
    // Even though all directives must appear before declarations and must occur
    // in a given order, we allow directives and declarations to occur in any
    // order so that we can recover better.
    //
    bool libraryDirectiveFound = false;
    bool partOfDirectiveFound = false;
    bool partDirectiveFound = false;
    bool directiveFoundAfterDeclaration = false;
    List<Directive> directives = <Directive>[];
    List<CompilationUnitMember> declarations = <CompilationUnitMember>[];
    Token memberStart = _currentToken;
    TokenType type = _currentToken.type;
    while (type != TokenType.EOF) {
      CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
      Keyword keyword = _currentToken.keyword;
      TokenType nextType = _currentToken.next.type;
      if ((keyword == Keyword.IMPORT ||
              keyword == Keyword.EXPORT ||
              keyword == Keyword.LIBRARY ||
              keyword == Keyword.PART) &&
          nextType != TokenType.PERIOD &&
          nextType != TokenType.LT &&
          nextType != TokenType.OPEN_PAREN) {
        Directive parseDirective() {
          if (keyword == Keyword.IMPORT) {
            if (partDirectiveFound) {
              _reportErrorForCurrentToken(
                  ParserErrorCode.IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE);
            }
            return parseImportDirective(commentAndMetadata);
          } else if (keyword == Keyword.EXPORT) {
            if (partDirectiveFound) {
              _reportErrorForCurrentToken(
                  ParserErrorCode.EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE);
            }
            return parseExportDirective(commentAndMetadata);
          } else if (keyword == Keyword.LIBRARY) {
            if (libraryDirectiveFound) {
              _reportErrorForCurrentToken(
                  ParserErrorCode.MULTIPLE_LIBRARY_DIRECTIVES);
            } else {
              if (directives.length > 0) {
                _reportErrorForCurrentToken(
                    ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST);
              }
              libraryDirectiveFound = true;
            }
            return parseLibraryDirective(commentAndMetadata);
          } else if (keyword == Keyword.PART) {
            if (_tokenMatchesKeyword(_peek(), Keyword.OF)) {
              partOfDirectiveFound = true;
              return _parsePartOfDirective(commentAndMetadata);
            } else {
              partDirectiveFound = true;
              return _parsePartDirective(commentAndMetadata);
            }
          } else {
            // Internal error: this method should not have been invoked if the
            // current token was something other than one of the above.
            throw new StateError(
                "parseDirective invoked in an invalid state (currentToken = $_currentToken)");
          }
        }

        Directive directive = parseDirective();
        if (declarations.length > 0 && !directiveFoundAfterDeclaration) {
          _reportErrorForToken(ParserErrorCode.DIRECTIVE_AFTER_DECLARATION,
              directive.beginToken);
          directiveFoundAfterDeclaration = true;
        }
        directives.add(directive);
      } else if (type == TokenType.SEMICOLON) {
        // TODO(brianwilkerson) Consider moving this error detection into
        // _parseCompilationUnitMember (in the places where EXPECTED_EXECUTABLE
        // is being generated).
        _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
            [_currentToken.lexeme]);
        _advance();
      } else {
        CompilationUnitMember member;
        try {
          member = parseCompilationUnitMember(commentAndMetadata);
        } on _TooDeepTreeError {
          _reportErrorForToken(ParserErrorCode.STACK_OVERFLOW, _currentToken);
          Token eof = new Token(TokenType.EOF, 0);
          eof.previous = eof;
          eof.setNext(eof);
          return astFactory.compilationUnit(eof, null, null, null, eof);
        }
        if (member != null) {
          declarations.add(member);
        }
      }
      if (identical(_currentToken, memberStart)) {
        _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
            [_currentToken.lexeme]);
        _advance();
        while (!_matches(TokenType.EOF) &&
            !_couldBeStartOfCompilationUnitMember()) {
          _advance();
        }
      }
      memberStart = _currentToken;
      type = _currentToken.type;
    }
    if (partOfDirectiveFound && directives.length > 1) {
      // TODO(brianwilkerson) Improve error reporting when both a library and
      // part-of directive are found.
//      if (libraryDirectiveFound) {
//        int directiveCount = directives.length;
//        for (int i = 0; i < directiveCount; i++) {
//          Directive directive = directives[i];
//          if (directive is PartOfDirective) {
//            _reportErrorForToken(
//                ParserErrorCode.PART_OF_IN_LIBRARY, directive.partKeyword);
//          }
//        }
//      } else {
      bool firstPartOf = true;
      int directiveCount = directives.length;
      for (int i = 0; i < directiveCount; i++) {
        Directive directive = directives[i];
        if (directive is PartOfDirective) {
          if (firstPartOf) {
            firstPartOf = false;
          } else {
            _reportErrorForToken(ParserErrorCode.MULTIPLE_PART_OF_DIRECTIVES,
                directive.partKeyword);
          }
        } else {
          _reportErrorForToken(ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART,
              directives[i].keyword);
        }
//        }
      }
    }
    return astFactory.compilationUnit(
        firstToken, scriptTag, directives, declarations, _currentToken);
  }

  /**
   * Parse a compilation unit member. The [commentAndMetadata] is the metadata
   * to be associated with the member. Return the compilation unit member that
   * was parsed, or `null` if what was parsed could not be represented as a
   * compilation unit member.
   *
   *     compilationUnitMember ::=
   *         classDefinition
   *       | functionTypeAlias
   *       | external functionSignature
   *       | external getterSignature
   *       | external setterSignature
   *       | functionSignature functionBody
   *       | returnType? getOrSet identifier formalParameterList functionBody
   *       | (final | const) type? staticFinalDeclarationList ';'
   *       | variableDeclaration ';'
   */
  CompilationUnitMember parseCompilationUnitMember(
      CommentAndMetadata commentAndMetadata) {
    Modifiers modifiers = parseModifiers();
    Keyword keyword = _currentToken.keyword;
    if (keyword == Keyword.CLASS) {
      return parseClassDeclaration(
          commentAndMetadata, _validateModifiersForClass(modifiers));
    }
    Token next = _peek();
    TokenType nextType = next.type;
    if (keyword == Keyword.TYPEDEF &&
        nextType != TokenType.PERIOD &&
        nextType != TokenType.LT &&
        nextType != TokenType.OPEN_PAREN) {
      _validateModifiersForTypedef(modifiers);
      return parseTypeAlias(commentAndMetadata);
    } else if (keyword == Keyword.ENUM) {
      _validateModifiersForEnum(modifiers);
      return parseEnumDeclaration(commentAndMetadata);
    } else if (keyword == Keyword.VOID ||
        _atGenericFunctionTypeAfterReturnType(_currentToken)) {
      TypeAnnotation returnType;
      if (keyword == Keyword.VOID) {
        if (_atGenericFunctionTypeAfterReturnType(next)) {
          returnType = parseTypeAnnotation(false);
        } else {
          returnType = astFactory.typeName(
              astFactory.simpleIdentifier(getAndAdvance()), null);
        }
      } else {
        returnType = parseTypeAnnotation(false);
      }
      keyword = _currentToken.keyword;
      next = _peek();
      if ((keyword == Keyword.GET || keyword == Keyword.SET) &&
          _tokenMatchesIdentifier(next)) {
        _validateModifiersForTopLevelFunction(modifiers);
        return parseFunctionDeclaration(
            commentAndMetadata, modifiers.externalKeyword, returnType);
      } else if (keyword == Keyword.OPERATOR && _isOperator(next)) {
        _reportErrorForToken(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken);
        return _convertToFunctionDeclaration(_parseOperatorAfterKeyword(
            commentAndMetadata,
            modifiers.externalKeyword,
            returnType,
            getAndAdvance()));
      } else if (_matchesIdentifier() &&
          next.matchesAny(const <TokenType>[
            TokenType.OPEN_PAREN,
            TokenType.OPEN_CURLY_BRACKET,
            TokenType.FUNCTION,
            TokenType.LT
          ])) {
        _validateModifiersForTopLevelFunction(modifiers);
        return parseFunctionDeclaration(
            commentAndMetadata, modifiers.externalKeyword, returnType);
      } else if (_matchesIdentifier() &&
          next.matchesAny(const <TokenType>[
            TokenType.EQ,
            TokenType.COMMA,
            TokenType.SEMICOLON
          ])) {
        if (returnType is! GenericFunctionType) {
          _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType);
        }
        return astFactory.topLevelVariableDeclaration(
            commentAndMetadata.comment,
            commentAndMetadata.metadata,
            parseVariableDeclarationListAfterType(null,
                _validateModifiersForTopLevelVariable(modifiers), returnType),
            _expect(TokenType.SEMICOLON));
      } else {
        //
        // We have found an error of some kind. Try to recover.
        //
        _reportErrorForToken(
            ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken);
        return null;
      }
    } else if ((keyword == Keyword.GET || keyword == Keyword.SET) &&
        _tokenMatchesIdentifier(next)) {
      _validateModifiersForTopLevelFunction(modifiers);
      return parseFunctionDeclaration(
          commentAndMetadata, modifiers.externalKeyword, null);
    } else if (keyword == Keyword.OPERATOR && _isOperator(next)) {
      _reportErrorForToken(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken);
      return _convertToFunctionDeclaration(_parseOperatorAfterKeyword(
          commentAndMetadata,
          modifiers.externalKeyword,
          null,
          getAndAdvance()));
    } else if (!_matchesIdentifier()) {
      Token keyword = modifiers.varKeyword;
      if (keyword == null) {
        keyword = modifiers.finalKeyword;
      }
      if (keyword == null) {
        keyword = modifiers.constKeyword;
      }
      if (keyword != null) {
        //
        // We appear to have found an incomplete top-level variable declaration.
        //
        _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
        VariableDeclaration variable = astFactory.variableDeclaration(
            createSyntheticIdentifier(), null, null);
        List<VariableDeclaration> variables = <VariableDeclaration>[variable];
        return astFactory.topLevelVariableDeclaration(
            commentAndMetadata.comment,
            commentAndMetadata.metadata,
            astFactory.variableDeclarationList(
                null, null, keyword, null, variables),
            _expect(TokenType.SEMICOLON));
      }
      _reportErrorForToken(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken);
      return null;
    } else if (_isPeekGenericTypeParametersAndOpenParen()) {
      return parseFunctionDeclaration(
          commentAndMetadata, modifiers.externalKeyword, null);
    } else if (_tokenMatches(next, TokenType.OPEN_PAREN)) {
      TypeName returnType = _parseOptionalTypeNameComment();
      _validateModifiersForTopLevelFunction(modifiers);
      return parseFunctionDeclaration(
          commentAndMetadata, modifiers.externalKeyword, returnType);
    } else if (next.matchesAny(const <TokenType>[
      TokenType.EQ,
      TokenType.COMMA,
      TokenType.SEMICOLON
    ])) {
      if (modifiers.constKeyword == null &&
          modifiers.finalKeyword == null &&
          modifiers.varKeyword == null) {
        _reportErrorForCurrentToken(
            ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE);
      }
      return astFactory.topLevelVariableDeclaration(
          commentAndMetadata.comment,
          commentAndMetadata.metadata,
          parseVariableDeclarationListAfterType(
              null, _validateModifiersForTopLevelVariable(modifiers), null),
          _expect(TokenType.SEMICOLON));
    }
    TypeAnnotation returnType = parseReturnType(false);
    keyword = _currentToken.keyword;
    next = _peek();
    if ((keyword == Keyword.GET || keyword == Keyword.SET) &&
        _tokenMatchesIdentifier(next)) {
      _validateModifiersForTopLevelFunction(modifiers);
      return parseFunctionDeclaration(
          commentAndMetadata, modifiers.externalKeyword, returnType);
    } else if (keyword == Keyword.OPERATOR && _isOperator(next)) {
      _reportErrorForToken(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken);
      return _convertToFunctionDeclaration(_parseOperatorAfterKeyword(
          commentAndMetadata,
          modifiers.externalKeyword,
          returnType,
          getAndAdvance()));
    } else if (_matches(TokenType.AT)) {
      return astFactory.topLevelVariableDeclaration(
          commentAndMetadata.comment,
          commentAndMetadata.metadata,
          parseVariableDeclarationListAfterType(null,
              _validateModifiersForTopLevelVariable(modifiers), returnType),
          _expect(TokenType.SEMICOLON));
    } else if (!_matchesIdentifier()) {
      // TODO(brianwilkerson) Generalize this error. We could also be parsing a
      // top-level variable at this point.
      _reportErrorForToken(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken);
      Token semicolon;
      if (_matches(TokenType.SEMICOLON)) {
        semicolon = getAndAdvance();
      } else {
        semicolon = _createSyntheticToken(TokenType.SEMICOLON);
      }
      VariableDeclaration variable = astFactory.variableDeclaration(
          createSyntheticIdentifier(), null, null);
      List<VariableDeclaration> variables = <VariableDeclaration>[variable];
      return astFactory.topLevelVariableDeclaration(
          commentAndMetadata.comment,
          commentAndMetadata.metadata,
          astFactory.variableDeclarationList(
              null, null, null, returnType, variables),
          semicolon);
    } else if (next.matchesAny(const <TokenType>[
      TokenType.OPEN_PAREN,
      TokenType.FUNCTION,
      TokenType.OPEN_CURLY_BRACKET,
      TokenType.LT
    ])) {
      _validateModifiersForTopLevelFunction(modifiers);
      return parseFunctionDeclaration(
          commentAndMetadata, modifiers.externalKeyword, returnType);
    }
    return astFactory.topLevelVariableDeclaration(
        commentAndMetadata.comment,
        commentAndMetadata.metadata,
        parseVariableDeclarationListAfterType(
            null, _validateModifiersForTopLevelVariable(modifiers), returnType),
        _expect(TokenType.SEMICOLON));
  }

  /**
   * Parse a conditional expression. Return the conditional expression that was
   * parsed.
   *
   *     conditionalExpression ::=
   *         ifNullExpression ('?' expressionWithoutCascade ':' expressionWithoutCascade)?
   */
  Expression parseConditionalExpression() {
    Expression condition = parseIfNullExpression();
    if (_currentToken.type != TokenType.QUESTION) {
      return condition;
    }
    Token question = getAndAdvance();
    Expression thenExpression = parseExpressionWithoutCascade();
    Token colon = _expect(TokenType.COLON);
    Expression elseExpression = parseExpressionWithoutCascade();
    return astFactory.conditionalExpression(
        condition, question, thenExpression, colon, elseExpression);
  }

  /**
   * Parse a configuration in either an import or export directive.
   *
   * This method assumes that the current token matches `Keyword.IF`.
   *
   *     configuration ::=
   *         'if' '(' test ')' uri
   *
   *     test ::=
   *         dottedName ('==' stringLiteral)?
   *
   *     dottedName ::=
   *         identifier ('.' identifier)*
   */
  Configuration parseConfiguration() {
    Token ifKeyword = getAndAdvance();
    Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
    DottedName name = parseDottedName();
    Token equalToken = null;
    StringLiteral value = null;
    if (_matches(TokenType.EQ_EQ)) {
      equalToken = getAndAdvance();
      value = parseStringLiteral();
      if (value is StringInterpolation) {
        _reportErrorForNode(
            ParserErrorCode.INVALID_LITERAL_IN_CONFIGURATION, value);
      }
    }
    Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
    StringLiteral libraryUri = _parseUri();
    return astFactory.configuration(ifKeyword, leftParenthesis, name,
        equalToken, value, rightParenthesis, libraryUri);
  }

  /**
   * Parse a const expression. Return the const expression that was parsed.
   *
   * This method assumes that the current token matches `Keyword.CONST`.
   *
   *     constExpression ::=
   *         instanceCreationExpression
   *       | listLiteral
   *       | mapLiteral
   */
  Expression parseConstExpression() {
    Token keyword = getAndAdvance();
    TokenType type = _currentToken.type;
    if (type == TokenType.LT || _injectGenericCommentTypeList()) {
      return parseListOrMapLiteral(keyword);
    } else if (type == TokenType.OPEN_SQUARE_BRACKET ||
        type == TokenType.INDEX) {
      return parseListLiteral(keyword, null);
    } else if (type == TokenType.OPEN_CURLY_BRACKET) {
      return parseMapLiteral(keyword, null);
    }
    return parseInstanceCreationExpression(keyword);
  }

  /**
   * Parse a field initializer within a constructor. The flag [hasThis] should
   * be true if the current token is `this`. Return the field initializer that
   * was parsed.
   *
   *     fieldInitializer:
   *         ('this' '.')? identifier '=' conditionalExpression cascadeSection*
   */
  ConstructorFieldInitializer parseConstructorFieldInitializer(bool hasThis) {
    Token keywordToken = null;
    Token period = null;
    if (hasThis) {
      keywordToken = getAndAdvance();
      period = _expect(TokenType.PERIOD);
    }
    SimpleIdentifier fieldName = parseSimpleIdentifier();
    Token equals = null;
    TokenType type = _currentToken.type;
    if (type == TokenType.EQ) {
      equals = getAndAdvance();
    } else {
      _reportErrorForCurrentToken(
          ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER);
      Keyword keyword = _currentToken.keyword;
      if (keyword != Keyword.THIS &&
          keyword != Keyword.SUPER &&
          type != TokenType.OPEN_CURLY_BRACKET &&
          type != TokenType.FUNCTION) {
        equals = _createSyntheticToken(TokenType.EQ);
      } else {
        return astFactory.constructorFieldInitializer(
            keywordToken,
            period,
            fieldName,
            _createSyntheticToken(TokenType.EQ),
            createSyntheticIdentifier());
      }
    }
    bool wasInInitializer = _inInitializer;
    _inInitializer = true;
    try {
      Expression expression = parseConditionalExpression();
      if (_matches(TokenType.PERIOD_PERIOD)) {
        List<Expression> cascadeSections = <Expression>[];
        do {
          Expression section = parseCascadeSection();
          if (section != null) {
            cascadeSections.add(section);
          }
        } while (_matches(TokenType.PERIOD_PERIOD));
        expression = astFactory.cascadeExpression(expression, cascadeSections);
      }
      return astFactory.constructorFieldInitializer(
          keywordToken, period, fieldName, equals, expression);
    } finally {
      _inInitializer = wasInInitializer;
    }
  }

  /**
   * Parse the name of a constructor. Return the constructor name that was
   * parsed.
   *
   *     constructorName:
   *         type ('.' identifier)?
   */
  ConstructorName parseConstructorName() {
    TypeName type = parseTypeName(false);
    Token period = null;
    SimpleIdentifier name = null;
    if (_matches(TokenType.PERIOD)) {
      period = getAndAdvance();
      name = parseSimpleIdentifier();
    }
    return astFactory.constructorName(type, period, name);
  }

  /**
   * Parse a continue statement. Return the continue statement that was parsed.
   *
   * This method assumes that the current token matches `Keyword.CONTINUE`.
   *
   *     continueStatement ::=
   *         'continue' identifier? ';'
   */
  Statement parseContinueStatement() {
    Token continueKeyword = getAndAdvance();
    if (!_inLoop && !_inSwitch) {
      _reportErrorForToken(
          ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP, continueKeyword);
    }
    SimpleIdentifier label = null;
    if (_matchesIdentifier()) {
      label = _parseSimpleIdentifierUnchecked();
    }
    if (_inSwitch && !_inLoop && label == null) {
      _reportErrorForToken(
          ParserErrorCode.CONTINUE_WITHOUT_LABEL_IN_CASE, continueKeyword);
    }
    Token semicolon = _expect(TokenType.SEMICOLON);
    return astFactory.continueStatement(continueKeyword, label, semicolon);
  }

  /**
   * Parse a directive. The [commentAndMetadata] is the metadata to be
   * associated with the directive. Return the directive that was parsed.
   *
   *     directive ::=
   *         exportDirective
   *       | libraryDirective
   *       | importDirective
   *       | partDirective
   */
  Directive parseDirective(CommentAndMetadata commentAndMetadata) {
    if (_matchesKeyword(Keyword.IMPORT)) {
      return parseImportDirective(commentAndMetadata);
    } else if (_matchesKeyword(Keyword.EXPORT)) {
      return parseExportDirective(commentAndMetadata);
    } else if (_matchesKeyword(Keyword.LIBRARY)) {
      return parseLibraryDirective(commentAndMetadata);
    } else if (_matchesKeyword(Keyword.PART)) {
      return parsePartOrPartOfDirective(commentAndMetadata);
    } else {
      // Internal error: this method should not have been invoked if the current
      // token was something other than one of the above.
      throw new StateError(
          "parseDirective invoked in an invalid state; currentToken = $_currentToken");
    }
  }

  /**
   * Parse the script tag and directives in a compilation unit, starting with
   * the given [token], until the first non-directive is encountered. The
   * remainder of the compilation unit will not be parsed. Specifically, if
   * there are directives later in the file, they will not be parsed. Return the
   * compilation unit that was parsed.
   */
  CompilationUnit parseDirectives(Token token) {
    _currentToken = token;
    return parseDirectives2();
  }

  /**
   * Parse the script tag and directives in a compilation unit until the first
   * non-directive is encountered. Return the compilation unit that was parsed.
   *
   *     compilationUnit ::=
   *         scriptTag? directive*
   */
  CompilationUnit parseDirectives2() {
    Token firstToken = _currentToken;
    ScriptTag scriptTag = null;
    if (_matches(TokenType.SCRIPT_TAG)) {
      scriptTag = astFactory.scriptTag(getAndAdvance());
    }
    List<Directive> directives = <Directive>[];
    while (!_matches(TokenType.EOF)) {
      CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
      Keyword keyword = _currentToken.keyword;
      TokenType type = _peek().type;
      if ((keyword == Keyword.IMPORT ||
              keyword == Keyword.EXPORT ||
              keyword == Keyword.LIBRARY ||
              keyword == Keyword.PART) &&
          type != TokenType.PERIOD &&
          type != TokenType.LT &&
          type != TokenType.OPEN_PAREN) {
        directives.add(parseDirective(commentAndMetadata));
      } else if (_matches(TokenType.SEMICOLON)) {
        _advance();
      } else {
        while (!_matches(TokenType.EOF)) {
          _advance();
        }
        return astFactory.compilationUnit(
            firstToken, scriptTag, directives, null, _currentToken);
      }
    }
    return astFactory.compilationUnit(
        firstToken, scriptTag, directives, null, _currentToken);
  }

  /**
   * Parse a documentation comment based on the given list of documentation
   * comment tokens. Return the documentation comment that was parsed, or `null`
   * if there was no comment.
   *
   *     documentationComment ::=
   *         multiLineComment?
   *       | singleLineComment*
   */
  Comment parseDocumentationComment(List<DocumentationCommentToken> tokens) {
    if (tokens == null) {
      return null;
    }
    List<CommentReference> references = parseCommentReferences(tokens);
    return astFactory.documentationComment(tokens, references);
  }

  /**
   * Parse a documentation comment. Return the documentation comment that was
   * parsed, or `null` if there was no comment.
   *
   *     documentationComment ::=
   *         multiLineComment?
   *       | singleLineComment*
   */
  List<DocumentationCommentToken> parseDocumentationCommentTokens() {
    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[];
    CommentToken commentToken = _currentToken.precedingComments;
    while (commentToken != null) {
      if (commentToken is DocumentationCommentToken) {
        if (tokens.isNotEmpty) {
          if (commentToken.type == TokenType.SINGLE_LINE_COMMENT) {
            if (tokens[0].type != TokenType.SINGLE_LINE_COMMENT) {
              tokens.clear();
            }
          } else {
            tokens.clear();
          }
        }
        tokens.add(commentToken);
      }
      commentToken = commentToken.next;
    }
    return tokens.isEmpty ? null : tokens;
  }

  /**
   * Parse a do statement. Return the do statement that was parsed.
   *
   * This method assumes that the current token matches `Keyword.DO`.
   *
   *     doStatement ::=
   *         'do' statement 'while' '(' expression ')' ';'
   */
  Statement parseDoStatement() {
    bool wasInLoop = _inLoop;
    _inLoop = true;
    try {
      Token doKeyword = getAndAdvance();
      Statement body = parseStatement2();
      Token whileKeyword = _expectKeyword(Keyword.WHILE);
      Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
      Expression condition = parseExpression2();
      Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
      Token semicolon = _expect(TokenType.SEMICOLON);
      return astFactory.doStatement(doKeyword, body, whileKeyword,
          leftParenthesis, condition, rightParenthesis, semicolon);
    } finally {
      _inLoop = wasInLoop;
    }
  }

  /**
   * Parse a dotted name. Return the dotted name that was parsed.
   *
   *     dottedName ::=
   *         identifier ('.' identifier)*
   */
  DottedName parseDottedName() {
    List<SimpleIdentifier> components = <SimpleIdentifier>[
      parseSimpleIdentifier()
    ];
    while (_optional(TokenType.PERIOD)) {
      components.add(parseSimpleIdentifier());
    }
    return astFactory.dottedName(components);
  }

  /**
   * Parse an empty statement. Return the empty statement that was parsed.
   *
   * This method assumes that the current token matches `TokenType.SEMICOLON`.
   *
   *     emptyStatement ::=
   *         ';'
   */
  Statement parseEmptyStatement() => astFactory.emptyStatement(getAndAdvance());

  /**
   * Parse an enum declaration. The [commentAndMetadata] is the metadata to be
   * associated with the member. Return the enum declaration that was parsed.
   *
   * This method assumes that the current token matches `Keyword.ENUM`.
   *
   *     enumType ::=
   *         metadata 'enum' id '{' id (',' id)* (',')? '}'
   */
  EnumDeclaration parseEnumDeclaration(CommentAndMetadata commentAndMetadata) {
    Token keyword = getAndAdvance();
    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
    Token leftBracket = null;
    List<EnumConstantDeclaration> constants = <EnumConstantDeclaration>[];
    Token rightBracket = null;
    if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
      leftBracket = getAndAdvance();
      if (_matchesIdentifier() || _matches(TokenType.AT)) {
        constants.add(_parseEnumConstantDeclaration());
      } else if (_matches(TokenType.COMMA) &&
          _tokenMatchesIdentifier(_peek())) {
        constants.add(_parseEnumConstantDeclaration());
        _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
      } else {
        constants.add(_parseEnumConstantDeclaration());
        _reportErrorForCurrentToken(ParserErrorCode.EMPTY_ENUM_BODY);
      }
      while (_optional(TokenType.COMMA)) {
        if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
          break;
        }
        constants.add(_parseEnumConstantDeclaration());
      }
      rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
    } else {
      leftBracket = _createSyntheticToken(TokenType.OPEN_CURLY_BRACKET);
      rightBracket = _createSyntheticToken(TokenType.CLOSE_CURLY_BRACKET);
      _reportErrorForCurrentToken(ParserErrorCode.MISSING_ENUM_BODY);
    }
    return astFactory.enumDeclaration(
        commentAndMetadata.comment,
        commentAndMetadata.metadata,
        keyword,
        name,
        leftBracket,
        constants,
        rightBracket);
  }

  /**
   * Parse an equality expression. Return the equality expression that was
   * parsed.
   *
   *     equalityExpression ::=
   *         relationalExpression (equalityOperator relationalExpression)?
   *       | 'super' equalityOperator relationalExpression
   */
  Expression parseEqualityExpression() {
    Expression expression;
    if (_currentToken.keyword == Keyword.SUPER &&
        _currentToken.next.type.isEqualityOperator) {
      expression = astFactory.superExpression(getAndAdvance());
    } else {
      expression = parseRelationalExpression();
    }
    bool leftEqualityExpression = false;
    while (_currentToken.type.isEqualityOperator) {
      if (leftEqualityExpression) {
        _reportErrorForNode(
            ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND, expression);
      }
      expression = astFactory.binaryExpression(
          expression, getAndAdvance(), parseRelationalExpression());
      leftEqualityExpression = true;
    }
    return expression;
  }

  /**
   * Parse an export directive. The [commentAndMetadata] is the metadata to be
   * associated with the directive. Return the export directive that was parsed.
   *
   * This method assumes that the current token matches `Keyword.EXPORT`.
   *
   *     exportDirective ::=
   *         metadata 'export' stringLiteral configuration* combinator*';'
   */
  ExportDirective parseExportDirective(CommentAndMetadata commentAndMetadata) {
    Token exportKeyword = getAndAdvance();
    StringLiteral libraryUri = _parseUri();
    List<Configuration> configurations = _parseConfigurations();
    List<Combinator> combinators = parseCombinators();
    Token semicolon = _expect(TokenType.SEMICOLON);
    return astFactory.exportDirective(
        commentAndMetadata.comment,
        commentAndMetadata.metadata,
        exportKeyword,
        libraryUri,
        configurations,
        combinators,
        semicolon);
  }

  /**
   * Parse an expression, starting with the given [token]. Return the expression
   * that was parsed, or `null` if the tokens do not represent a recognizable
   * expression.
   */
  Expression parseExpression(Token token) {
    _currentToken = token;
    return parseExpression2();
  }

  /**
   * Parse an expression that might contain a cascade. Return the expression
   * that was parsed.
   *
   *     expression ::=
   *         assignableExpression assignmentOperator expression
   *       | conditionalExpression cascadeSection*
   *       | throwExpression
   */
  Expression parseExpression2() {
    if (_treeDepth > _MAX_TREE_DEPTH) {
      throw new _TooDeepTreeError();
    }
    _treeDepth++;
    try {
      Keyword keyword = _currentToken.keyword;
      if (keyword == Keyword.THROW) {
        return parseThrowExpression();
      } else if (keyword == Keyword.RETHROW) {
        // TODO(brianwilkerson) Rethrow is a statement again.
        return parseRethrowExpression();
      }
      //
      // assignableExpression is a subset of conditionalExpression, so we can
      // parse a conditional expression and then determine whether it is followed
      // by an assignmentOperator, checking for conformance to the restricted
      // grammar after making that determination.
      //
      Expression expression = parseConditionalExpression();
      TokenType type = _currentToken.type;
      if (type == TokenType.PERIOD_PERIOD) {
        List<Expression> cascadeSections = <Expression>[];
        do {
          Expression section = parseCascadeSection();
          if (section != null) {
            cascadeSections.add(section);
          }
        } while (_currentToken.type == TokenType.PERIOD_PERIOD);
        return astFactory.cascadeExpression(expression, cascadeSections);
      } else if (type.isAssignmentOperator) {
        Token operator = getAndAdvance();
        _ensureAssignable(expression);
        return astFactory.assignmentExpression(
            expression, operator, parseExpression2());
      }
      return expression;
    } finally {
      _treeDepth--;
    }
  }

  /**
   * Parse a list of expressions. Return the expression that was parsed.
   *
   *     expressionList ::=
   *         expression (',' expression)*
   */
  List<Expression> parseExpressionList() {
    List<Expression> expressions = <Expression>[parseExpression2()];
    while (_optional(TokenType.COMMA)) {
      expressions.add(parseExpression2());
    }
    return expressions;
  }

  /**
   * Parse an expression that does not contain any cascades. Return the
   * expression that was parsed.
   *
   *     expressionWithoutCascade ::=
   *         assignableExpression assignmentOperator expressionWithoutCascade
   *       | conditionalExpression
   *       | throwExpressionWithoutCascade
   */
  Expression parseExpressionWithoutCascade() {
    if (_matchesKeyword(Keyword.THROW)) {
      return parseThrowExpressionWithoutCascade();
    } else if (_matchesKeyword(Keyword.RETHROW)) {
      return parseRethrowExpression();
    }
    //
    // assignableExpression is a subset of conditionalExpression, so we can
    // parse a conditional expression and then determine whether it is followed
    // by an assignmentOperator, checking for conformance to the restricted
    // grammar after making that determination.
    //
    Expression expression = parseConditionalExpression();
    if (_currentToken.type.isAssignmentOperator) {
      Token operator = getAndAdvance();
      _ensureAssignable(expression);
      expression = astFactory.assignmentExpression(
          expression, operator, parseExpressionWithoutCascade());
    }
    return expression;
  }

  /**
   * Parse a class extends clause. Return the class extends clause that was
   * parsed.
   *
   * This method assumes that the current token matches `Keyword.EXTENDS`.
   *
   *     classExtendsClause ::=
   *         'extends' type
   */
  ExtendsClause parseExtendsClause() {
    Token keyword = getAndAdvance();
    TypeName superclass = parseTypeName(false);
    _mustNotBeNullable(superclass, ParserErrorCode.NULLABLE_TYPE_IN_EXTENDS);
    return astFactory.extendsClause(keyword, superclass);
  }

  /**
   * Parse the 'final', 'const', 'var' or type preceding a variable declaration.
   * The [optional] is `true` if the keyword and type are optional. Return the
   * 'final', 'const', 'var' or type that was parsed.
   *
   *     finalConstVarOrType ::=
   *         'final' type?
   *       | 'const' type?
   *       | 'var'
   *       | type
   */
  FinalConstVarOrType parseFinalConstVarOrType(bool optional,
      {bool inFunctionType: false}) {
    Token keywordToken = null;
    TypeAnnotation type = null;
    Keyword keyword = _currentToken.keyword;
    if (keyword == Keyword.FINAL || keyword == Keyword.CONST) {
      keywordToken = getAndAdvance();
      if (_isTypedIdentifier(_currentToken)) {
        type = parseTypeAnnotation(false);
      } else {
        // Support `final/*=T*/ x;`
        type = _parseOptionalTypeNameComment();
      }
    } else if (keyword == Keyword.VAR) {
      keywordToken = getAndAdvance();
      // Support `var/*=T*/ x;`
      type = _parseOptionalTypeNameComment();
      if (type != null) {
        // Clear the keyword to prevent an error.
        keywordToken = null;
      }
    } else if (_isTypedIdentifier(_currentToken)) {
      type = parseReturnType(false);
    } else if (inFunctionType && _matchesIdentifier()) {
      type = parseTypeAnnotation(false);
    } else if (!optional) {
      _reportErrorForCurrentToken(
          ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE);
    } else {
      // Support parameters such as `(/*=K*/ key, /*=V*/ value)`
      // This is not supported if the type is required.
      type = _parseOptionalTypeNameComment();
    }
    return new FinalConstVarOrType(keywordToken, type);
  }

  /**
   * Parse a formal parameter. At most one of `isOptional` and `isNamed` can be
   * `true`. The [kind] is the kind of parameter being expected based on the
   * presence or absence of group delimiters. Return the formal parameter that
   * was parsed.
   *
   *     defaultFormalParameter ::=
   *         normalFormalParameter ('=' expression)?
   *
   *     defaultNamedParameter ::=
   *         normalFormalParameter ('=' expression)?
   *         normalFormalParameter (':' expression)?
   */
  FormalParameter parseFormalParameter(ParameterKind kind,
      {bool inFunctionType: false}) {
    NormalFormalParameter parameter =
        parseNormalFormalParameter(inFunctionType: inFunctionType);
    TokenType type = _currentToken.type;
    if (type == TokenType.EQ) {
      if (inFunctionType) {
        _reportErrorForCurrentToken(
            ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE);
      }
      Token separator = getAndAdvance();
      Expression defaultValue = parseExpression2();
      if (kind == ParameterKind.REQUIRED) {
        _reportErrorForNode(
            ParserErrorCode.POSITIONAL_PARAMETER_OUTSIDE_GROUP, parameter);
        kind = ParameterKind.POSITIONAL;
      } else if (kind == ParameterKind.NAMED &&
          inFunctionType &&
          parameter.identifier == null) {
        _reportErrorForCurrentToken(
            ParserErrorCode.MISSING_NAME_FOR_NAMED_PARAMETER);
      }
      return astFactory.defaultFormalParameter(
          parameter, kind, separator, defaultValue);
    } else if (type == TokenType.COLON) {
      if (inFunctionType) {
        _reportErrorForCurrentToken(
            ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE);
      }
      Token separator = getAndAdvance();
      Expression defaultValue = parseExpression2();
      if (kind == ParameterKind.REQUIRED) {
        _reportErrorForNode(
            ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP, parameter);
        kind = ParameterKind.NAMED;
      } else if (kind == ParameterKind.POSITIONAL) {
        _reportErrorForToken(
            ParserErrorCode.WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER,
            separator);
      } else if (kind == ParameterKind.NAMED &&
          inFunctionType &&
          parameter.identifier == null) {
        _reportErrorForCurrentToken(
            ParserErrorCode.MISSING_NAME_FOR_NAMED_PARAMETER);
      }
      return astFactory.defaultFormalParameter(
          parameter, kind, separator, defaultValue);
    } else if (kind != ParameterKind.REQUIRED) {
      if (kind == ParameterKind.NAMED &&
          inFunctionType &&
          parameter.identifier == null) {
        _reportErrorForCurrentToken(
            ParserErrorCode.MISSING_NAME_FOR_NAMED_PARAMETER);
      }
      return astFactory.defaultFormalParameter(parameter, kind, null, null);
    }
    return parameter;
  }

  /**
   * Parse a list of formal parameters. Return the formal parameters that were
   * parsed.
   *
   *     formalParameterList ::=
   *         '(' ')'
   *       | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
   *       | '(' optionalFormalParameters ')'
   *
   *     normalFormalParameters ::=
   *         normalFormalParameter (',' normalFormalParameter)*
   *
   *     optionalFormalParameters ::=
   *         optionalPositionalFormalParameters
   *       | namedFormalParameters
   *
   *     optionalPositionalFormalParameters ::=
   *         '[' defaultFormalParameter (',' defaultFormalParameter)* ']'
   *
   *     namedFormalParameters ::=
   *         '{' defaultNamedParameter (',' defaultNamedParameter)* '}'
   */
  FormalParameterList parseFormalParameterList({bool inFunctionType: false}) {
    if (_matches(TokenType.OPEN_PAREN)) {
      return _parseFormalParameterListUnchecked(inFunctionType: inFunctionType);
    }
    // TODO(brianwilkerson) Improve the error message.
    _reportErrorForCurrentToken(
        ParserErrorCode.EXPECTED_TOKEN, [TokenType.OPEN_PAREN.lexeme]);
    // Recovery: Check for an unmatched closing paren and parse parameters until
    // it is reached.
    return _parseFormalParameterListAfterParen(
        _createSyntheticToken(TokenType.OPEN_PAREN));
  }

  /**
   * Parse a for statement. Return the for statement that was parsed.
   *
   *     forStatement ::=
   *         'for' '(' forLoopParts ')' statement
   *
   *     forLoopParts ::=
   *         forInitializerStatement expression? ';' expressionList?
   *       | declaredIdentifier 'in' expression
   *       | identifier 'in' expression
   *
   *     forInitializerStatement ::=
   *         localVariableDeclaration ';'
   *       | expression? ';'
   */
  Statement parseForStatement() {
    bool wasInLoop = _inLoop;
    _inLoop = true;
    try {
      Token awaitKeyword = null;
      if (_matchesKeyword(Keyword.AWAIT)) {
        awaitKeyword = getAndAdvance();
      }
      Token forKeyword = _expectKeyword(Keyword.FOR);
      Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
      VariableDeclarationList variableList = null;
      Expression initialization = null;
      if (!_matches(TokenType.SEMICOLON)) {
        CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
        if (_matchesIdentifier() &&
            (_tokenMatchesKeyword(_peek(), Keyword.IN) ||
                _tokenMatches(_peek(), TokenType.COLON))) {
          SimpleIdentifier variableName = _parseSimpleIdentifierUnchecked();
          variableList = astFactory.variableDeclarationList(
              commentAndMetadata.comment,
              commentAndMetadata.metadata,
              null,
              null, <VariableDeclaration>[
            astFactory.variableDeclaration(variableName, null, null)
          ]);
        } else if (isInitializedVariableDeclaration()) {
          variableList =
              parseVariableDeclarationListAfterMetadata(commentAndMetadata);
        } else {
          initialization = parseExpression2();
        }
        TokenType type = _currentToken.type;
        if (_matchesKeyword(Keyword.IN) || type == TokenType.COLON) {
          if (type == TokenType.COLON) {
            _reportErrorForCurrentToken(ParserErrorCode.COLON_IN_PLACE_OF_IN);
          }
          DeclaredIdentifier loopVariable = null;
          SimpleIdentifier identifier = null;
          if (variableList == null) {
            // We found: <expression> 'in'
            _reportErrorForCurrentToken(
                ParserErrorCode.MISSING_VARIABLE_IN_FOR_EACH);
          } else {
            NodeList<VariableDeclaration> variables = variableList.variables;
            if (variables.length > 1) {
              _reportErrorForCurrentToken(
                  ParserErrorCode.MULTIPLE_VARIABLES_IN_FOR_EACH,
                  [variables.length.toString()]);
            }
            VariableDeclaration variable = variables[0];
            if (variable.initializer != null) {
              _reportErrorForCurrentToken(
                  ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH);
            }
            Token keyword = variableList.keyword;
            TypeAnnotation type = variableList.type;
            if (keyword != null || type != null) {
              loopVariable = astFactory.declaredIdentifier(
                  commentAndMetadata.comment,
                  commentAndMetadata.metadata,
                  keyword,
                  type,
                  astFactory.simpleIdentifier(variable.name.token,
                      isDeclaration: true));
            } else {
              if (commentAndMetadata.hasMetadata) {
                // TODO(jwren) metadata isn't allowed before the identifier in
                // "identifier in expression", add warning if commentAndMetadata
                // has content
              }
              identifier = variable.name;
            }
          }
          Token inKeyword = getAndAdvance();
          Expression iterator = parseExpression2();
          Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
          Statement body = parseStatement2();
          if (loopVariable == null) {
            return astFactory.forEachStatementWithReference(
                awaitKeyword,
                forKeyword,
                leftParenthesis,
                identifier,
                inKeyword,
                iterator,
                rightParenthesis,
                body);
          }
          return astFactory.forEachStatementWithDeclaration(
              awaitKeyword,
              forKeyword,
              leftParenthesis,
              loopVariable,
              inKeyword,
              iterator,
              rightParenthesis,
              body);
        }
      }
      if (awaitKeyword != null) {
        _reportErrorForToken(
            ParserErrorCode.INVALID_AWAIT_IN_FOR, awaitKeyword);
      }
      Token leftSeparator = _expect(TokenType.SEMICOLON);
      Expression condition = null;
      if (!_matches(TokenType.SEMICOLON)) {
        condition = parseExpression2();
      }
      Token rightSeparator = _expect(TokenType.SEMICOLON);
      List<Expression> updaters = null;
      if (!_matches(TokenType.CLOSE_PAREN)) {
        updaters = parseExpressionList();
      }
      Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
      Statement body = parseStatement2();
      return astFactory.forStatement(
          forKeyword,
          leftParenthesis,
          variableList,
          initialization,
          leftSeparator,
          condition,
          rightSeparator,
          updaters,
          rightParenthesis,
          body);
    } finally {
      _inLoop = wasInLoop;
    }
  }

  /**
   * Parse a function body. The [mayBeEmpty] is `true` if the function body is
   * allowed to be empty. The [emptyErrorCode] is the error code to report if
   * function body expected, but not found. The [inExpression] is `true` if the
   * function body is being parsed as part of an expression and therefore does
   * not have a terminating semicolon. Return the function body that was parsed.
   *
   *     functionBody ::=
   *         '=>' expression ';'
   *       | block
   *
   *     functionExpressionBody ::=
   *         '=>' expression
   *       | block
   */
  FunctionBody parseFunctionBody(
      bool mayBeEmpty, ParserErrorCode emptyErrorCode, bool inExpression) {
    bool wasInAsync = _inAsync;
    bool wasInGenerator = _inGenerator;
    bool wasInLoop = _inLoop;
    bool wasInSwitch = _inSwitch;
    _inAsync = false;
    _inGenerator = false;
    _inLoop = false;
    _inSwitch = false;
    try {
      TokenType type = _currentToken.type;
      if (type == TokenType.SEMICOLON) {
        if (!mayBeEmpty) {
          _reportErrorForCurrentToken(emptyErrorCode);
        }
        return astFactory.emptyFunctionBody(getAndAdvance());
      }
      Token keyword = null;
      Token star = null;
      bool foundAsync = false;
      bool foundSync = false;
      if (type == TokenType.KEYWORD) {
        String lexeme = _currentToken.lexeme;
        if (lexeme == ASYNC) {
          foundAsync = true;
          keyword = getAndAdvance();
          if (_matches(TokenType.STAR)) {
            star = getAndAdvance();
            _inGenerator = true;
          }
          type = _currentToken.type;
          _inAsync = true;
        } else if (lexeme == SYNC) {
          foundSync = true;
          keyword = getAndAdvance();
          if (_matches(TokenType.STAR)) {
            star = getAndAdvance();
            _inGenerator = true;
          }
          type = _currentToken.type;
        }
      }
      if (type == TokenType.FUNCTION) {
        if (keyword != null) {
          if (!foundAsync) {
            _reportErrorForToken(ParserErrorCode.INVALID_SYNC, keyword);
            keyword = null;
          } else if (star != null) {
            _reportErrorForToken(
                ParserErrorCode.INVALID_STAR_AFTER_ASYNC, star);
          }
        }
        Token functionDefinition = getAndAdvance();
        if (_matchesKeyword(Keyword.RETURN)) {
          _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
              [_currentToken.lexeme]);
          _advance();
        }
        Expression expression = parseExpression2();
        Token semicolon = null;
        if (!inExpression) {
          semicolon = _expect(TokenType.SEMICOLON);
        }
        if (!_parseFunctionBodies) {
          return astFactory
              .emptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON));
        }
        return astFactory.expressionFunctionBody(
            keyword, functionDefinition, expression, semicolon);
      } else if (type == TokenType.OPEN_CURLY_BRACKET) {
        if (keyword != null) {
          if (foundSync && star == null) {
            _reportErrorForToken(
                ParserErrorCode.MISSING_STAR_AFTER_SYNC, keyword);
          }
        }
        if (!_parseFunctionBodies) {
          _skipBlock();
          return astFactory
              .emptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON));
        }
        return astFactory.blockFunctionBody(keyword, star, parseBlock());
      } else if (_matchesKeyword(Keyword.NATIVE)) {
        Token nativeToken = getAndAdvance();
        StringLiteral stringLiteral = null;
        if (_matches(TokenType.STRING)) {
          stringLiteral = _parseStringLiteralUnchecked();
        }
        return astFactory.nativeFunctionBody(
            nativeToken, stringLiteral, _expect(TokenType.SEMICOLON));
      } else {
        // Invalid function body
        _reportErrorForCurrentToken(emptyErrorCode);
        return astFactory
            .emptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON));
      }
    } finally {
      _inAsync = wasInAsync;
      _inGenerator = wasInGenerator;
      _inLoop = wasInLoop;
      _inSwitch = wasInSwitch;
    }
  }

  /**
   * Parse a function declaration. The [commentAndMetadata] is the documentation
   * comment and metadata to be associated with the declaration. The
   * [externalKeyword] is the 'external' keyword, or `null` if the function is
   * not external. The [returnType] is the return type, or `null` if there is no
   * return type. The [isStatement] is `true` if the function declaration is
   * being parsed as a statement. Return the function declaration that was
   * parsed.
   *
   *     functionDeclaration ::=
   *         functionSignature functionBody
   *       | returnType? getOrSet identifier formalParameterList functionBody
   */
  FunctionDeclaration parseFunctionDeclaration(
      CommentAndMetadata commentAndMetadata,
      Token externalKeyword,
      TypeAnnotation returnType) {
    Token keywordToken = null;
    bool isGetter = false;
    Keyword keyword = _currentToken.keyword;
    SimpleIdentifier name = null;
    if (keyword == Keyword.GET) {
      keywordToken = getAndAdvance();
      isGetter = true;
    } else if (keyword == Keyword.SET) {
      keywordToken = getAndAdvance();
    }
    if (keywordToken != null && _matches(TokenType.OPEN_PAREN)) {
      name = astFactory.simpleIdentifier(keywordToken, isDeclaration: true);
      keywordToken = null;
      isGetter = false;
    } else {
      name = parseSimpleIdentifier(isDeclaration: true);
    }
    TypeParameterList typeParameters = _parseGenericMethodTypeParameters();
    FormalParameterList parameters = null;
    if (!isGetter) {
      if (_matches(TokenType.OPEN_PAREN)) {
        parameters = _parseFormalParameterListUnchecked();
        _validateFormalParameterList(parameters);
      } else {
        _reportErrorForCurrentToken(
            ParserErrorCode.MISSING_FUNCTION_PARAMETERS);
        parameters = astFactory.formalParameterList(
            _createSyntheticToken(TokenType.OPEN_PAREN),
            null,
            null,
            null,
            _createSyntheticToken(TokenType.CLOSE_PAREN));
      }
    } else if (_matches(TokenType.OPEN_PAREN)) {
      _reportErrorForCurrentToken(ParserErrorCode.GETTER_WITH_PARAMETERS);
      _parseFormalParameterListUnchecked();
    }
    FunctionBody body;
    if (externalKeyword == null) {
      body = parseFunctionBody(
          false, ParserErrorCode.MISSING_FUNCTION_BODY, false);
    } else {
      body = astFactory.emptyFunctionBody(_expect(TokenType.SEMICOLON));
    }
//        if (!isStatement && matches(TokenType.SEMICOLON)) {
//          // TODO(brianwilkerson) Improve this error message.
//          reportError(ParserErrorCode.UNEXPECTED_TOKEN, currentToken.getLexeme());
//          advance();
//        }
    return astFactory.functionDeclaration(
        commentAndMetadata.comment,
        commentAndMetadata.metadata,
        externalKeyword,
        returnType,
        keywordToken,
        name,
        astFactory.functionExpression(typeParameters, parameters, body));
  }

  /**
   * Parse a function declaration statement. Return the function declaration
   * statement that was parsed.
   *
   *     functionDeclarationStatement ::=
   *         functionSignature functionBody
   */
  Statement parseFunctionDeclarationStatement() {
    Modifiers modifiers = parseModifiers();
    _validateModifiersForFunctionDeclarationStatement(modifiers);
    return _parseFunctionDeclarationStatementAfterReturnType(
        parseCommentAndMetadata(), _parseOptionalReturnType());
  }

  /**
   * Parse a function expression. Return the function expression that was
   * parsed.
   *
   *     functionExpression ::=
   *         typeParameters? formalParameterList functionExpressionBody
   */
  FunctionExpression parseFunctionExpression() {
    TypeParameterList typeParameters = _parseGenericMethodTypeParameters();
    FormalParameterList parameters = parseFormalParameterList();
    _validateFormalParameterList(parameters);
    FunctionBody body =
        parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTION_BODY, true);
    return astFactory.functionExpression(typeParameters, parameters, body);
  }

  /**
   * Parse the portion of a generic function type following the [returnType].
   *
   *     functionType ::=
   *         returnType? 'Function' typeParameters? parameterTypeList
   *     parameterTypeList ::=
   *         '(' ')' |
   *       | '(' normalParameterTypes ','? ')' |
   *       | '(' normalParameterTypes ',' optionalParameterTypes ')' |
   *       | '(' optionalParameterTypes ')'
   *     normalParameterTypes ::=
   *     normalParameterType (',' normalParameterType)*
   *     normalParameterType ::=
   *         type | typedIdentifier
   *     optionalParameterTypes ::=
   *         optionalPositionalParameterTypes | namedParameterTypes
   *     optionalPositionalParameterTypes ::=
   *         '[' normalParameterTypes ','? ']'
   *     namedParameterTypes ::=
   *         '{' typedIdentifier (',' typedIdentifier)* ','? '}'
   *     typedIdentifier ::=
   *         type identifier
   */
  GenericFunctionType parseGenericFunctionTypeAfterReturnType(
      TypeAnnotation returnType) {
    Token functionKeyword = null;
    if (_matchesKeyword(Keyword.FUNCTION)) {
      functionKeyword = getAndAdvance();
    } else if (_matchesIdentifier()) {
      _reportErrorForCurrentToken(ParserErrorCode.NAMED_FUNCTION_TYPE);
    } else {
      _reportErrorForCurrentToken(ParserErrorCode.MISSING_FUNCTION_KEYWORD);
    }
    TypeParameterList typeParameters = null;
    if (_matches(TokenType.LT)) {
      typeParameters = parseTypeParameterList();
    }
    FormalParameterList parameters =
        parseFormalParameterList(inFunctionType: true);
    return astFactory.genericFunctionType(
        returnType, functionKeyword, typeParameters, parameters);
  }

  /**
   * Parse a generic function type alias.
   *
   * This method assumes that the current token is an identifier.
   *
   *     genericTypeAlias ::=
   *         'typedef' identifier typeParameterList? '=' functionType ';'
   */
  GenericTypeAlias parseGenericTypeAlias(
      CommentAndMetadata commentAndMetadata, Token keyword) {
    Identifier name = _parseSimpleIdentifierUnchecked(isDeclaration: true);
    TypeParameterList typeParameters = null;
    if (_matches(TokenType.LT)) {
      typeParameters = parseTypeParameterList();
    }
    Token equals = _expect(TokenType.EQ);
    TypeAnnotation functionType = parseTypeAnnotation(false);
    Token semicolon = _expect(TokenType.SEMICOLON);
    if (functionType is! GenericFunctionType) {
      // TODO(brianwilkerson) Generate a better error.
      _reportErrorForToken(
          ParserErrorCode.INVALID_GENERIC_FUNCTION_TYPE, semicolon);
      // TODO(brianwilkerson) Recover better than this.
      return astFactory.genericTypeAlias(
          commentAndMetadata.comment,
          commentAndMetadata.metadata,
          keyword,
          name,
          typeParameters,
          equals,
          null,
          semicolon);
    }
    return astFactory.genericTypeAlias(
        commentAndMetadata.comment,
        commentAndMetadata.metadata,
        keyword,
        name,
        typeParameters,
        equals,
        functionType,
        semicolon);
  }

  /**
   * Parse a getter. The [commentAndMetadata] is the documentation comment and
   * metadata to be associated with the declaration. The externalKeyword] is the
   * 'external' token. The staticKeyword] is the static keyword, or `null` if
   * the getter is not static. The [returnType] the return type that has already
   * been parsed, or `null` if there was no return type. Return the getter that
   * was parsed.
   *
   * This method assumes that the current token matches `Keyword.GET`.
   *
   *     getter ::=
   *         getterSignature functionBody?
   *
   *     getterSignature ::=
   *         'external'? 'static'? returnType? 'get' identifier
   */
  MethodDeclaration parseGetter(CommentAndMetadata commentAndMetadata,
      Token externalKeyword, Token staticKeyword, TypeAnnotation returnType) {
    Token propertyKeyword = getAndAdvance();
    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
    if (_matches(TokenType.OPEN_PAREN) &&
        _tokenMatches(_peek(), TokenType.CLOSE_PAREN)) {
      _reportErrorForCurrentToken(ParserErrorCode.GETTER_WITH_PARAMETERS);
      _advance();
      _advance();
    }
    FunctionBody body = parseFunctionBody(
        externalKeyword != null || staticKeyword == null,
        ParserErrorCode.STATIC_GETTER_WITHOUT_BODY,
        false);
    if (externalKeyword != null && body is! EmptyFunctionBody) {
      _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_GETTER_WITH_BODY);
    }
    return astFactory.methodDeclaration(
        commentAndMetadata.comment,
        commentAndMetadata.metadata,
        externalKeyword,
        staticKeyword,
        returnType,
        propertyKeyword,
        null,
        name,
        null,
        null,
        body);
  }

  /**
   * Parse a list of identifiers. Return the list of identifiers that were
   * parsed.
   *
   *     identifierList ::=
   *         identifier (',' identifier)*
   */
  List<SimpleIdentifier> parseIdentifierList() {
    List<SimpleIdentifier> identifiers = <SimpleIdentifier>[
      parseSimpleIdentifier()
    ];
    while (_optional(TokenType.COMMA)) {
      identifiers.add(parseSimpleIdentifier());
    }
    return identifiers;
  }

  /**
   * Parse an if-null expression.  Return the if-null expression that was
   * parsed.
   *
   *     ifNullExpression ::= logicalOrExpression ('??' logicalOrExpression)*
   */
  Expression parseIfNullExpression() {
    Expression expression = parseLogicalOrExpression();
    while (_currentToken.type == TokenType.QUESTION_QUESTION) {
      expression = astFactory.binaryExpression(
          expression, getAndAdvance(), parseLogicalOrExpression());
    }
    return expression;
  }

  /**
   * Parse an if statement. Return the if statement that was parsed.
   *
   * This method assumes that the current token matches `Keyword.IF`.
   *
   *     ifStatement ::=
   *         'if' '(' expression ')' statement ('else' statement)?
   */
  Statement parseIfStatement() {
    Token ifKeyword = getAndAdvance();
    Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
    Expression condition = parseExpression2();
    Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
    Statement thenStatement = parseStatement2();
    Token elseKeyword = null;
    Statement elseStatement = null;
    if (_matchesKeyword(Keyword.ELSE)) {
      elseKeyword = getAndAdvance();
      elseStatement = parseStatement2();
    }
    return astFactory.ifStatement(ifKeyword, leftParenthesis, condition,
        rightParenthesis, thenStatement, elseKeyword, elseStatement);
  }

  /**
   * Parse an implements clause. Return the implements clause that was parsed.
   *
   * This method assumes that the current token matches `Keyword.IMPLEMENTS`.
   *
   *     implementsClause ::=
   *         'implements' type (',' type)*
   */
  ImplementsClause parseImplementsClause() {
    Token keyword = getAndAdvance();
    List<TypeName> interfaces = <TypeName>[];
    do {
      TypeName typeName = parseTypeName(false);
      _mustNotBeNullable(typeName, ParserErrorCode.NULLABLE_TYPE_IN_IMPLEMENTS);
      interfaces.add(typeName);
    } while (_optional(TokenType.COMMA));
    return astFactory.implementsClause(keyword, interfaces);
  }

  /**
   * Parse an import directive. The [commentAndMetadata] is the metadata to be
   * associated with the directive. Return the import directive that was parsed.
   *
   * This method assumes that the current token matches `Keyword.IMPORT`.
   *
   *     importDirective ::=
   *         metadata 'import' stringLiteral configuration* (deferred)? ('as' identifier)? combinator*';'
   */
  ImportDirective parseImportDirective(CommentAndMetadata commentAndMetadata) {
    Token importKeyword = getAndAdvance();
    StringLiteral libraryUri = _parseUri();
    List<Configuration> configurations = _parseConfigurations();
    Token deferredToken = null;
    Token asToken = null;
    SimpleIdentifier prefix = null;
    if (_matchesKeyword(Keyword.DEFERRED)) {
      deferredToken = getAndAdvance();
    }
    if (_matchesKeyword(Keyword.AS)) {
      asToken = getAndAdvance();
      prefix = parseSimpleIdentifier(isDeclaration: true);
    } else if (deferredToken != null) {
      _reportErrorForCurrentToken(
          ParserErrorCode.MISSING_PREFIX_IN_DEFERRED_IMPORT);
    } else if (!_matches(TokenType.SEMICOLON) &&
        !_matchesKeyword(Keyword.SHOW) &&
        !_matchesKeyword(Keyword.HIDE)) {
      Token nextToken = _peek();
      if (_tokenMatchesKeyword(nextToken, Keyword.AS) ||
          _tokenMatchesKeyword(nextToken, Keyword.SHOW) ||
          _tokenMatchesKeyword(nextToken, Keyword.HIDE)) {
        _reportErrorForCurrentToken(
            ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken]);
        _advance();
        if (_matchesKeyword(Keyword.AS)) {
          asToken = getAndAdvance();
          prefix = parseSimpleIdentifier(isDeclaration: true);
        }
      }
    }
    List<Combinator> combinators = parseCombinators();
    Token semicolon = _expect(TokenType.SEMICOLON);
    return astFactory.importDirective(
        commentAndMetadata.comment,
        commentAndMetadata.metadata,
        importKeyword,
        libraryUri,
        configurations,
        deferredToken,
        asToken,
        prefix,
        combinators,
        semicolon);
  }

  /**
   * Parse a list of initialized identifiers. The [commentAndMetadata] is the
   * documentation comment and metadata to be associated with the declaration.
   * The [staticKeyword] is the static keyword, or `null` if the getter is not
   * static. The [keyword] is the token representing the 'final', 'const' or
   * 'var' keyword, or `null` if there is no keyword. The [type] is the type
   * that has already been parsed, or `null` if 'var' was provided. Return the
   * getter that was parsed.
   *
   *     declaration ::=
   *         ('static' | 'covariant')? ('var' | type) initializedIdentifierList ';'
   *       | 'final' type? initializedIdentifierList ';'
   *
   *     initializedIdentifierList ::=
   *         initializedIdentifier (',' initializedIdentifier)*
   *
   *     initializedIdentifier ::=
   *         identifier ('=' expression)?
   */
  FieldDeclaration parseInitializedIdentifierList(
      CommentAndMetadata commentAndMetadata,
      Token staticKeyword,
      Token covariantKeyword,
      Token keyword,
      TypeAnnotation type) {
    VariableDeclarationList fieldList =
        parseVariableDeclarationListAfterType(null, keyword, type);
    return astFactory.fieldDeclaration2(
        comment: commentAndMetadata.comment,
        metadata: commentAndMetadata.metadata,
        covariantKeyword: covariantKeyword,
        staticKeyword: staticKeyword,
        fieldList: fieldList,
        semicolon: _expect(TokenType.SEMICOLON));
  }

  /**
   * Parse an instance creation expression. The [keyword] is the 'new' or
   * 'const' keyword that introduces the expression. Return the instance
   * creation expression that was parsed.
   *
   *     instanceCreationExpression ::=
   *         ('new' | 'const') type ('.' identifier)? argumentList
   */
  InstanceCreationExpression parseInstanceCreationExpression(Token keyword) {
    ConstructorName constructorName = parseConstructorName();
    ArgumentList argumentList = _parseArgumentListChecked();
    return astFactory.instanceCreationExpression(
        keyword, constructorName, argumentList);
  }

  /**
   * Parse a label. Return the label that was parsed.
   *
   * This method assumes that the current token matches an identifier and that
   * the following token matches `TokenType.COLON`.
   *
   *     label ::=
   *         identifier ':'
   */
  Label parseLabel({bool isDeclaration: false}) {
    SimpleIdentifier label =
        _parseSimpleIdentifierUnchecked(isDeclaration: isDeclaration);
    Token colon = getAndAdvance();
    return astFactory.label(label, colon);
  }

  /**
   * Parse a library directive. The [commentAndMetadata] is the metadata to be
   * associated with the directive. Return the library directive that was
   * parsed.
   *
   * This method assumes that the current token matches `Keyword.LIBRARY`.
   *
   *     libraryDirective ::=
   *         metadata 'library' identifier ';'
   */
  LibraryDirective parseLibraryDirective(
      CommentAndMetadata commentAndMetadata) {
    Token keyword = getAndAdvance();
    LibraryIdentifier libraryName = _parseLibraryName(
        ParserErrorCode.MISSING_NAME_IN_LIBRARY_DIRECTIVE, keyword);
    Token semicolon = _expect(TokenType.SEMICOLON);
    return astFactory.libraryDirective(commentAndMetadata.comment,
        commentAndMetadata.metadata, keyword, libraryName, semicolon);
  }

  /**
   * Parse a library identifier. Return the library identifier that was parsed.
   *
   *     libraryIdentifier ::=
   *         identifier ('.' identifier)*
   */
  LibraryIdentifier parseLibraryIdentifier() {
    List<SimpleIdentifier> components = <SimpleIdentifier>[];
    components.add(parseSimpleIdentifier());
    while (_optional(TokenType.PERIOD)) {
      components.add(parseSimpleIdentifier());
    }
    return astFactory.libraryIdentifier(components);
  }

  /**
   * Parse a list literal. The [modifier] is the 'const' modifier appearing
   * before the literal, or `null` if there is no modifier. The [typeArguments]
   * is the type arguments appearing before the literal, or `null` if there are
   * no type arguments. Return the list literal that was parsed.
   *
   * This method assumes that the current token matches either
   * `TokenType.OPEN_SQUARE_BRACKET` or `TokenType.INDEX`.
   *
   *     listLiteral ::=
   *         'const'? typeArguments? '[' (expressionList ','?)? ']'
   */
  ListLiteral parseListLiteral(Token modifier, TypeArgumentList typeArguments) {
    if (_matches(TokenType.INDEX)) {
      _splitIndex();
      return astFactory.listLiteral(
          modifier, typeArguments, getAndAdvance(), null, getAndAdvance());
    }
    Token leftBracket = getAndAdvance();
    if (_matches(TokenType.CLOSE_SQUARE_BRACKET)) {
      return astFactory.listLiteral(
          modifier, typeArguments, leftBracket, null, getAndAdvance());
    }
    bool wasInInitializer = _inInitializer;
    _inInitializer = false;
    try {
      List<Expression> elements = <Expression>[parseExpression2()];
      while (_optional(TokenType.COMMA)) {
        if (_matches(TokenType.CLOSE_SQUARE_BRACKET)) {
          return astFactory.listLiteral(
              modifier, typeArguments, leftBracket, elements, getAndAdvance());
        }
        elements.add(parseExpression2());
      }
      Token rightBracket = _expect(TokenType.CLOSE_SQUARE_BRACKET);
      return astFactory.listLiteral(
          modifier, typeArguments, leftBracket, elements, rightBracket);
    } finally {
      _inInitializer = wasInInitializer;
    }
  }

  /**
   * Parse a list or map literal. The [modifier] is the 'const' modifier
   * appearing before the literal, or `null` if there is no modifier. Return the
   * list or map literal that was parsed.
   *
   *     listOrMapLiteral ::=
   *         listLiteral
   *       | mapLiteral
   */
  TypedLiteral parseListOrMapLiteral(Token modifier) {
    TypeArgumentList typeArguments = _parseOptionalTypeArguments();
    if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
      return parseMapLiteral(modifier, typeArguments);
    } else if (_matches(TokenType.OPEN_SQUARE_BRACKET) ||
        _matches(TokenType.INDEX)) {
      return parseListLiteral(modifier, typeArguments);
    }
    _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL);
    return astFactory.listLiteral(
        modifier,
        typeArguments,
        _createSyntheticToken(TokenType.OPEN_SQUARE_BRACKET),
        null,
        _createSyntheticToken(TokenType.CLOSE_SQUARE_BRACKET));
  }

  /**
   * Parse a logical and expression. Return the logical and expression that was
   * parsed.
   *
   *     logicalAndExpression ::=
   *         equalityExpression ('&&' equalityExpression)*
   */
  Expression parseLogicalAndExpression() {
    Expression expression = parseEqualityExpression();
    while (_currentToken.type == TokenType.AMPERSAND_AMPERSAND) {
      expression = astFactory.binaryExpression(
          expression, getAndAdvance(), parseEqualityExpression());
    }
    return expression;
  }

  /**
   * Parse a logical or expression. Return the logical or expression that was
   * parsed.
   *
   *     logicalOrExpression ::=
   *         logicalAndExpression ('||' logicalAndExpression)*
   */
  Expression parseLogicalOrExpression() {
    Expression expression = parseLogicalAndExpression();
    while (_currentToken.type == TokenType.BAR_BAR) {
      expression = astFactory.binaryExpression(
          expression, getAndAdvance(), parseLogicalAndExpression());
    }
    return expression;
  }

  /**
   * Parse a map literal. The [modifier] is the 'const' modifier appearing
   * before the literal, or `null` if there is no modifier. The [typeArguments]
   * is the type arguments that were declared, or `null` if there are no type
   * arguments. Return the map literal that was parsed.
   *
   * This method assumes that the current token matches
   * `TokenType.OPEN_CURLY_BRACKET`.
   *
   *     mapLiteral ::=
   *         'const'? typeArguments? '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}'
   */
  MapLiteral parseMapLiteral(Token modifier, TypeArgumentList typeArguments) {
    Token leftBracket = getAndAdvance();
    if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
      return astFactory.mapLiteral(
          modifier, typeArguments, leftBracket, null, getAndAdvance());
    }
    bool wasInInitializer = _inInitializer;
    _inInitializer = false;
    try {
      List<MapLiteralEntry> entries = <MapLiteralEntry>[parseMapLiteralEntry()];
      while (_optional(TokenType.COMMA)) {
        if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
          return astFactory.mapLiteral(
              modifier, typeArguments, leftBracket, entries, getAndAdvance());
        }
        entries.add(parseMapLiteralEntry());
      }
      Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
      return astFactory.mapLiteral(
          modifier, typeArguments, leftBracket, entries, rightBracket);
    } finally {
      _inInitializer = wasInInitializer;
    }
  }

  /**
   * Parse a map literal entry. Return the map literal entry that was parsed.
   *
   *     mapLiteralEntry ::=
   *         expression ':' expression
   */
  MapLiteralEntry parseMapLiteralEntry() {
    Expression key = parseExpression2();
    Token separator = _expect(TokenType.COLON);
    Expression value = parseExpression2();
    return astFactory.mapLiteralEntry(key, separator, value);
  }

  /**
   * Parse the modifiers preceding a declaration. This method allows the
   * modifiers to appear in any order but does generate errors for duplicated
   * modifiers. Checks for other problems, such as having the modifiers appear
   * in the wrong order or specifying both 'const' and 'final', are reported in
   * one of the methods whose name is prefixed with `validateModifiersFor`.
   * Return the modifiers that were parsed.
   *
   *     modifiers ::=
   *         ('abstract' | 'const' | 'external' | 'factory' | 'final' | 'static' | 'var')*
   */
  Modifiers parseModifiers() {
    Modifiers modifiers = new Modifiers();
    bool progress = true;
    while (progress) {
      TokenType nextType = _peek().type;
      if (nextType == TokenType.PERIOD ||
          nextType == TokenType.LT ||
          nextType == TokenType.OPEN_PAREN) {
        return modifiers;
      }
      Keyword keyword = _currentToken.keyword;
      if (keyword == Keyword.ABSTRACT) {
        if (modifiers.abstractKeyword != null) {
          _reportErrorForCurrentToken(
              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          _advance();
        } else {
          modifiers.abstractKeyword = getAndAdvance();
        }
      } else if (keyword == Keyword.CONST) {
        if (modifiers.constKeyword != null) {
          _reportErrorForCurrentToken(
              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          _advance();
        } else {
          modifiers.constKeyword = getAndAdvance();
        }
      } else if (keyword == Keyword.COVARIANT) {
        if (modifiers.covariantKeyword != null) {
          _reportErrorForCurrentToken(
              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          _advance();
        } else {
          modifiers.covariantKeyword = getAndAdvance();
        }
      } else if (keyword == Keyword.EXTERNAL) {
        if (modifiers.externalKeyword != null) {
          _reportErrorForCurrentToken(
              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          _advance();
        } else {
          modifiers.externalKeyword = getAndAdvance();
        }
      } else if (keyword == Keyword.FACTORY) {
        if (modifiers.factoryKeyword != null) {
          _reportErrorForCurrentToken(
              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          _advance();
        } else {
          modifiers.factoryKeyword = getAndAdvance();
        }
      } else if (keyword == Keyword.FINAL) {
        if (modifiers.finalKeyword != null) {
          _reportErrorForCurrentToken(
              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          _advance();
        } else {
          modifiers.finalKeyword = getAndAdvance();
        }
      } else if (keyword == Keyword.STATIC) {
        if (modifiers.staticKeyword != null) {
          _reportErrorForCurrentToken(
              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          _advance();
        } else {
          modifiers.staticKeyword = getAndAdvance();
        }
      } else if (keyword == Keyword.VAR) {
        if (modifiers.varKeyword != null) {
          _reportErrorForCurrentToken(
              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          _advance();
        } else {
          modifiers.varKeyword = getAndAdvance();
        }
      } else {
        progress = false;
      }
    }
    return modifiers;
  }

  /**
   * Parse a multiplicative expression. Return the multiplicative expression
   * that was parsed.
   *
   *     multiplicativeExpression ::=
   *         unaryExpression (multiplicativeOperator unaryExpression)*
   *       | 'super' (multiplicativeOperator unaryExpression)+
   */
  Expression parseMultiplicativeExpression() {
    Expression expression;
    if (_currentToken.keyword == Keyword.SUPER &&
        _currentToken.next.type.isMultiplicativeOperator) {
      expression = astFactory.superExpression(getAndAdvance());
    } else {
      expression = parseUnaryExpression();
    }
    while (_currentToken.type.isMultiplicativeOperator) {
      expression = astFactory.binaryExpression(
          expression, getAndAdvance(), parseUnaryExpression());
    }
    return expression;
  }

  /**
   * Parse a new expression. Return the new expression that was parsed.
   *
   * This method assumes that the current token matches `Keyword.NEW`.
   *
   *     newExpression ::=
   *         instanceCreationExpression
   */
  InstanceCreationExpression parseNewExpression() =>
      parseInstanceCreationExpression(getAndAdvance());

  /**
   * Parse a non-labeled statement. Return the non-labeled statement that was
   * parsed.
   *
   *     nonLabeledStatement ::=
   *         block
   *       | assertStatement
   *       | breakStatement
   *       | continueStatement
   *       | doStatement
   *       | forStatement
   *       | ifStatement
   *       | returnStatement
   *       | switchStatement
   *       | tryStatement
   *       | whileStatement
   *       | variableDeclarationList ';'
   *       | expressionStatement
   *       | functionSignature functionBody
   */
  Statement parseNonLabeledStatement() {
    // TODO(brianwilkerson) Pass the comment and metadata on where appropriate.
    CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
    TokenType type = _currentToken.type;
    if (type == TokenType.OPEN_CURLY_BRACKET) {
      if (_tokenMatches(_peek(), TokenType.STRING)) {
        Token afterString = skipStringLiteral(_currentToken.next);
        if (afterString != null && afterString.type == TokenType.COLON) {
          return astFactory.expressionStatement(
              parseExpression2(), _expect(TokenType.SEMICOLON));
        }
      }
      return parseBlock();
    } else if (type == TokenType.KEYWORD &&
        !_currentToken.keyword.isBuiltInOrPseudo) {
      Keyword keyword = _currentToken.keyword;
      // TODO(jwren) compute some metrics to figure out a better order for this
      // if-then sequence to optimize performance
      if (keyword == Keyword.ASSERT) {
        return parseAssertStatement();
      } else if (keyword == Keyword.BREAK) {
        return parseBreakStatement();
      } else if (keyword == Keyword.CONTINUE) {
        return parseContinueStatement();
      } else if (keyword == Keyword.DO) {
        return parseDoStatement();
      } else if (keyword == Keyword.FOR) {
        return parseForStatement();
      } else if (keyword == Keyword.IF) {
        return parseIfStatement();
      } else if (keyword == Keyword.RETHROW) {
        return astFactory.expressionStatement(
            parseRethrowExpression(), _expect(TokenType.SEMICOLON));
      } else if (keyword == Keyword.RETURN) {
        return parseReturnStatement();
      } else if (keyword == Keyword.SWITCH) {
        return parseSwitchStatement();
      } else if (keyword == Keyword.THROW) {
        return astFactory.expressionStatement(
            parseThrowExpression(), _expect(TokenType.SEMICOLON));
      } else if (keyword == Keyword.TRY) {
        return parseTryStatement();
      } else if (keyword == Keyword.WHILE) {
        return parseWhileStatement();
      } else if (keyword == Keyword.VAR || keyword == Keyword.FINAL) {
        return parseVariableDeclarationStatementAfterMetadata(
            commentAndMetadata);
      } else if (keyword == Keyword.VOID) {
        TypeAnnotation returnType;
        if (_atGenericFunctionTypeAfterReturnType(_peek())) {
          returnType = parseTypeAnnotation(false);
        } else {
          returnType = astFactory.typeName(
              astFactory.simpleIdentifier(getAndAdvance()), null);
        }
        Token next = _currentToken.next;
        if (_matchesIdentifier() &&
            next.matchesAny(const <TokenType>[
              TokenType.OPEN_PAREN,
              TokenType.OPEN_CURLY_BRACKET,
              TokenType.FUNCTION,
              TokenType.LT
            ])) {
          return _parseFunctionDeclarationStatementAfterReturnType(
              commentAndMetadata, returnType);
        } else if (_matchesIdentifier() &&
            next.matchesAny(const <TokenType>[
              TokenType.EQ,
              TokenType.COMMA,
              TokenType.SEMICOLON
            ])) {
          if (returnType is! GenericFunctionType) {
            _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType);
          }
          return _parseVariableDeclarationStatementAfterType(
              commentAndMetadata, null, returnType);
        } else {
          //
          // We have found an error of some kind. Try to recover.
          //
          if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
            //
            // We appear to have found an incomplete statement at the end of a
            // block. Parse it as a variable declaration.
            //
            return _parseVariableDeclarationStatementAfterType(
                commentAndMetadata, null, returnType);
          }
          _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT);
          // TODO(brianwilkerson) Recover from this error.
          return astFactory
              .emptyStatement(_createSyntheticToken(TokenType.SEMICOLON));
        }
      } else if (keyword == Keyword.CONST) {
        Token next = _currentToken.next;
        if (next.matchesAny(const <TokenType>[
          TokenType.LT,
          TokenType.OPEN_CURLY_BRACKET,
          TokenType.OPEN_SQUARE_BRACKET,
          TokenType.INDEX
        ])) {
          return astFactory.expressionStatement(
              parseExpression2(), _expect(TokenType.SEMICOLON));
        } else if (_tokenMatches(next, TokenType.IDENTIFIER)) {
          Token afterType = skipTypeName(next);
          if (afterType != null) {
            if (_tokenMatches(afterType, TokenType.OPEN_PAREN) ||
                (_tokenMatches(afterType, TokenType.PERIOD) &&
                    _tokenMatches(afterType.next, TokenType.IDENTIFIER) &&
                    _tokenMatches(afterType.next.next, TokenType.OPEN_PAREN))) {
              return astFactory.expressionStatement(
                  parseExpression2(), _expect(TokenType.SEMICOLON));
            }
          }
        }
        return parseVariableDeclarationStatementAfterMetadata(
            commentAndMetadata);
      } else if (keyword == Keyword.NEW ||
          keyword == Keyword.TRUE ||
          keyword == Keyword.FALSE ||
          keyword == Keyword.NULL ||
          keyword == Keyword.SUPER ||
          keyword == Keyword.THIS) {
        return astFactory.expressionStatement(
            parseExpression2(), _expect(TokenType.SEMICOLON));
      } else {
        //
        // We have found an error of some kind. Try to recover.
        //
        _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT);
        return astFactory
            .emptyStatement(_createSyntheticToken(TokenType.SEMICOLON));
      }
    } else if (_atGenericFunctionTypeAfterReturnType(_currentToken)) {
      TypeAnnotation returnType = parseTypeAnnotation(false);
      Token next = _currentToken.next;
      if (_matchesIdentifier() &&
          next.matchesAny(const <TokenType>[
            TokenType.OPEN_PAREN,
            TokenType.OPEN_CURLY_BRACKET,
            TokenType.FUNCTION,
            TokenType.LT
          ])) {
        return _parseFunctionDeclarationStatementAfterReturnType(
            commentAndMetadata, returnType);
      } else if (_matchesIdentifier() &&
          next.matchesAny(const <TokenType>[
            TokenType.EQ,
            TokenType.COMMA,
            TokenType.SEMICOLON
          ])) {
        if (returnType is! GenericFunctionType) {
          _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType);
        }
        return _parseVariableDeclarationStatementAfterType(
            commentAndMetadata, null, returnType);
      } else {
        //
        // We have found an error of some kind. Try to recover.
        //
        if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
          //
          // We appear to have found an incomplete statement at the end of a
          // block. Parse it as a variable declaration.
          //
          return _parseVariableDeclarationStatementAfterType(
              commentAndMetadata, null, returnType);
        }
        _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT);
        // TODO(brianwilkerson) Recover from this error.
        return astFactory
            .emptyStatement(_createSyntheticToken(TokenType.SEMICOLON));
      }
    } else if (_inGenerator && _matchesKeyword(Keyword.YIELD)) {
      return parseYieldStatement();
    } else if (_inAsync && _matchesKeyword(Keyword.AWAIT)) {
      if (_tokenMatchesKeyword(_peek(), Keyword.FOR)) {
        return parseForStatement();
      }
      return astFactory.expressionStatement(
          parseExpression2(), _expect(TokenType.SEMICOLON));
    } else if (_matchesKeyword(Keyword.AWAIT) &&
        _tokenMatchesKeyword(_peek(), Keyword.FOR)) {
      Token awaitToken = _currentToken;
      Statement statement = parseForStatement();
      if (statement is! ForStatement) {
        _reportErrorForToken(
            CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT, awaitToken);
      }
      return statement;
    } else if (type == TokenType.SEMICOLON) {
      return parseEmptyStatement();
    } else if (isInitializedVariableDeclaration()) {
      return parseVariableDeclarationStatementAfterMetadata(commentAndMetadata);
    } else if (isFunctionDeclaration()) {
      return parseFunctionDeclarationStatement();
    } else if (type == TokenType.CLOSE_CURLY_BRACKET) {
      _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT);
      return astFactory
          .emptyStatement(_createSyntheticToken(TokenType.SEMICOLON));
    } else {
      return astFactory.expressionStatement(
          parseExpression2(), _expect(TokenType.SEMICOLON));
    }
  }

  /**
   * Parse a normal formal parameter. Return the normal formal parameter that
   * was parsed.
   *
   *     normalFormalParameter ::=
   *         functionSignature
   *       | fieldFormalParameter
   *       | simpleFormalParameter
   *
   *     functionSignature:
   *         metadata returnType? identifier typeParameters? formalParameterList
   *
   *     fieldFormalParameter ::=
   *         metadata finalConstVarOrType? 'this' '.' identifier
   *
   *     simpleFormalParameter ::=
   *         declaredIdentifier
   *       | metadata identifier
   */
  NormalFormalParameter parseNormalFormalParameter(
      {bool inFunctionType: false}) {
    Token covariantKeyword;
    CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
    if (_matchesKeyword(Keyword.COVARIANT)) {
      // Check to ensure that 'covariant' isn't being used as the parameter name.
      Token next = _peek();
      if (_tokenMatchesKeyword(next, Keyword.FINAL) ||
          _tokenMatchesKeyword(next, Keyword.CONST) ||
          _tokenMatchesKeyword(next, Keyword.VAR) ||
          _tokenMatchesKeyword(next, Keyword.THIS) ||
          _tokenMatchesIdentifier(next)) {
        covariantKeyword = getAndAdvance();
      }
    }
    FinalConstVarOrType holder = parseFinalConstVarOrType(!inFunctionType,
        inFunctionType: inFunctionType);
    Token thisKeyword = null;
    Token period = null;
    if (_matchesKeyword(Keyword.THIS)) {
      thisKeyword = getAndAdvance();
      period = _expect(TokenType.PERIOD);
    }
    if (!_matchesIdentifier() && inFunctionType) {
      return astFactory.simpleFormalParameter2(
          comment: commentAndMetadata.comment,
          metadata: commentAndMetadata.metadata,
          covariantKeyword: covariantKeyword,
          keyword: holder.keyword,
          type: holder.type,
          identifier: null);
    }
    SimpleIdentifier identifier = parseSimpleIdentifier();
    TypeParameterList typeParameters = _parseGenericMethodTypeParameters();
    if (_matches(TokenType.OPEN_PAREN)) {
      FormalParameterList parameters = _parseFormalParameterListUnchecked();
      if (thisKeyword == null) {
        if (holder.keyword != null) {
          _reportErrorForToken(
              ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, holder.keyword);
        }
        Token question = null;
        if (enableNnbd && _matches(TokenType.QUESTION)) {
          question = getAndAdvance();
        }
        return astFactory.functionTypedFormalParameter2(
            comment: commentAndMetadata.comment,
            metadata: commentAndMetadata.metadata,
            covariantKeyword: covariantKeyword,
            returnType: holder.type,
            identifier: astFactory.simpleIdentifier(identifier.token,
                isDeclaration: true),
            typeParameters: typeParameters,
            parameters: parameters,
            question: question);
      } else {
        return astFactory.fieldFormalParameter2(
            comment: commentAndMetadata.comment,
            metadata: commentAndMetadata.metadata,
            covariantKeyword: covariantKeyword,
            keyword: holder.keyword,
            type: holder.type,
            thisKeyword: thisKeyword,
            period: period,
            identifier: identifier,
            typeParameters: typeParameters,
            parameters: parameters);
      }
    } else if (typeParameters != null) {
      // TODO(brianwilkerson) Report an error. It looks like a function-typed
      // parameter with no parameter list.
      //_reportErrorForToken(ParserErrorCode.MISSING_PARAMETERS, typeParameters.endToken);
    }
    TypeAnnotation type = holder.type;
    if (type != null) {
      if (type is TypeName &&
          _tokenMatchesKeyword(type.name.beginToken, Keyword.VOID)) {
        _reportErrorForToken(
            ParserErrorCode.VOID_PARAMETER, type.name.beginToken);
      } else if (holder.keyword != null &&
          _tokenMatchesKeyword(holder.keyword, Keyword.VAR)) {
        _reportErrorForToken(ParserErrorCode.VAR_AND_TYPE, holder.keyword);
      }
    }
    if (thisKeyword != null) {
      // TODO(brianwilkerson) If there are type parameters but no parameters,
      // should we create a synthetic empty parameter list here so we can
      // capture the type parameters?
      return astFactory.fieldFormalParameter2(
          comment: commentAndMetadata.comment,
          metadata: commentAndMetadata.metadata,
          covariantKeyword: covariantKeyword,
          keyword: holder.keyword,
          type: type,
          thisKeyword: thisKeyword,
          period: period,
          identifier: identifier);
    }
    return astFactory.simpleFormalParameter2(
        comment: commentAndMetadata.comment,
        metadata: commentAndMetadata.metadata,
        covariantKeyword: covariantKeyword,
        keyword: holder.keyword,
        type: type,
        identifier:
            astFactory.simpleIdentifier(identifier.token, isDeclaration: true));
  }

  /**
   * Parse an operator declaration. The [commentAndMetadata] is the
   * documentation comment and metadata to be associated with the declaration.
   * The [externalKeyword] is the 'external' token. The [returnType] is the
   * return type that has already been parsed, or `null` if there was no return
   * type. Return the operator declaration that was parsed.
   *
   *     operatorDeclaration ::=
   *         operatorSignature (';' | functionBody)
   *
   *     operatorSignature ::=
   *         'external'? returnType? 'operator' operator formalParameterList
   */
  MethodDeclaration parseOperator(CommentAndMetadata commentAndMetadata,
      Token externalKeyword, TypeName returnType) {
    Token operatorKeyword;
    if (_matchesKeyword(Keyword.OPERATOR)) {
      operatorKeyword = getAndAdvance();
    } else {
      _reportErrorForToken(
          ParserErrorCode.MISSING_KEYWORD_OPERATOR, _currentToken);
      operatorKeyword = _createSyntheticKeyword(Keyword.OPERATOR);
    }
    return _parseOperatorAfterKeyword(
        commentAndMetadata, externalKeyword, returnType, operatorKeyword);
  }

  /**
   * Parse a part or part-of directive. The [commentAndMetadata] is the metadata
   * to be associated with the directive. Return the part or part-of directive
   * that was parsed.
   *
   * This method assumes that the current token matches `Keyword.PART`.
   *
   *     partDirective ::=
   *         metadata 'part' stringLiteral ';'
   *
   *     partOfDirective ::=
   *         metadata 'part' 'of' identifier ';'
   */
  Directive parsePartOrPartOfDirective(CommentAndMetadata commentAndMetadata) {
    if (_tokenMatchesKeyword(_peek(), Keyword.OF)) {
      return _parsePartOfDirective(commentAndMetadata);
    }
    return _parsePartDirective(commentAndMetadata);
  }

  /**
   * Parse a postfix expression. Return the postfix expression that was parsed.
   *
   *     postfixExpression ::=
   *         assignableExpression postfixOperator
   *       | primary selector*
   *
   *     selector ::=
   *         assignableSelector
   *       | argumentList
   */
  Expression parsePostfixExpression() {
    Expression operand = parseAssignableExpression(true);
    TokenType type = _currentToken.type;
    if (type == TokenType.OPEN_SQUARE_BRACKET ||
        type == TokenType.PERIOD ||
        type == TokenType.QUESTION_PERIOD ||
        type == TokenType.OPEN_PAREN ||
        type == TokenType.LT ||
        type == TokenType.INDEX) {
      do {
        if (_isLikelyArgumentList()) {
          TypeArgumentList typeArguments = _parseOptionalTypeArguments();
          ArgumentList argumentList = parseArgumentList();
          Expression currentOperand = operand;
          if (currentOperand is PropertyAccess) {
            operand = astFactory.methodInvocation(
                currentOperand.target,
                currentOperand.operator,
                currentOperand.propertyName,
                typeArguments,
                argumentList);
          } else {
            operand = astFactory.functionExpressionInvocation(
                operand, typeArguments, argumentList);
          }
        } else {
          operand = parseAssignableSelector(operand, true);
        }
        type = _currentToken.type;
      } while (type == TokenType.OPEN_SQUARE_BRACKET ||
          type == TokenType.PERIOD ||
          type == TokenType.QUESTION_PERIOD ||
          type == TokenType.OPEN_PAREN ||
          type == TokenType.INDEX);
      return operand;
    }
    if (!_currentToken.type.isIncrementOperator) {
      return operand;
    }
    _ensureAssignable(operand);
    Token operator = getAndAdvance();
    return astFactory.postfixExpression(operand, operator);
  }

  /**
   * Parse a prefixed identifier. Return the prefixed identifier that was
   * parsed.
   *
   *     prefixedIdentifier ::=
   *         identifier ('.' identifier)?
   */
  Identifier parsePrefixedIdentifier() {
    return _parsePrefixedIdentifierAfterIdentifier(parseSimpleIdentifier());
  }

  /**
   * Parse a primary expression. Return the primary expression that was parsed.
   *
   *     primary ::=
   *         thisExpression
   *       | 'super' unconditionalAssignableSelector
   *       | functionExpression
   *       | literal
   *       | identifier
   *       | newExpression
   *       | constObjectExpression
   *       | '(' expression ')'
   *       | argumentDefinitionTest
   *
   *     literal ::=
   *         nullLiteral
   *       | booleanLiteral
   *       | numericLiteral
   *       | stringLiteral
   *       | symbolLiteral
   *       | mapLiteral
   *       | listLiteral
   */
  Expression parsePrimaryExpression() {
    if (_matchesIdentifier()) {
      // TODO(brianwilkerson) The code below was an attempt to recover from an
      // error case, but it needs to be applied as a recovery only after we
      // know that parsing it as an identifier doesn't work. Leaving the code as
      // a reminder of how to recover.
//      if (isFunctionExpression(_peek())) {
//        //
//        // Function expressions were allowed to have names at one point, but this is now illegal.
//        //
//        reportError(ParserErrorCode.NAMED_FUNCTION_EXPRESSION, getAndAdvance());
//        return parseFunctionExpression();
//      }
      return _parsePrefixedIdentifierUnchecked();
    }
    TokenType type = _currentToken.type;
    if (type == TokenType.STRING) {
      return parseStringLiteral();
    } else if (type == TokenType.INT) {
      Token token = getAndAdvance();
      int value = null;
      try {
        value = int.parse(token.lexeme);
      } on FormatException {
        // The invalid format should have been reported by the scanner.
      }
      return astFactory.integerLiteral(token, value);
    }
    Keyword keyword = _currentToken.keyword;
    if (keyword == Keyword.NULL) {
      return astFactory.nullLiteral(getAndAdvance());
    } else if (keyword == Keyword.NEW) {
      return parseNewExpression();
    } else if (keyword == Keyword.THIS) {
      return astFactory.thisExpression(getAndAdvance());
    } else if (keyword == Keyword.SUPER) {
      // TODO(paulberry): verify with Gilad that "super" must be followed by
      // unconditionalAssignableSelector in this case.
      return parseAssignableSelector(
          astFactory.superExpression(getAndAdvance()), false,
          allowConditional: false);
    } else if (keyword == Keyword.FALSE) {
      return astFactory.booleanLiteral(getAndAdvance(), false);
    } else if (keyword == Keyword.TRUE) {
      return astFactory.booleanLiteral(getAndAdvance(), true);
    }
    if (type == TokenType.DOUBLE) {
      Token token = getAndAdvance();
      double value = 0.0;
      try {
        value = double.parse(token.lexeme);
      } on FormatException {
        // The invalid format should have been reported by the scanner.
      }
      return astFactory.doubleLiteral(token, value);
    } else if (type == TokenType.HEXADECIMAL) {
      Token token = getAndAdvance();
      int value = null;
      try {
        value = int.parse(token.lexeme.substring(2), radix: 16);
      } on FormatException {
        // The invalid format should have been reported by the scanner.
      }
      return astFactory.integerLiteral(token, value);
    } else if (keyword == Keyword.CONST) {
      return parseConstExpression();
    } else if (type == TokenType.OPEN_PAREN) {
      if (isFunctionExpression(_currentToken)) {
        return parseFunctionExpression();
      }
      Token leftParenthesis = getAndAdvance();
      bool wasInInitializer = _inInitializer;
      _inInitializer = false;
      try {
        Expression expression = parseExpression2();
        Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
        return astFactory.parenthesizedExpression(
            leftParenthesis, expression, rightParenthesis);
      } finally {
        _inInitializer = wasInInitializer;
      }
    } else if (type == TokenType.LT || _injectGenericCommentTypeList()) {
      if (isFunctionExpression(currentToken)) {
        return parseFunctionExpression();
      }
      return parseListOrMapLiteral(null);
    } else if (type == TokenType.OPEN_CURLY_BRACKET) {
      return parseMapLiteral(null, null);
    } else if (type == TokenType.OPEN_SQUARE_BRACKET ||
        type == TokenType.INDEX) {
      return parseListLiteral(null, null);
    } else if (type == TokenType.QUESTION &&
        _tokenMatches(_peek(), TokenType.IDENTIFIER)) {
      _reportErrorForCurrentToken(
          ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken.lexeme]);
      _advance();
      return parsePrimaryExpression();
    } else if (keyword == Keyword.VOID) {
      //
      // Recover from having a return type of "void" where a return type is not
      // expected.
      //
      // TODO(brianwilkerson) Improve this error message.
      _reportErrorForCurrentToken(
          ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken.lexeme]);
      _advance();
      return parsePrimaryExpression();
    } else if (type == TokenType.HASH) {
      return parseSymbolLiteral();
    } else {
      _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
      return createSyntheticIdentifier();
    }
  }

  /**
   * Parse a redirecting constructor invocation. The flag [hasPeriod] should be
   * `true` if the `this` is followed by a period. Return the redirecting
   * constructor invocation that was parsed.
   *
   * This method assumes that the current token matches `Keyword.THIS`.
   *
   *     redirectingConstructorInvocation ::=
   *         'this' ('.' identifier)? arguments
   */
  RedirectingConstructorInvocation parseRedirectingConstructorInvocation(
      bool hasPeriod) {
    Token keyword = getAndAdvance();
    Token period = null;
    SimpleIdentifier constructorName = null;
    if (hasPeriod) {
      period = getAndAdvance();
      if (_matchesIdentifier()) {
        constructorName = _parseSimpleIdentifierUnchecked(isDeclaration: false);
      } else {
        _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
        constructorName = createSyntheticIdentifier(isDeclaration: false);
        _advance();
      }
    }
    ArgumentList argumentList = _parseArgumentListChecked();
    return astFactory.redirectingConstructorInvocation(
        keyword, period, constructorName, argumentList);
  }

  /**
   * Parse a relational expression. Return the relational expression that was
   * parsed.
   *
   *     relationalExpression ::=
   *         bitwiseOrExpression ('is' '!'? type | 'as' type | relationalOperator bitwiseOrExpression)?
   *       | 'super' relationalOperator bitwiseOrExpression
   */
  Expression parseRelationalExpression() {
    if (_currentToken.keyword == Keyword.SUPER &&
        _currentToken.next.type.isRelationalOperator) {
      Expression expression = astFactory.superExpression(getAndAdvance());
      Token operator = getAndAdvance();
      return astFactory.binaryExpression(
          expression, operator, parseBitwiseOrExpression());
    }
    Expression expression = parseBitwiseOrExpression();
    Keyword keyword = _currentToken.keyword;
    if (keyword == Keyword.AS) {
      Token asOperator = getAndAdvance();
      return astFactory.asExpression(
          expression, asOperator, parseTypeAnnotation(true));
    } else if (keyword == Keyword.IS) {
      Token isOperator = getAndAdvance();
      Token notOperator = null;
      if (_matches(TokenType.BANG)) {
        notOperator = getAndAdvance();
      }
      TypeAnnotation type = parseTypeAnnotation(true);
      return astFactory.isExpression(expression, isOperator, notOperator, type);
    } else if (_currentToken.type.isRelationalOperator) {
      Token operator = getAndAdvance();
      return astFactory.binaryExpression(
          expression, operator, parseBitwiseOrExpression());
    }
    return expression;
  }

  /**
   * Parse a rethrow expression. Return the rethrow expression that was parsed.
   *
   * This method assumes that the current token matches `Keyword.RETHROW`.
   *
   *     rethrowExpression ::=
   *         'rethrow'
   */
  Expression parseRethrowExpression() =>
      astFactory.rethrowExpression(getAndAdvance());

  /**
   * Parse a return statement. Return the return statement that was parsed.
   *
   * This method assumes that the current token matches `Keyword.RETURN`.
   *
   *     returnStatement ::=
   *         'return' expression? ';'
   */
  Statement parseReturnStatement() {
    Token returnKeyword = getAndAdvance();
    if (_matches(TokenType.SEMICOLON)) {
      return astFactory.returnStatement(returnKeyword, null, getAndAdvance());
    }
    Expression expression = parseExpression2();
    Token semicolon = _expect(TokenType.SEMICOLON);
    return astFactory.returnStatement(returnKeyword, expression, semicolon);
  }

  /**
   * Parse a return type. Return the return type that was parsed.
   *
   *     returnType ::=
   *         'void'
   *       | type
   */
  TypeAnnotation parseReturnType(bool inExpression) {
    if (_currentToken.keyword == Keyword.VOID) {
      if (_atGenericFunctionTypeAfterReturnType(_peek())) {
        return parseTypeAnnotation(false);
      } else {
        return astFactory.typeName(
            astFactory.simpleIdentifier(getAndAdvance()), null);
      }
    } else {
      return parseTypeAnnotation(inExpression);
    }
  }

  /**
   * Parse a setter. The [commentAndMetadata] is the documentation comment and
   * metadata to be associated with the declaration. The [externalKeyword] is
   * the 'external' token. The [staticKeyword] is the static keyword, or `null`
   * if the setter is not static. The [returnType] is the return type that has
   * already been parsed, or `null` if there was no return type. Return the
   * setter that was parsed.
   *
   * This method assumes that the current token matches `Keyword.SET`.
   *
   *     setter ::=
   *         setterSignature functionBody?
   *
   *     setterSignature ::=
   *         'external'? 'static'? returnType? 'set' identifier formalParameterList
   */
  MethodDeclaration parseSetter(CommentAndMetadata commentAndMetadata,
      Token externalKeyword, Token staticKeyword, TypeAnnotation returnType) {
    Token propertyKeyword = getAndAdvance();
    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
    FormalParameterList parameters = parseFormalParameterList();
    _validateFormalParameterList(parameters);
    FunctionBody body = parseFunctionBody(
        externalKeyword != null || staticKeyword == null,
        ParserErrorCode.STATIC_SETTER_WITHOUT_BODY,
        false);
    if (externalKeyword != null && body is! EmptyFunctionBody) {
      _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_SETTER_WITH_BODY);
    }
    return astFactory.methodDeclaration(
        commentAndMetadata.comment,
        commentAndMetadata.metadata,
        externalKeyword,
        staticKeyword,
        returnType,
        propertyKeyword,
        null,
        name,
        null,
        parameters,
        body);
  }

  /**
   * Parse a shift expression. Return the shift expression that was parsed.
   *
   *     shiftExpression ::=
   *         additiveExpression (shiftOperator additiveExpression)*
   *       | 'super' (shiftOperator additiveExpression)+
   */
  Expression parseShiftExpression() {
    Expression expression;
    if (_currentToken.keyword == Keyword.SUPER &&
        _currentToken.next.type.isShiftOperator) {
      expression = astFactory.superExpression(getAndAdvance());
    } else {
      expression = parseAdditiveExpression();
    }
    while (_currentToken.type.isShiftOperator) {
      expression = astFactory.binaryExpression(
          expression, getAndAdvance(), parseAdditiveExpression());
    }
    return expression;
  }

  /**
   * Parse a simple identifier. Return the simple identifier that was parsed.
   *
   *     identifier ::=
   *         IDENTIFIER
   */
  SimpleIdentifier parseSimpleIdentifier(
      {bool allowKeyword: false, bool isDeclaration: false}) {
    if (_matchesIdentifier() ||
        (allowKeyword && _tokenMatchesIdentifierOrKeyword(_currentToken))) {
      return _parseSimpleIdentifierUnchecked(isDeclaration: isDeclaration);
    }
    _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
    return createSyntheticIdentifier(isDeclaration: isDeclaration);
  }

  /**
   * Parse a statement, starting with the given [token]. Return the statement
   * that was parsed, or `null` if the tokens do not represent a recognizable
   * statement.
   */
  Statement parseStatement(Token token) {
    _currentToken = token;
    return parseStatement2();
  }

  /**
   * Parse a statement. Return the statement that was parsed.
   *
   *     statement ::=
   *         label* nonLabeledStatement
   */
  Statement parseStatement2() {
    if (_treeDepth > _MAX_TREE_DEPTH) {
      throw new _TooDeepTreeError();
    }
    _treeDepth++;
    try {
      List<Label> labels = null;
      while (
          _matchesIdentifier() && _currentToken.next.type == TokenType.COLON) {
        Label label = parseLabel(isDeclaration: true);
        if (labels == null) {
          labels = <Label>[label];
        } else {
          labels.add(label);
        }
      }
      Statement statement = parseNonLabeledStatement();
      if (labels == null) {
        return statement;
      }
      return astFactory.labeledStatement(labels, statement);
    } finally {
      _treeDepth--;
    }
  }

  /**
   * Parse a sequence of statements, starting with the given [token]. Return the
   * statements that were parsed, or `null` if the tokens do not represent a
   * recognizable sequence of statements.
   */
  List<Statement> parseStatements(Token token) {
    _currentToken = token;
    return _parseStatementList();
  }

  /**
   * Parse a string literal. Return the string literal that was parsed.
   *
   *     stringLiteral ::=
   *         MULTI_LINE_STRING+
   *       | SINGLE_LINE_STRING+
   */
  StringLiteral parseStringLiteral() {
    if (_matches(TokenType.STRING)) {
      return _parseStringLiteralUnchecked();
    }
    _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_STRING_LITERAL);
    return createSyntheticStringLiteral();
  }

  /**
   * Parse a super constructor invocation. Return the super constructor
   * invocation that was parsed.
   *
   * This method assumes that the current token matches [Keyword.SUPER].
   *
   *     superConstructorInvocation ::=
   *         'super' ('.' identifier)? arguments
   */
  SuperConstructorInvocation parseSuperConstructorInvocation() {
    Token keyword = getAndAdvance();
    Token period = null;
    SimpleIdentifier constructorName = null;
    if (_matches(TokenType.PERIOD)) {
      period = getAndAdvance();
      constructorName = parseSimpleIdentifier();
    }
    ArgumentList argumentList = _parseArgumentListChecked();
    return astFactory.superConstructorInvocation(
        keyword, period, constructorName, argumentList);
  }

  /**
   * Parse a switch statement. Return the switch statement that was parsed.
   *
   *     switchStatement ::=
   *         'switch' '(' expression ')' '{' switchCase* defaultCase? '}'
   *
   *     switchCase ::=
   *         label* ('case' expression ':') statements
   *
   *     defaultCase ::=
   *         label* 'default' ':' statements
   */
  SwitchStatement parseSwitchStatement() {
    bool wasInSwitch = _inSwitch;
    _inSwitch = true;
    try {
      HashSet<String> definedLabels = new HashSet<String>();
      Token keyword = _expectKeyword(Keyword.SWITCH);
      Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
      Expression expression = parseExpression2();
      Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
      Token leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET);
      Token defaultKeyword = null;
      List<SwitchMember> members = <SwitchMember>[];
      TokenType type = _currentToken.type;
      while (type != TokenType.EOF && type != TokenType.CLOSE_CURLY_BRACKET) {
        List<Label> labels = <Label>[];
        while (
            _matchesIdentifier() && _tokenMatches(_peek(), TokenType.COLON)) {
          SimpleIdentifier identifier =
              _parseSimpleIdentifierUnchecked(isDeclaration: true);
          String label = identifier.token.lexeme;
          if (definedLabels.contains(label)) {
            _reportErrorForToken(
                ParserErrorCode.DUPLICATE_LABEL_IN_SWITCH_STATEMENT,
                identifier.token,
                [label]);
          } else {
            definedLabels.add(label);
          }
          Token colon = getAndAdvance();
          labels.add(astFactory.label(identifier, colon));
        }
        Keyword keyword = _currentToken.keyword;
        if (keyword == Keyword.CASE) {
          Token caseKeyword = getAndAdvance();
          Expression caseExpression = parseExpression2();
          Token colon = _expect(TokenType.COLON);
          members.add(astFactory.switchCase(labels, caseKeyword, caseExpression,
              colon, _parseStatementList()));
          if (defaultKeyword != null) {
            _reportErrorForToken(
                ParserErrorCode.SWITCH_HAS_CASE_AFTER_DEFAULT_CASE,
                caseKeyword);
          }
        } else if (keyword == Keyword.DEFAULT) {
          if (defaultKeyword != null) {
            _reportErrorForToken(
                ParserErrorCode.SWITCH_HAS_MULTIPLE_DEFAULT_CASES, _peek());
          }
          defaultKeyword = getAndAdvance();
          Token colon = _expect(TokenType.COLON);
          members.add(astFactory.switchDefault(
              labels, defaultKeyword, colon, _parseStatementList()));
        } else {
          // We need to advance, otherwise we could end up in an infinite loop,
          // but this could be a lot smarter about recovering from the error.
          _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_CASE_OR_DEFAULT);
          bool atEndOrNextMember() {
            TokenType type = _currentToken.type;
            if (type == TokenType.EOF ||
                type == TokenType.CLOSE_CURLY_BRACKET) {
              return true;
            }
            Keyword keyword = _currentToken.keyword;
            return keyword == Keyword.CASE || keyword == Keyword.DEFAULT;
          }

          while (!atEndOrNextMember()) {
            _advance();
          }
        }
        type = _currentToken.type;
      }
      Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
      return astFactory.switchStatement(keyword, leftParenthesis, expression,
          rightParenthesis, leftBracket, members, rightBracket);
    } finally {
      _inSwitch = wasInSwitch;
    }
  }

  /**
   * Parse a symbol literal. Return the symbol literal that was parsed.
   *
   * This method assumes that the current token matches [TokenType.HASH].
   *
   *     symbolLiteral ::=
   *         '#' identifier ('.' identifier)*
   */
  SymbolLiteral parseSymbolLiteral() {
    Token poundSign = getAndAdvance();
    List<Token> components = <Token>[];
    if (_matchesIdentifier()) {
      components.add(getAndAdvance());
      while (_optional(TokenType.PERIOD)) {
        if (_matchesIdentifier()) {
          components.add(getAndAdvance());
        } else {
          _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
          components.add(_createSyntheticToken(TokenType.IDENTIFIER));
          break;
        }
      }
    } else if (_currentToken.isOperator) {
      components.add(getAndAdvance());
    } else if (_matchesKeyword(Keyword.VOID)) {
      components.add(getAndAdvance());
    } else {
      _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
      components.add(_createSyntheticToken(TokenType.IDENTIFIER));
    }
    return astFactory.symbolLiteral(poundSign, components);
  }

  /**
   * Parse a throw expression. Return the throw expression that was parsed.
   *
   * This method assumes that the current token matches [Keyword.THROW].
   *
   *     throwExpression ::=
   *         'throw' expression
   */
  Expression parseThrowExpression() {
    Token keyword = getAndAdvance();
    TokenType type = _currentToken.type;
    if (type == TokenType.SEMICOLON || type == TokenType.CLOSE_PAREN) {
      _reportErrorForToken(
          ParserErrorCode.MISSING_EXPRESSION_IN_THROW, _currentToken);
      return astFactory.throwExpression(keyword, createSyntheticIdentifier());
    }
    Expression expression = parseExpression2();
    return astFactory.throwExpression(keyword, expression);
  }

  /**
   * Parse a throw expression. Return the throw expression that was parsed.
   *
   * This method assumes that the current token matches [Keyword.THROW].
   *
   *     throwExpressionWithoutCascade ::=
   *         'throw' expressionWithoutCascade
   */
  Expression parseThrowExpressionWithoutCascade() {
    Token keyword = getAndAdvance();
    TokenType type = _currentToken.type;
    if (type == TokenType.SEMICOLON || type == TokenType.CLOSE_PAREN) {
      _reportErrorForToken(
          ParserErrorCode.MISSING_EXPRESSION_IN_THROW, _currentToken);
      return astFactory.throwExpression(keyword, createSyntheticIdentifier());
    }
    Expression expression = parseExpressionWithoutCascade();
    return astFactory.throwExpression(keyword, expression);
  }

  /**
   * Parse a try statement. Return the try statement that was parsed.
   *
   * This method assumes that the current token matches [Keyword.TRY].
   *
   *     tryStatement ::=
   *         'try' block (onPart+ finallyPart? | finallyPart)
   *
   *     onPart ::=
   *         catchPart block
   *       | 'on' type catchPart? block
   *
   *     catchPart ::=
   *         'catch' '(' identifier (',' identifier)? ')'
   *
   *     finallyPart ::=
   *         'finally' block
   */
  Statement parseTryStatement() {
    Token tryKeyword = getAndAdvance();
    Block body = _parseBlockChecked();
    List<CatchClause> catchClauses = <CatchClause>[];
    Block finallyClause = null;
    while (_matchesKeyword(Keyword.ON) || _matchesKeyword(Keyword.CATCH)) {
      Token onKeyword = null;
      TypeName exceptionType = null;
      if (_matchesKeyword(Keyword.ON)) {
        onKeyword = getAndAdvance();
        exceptionType = parseTypeAnnotation(false);
      }
      Token catchKeyword = null;
      Token leftParenthesis = null;
      SimpleIdentifier exceptionParameter = null;
      Token comma = null;
      SimpleIdentifier stackTraceParameter = null;
      Token rightParenthesis = null;
      if (_matchesKeyword(Keyword.CATCH)) {
        catchKeyword = getAndAdvance();
        leftParenthesis = _expect(TokenType.OPEN_PAREN);
        exceptionParameter = parseSimpleIdentifier(isDeclaration: true);
        if (_matches(TokenType.COMMA)) {
          comma = getAndAdvance();
          stackTraceParameter = parseSimpleIdentifier(isDeclaration: true);
        }
        rightParenthesis = _expect(TokenType.CLOSE_PAREN);
      }
      Block catchBody = _parseBlockChecked();
      catchClauses.add(astFactory.catchClause(
          onKeyword,
          exceptionType,
          catchKeyword,
          leftParenthesis,
          exceptionParameter,
          comma,
          stackTraceParameter,
          rightParenthesis,
          catchBody));
    }
    Token finallyKeyword = null;
    if (_matchesKeyword(Keyword.FINALLY)) {
      finallyKeyword = getAndAdvance();
      finallyClause = _parseBlockChecked();
    } else if (catchClauses.isEmpty) {
      _reportErrorForCurrentToken(ParserErrorCode.MISSING_CATCH_OR_FINALLY);
    }
    return astFactory.tryStatement(
        tryKeyword, body, catchClauses, finallyKeyword, finallyClause);
  }

  /**
   * Parse a type alias. The [commentAndMetadata] is the metadata to be
   * associated with the member. Return the type alias that was parsed.
   *
   * This method assumes that the current token matches [Keyword.TYPEDEF].
   *
   *     typeAlias ::=
   *         'typedef' typeAliasBody
   *       | genericTypeAlias
   *
   *     typeAliasBody ::=
   *         functionTypeAlias
   *
   *     functionTypeAlias ::=
   *         functionPrefix typeParameterList? formalParameterList ';'
   *
   *     functionPrefix ::=
   *         returnType? name
   */
  TypeAlias parseTypeAlias(CommentAndMetadata commentAndMetadata) {
    Token keyword = getAndAdvance();
    if (_matchesIdentifier()) {
      Token next = _peek();
      if (_tokenMatches(next, TokenType.LT)) {
        next = _skipTypeParameterList(next);
        if (next != null && _tokenMatches(next, TokenType.EQ)) {
          TypeAlias typeAlias =
              parseGenericTypeAlias(commentAndMetadata, keyword);
          return typeAlias;
        }
      } else if (_tokenMatches(next, TokenType.EQ)) {
        TypeAlias typeAlias =
            parseGenericTypeAlias(commentAndMetadata, keyword);
        return typeAlias;
      }
    }
    return _parseFunctionTypeAlias(commentAndMetadata, keyword);
  }

  /**
   * Parse a type.
   *
   *     type ::=
   *         typeWithoutFunction
   *       | functionType
   */
  TypeAnnotation parseTypeAnnotation(bool inExpression) {
    TypeAnnotation type = null;
    if (_atGenericFunctionTypeAfterReturnType(_currentToken)) {
      // Generic function type with no return type.
      type = parseGenericFunctionTypeAfterReturnType(null);
    } else if (_currentToken.keyword == Keyword.VOID &&
        _atGenericFunctionTypeAfterReturnType(_currentToken.next)) {
      type = astFactory.typeName(
          astFactory.simpleIdentifier(getAndAdvance()), null);
    } else {
      type = parseTypeName(inExpression);
    }
    while (_atGenericFunctionTypeAfterReturnType(_currentToken)) {
      type = parseGenericFunctionTypeAfterReturnType(type);
    }
    return type;
  }

  /**
   * Parse a list of type arguments. Return the type argument list that was
   * parsed.
   *
   * This method assumes that the current token matches `TokenType.LT`.
   *
   *     typeArguments ::=
   *         '<' typeList '>'
   *
   *     typeList ::=
   *         type (',' type)*
   */
  TypeArgumentList parseTypeArgumentList() {
    Token leftBracket = getAndAdvance();
    List<TypeAnnotation> arguments = <TypeAnnotation>[
      parseTypeAnnotation(false)
    ];
    while (_optional(TokenType.COMMA)) {
      arguments.add(parseTypeAnnotation(false));
    }
    Token rightBracket = _expectGt();
    return astFactory.typeArgumentList(leftBracket, arguments, rightBracket);
  }

  /**
   * Parse a type name. Return the type name that was parsed.
   *
   *     type ::=
   *         qualified typeArguments?
   */
  TypeName parseTypeName(bool inExpression) {
    TypeName realType = _parseTypeName(inExpression);
    // If this is followed by a generic method type comment, allow the comment
    // type to replace the real type name.
    // TODO(jmesserly): this feels like a big hammer. Can we restrict it to
    // only work inside generic methods?
    TypeName typeFromComment = _parseOptionalTypeNameComment();
    return typeFromComment ?? realType;
  }

  /**
   * Parse a type parameter. Return the type parameter that was parsed.
   *
   *     typeParameter ::=
   *         metadata name ('extends' bound)?
   */
  TypeParameter parseTypeParameter() {
    CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
    if (_matches(TokenType.QUESTION)) {
      _reportErrorForCurrentToken(ParserErrorCode.NULLABLE_TYPE_PARAMETER);
      _advance();
    }
    if (_matchesKeyword(Keyword.EXTENDS)) {
      Token keyword = getAndAdvance();
      TypeAnnotation bound = parseTypeAnnotation(false);
      return astFactory.typeParameter(commentAndMetadata.comment,
          commentAndMetadata.metadata, name, keyword, bound);
    }
    return astFactory.typeParameter(commentAndMetadata.comment,
        commentAndMetadata.metadata, name, null, null);
  }

  /**
   * Parse a list of type parameters. Return the list of type parameters that
   * were parsed.
   *
   * This method assumes that the current token matches `TokenType.LT`.
   *
   *     typeParameterList ::=
   *         '<' typeParameter (',' typeParameter)* '>'
   */
  TypeParameterList parseTypeParameterList() {
    Token leftBracket = getAndAdvance();
    List<TypeParameter> typeParameters = <TypeParameter>[parseTypeParameter()];
    while (_optional(TokenType.COMMA)) {
      typeParameters.add(parseTypeParameter());
    }
    Token rightBracket = _expectGt();
    return astFactory.typeParameterList(
        leftBracket, typeParameters, rightBracket);
  }

  /**
   * Parse a unary expression. Return the unary expression that was parsed.
   *
   *     unaryExpression ::=
   *         prefixOperator unaryExpression
   *       | awaitExpression
   *       | postfixExpression
   *       | unaryOperator 'super'
   *       | '-' 'super'
   *       | incrementOperator assignableExpression
   */
  Expression parseUnaryExpression() {
    TokenType type = _currentToken.type;
    if (type == TokenType.MINUS ||
        type == TokenType.BANG ||
        type == TokenType.TILDE) {
      Token operator = getAndAdvance();
      if (_matchesKeyword(Keyword.SUPER)) {
        TokenType nextType = _peek().type;
        if (nextType == TokenType.OPEN_SQUARE_BRACKET ||
            nextType == TokenType.PERIOD) {
          //     "prefixOperator unaryExpression"
          // --> "prefixOperator postfixExpression"
          // --> "prefixOperator primary                    selector*"
          // --> "prefixOperator 'super' assignableSelector selector*"
          return astFactory.prefixExpression(operator, parseUnaryExpression());
        }
        return astFactory.prefixExpression(
            operator, astFactory.superExpression(getAndAdvance()));
      }
      return astFactory.prefixExpression(operator, parseUnaryExpression());
    } else if (_currentToken.type.isIncrementOperator) {
      Token operator = getAndAdvance();
      if (_matchesKeyword(Keyword.SUPER)) {
        TokenType nextType = _peek().type;
        if (nextType == TokenType.OPEN_SQUARE_BRACKET ||
            nextType == TokenType.PERIOD) {
          // --> "prefixOperator 'super' assignableSelector selector*"
          return astFactory.prefixExpression(operator, parseUnaryExpression());
        }
        //
        // Even though it is not valid to use an incrementing operator
        // ('++' or '--') before 'super', we can (and therefore must) interpret
        // "--super" as semantically equivalent to "-(-super)". Unfortunately,
        // we cannot do the same for "++super" because "+super" is also not
        // valid.
        //
        if (type == TokenType.MINUS_MINUS) {
          Token firstOperator = _createToken(operator, TokenType.MINUS);
          Token secondOperator =
              new Token(TokenType.MINUS, operator.offset + 1);
          secondOperator.setNext(_currentToken);
          firstOperator.setNext(secondOperator);
          operator.previous.setNext(firstOperator);
          return astFactory.prefixExpression(
              firstOperator,
              astFactory.prefixExpression(
                  secondOperator, astFactory.superExpression(getAndAdvance())));
        }
        // Invalid operator before 'super'
        _reportErrorForCurrentToken(
            ParserErrorCode.INVALID_OPERATOR_FOR_SUPER, [operator.lexeme]);
        return astFactory.prefixExpression(
            operator, astFactory.superExpression(getAndAdvance()));
      }
      return astFactory.prefixExpression(
          operator, _parseAssignableExpressionNotStartingWithSuper(false));
    } else if (type == TokenType.PLUS) {
      _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
      return createSyntheticIdentifier();
    } else if (_inAsync && _matchesKeyword(Keyword.AWAIT)) {
      return parseAwaitExpression();
    }
    return parsePostfixExpression();
  }

  /**
   * Parse a variable declaration. Return the variable declaration that was
   * parsed.
   *
   *     variableDeclaration ::=
   *         identifier ('=' expression)?
   */
  VariableDeclaration parseVariableDeclaration() {
    // TODO(paulberry): prior to the fix for bug 23204, we permitted
    // annotations before variable declarations (e.g. "String @deprecated s;").
    // Although such constructions are prohibited by the spec, we may want to
    // consider handling them anyway to allow for better parser recovery in the
    // event that the user erroneously tries to use them.  However, as a
    // counterargument, this would likely degrade parser recovery in the event
    // of a construct like "class C { int @deprecated foo() {} }" (i.e. the
    // user is in the middle of inserting "int bar;" prior to
    // "@deprecated foo() {}").
    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
    Token equals = null;
    Expression initializer = null;
    if (_matches(TokenType.EQ)) {
      equals = getAndAdvance();
      initializer = parseExpression2();
    }
    return astFactory.variableDeclaration(name, equals, initializer);
  }

  /**
   * Parse a variable declaration list. The [commentAndMetadata] is the metadata
   * to be associated with the variable declaration list. Return the variable
   * declaration list that was parsed.
   *
   *     variableDeclarationList ::=
   *         finalConstVarOrType variableDeclaration (',' variableDeclaration)*
   */
  VariableDeclarationList parseVariableDeclarationListAfterMetadata(
      CommentAndMetadata commentAndMetadata) {
    FinalConstVarOrType holder = parseFinalConstVarOrType(false);
    return parseVariableDeclarationListAfterType(
        commentAndMetadata, holder.keyword, holder.type);
  }

  /**
   * Parse a variable declaration list. The [commentAndMetadata] is the metadata
   * to be associated with the variable declaration list, or `null` if there is
   * no attempt at parsing the comment and metadata. The [keyword] is the token
   * representing the 'final', 'const' or 'var' keyword, or `null` if there is
   * no keyword. The [type] is the type of the variables in the list. Return the
   * variable declaration list that was parsed.
   *
   *     variableDeclarationList ::=
   *         finalConstVarOrType variableDeclaration (',' variableDeclaration)*
   */
  VariableDeclarationList parseVariableDeclarationListAfterType(
      CommentAndMetadata commentAndMetadata,
      Token keyword,
      TypeAnnotation type) {
    if (type != null &&
        keyword != null &&
        _tokenMatchesKeyword(keyword, Keyword.VAR)) {
      _reportErrorForToken(ParserErrorCode.VAR_AND_TYPE, keyword);
    }
    List<VariableDeclaration> variables = <VariableDeclaration>[
      parseVariableDeclaration()
    ];
    while (_optional(TokenType.COMMA)) {
      variables.add(parseVariableDeclaration());
    }
    return astFactory.variableDeclarationList(commentAndMetadata?.comment,
        commentAndMetadata?.metadata, keyword, type, variables);
  }

  /**
   * Parse a variable declaration statement. The [commentAndMetadata] is the
   * metadata to be associated with the variable declaration statement, or
   * `null` if there is no attempt at parsing the comment and metadata. Return
   * the variable declaration statement that was parsed.
   *
   *     variableDeclarationStatement ::=
   *         variableDeclarationList ';'
   */
  VariableDeclarationStatement parseVariableDeclarationStatementAfterMetadata(
      CommentAndMetadata commentAndMetadata) {
    //    Token startToken = currentToken;
    VariableDeclarationList variableList =
        parseVariableDeclarationListAfterMetadata(commentAndMetadata);
//        if (!matches(TokenType.SEMICOLON)) {
//          if (matches(startToken, Keyword.VAR) && isTypedIdentifier(startToken.getNext())) {
//            // TODO(brianwilkerson) This appears to be of the form "var type variable". We should do
//            // a better job of recovering in this case.
//          }
//        }
    Token semicolon = _expect(TokenType.SEMICOLON);
    return astFactory.variableDeclarationStatement(variableList, semicolon);
  }

  /**
   * Parse a while statement. Return the while statement that was parsed.
   *
   * This method assumes that the current token matches [Keyword.WHILE].
   *
   *     whileStatement ::=
   *         'while' '(' expression ')' statement
   */
  Statement parseWhileStatement() {
    bool wasInLoop = _inLoop;
    _inLoop = true;
    try {
      Token keyword = getAndAdvance();
      Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
      Expression condition = parseExpression2();
      Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
      Statement body = parseStatement2();
      return astFactory.whileStatement(
          keyword, leftParenthesis, condition, rightParenthesis, body);
    } finally {
      _inLoop = wasInLoop;
    }
  }

  /**
   * Parse a with clause. Return the with clause that was parsed.
   *
   * This method assumes that the current token matches `Keyword.WITH`.
   *
   *     withClause ::=
   *         'with' typeName (',' typeName)*
   */
  WithClause parseWithClause() {
    Token withKeyword = getAndAdvance();
    List<TypeName> types = <TypeName>[];
    do {
      TypeName typeName = parseTypeName(false);
      _mustNotBeNullable(typeName, ParserErrorCode.NULLABLE_TYPE_IN_WITH);
      types.add(typeName);
    } while (_optional(TokenType.COMMA));
    return astFactory.withClause(withKeyword, types);
  }

  /**
   * Parse a yield statement. Return the yield statement that was parsed.
   *
   * This method assumes that the current token matches [Keyword.YIELD].
   *
   *     yieldStatement ::=
   *         'yield' '*'? expression ';'
   */
  YieldStatement parseYieldStatement() {
    Token yieldToken = getAndAdvance();
    Token star = null;
    if (_matches(TokenType.STAR)) {
      star = getAndAdvance();
    }
    Expression expression = parseExpression2();
    Token semicolon = _expect(TokenType.SEMICOLON);
    return astFactory.yieldStatement(yieldToken, star, expression, semicolon);
  }

  /**
   * Parse a formal parameter list, starting at the [startToken], without
   * actually creating a formal parameter list or changing the current token.
   * Return the token following the parameter list that was parsed, or `null`
   * if the given token is not the first token in a valid parameter list.
   *
   * This method must be kept in sync with [parseFormalParameterList].
   */
  Token skipFormalParameterList(Token startToken) {
    if (!_tokenMatches(startToken, TokenType.OPEN_PAREN)) {
      return null;
    }
    return (startToken as BeginToken).endToken.next;
  }

  /**
   * Parse the portion of a generic function type after the return type,
   * starting at the [startToken], without actually creating a generic function
   * type or changing the current token. Return the token following the generic
   * function type that was parsed, or `null` if the given token is not the
   * first token in a valid generic function type.
   *
   * This method must be kept in sync with
   * [parseGenericFunctionTypeAfterReturnType].
   */
  Token skipGenericFunctionTypeAfterReturnType(Token startToken) {
    Token next = startToken.next; // Skip 'Function'
    if (_tokenMatches(next, TokenType.LT)) {
      next = skipTypeParameterList(next);
    }
    return skipFormalParameterList(next);
  }

  /**
   * Parse a prefixed identifier, starting at the [startToken], without actually
   * creating a prefixed identifier or changing the current token. Return the
   * token following the prefixed identifier that was parsed, or `null` if the
   * given token is not the first token in a valid prefixed identifier.
   *
   * This method must be kept in sync with [parsePrefixedIdentifier].
   *
   *     prefixedIdentifier ::=
   *         identifier ('.' identifier)?
   */
  Token skipPrefixedIdentifier(Token startToken) {
    Token token = skipSimpleIdentifier(startToken);
    if (token == null) {
      return null;
    } else if (!_tokenMatches(token, TokenType.PERIOD)) {
      return token;
    }
    token = token.next;
    Token nextToken = skipSimpleIdentifier(token);
    if (nextToken != null) {
      return nextToken;
    } else if (_tokenMatches(token, TokenType.CLOSE_PAREN) ||
        _tokenMatches(token, TokenType.COMMA)) {
      // If the `id.` is followed by something that cannot produce a valid
      // structure then assume this is a prefixed identifier but missing the
      // trailing identifier
      return token;
    }
    return null;
  }

  /**
   * Parse a return type, starting at the [startToken], without actually
   * creating a return type or changing the current token. Return the token
   * following the return type that was parsed, or `null` if the given token is
   * not the first token in a valid return type.
   *
   * This method must be kept in sync with [parseReturnType].
   *
   *     returnType ::=
   *         'void'
   *       | type
   */
  Token skipReturnType(Token startToken) {
    if (_tokenMatchesKeyword(startToken, Keyword.VOID)) {
      if (_atGenericFunctionTypeAfterReturnType(_peek())) {
        return skipTypeAnnotation(startToken);
      }
      return startToken.next;
    } else {
      return skipTypeAnnotation(startToken);
    }
  }

  /**
   * Parse a simple identifier, starting at the [startToken], without actually
   * creating a simple identifier or changing the current token. Return the
   * token following the simple identifier that was parsed, or `null` if the
   * given token is not the first token in a valid simple identifier.
   *
   * This method must be kept in sync with [parseSimpleIdentifier].
   *
   *     identifier ::=
   *         IDENTIFIER
   */
  Token skipSimpleIdentifier(Token startToken) {
    if (_tokenMatches(startToken, TokenType.IDENTIFIER) ||
        _tokenMatchesPseudoKeyword(startToken)) {
      return startToken.next;
    }
    return null;
  }

  /**
   * Parse a string literal, starting at the [startToken], without actually
   * creating a string literal or changing the current token. Return the token
   * following the string literal that was parsed, or `null` if the given token
   * is not the first token in a valid string literal.
   *
   * This method must be kept in sync with [parseStringLiteral].
   *
   *     stringLiteral ::=
   *         MULTI_LINE_STRING+
   *       | SINGLE_LINE_STRING+
   */
  Token skipStringLiteral(Token startToken) {
    Token token = startToken;
    while (token != null && _tokenMatches(token, TokenType.STRING)) {
      token = token.next;
      TokenType type = token.type;
      if (type == TokenType.STRING_INTERPOLATION_EXPRESSION ||
          type == TokenType.STRING_INTERPOLATION_IDENTIFIER) {
        token = _skipStringInterpolation(token);
      }
    }
    if (identical(token, startToken)) {
      return null;
    }
    return token;
  }

  /**
   * Parse a type annotation, starting at the [startToken], without actually
   * creating a type annotation or changing the current token. Return the token
   * following the type annotation that was parsed, or `null` if the given token
   * is not the first token in a valid type annotation.
   *
   * This method must be kept in sync with [parseTypeAnnotation].
   */
  Token skipTypeAnnotation(Token startToken) {
    Token next = null;
    if (_atGenericFunctionTypeAfterReturnType(startToken)) {
      next = skipGenericFunctionTypeAfterReturnType(startToken);
    } else if (_currentToken.keyword == Keyword.VOID &&
        _atGenericFunctionTypeAfterReturnType(_currentToken.next)) {
      next = next.next;
    } else {
      next = skipTypeName(startToken);
    }
    while (next != null && _atGenericFunctionTypeAfterReturnType(next)) {
      next = skipGenericFunctionTypeAfterReturnType(next);
    }
    return next;
  }

  /**
   * Parse a list of type arguments, starting at the [startToken], without
   * actually creating a type argument list or changing the current token.
   * Return the token following the type argument list that was parsed, or
   * `null` if the given token is not the first token in a valid type argument
   * list.
   *
   * This method must be kept in sync with [parseTypeArgumentList].
   *
   *     typeArguments ::=
   *         '<' typeList '>'
   *
   *     typeList ::=
   *         type (',' type)*
   */
  Token skipTypeArgumentList(Token startToken) {
    Token token = startToken;
    if (!_tokenMatches(token, TokenType.LT) &&
        !_injectGenericCommentTypeList()) {
      return null;
    }
    token = skipTypeName(token.next);
    if (token == null) {
      // If the start token '<' is followed by '>'
      // then assume this should be type argument list but is missing a type
      token = startToken.next;
      if (_tokenMatches(token, TokenType.GT)) {
        return token.next;
      }
      return null;
    }
    while (_tokenMatches(token, TokenType.COMMA)) {
      token = skipTypeName(token.next);
      if (token == null) {
        return null;
      }
    }
    if (token.type == TokenType.GT) {
      return token.next;
    } else if (token.type == TokenType.GT_GT) {
      Token second = new Token(TokenType.GT, token.offset + 1);
      second.setNextWithoutSettingPrevious(token.next);
      return second;
    }
    return null;
  }

  /**
   * Parse a type name, starting at the [startToken], without actually creating
   * a type name or changing the current token. Return the token following the
   * type name that was parsed, or `null` if the given token is not the first
   * token in a valid type name.
   *
   * This method must be kept in sync with [parseTypeName].
   *
   *     type ::=
   *         qualified typeArguments?
   */
  Token skipTypeName(Token startToken) {
    Token token = skipPrefixedIdentifier(startToken);
    if (token == null) {
      return null;
    }
    if (_tokenMatches(token, TokenType.LT)) {
      token = skipTypeArgumentList(token);
    }
    return token;
  }

  /**
   * Parse a type parameter list, starting at the [startToken], without actually
   * creating a type parameter list or changing the current token. Return the
   * token following the type parameter list that was parsed, or `null` if the
   * given token is not the first token in a valid type parameter list.
   *
   * This method must be kept in sync with [parseTypeParameterList].
   */
  Token skipTypeParameterList(Token startToken) {
    if (!_tokenMatches(startToken, TokenType.LT)) {
      return null;
    }
    int depth = 1;
    Token previous = startToken;
    Token next = startToken.next;
    while (next != previous) {
      if (_tokenMatches(next, TokenType.LT)) {
        depth++;
      } else if (_tokenMatches(next, TokenType.GT)) {
        depth--;
        if (depth == 0) {
          return next.next;
        }
      }
      previous = next;
      next = next.next;
    }
    return null;
  }

  /**
   * Advance to the next token in the token stream.
   */
  void _advance() {
    _currentToken = _currentToken.next;
  }

  /**
   * Append the character equivalent of the given [codePoint] to the given
   * [builder]. Use the [startIndex] and [endIndex] to report an error, and
   * don't append anything to the builder, if the code point is invalid. The
   * [escapeSequence] is the escape sequence that was parsed to produce the
   * code point (used for error reporting).
   */
  void _appendCodePoint(StringBuffer buffer, String source, int codePoint,
      int startIndex, int endIndex) {
    if (codePoint < 0 || codePoint > Character.MAX_CODE_POINT) {
      String escapeSequence = source.substring(startIndex, endIndex + 1);
      _reportErrorForCurrentToken(
          ParserErrorCode.INVALID_CODE_POINT, [escapeSequence]);
      return;
    }
    if (codePoint < Character.MAX_VALUE) {
      buffer.writeCharCode(codePoint);
    } else {
      buffer.write(Character.toChars(codePoint));
    }
  }

  /**
   * Return `true` if we are positioned at the keyword 'Function' in a generic
   * function type alias.
   */
  bool _atGenericFunctionTypeAfterReturnType(Token startToken) {
    if (_tokenMatchesKeyword(startToken, Keyword.FUNCTION)) {
      Token next = startToken.next;
      if (next != null &&
          (_tokenMatches(next, TokenType.OPEN_PAREN) ||
              _tokenMatches(next, TokenType.LT))) {
        return true;
      }
    }
    return false;
  }

  /**
   * Clone all token starting from the given [token] up to the end of the token
   * stream, and return the first token in the new token stream.
   */
  Token _cloneTokens(Token token) {
    if (token == null) {
      return null;
    }
    token = token is CommentToken ? token.parent : token;
    Token head = new Token(TokenType.EOF, -1);
    head.setNext(head);
    Token current = head;
    while (token.type != TokenType.EOF) {
      Token clone = token.copy();
      current.setNext(clone);
      current = clone;
      token = token.next;
    }
    Token tail = new Token(TokenType.EOF, 0);
    tail.setNext(tail);
    current.setNext(tail);
    return head.next;
  }

  /**
   * Convert the given [method] declaration into the nearest valid top-level
   * function declaration (that is, the function declaration that most closely
   * captures the components of the given method declaration).
   */
  FunctionDeclaration _convertToFunctionDeclaration(MethodDeclaration method) =>
      astFactory.functionDeclaration(
          method.documentationComment,
          method.metadata,
          method.externalKeyword,
          method.returnType,
          method.propertyKeyword,
          method.name,
          astFactory.functionExpression(
              method.typeParameters, method.parameters, method.body));

  /**
   * Return `true` if the current token could be the start of a compilation unit
   * member. This method is used for recovery purposes to decide when to stop
   * skipping tokens after finding an error while parsing a compilation unit
   * member.
   */
  bool _couldBeStartOfCompilationUnitMember() {
    Keyword keyword = _currentToken.keyword;
    Token next = _currentToken.next;
    TokenType nextType = next.type;
    if ((keyword == Keyword.IMPORT ||
            keyword == Keyword.EXPORT ||
            keyword == Keyword.LIBRARY ||
            keyword == Keyword.PART) &&
        nextType != TokenType.PERIOD &&
        nextType != TokenType.LT) {
      // This looks like the start of a directive
      return true;
    } else if (keyword == Keyword.CLASS) {
      // This looks like the start of a class definition
      return true;
    } else if (keyword == Keyword.TYPEDEF &&
        nextType != TokenType.PERIOD &&
        nextType != TokenType.LT) {
      // This looks like the start of a typedef
      return true;
    } else if (keyword == Keyword.VOID ||
        ((keyword == Keyword.GET || keyword == Keyword.SET) &&
            _tokenMatchesIdentifier(next)) ||
        (keyword == Keyword.OPERATOR && _isOperator(next))) {
      // This looks like the start of a function
      return true;
    } else if (_matchesIdentifier()) {
      if (nextType == TokenType.OPEN_PAREN) {
        // This looks like the start of a function
        return true;
      }
      Token token = skipReturnType(_currentToken);
      if (token == null) {
        return false;
      }
      // TODO(brianwilkerson) This looks wrong; should we be checking 'token'?
      if (keyword == Keyword.GET ||
          keyword == Keyword.SET ||
          (keyword == Keyword.OPERATOR && _isOperator(next)) ||
          _matchesIdentifier()) {
        return true;
      }
    }
    return false;
  }

  /**
   * Return a synthetic token representing the given [keyword].
   */
  Token _createSyntheticKeyword(Keyword keyword) =>
      _injectToken(new SyntheticKeywordToken(keyword, _currentToken.offset));

  /**
   * Return a synthetic token with the given [type].
   */
  Token _createSyntheticToken(TokenType type) =>
      _injectToken(new StringToken(type, "", _currentToken.offset));

  /**
   * Create and return a new token with the given [type]. The token will replace
   * the first portion of the given [token], so it will have the same offset and
   * will have any comments that might have preceeded the token.
   */
  Token _createToken(Token token, TokenType type, {bool isBegin: false}) {
    CommentToken comments = token.precedingComments;
    if (comments == null) {
      if (isBegin) {
        return new BeginToken(type, token.offset);
      }
      return new Token(type, token.offset);
    } else if (isBegin) {
      return new BeginTokenWithComment(type, token.offset, comments);
    }
    return new TokenWithComment(type, token.offset, comments);
  }

  /**
   * Check that the given [expression] is assignable and report an error if it
   * isn't.
   *
   *     assignableExpression ::=
   *         primary (arguments* assignableSelector)+
   *       | 'super' unconditionalAssignableSelector
   *       | identifier
   *
   *     unconditionalAssignableSelector ::=
   *         '[' expression ']'
   *       | '.' identifier
   *
   *     assignableSelector ::=
   *         unconditionalAssignableSelector
   *       | '?.' identifier
   */
  void _ensureAssignable(Expression expression) {
    if (expression != null && !expression.isAssignable) {
      _reportErrorForCurrentToken(
          ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE);
    }
  }

  /**
   * If the current token has the expected type, return it after advancing to
   * the next token. Otherwise report an error and return the current token
   * without advancing.
   *
   * Note that the method [_expectGt] should be used if the argument to this
   * method would be [TokenType.GT].
   *
   * The [type] is the type of token that is expected.
   */
  Token _expect(TokenType type) {
    if (_matches(type)) {
      return getAndAdvance();
    }
    // Remove uses of this method in favor of matches?
    // Pass in the error code to use to report the error?
    if (type == TokenType.SEMICOLON) {
      if (_tokenMatches(_currentToken.next, TokenType.SEMICOLON)) {
        _reportErrorForCurrentToken(
            ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken.lexeme]);
        _advance();
        return getAndAdvance();
      }
      _reportErrorForToken(ParserErrorCode.EXPECTED_TOKEN,
          _currentToken.previous, [type.lexeme]);
      return _createSyntheticToken(TokenType.SEMICOLON);
    }
    _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TOKEN, [type.lexeme]);
    return _createSyntheticToken(type);
  }

  /**
   * If the current token has the type [TokenType.GT], return it after advancing
   * to the next token. Otherwise report an error and create a synthetic token.
   */
  Token _expectGt() {
    if (_matchesGt()) {
      return getAndAdvance();
    }
    _reportErrorForCurrentToken(
        ParserErrorCode.EXPECTED_TOKEN, [TokenType.GT.lexeme]);
    return _createSyntheticToken(TokenType.GT);
  }

  /**
   * If the current token is a keyword matching the given [keyword], return it
   * after advancing to the next token. Otherwise report an error and return the
   * current token without advancing.
   */
  Token _expectKeyword(Keyword keyword) {
    if (_matchesKeyword(keyword)) {
      return getAndAdvance();
    }
    // Remove uses of this method in favor of matches?
    // Pass in the error code to use to report the error?
    _reportErrorForCurrentToken(
        ParserErrorCode.EXPECTED_TOKEN, [keyword.syntax]);
    return _currentToken;
  }

  /**
   * Search the given list of [ranges] for a range that contains the given
   * [index]. Return the range that was found, or `null` if none of the ranges
   * contain the index.
   */
  List<int> _findRange(List<List<int>> ranges, int index) {
    int rangeCount = ranges.length;
    for (int i = 0; i < rangeCount; i++) {
      List<int> range = ranges[i];
      if (range[0] <= index && index <= range[1]) {
        return range;
      } else if (index < range[0]) {
        return null;
      }
    }
    return null;
  }

  /**
   * Return a list of the ranges of characters in the given [comment] that
   * should be treated as code blocks.
   */
  List<List<int>> _getCodeBlockRanges(String comment) {
    List<List<int>> ranges = <List<int>>[];
    int length = comment.length;
    if (length < 3) {
      return ranges;
    }
    int index = 0;
    int firstChar = comment.codeUnitAt(0);
    if (firstChar == 0x2F) {
      int secondChar = comment.codeUnitAt(1);
      int thirdChar = comment.codeUnitAt(2);
      if ((secondChar == 0x2A && thirdChar == 0x2A) ||
          (secondChar == 0x2F && thirdChar == 0x2F)) {
        index = 3;
      }
    }
    if (StringUtilities.startsWith4(comment, index, 0x20, 0x20, 0x20, 0x20)) {
      int end = index + 4;
      while (end < length &&
          comment.codeUnitAt(end) != 0xD &&
          comment.codeUnitAt(end) != 0xA) {
        end = end + 1;
      }
      ranges.add(<int>[index, end]);
      index = end;
    }
    while (index < length) {
      int currentChar = comment.codeUnitAt(index);
      if (currentChar == 0xD || currentChar == 0xA) {
        index = index + 1;
        while (index < length &&
            Character.isWhitespace(comment.codeUnitAt(index))) {
          index = index + 1;
        }
        if (StringUtilities.startsWith6(
            comment, index, 0x2A, 0x20, 0x20, 0x20, 0x20, 0x20)) {
          int end = index + 6;
          while (end < length &&
              comment.codeUnitAt(end) != 0xD &&
              comment.codeUnitAt(end) != 0xA) {
            end = end + 1;
          }
          ranges.add(<int>[index, end]);
          index = end;
        }
      } else if (index + 1 < length &&
          currentChar == 0x5B &&
          comment.codeUnitAt(index + 1) == 0x3A) {
        int end = StringUtilities.indexOf2(comment, index + 2, 0x3A, 0x5D);
        if (end < 0) {
          end = length;
        }
        ranges.add(<int>[index, end]);
        index = end + 1;
      } else {
        index = index + 1;
      }
    }
    return ranges;
  }

  /**
   * Return the end token associated with the given [beginToken], or `null` if
   * either the given token is not a begin token or it does not have an end
   * token associated with it.
   */
  Token _getEndToken(Token beginToken) {
    if (beginToken is BeginToken) {
      return beginToken.endToken;
    }
    return null;
  }

  bool _injectGenericComment(TokenType type, int prefixLen) {
    if (parseGenericMethodComments) {
      CommentToken t = _currentToken.precedingComments;
      for (; t != null; t = t.next) {
        if (t.type == type) {
          String comment = t.lexeme.substring(prefixLen, t.lexeme.length - 2);
          Token list = _scanGenericMethodComment(comment, t.offset + prefixLen);
          if (list != null) {
            // Remove the token from the comment stream.
            t.remove();
            // Insert the tokens into the stream.
            _injectTokenList(list);
            return true;
          }
        }
      }
    }
    return false;
  }

  /**
   * Matches a generic comment type substitution and injects it into the token
   * stream. Returns true if a match was injected, otherwise false.
   *
   * These comments are of the form `/*=T*/`, in other words, a [TypeName]
   * inside a slash-star comment, preceded by equals sign.
   */
  bool _injectGenericCommentTypeAssign() {
    return _injectGenericComment(TokenType.GENERIC_METHOD_TYPE_ASSIGN, 3);
  }

  /**
   * Matches a generic comment type parameters and injects them into the token
   * stream. Returns true if a match was injected, otherwise false.
   *
   * These comments are of the form `/*<K, V>*/`, in other words, a
   * [TypeParameterList] or [TypeArgumentList] inside a slash-star comment.
   */
  bool _injectGenericCommentTypeList() {
    return _injectGenericComment(TokenType.GENERIC_METHOD_TYPE_LIST, 2);
  }

  /**
   * Inject the given [token] into the token stream immediately before the
   * current token.
   */
  Token _injectToken(Token token) {
    Token previous = _currentToken.previous;
    token.setNext(_currentToken);
    previous.setNext(token);
    return token;
  }

  void _injectTokenList(Token firstToken) {
    // Scanner creates a cyclic EOF token.
    Token lastToken = firstToken;
    while (lastToken.next.type != TokenType.EOF) {
      lastToken = lastToken.next;
    }
    // Inject these new tokens into the stream.
    Token previous = _currentToken.previous;
    lastToken.setNext(_currentToken);
    previous.setNext(firstToken);
    _currentToken = firstToken;
  }

  /**
   * Return `true` if the current token could be the question mark in a
   * condition expression. The current token is assumed to be a question mark.
   */
  bool _isConditionalOperator() {
    void parseOperation(Parser parser) {
      parser.parseExpressionWithoutCascade();
    }

    Token token = _skip(_currentToken.next, parseOperation);
    if (token == null || !_tokenMatches(token, TokenType.COLON)) {
      return false;
    }
    token = _skip(token.next, parseOperation);
    return token != null;
  }

  /**
   * Return `true` if the given [character] is a valid hexadecimal digit.
   */
  bool _isHexDigit(int character) =>
      (0x30 <= character && character <= 0x39) ||
      (0x41 <= character && character <= 0x46) ||
      (0x61 <= character && character <= 0x66);

  bool _isLikelyArgumentList() {
    // Try to reduce the amount of lookahead required here before enabling
    // generic methods.
    if (_matches(TokenType.OPEN_PAREN)) {
      return true;
    }
    Token token = skipTypeArgumentList(_currentToken);
    return token != null && _tokenMatches(token, TokenType.OPEN_PAREN);
  }

  /**
   * Given that we have just found bracketed text within the given [comment],
   * look to see whether that text is (a) followed by a parenthesized link
   * address, (b) followed by a colon, or (c) followed by optional whitespace
   * and another square bracket. The [rightIndex] is the index of the right
   * bracket. Return `true` if the bracketed text is followed by a link address.
   *
   * This method uses the syntax described by the
   * <a href="http://daringfireball.net/projects/markdown/syntax">markdown</a>
   * project.
   */
  bool _isLinkText(String comment, int rightIndex) {
    int length = comment.length;
    int index = rightIndex + 1;
    if (index >= length) {
      return false;
    }
    int nextChar = comment.codeUnitAt(index);
    if (nextChar == 0x28 || nextChar == 0x3A) {
      return true;
    }
    while (Character.isWhitespace(nextChar)) {
      index = index + 1;
      if (index >= length) {
        return false;
      }
      nextChar = comment.codeUnitAt(index);
    }
    return nextChar == 0x5B;
  }

  /**
   * Return `true` if the given [startToken] appears to be the beginning of an
   * operator declaration.
   */
  bool _isOperator(Token startToken) {
    // Accept any operator here, even if it is not user definable.
    if (!startToken.isOperator) {
      return false;
    }
    // Token "=" means that it is actually a field initializer.
    if (startToken.type == TokenType.EQ) {
      return false;
    }
    // Consume all operator tokens.
    Token token = startToken.next;
    while (token.isOperator) {
      token = token.next;
    }
    // Formal parameter list is expect now.
    return _tokenMatches(token, TokenType.OPEN_PAREN);
  }

  bool _isPeekGenericTypeParametersAndOpenParen() {
    Token token = _skipTypeParameterList(_peek());
    return token != null && _tokenMatches(token, TokenType.OPEN_PAREN);
  }

  /**
   * Return `true` if the [startToken] appears to be the first token of a type
   * name that is followed by a variable or field formal parameter.
   */
  bool _isTypedIdentifier(Token startToken) {
    Token token = skipReturnType(startToken);
    if (token == null) {
      return false;
    } else if (_tokenMatchesIdentifier(token)) {
      return true;
    } else if (_tokenMatchesKeyword(token, Keyword.THIS) &&
        _tokenMatches(token.next, TokenType.PERIOD) &&
        _tokenMatchesIdentifier(token.next.next)) {
      return true;
    } else if (_tokenMatchesKeyword(startToken, Keyword.VOID)) {
      // The keyword 'void' isn't a valid identifier, so it should be assumed to
      // be a type name.
      return true;
    } else if (startToken.next != token &&
        !_tokenMatches(token, TokenType.OPEN_PAREN)) {
      // The type is more than a simple identifier, so it should be assumed to
      // be a type name.
      return true;
    }
    return false;
  }

  /**
   * Increments the error reporting lock level. If level is more than `0`, then
   * [reportError] wont report any error.
   */
  void _lockErrorListener() {
    _errorListenerLock++;
  }

  /**
   * Return `true` if the current token has the given [type]. Note that the
   * method [_matchesGt] should be used if the argument to this method would be
   * [TokenType.GT].
   */
  bool _matches(TokenType type) => _currentToken.type == type;

  /**
   * Return `true` if the current token has a type of [TokenType.GT]. Note that
   * this method, unlike other variants, will modify the token stream if
   * possible to match desired type. In particular, if the next token is either
   * a '>>' or '>>>', the token stream will be re-written and `true` will be
   * returned.
   */
  bool _matchesGt() {
    TokenType currentType = _currentToken.type;
    if (currentType == TokenType.GT) {
      return true;
    } else if (currentType == TokenType.GT_GT) {
      Token first = _createToken(_currentToken, TokenType.GT);
      Token second = new Token(TokenType.GT, _currentToken.offset + 1);
      second.setNext(_currentToken.next);
      first.setNext(second);
      _currentToken.previous.setNext(first);
      _currentToken = first;
      return true;
    } else if (currentType == TokenType.GT_EQ) {
      Token first = _createToken(_currentToken, TokenType.GT);
      Token second = new Token(TokenType.EQ, _currentToken.offset + 1);
      second.setNext(_currentToken.next);
      first.setNext(second);
      _currentToken.previous.setNext(first);
      _currentToken = first;
      return true;
    } else if (currentType == TokenType.GT_GT_EQ) {
      int offset = _currentToken.offset;
      Token first = _createToken(_currentToken, TokenType.GT);
      Token second = new Token(TokenType.GT, offset + 1);
      Token third = new Token(TokenType.EQ, offset + 2);
      third.setNext(_currentToken.next);
      second.setNext(third);
      first.setNext(second);
      _currentToken.previous.setNext(first);
      _currentToken = first;
      return true;
    }
    return false;
  }

  /**
   * Return `true` if the current token is a valid identifier. Valid identifiers
   * include built-in identifiers (pseudo-keywords).
   */
  bool _matchesIdentifier() => _tokenMatchesIdentifier(_currentToken);

  /**
   * Return `true` if the current token matches the given [keyword].
   */
  bool _matchesKeyword(Keyword keyword) =>
      _tokenMatchesKeyword(_currentToken, keyword);

  /**
   * Report an error with the given [errorCode] if the given [typeName] has been
   * marked as nullable.
   */
  void _mustNotBeNullable(TypeName typeName, ParserErrorCode errorCode) {
    if (typeName.question != null) {
      _reportErrorForToken(errorCode, typeName.question);
    }
  }

  /**
   * If the current token has the given [type], then advance to the next token
   * and return `true`. Otherwise, return `false` without advancing. This method
   * should not be invoked with an argument value of [TokenType.GT].
   */
  bool _optional(TokenType type) {
    if (_currentToken.type == type) {
      _advance();
      return true;
    }
    return false;
  }

  /**
   * Parse an argument list when we need to check for an open paren and recover
   * when there isn't one. Return the argument list that was parsed.
   */
  ArgumentList _parseArgumentListChecked() {
    if (_matches(TokenType.OPEN_PAREN)) {
      return parseArgumentList();
    }
    _reportErrorForCurrentToken(
        ParserErrorCode.EXPECTED_TOKEN, [TokenType.OPEN_PAREN.lexeme]);
    // Recovery: Look to see whether there is a close paren that isn't matched
    // to an open paren and if so parse the list of arguments as normal.
    return astFactory.argumentList(_createSyntheticToken(TokenType.OPEN_PAREN),
        null, _createSyntheticToken(TokenType.CLOSE_PAREN));
  }

  /**
   * Parse an assert within a constructor's initializer list. Return the assert.
   *
   * This method assumes that the current token matches `Keyword.ASSERT`.
   *
   *     assertInitializer ::=
   *         'assert' '(' expression [',' expression] ')'
   */
  AssertInitializer _parseAssertInitializer() {
    Token keyword = getAndAdvance();
    Token leftParen = _expect(TokenType.OPEN_PAREN);
    Expression expression = parseExpression2();
    Token comma;
    Expression message;
    if (_matches(TokenType.COMMA)) {
      comma = getAndAdvance();
      message = parseExpression2();
    }
    Token rightParen = _expect(TokenType.CLOSE_PAREN);
    return astFactory.assertInitializer(
        keyword, leftParen, expression, comma, message, rightParen);
  }

  /**
   * Parse an assignable expression given that the current token is not 'super'.
   * The [primaryAllowed] is `true` if the expression is allowed to be a primary
   * without any assignable selector. Return the assignable expression that was
   * parsed.
   */
  Expression _parseAssignableExpressionNotStartingWithSuper(
      bool primaryAllowed) {
    //
    // A primary expression can start with an identifier. We resolve the
    // ambiguity by determining whether the primary consists of anything other
    // than an identifier and/or is followed by an assignableSelector.
    //
    Expression expression = parsePrimaryExpression();
    bool isOptional = primaryAllowed || expression is SimpleIdentifier;
    while (true) {
      while (_isLikelyArgumentList()) {
        TypeArgumentList typeArguments = _parseOptionalTypeArguments();
        ArgumentList argumentList = parseArgumentList();
        Expression currentExpression = expression;
        if (currentExpression is SimpleIdentifier) {
          expression = astFactory.methodInvocation(
              null, null, currentExpression, typeArguments, argumentList);
        } else if (currentExpression is PrefixedIdentifier) {
          expression = astFactory.methodInvocation(
              currentExpression.prefix,
              currentExpression.period,
              currentExpression.identifier,
              typeArguments,
              argumentList);
        } else if (currentExpression is PropertyAccess) {
          expression = astFactory.methodInvocation(
              currentExpression.target,
              currentExpression.operator,
              currentExpression.propertyName,
              typeArguments,
              argumentList);
        } else {
          expression = astFactory.functionExpressionInvocation(
              expression, typeArguments, argumentList);
        }
        if (!primaryAllowed) {
          isOptional = false;
        }
      }
      Expression selectorExpression = parseAssignableSelector(
          expression, isOptional || (expression is PrefixedIdentifier));
      if (identical(selectorExpression, expression)) {
        return expression;
      }
      expression = selectorExpression;
      isOptional = true;
    }
  }

  /**
   * Parse a block when we need to check for an open curly brace and recover
   * when there isn't one. Return the block that was parsed.
   *
   *     block ::=
   *         '{' statements '}'
   */
  Block _parseBlockChecked() {
    if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
      return parseBlock();
    }
    // TODO(brianwilkerson) Improve the error message.
    _reportErrorForCurrentToken(
        ParserErrorCode.EXPECTED_TOKEN, [TokenType.OPEN_CURLY_BRACKET.lexeme]);
    // Recovery: Check for an unmatched closing curly bracket and parse
    // statements until it is reached.
    return astFactory.block(_createSyntheticToken(TokenType.OPEN_CURLY_BRACKET),
        null, _createSyntheticToken(TokenType.CLOSE_CURLY_BRACKET));
  }

  /**
   * Parse a list of class members. The [className] is the name of the class
   * whose members are being parsed. The [closingBracket] is the closing bracket
   * for the class, or `null` if the closing bracket is missing. Return the list
   * of class members that were parsed.
   *
   *     classMembers ::=
   *         (metadata memberDefinition)*
   */
  List<ClassMember> _parseClassMembers(String className, Token closingBracket) {
    List<ClassMember> members = <ClassMember>[];
    Token memberStart = _currentToken;
    TokenType type = _currentToken.type;
    Keyword keyword = _currentToken.keyword;
    while (type != TokenType.EOF &&
        type != TokenType.CLOSE_CURLY_BRACKET &&
        (closingBracket != null ||
            (keyword != Keyword.CLASS && keyword != Keyword.TYPEDEF))) {
      if (type == TokenType.SEMICOLON) {
        _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
            [_currentToken.lexeme]);
        _advance();
      } else {
        ClassMember member = parseClassMember(className);
        if (member != null) {
          members.add(member);
        }
      }
      if (identical(_currentToken, memberStart)) {
        _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
            [_currentToken.lexeme]);
        _advance();
      }
      memberStart = _currentToken;
      type = _currentToken.type;
      keyword = _currentToken.keyword;
    }
    return members;
  }

  /**
   * Parse a class type alias. The [commentAndMetadata] is the metadata to be
   * associated with the member. The [abstractKeyword] is the token representing
   * the 'abstract' keyword. The [classKeyword] is the token representing the
   * 'class' keyword. The [className] is the name of the alias, and the
   * [typeParameters] are the type parameters following the name. Return the
   * class type alias that was parsed.
   *
   *     classTypeAlias ::=
   *         identifier typeParameters? '=' 'abstract'? mixinApplication
   *
   *     mixinApplication ::=
   *         type withClause implementsClause? ';'
   */
  ClassTypeAlias _parseClassTypeAliasAfterName(
      CommentAndMetadata commentAndMetadata,
      Token abstractKeyword,
      Token classKeyword,
      SimpleIdentifier className,
      TypeParameterList typeParameters) {
    Token equals = _expect(TokenType.EQ);
    TypeName superclass = parseTypeName(false);
    WithClause withClause = null;
    if (_matchesKeyword(Keyword.WITH)) {
      withClause = parseWithClause();
    } else {
      _reportErrorForCurrentToken(
          ParserErrorCode.EXPECTED_TOKEN, [Keyword.WITH.syntax]);
    }
    ImplementsClause implementsClause = null;
    if (_matchesKeyword(Keyword.IMPLEMENTS)) {
      implementsClause = parseImplementsClause();
    }
    Token semicolon;
    if (_matches(TokenType.SEMICOLON)) {
      semicolon = getAndAdvance();
    } else {
      if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
        _reportErrorForCurrentToken(
            ParserErrorCode.EXPECTED_TOKEN, [TokenType.SEMICOLON.lexeme]);
        Token leftBracket = getAndAdvance();
        _parseClassMembers(className.name, _getEndToken(leftBracket));
        _expect(TokenType.CLOSE_CURLY_BRACKET);
      } else {
        _reportErrorForToken(ParserErrorCode.EXPECTED_TOKEN,
            _currentToken.previous, [TokenType.SEMICOLON.lexeme]);
      }
      semicolon = _createSyntheticToken(TokenType.SEMICOLON);
    }
    return astFactory.classTypeAlias(
        commentAndMetadata.comment,
        commentAndMetadata.metadata,
        classKeyword,
        className,
        typeParameters,
        equals,
        abstractKeyword,
        superclass,
        withClause,
        implementsClause,
        semicolon);
  }

  /**
   * Parse a list of configurations. Return the configurations that were parsed,
   * or `null` if there are no configurations.
   */
  List<Configuration> _parseConfigurations() {
    List<Configuration> configurations = null;
    while (_matchesKeyword(Keyword.IF)) {
      configurations ??= <Configuration>[];
      configurations.add(parseConfiguration());
    }
    return configurations;
  }

  ConstructorDeclaration _parseConstructor(
      CommentAndMetadata commentAndMetadata,
      Token externalKeyword,
      Token constKeyword,
      Token factoryKeyword,
      SimpleIdentifier returnType,
      Token period,
      SimpleIdentifier name,
      FormalParameterList parameters) {
    bool bodyAllowed = externalKeyword == null;
    Token separator = null;
    List<ConstructorInitializer> initializers = null;
    if (_matches(TokenType.COLON)) {
      separator = getAndAdvance();
      initializers = <ConstructorInitializer>[];
      do {
        Keyword keyword = _currentToken.keyword;
        if (keyword == Keyword.THIS) {
          TokenType nextType = _peek().type;
          if (nextType == TokenType.OPEN_PAREN) {
            bodyAllowed = false;
            initializers.add(parseRedirectingConstructorInvocation(false));
          } else if (nextType == TokenType.PERIOD &&
              _tokenMatches(_peekAt(3), TokenType.OPEN_PAREN)) {
            bodyAllowed = false;
            initializers.add(parseRedirectingConstructorInvocation(true));
          } else {
            initializers.add(parseConstructorFieldInitializer(true));
          }
        } else if (keyword == Keyword.SUPER) {
          initializers.add(parseSuperConstructorInvocation());
        } else if (_matches(TokenType.OPEN_CURLY_BRACKET) ||
            _matches(TokenType.FUNCTION)) {
          _reportErrorForCurrentToken(ParserErrorCode.MISSING_INITIALIZER);
        } else if (_enableAssertInitializer &&
            _matchesKeyword(Keyword.ASSERT)) {
          initializers.add(_parseAssertInitializer());
        } else {
          initializers.add(parseConstructorFieldInitializer(false));
        }
      } while (_optional(TokenType.COMMA));
      if (factoryKeyword != null) {
        _reportErrorForToken(
            ParserErrorCode.FACTORY_WITH_INITIALIZERS, factoryKeyword);
      }
    }
    ConstructorName redirectedConstructor = null;
    FunctionBody body;
    if (_matches(TokenType.EQ)) {
      separator = getAndAdvance();
      redirectedConstructor = parseConstructorName();
      body = astFactory.emptyFunctionBody(_expect(TokenType.SEMICOLON));
      if (factoryKeyword == null) {
        _reportErrorForNode(
            ParserErrorCode.REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR,
            redirectedConstructor);
      }
    } else {
      body =
          parseFunctionBody(true, ParserErrorCode.MISSING_FUNCTION_BODY, false);
      if (constKeyword != null &&
          factoryKeyword != null &&
          externalKeyword == null &&
          body is! NativeFunctionBody) {
        _reportErrorForToken(ParserErrorCode.CONST_FACTORY, factoryKeyword);
      } else if (body is EmptyFunctionBody) {
        if (factoryKeyword != null &&
            externalKeyword == null &&
            _parseFunctionBodies) {
          _reportErrorForToken(
              ParserErrorCode.FACTORY_WITHOUT_BODY, factoryKeyword);
        }
      } else {
        if (constKeyword != null && body is! NativeFunctionBody) {
          _reportErrorForNode(
              ParserErrorCode.CONST_CONSTRUCTOR_WITH_BODY, body);
        } else if (externalKeyword != null) {
          _reportErrorForNode(
              ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_BODY, body);
        } else if (!bodyAllowed) {
          _reportErrorForNode(
              ParserErrorCode.REDIRECTING_CONSTRUCTOR_WITH_BODY, body);
        }
      }
    }
    return astFactory.constructorDeclaration(
        commentAndMetadata.comment,
        commentAndMetadata.metadata,
        externalKeyword,
        constKeyword,
        factoryKeyword,
        returnType,
        period,
        name,
        parameters,
        separator,
        initializers,
        redirectedConstructor,
        body);
  }

  /**
   * Parse an enum constant declaration. Return the enum constant declaration
   * that was parsed.
   *
   * Specified:
   *
   *     enumConstant ::=
   *         id
   *
   * Actual:
   *
   *     enumConstant ::=
   *         metadata id
   */
  EnumConstantDeclaration _parseEnumConstantDeclaration() {
    CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
    SimpleIdentifier name;
    if (_matchesIdentifier()) {
      name = _parseSimpleIdentifierUnchecked(isDeclaration: true);
    } else {
      name = createSyntheticIdentifier();
    }
    if (commentAndMetadata.hasMetadata) {
      _reportErrorForNode(ParserErrorCode.ANNOTATION_ON_ENUM_CONSTANT,
          commentAndMetadata.metadata[0]);
    }
    return astFactory.enumConstantDeclaration(
        commentAndMetadata.comment, commentAndMetadata.metadata, name);
  }

  /**
   * Parse a list of formal parameters given that the list starts with the given
   * [leftParenthesis]. Return the formal parameters that were parsed.
   */
  FormalParameterList _parseFormalParameterListAfterParen(Token leftParenthesis,
      {bool inFunctionType: false}) {
    if (_matches(TokenType.CLOSE_PAREN)) {
      return astFactory.formalParameterList(
          leftParenthesis, null, null, null, getAndAdvance());
    }
    //
    // Even though it is invalid to have default parameters outside of brackets,
    // required parameters inside of brackets, or multiple groups of default and
    // named parameters, we allow all of these cases so that we can recover
    // better.
    //
    List<FormalParameter> parameters = <FormalParameter>[];
    Token leftSquareBracket = null;
    Token rightSquareBracket = null;
    Token leftCurlyBracket = null;
    Token rightCurlyBracket = null;
    ParameterKind kind = ParameterKind.REQUIRED;
    bool firstParameter = true;
    bool reportedMultiplePositionalGroups = false;
    bool reportedMultipleNamedGroups = false;
    bool reportedMixedGroups = false;
    bool wasOptionalParameter = false;
    Token initialToken = null;
    do {
      if (firstParameter) {
        firstParameter = false;
      } else if (!_optional(TokenType.COMMA)) {
        // TODO(brianwilkerson) The token is wrong, we need to recover from this
        // case.
        if (_getEndToken(leftParenthesis) != null) {
          _reportErrorForCurrentToken(
              ParserErrorCode.EXPECTED_TOKEN, [TokenType.COMMA.lexeme]);
        } else {
          _reportErrorForToken(ParserErrorCode.MISSING_CLOSING_PARENTHESIS,
              _currentToken.previous);
          break;
        }
      }
      initialToken = _currentToken;
      //
      // Handle the beginning of parameter groups.
      //
      TokenType type = _currentToken.type;
      if (type == TokenType.OPEN_SQUARE_BRACKET) {
        wasOptionalParameter = true;
        if (leftSquareBracket != null && !reportedMultiplePositionalGroups) {
          _reportErrorForCurrentToken(
              ParserErrorCode.MULTIPLE_POSITIONAL_PARAMETER_GROUPS);
          reportedMultiplePositionalGroups = true;
        }
        if (leftCurlyBracket != null && !reportedMixedGroups) {
          _reportErrorForCurrentToken(ParserErrorCode.MIXED_PARAMETER_GROUPS);
          reportedMixedGroups = true;
        }
        leftSquareBracket = getAndAdvance();
        kind = ParameterKind.POSITIONAL;
      } else if (type == TokenType.OPEN_CURLY_BRACKET) {
        wasOptionalParameter = true;
        if (leftCurlyBracket != null && !reportedMultipleNamedGroups) {
          _reportErrorForCurrentToken(
              ParserErrorCode.MULTIPLE_NAMED_PARAMETER_GROUPS);
          reportedMultipleNamedGroups = true;
        }
        if (leftSquareBracket != null && !reportedMixedGroups) {
          _reportErrorForCurrentToken(ParserErrorCode.MIXED_PARAMETER_GROUPS);
          reportedMixedGroups = true;
        }
        leftCurlyBracket = getAndAdvance();
        kind = ParameterKind.NAMED;
      }
      //
      // Parse and record the parameter.
      //
      FormalParameter parameter =
          parseFormalParameter(kind, inFunctionType: inFunctionType);
      parameters.add(parameter);
      if (kind == ParameterKind.REQUIRED && wasOptionalParameter) {
        _reportErrorForNode(
            ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS, parameter);
      }
      //
      // Handle the end of parameter groups.
      //
      // TODO(brianwilkerson) Improve the detection and reporting of missing and
      // mismatched delimiters.
      type = _currentToken.type;

      // Advance past trailing commas as appropriate.
      if (type == TokenType.COMMA) {
        // Only parse commas trailing normal (non-positional/named) params.
        if (rightSquareBracket == null && rightCurlyBracket == null) {
          Token next = _peek();
          if (next.type == TokenType.CLOSE_PAREN ||
              next.type == TokenType.CLOSE_CURLY_BRACKET ||
              next.type == TokenType.CLOSE_SQUARE_BRACKET) {
            _advance();
            type = _currentToken.type;
          }
        }
      }

      if (type == TokenType.CLOSE_SQUARE_BRACKET) {
        rightSquareBracket = getAndAdvance();
        if (leftSquareBracket == null) {
          if (leftCurlyBracket != null) {
            _reportErrorForCurrentToken(
                ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP,
                ['}', ']']);
            rightCurlyBracket = rightSquareBracket;
            rightSquareBracket = null;
          } else {
            _reportErrorForCurrentToken(
                ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP,
                ["["]);
          }
        }
        kind = ParameterKind.REQUIRED;
      } else if (type == TokenType.CLOSE_CURLY_BRACKET) {
        rightCurlyBracket = getAndAdvance();
        if (leftCurlyBracket == null) {
          if (leftSquareBracket != null) {
            _reportErrorForCurrentToken(
                ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP,
                [']', '}']);
            rightSquareBracket = rightCurlyBracket;
            rightCurlyBracket = null;
          } else {
            _reportErrorForCurrentToken(
                ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP,
                ["{"]);
          }
        }
        kind = ParameterKind.REQUIRED;
      }
    } while (!_matches(TokenType.CLOSE_PAREN) &&
        !identical(initialToken, _currentToken));
    Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
    //
    // Check that the groups were closed correctly.
    //
    if (leftSquareBracket != null && rightSquareBracket == null) {
      _reportErrorForCurrentToken(
          ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP, ["]"]);
    }
    if (leftCurlyBracket != null && rightCurlyBracket == null) {
      _reportErrorForCurrentToken(
          ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP, ["}"]);
    }
    //
    // Build the parameter list.
    //
    leftSquareBracket ??= leftCurlyBracket;
    rightSquareBracket ??= rightCurlyBracket;
    return astFactory.formalParameterList(leftParenthesis, parameters,
        leftSquareBracket, rightSquareBracket, rightParenthesis);
  }

  /**
   * Parse a list of formal parameters. Return the formal parameters that were
   * parsed.
   *
   * This method assumes that the current token matches `TokenType.OPEN_PAREN`.
   */
  FormalParameterList _parseFormalParameterListUnchecked(
      {bool inFunctionType: false}) {
    return _parseFormalParameterListAfterParen(getAndAdvance(),
        inFunctionType: inFunctionType);
  }

  /**
   * Parse a function declaration statement. The [commentAndMetadata] is the
   * documentation comment and metadata to be associated with the declaration.
   * The [returnType] is the return type, or `null` if there is no return type.
   * Return the function declaration statement that was parsed.
   *
   *     functionDeclarationStatement ::=
   *         functionSignature functionBody
   */
  Statement _parseFunctionDeclarationStatementAfterReturnType(
      CommentAndMetadata commentAndMetadata, TypeAnnotation returnType) {
    FunctionDeclaration declaration =
        parseFunctionDeclaration(commentAndMetadata, null, returnType);
    Token propertyKeyword = declaration.propertyKeyword;
    if (propertyKeyword != null) {
      if (propertyKeyword.keyword == Keyword.GET) {
        _reportErrorForToken(
            ParserErrorCode.GETTER_IN_FUNCTION, propertyKeyword);
      } else {
        _reportErrorForToken(
            ParserErrorCode.SETTER_IN_FUNCTION, propertyKeyword);
      }
    }
    return astFactory.functionDeclarationStatement(declaration);
  }

  /**
   * Parse a function type alias. The [commentAndMetadata] is the metadata to be
   * associated with the member. The [keyword] is the token representing the
   * 'typedef' keyword. Return the function type alias that was parsed.
   *
   *     functionTypeAlias ::=
   *         functionPrefix typeParameterList? formalParameterList ';'
   *
   *     functionPrefix ::=
   *         returnType? name
   */
  FunctionTypeAlias _parseFunctionTypeAlias(
      CommentAndMetadata commentAndMetadata, Token keyword) {
    TypeAnnotation returnType = null;
    if (hasReturnTypeInTypeAlias) {
      returnType = parseReturnType(false);
    }
    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
    TypeParameterList typeParameters = null;
    if (_matches(TokenType.LT)) {
      typeParameters = parseTypeParameterList();
    }
    TokenType type = _currentToken.type;
    if (type == TokenType.SEMICOLON || type == TokenType.EOF) {
      _reportErrorForCurrentToken(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS);
      FormalParameterList parameters = astFactory.formalParameterList(
          _createSyntheticToken(TokenType.OPEN_PAREN),
          null,
          null,
          null,
          _createSyntheticToken(TokenType.CLOSE_PAREN));
      Token semicolon = _expect(TokenType.SEMICOLON);
      return astFactory.functionTypeAlias(
          commentAndMetadata.comment,
          commentAndMetadata.metadata,
          keyword,
          returnType,
          name,
          typeParameters,
          parameters,
          semicolon);
    } else if (type == TokenType.OPEN_PAREN) {
      FormalParameterList parameters = _parseFormalParameterListUnchecked();
      _validateFormalParameterList(parameters);
      Token semicolon = _expect(TokenType.SEMICOLON);
      return astFactory.functionTypeAlias(
          commentAndMetadata.comment,
          commentAndMetadata.metadata,
          keyword,
          returnType,
          name,
          typeParameters,
          parameters,
          semicolon);
    } else {
      _reportErrorForCurrentToken(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS);
      // Recovery: At the very least we should skip to the start of the next
      // valid compilation unit member, allowing for the possibility of finding
      // the typedef parameters before that point.
      return astFactory.functionTypeAlias(
          commentAndMetadata.comment,
          commentAndMetadata.metadata,
          keyword,
          returnType,
          name,
          typeParameters,
          astFactory.formalParameterList(
              _createSyntheticToken(TokenType.OPEN_PAREN),
              null,
              null,
              null,
              _createSyntheticToken(TokenType.CLOSE_PAREN)),
          _createSyntheticToken(TokenType.SEMICOLON));
    }
  }

  /**
   * Parses generic type parameters from a comment.
   *
   * Normally this is handled by [_parseGenericMethodTypeParameters], but if the
   * code already handles the normal generic type parameters, the comment
   * matcher can be called directly. For example, we may have already tried
   * matching `<` (less than sign) in a method declaration, and be currently
   * on the `(` (open paren) because we didn't find it. In that case, this
   * function will parse the preceding comment such as `/*<T, R>*/`.
   */
  TypeParameterList _parseGenericCommentTypeParameters() {
    if (_injectGenericCommentTypeList()) {
      return parseTypeParameterList();
    }
    return null;
  }

  /**
   * Parse the generic method or function's type parameters.
   *
   * For backwards compatibility this can optionally use comments.
   * See [parseGenericMethodComments].
   */
  TypeParameterList _parseGenericMethodTypeParameters() {
    if (_matches(TokenType.LT) || _injectGenericCommentTypeList()) {
      return parseTypeParameterList();
    }
    return null;
  }

  /**
   * Parse a library name. The [missingNameError] is the error code to be used
   * if the library name is missing. The [missingNameToken] is the token
   * associated with the error produced if the library name is missing. Return
   * the library name that was parsed.
   *
   *     libraryName ::=
   *         libraryIdentifier
   */
  LibraryIdentifier _parseLibraryName(
      ParserErrorCode missingNameError, Token missingNameToken) {
    if (_matchesIdentifier()) {
      return parseLibraryIdentifier();
    } else if (_matches(TokenType.STRING)) {
      // Recovery: This should be extended to handle arbitrary tokens until we
      // can find a token that can start a compilation unit member.
      StringLiteral string = parseStringLiteral();
      _reportErrorForNode(ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME, string);
    } else {
      _reportErrorForToken(missingNameError, missingNameToken);
    }
    return astFactory
        .libraryIdentifier(<SimpleIdentifier>[createSyntheticIdentifier()]);
  }

  /**
   * Parse a method declaration. The [commentAndMetadata] is the documentation
   * comment and metadata to be associated with the declaration. The
   * [externalKeyword] is the 'external' token. The [staticKeyword] is the
   * static keyword, or `null` if the getter is not static. The [returnType] is
   * the return type of the method. The [name] is the name of the method. The
   * [parameters] is the parameters to the method. Return the method declaration
   * that was parsed.
   *
   *     functionDeclaration ::=
   *         ('external' 'static'?)? functionSignature functionBody
   *       | 'external'? functionSignature ';'
   */
  MethodDeclaration _parseMethodDeclarationAfterParameters(
      CommentAndMetadata commentAndMetadata,
      Token externalKeyword,
      Token staticKeyword,
      TypeAnnotation returnType,
      SimpleIdentifier name,
      TypeParameterList typeParameters,
      FormalParameterList parameters) {
    FunctionBody body = parseFunctionBody(
        externalKeyword != null || staticKeyword == null,
        ParserErrorCode.MISSING_FUNCTION_BODY,
        false);
    if (externalKeyword != null) {
      if (body is! EmptyFunctionBody) {
        _reportErrorForNode(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, body);
      }
    } else if (staticKeyword != null) {
      if (body is EmptyFunctionBody && _parseFunctionBodies) {
        _reportErrorForNode(ParserErrorCode.ABSTRACT_STATIC_METHOD, body);
      }
    }
    return astFactory.methodDeclaration(
        commentAndMetadata.comment,
        commentAndMetadata.metadata,
        externalKeyword,
        staticKeyword,
        returnType,
        null,
        null,
        name,
        typeParameters,
        parameters,
        body);
  }

  /**
   * Parse a method declaration. The [commentAndMetadata] is the documentation
   * comment and metadata to be associated with the declaration. The
   * [externalKeyword] is the 'external' token. The [staticKeyword] is the
   * static keyword, or `null` if the getter is not static. The [returnType] is
   * the return type of the method. Return the method declaration that was
   * parsed.
   *
   *     functionDeclaration ::=
   *         'external'? 'static'? functionSignature functionBody
   *       | 'external'? functionSignature ';'
   */
  MethodDeclaration _parseMethodDeclarationAfterReturnType(
      CommentAndMetadata commentAndMetadata,
      Token externalKeyword,
      Token staticKeyword,
      TypeAnnotation returnType) {
    SimpleIdentifier methodName = parseSimpleIdentifier(isDeclaration: true);
    TypeParameterList typeParameters = _parseGenericMethodTypeParameters();
    FormalParameterList parameters;
    TokenType type = _currentToken.type;
    // TODO(brianwilkerson) Figure out why we care what the current token is if
    // it isn't a paren.
    if (type != TokenType.OPEN_PAREN &&
        (type == TokenType.OPEN_CURLY_BRACKET || type == TokenType.FUNCTION)) {
      _reportErrorForToken(
          ParserErrorCode.MISSING_METHOD_PARAMETERS, _currentToken.previous);
      parameters = astFactory.formalParameterList(
          _createSyntheticToken(TokenType.OPEN_PAREN),
          null,
          null,
          null,
          _createSyntheticToken(TokenType.CLOSE_PAREN));
    } else {
      parameters = parseFormalParameterList();
    }
    _validateFormalParameterList(parameters);
    return _parseMethodDeclarationAfterParameters(
        commentAndMetadata,
        externalKeyword,
        staticKeyword,
        returnType,
        methodName,
        typeParameters,
        parameters);
  }

  /**
   * Parse a class native clause. Return the native clause that was parsed.
   *
   * This method assumes that the current token matches `_NATIVE`.
   *
   *     classNativeClause ::=
   *         'native' name
   */
  NativeClause _parseNativeClause() {
    Token keyword = getAndAdvance();
    StringLiteral name = parseStringLiteral();
    return astFactory.nativeClause(keyword, name);
  }

  /**
   * Parse an operator declaration starting after the 'operator' keyword. The
   * [commentAndMetadata] is the documentation comment and metadata to be
   * associated with the declaration. The [externalKeyword] is the 'external'
   * token. The [returnType] is the return type that has already been parsed, or
   * `null` if there was no return type. The [operatorKeyword] is the 'operator'
   * keyword. Return the operator declaration that was parsed.
   *
   *     operatorDeclaration ::=
   *         operatorSignature (';' | functionBody)
   *
   *     operatorSignature ::=
   *         'external'? returnType? 'operator' operator formalParameterList
   */
  MethodDeclaration _parseOperatorAfterKeyword(
      CommentAndMetadata commentAndMetadata,
      Token externalKeyword,
      TypeAnnotation returnType,
      Token operatorKeyword) {
    if (!_currentToken.isUserDefinableOperator) {
      _reportErrorForCurrentToken(
          ParserErrorCode.NON_USER_DEFINABLE_OPERATOR, [_currentToken.lexeme]);
    }
    SimpleIdentifier name =
        astFactory.simpleIdentifier(getAndAdvance(), isDeclaration: true);
    if (_matches(TokenType.EQ)) {
      Token previous = _currentToken.previous;
      if ((_tokenMatches(previous, TokenType.EQ_EQ) ||
              _tokenMatches(previous, TokenType.BANG_EQ)) &&
          _currentToken.offset == previous.offset + 2) {
        _reportErrorForCurrentToken(ParserErrorCode.INVALID_OPERATOR,
            ["${previous.lexeme}${_currentToken.lexeme}"]);
        _advance();
      }
    }
    FormalParameterList parameters = parseFormalParameterList();
    _validateFormalParameterList(parameters);
    FunctionBody body =
        parseFunctionBody(true, ParserErrorCode.MISSING_FUNCTION_BODY, false);
    if (externalKeyword != null && body is! EmptyFunctionBody) {
      _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_OPERATOR_WITH_BODY);
    }
    return astFactory.methodDeclaration(
        commentAndMetadata.comment,
        commentAndMetadata.metadata,
        externalKeyword,
        null,
        returnType,
        null,
        operatorKeyword,
        name,
        null,
        parameters,
        body);
  }

  /**
   * Parse a return type if one is given, otherwise return `null` without
   * advancing. Return the return type that was parsed.
   */
  TypeAnnotation _parseOptionalReturnType() {
    TypeName typeComment = _parseOptionalTypeNameComment();
    if (typeComment != null) {
      return typeComment;
    }
    Keyword keyword = _currentToken.keyword;
    if (keyword == Keyword.VOID) {
      if (_atGenericFunctionTypeAfterReturnType(_peek())) {
        return parseTypeAnnotation(false);
      }
      return astFactory.typeName(
          astFactory.simpleIdentifier(getAndAdvance()), null);
    } else if (_matchesIdentifier()) {
      Token next = _peek();
      if (keyword != Keyword.GET &&
          keyword != Keyword.SET &&
          keyword != Keyword.OPERATOR &&
          (_tokenMatchesIdentifier(next) ||
              _tokenMatches(next, TokenType.LT))) {
        Token afterTypeParameters = _skipTypeParameterList(next);
        if (afterTypeParameters != null &&
            _tokenMatches(afterTypeParameters, TokenType.OPEN_PAREN)) {
          // If the identifier is followed by type parameters and a parenthesis,
          // then the identifier is the name of a generic method, not a return
          // type.
          return null;
        }
        return parseReturnType(false);
      }
      Token next2 = next.next;
      Token next3 = next2.next;
      if (_tokenMatches(next, TokenType.PERIOD) &&
          _tokenMatchesIdentifier(next2) &&
          (_tokenMatchesIdentifier(next3) ||
              _tokenMatches(next3, TokenType.LT))) {
        return parseReturnType(false);
      }
    }
    return null;
  }

  /**
   * Parse a [TypeArgumentList] if present, otherwise return null.
   * This also supports the comment form, if enabled: `/*<T>*/`
   */
  TypeArgumentList _parseOptionalTypeArguments() {
    if (_matches(TokenType.LT) || _injectGenericCommentTypeList()) {
      return parseTypeArgumentList();
    }
    return null;
  }

  TypeName _parseOptionalTypeNameComment() {
    if (_injectGenericCommentTypeAssign()) {
      return _parseTypeName(false);
    }
    return null;
  }

  /**
   * Parse a part directive. The [commentAndMetadata] is the metadata to be
   * associated with the directive. Return the part or part-of directive that
   * was parsed.
   *
   * This method assumes that the current token matches `Keyword.PART`.
   *
   *     partDirective ::=
   *         metadata 'part' stringLiteral ';'
   */
  Directive _parsePartDirective(CommentAndMetadata commentAndMetadata) {
    Token partKeyword = getAndAdvance();
    StringLiteral partUri = _parseUri();
    Token semicolon = _expect(TokenType.SEMICOLON);
    return astFactory.partDirective(commentAndMetadata.comment,
        commentAndMetadata.metadata, partKeyword, partUri, semicolon);
  }

  /**
   * Parse a part-of directive. The [commentAndMetadata] is the metadata to be
   * associated with the directive. Return the part or part-of directive that
   * was parsed.
   *
   * This method assumes that the current token matches [Keyword.PART] and that
   * the following token matches the identifier 'of'.
   *
   *     partOfDirective ::=
   *         metadata 'part' 'of' identifier ';'
   */
  Directive _parsePartOfDirective(CommentAndMetadata commentAndMetadata) {
    Token partKeyword = getAndAdvance();
    Token ofKeyword = getAndAdvance();
    if (enableUriInPartOf && _matches(TokenType.STRING)) {
      StringLiteral libraryUri = _parseUri();
      Token semicolon = _expect(TokenType.SEMICOLON);
      return astFactory.partOfDirective(
          commentAndMetadata.comment,
          commentAndMetadata.metadata,
          partKeyword,
          ofKeyword,
          libraryUri,
          null,
          semicolon);
    }
    LibraryIdentifier libraryName = _parseLibraryName(
        ParserErrorCode.MISSING_NAME_IN_PART_OF_DIRECTIVE, ofKeyword);
    Token semicolon = _expect(TokenType.SEMICOLON);
    return astFactory.partOfDirective(
        commentAndMetadata.comment,
        commentAndMetadata.metadata,
        partKeyword,
        ofKeyword,
        null,
        libraryName,
        semicolon);
  }

  /**
   * Parse a prefixed identifier given that the given [qualifier] was already
   * parsed. Return the prefixed identifier that was parsed.
   *
   *     prefixedIdentifier ::=
   *         identifier ('.' identifier)?
   */
  Identifier _parsePrefixedIdentifierAfterIdentifier(
      SimpleIdentifier qualifier) {
    if (!_matches(TokenType.PERIOD) || _injectGenericCommentTypeList()) {
      return qualifier;
    }
    Token period = getAndAdvance();
    SimpleIdentifier qualified = parseSimpleIdentifier();
    return astFactory.prefixedIdentifier(qualifier, period, qualified);
  }

  /**
   * Parse a prefixed identifier. Return the prefixed identifier that was
   * parsed.
   *
   * This method assumes that the current token matches an identifier.
   *
   *     prefixedIdentifier ::=
   *         identifier ('.' identifier)?
   */
  Identifier _parsePrefixedIdentifierUnchecked() {
    return _parsePrefixedIdentifierAfterIdentifier(
        _parseSimpleIdentifierUnchecked());
  }

  /**
   * Parse a simple identifier. Return the simple identifier that was parsed.
   *
   * This method assumes that the current token matches an identifier.
   *
   *     identifier ::=
   *         IDENTIFIER
   */
  SimpleIdentifier _parseSimpleIdentifierUnchecked(
      {bool isDeclaration: false}) {
    String lexeme = _currentToken.lexeme;
    if ((_inAsync || _inGenerator) &&
        (lexeme == ASYNC || lexeme == _AWAIT || lexeme == _YIELD)) {
      _reportErrorForCurrentToken(
          ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER);
    }
    return astFactory.simpleIdentifier(getAndAdvance(),
        isDeclaration: isDeclaration);
  }

  /**
   * Parse a list of statements within a switch statement. Return the statements
   * that were parsed.
   *
   *     statements ::=
   *         statement*
   */
  List<Statement> _parseStatementList() {
    List<Statement> statements = <Statement>[];
    Token statementStart = _currentToken;
    TokenType type = _currentToken.type;
    while (type != TokenType.EOF &&
        type != TokenType.CLOSE_CURLY_BRACKET &&
        !isSwitchMember()) {
      statements.add(parseStatement2());
      if (identical(_currentToken, statementStart)) {
        _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
            [_currentToken.lexeme]);
        _advance();
      }
      statementStart = _currentToken;
      type = _currentToken.type;
    }
    return statements;
  }

  /**
   * Parse a string literal that contains interpolations. Return the string
   * literal that was parsed.
   *
   * This method assumes that the current token matches either
   * [TokenType.STRING_INTERPOLATION_EXPRESSION] or
   * [TokenType.STRING_INTERPOLATION_IDENTIFIER].
   */
  StringInterpolation _parseStringInterpolation(Token string) {
    List<InterpolationElement> elements = <InterpolationElement>[
      astFactory.interpolationString(
          string, computeStringValue(string.lexeme, true, false))
    ];
    bool hasMore = true;
    bool isExpression = _matches(TokenType.STRING_INTERPOLATION_EXPRESSION);
    while (hasMore) {
      if (isExpression) {
        Token openToken = getAndAdvance();
        bool wasInInitializer = _inInitializer;
        _inInitializer = false;
        try {
          Expression expression = parseExpression2();
          Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
          elements.add(astFactory.interpolationExpression(
              openToken, expression, rightBracket));
        } finally {
          _inInitializer = wasInInitializer;
        }
      } else {
        Token openToken = getAndAdvance();
        Expression expression = null;
        if (_matchesKeyword(Keyword.THIS)) {
          expression = astFactory.thisExpression(getAndAdvance());
        } else {
          expression = parseSimpleIdentifier();
        }
        elements.add(
            astFactory.interpolationExpression(openToken, expression, null));
      }
      if (_matches(TokenType.STRING)) {
        string = getAndAdvance();
        isExpression = _matches(TokenType.STRING_INTERPOLATION_EXPRESSION);
        hasMore =
            isExpression || _matches(TokenType.STRING_INTERPOLATION_IDENTIFIER);
        elements.add(astFactory.interpolationString(
            string, computeStringValue(string.lexeme, false, !hasMore)));
      } else {
        hasMore = false;
      }
    }
    return astFactory.stringInterpolation(elements);
  }

  /**
   * Parse a string literal. Return the string literal that was parsed.
   *
   * This method assumes that the current token matches `TokenType.STRING`.
   *
   *     stringLiteral ::=
   *         MULTI_LINE_STRING+
   *       | SINGLE_LINE_STRING+
   */
  StringLiteral _parseStringLiteralUnchecked() {
    List<StringLiteral> strings = <StringLiteral>[];
    do {
      Token string = getAndAdvance();
      if (_matches(TokenType.STRING_INTERPOLATION_EXPRESSION) ||
          _matches(TokenType.STRING_INTERPOLATION_IDENTIFIER)) {
        strings.add(_parseStringInterpolation(string));
      } else {
        strings.add(astFactory.simpleStringLiteral(
            string, computeStringValue(string.lexeme, true, true)));
      }
    } while (_matches(TokenType.STRING));
    return strings.length == 1
        ? strings[0]
        : astFactory.adjacentStrings(strings);
  }

  /**
   * Parse a type annotation, possibly superseded by a type name in a comment.
   * Return the type name that was parsed.
   *
   * This method assumes that the current token is an identifier.
   *
   *     type ::=
   *         qualified typeArguments?
   */
  TypeAnnotation _parseTypeAnnotationAfterIdentifier() {
    TypeAnnotation type = parseTypeAnnotation(false);
    // If this is followed by a generic method type comment, allow the comment
    // type to replace the real type name.
    TypeName typeFromComment = _parseOptionalTypeNameComment();
    return typeFromComment ?? type;
  }

  TypeName _parseTypeName(bool inExpression) {
    Identifier typeName;
    if (_matchesIdentifier()) {
      typeName = _parsePrefixedIdentifierUnchecked();
    } else if (_matchesKeyword(Keyword.VAR)) {
      _reportErrorForCurrentToken(ParserErrorCode.VAR_AS_TYPE_NAME);
      typeName = astFactory.simpleIdentifier(getAndAdvance());
    } else {
      typeName = createSyntheticIdentifier();
      _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TYPE_NAME);
    }
    TypeArgumentList typeArguments = _parseOptionalTypeArguments();
    Token question = null;
    if (enableNnbd && _matches(TokenType.QUESTION)) {
      if (!inExpression || !_isConditionalOperator()) {
        question = getAndAdvance();
      }
    }
    return astFactory.typeName(typeName, typeArguments, question: question);
  }

  /**
   * Parse a string literal representing a URI. Return the string literal that
   * was parsed.
   */
  StringLiteral _parseUri() {
    // TODO(brianwilkerson) Should this function also return true for valid
    // top-level keywords?
    bool isKeywordAfterUri(Token token) =>
        token.lexeme == Keyword.AS.syntax ||
        token.lexeme == _HIDE ||
        token.lexeme == _SHOW;
    TokenType type = _currentToken.type;
    if (type != TokenType.STRING &&
        type != TokenType.SEMICOLON &&
        !isKeywordAfterUri(_currentToken)) {
      // Attempt to recover in the case where the URI was not enclosed in
      // quotes.
      Token token = _currentToken;
      bool isValidInUri(Token token) {
        TokenType type = token.type;
        return type == TokenType.COLON ||
            type == TokenType.SLASH ||
            type == TokenType.PERIOD ||
            type == TokenType.PERIOD_PERIOD ||
            type == TokenType.PERIOD_PERIOD_PERIOD ||
            type == TokenType.INT ||
            type == TokenType.DOUBLE;
      }

      while ((_tokenMatchesIdentifier(token) && !isKeywordAfterUri(token)) ||
          isValidInUri(token)) {
        token = token.next;
      }
      if (_tokenMatches(token, TokenType.SEMICOLON) ||
          isKeywordAfterUri(token)) {
        Token endToken = token.previous;
        token = _currentToken;
        int endOffset = token.end;
        StringBuffer buffer = new StringBuffer();
        buffer.write(token.lexeme);
        while (token != endToken) {
          token = token.next;
          if (token.offset != endOffset || token.precedingComments != null) {
            return parseStringLiteral();
          }
          buffer.write(token.lexeme);
          endOffset = token.end;
        }
        String value = buffer.toString();
        Token newToken =
            new StringToken(TokenType.STRING, "'$value'", _currentToken.offset);
        _reportErrorForToken(
            ParserErrorCode.NON_STRING_LITERAL_AS_URI, newToken);
        _currentToken = endToken.next;
        return astFactory.simpleStringLiteral(newToken, value);
      }
    }
    return parseStringLiteral();
  }

  /**
   * Parse a variable declaration statement. The [commentAndMetadata] is the
   * metadata to be associated with the variable declaration statement, or
   * `null` if there is no attempt at parsing the comment and metadata. The
   * [keyword] is the token representing the 'final', 'const' or 'var' keyword,
   * or `null` if there is no keyword. The [type] is the type of the variables
   * in the list. Return the variable declaration statement that was parsed.
   *
   *     variableDeclarationStatement ::=
   *         variableDeclarationList ';'
   */
  VariableDeclarationStatement _parseVariableDeclarationStatementAfterType(
      CommentAndMetadata commentAndMetadata,
      Token keyword,
      TypeAnnotation type) {
    VariableDeclarationList variableList =
        parseVariableDeclarationListAfterType(
            commentAndMetadata, keyword, type);
    Token semicolon = _expect(TokenType.SEMICOLON);
    return astFactory.variableDeclarationStatement(variableList, semicolon);
  }

  /**
   * Return the token that is immediately after the current token. This is
   * equivalent to [_peekAt](1).
   */
  Token _peek() => _currentToken.next;

  /**
   * Return the token that is the given [distance] after the current token,
   * where the distance is the number of tokens to look ahead. A distance of `0`
   * is the current token, `1` is the next token, etc.
   */
  Token _peekAt(int distance) {
    Token token = _currentToken;
    for (int i = 0; i < distance; i++) {
      token = token.next;
    }
    return token;
  }

  String _removeGitHubInlineCode(String comment) {
    int index = 0;
    while (true) {
      int beginIndex = comment.indexOf('`', index);
      if (beginIndex == -1) {
        break;
      }
      int endIndex = comment.indexOf('`', beginIndex + 1);
      if (endIndex == -1) {
        break;
      }
      comment = comment.substring(0, beginIndex + 1) +
          ' ' * (endIndex - beginIndex - 1) +
          comment.substring(endIndex);
      index = endIndex + 1;
    }
    return comment;
  }

  /**
   * Report the given [error].
   */
  void _reportError(AnalysisError error) {
    if (_errorListenerLock != 0) {
      return;
    }
    _errorListener.onError(error);
  }

  /**
   * Report an error with the given [errorCode] and [arguments] associated with
   * the current token.
   */
  void _reportErrorForCurrentToken(ParserErrorCode errorCode,
      [List<Object> arguments]) {
    _reportErrorForToken(errorCode, _currentToken, arguments);
  }

  /**
   * Report an error with the given [errorCode] and [arguments] associated with
   * the given [node].
   */
  void _reportErrorForNode(ParserErrorCode errorCode, AstNode node,
      [List<Object> arguments]) {
    _reportError(new AnalysisError(
        _source, node.offset, node.length, errorCode, arguments));
  }

  /**
   * Report an error with the given [errorCode] and [arguments] associated with
   * the given [token].
   */
  void _reportErrorForToken(ErrorCode errorCode, Token token,
      [List<Object> arguments]) {
    if (token.type == TokenType.EOF) {
      token = token.previous;
    }
    _reportError(new AnalysisError(_source, token.offset,
        math.max(token.length, 1), errorCode, arguments));
  }

  /**
   * Scans the generic method comment, and returns the tokens, otherwise
   * returns null.
   */
  Token _scanGenericMethodComment(String code, int offset) {
    BooleanErrorListener listener = new BooleanErrorListener();
    Scanner scanner =
        new Scanner(null, new SubSequenceReader(code, offset), listener);
    scanner.setSourceStart(1, 1);
    Token firstToken = scanner.tokenize();
    if (listener.errorReported) {
      return null;
    }
    return firstToken;
  }

  /**
   * Execute the given [parseOperation] in a temporary parser whose current
   * token has been set to the given [startToken]. If the parse does not
   * generate any errors or exceptions, then return the token following the
   * matching portion of the token stream. Otherwise, return `null`.
   *
   * Note: This is an extremely inefficient way of testing whether the tokens in
   * the token stream match a given production. It should not be used for
   * production code.
   */
  Token _skip(Token startToken, parseOperation(Parser parser)) {
    BooleanErrorListener listener = new BooleanErrorListener();
    Parser parser = new Parser(_source, listener);
    parser._currentToken = _cloneTokens(startToken);
    parser._enableAssertInitializer = _enableAssertInitializer;
    parser._enableNnbd = _enableNnbd;
    parser._inAsync = _inAsync;
    parser._inGenerator = _inGenerator;
    parser._inInitializer = _inInitializer;
    parser._inLoop = _inLoop;
    parser._inSwitch = _inSwitch;
    parser._parseFunctionBodies = _parseFunctionBodies;
    try {
      parseOperation(parser);
    } catch (exception) {
      return null;
    }
    if (listener.errorReported) {
      return null;
    }
    return parser._currentToken;
  }

  /**
   * Skips a block with all containing blocks.
   */
  void _skipBlock() {
    Token endToken = (_currentToken as BeginToken).endToken;
    if (endToken == null) {
      endToken = _currentToken.next;
      while (!identical(endToken, _currentToken)) {
        _currentToken = endToken;
        endToken = _currentToken.next;
      }
      _reportErrorForToken(
          ParserErrorCode.EXPECTED_TOKEN, _currentToken.previous, ["}"]);
    } else {
      _currentToken = endToken.next;
    }
  }

  /**
   * Parse the 'final', 'const', 'var' or type preceding a variable declaration,
   * starting at the given token, without actually creating a type or changing
   * the current token. Return the token following the type that was parsed, or
   * `null` if the given token is not the first token in a valid type. The
   * [startToken] is the token at which parsing is to begin. Return the token
   * following the type that was parsed.
   *
   * finalConstVarOrType ::=
   *   | 'final' type?
   *   | 'const' type?
   *   | 'var'
   *   | type
   */
  Token _skipFinalConstVarOrType(Token startToken) {
    Keyword keyword = startToken.keyword;
    if (keyword == Keyword.FINAL || keyword == Keyword.CONST) {
      Token next = startToken.next;
      if (_tokenMatchesIdentifier(next)) {
        Token next2 = next.next;
        // "Type parameter" or "Type<" or "prefix.Type"
        if (_tokenMatchesIdentifier(next2) ||
            _tokenMatches(next2, TokenType.LT) ||
            _tokenMatches(next2, TokenType.PERIOD)) {
          return skipTypeName(next);
        }
        // "parameter"
        return next;
      }
    } else if (keyword == Keyword.VAR) {
      return startToken.next;
    } else if (_tokenMatchesIdentifier(startToken)) {
      Token next = startToken.next;
      if (_tokenMatchesIdentifier(next) ||
          _tokenMatches(next, TokenType.LT) ||
          _tokenMatchesKeyword(next, Keyword.THIS) ||
          (_tokenMatches(next, TokenType.PERIOD) &&
              _tokenMatchesIdentifier(next.next) &&
              (_tokenMatchesIdentifier(next.next.next) ||
                  _tokenMatches(next.next.next, TokenType.LT) ||
                  _tokenMatchesKeyword(next.next.next, Keyword.THIS)))) {
        return skipReturnType(startToken);
      }
    }
    return null;
  }

  /**
   * Parse a list of formal parameters, starting at the [startToken], without
   * actually creating a formal parameter list or changing the current token.
   * Return the token following the formal parameter list that was parsed, or
   * `null` if the given token is not the first token in a valid list of formal
   * parameter.
   *
   * Note that unlike other skip methods, this method uses a heuristic. In the
   * worst case, the parameters could be prefixed by metadata, which would
   * require us to be able to skip arbitrary expressions. Rather than duplicate
   * the logic of most of the parse methods we simply look for something that is
   * likely to be a list of parameters and then skip to returning the token
   * after the closing parenthesis.
   *
   * This method must be kept in sync with [parseFormalParameterList].
   *
   *     formalParameterList ::=
   *         '(' ')'
   *       | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
   *       | '(' optionalFormalParameters ')'
   *
   *     normalFormalParameters ::=
   *         normalFormalParameter (',' normalFormalParameter)*
   *
   *     optionalFormalParameters ::=
   *         optionalPositionalFormalParameters
   *       | namedFormalParameters
   *
   *     optionalPositionalFormalParameters ::=
   *         '[' defaultFormalParameter (',' defaultFormalParameter)* ']'
   *
   *     namedFormalParameters ::=
   *         '{' defaultNamedParameter (',' defaultNamedParameter)* '}'
   */
  Token _skipFormalParameterList(Token startToken) {
    if (!_tokenMatches(startToken, TokenType.OPEN_PAREN)) {
      return null;
    }
    Token next = startToken.next;
    if (_tokenMatches(next, TokenType.CLOSE_PAREN)) {
      return next.next;
    }
    //
    // Look to see whether the token after the open parenthesis is something
    // that should only occur at the beginning of a parameter list.
    //
    if (next.matchesAny(const <TokenType>[
          TokenType.AT,
          TokenType.OPEN_SQUARE_BRACKET,
          TokenType.OPEN_CURLY_BRACKET
        ]) ||
        _tokenMatchesKeyword(next, Keyword.VOID) ||
        (_tokenMatchesIdentifier(next) &&
            (next.next.matchesAny(
                const <TokenType>[TokenType.COMMA, TokenType.CLOSE_PAREN])))) {
      return _skipPastMatchingToken(startToken);
    }
    //
    // Look to see whether the first parameter is a function typed parameter
    // without a return type.
    //
    if (_tokenMatchesIdentifier(next) &&
        _tokenMatches(next.next, TokenType.OPEN_PAREN)) {
      Token afterParameters = _skipFormalParameterList(next.next);
      if (afterParameters != null &&
          afterParameters.matchesAny(
              const <TokenType>[TokenType.COMMA, TokenType.CLOSE_PAREN])) {
        return _skipPastMatchingToken(startToken);
      }
    }
    //
    // Look to see whether the first parameter has a type or is a function typed
    // parameter with a return type.
    //
    Token afterType = _skipFinalConstVarOrType(next);
    if (afterType == null) {
      return null;
    }
    if (skipSimpleIdentifier(afterType) == null) {
      return null;
    }
    return _skipPastMatchingToken(startToken);
  }

  /**
   * If the [startToken] is a begin token with an associated end token, then
   * return the token following the end token. Otherwise, return `null`.
   */
  Token _skipPastMatchingToken(Token startToken) {
    if (startToken is! BeginToken) {
      return null;
    }
    Token closeParen = (startToken as BeginToken).endToken;
    if (closeParen == null) {
      return null;
    }
    return closeParen.next;
  }

  /**
   * Parse a string literal that contains interpolations, starting at the
   * [startToken], without actually creating a string literal or changing the
   * current token. Return the token following the string literal that was
   * parsed, or `null` if the given token is not the first token in a valid
   * string literal.
   *
   * This method must be kept in sync with [parseStringInterpolation].
   */
  Token _skipStringInterpolation(Token startToken) {
    Token token = startToken;
    TokenType type = token.type;
    while (type == TokenType.STRING_INTERPOLATION_EXPRESSION ||
        type == TokenType.STRING_INTERPOLATION_IDENTIFIER) {
      if (type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
        token = token.next;
        type = token.type;
        //
        // Rather than verify that the following tokens represent a valid
        // expression, we simply skip tokens until we reach the end of the
        // interpolation, being careful to handle nested string literals.
        //
        int bracketNestingLevel = 1;
        while (bracketNestingLevel > 0) {
          if (type == TokenType.EOF) {
            return null;
          } else if (type == TokenType.OPEN_CURLY_BRACKET) {
            bracketNestingLevel++;
            token = token.next;
          } else if (type == TokenType.CLOSE_CURLY_BRACKET) {
            bracketNestingLevel--;
            token = token.next;
          } else if (type == TokenType.STRING) {
            token = skipStringLiteral(token);
            if (token == null) {
              return null;
            }
          } else {
            token = token.next;
          }
          type = token.type;
        }
        token = token.next;
        type = token.type;
      } else {
        token = token.next;
        if (token.type != TokenType.IDENTIFIER) {
          return null;
        }
        token = token.next;
      }
      type = token.type;
      if (type == TokenType.STRING) {
        token = token.next;
        type = token.type;
      }
    }
    return token;
  }

  /**
   * Parse a list of type parameters, starting at the [startToken], without
   * actually creating a type parameter list or changing the current token.
   * Return the token following the type parameter list that was parsed, or
   * `null` if the given token is not the first token in a valid type parameter
   * list.
   *
   * This method must be kept in sync with [parseTypeParameterList].
   *
   *     typeParameterList ::=
   *         '<' typeParameter (',' typeParameter)* '>'
   */
  Token _skipTypeParameterList(Token startToken) {
    if (!_tokenMatches(startToken, TokenType.LT)) {
      return null;
    }
    //
    // We can't skip a type parameter because it can be preceeded by metadata,
    // so we just assume that everything before the matching end token is valid.
    //
    int depth = 1;
    Token next = startToken.next;
    while (depth > 0) {
      if (_tokenMatches(next, TokenType.EOF)) {
        return null;
      } else if (_tokenMatches(next, TokenType.LT)) {
        depth++;
      } else if (_tokenMatches(next, TokenType.GT)) {
        depth--;
      } else if (_tokenMatches(next, TokenType.GT_EQ)) {
        if (depth == 1) {
          Token fakeEquals = new Token(TokenType.EQ, next.offset + 2);
          fakeEquals.setNextWithoutSettingPrevious(next.next);
          return fakeEquals;
        }
        depth--;
      } else if (_tokenMatches(next, TokenType.GT_GT)) {
        depth -= 2;
      } else if (_tokenMatches(next, TokenType.GT_GT_EQ)) {
        if (depth < 2) {
          return null;
        } else if (depth == 2) {
          Token fakeEquals = new Token(TokenType.EQ, next.offset + 2);
          fakeEquals.setNextWithoutSettingPrevious(next.next);
          return fakeEquals;
        }
        depth -= 2;
      }
      next = next.next;
    }
    return next;
  }

  /**
   * Assuming that the current token is an index token ('[]'), split it into two
   * tokens ('[' and ']'), leaving the left bracket as the current token.
   */
  void _splitIndex() {
    // Split the token into two separate tokens.
    BeginToken leftBracket = _createToken(
        _currentToken, TokenType.OPEN_SQUARE_BRACKET,
        isBegin: true);
    Token rightBracket =
        new Token(TokenType.CLOSE_SQUARE_BRACKET, _currentToken.offset + 1);
    leftBracket.endToken = rightBracket;
    rightBracket.setNext(_currentToken.next);
    leftBracket.setNext(rightBracket);
    _currentToken.previous.setNext(leftBracket);
    _currentToken = leftBracket;
  }

  /**
   * Return `true` if the given [token] has the given [type].
   */
  bool _tokenMatches(Token token, TokenType type) => token.type == type;

  /**
   * Return `true` if the given [token] is a valid identifier. Valid identifiers
   * include built-in identifiers (pseudo-keywords).
   */
  bool _tokenMatchesIdentifier(Token token) =>
      _tokenMatches(token, TokenType.IDENTIFIER) ||
      _tokenMatchesPseudoKeyword(token);

  /**
   * Return `true` if the given [token] is either an identifier or a keyword.
   */
  bool _tokenMatchesIdentifierOrKeyword(Token token) =>
      _tokenMatches(token, TokenType.IDENTIFIER) ||
      _tokenMatches(token, TokenType.KEYWORD);

  /**
   * Return `true` if the given [token] matches the given [keyword].
   */
  bool _tokenMatchesKeyword(Token token, Keyword keyword) =>
      token.keyword == keyword;

  /**
   * Return `true` if the given [token] matches a pseudo keyword.
   */
  bool _tokenMatchesPseudoKeyword(Token token) =>
      token.keyword?.isBuiltInOrPseudo ?? false;

  /**
   * Translate the characters at the given [index] in the given [lexeme],
   * appending the translated character to the given [buffer]. The index is
   * assumed to be valid.
   */
  int _translateCharacter(StringBuffer buffer, String lexeme, int index) {
    int currentChar = lexeme.codeUnitAt(index);
    if (currentChar != 0x5C) {
      buffer.writeCharCode(currentChar);
      return index + 1;
    }
    //
    // We have found an escape sequence, so we parse the string to determine
    // what kind of escape sequence and what character to add to the builder.
    //
    int length = lexeme.length;
    int currentIndex = index + 1;
    if (currentIndex >= length) {
      // Illegal escape sequence: no char after escape.
      // This cannot actually happen because it would require the escape
      // character to be the last character in the string, but if it were it
      // would escape the closing quote, leaving the string unclosed.
      // reportError(ParserErrorCode.MISSING_CHAR_IN_ESCAPE_SEQUENCE);
      return length;
    }
    currentChar = lexeme.codeUnitAt(currentIndex);
    if (currentChar == 0x6E) {
      buffer.writeCharCode(0xA);
      // newline
    } else if (currentChar == 0x72) {
      buffer.writeCharCode(0xD);
      // carriage return
    } else if (currentChar == 0x66) {
      buffer.writeCharCode(0xC);
      // form feed
    } else if (currentChar == 0x62) {
      buffer.writeCharCode(0x8);
      // backspace
    } else if (currentChar == 0x74) {
      buffer.writeCharCode(0x9);
      // tab
    } else if (currentChar == 0x76) {
      buffer.writeCharCode(0xB);
      // vertical tab
    } else if (currentChar == 0x78) {
      if (currentIndex + 2 >= length) {
        // Illegal escape sequence: not enough hex digits
        _reportErrorForCurrentToken(ParserErrorCode.INVALID_HEX_ESCAPE);
        return length;
      }
      int firstDigit = lexeme.codeUnitAt(currentIndex + 1);
      int secondDigit = lexeme.codeUnitAt(currentIndex + 2);
      if (!_isHexDigit(firstDigit) || !_isHexDigit(secondDigit)) {
        // Illegal escape sequence: invalid hex digit
        _reportErrorForCurrentToken(ParserErrorCode.INVALID_HEX_ESCAPE);
      } else {
        int charCode = (Character.digit(firstDigit, 16) << 4) +
            Character.digit(secondDigit, 16);
        buffer.writeCharCode(charCode);
      }
      return currentIndex + 3;
    } else if (currentChar == 0x75) {
      currentIndex++;
      if (currentIndex >= length) {
        // Illegal escape sequence: not enough hex digits
        _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
        return length;
      }
      currentChar = lexeme.codeUnitAt(currentIndex);
      if (currentChar == 0x7B) {
        currentIndex++;
        if (currentIndex >= length) {
          // Illegal escape sequence: incomplete escape
          _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
          return length;
        }
        currentChar = lexeme.codeUnitAt(currentIndex);
        int digitCount = 0;
        int value = 0;
        while (currentChar != 0x7D) {
          if (!_isHexDigit(currentChar)) {
            // Illegal escape sequence: invalid hex digit
            _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
            currentIndex++;
            while (currentIndex < length &&
                lexeme.codeUnitAt(currentIndex) != 0x7D) {
              currentIndex++;
            }
            return currentIndex + 1;
          }
          digitCount++;
          value = (value << 4) + Character.digit(currentChar, 16);
          currentIndex++;
          if (currentIndex >= length) {
            // Illegal escape sequence: incomplete escape
            _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
            return length;
          }
          currentChar = lexeme.codeUnitAt(currentIndex);
        }
        if (digitCount < 1 || digitCount > 6) {
          // Illegal escape sequence: not enough or too many hex digits
          _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
        }
        _appendCodePoint(buffer, lexeme, value, index, currentIndex);
        return currentIndex + 1;
      } else {
        if (currentIndex + 3 >= length) {
          // Illegal escape sequence: not enough hex digits
          _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
          return length;
        }
        int firstDigit = currentChar;
        int secondDigit = lexeme.codeUnitAt(currentIndex + 1);
        int thirdDigit = lexeme.codeUnitAt(currentIndex + 2);
        int fourthDigit = lexeme.codeUnitAt(currentIndex + 3);
        if (!_isHexDigit(firstDigit) ||
            !_isHexDigit(secondDigit) ||
            !_isHexDigit(thirdDigit) ||
            !_isHexDigit(fourthDigit)) {
          // Illegal escape sequence: invalid hex digits
          _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
        } else {
          _appendCodePoint(
              buffer,
              lexeme,
              (((((Character.digit(firstDigit, 16) << 4) +
                                  Character.digit(secondDigit, 16)) <<
                              4) +
                          Character.digit(thirdDigit, 16)) <<
                      4) +
                  Character.digit(fourthDigit, 16),
              index,
              currentIndex + 3);
        }
        return currentIndex + 4;
      }
    } else {
      buffer.writeCharCode(currentChar);
    }
    return currentIndex + 1;
  }

  /**
   * Decrements the error reporting lock level. If level is more than `0`, then
   * [reportError] wont report any error.
   */
  void _unlockErrorListener() {
    if (_errorListenerLock == 0) {
      throw new StateError("Attempt to unlock not locked error listener.");
    }
    _errorListenerLock--;
  }

  /**
   * Validate that the given [parameterList] does not contain any field
   * initializers.
   */
  void _validateFormalParameterList(FormalParameterList parameterList) {
    for (FormalParameter parameter in parameterList.parameters) {
      if (parameter is FieldFormalParameter) {
        _reportErrorForNode(
            ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR,
            parameter.identifier);
      }
    }
  }

  /**
   * Validate that the given set of [modifiers] is appropriate for a class and
   * return the 'abstract' keyword if there is one.
   */
  Token _validateModifiersForClass(Modifiers modifiers) {
    _validateModifiersForTopLevelDeclaration(modifiers);
    if (modifiers.constKeyword != null) {
      _reportErrorForToken(ParserErrorCode.CONST_CLASS, modifiers.constKeyword);
    }
    if (modifiers.externalKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.EXTERNAL_CLASS, modifiers.externalKeyword);
    }
    if (modifiers.finalKeyword != null) {
      _reportErrorForToken(ParserErrorCode.FINAL_CLASS, modifiers.finalKeyword);
    }
    if (modifiers.varKeyword != null) {
      _reportErrorForToken(ParserErrorCode.VAR_CLASS, modifiers.varKeyword);
    }
    return modifiers.abstractKeyword;
  }

  /**
   * Validate that the given set of [modifiers] is appropriate for a constructor
   * and return the 'const' keyword if there is one.
   */
  Token _validateModifiersForConstructor(Modifiers modifiers) {
    if (modifiers.abstractKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.ABSTRACT_CLASS_MEMBER, modifiers.abstractKeyword);
    }
    if (modifiers.covariantKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.COVARIANT_CONSTRUCTOR, modifiers.covariantKeyword);
    }
    if (modifiers.finalKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.FINAL_CONSTRUCTOR, modifiers.finalKeyword);
    }
    if (modifiers.staticKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.STATIC_CONSTRUCTOR, modifiers.staticKeyword);
    }
    if (modifiers.varKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, modifiers.varKeyword);
    }
    Token externalKeyword = modifiers.externalKeyword;
    Token constKeyword = modifiers.constKeyword;
    Token factoryKeyword = modifiers.factoryKeyword;
    if (externalKeyword != null &&
        constKeyword != null &&
        constKeyword.offset < externalKeyword.offset) {
      _reportErrorForToken(
          ParserErrorCode.EXTERNAL_AFTER_CONST, externalKeyword);
    }
    if (externalKeyword != null &&
        factoryKeyword != null &&
        factoryKeyword.offset < externalKeyword.offset) {
      _reportErrorForToken(
          ParserErrorCode.EXTERNAL_AFTER_FACTORY, externalKeyword);
    }
    return constKeyword;
  }

  /**
   * Validate that the given set of [modifiers] is appropriate for an enum and
   * return the 'abstract' keyword if there is one.
   */
  void _validateModifiersForEnum(Modifiers modifiers) {
    _validateModifiersForTopLevelDeclaration(modifiers);
    if (modifiers.abstractKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.ABSTRACT_ENUM, modifiers.abstractKeyword);
    }
    if (modifiers.constKeyword != null) {
      _reportErrorForToken(ParserErrorCode.CONST_ENUM, modifiers.constKeyword);
    }
    if (modifiers.externalKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.EXTERNAL_ENUM, modifiers.externalKeyword);
    }
    if (modifiers.finalKeyword != null) {
      _reportErrorForToken(ParserErrorCode.FINAL_ENUM, modifiers.finalKeyword);
    }
    if (modifiers.varKeyword != null) {
      _reportErrorForToken(ParserErrorCode.VAR_ENUM, modifiers.varKeyword);
    }
  }

  /**
   * Validate that the given set of [modifiers] is appropriate for a field and
   * return the 'final', 'const' or 'var' keyword if there is one.
   */
  Token _validateModifiersForField(Modifiers modifiers) {
    if (modifiers.abstractKeyword != null) {
      _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER);
    }
    if (modifiers.externalKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.EXTERNAL_FIELD, modifiers.externalKeyword);
    }
    if (modifiers.factoryKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.factoryKeyword);
    }
    Token staticKeyword = modifiers.staticKeyword;
    Token covariantKeyword = modifiers.covariantKeyword;
    Token constKeyword = modifiers.constKeyword;
    Token finalKeyword = modifiers.finalKeyword;
    Token varKeyword = modifiers.varKeyword;
    if (constKeyword != null) {
      if (covariantKeyword != null) {
        _reportErrorForToken(
            ParserErrorCode.CONST_AND_COVARIANT, covariantKeyword);
      }
      if (finalKeyword != null) {
        _reportErrorForToken(ParserErrorCode.CONST_AND_FINAL, finalKeyword);
      }
      if (varKeyword != null) {
        _reportErrorForToken(ParserErrorCode.CONST_AND_VAR, varKeyword);
      }
      if (staticKeyword != null && constKeyword.offset < staticKeyword.offset) {
        _reportErrorForToken(ParserErrorCode.STATIC_AFTER_CONST, staticKeyword);
      }
    } else if (finalKeyword != null) {
      if (covariantKeyword != null) {
        _reportErrorForToken(
            ParserErrorCode.FINAL_AND_COVARIANT, covariantKeyword);
      }
      if (varKeyword != null) {
        _reportErrorForToken(ParserErrorCode.FINAL_AND_VAR, varKeyword);
      }
      if (staticKeyword != null && finalKeyword.offset < staticKeyword.offset) {
        _reportErrorForToken(ParserErrorCode.STATIC_AFTER_FINAL, staticKeyword);
      }
    } else if (varKeyword != null) {
      if (staticKeyword != null && varKeyword.offset < staticKeyword.offset) {
        _reportErrorForToken(ParserErrorCode.STATIC_AFTER_VAR, staticKeyword);
      }
      if (covariantKeyword != null &&
          varKeyword.offset < covariantKeyword.offset) {
        _reportErrorForToken(
            ParserErrorCode.COVARIANT_AFTER_VAR, covariantKeyword);
      }
    }
    if (covariantKeyword != null && staticKeyword != null) {
      _reportErrorForToken(ParserErrorCode.COVARIANT_AND_STATIC, staticKeyword);
    }
    return Token.lexicallyFirst([constKeyword, finalKeyword, varKeyword]);
  }

  /**
   * Validate that the given set of [modifiers] is appropriate for a local
   * function.
   */
  void _validateModifiersForFunctionDeclarationStatement(Modifiers modifiers) {
    if (modifiers.abstractKeyword != null ||
        modifiers.constKeyword != null ||
        modifiers.externalKeyword != null ||
        modifiers.factoryKeyword != null ||
        modifiers.finalKeyword != null ||
        modifiers.staticKeyword != null ||
        modifiers.varKeyword != null) {
      _reportErrorForCurrentToken(
          ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER);
    }
  }

  /**
   * Validate that the given set of [modifiers] is appropriate for a getter,
   * setter, or method.
   */
  void _validateModifiersForGetterOrSetterOrMethod(Modifiers modifiers) {
    if (modifiers.abstractKeyword != null) {
      _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER);
    }
    if (modifiers.constKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.CONST_METHOD, modifiers.constKeyword);
    }
    if (modifiers.covariantKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.COVARIANT_MEMBER, modifiers.covariantKeyword);
    }
    if (modifiers.factoryKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.factoryKeyword);
    }
    if (modifiers.finalKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.FINAL_METHOD, modifiers.finalKeyword);
    }
    if (modifiers.varKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword);
    }
    Token externalKeyword = modifiers.externalKeyword;
    Token staticKeyword = modifiers.staticKeyword;
    if (externalKeyword != null &&
        staticKeyword != null &&
        staticKeyword.offset < externalKeyword.offset) {
      _reportErrorForToken(
          ParserErrorCode.EXTERNAL_AFTER_STATIC, externalKeyword);
    }
  }

  /**
   * Validate that the given set of [modifiers] is appropriate for a getter,
   * setter, or method.
   */
  void _validateModifiersForOperator(Modifiers modifiers) {
    if (modifiers.abstractKeyword != null) {
      _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER);
    }
    if (modifiers.constKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.CONST_METHOD, modifiers.constKeyword);
    }
    if (modifiers.factoryKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.factoryKeyword);
    }
    if (modifiers.finalKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.FINAL_METHOD, modifiers.finalKeyword);
    }
    if (modifiers.staticKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.STATIC_OPERATOR, modifiers.staticKeyword);
    }
    if (modifiers.varKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword);
    }
  }

  /**
   * Validate that the given set of [modifiers] is appropriate for a top-level
   * declaration.
   */
  void _validateModifiersForTopLevelDeclaration(Modifiers modifiers) {
    if (modifiers.covariantKeyword != null) {
      _reportErrorForToken(ParserErrorCode.COVARIANT_TOP_LEVEL_DECLARATION,
          modifiers.covariantKeyword);
    }
    if (modifiers.factoryKeyword != null) {
      _reportErrorForToken(ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION,
          modifiers.factoryKeyword);
    }
    if (modifiers.staticKeyword != null) {
      _reportErrorForToken(ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION,
          modifiers.staticKeyword);
    }
  }

  /**
   * Validate that the given set of [modifiers] is appropriate for a top-level
   * function.
   */
  void _validateModifiersForTopLevelFunction(Modifiers modifiers) {
    _validateModifiersForTopLevelDeclaration(modifiers);
    if (modifiers.abstractKeyword != null) {
      _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION);
    }
    if (modifiers.constKeyword != null) {
      _reportErrorForToken(ParserErrorCode.CONST_CLASS, modifiers.constKeyword);
    }
    if (modifiers.finalKeyword != null) {
      _reportErrorForToken(ParserErrorCode.FINAL_CLASS, modifiers.finalKeyword);
    }
    if (modifiers.varKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword);
    }
  }

  /**
   * Validate that the given set of [modifiers] is appropriate for a field and
   * return the 'final', 'const' or 'var' keyword if there is one.
   */
  Token _validateModifiersForTopLevelVariable(Modifiers modifiers) {
    _validateModifiersForTopLevelDeclaration(modifiers);
    if (modifiers.abstractKeyword != null) {
      _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_TOP_LEVEL_VARIABLE);
    }
    if (modifiers.externalKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.EXTERNAL_FIELD, modifiers.externalKeyword);
    }
    Token constKeyword = modifiers.constKeyword;
    Token finalKeyword = modifiers.finalKeyword;
    Token varKeyword = modifiers.varKeyword;
    if (constKeyword != null) {
      if (finalKeyword != null) {
        _reportErrorForToken(ParserErrorCode.CONST_AND_FINAL, finalKeyword);
      }
      if (varKeyword != null) {
        _reportErrorForToken(ParserErrorCode.CONST_AND_VAR, varKeyword);
      }
    } else if (finalKeyword != null) {
      if (varKeyword != null) {
        _reportErrorForToken(ParserErrorCode.FINAL_AND_VAR, varKeyword);
      }
    }
    return Token.lexicallyFirst([constKeyword, finalKeyword, varKeyword]);
  }

  /**
   * Validate that the given set of [modifiers] is appropriate for a class and
   * return the 'abstract' keyword if there is one.
   */
  void _validateModifiersForTypedef(Modifiers modifiers) {
    _validateModifiersForTopLevelDeclaration(modifiers);
    if (modifiers.abstractKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.ABSTRACT_TYPEDEF, modifiers.abstractKeyword);
    }
    if (modifiers.constKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.CONST_TYPEDEF, modifiers.constKeyword);
    }
    if (modifiers.externalKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.EXTERNAL_TYPEDEF, modifiers.externalKeyword);
    }
    if (modifiers.finalKeyword != null) {
      _reportErrorForToken(
          ParserErrorCode.FINAL_TYPEDEF, modifiers.finalKeyword);
    }
    if (modifiers.varKeyword != null) {
      _reportErrorForToken(ParserErrorCode.VAR_TYPEDEF, modifiers.varKeyword);
    }
  }
}

/**
 * Instances of this class are thrown when the parser detects that AST has
 * too many nested expressions to be parsed safely and avoid possibility of
 * [StackOverflowError] in the parser or during later analysis.
 */
class _TooDeepTreeError {}
