// 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: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/analysis/experiments.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:front_end/src/fasta/parser/identifier_context.dart' as fasta;
import 'package:front_end/src/fasta/parser/member_kind.dart' as fasta;
import 'package:front_end/src/fasta/parser/parser.dart' as fasta;
import 'package:front_end/src/fasta/parser/type_info.dart' as fasta;
import 'package:front_end/src/fasta/scanner.dart' as fasta;

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 = new StringBuffer();
    bool needsSpace = _appendKeyword(buffer, false, abstractKeyword);
    needsSpace = _appendKeyword(buffer, needsSpace, constKeyword);
    needsSpace = _appendKeyword(buffer, needsSpace, externalKeyword);
    needsSpace = _appendKeyword(buffer, needsSpace, factoryKeyword);
    needsSpace = _appendKeyword(buffer, needsSpace, finalKeyword);
    needsSpace = _appendKeyword(buffer, needsSpace, staticKeyword);
    _appendKeyword(buffer, needsSpace, varKeyword);
    return buffer.toString();
  }

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

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

  static String _AWAIT = Keyword.AWAIT.lexeme;

  static String _HIDE = Keyword.HIDE.lexeme;

  static String _SHOW = Keyword.SHOW.lexeme;

  static String SYNC = Keyword.SYNC.lexeme;

  static 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 =
      const 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].
  ///
  /// In a future major version release of the analyzer, the [featureSet]
  /// argument will be required.
  factory Parser(Source source, AnalysisErrorListener errorListener,
      {bool useFasta, FeatureSet featureSet}) {
    if (useFasta ?? Parser.useFasta) {
      var parser = new _Parser2(source, errorListener, allowNativeClause: true);
      if (featureSet != null) {
        parser.configureFeatures(featureSet);
      }
      return parser;
    } else {
      return new 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].
  void set currentToken(Token token) {
    this._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
  void set enableAssertInitializer(bool enable) {}

  /// Enables or disables parsing of control flow collections.
  @Deprecated('Pass a FeatureSet to the constructor instead')
  void set enableControlFlowCollections(bool value) {
    if (value) {
      throw new UnimplementedError('control_flow_collections experiment'
          ' not supported by analyzer parser');
    }
  }

  /// Enables or disables non-nullable by default.
  @Deprecated('Pass a FeatureSet to the constructor instead')
  void set enableNonNullable(bool value) {
    if (value) {
      throw new UnimplementedError(
          'non-nullable experiment not supported by analyzer parser');
    }
  }

  /// 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.
  void set enableOptionalNewAndConst(bool enable) {
    _enableOptionalNewAndConst = enable;
  }

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

  /// Enables or disables parsing of spread collections.
  @Deprecated('Pass a FeatureSet to the constructor instead')
  void set enableSpreadCollections(bool value) {
    if (value) {
      throw new UnimplementedError(
          'spread_collections experiment not supported by analyzer parser');
    }
  }

  /// Enables or disables parsing of the triple shift operators.
  @Deprecated('Pass a FeatureSet to the constructor instead')
  void set enableTripleShift(bool value) {
    if (value) {
      throw new UnimplementedError('triple_shift experiment'
          ' not supported by analyzer parser');
    }
  }

  /// 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
  void 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
  void set parseAsync(bool parseAsync) {}

  @deprecated
  bool get parseConditionalDirectives => true;

  @deprecated
  void set parseConditionalDirectives(bool value) {}

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

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

  /// Configures the parser appropriately for the given [featureSet].
  @Deprecated('Pass a FeatureSet to the constructor instead')
  void configureFeatures(FeatureSet featureSet) {
    _configureFeatures(featureSet);
  }

  /// 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(new SyntheticStringToken(
          TokenType.IDENTIFIER, _currentToken.lexeme, _currentToken.offset));
    } else {
      syntheticToken = _createSyntheticToken(TokenType.IDENTIFIER);
    }
    return astFactory.simpleIdentifier(syntheticToken,
        isDeclaration: isDeclaration);
  }

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

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

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

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

  /// Return `true` if the current token is the first token in an initialized
  /// variable declaration rather than an expression. This method assumes that
  /// we have already skipped past any metadata that might be associated with
  /// the declaration.
  ///
  ///     initializedVariableDeclaration ::=
  ///         declaredIdentifier ('=' expression)? (',' initializedIdentifier)*
  ///
  ///     declaredIdentifier ::=
  ///         metadata finalConstVarOrType identifier
  ///
  ///     finalConstVarOrType ::=
  ///         'final' type?
  ///       | 'const' type?
  ///       | 'var'
  ///       | type
  ///
  ///     type ::=
  ///         qualified typeArguments?
  ///
  ///     initializedIdentifier ::=
  ///         identifier ('=' expression)?
  bool isInitializedVariableDeclaration() {
    Keyword keyword = _currentToken.keyword;
    if (keyword == Keyword.FINAL ||
        keyword == Keyword.VAR ||
        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 = null;
    SimpleIdentifier constructorName = null;
    if (_matches(TokenType.PERIOD)) {
      period = getAndAdvance();
      constructorName = parseSimpleIdentifier();
    }
    ArgumentList arguments = null;
    if (_matches(TokenType.OPEN_PAREN)) {
      arguments = parseArgumentList();
    }
    return astFactory.annotation(
        atSign, name, period, constructorName, arguments);
  }

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

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

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

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

  /// Parse an assert statement. Return the assert statement.
  ///
  /// This method assumes that the current token matches `Keyword.ASSERT`.
  ///
  ///     assertStatement ::=
  ///         'assert' '(' expression [',' expression] ')' ';'
  AssertStatement parseAssertStatement() {
    Token keyword = getAndAdvance();
    Token leftParen = _expect(TokenType.OPEN_PAREN);
    Expression expression = parseExpression2();
    Token comma;
    Expression message;
    if (_matches(TokenType.COMMA)) {
      comma = getAndAdvance();
      if (_matches(TokenType.CLOSE_PAREN)) {
        comma = null;
      } 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.indexExpressionForTarget(
            prefix, leftBracket, index, rightBracket);
      } finally {
        _inInitializer = wasInInitializer;
      }
    } else {
      bool isQuestionPeriod = type == TokenType.QUESTION_PERIOD;
      if (type == TokenType.PERIOD || isQuestionPeriod) {
        if (isQuestionPeriod && !allowConditional) {
          _reportErrorForCurrentToken(
              ParserErrorCode.INVALID_OPERATOR_FOR_SUPER,
              [_currentToken.lexeme]);
        }
        Token operator = getAndAdvance();
        return astFactory.propertyAccess(
            prefix, operator, parseSimpleIdentifier());
      } else if (type == TokenType.INDEX) {
        _splitIndex();
        Token leftBracket = getAndAdvance();
        Expression index = parseSimpleIdentifier();
        Token rightBracket = getAndAdvance();
        return astFactory.indexExpressionForTarget(
            prefix, leftBracket, index, rightBracket);
      } else {
        if (!optional) {
          // Report the missing selector.
          _reportErrorForCurrentToken(
              ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR);
        }
        return prefix;
      }
    }
  }

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

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

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

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

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

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

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

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

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

  /// Parse a class member. The [className] is the name of the class containing
  /// the member being parsed. Return the class member that was parsed, or
  /// `null` if what was found was not a valid class member.
  ///
  ///     classMemberDefinition ::=
  ///         declaration ';'
  ///       | methodSignature functionBody
  ClassMember parseClassMember(String className) {
    CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
    Modifiers modifiers = parseModifiers();
    Keyword keyword = _currentToken.keyword;
    if (keyword == Keyword.VOID ||
        _atGenericFunctionTypeAfterReturnType(_currentToken)) {
      TypeAnnotation returnType;
      if (keyword == Keyword.VOID) {
        if (_atGenericFunctionTypeAfterReturnType(_peek())) {
          returnType = parseTypeAnnotation(false);
        } else {
          returnType = astFactory.typeName(
              astFactory.simpleIdentifier(getAndAdvance()), null);
        }
      } else {
        returnType = parseTypeAnnotation(false);
      }
      keyword = _currentToken.keyword;
      Token next = _peek();
      bool isFollowedByIdentifier = _tokenMatchesIdentifier(next);
      if (keyword == Keyword.GET && isFollowedByIdentifier) {
        _validateModifiersForGetterOrSetterOrMethod(modifiers);
        return parseGetter(commentAndMetadata, modifiers.externalKeyword,
            modifiers.staticKeyword, returnType);
      } else if (keyword == Keyword.SET && isFollowedByIdentifier) {
        _validateModifiersForGetterOrSetterOrMethod(modifiers);
        return parseSetter(commentAndMetadata, modifiers.externalKeyword,
            modifiers.staticKeyword, returnType);
      } else if (keyword == Keyword.OPERATOR &&
          (_isOperator(next) || 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 = null;
      SimpleIdentifier methodName = parseSimpleIdentifier(isDeclaration: true);
      TypeParameterList typeParameters = null;
      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 = null;
      FormalParameterList parameters = parseFormalParameterList();
      if (methodName.name == className) {
        _reportErrorForNode(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, type);
        return _parseConstructor(
            commentAndMetadata,
            modifiers.externalKeyword,
            _validateModifiersForConstructor(modifiers),
            modifiers.factoryKeyword,
            astFactory.simpleIdentifier(methodName.token, isDeclaration: true),
            null,
            null,
            parameters);
      }
      _validateModifiersForGetterOrSetterOrMethod(modifiers);
      _validateFormalParameterList(parameters);
      return _parseMethodDeclarationAfterParameters(
          commentAndMetadata,
          modifiers.externalKeyword,
          modifiers.staticKeyword,
          type,
          methodName,
          typeParameters,
          parameters);
    } else if (_tokenMatches(next, TokenType.LT)) {
      return _parseMethodDeclarationAfterReturnType(commentAndMetadata,
          modifiers.externalKeyword, modifiers.staticKeyword, type);
    } else if (_tokenMatches(next, TokenType.OPEN_CURLY_BRACKET)) {
      // We have found "TypeName identifier {", and are guessing that this is a
      // getter without the keyword 'get'.
      _validateModifiersForGetterOrSetterOrMethod(modifiers);
      _reportErrorForCurrentToken(ParserErrorCode.MISSING_GET);
      _currentToken = _injectToken(
          new SyntheticKeywordToken(Keyword.GET, _currentToken.offset));
      return parseGetter(commentAndMetadata, modifiers.externalKeyword,
          modifiers.staticKeyword, type);
    }
    return parseInitializedIdentifierList(
        commentAndMetadata,
        modifiers.staticKeyword,
        modifiers.covariantKeyword,
        _validateModifiersForField(modifiers),
        type);
  }

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

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

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

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

  /// Parse all of the comment references occurring in the given array of
  /// documentation comments. The [tokens] are the comment tokens representing
  /// the documentation comments to be parsed. Return the comment references
  /// that were parsed.
  ///
  ///     commentReference ::=
  ///         '[' 'new'? qualified ']' libraryReference?
  ///
  ///     libraryReference ::=
  ///          '(' stringLiteral ')'
  List<CommentReference> parseCommentReferences(
      List<DocumentationCommentToken> tokens) {
    List<CommentReference> references = <CommentReference>[];
    bool isInGitHubCodeBlock = false;
    for (DocumentationCommentToken token in tokens) {
      String comment = token.lexeme;
      // Skip GitHub code blocks.
      // https://help.github.com/articles/creating-and-highlighting-code-blocks/
      if (tokens.length != 1) {
        if (comment.indexOf('```') != -1) {
          isInGitHubCodeBlock = !isInGitHubCodeBlock;
        }
        if (isInGitHubCodeBlock) {
          continue;
        }
      }
      // Remove GitHub include code.
      comment = _removeGitHubInlineCode(comment);
      // Find references.
      int length = comment.length;
      List<List<int>> codeBlockRanges = _getCodeBlockRanges(comment);
      int leftIndex = comment.indexOf('[');
      while (leftIndex >= 0 && leftIndex + 1 < length) {
        List<int> range = _findRange(codeBlockRanges, leftIndex);
        if (range == null) {
          int nameOffset = token.offset + leftIndex + 1;
          int rightIndex = comment.indexOf(']', leftIndex);
          if (rightIndex >= 0) {
            int firstChar = comment.codeUnitAt(leftIndex + 1);
            if (firstChar != 0x27 && firstChar != 0x22) {
              if (_isLinkText(comment, rightIndex)) {
                // TODO(brianwilkerson) Handle the case where there's a library
                // URI in the link text.
              } else {
                CommentReference reference = parseCommentReference(
                    comment.substring(leftIndex + 1, rightIndex), nameOffset);
                if (reference != null) {
                  references.add(reference);
                }
              }
            }
          } else {
            // terminating ']' is not typed yet
            int charAfterLeft = comment.codeUnitAt(leftIndex + 1);
            Token nameToken;
            if (Character.isLetterOrDigit(charAfterLeft)) {
              int nameEnd = StringUtilities.indexOfFirstNotLetterDigit(
                  comment, leftIndex + 1);
              String name = comment.substring(leftIndex + 1, nameEnd);
              nameToken =
                  new StringToken(TokenType.IDENTIFIER, name, nameOffset);
            } else {
              nameToken = new SyntheticStringToken(
                  TokenType.IDENTIFIER, '', nameOffset);
            }
            nameToken.setNext(new 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 = null;
    if (_matches(TokenType.SCRIPT_TAG)) {
      scriptTag = astFactory.scriptTag(getAndAdvance());
    }
    //
    // Even though all directives must appear before declarations and must occur
    // in a given order, we allow directives and declarations to occur in any
    // order so that we can recover better.
    //
    bool libraryDirectiveFound = false;
    bool partOfDirectiveFound = false;
    bool partDirectiveFound = false;
    bool directiveFoundAfterDeclaration = false;
    List<Directive> directives = <Directive>[];
    List<CompilationUnitMember> declarations = <CompilationUnitMember>[];
    Token memberStart = _currentToken;
    TokenType type = _currentToken.type;
    while (type != TokenType.EOF) {
      CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
      Keyword keyword = _currentToken.keyword;
      TokenType nextType = _currentToken.next.type;
      if ((keyword == Keyword.IMPORT ||
              keyword == Keyword.EXPORT ||
              keyword == Keyword.LIBRARY ||
              keyword == Keyword.PART) &&
          nextType != TokenType.PERIOD &&
          nextType != TokenType.LT &&
          nextType != TokenType.OPEN_PAREN) {
        Directive parseDirective() {
          if (keyword == Keyword.IMPORT) {
            if (partDirectiveFound) {
              _reportErrorForCurrentToken(
                  ParserErrorCode.IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE);
            }
            return parseImportDirective(commentAndMetadata);
          } else if (keyword == Keyword.EXPORT) {
            if (partDirectiveFound) {
              _reportErrorForCurrentToken(
                  ParserErrorCode.EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE);
            }
            return parseExportDirective(commentAndMetadata);
          } else if (keyword == Keyword.LIBRARY) {
            if (libraryDirectiveFound) {
              _reportErrorForCurrentToken(
                  ParserErrorCode.MULTIPLE_LIBRARY_DIRECTIVES);
            } else {
              if (directives.length > 0) {
                _reportErrorForCurrentToken(
                    ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST);
              }
              libraryDirectiveFound = true;
            }
            return parseLibraryDirective(commentAndMetadata);
          } else if (keyword == Keyword.PART) {
            if (_tokenMatchesKeyword(_peek(), Keyword.OF)) {
              partOfDirectiveFound = true;
              return _parsePartOfDirective(commentAndMetadata);
            } else {
              partDirectiveFound = true;
              return _parsePartDirective(commentAndMetadata);
            }
          } else {
            // Internal error: this method should not have been invoked if the
            // current token was something other than one of the above.
            throw new StateError(
                "parseDirective invoked in an invalid state (currentToken = $_currentToken)");
          }
        }

        Directive directive = parseDirective();
        if (declarations.length > 0 && !directiveFoundAfterDeclaration) {
          _reportErrorForToken(ParserErrorCode.DIRECTIVE_AFTER_DECLARATION,
              directive.beginToken);
          directiveFoundAfterDeclaration = true;
        }
        directives.add(directive);
      } else if (type == TokenType.SEMICOLON) {
        // TODO(brianwilkerson) Consider moving this error detection into
        // _parseCompilationUnitMember (in the places where EXPECTED_EXECUTABLE
        // is being generated).
        _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
            [_currentToken.lexeme]);
        _advance();
      } else {
        CompilationUnitMember member;
        try {
          member = parseCompilationUnitMember(commentAndMetadata);
        } on _TooDeepTreeError {
          _reportErrorForToken(ParserErrorCode.STACK_OVERFLOW, _currentToken);
          Token eof = new Token.eof(0);
          return astFactory.compilationUnit2(
              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.compilationUnit2(
        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;
      if (keyword == null) {
        keyword = modifiers.finalKeyword;
      }
      if (keyword == null) {
        keyword = modifiers.constKeyword;
      }
      if (keyword != null) {
        //
        // We appear to have found an incomplete top-level variable declaration.
        //
        _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
        VariableDeclaration variable = astFactory.variableDeclaration(
            createSyntheticIdentifier(), null, null);
        List<VariableDeclaration> variables = <VariableDeclaration>[variable];
        return astFactory.topLevelVariableDeclaration(
            commentAndMetadata.comment,
            commentAndMetadata.metadata,
            astFactory.variableDeclarationList(
                null, null, keyword, null, variables),
            _expect(TokenType.SEMICOLON));
      }
      _reportErrorForToken(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken);
      return null;
    } else if (_isPeekGenericTypeParametersAndOpenParen()) {
      return parseFunctionDeclaration(
          commentAndMetadata, modifiers.externalKeyword, null);
    } else if (_tokenMatches(next, TokenType.OPEN_PAREN)) {
      TypeName returnType = null;
      _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 = null;
    StringLiteral value = null;
    if (_matches(TokenType.EQ_EQ)) {
      equalToken = getAndAdvance();
      value = parseStringLiteral();
      if (value is StringInterpolation) {
        _reportErrorForNode(
            ParserErrorCode.INVALID_LITERAL_IN_CONFIGURATION, value);
      }
    }
    Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
    StringLiteral libraryUri = _parseUri();
    return astFactory.configuration(ifKeyword, leftParenthesis, name,
        equalToken, value, rightParenthesis, libraryUri);
  }

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

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

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

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

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

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

  /// Parse the script tag and directives in a compilation unit until the first
  /// non-directive is encountered. Return the compilation unit that was parsed.
  ///
  ///     compilationUnit ::=
  ///         scriptTag? directive*
  CompilationUnit parseDirectives2() {
    Token firstToken = _currentToken;
    ScriptTag scriptTag = null;
    if (_matches(TokenType.SCRIPT_TAG)) {
      scriptTag = astFactory.scriptTag(getAndAdvance());
    }
    List<Directive> directives = <Directive>[];
    while (!_matches(TokenType.EOF)) {
      CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
      Keyword keyword = _currentToken.keyword;
      TokenType type = _peek().type;
      if ((keyword == Keyword.IMPORT ||
              keyword == Keyword.EXPORT ||
              keyword == Keyword.LIBRARY ||
              keyword == Keyword.PART) &&
          type != TokenType.PERIOD &&
          type != TokenType.LT &&
          type != TokenType.OPEN_PAREN) {
        directives.add(parseDirective(commentAndMetadata));
      } else if (_matches(TokenType.SEMICOLON)) {
        _advance();
      } else {
        while (!_matches(TokenType.EOF)) {
          _advance();
        }
        return astFactory.compilationUnit2(
            beginToken: firstToken,
            scriptTag: scriptTag,
            directives: directives,
            endToken: _currentToken,
            featureSet: _featureSet);
      }
    }
    return astFactory.compilationUnit2(
        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 = null;
    List<EnumConstantDeclaration> constants = <EnumConstantDeclaration>[];
    Token rightBracket = null;
    if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
      leftBracket = getAndAdvance();
      if (_matchesIdentifier() || _matches(TokenType.AT)) {
        constants.add(_parseEnumConstantDeclaration());
      } else if (_matches(TokenType.COMMA) &&
          _tokenMatchesIdentifier(_peek())) {
        constants.add(_parseEnumConstantDeclaration());
        _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
      } else {
        constants.add(_parseEnumConstantDeclaration());
        _reportErrorForCurrentToken(ParserErrorCode.EMPTY_ENUM_BODY);
      }
      while (_optional(TokenType.COMMA)) {
        if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
          break;
        }
        constants.add(_parseEnumConstantDeclaration());
      }
      rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
    } else {
      leftBracket = _createSyntheticToken(TokenType.OPEN_CURLY_BRACKET);
      rightBracket = _createSyntheticToken(TokenType.CLOSE_CURLY_BRACKET);
      _reportErrorForCurrentToken(ParserErrorCode.MISSING_ENUM_BODY);
    }
    return astFactory.enumDeclaration(
        commentAndMetadata.comment,
        commentAndMetadata.metadata,
        keyword,
        name,
        leftBracket,
        constants,
        rightBracket);
  }

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

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

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

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

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

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

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

  /// Parse the 'final', 'const', 'var' or type preceding a variable
  /// declaration. The [optional] is `true` if the keyword and type are
  /// optional. Return the 'final', 'const', 'var' or type that was parsed.
  ///
  ///     finalConstVarOrType ::=
  ///         'final' type?
  ///       | 'const' type?
  ///       | 'var'
  ///       | type
  FinalConstVarOrType parseFinalConstVarOrType(bool optional,
      {bool inFunctionType: false}) {
    Token keywordToken = null;
    TypeAnnotation type = null;
    Keyword keyword = _currentToken.keyword;
    if (keyword == Keyword.FINAL || keyword == Keyword.CONST) {
      keywordToken = getAndAdvance();
      if (_isTypedIdentifier(_currentToken)) {
        type = parseTypeAnnotation(false);
      }
    } else 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 = null;
    }
    return new FinalConstVarOrType(keywordToken, type);
  }

  /// Parse a formal parameter. At most one of `isOptional` and `isNamed` can be
  /// `true`. The [kind] is the kind of parameter being expected based on the
  /// presence or absence of group delimiters. Return the formal parameter that
  /// was parsed.
  ///
  ///     defaultFormalParameter ::=
  ///         normalFormalParameter ('=' expression)?
  ///
  ///     defaultNamedParameter ::=
  ///         normalFormalParameter ('=' expression)?
  ///         normalFormalParameter (':' expression)?
  FormalParameter parseFormalParameter(ParameterKind kind,
      {bool inFunctionType: false}) {
    NormalFormalParameter parameter =
        parseNormalFormalParameter(inFunctionType: inFunctionType);
    TokenType type = _currentToken.type;
    if (type == TokenType.EQ) {
      if (inFunctionType) {
        _reportErrorForCurrentToken(
            ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE);
      }
      Token separator = getAndAdvance();
      Expression defaultValue = parseExpression2();
      if (kind == ParameterKind.REQUIRED) {
        _reportErrorForNode(
            ParserErrorCode.POSITIONAL_PARAMETER_OUTSIDE_GROUP, parameter);
        kind = ParameterKind.POSITIONAL;
      } else if (kind == ParameterKind.NAMED &&
          inFunctionType &&
          parameter.identifier == null) {
        _reportErrorForCurrentToken(
            ParserErrorCode.MISSING_NAME_FOR_NAMED_PARAMETER);
        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 = null;
      if (_matchesKeyword(Keyword.AWAIT)) {
        awaitKeyword = getAndAdvance();
      }
      Token forKeyword = _expectKeyword(Keyword.FOR);
      Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
      VariableDeclarationList variableList = null;
      Expression initialization = null;
      if (!_matches(TokenType.SEMICOLON)) {
        CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
        if (_matchesIdentifier() &&
            (_tokenMatchesKeyword(_peek(), Keyword.IN) ||
                _tokenMatches(_peek(), TokenType.COLON))) {
          SimpleIdentifier variableName = _parseSimpleIdentifierUnchecked();
          variableList = astFactory.variableDeclarationList(
              commentAndMetadata.comment,
              commentAndMetadata.metadata,
              null,
              null, <VariableDeclaration>[
            astFactory.variableDeclaration(variableName, null, null)
          ]);
        } else if (isInitializedVariableDeclaration()) {
          variableList =
              parseVariableDeclarationListAfterMetadata(commentAndMetadata);
        } else {
          initialization = parseExpression2();
        }
        TokenType type = _currentToken.type;
        if (_matchesKeyword(Keyword.IN) || type == TokenType.COLON) {
          if (type == TokenType.COLON) {
            _reportErrorForCurrentToken(ParserErrorCode.COLON_IN_PLACE_OF_IN);
          }
          DeclaredIdentifier loopVariable = null;
          SimpleIdentifier identifier = null;
          if (variableList == null) {
            // We found: <expression> 'in'
            _reportErrorForCurrentToken(
                ParserErrorCode.MISSING_VARIABLE_IN_FOR_EACH);
          } else {
            NodeList<VariableDeclaration> variables = variableList.variables;
            if (variables.length > 1) {
              _reportErrorForCurrentToken(
                  ParserErrorCode.MULTIPLE_VARIABLES_IN_FOR_EACH,
                  [variables.length.toString()]);
            }
            VariableDeclaration variable = variables[0];
            if (variable.initializer != null) {
              _reportErrorForCurrentToken(
                  ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH);
            }
            Token keyword = variableList.keyword;
            TypeAnnotation type = variableList.type;
            if (keyword != null || type != null) {
              loopVariable = astFactory.declaredIdentifier(
                  commentAndMetadata.comment,
                  commentAndMetadata.metadata,
                  keyword,
                  type,
                  astFactory.simpleIdentifier(variable.name.token,
                      isDeclaration: true));
            } else {
              if (commentAndMetadata.hasMetadata) {
                // TODO(jwren) metadata isn't allowed before the identifier in
                // "identifier in expression", add warning if commentAndMetadata
                // has content
              }
              identifier = variable.name;
            }
          }
          Token inKeyword = getAndAdvance();
          Expression iterator = parseExpression2();
          Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
          Statement body = parseStatement2();
          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 = null;
      if (!_matches(TokenType.SEMICOLON)) {
        condition = parseExpression2();
      }
      Token rightSeparator = _expect(TokenType.SEMICOLON);
      List<Expression> updaters = null;
      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 = null;
      Token star = null;
      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 = null;
          } else if (star != null) {
            _reportErrorForToken(
                ParserErrorCode.INVALID_STAR_AFTER_ASYNC, star);
          }
        }
        Token functionDefinition = getAndAdvance();
        if (_matchesKeyword(Keyword.RETURN)) {
          _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
              [_currentToken.lexeme]);
          _advance();
        }
        Expression expression = parseExpression2();
        Token semicolon = null;
        if (!inExpression) {
          semicolon = _expect(TokenType.SEMICOLON);
        }
        if (!_parseFunctionBodies) {
          return astFactory
              .emptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON));
        }
        return astFactory.expressionFunctionBody(
            keyword, functionDefinition, expression, semicolon);
      } else if (type == TokenType.OPEN_CURLY_BRACKET) {
        if (keyword != null) {
          if (foundSync && star == null) {
            _reportErrorForToken(
                ParserErrorCode.MISSING_STAR_AFTER_SYNC, keyword);
          }
        }
        if (!_parseFunctionBodies) {
          _skipBlock();
          return astFactory
              .emptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON));
        }
        return astFactory.blockFunctionBody(keyword, star, parseBlock());
      } else if (_matchesKeyword(Keyword.NATIVE)) {
        Token nativeToken = getAndAdvance();
        StringLiteral stringLiteral = null;
        if (_matches(TokenType.STRING)) {
          stringLiteral = _parseStringLiteralUnchecked();
        }
        return astFactory.nativeFunctionBody(
            nativeToken, stringLiteral, _expect(TokenType.SEMICOLON));
      } else {
        // Invalid function body
        _reportErrorForCurrentToken(emptyErrorCode);
        return astFactory
            .emptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON));
      }
    } finally {
      _inAsync = wasInAsync;
      _inGenerator = wasInGenerator;
      _inLoop = wasInLoop;
      _inSwitch = wasInSwitch;
    }
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  /// Parse a map literal. The [modifier] is the 'const' modifier appearing
  /// before the literal, or `null` if there is no modifier. The [typeArguments]
  /// is the type arguments that were declared, or `null` if there are no type
  /// arguments. Return the map literal that was parsed.
  ///
  /// This method assumes that the current token matches
  /// `TokenType.OPEN_CURLY_BRACKET`.
  ///
  ///     mapLiteral ::=
  ///         'const'? typeArguments? '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}'
  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 = new Modifiers();
    bool progress = true;
    while (progress) {
      TokenType nextType = _peek().type;
      if (nextType == TokenType.PERIOD ||
          nextType == TokenType.LT ||
          nextType == TokenType.OPEN_PAREN) {
        return modifiers;
      }
      Keyword keyword = _currentToken.keyword;
      if (keyword == Keyword.ABSTRACT) {
        if (modifiers.abstractKeyword != null) {
          _reportErrorForCurrentToken(
              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          _advance();
        } else {
          modifiers.abstractKeyword = getAndAdvance();
        }
      } else if (keyword == Keyword.CONST) {
        if (modifiers.constKeyword != null) {
          _reportErrorForCurrentToken(
              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          _advance();
        } else {
          modifiers.constKeyword = getAndAdvance();
        }
      } else if (keyword == Keyword.COVARIANT) {
        if (modifiers.covariantKeyword != null) {
          _reportErrorForCurrentToken(
              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          _advance();
        } else {
          modifiers.covariantKeyword = getAndAdvance();
        }
      } else if (keyword == Keyword.EXTERNAL) {
        if (modifiers.externalKeyword != null) {
          _reportErrorForCurrentToken(
              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          _advance();
        } else {
          modifiers.externalKeyword = getAndAdvance();
        }
      } else if (keyword == Keyword.FACTORY) {
        if (modifiers.factoryKeyword != null) {
          _reportErrorForCurrentToken(
              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          _advance();
        } else {
          modifiers.factoryKeyword = getAndAdvance();
        }
      } else if (keyword == Keyword.FINAL) {
        if (modifiers.finalKeyword != null) {
          _reportErrorForCurrentToken(
              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          _advance();
        } else {
          modifiers.finalKeyword = getAndAdvance();
        }
      } else if (keyword == Keyword.STATIC) {
        if (modifiers.staticKeyword != null) {
          _reportErrorForCurrentToken(
              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          _advance();
        } else {
          modifiers.staticKeyword = getAndAdvance();
        }
      } else if (keyword == Keyword.VAR) {
        if (modifiers.varKeyword != null) {
          _reportErrorForCurrentToken(
              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          _advance();
        } else {
          modifiers.varKeyword = getAndAdvance();
        }
      } else {
        progress = false;
      }
    }
    return modifiers;
  }

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

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

  /// Parse a non-labeled statement. Return the non-labeled statement that was
  /// parsed.
  ///
  ///     nonLabeledStatement ::=
  ///         block
  ///       | assertStatement
  ///       | breakStatement
  ///       | continueStatement
  ///       | doStatement
  ///       | forStatement
  ///       | ifStatement
  ///       | returnStatement
  ///       | switchStatement
  ///       | tryStatement
  ///       | whileStatement
  ///       | variableDeclarationList ';'
  ///       | expressionStatement
  ///       | functionSignature functionBody
  Statement parseNonLabeledStatement() {
    // TODO(brianwilkerson) Pass the comment and metadata on where appropriate.
    CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
    TokenType type = _currentToken.type;
    if (type == TokenType.OPEN_CURLY_BRACKET) {
      if (_tokenMatches(_peek(), TokenType.STRING)) {
        Token afterString = skipStringLiteral(_currentToken.next);
        if (afterString != null && afterString.type == TokenType.COLON) {
          return astFactory.expressionStatement(
              parseExpression2(), _expect(TokenType.SEMICOLON));
        }
      }
      return parseBlock();
    } else if (type.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 = null;
    Token period = null;
    if (_matchesKeyword(Keyword.THIS)) {
      thisKeyword = getAndAdvance();
      period = _expect(TokenType.PERIOD);
    }
    if (!_matchesIdentifier() && inFunctionType) {
      return astFactory.simpleFormalParameter2(
          comment: commentAndMetadata.comment,
          metadata: commentAndMetadata.metadata,
          covariantKeyword: covariantKeyword,
          keyword: holder.keyword,
          type: holder.type,
          identifier: null);
    }
    SimpleIdentifier identifier = parseSimpleIdentifier();
    TypeParameterList typeParameters = _parseGenericMethodTypeParameters();
    if (_matches(TokenType.OPEN_PAREN)) {
      FormalParameterList parameters = _parseFormalParameterListUnchecked();
      if (thisKeyword == null) {
        if (holder.keyword != null) {
          _reportErrorForToken(
              ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, holder.keyword);
        }
        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 = null;
      try {
        value = int.parse(token.lexeme);
      } on FormatException {
        // The invalid format should have been reported by the scanner.
      }
      return astFactory.integerLiteral(token, value);
    }
    Keyword keyword = _currentToken.keyword;
    if (keyword == Keyword.NULL) {
      return astFactory.nullLiteral(getAndAdvance());
    } else if (keyword == Keyword.NEW) {
      return parseNewExpression();
    } else if (keyword == Keyword.THIS) {
      return astFactory.thisExpression(getAndAdvance());
    } else if (keyword == Keyword.SUPER) {
      return parseAssignableSelector(
          astFactory.superExpression(getAndAdvance()), false,
          allowConditional: false);
    } else if (keyword == Keyword.FALSE) {
      return astFactory.booleanLiteral(getAndAdvance(), false);
    } else if (keyword == Keyword.TRUE) {
      return astFactory.booleanLiteral(getAndAdvance(), true);
    }
    if (type == TokenType.DOUBLE) {
      Token token = getAndAdvance();
      double value = 0.0;
      try {
        value = double.parse(token.lexeme);
      } on FormatException {
        // The invalid format should have been reported by the scanner.
      }
      return astFactory.doubleLiteral(token, value);
    } else if (type == TokenType.HEXADECIMAL) {
      Token token = getAndAdvance();
      int value = null;
      try {
        value = int.parse(token.lexeme);
      } 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 = null;
    SimpleIdentifier constructorName = null;
    if (hasPeriod) {
      period = getAndAdvance();
      if (_matchesIdentifier()) {
        constructorName = _parseSimpleIdentifierUnchecked(isDeclaration: false);
      } else {
        _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
        constructorName = createSyntheticIdentifier(isDeclaration: false);
        _advance();
      }
    }
    ArgumentList argumentList = _parseArgumentListChecked();
    return astFactory.redirectingConstructorInvocation(
        keyword, period, constructorName, argumentList);
  }

  /// Parse a relational expression. Return the relational expression that was
  /// parsed.
  ///
  ///     relationalExpression ::=
  ///         bitwiseOrExpression ('is' '!'? type | 'as' type | relationalOperator bitwiseOrExpression)?
  ///       | 'super' relationalOperator bitwiseOrExpression
  Expression parseRelationalExpression() {
    if (_currentToken.keyword == Keyword.SUPER &&
        _currentToken.next.type.isRelationalOperator) {
      Expression expression = astFactory.superExpression(getAndAdvance());
      Token operator = getAndAdvance();
      return astFactory.binaryExpression(
          expression, operator, parseBitwiseOrExpression());
    }
    Expression expression = parseBitwiseOrExpression();
    Keyword keyword = _currentToken.keyword;
    if (keyword == Keyword.AS) {
      Token asOperator = getAndAdvance();
      return astFactory.asExpression(
          expression, asOperator, parseTypeNotVoid(true));
    } else if (keyword == Keyword.IS) {
      Token isOperator = getAndAdvance();
      Token notOperator = null;
      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 new _TooDeepTreeError();
    }
    _treeDepth++;
    try {
      List<Label> labels = null;
      while (
          _matchesIdentifier() && _currentToken.next.type == TokenType.COLON) {
        Label label = parseLabel(isDeclaration: true);
        if (labels == null) {
          labels = <Label>[label];
        } else {
          labels.add(label);
        }
      }
      Statement statement = parseNonLabeledStatement();
      if (labels == null) {
        return statement;
      }
      return astFactory.labeledStatement(labels, statement);
    } finally {
      _treeDepth--;
    }
  }

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

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

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

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

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

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

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

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

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

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

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

  /// Parse a 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 =
              new Token(TokenType.MINUS, operator.offset + 1);
          secondOperator.setNext(_currentToken);
          firstOperator.setNext(secondOperator);
          operator.previous.setNext(firstOperator);
          return astFactory.prefixExpression(
              firstOperator,
              astFactory.prefixExpression(
                  secondOperator, astFactory.superExpression(getAndAdvance())));
        }
        // Invalid operator before 'super'
        _reportErrorForCurrentToken(
            ParserErrorCode.INVALID_OPERATOR_FOR_SUPER, [operator.lexeme]);
        return astFactory.prefixExpression(
            operator, astFactory.superExpression(getAndAdvance()));
      }
      return astFactory.prefixExpression(
          operator, 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 = null;
    Expression initializer = null;
    if (_matches(TokenType.EQ)) {
      equals = getAndAdvance();
      initializer = parseExpression2();
    }
    return astFactory.variableDeclaration(name, equals, initializer);
  }

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

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

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

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

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

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

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

  /// Parse the portion of a generic function type after the return type,
  /// starting at the [startToken], without actually creating a generic function
  /// type or changing the current token. Return the token following the generic
  /// function type that was parsed, or `null` if the given token is not the
  /// first token in a valid generic function type.
  ///
  /// This method must be kept in sync with
  /// [parseGenericFunctionTypeAfterReturnType].
  Token skipGenericFunctionTypeAfterReturnType(Token startToken) {
    Token next = startToken.next; // Skip 'Function'
    if (_tokenMatches(next, TokenType.LT)) {
      next = skipTypeParameterList(next);
      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 = null;
    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 = new Token(TokenType.GT, token.offset + 1);
      second.setNextWithoutSettingPrevious(token.next);
      return second;
    }
    return null;
  }

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

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

  /// 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 new UnimplementedError('control_flow_collections experiment'
          ' not supported by analyzer parser');
    }
    if (featureSet.isEnabled(Feature.non_nullable)) {
      throw new UnimplementedError(
          'non-nullable experiment not supported by analyzer parser');
    }
    if (featureSet.isEnabled(Feature.spread_collections)) {
      throw new UnimplementedError(
          'spread_collections experiment not supported by analyzer parser');
    }
    if (featureSet.isEnabled(Feature.triple_shift)) {
      throw new 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(new SyntheticKeywordToken(keyword, _currentToken.offset));

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

  /// Create and return a new token with the given [type]. The token will
  /// replace the first portion of the given [token], so it will have the same
  /// offset and will have any comments that might have preceeded the token.
  Token _createToken(Token token, TokenType type, {bool isBegin: false}) {
    CommentToken comments = token.precedingComments;
    if (comments == null) {
      if (isBegin) {
        return new BeginToken(type, token.offset);
      }
      return new Token(type, token.offset);
    } else if (isBegin) {
      return new BeginToken(type, token.offset, comments);
    }
    return new 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 = new Token(TokenType.GT, _currentToken.offset + 1);
      second.setNext(_currentToken.next);
      first.setNext(second);
      _currentToken.previous.setNext(first);
      _currentToken = first;
      return true;
    } else if (currentType == TokenType.GT_EQ) {
      Token first = _createToken(_currentToken, TokenType.GT);
      Token second = new Token(TokenType.EQ, _currentToken.offset + 1);
      second.setNext(_currentToken.next);
      first.setNext(second);
      _currentToken.previous.setNext(first);
      _currentToken = first;
      return true;
    } else if (currentType == TokenType.GT_GT_EQ) {
      int offset = _currentToken.offset;
      Token first = _createToken(_currentToken, TokenType.GT);
      Token second = new Token(TokenType.GT, offset + 1);
      Token third = new Token(TokenType.EQ, offset + 2);
      third.setNext(_currentToken.next);
      second.setNext(third);
      first.setNext(second);
      _currentToken.previous.setNext(first);
      _currentToken = first;
      return true;
    }
    return false;
  }

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

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

  /// 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 = null;
      } 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 = null;
    if (_matchesKeyword(Keyword.WITH)) {
      withClause = parseWithClause();
    } else {
      _reportErrorForCurrentToken(
          ParserErrorCode.EXPECTED_TOKEN, [Keyword.WITH.lexeme]);
    }
    ImplementsClause implementsClause = null;
    if (_matchesKeyword(Keyword.IMPLEMENTS)) {
      implementsClause = parseImplementsClause();
    }
    Token semicolon;
    if (_matches(TokenType.SEMICOLON)) {
      semicolon = getAndAdvance();
    } else {
      if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
        _reportErrorForCurrentToken(
            ParserErrorCode.EXPECTED_TOKEN, [TokenType.SEMICOLON.lexeme]);
        Token leftBracket = getAndAdvance();
        _parseClassMembers(className.name, _getEndToken(leftBracket));
        _expect(TokenType.CLOSE_CURLY_BRACKET);
      } else {
        _reportErrorForToken(ParserErrorCode.EXPECTED_TOKEN,
            _currentToken.previous, [TokenType.SEMICOLON.lexeme]);
      }
      semicolon = _createSyntheticToken(TokenType.SEMICOLON);
    }
    return astFactory.classTypeAlias(
        commentAndMetadata.comment,
        commentAndMetadata.metadata,
        classKeyword,
        className,
        typeParameters,
        equals,
        abstractKeyword,
        superclass,
        withClause,
        implementsClause,
        semicolon);
  }

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

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

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

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

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

      if (type == TokenType.CLOSE_SQUARE_BRACKET) {
        rightSquareBracket = getAndAdvance();
        if (leftSquareBracket == null) {
          if (leftCurlyBracket != null) {
            _reportErrorForCurrentToken(
                ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP,
                ['}', ']']);
            rightCurlyBracket = rightSquareBracket;
            rightSquareBracket = null;
            // 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 = null;
            // 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 = null;
    if (hasReturnTypeInTypeAlias) {
      returnType = parseTypeAnnotation(false);
    }
    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
    TypeParameterList typeParameters = null;
    if (_matches(TokenType.LT)) {
      typeParameters = parseTypeParameterList();
    }
    TokenType type = _currentToken.type;
    if (type == TokenType.SEMICOLON || type == TokenType.EOF) {
      _reportErrorForCurrentToken(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS);
      FormalParameterList parameters = astFactory.formalParameterList(
          _createSyntheticToken(TokenType.OPEN_PAREN),
          null,
          null,
          null,
          _createSyntheticToken(TokenType.CLOSE_PAREN));
      Token semicolon = _expect(TokenType.SEMICOLON);
      return astFactory.functionTypeAlias(
          commentAndMetadata.comment,
          commentAndMetadata.metadata,
          keyword,
          returnType,
          name,
          typeParameters,
          parameters,
          semicolon);
    } else if (type == TokenType.OPEN_PAREN) {
      FormalParameterList parameters = _parseFormalParameterListUnchecked();
      _validateFormalParameterList(parameters);
      Token semicolon = _expect(TokenType.SEMICOLON);
      return astFactory.functionTypeAlias(
          commentAndMetadata.comment,
          commentAndMetadata.metadata,
          keyword,
          returnType,
          name,
          typeParameters,
          parameters,
          semicolon);
    } else {
      _reportErrorForCurrentToken(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS);
      // Recovery: At the very least we should skip to the start of the next
      // valid compilation unit member, allowing for the possibility of finding
      // the typedef parameters before that point.
      return astFactory.functionTypeAlias(
          commentAndMetadata.comment,
          commentAndMetadata.metadata,
          keyword,
          returnType,
          name,
          typeParameters,
          astFactory.formalParameterList(
              _createSyntheticToken(TokenType.OPEN_PAREN),
              null,
              null,
              null,
              _createSyntheticToken(TokenType.CLOSE_PAREN)),
          _createSyntheticToken(TokenType.SEMICOLON));
    }
  }

  /// 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 = null;
        if (_matchesKeyword(Keyword.THIS)) {
          expression = astFactory.thisExpression(getAndAdvance());
        } else {
          expression = parseSimpleIdentifier();
        }
        elements.add(
            astFactory.interpolationExpression(openToken, expression, null));
      }
      if (_matches(TokenType.STRING)) {
        string = getAndAdvance();
        isExpression = _matches(TokenType.STRING_INTERPOLATION_EXPRESSION);
        hasMore =
            isExpression || _matches(TokenType.STRING_INTERPOLATION_IDENTIFIER);
        elements.add(astFactory.interpolationString(
            string, computeStringValue(string.lexeme, false, !hasMore)));
      } else {
        hasMore = false;
      }
    }
    return astFactory.stringInterpolation(elements);
  }

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

  /// Parse a type annotation, possibly superseded by a type name in a comment.
  /// Return the type name that was parsed.
  ///
  /// This method assumes that the current token is an identifier.
  ///
  ///     type ::=
  ///         qualified typeArguments?
  TypeAnnotation _parseTypeAnnotationAfterIdentifier() {
    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 = new StringBuffer();
        buffer.write(token.lexeme);
        while (token != endToken) {
          token = token.next;
          if (token.offset != endOffset || token.precedingComments != null) {
            return parseStringLiteral();
          }
          buffer.write(token.lexeme);
          endOffset = token.end;
        }
        String value = buffer.toString();
        Token newToken =
            new StringToken(TokenType.STRING, "'$value'", _currentToken.offset);
        _reportErrorForToken(
            ParserErrorCode.NON_STRING_LITERAL_AS_URI, newToken);
        _currentToken = endToken.next;
        return astFactory.simpleStringLiteral(newToken, value);
      }
    }
    return parseStringLiteral();
  }

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

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

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

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

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

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

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

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

  /// 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 preceeded by metadata,
    // so we just assume that everything before the matching end token is valid.
    //
    int depth = 1;
    Token next = startToken.next;
    while (depth > 0) {
      if (_tokenMatches(next, TokenType.EOF)) {
        return null;
      } else if (_tokenMatches(next, TokenType.LT)) {
        depth++;
      } else if (_tokenMatches(next, TokenType.GT)) {
        depth--;
      } else if (_tokenMatches(next, TokenType.GT_EQ)) {
        if (depth == 1) {
          Token fakeEquals = new Token(TokenType.EQ, next.offset + 2);
          fakeEquals.setNextWithoutSettingPrevious(next.next);
          return fakeEquals;
        }
        depth--;
      } else if (_tokenMatches(next, TokenType.GT_GT)) {
        depth -= 2;
      } else if (_tokenMatches(next, TokenType.GT_GT_EQ)) {
        if (depth < 2) {
          return null;
        } else if (depth == 2) {
          Token fakeEquals = new Token(TokenType.EQ, next.offset + 2);
          fakeEquals.setNextWithoutSettingPrevious(next.next);
          return fakeEquals;
        }
        depth -= 2;
      }
      next = next.next;
    }
    return next;
  }

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

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

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

  /// Return `true` if the given [token] is either an identifier or a keyword.
  bool _tokenMatchesIdentifierOrKeyword(Token token) =>
      _tokenMatches(token, TokenType.IDENTIFIER) || 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 new StateError("Attempt to unlock not locked error listener.");
    }
    _errorListenerLock--;
  }

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

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

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

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

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

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

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

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

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

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

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

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

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