// 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.parser;

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

import 'package:_fe_analyzer_shared/src/parser/identifier_context.dart'
    as fasta;
import 'package:_fe_analyzer_shared/src/parser/member_kind.dart' as fasta;
import 'package:_fe_analyzer_shared/src/parser/parser.dart' as fasta;
import 'package:_fe_analyzer_shared/src/parser/type_info.dart' as fasta;
import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' as fasta;
import 'package:analyzer/dart/analysis/features.dart';
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/fasta/ast_builder.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';
import 'package:meta/meta.dart';

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

part 'parser_fasta.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 = 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.lexeme;

  static final String _AWAIT = Keyword.AWAIT.lexeme;

  static final String _HIDE = Keyword.HIDE.lexeme;

  static final String _SHOW = Keyword.SHOW.lexeme;

  static final String SYNC = Keyword.SYNC.lexeme;

  static final String _YIELD = Keyword.YIELD.lexeme;

  static const int _MAX_TREE_DEPTH = 300;

  /// A flag indicating whether the analyzer [Parser] factory method
  /// will return a fasta based parser or an analyzer based parser.
  static const bool useFasta =
      bool.fromEnvironment("useFastaParser", defaultValue: true);

  /// 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 should parse instance creation
  /// expressions that lack either the `new` or `const` keyword.
  bool _enableOptionalNewAndConst = 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;

  bool allowNativeClause;

  FeatureSet _featureSet;

  /// Initialize a newly created parser to parse tokens in the given [_source]
  /// and to report any errors that are found to the given [_errorListener].
  factory Parser(Source source, AnalysisErrorListener errorListener,
      {bool useFasta, @required FeatureSet featureSet}) {
    featureSet ??= FeatureSet.fromEnableFlags([]);
    if (useFasta ?? Parser.useFasta) {
      return _Parser2(source, errorListener, featureSet,
          allowNativeClause: true);
    } else {
      return Parser.withoutFasta(source, errorListener, featureSet: featureSet);
    }
  }

  /// Creates a parser using the old (legacy) analyzer parsing logic.
  ///
  /// In a future major version release of the analyzer, the [featureSet]
  /// argument will be required.
  Parser.withoutFasta(this._source, this._errorListener,
      {FeatureSet featureSet}) {
    if (featureSet != null) {
      _configureFeatures(featureSet);
    }
  }

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

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

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

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

  /// Return `true` if the parser should parse instance creation expressions
  /// that lack either the `new` or `const` keyword.
  bool get enableOptionalNewAndConst => _enableOptionalNewAndConst;

  /// Set whether the parser should parse instance creation expressions that
  /// lack either the `new` or `const` keyword.
  set enableOptionalNewAndConst(bool enable) {
    _enableOptionalNewAndConst = enable;
  }

  /// Enables or disables parsing of set literals.
  set enableSetLiterals(bool value) {
    // TODO(danrubel): Remove this method once the reference to this flag
    // has been removed from dartfmt.
  }

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

  /// Set whether the parser is to allow URI's in part-of directives to the
  /// given [enable] flag.
  @deprecated
  set enableUriInPartOf(bool 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 = skipTypeAnnotation(_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
  set parseAsync(bool parseAsync) {}

  @deprecated
  bool get parseConditionalDirectives => true;

  @deprecated
  set parseConditionalDirectives(bool value) {}

  /// Set whether parser is to parse function bodies.
  set parseFunctionBodies(bool parseFunctionBodies) {
    _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 = StringLexemeHelper(lexeme, isFirst, isLast);
    int start = helper.start;
    int end = helper.end;
    bool stringEndsAfterStart = end >= start;
    assert(stringEndsAfterStart);
    if (!stringEndsAfterStart) {
      AnalysisEngine.instance.instrumentationService.logError(
          "Internal error: computeStringValue($lexeme, $isFirst, $isLast)");
      return "";
    }
    if (helper.isRaw) {
      return lexeme.substring(start, end);
    }
    StringBuffer buffer = 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.isKeyword) {
      // 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(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;
    Token afterReturnType = skipTypeWithoutFunction(_currentToken);
    if (afterReturnType != null &&
        _tokenMatchesKeyword(afterReturnType, Keyword.FUNCTION)) {
      afterReturnType = skipGenericFunctionTypeAfterReturnType(afterReturnType);
    }
    // If there was no return type, because it was optional, go back
    // to where we started.
    afterReturnType ??= _currentToken;
    Token afterIdentifier = skipSimpleIdentifier(afterReturnType);

    // 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);
    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 ||
        keyword == Keyword.VOID) {
      // 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.isKeyword ||
          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;
    SimpleIdentifier constructorName;
    if (_matches(TokenType.PERIOD)) {
      period = getAndAdvance();
      constructorName = parseSimpleIdentifier();
    }
    ArgumentList arguments;
    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();
      if (_matches(TokenType.CLOSE_PAREN)) {
        comma;
      } else {
        message = parseExpression2();
        if (_matches(TokenType.COMMA)) {
          getAndAdvance();
        }
      }
    }
    Token rightParen = _expect(TokenType.CLOSE_PAREN);
    Token semicolon = _expect(TokenType.SEMICOLON);
    // TODO(brianwilkerson) We should capture the trailing comma in the AST, but
    // that would be a breaking change, so we drop it for now.
    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) {
    //
    // 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 || _isValidAssignableExpression(expression);
    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 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.indexExpressionForTarget2(
            target: prefix,
            leftBracket: leftBracket,
            index: index,
            rightBracket: 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.indexExpressionForTarget2(
            target: prefix,
            leftBracket: leftBracket,
            index: index,
            rightBracket: 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;
    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;
    SimpleIdentifier functionName;
    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.indexExpressionForCascade2(
            period: period,
            leftBracket: leftBracket,
            index: index,
            rightBracket: rightBracket);
        period;
      } 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;
          functionName;
        } 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;
    }
    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;
    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;
    WithClause withClause;
    ImplementsClause implementsClause;
    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;
      }
    }
    //
    // Look for and skip over the extra-lingual 'native' specification.
    //
    NativeClause nativeClause;
    if (_matchesKeyword(Keyword.NATIVE) &&
        _tokenMatches(_peek(), TokenType.STRING)) {
      nativeClause = _parseNativeClause();
    }
    //
    // Parse the body of the class.
    //
    Token leftBracket;
    List<ClassMember> members;
    Token rightBracket;
    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.EXPECTED_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) || next.type == TokenType.EQ_EQ_EQ)) {
        _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
          ])) {
        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;
      SimpleIdentifier methodName = parseSimpleIdentifier(isDeclaration: true);
      TypeParameterList typeParameters;
      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;
      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(
          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;
    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;
    while (_matches(TokenType.AT)) {
      metadata ??= <Annotation>[];
      metadata.add(parseAnnotation());
      List<DocumentationCommentToken> optionalTokens =
          parseDocumentationCommentTokens();
      if (optionalTokens != null) {
        tokens = optionalTokens;
      }
    }
    return 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 = BooleanErrorListener();
      Scanner scanner = Scanner(
          null, SubSequenceReader(referenceSource, sourceOffset), listener)
        ..configureFeatures(
          featureSetForOverriding: _featureSet,
          featureSet: _featureSet,
        );
      scanner.setSourceStart(1, 1);
      Token firstToken = scanner.tokenize();
      if (listener.errorReported) {
        return null;
      }
      if (firstToken.type == TokenType.EOF) {
        Token syntheticToken =
            SyntheticStringToken(TokenType.IDENTIFIER, "", sourceOffset);
        syntheticToken.setNext(firstToken);
        return astFactory.commentReference(
            null, astFactory.simpleIdentifier(syntheticToken));
      }
      Token newKeyword;
      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.contains('```')) {
          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);
                }
              }
            }
          } 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 = StringToken(TokenType.IDENTIFIER, name, nameOffset);
            } else {
              nameToken =
                  SyntheticStringToken(TokenType.IDENTIFIER, '', nameOffset);
            }
            nameToken.setNext(Token.eof(nameToken.end));
            references.add(astFactory.commentReference(
                null, astFactory.simpleIdentifier(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;
    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.isNotEmpty) {
                _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 StateError(
                "parseDirective invoked in an invalid state (currentToken = $_currentToken)");
          }
        }

        Directive directive = parseDirective();
        if (declarations.isNotEmpty && !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 = Token.eof(0);
          return astFactory.compilationUnit(
            beginToken: eof,
            endToken: eof,
            featureSet: _featureSet,
          );
        }
        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(
      beginToken: firstToken,
      scriptTag: scriptTag,
      directives: directives,
      declarations: declarations,
      endToken: _currentToken,
      featureSet: _featureSet,
    );
  }

  /// 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
          ])) {
        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;
      keyword ??= modifiers.finalKeyword;
      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;
      _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 = 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 (_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;
    StringLiteral value;
    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) {
      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;
    Token period;
    if (hasThis) {
      keywordToken = getAndAdvance();
      period = _expect(TokenType.PERIOD);
    }
    SimpleIdentifier fieldName = parseSimpleIdentifier();
    Token equals;
    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;
    SimpleIdentifier name;
    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;
    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 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;
    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(
          beginToken: firstToken,
          scriptTag: scriptTag,
          directives: directives,
          endToken: _currentToken,
          featureSet: _featureSet,
        );
      }
    }
    return astFactory.compilationUnit(
      beginToken: firstToken,
      scriptTag: scriptTag,
      directives: directives,
      endToken: _currentToken,
      featureSet: _featureSet,
    );
  }

  /// 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;
    List<EnumConstantDeclaration> constants = <EnumConstantDeclaration>[];
    Token rightBracket;
    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 _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);
    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;
    TypeAnnotation type;
    Keyword keyword = _currentToken.keyword;
    if (keyword == Keyword.FINAL || keyword == Keyword.CONST) {
      keywordToken = getAndAdvance();
      if (_isTypedIdentifier(_currentToken)) {
        type = parseTypeAnnotation(false);
      }
    } else if (keyword == Keyword.VAR) {
      keywordToken = getAndAdvance();
    } else if (_isTypedIdentifier(_currentToken)) {
      type = parseTypeAnnotation(false);
    } else if (inFunctionType && _matchesIdentifier()) {
      type = parseTypeAnnotation(false);
    } else if (!optional) {
      // If there is a valid type immediately following an unexpected token,
      // then report and skip the unexpected token.
      Token next = _peek();
      Keyword nextKeyword = next.keyword;
      if (nextKeyword == Keyword.FINAL ||
          nextKeyword == Keyword.CONST ||
          nextKeyword == Keyword.VAR ||
          _isTypedIdentifier(next) ||
          inFunctionType && _tokenMatchesIdentifier(next)) {
        _reportErrorForCurrentToken(
            ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken.lexeme]);
        _advance();
        return parseFinalConstVarOrType(optional,
            inFunctionType: inFunctionType);
      }
      _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;
    }
    return 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);
        parameter.identifier = createSyntheticIdentifier(isDeclaration: true);
      }
      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);
        parameter.identifier = createSyntheticIdentifier(isDeclaration: true);
      }
      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);
        parameter.identifier = createSyntheticIdentifier(isDeclaration: true);
      }
      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;
      if (_matchesKeyword(Keyword.AWAIT)) {
        awaitKeyword = getAndAdvance();
      }
      Token forKeyword = _expectKeyword(Keyword.FOR);
      Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
      VariableDeclarationList variableList;
      Expression initialization;
      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;
          SimpleIdentifier identifier;
          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();
          ForLoopParts forLoopParts;
          if (loopVariable == null) {
            forLoopParts = astFactory.forEachPartsWithIdentifier(
                identifier: identifier,
                inKeyword: inKeyword,
                iterable: iterator);
          } else {
            forLoopParts = astFactory.forEachPartsWithDeclaration(
                loopVariable: loopVariable,
                inKeyword: inKeyword,
                iterable: iterator);
          }
          return astFactory.forStatement(
              forKeyword: forKeyword,
              leftParenthesis: leftParenthesis,
              forLoopParts: forLoopParts,
              rightParenthesis: rightParenthesis,
              body: body);
        }
      }
      if (awaitKeyword != null) {
        _reportErrorForToken(
            ParserErrorCode.INVALID_AWAIT_IN_FOR, awaitKeyword);
      }
      Token leftSeparator = _expect(TokenType.SEMICOLON);
      Expression condition;
      if (!_matches(TokenType.SEMICOLON)) {
        condition = parseExpression2();
      }
      Token rightSeparator = _expect(TokenType.SEMICOLON);
      List<Expression> updaters;
      if (!_matches(TokenType.CLOSE_PAREN)) {
        updaters = parseExpressionList();
      }
      ForLoopParts forLoopParts;
      if (variableList != null) {
        forLoopParts = astFactory.forPartsWithDeclarations(
            variables: variableList,
            leftSeparator: leftSeparator,
            condition: condition,
            rightSeparator: rightSeparator,
            updaters: updaters);
      } else {
        forLoopParts = astFactory.forPartsWithExpression(
            initialization: initialization,
            leftSeparator: leftSeparator,
            condition: condition,
            rightSeparator: rightSeparator,
            updaters: updaters);
      }
      Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
      Statement body = parseStatement2();
      return astFactory.forStatement(
          forKeyword: forKeyword,
          leftParenthesis: leftParenthesis,
          forLoopParts: forLoopParts,
          rightParenthesis: rightParenthesis,
          body: 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;
      Token star;
      bool foundAsync = false;
      bool foundSync = false;
      if (type.isKeyword) {
        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;
          } 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;
        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;
        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;
    bool isGetter = false;
    Keyword keyword = _currentToken.keyword;
    SimpleIdentifier name;
    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;
      isGetter = false;
    } else {
      name = parseSimpleIdentifier(isDeclaration: true);
    }
    TypeParameterList typeParameters = _parseGenericMethodTypeParameters();
    FormalParameterList parameters;
    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;
    if (_matchesKeyword(Keyword.FUNCTION)) {
      functionKeyword = getAndAdvance();
    } else if (_matchesIdentifier()) {
      _reportErrorForCurrentToken(ParserErrorCode.NAMED_FUNCTION_TYPE);
    } else {
      _reportErrorForCurrentToken(ParserErrorCode.MISSING_FUNCTION_KEYWORD);
    }
    TypeParameterList typeParameters;
    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;
    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;
    Statement elseStatement;
    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);
      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;
    Token asToken;
    SimpleIdentifier prefix;
    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)* ','?)? '}'
  SetOrMapLiteral parseMapLiteral(
      Token modifier, TypeArgumentList typeArguments) {
    Token leftBracket = getAndAdvance();
    if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
      return astFactory.setOrMapLiteral(
          constKeyword: modifier,
          typeArguments: typeArguments,
          leftBracket: leftBracket,
          rightBracket: getAndAdvance());
    }
    bool wasInInitializer = _inInitializer;
    _inInitializer = false;
    try {
      List<MapLiteralEntry> entries = <MapLiteralEntry>[parseMapLiteralEntry()];
      while (_optional(TokenType.COMMA)) {
        if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
          return astFactory.setOrMapLiteral(
              constKeyword: modifier,
              typeArguments: typeArguments,
              leftBracket: leftBracket,
              elements: entries,
              rightBracket: getAndAdvance());
        }
        entries.add(parseMapLiteralEntry());
      }
      Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
      return astFactory.setOrMapLiteral(
          constKeyword: modifier,
          typeArguments: typeArguments,
          leftBracket: leftBracket,
          elements: entries,
          rightBracket: 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 = 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.isKeyword && !_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
            ])) {
          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
          ])) {
        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 && statement.forLoopParts is ForParts)) {
        _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) ||
          _tokenMatchesKeyword(next, Keyword.VOID) ||
          _tokenMatchesIdentifier(next)) {
        covariantKeyword = getAndAdvance();
      }
    }
    FinalConstVarOrType holder = parseFinalConstVarOrType(!inFunctionType,
        inFunctionType: inFunctionType);
    Token thisKeyword;
    Token period;
    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);
        }
        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);
      } 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 &&
        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
  ///       | argumentPart
  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 if (enableOptionalNewAndConst &&
            operand is Identifier &&
            _isLikelyNamedInstanceCreation()) {
          TypeArgumentList typeArguments = _parseOptionalTypeArguments();
          Token period = _expect(TokenType.PERIOD);
          SimpleIdentifier name = parseSimpleIdentifier();
          ArgumentList argumentList = parseArgumentList();
          TypeName typeName = astFactory.typeName(operand, typeArguments);
          operand = astFactory.instanceCreationExpression(null,
              astFactory.constructorName(typeName, period, name), 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;
      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) {
      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;
      try {
        value = int.parse(token.lexeme);
      } 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) {
      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;
    SimpleIdentifier constructorName;
    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, parseTypeNotVoid(true));
    } else if (keyword == Keyword.IS) {
      Token isOperator = getAndAdvance();
      Token notOperator;
      if (_matches(TokenType.BANG)) {
        notOperator = getAndAdvance();
      }
      TypeAnnotation type = parseTypeNotVoid(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 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 _TooDeepTreeError();
    }
    _treeDepth++;
    try {
      List<Label> labels;
      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;
    SimpleIdentifier constructorName;
    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 = 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;
      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;
    while (_matchesKeyword(Keyword.ON) || _matchesKeyword(Keyword.CATCH)) {
      Token onKeyword;
      TypeName exceptionType;
      if (_matchesKeyword(Keyword.ON)) {
        onKeyword = getAndAdvance();
        exceptionType = parseTypeNotVoid(false);
      }
      Token catchKeyword;
      Token leftParenthesis;
      SimpleIdentifier exceptionParameter;
      Token comma;
      SimpleIdentifier stackTraceParameter;
      Token rightParenthesis;
      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;
    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;
    if (_atGenericFunctionTypeAfterReturnType(_currentToken)) {
      // Generic function type with no return type.
      type = parseGenericFunctionTypeAfterReturnType(null);
    } else {
      type = parseTypeWithoutFunction(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 which is not void and is not a function type. Return the type
  /// that was parsed.
  ///
  ///     typeNotVoidWithoutFunction ::=
  ///         qualified typeArguments?
  // TODO(eernst): Rename this to `parseTypeNotVoidWithoutFunction`?
  // Apparently,  it was named `parseTypeName` before type arguments existed.
  TypeName parseTypeName(bool inExpression) {
    return _parseTypeName(inExpression);
  }

  /// Parse a type which is not `void`.
  ///
  ///     typeNotVoid ::=
  ///         functionType
  ///       | typeNotVoidWithoutFunction
  TypeAnnotation parseTypeNotVoid(bool inExpression) {
    TypeAnnotation type;
    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 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 (_matchesKeyword(Keyword.EXTENDS)) {
      Token keyword = getAndAdvance();
      TypeAnnotation bound = parseTypeNotVoid(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 type which is not a function type.
  ///
  ///     typeWithoutFunction ::=
  ///         `void`
  ///       | typeNotVoidWithoutFunction
  TypeAnnotation parseTypeWithoutFunction(bool inExpression) {
    if (_currentToken.keyword == Keyword.VOID) {
      return astFactory.typeName(
          astFactory.simpleIdentifier(getAndAdvance()), null);
    } else {
      return parseTypeName(inExpression);
    }
  }

  /// 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 = 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, parseAssignableExpression(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;
    Expression initializer;
    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);
      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;
    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);
      if (next == null) {
        return null;
      }
    }
    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 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;
    if (_atGenericFunctionTypeAfterReturnType(startToken)) {
      // Generic function type with no return type.
      next = skipGenericFunctionTypeAfterReturnType(startToken);
    } else {
      next = skipTypeWithoutFunction(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)) {
      return null;
    }
    token = skipTypeAnnotation(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 = skipTypeAnnotation(token.next);
      if (token == null) {
        return null;
      }
    }
    if (token.type == TokenType.GT) {
      return token.next;
    } else if (token.type == TokenType.GT_GT) {
      Token second = 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;
  }

  /// Parse a typeWithoutFunction, starting at the [startToken], without
  /// actually creating a TypeAnnotation or changing the current token. Return
  /// the token following the typeWithoutFunction that was parsed, or `null` if
  /// the given token is not the first token in a valid typeWithoutFunction.
  ///
  /// This method must be kept in sync with [parseTypeWithoutFunction].
  Token skipTypeWithoutFunction(Token startToken) {
    if (startToken.keyword == Keyword.VOID) {
      return startToken.next;
    } else {
      return skipTypeName(startToken);
    }
  }

  /// 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;
  }

  void _configureFeatures(FeatureSet featureSet) {
    if (featureSet.isEnabled(Feature.control_flow_collections)) {
      throw UnimplementedError('control_flow_collections experiment'
          ' not supported by analyzer parser');
    }
    if (featureSet.isEnabled(Feature.non_nullable)) {
      throw UnimplementedError(
          'non-nullable experiment not supported by analyzer parser');
    }
    if (featureSet.isEnabled(Feature.spread_collections)) {
      throw UnimplementedError(
          'spread_collections experiment not supported by analyzer parser');
    }
    if (featureSet.isEnabled(Feature.triple_shift)) {
      throw UnimplementedError('triple_shift experiment'
          ' not supported by analyzer parser');
    }
    _featureSet = featureSet;
  }

  /// 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 = skipTypeAnnotation(_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(SyntheticKeywordToken(keyword, _currentToken.offset));

  /// Return a synthetic token with the given [type].
  Token _createSyntheticToken(TokenType type) =>
      _injectToken(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 preceded the token.
  Token _createToken(Token token, TokenType type, {bool isBegin = false}) {
    CommentToken comments = token.precedingComments;
    if (comments == null) {
      if (isBegin) {
        return BeginToken(type, token.offset);
      }
      return Token(type, token.offset);
    } else if (isBegin) {
      return BeginToken(type, token.offset, comments);
    }
    return Token(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.lexeme]);
    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;
  }

  /// 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;
  }

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

  /// Return `true` if it looks like we have found the invocation of a named
  /// constructor following the name of the type:
  /// ```
  /// typeArguments? '.' identifier '('
  /// ```
  bool _isLikelyNamedInstanceCreation() {
    Token token = skipTypeArgumentList(_currentToken);
    if (token != null && _tokenMatches(token, TokenType.PERIOD)) {
      token = skipSimpleIdentifier(token.next);
      if (token != null && _tokenMatches(token, TokenType.OPEN_PAREN)) {
        return true;
      }
    }
    return false;
  }

  /// 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 = skipTypeAnnotation(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 (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;
  }

  /// Return `true` if the given [expression] is a primary expression that is
  /// allowed to be an assignable expression without any assignable selector.
  bool _isValidAssignableExpression(Expression expression) {
    if (expression is SimpleIdentifier) {
      return true;
    } else if (expression is PropertyAccess) {
      return expression.target is SuperExpression;
    } else if (expression is IndexExpression) {
      return expression.target is SuperExpression;
    }
    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 = 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 = 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 = Token(TokenType.GT, offset + 1);
      Token third = 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);

  /// 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();
      if (_matches(TokenType.CLOSE_PAREN)) {
        comma;
      } else {
        message = parseExpression2();
        if (_matches(TokenType.COMMA)) {
          getAndAdvance();
        }
      }
    }
    Token rightParen = _expect(TokenType.CLOSE_PAREN);
    return astFactory.assertInitializer(
        keyword, leftParen, expression, comma, message, rightParen);
  }

  /// 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;
    if (_matchesKeyword(Keyword.WITH)) {
      withClause = parseWithClause();
    } else {
      _reportErrorForCurrentToken(
          ParserErrorCode.EXPECTED_TOKEN, [Keyword.WITH.lexeme]);
    }
    ImplementsClause implementsClause;
    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;
    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;
    List<ConstructorInitializer> initializers;
    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 (_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;
    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();
    }
    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;
    Token rightSquareBracket;
    Token leftCurlyBracket;
    Token rightCurlyBracket;
    ParameterKind kind = ParameterKind.REQUIRED;
    bool firstParameter = true;
    bool reportedMultiplePositionalGroups = false;
    bool reportedMultipleNamedGroups = false;
    bool reportedMixedGroups = false;
    bool wasOptionalParameter = false;
    Token initialToken;
    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;
            // Skip over synthetic closer inserted by fasta
            // since we've already reported an error
            if (_currentToken.type == TokenType.CLOSE_CURLY_BRACKET &&
                _currentToken.isSynthetic) {
              _advance();
            }
          } 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;
            // Skip over synthetic closer inserted by fasta
            // since we've already reported an error
            if (_currentToken.type == TokenType.CLOSE_SQUARE_BRACKET &&
                _currentToken.isSynthetic) {
              _advance();
            }
          } 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;
    if (hasReturnTypeInTypeAlias) {
      returnType = parseTypeAnnotation(false);
    }
    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
    TypeParameterList typeParameters;
    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));
    }
  }

  /// 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)) {
      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(
          _currentToken.type == TokenType.EQ_EQ_EQ
              ? ParserErrorCode.INVALID_OPERATOR
              : 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() {
    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 parseTypeAnnotation(false);
      }
      Token next2 = next.next;
      Token next3 = next2.next;
      if (_tokenMatches(next, TokenType.PERIOD) &&
          _tokenMatchesIdentifier(next2) &&
          (_tokenMatchesIdentifier(next3) ||
              _tokenMatches(next3, TokenType.LT))) {
        return parseTypeAnnotation(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)) {
      return parseTypeArgumentList();
    }
    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 (_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)) {
      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 == _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;
        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() {
    return parseTypeAnnotation(false);
  }

  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();
    return astFactory.typeName(typeName, typeArguments);
  }

  /// 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.lexeme ||
        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 = 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 =
            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(
        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(AnalysisError(_source, token.offset, math.max(token.length, 1),
        errorCode, arguments));
  }

  /// 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 skipTypeAnnotation(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 preceded 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 = 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 = 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 =
        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) || token.type.isKeyword;

  /// 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 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.MODIFIER_OUT_OF_ORDER, externalKeyword);
    }
    if (externalKeyword != null &&
        factoryKeyword != null &&
        factoryKeyword.offset < externalKeyword.offset) {
      _reportErrorForToken(
          ParserErrorCode.MODIFIER_OUT_OF_ORDER, 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.MODIFIER_OUT_OF_ORDER, covariantKeyword);
      }
      if (finalKeyword != null) {
        _reportErrorForToken(ParserErrorCode.CONST_AND_FINAL, finalKeyword);
      }
      if (varKeyword != null) {
        _reportErrorForToken(ParserErrorCode.MODIFIER_OUT_OF_ORDER, varKeyword);
      }
      if (staticKeyword != null && constKeyword.offset < staticKeyword.offset) {
        _reportErrorForToken(
            ParserErrorCode.MODIFIER_OUT_OF_ORDER, 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.MODIFIER_OUT_OF_ORDER, staticKeyword);
      }
    } else if (varKeyword != null) {
      if (staticKeyword != null && varKeyword.offset < staticKeyword.offset) {
        _reportErrorForToken(
            ParserErrorCode.MODIFIER_OUT_OF_ORDER, staticKeyword);
      }
      if (covariantKeyword != null &&
          varKeyword.offset < covariantKeyword.offset) {
        _reportErrorForToken(
            ParserErrorCode.MODIFIER_OUT_OF_ORDER, 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.MODIFIER_OUT_OF_ORDER, 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.MODIFIER_OUT_OF_ORDER, 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 {}
