// This code was auto-generated, is not intended to be edited, and is subject to
// significant change. Please see the README file for more information.
library engine.parser;
import 'dart:collection';
import 'java_core.dart';
import 'instrumentation.dart';
import 'error.dart';
import 'source.dart';
import 'scanner.dart';
import 'ast.dart';
import 'utilities_dart.dart';
import 'engine.dart' show AnalysisEngine;
/**
 * Instances of the class `CommentAndMetadata` implement a simple data-holder for a method
 * that needs to return multiple values.
 *
 * @coverage dart.engine.parser
 */
class CommentAndMetadata {

  /**
   * The documentation comment that was parsed, or `null` if none was given.
   */
  Comment comment;

  /**
   * The metadata that was parsed.
   */
  List<Annotation> metadata;

  /**
   * Initialize a newly created holder with the given data.
   *
   * @param comment the documentation comment that was parsed
   * @param metadata the metadata that was parsed
   */
  CommentAndMetadata(Comment comment, List<Annotation> metadata) {
    this.comment = comment;
    this.metadata = metadata;
  }
}
/**
 * Instances of the class `FinalConstVarOrType` implement a simple data-holder for a method
 * that needs to return multiple values.
 *
 * @coverage dart.engine.parser
 */
class FinalConstVarOrType {

  /**
   * The 'final', 'const' or 'var' keyword, or `null` if none was given.
   */
  Token keyword;

  /**
   * The type, of `null` if no type was specified.
   */
  TypeName type;

  /**
   * Initialize a newly created holder with the given data.
   *
   * @param keyword the 'final', 'const' or 'var' keyword
   * @param type the type
   */
  FinalConstVarOrType(Token keyword, TypeName type) {
    this.keyword = keyword;
    this.type = type;
  }
}
/**
 * Instances of the class `Modifiers` implement a simple data-holder for a method that needs
 * to return multiple values.
 *
 * @coverage dart.engine.parser
 */
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 '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;
  String toString() {
    JavaStringBuilder builder = new JavaStringBuilder();
    bool needsSpace = appendKeyword(builder, false, abstractKeyword);
    needsSpace = appendKeyword(builder, needsSpace, constKeyword);
    needsSpace = appendKeyword(builder, needsSpace, externalKeyword);
    needsSpace = appendKeyword(builder, needsSpace, factoryKeyword);
    needsSpace = appendKeyword(builder, needsSpace, finalKeyword);
    needsSpace = appendKeyword(builder, needsSpace, staticKeyword);
    appendKeyword(builder, needsSpace, varKeyword);
    return builder.toString();
  }

  /**
   * If the given keyword is not `null`, append it to the given builder, prefixing it with a
   * space if needed.
   *
   * @param builder the builder to which the keyword will be appended
   * @param needsSpace `true` if the keyword needs to be prefixed with a space
   * @param keyword the keyword to be appended
   * @return `true` if subsequent keywords need to be prefixed with a space
   */
  bool appendKeyword(JavaStringBuilder builder, bool needsSpace, Token keyword) {
    if (keyword != null) {
      if (needsSpace) {
        builder.appendChar(0x20);
      }
      builder.append(keyword.lexeme);
      return true;
    }
    return needsSpace;
  }
}
/**
 * Instances of the class `Parser` are used to parse tokens into an AST structure.
 *
 * @coverage dart.engine.parser
 */
class Parser {

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

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

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

  /**
   * 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;
  static String _HIDE = "hide";
  static String _OF = "of";
  static String _ON = "on";
  static String _SHOW = "show";
  static String _NATIVE = "native";

  /**
   * Initialize a newly created parser.
   *
   * @param source the source being parsed
   * @param errorListener the error listener that will be informed of any errors that are found
   *          during the parse
   */
  Parser(Source source, AnalysisErrorListener errorListener) {
    this._source = source;
    this._errorListener = errorListener;
  }

  /**
   * Parse a compilation unit, starting with the given token.
   *
   * @param token the first token of the compilation unit
   * @return the compilation unit that was parsed
   */
  CompilationUnit parseCompilationUnit(Token token) {
    InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engine.Parser.parseCompilationUnit");
    try {
      _currentToken = token;
      CompilationUnit compilationUnit = parseCompilationUnit2();
      gatherTodoComments(token);
      return compilationUnit;
    } finally {
      instrumentation.log();
    }
  }

  /**
   * Parse an expression, starting with the given token.
   *
   * @param token the first token of the expression
   * @return the expression that was parsed, or `null` if the tokens do not represent a
   *         recognizable expression
   */
  Expression parseExpression(Token token) {
    InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engine.Parser.parseExpression");
    try {
      _currentToken = token;
      return parseExpression2();
    } finally {
      instrumentation.log();
    }
  }

  /**
   * Parse a statement, starting with the given token.
   *
   * @param token the first token of the statement
   * @return the statement that was parsed, or `null` if the tokens do not represent a
   *         recognizable statement
   */
  Statement parseStatement(Token token) {
    InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engine.Parser.parseStatement");
    try {
      _currentToken = token;
      return parseStatement2();
    } finally {
      instrumentation.log();
    }
  }

  /**
   * Parse a sequence of statements, starting with the given token.
   *
   * @param token the first token of the sequence of statement
   * @return the statements that were parsed, or `null` if the tokens do not represent a
   *         recognizable sequence of statements
   */
  List<Statement> parseStatements(Token token) {
    InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engine.Parser.parseStatements");
    try {
      _currentToken = token;
      return parseStatements2();
    } finally {
      instrumentation.log();
    }
  }
  void set currentToken(Token currentToken) {
    this._currentToken = currentToken;
  }

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

  /**
   * Append the character equivalent of the given scalar value to the given builder. Use the start
   * and end indices to report an error, and don't append anything to the builder, if the scalar
   * value is invalid.
   *
   * @param builder the builder to which the scalar value is to be appended
   * @param escapeSequence the escape sequence that was parsed to produce the scalar value
   * @param scalarValue the value to be appended
   * @param startIndex the index of the first character representing the scalar value
   * @param endIndex the index of the last character representing the scalar value
   */
  void appendScalarValue(JavaStringBuilder builder, String escapeSequence, int scalarValue, int startIndex, int endIndex) {
    if (scalarValue < 0 || scalarValue > Character.MAX_CODE_POINT || (scalarValue >= 0xD800 && scalarValue <= 0xDFFF)) {
      reportError8(ParserErrorCode.INVALID_CODE_POINT, [escapeSequence]);
      return;
    }
    if (scalarValue < Character.MAX_VALUE) {
      builder.appendChar(scalarValue as int);
    } else {
      builder.append(Character.toChars(scalarValue));
    }
  }

  /**
   * Compute the content of a string with the given literal representation.
   *
   * @param lexeme the literal representation of the string
   * @param first `true` if this is the first token in a string literal
   * @param last `true` if this is the last token in a string literal
   * @return the actual value of the string
   */
  String computeStringValue(String lexeme, bool first, bool last) {
    bool isRaw = false;
    int start = 0;
    if (first) {
      if (lexeme.startsWith("r\"\"\"") || lexeme.startsWith("r'''")) {
        isRaw = true;
        start += 4;
      } else if (lexeme.startsWith("r\"") || lexeme.startsWith("r'")) {
        isRaw = true;
        start += 2;
      } else if (lexeme.startsWith("\"\"\"") || lexeme.startsWith("'''")) {
        start += 3;
      } else if (lexeme.startsWith("\"") || lexeme.startsWith("'")) {
        start += 1;
      }
    }
    int end = lexeme.length;
    if (last) {
      if (lexeme.endsWith("\"\"\"") || lexeme.endsWith("'''")) {
        end -= 3;
      } else if (lexeme.endsWith("\"") || lexeme.endsWith("'")) {
        end -= 1;
      }
    }
    if (end - start + 1 < 0) {
      AnalysisEngine.instance.logger.logError("Internal error: computeStringValue(${lexeme}, ${first}, ${last})");
      return "";
    }
    if (isRaw) {
      return lexeme.substring(start, end);
    }
    JavaStringBuilder builder = new JavaStringBuilder();
    int index = start;
    while (index < end) {
      index = translateCharacter(builder, lexeme, index);
    }
    return builder.toString();
  }

  /**
   * Convert the given method declaration into the nearest valid top-level function declaration.
   *
   * @param method the method to be converted
   * @return the function declaration that most closely captures the components of the given method
   *         declaration
   */
  FunctionDeclaration convertToFunctionDeclaration(MethodDeclaration method) => new FunctionDeclaration.full(method.documentationComment, method.metadata, method.externalKeyword, method.returnType, method.propertyKeyword, method.name, new FunctionExpression.full(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.
   *
   * @return `true` if the current token could be the start of a compilation unit member
   */
  bool couldBeStartOfCompilationUnitMember() {
    if ((matches(Keyword.IMPORT) || matches(Keyword.EXPORT) || matches(Keyword.LIBRARY) || matches(Keyword.PART)) && !matches4(peek(), TokenType.PERIOD) && !matches4(peek(), TokenType.LT)) {
      return true;
    } else if (matches(Keyword.CLASS)) {
      return true;
    } else if (matches(Keyword.TYPEDEF) && !matches4(peek(), TokenType.PERIOD) && !matches4(peek(), TokenType.LT)) {
      return true;
    } else if (matches(Keyword.VOID) || ((matches(Keyword.GET) || matches(Keyword.SET)) && matchesIdentifier2(peek())) || (matches(Keyword.OPERATOR) && isOperator(peek()))) {
      return true;
    } else if (matchesIdentifier()) {
      if (matches4(peek(), TokenType.OPEN_PAREN)) {
        return true;
      }
      Token token = skipReturnType(_currentToken);
      if (token == null) {
        return false;
      }
      if (matches(Keyword.GET) || matches(Keyword.SET) || (matches(Keyword.OPERATOR) && isOperator(peek())) || matchesIdentifier()) {
        return true;
      }
    }
    return false;
  }

  /**
   * Create a synthetic identifier.
   *
   * @return the synthetic identifier that was created
   */
  SimpleIdentifier createSyntheticIdentifier() => new SimpleIdentifier.full(createSyntheticToken2(TokenType.IDENTIFIER));

  /**
   * Create a synthetic string literal.
   *
   * @return the synthetic string literal that was created
   */
  SimpleStringLiteral createSyntheticStringLiteral() => new SimpleStringLiteral.full(createSyntheticToken2(TokenType.STRING), "");

  /**
   * Create a synthetic token representing the given keyword.
   *
   * @return the synthetic token that was created
   */
  Token createSyntheticToken(Keyword keyword) => new KeywordToken_13(keyword, _currentToken.offset);

  /**
   * Create a synthetic token with the given type.
   *
   * @return the synthetic token that was created
   */
  Token createSyntheticToken2(TokenType type) => new StringToken(type, "", _currentToken.offset);

  /**
   * Check that the given expression is assignable and report an error if it isn't.
   *
   * <pre>
   * assignableExpression ::=
   *     primary (arguments* assignableSelector)+
   *   | 'super' assignableSelector
   *   | identifier
   *
   * assignableSelector ::=
   *     '[' expression ']'
   *   | '.' identifier
   * </pre>
   *
   * @param expression the expression being checked
   */
  void ensureAssignable(Expression expression) {
    if (expression != null && !expression.isAssignable) {
      reportError8(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, []);
    }
  }

  /**
   * If the current token is a keyword matching the given string, return it after advancing to the
   * next token. Otherwise report an error and return the current token without advancing.
   *
   * @param keyword the keyword that is expected
   * @return the token that matched the given type
   */
  Token expect(Keyword keyword) {
    if (matches(keyword)) {
      return andAdvance;
    }
    reportError8(ParserErrorCode.EXPECTED_TOKEN, [keyword.syntax]);
    return _currentToken;
  }

  /**
   * 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.
   *
   * @param type the type of token that is expected
   * @return the token that matched the given type
   */
  Token expect2(TokenType type) {
    if (matches5(type)) {
      return andAdvance;
    }
    if (identical(type, TokenType.SEMICOLON)) {
      reportError9(ParserErrorCode.EXPECTED_TOKEN, _currentToken.previous, [type.lexeme]);
    } else {
      reportError8(ParserErrorCode.EXPECTED_TOKEN, [type.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.
   *
   * @param ranges the ranges to be searched
   * @param index the index contained in the returned range
   * @return the range that was found
   */
  List<int> findRange(List<List<int>> ranges, int index) {
    for (List<int> range in ranges) {
      if (range[0] <= index && index <= range[1]) {
        return range;
      } else if (index < range[0]) {
        return null;
      }
    }
    return null;
  }
  void gatherTodoComments(Token token) {
    while (token != null && token.type != TokenType.EOF) {
      Token commentToken = token.precedingComments;
      while (commentToken != null) {
        if (identical(commentToken.type, TokenType.SINGLE_LINE_COMMENT) || identical(commentToken.type, TokenType.MULTI_LINE_COMMENT)) {
          scrapeTodoComment(commentToken);
        }
        commentToken = commentToken.next;
      }
      token = token.next;
    }
  }

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

  /**
   * Return a list of the ranges of characters in the given comment string that should be treated as
   * code blocks.
   *
   * @param comment the comment being processed
   * @return the ranges of characters that should be treated as code blocks
   */
  List<List<int>> getCodeBlockRanges(String comment) {
    List<List<int>> ranges = new List<List<int>>();
    int length = comment.length;
    int index = 0;
    if (comment.startsWith("/**") || comment.startsWith("///")) {
      index = 3;
    }
    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 (JavaString.startsWithBefore(comment, "*     ", index)) {
          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 (JavaString.startsWithBefore(comment, "[:", index)) {
        int end = JavaString.indexOf(comment, ":]", index + 2);
        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 begin token, or `null` if either the given
   * token is not a begin token or it does not have an end token associated with it.
   *
   * @param beginToken the token that is expected to have an end token associated with it
   * @return the end token associated with the begin token
   */
  Token getEndToken(Token beginToken) {
    if (beginToken is BeginToken) {
      return ((beginToken as BeginToken)).endToken;
    }
    return null;
  }

  /**
   * 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.
   *
   * @return `true` if we can successfully parse the rest of a type alias if we first parse a
   *         return type.
   */
  bool hasReturnTypeInTypeAlias() {
    Token next = skipReturnType(_currentToken);
    if (next == null) {
      return false;
    }
    return matchesIdentifier2(next);
  }

  /**
   * Return `true` if the current token appears to be the beginning of a function declaration.
   *
   * @return `true` if the current token appears to be the beginning of a function declaration
   */
  bool isFunctionDeclaration() {
    if (matches(Keyword.VOID)) {
      return true;
    }
    Token afterReturnType = skipTypeName(_currentToken);
    if (afterReturnType == null) {
      afterReturnType = _currentToken;
    }
    Token afterIdentifier = skipSimpleIdentifier(afterReturnType);
    if (afterIdentifier == null) {
      afterIdentifier = skipSimpleIdentifier(_currentToken);
    }
    if (afterIdentifier == null) {
      return false;
    }
    if (isFunctionExpression(afterIdentifier)) {
      return true;
    }
    if (matches(Keyword.GET)) {
      Token afterName = skipSimpleIdentifier(_currentToken.next);
      if (afterName == null) {
        return false;
      }
      return matches4(afterName, TokenType.FUNCTION) || matches4(afterName, TokenType.OPEN_CURLY_BRACKET);
    }
    return false;
  }

  /**
   * Return `true` if the given token appears to be the beginning of a function expression.
   *
   * @param startToken the token that might be the start of a function expression
   * @return `true` if the given token appears to be the beginning of a function expression
   */
  bool isFunctionExpression(Token startToken) {
    Token afterParameters = skipFormalParameterList(startToken);
    if (afterParameters == null) {
      return false;
    }
    return matchesAny(afterParameters, [TokenType.OPEN_CURLY_BRACKET, TokenType.FUNCTION]);
  }

  /**
   * Return `true` if the given character is a valid hexadecimal digit.
   *
   * @param character the character being tested
   * @return `true` if the character is a valid hexadecimal digit
   */
  bool isHexDigit(int character) => (0x30 <= character && character <= 0x39) || (0x41 <= character && character <= 0x46) || (0x61 <= character && character <= 0x66);

  /**
   * 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.
   *
   * <pre>
   * initializedVariableDeclaration ::=
   *     declaredIdentifier ('=' expression)? (',' initializedIdentifier)*
   *
   * declaredIdentifier ::=
   *     metadata finalConstVarOrType identifier
   *
   * finalConstVarOrType ::=
   *     'final' type?
   *   | 'const' type?
   *   | 'var'
   *   | type
   *
   * type ::=
   *     qualified typeArguments?
   *
   * initializedIdentifier ::=
   *     identifier ('=' expression)?
   * </pre>
   *
   * @return `true` if the current token is the first token in an initialized variable
   *         declaration
   */
  bool isInitializedVariableDeclaration() {
    if (matches(Keyword.FINAL) || matches(Keyword.VAR)) {
      return true;
    }
    if (matches(Keyword.CONST)) {
      return !matchesAny(peek(), [
          TokenType.LT,
          TokenType.OPEN_CURLY_BRACKET,
          TokenType.OPEN_SQUARE_BRACKET,
          TokenType.INDEX]);
    }
    Token token = skipTypeName(_currentToken);
    if (token == null) {
      return false;
    }
    token = skipSimpleIdentifier(token);
    if (token == null) {
      return false;
    }
    TokenType type = token.type;
    return identical(type, TokenType.EQ) || identical(type, TokenType.COMMA) || identical(type, TokenType.SEMICOLON) || matches3(token, Keyword.IN);
  }

  /**
   * Given that we have just found bracketed text within a 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.
   *
   * This method uses the syntax described by the <a
   * href="http://daringfireball.net/projects/markdown/syntax">markdown</a> project.
   *
   * @param comment the comment text in which the bracketed text was found
   * @param rightIndex the index of the right bracket
   * @return `true` if the bracketed text is followed by a link address
   */
  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 token appears to be the beginning of an operator declaration.
   *
   * @param startToken the token that might be the start of an operator declaration
   * @return `true` if the given token appears to be the beginning of an operator declaration
   */
  bool isOperator(Token startToken) {
    if (startToken.isOperator) {
      Token token = startToken.next;
      while (token.isOperator) {
        token = token.next;
      }
      return matches4(token, TokenType.OPEN_PAREN);
    }
    return false;
  }

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

  /**
   * Return `true` if the given token appears to be the first token of a type name that is
   * followed by a variable or field formal parameter.
   *
   * @param startToken the first token of the sequence being checked
   * @return `true` if there is a type name and variable starting at the given token
   */
  bool isTypedIdentifier(Token startToken) {
    Token token = skipReturnType(startToken);
    if (token == null) {
      return false;
    } else if (matchesIdentifier2(token)) {
      return true;
    } else if (matches3(token, Keyword.THIS) && matches4(token.next, TokenType.PERIOD) && matchesIdentifier2(token.next.next)) {
      return true;
    }
    return false;
  }

  /**
   * Compare the given tokens to find the token that appears first in the source being parsed. That
   * is, return the left-most of all of the tokens. The arguments are allowed to be `null`.
   * Return the token with the smallest offset, or `null` if there are no arguments or if all
   * of the arguments are `null`.
   *
   * @param tokens the tokens being compared
   * @return the token with the smallest offset
   */
  Token lexicallyFirst(List<Token> tokens) {
    Token first = null;
    int firstOffset = 2147483647;
    for (Token token in tokens) {
      if (token != null) {
        int offset = token.offset;
        if (offset < firstOffset) {
          first = token;
          firstOffset = offset;
        }
      }
    }
    return first;
  }

  /**
   * Return `true` if the current token matches the given keyword.
   *
   * @param keyword the keyword that can optionally appear in the current location
   * @return `true` if the current token matches the given keyword
   */
  bool matches(Keyword keyword) => matches3(_currentToken, keyword);

  /**
   * Return `true` if the current token matches the given identifier.
   *
   * @param identifier the identifier that can optionally appear in the current location
   * @return `true` if the current token matches the given identifier
   */
  bool matches2(String identifier) => identical(_currentToken.type, TokenType.IDENTIFIER) && _currentToken.lexeme == identifier;

  /**
   * Return `true` if the given token matches the given keyword.
   *
   * @param token the token being tested
   * @param keyword the keyword that is being tested for
   * @return `true` if the given token matches the given keyword
   */
  bool matches3(Token token, Keyword keyword) => identical(token.type, TokenType.KEYWORD) && identical(((token as KeywordToken)).keyword, keyword);

  /**
   * Return `true` if the given token has the given type.
   *
   * @param token the token being tested
   * @param type the type of token that is being tested for
   * @return `true` if the given token has the given type
   */
  bool matches4(Token token, TokenType type) => identical(token.type, type);

  /**
   * Return `true` if the current token has the given type. Note that this method, unlike
   * other variants, will modify the token stream if possible to match a wider range of tokens. In
   * particular, if we are attempting to match a '>' and the next token is either a '>>' or '>>>',
   * the token stream will be re-written and `true` will be returned.
   *
   * @param type the type of token that can optionally appear in the current location
   * @return `true` if the current token has the given type
   */
  bool matches5(TokenType type) {
    TokenType currentType = _currentToken.type;
    if (currentType != type) {
      if (identical(type, TokenType.GT)) {
        if (identical(currentType, TokenType.GT_GT)) {
          int offset = _currentToken.offset;
          Token first = new Token(TokenType.GT, offset);
          Token second = new Token(TokenType.GT, offset + 1);
          second.setNext(_currentToken.next);
          first.setNext(second);
          _currentToken.previous.setNext(first);
          _currentToken = first;
          return true;
        } else if (identical(currentType, TokenType.GT_EQ)) {
          int offset = _currentToken.offset;
          Token first = new Token(TokenType.GT, offset);
          Token second = new Token(TokenType.EQ, offset + 1);
          second.setNext(_currentToken.next);
          first.setNext(second);
          _currentToken.previous.setNext(first);
          _currentToken = first;
          return true;
        } else if (identical(currentType, TokenType.GT_GT_EQ)) {
          int offset = _currentToken.offset;
          Token first = new Token(TokenType.GT, offset);
          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;
  }

  /**
   * Return `true` if the given token has any one of the given types.
   *
   * @param token the token being tested
   * @param types the types of token that are being tested for
   * @return `true` if the given token has any of the given types
   */
  bool matchesAny(Token token, List<TokenType> types) {
    TokenType actualType = token.type;
    for (TokenType type in types) {
      if (identical(actualType, type)) {
        return true;
      }
    }
    return false;
  }

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

  /**
   * Return `true` if the given token is a valid identifier. Valid identifiers include
   * built-in identifiers (pseudo-keywords).
   *
   * @return `true` if the given token is a valid identifier
   */
  bool matchesIdentifier2(Token token) => matches4(token, TokenType.IDENTIFIER) || (matches4(token, TokenType.KEYWORD) && ((token as KeywordToken)).keyword.isPseudoKeyword);

  /**
   * If the current token has the given type, then advance to the next token and return `true`
   * . Otherwise, return `false` without advancing.
   *
   * @param type the type of token that can optionally appear in the current location
   * @return `true` if the current token has the given type
   */
  bool optional(TokenType type) {
    if (matches5(type)) {
      advance();
      return true;
    }
    return false;
  }

  /**
   * Parse an additive expression.
   *
   * <pre>
   * additiveExpression ::=
   *     multiplicativeExpression (additiveOperator multiplicativeExpression)*
   *   | 'super' (additiveOperator multiplicativeExpression)+
   * </pre>
   *
   * @return the additive expression that was parsed
   */
  Expression parseAdditiveExpression() {
    Expression expression;
    if (matches(Keyword.SUPER) && _currentToken.next.type.isAdditiveOperator) {
      expression = new SuperExpression.full(andAdvance);
    } else {
      expression = parseMultiplicativeExpression();
    }
    while (_currentToken.type.isAdditiveOperator) {
      Token operator = andAdvance;
      expression = new BinaryExpression.full(expression, operator, parseMultiplicativeExpression());
    }
    return expression;
  }

  /**
   * Parse an annotation.
   *
   * <pre>
   * annotation ::=
   *     '@' qualified ('.' identifier)? arguments?
   * </pre>
   *
   * @return the annotation that was parsed
   */
  Annotation parseAnnotation() {
    Token atSign = expect2(TokenType.AT);
    Identifier name = parsePrefixedIdentifier();
    Token period = null;
    SimpleIdentifier constructorName = null;
    if (matches5(TokenType.PERIOD)) {
      period = andAdvance;
      constructorName = parseSimpleIdentifier();
    }
    ArgumentList arguments = null;
    if (matches5(TokenType.OPEN_PAREN)) {
      arguments = parseArgumentList();
    }
    return new Annotation.full(atSign, name, period, constructorName, arguments);
  }

  /**
   * Parse an argument.
   *
   * <pre>
   * argument ::=
   *     namedArgument
   *   | expression
   *
   * namedArgument ::=
   *     label expression
   * </pre>
   *
   * @return the argument that was parsed
   */
  Expression parseArgument() {
    if (matchesIdentifier() && matches4(peek(), TokenType.COLON)) {
      SimpleIdentifier label = new SimpleIdentifier.full(andAdvance);
      Label name = new Label.full(label, andAdvance);
      return new NamedExpression.full(name, parseExpression2());
    } else {
      return parseExpression2();
    }
  }

  /**
   * Parse an argument definition test.
   *
   * <pre>
   * argumentDefinitionTest ::=
   *     '?' identifier
   * </pre>
   *
   * @return the argument definition test that was parsed
   */
  ArgumentDefinitionTest parseArgumentDefinitionTest() {
    Token question = expect2(TokenType.QUESTION);
    SimpleIdentifier identifier = parseSimpleIdentifier();
    reportError9(ParserErrorCode.DEPRECATED_ARGUMENT_DEFINITION_TEST, question, []);
    return new ArgumentDefinitionTest.full(question, identifier);
  }

  /**
   * Parse a list of arguments.
   *
   * <pre>
   * arguments ::=
   *     '(' argumentList? ')'
   *
   * argumentList ::=
   *     namedArgument (',' namedArgument)*
   *   | expressionList (',' namedArgument)*
   * </pre>
   *
   * @return the argument list that was parsed
   */
  ArgumentList parseArgumentList() {
    Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
    List<Expression> arguments = new List<Expression>();
    if (matches5(TokenType.CLOSE_PAREN)) {
      return new ArgumentList.full(leftParenthesis, arguments, andAdvance);
    }
    Expression argument = parseArgument();
    arguments.add(argument);
    bool foundNamedArgument = argument is NamedExpression;
    bool generatedError = false;
    while (optional(TokenType.COMMA)) {
      argument = parseArgument();
      arguments.add(argument);
      if (foundNamedArgument) {
        if (!generatedError && argument is! NamedExpression) {
          reportError8(ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT, []);
          generatedError = true;
        }
      } else if (argument is NamedExpression) {
        foundNamedArgument = true;
      }
    }
    Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
    return new ArgumentList.full(leftParenthesis, arguments, rightParenthesis);
  }

  /**
   * Parse an assert statement.
   *
   * <pre>
   * assertStatement ::=
   *     'assert' '(' conditionalExpression ')' ';'
   * </pre>
   *
   * @return the assert statement
   */
  AssertStatement parseAssertStatement() {
    Token keyword = expect(Keyword.ASSERT);
    Token leftParen = expect2(TokenType.OPEN_PAREN);
    Expression expression = parseExpression2();
    if (expression is AssignmentExpression) {
      reportError(ParserErrorCode.ASSERT_DOES_NOT_TAKE_ASSIGNMENT, expression, []);
    } else if (expression is CascadeExpression) {
      reportError(ParserErrorCode.ASSERT_DOES_NOT_TAKE_CASCADE, expression, []);
    } else if (expression is ThrowExpression) {
      reportError(ParserErrorCode.ASSERT_DOES_NOT_TAKE_THROW, expression, []);
    } else if (expression is RethrowExpression) {
      reportError(ParserErrorCode.ASSERT_DOES_NOT_TAKE_RETHROW, expression, []);
    }
    Token rightParen = expect2(TokenType.CLOSE_PAREN);
    Token semicolon = expect2(TokenType.SEMICOLON);
    return new AssertStatement.full(keyword, leftParen, expression, rightParen, semicolon);
  }

  /**
   * Parse an assignable expression.
   *
   * <pre>
   * assignableExpression ::=
   *     primary (arguments* assignableSelector)+
   *   | 'super' assignableSelector
   *   | identifier
   * </pre>
   *
   * @param primaryAllowed `true` if the expression is allowed to be a primary without any
   *          assignable selector
   * @return the assignable expression that was parsed
   */
  Expression parseAssignableExpression(bool primaryAllowed) {
    if (matches(Keyword.SUPER)) {
      return parseAssignableSelector(new SuperExpression.full(andAdvance), false);
    }
    Expression expression = parsePrimaryExpression();
    bool isOptional = primaryAllowed || expression is SimpleIdentifier;
    while (true) {
      while (matches5(TokenType.OPEN_PAREN)) {
        ArgumentList argumentList = parseArgumentList();
        if (expression is SimpleIdentifier) {
          expression = new MethodInvocation.full(null, null, expression as SimpleIdentifier, argumentList);
        } else if (expression is PrefixedIdentifier) {
          PrefixedIdentifier identifier = expression as PrefixedIdentifier;
          expression = new MethodInvocation.full(identifier.prefix, identifier.period, identifier.identifier, argumentList);
        } else if (expression is PropertyAccess) {
          PropertyAccess access = expression as PropertyAccess;
          expression = new MethodInvocation.full(access.target, access.operator, access.propertyName, argumentList);
        } else {
          expression = new FunctionExpressionInvocation.full(expression, argumentList);
        }
        if (!primaryAllowed) {
          isOptional = false;
        }
      }
      Expression selectorExpression = parseAssignableSelector(expression, isOptional || (expression is PrefixedIdentifier));
      if (identical(selectorExpression, expression)) {
        if (!isOptional && (expression is PrefixedIdentifier)) {
          PrefixedIdentifier identifier = expression as PrefixedIdentifier;
          expression = new PropertyAccess.full(identifier.prefix, identifier.period, identifier.identifier);
        }
        return expression;
      }
      expression = selectorExpression;
      isOptional = true;
    }
  }

  /**
   * Parse an assignable selector.
   *
   * <pre>
   * assignableSelector ::=
   *     '[' expression ']'
   *   | '.' identifier
   * </pre>
   *
   * @param prefix the expression preceding the selector
   * @param optional `true` if the selector is optional
   * @return the assignable selector that was parsed
   */
  Expression parseAssignableSelector(Expression prefix, bool optional) {
    if (matches5(TokenType.OPEN_SQUARE_BRACKET)) {
      Token leftBracket = andAdvance;
      Expression index = parseExpression2();
      Token rightBracket = expect2(TokenType.CLOSE_SQUARE_BRACKET);
      return new IndexExpression.forTarget_full(prefix, leftBracket, index, rightBracket);
    } else if (matches5(TokenType.PERIOD)) {
      Token period = andAdvance;
      return new PropertyAccess.full(prefix, period, parseSimpleIdentifier());
    } else {
      if (!optional) {
        reportError8(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, []);
      }
      return prefix;
    }
  }

  /**
   * Parse a bitwise and expression.
   *
   * <pre>
   * bitwiseAndExpression ::=
   *     shiftExpression ('&' shiftExpression)*
   *   | 'super' ('&' shiftExpression)+
   * </pre>
   *
   * @return the bitwise and expression that was parsed
   */
  Expression parseBitwiseAndExpression() {
    Expression expression;
    if (matches(Keyword.SUPER) && matches4(peek(), TokenType.AMPERSAND)) {
      expression = new SuperExpression.full(andAdvance);
    } else {
      expression = parseShiftExpression();
    }
    while (matches5(TokenType.AMPERSAND)) {
      Token operator = andAdvance;
      expression = new BinaryExpression.full(expression, operator, parseShiftExpression());
    }
    return expression;
  }

  /**
   * Parse a bitwise or expression.
   *
   * <pre>
   * bitwiseOrExpression ::=
   *     bitwiseXorExpression ('|' bitwiseXorExpression)*
   *   | 'super' ('|' bitwiseXorExpression)+
   * </pre>
   *
   * @return the bitwise or expression that was parsed
   */
  Expression parseBitwiseOrExpression() {
    Expression expression;
    if (matches(Keyword.SUPER) && matches4(peek(), TokenType.BAR)) {
      expression = new SuperExpression.full(andAdvance);
    } else {
      expression = parseBitwiseXorExpression();
    }
    while (matches5(TokenType.BAR)) {
      Token operator = andAdvance;
      expression = new BinaryExpression.full(expression, operator, parseBitwiseXorExpression());
    }
    return expression;
  }

  /**
   * Parse a bitwise exclusive-or expression.
   *
   * <pre>
   * bitwiseXorExpression ::=
   *     bitwiseAndExpression ('^' bitwiseAndExpression)*
   *   | 'super' ('^' bitwiseAndExpression)+
   * </pre>
   *
   * @return the bitwise exclusive-or expression that was parsed
   */
  Expression parseBitwiseXorExpression() {
    Expression expression;
    if (matches(Keyword.SUPER) && matches4(peek(), TokenType.CARET)) {
      expression = new SuperExpression.full(andAdvance);
    } else {
      expression = parseBitwiseAndExpression();
    }
    while (matches5(TokenType.CARET)) {
      Token operator = andAdvance;
      expression = new BinaryExpression.full(expression, operator, parseBitwiseAndExpression());
    }
    return expression;
  }

  /**
   * Parse a block.
   *
   * <pre>
   * block ::=
   *     '{' statements '}'
   * </pre>
   *
   * @return the block that was parsed
   */
  Block parseBlock() {
    Token leftBracket = expect2(TokenType.OPEN_CURLY_BRACKET);
    List<Statement> statements = new List<Statement>();
    Token statementStart = _currentToken;
    while (!matches5(TokenType.EOF) && !matches5(TokenType.CLOSE_CURLY_BRACKET)) {
      Statement statement = parseStatement2();
      if (statement != null) {
        statements.add(statement);
      }
      if (identical(_currentToken, statementStart)) {
        reportError9(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_currentToken.lexeme]);
        advance();
      }
      statementStart = _currentToken;
    }
    Token rightBracket = expect2(TokenType.CLOSE_CURLY_BRACKET);
    return new Block.full(leftBracket, statements, rightBracket);
  }

  /**
   * Parse a break statement.
   *
   * <pre>
   * breakStatement ::=
   *     'break' identifier? ';'
   * </pre>
   *
   * @return the break statement that was parsed
   */
  Statement parseBreakStatement() {
    Token breakKeyword = expect(Keyword.BREAK);
    SimpleIdentifier label = null;
    if (matchesIdentifier()) {
      label = parseSimpleIdentifier();
    }
    if (!_inLoop && !_inSwitch && label == null) {
      reportError9(ParserErrorCode.BREAK_OUTSIDE_OF_LOOP, breakKeyword, []);
    }
    Token semicolon = expect2(TokenType.SEMICOLON);
    return new BreakStatement.full(breakKeyword, label, semicolon);
  }

  /**
   * Parse a cascade section.
   *
   * <pre>
   * cascadeSection ::=
   *     '..' (cascadeSelector arguments*) (assignableSelector arguments*)* cascadeAssignment?
   *
   * cascadeSelector ::=
   *     '[' expression ']'
   *   | identifier
   *
   * cascadeAssignment ::=
   *     assignmentOperator expressionWithoutCascade
   * </pre>
   *
   * @return the expression representing the cascaded method invocation
   */
  Expression parseCascadeSection() {
    Token period = expect2(TokenType.PERIOD_PERIOD);
    Expression expression = null;
    SimpleIdentifier functionName = null;
    if (matchesIdentifier()) {
      functionName = parseSimpleIdentifier();
    } else if (identical(_currentToken.type, TokenType.OPEN_SQUARE_BRACKET)) {
      Token leftBracket = andAdvance;
      Expression index = parseExpression2();
      Token rightBracket = expect2(TokenType.CLOSE_SQUARE_BRACKET);
      expression = new IndexExpression.forCascade_full(period, leftBracket, index, rightBracket);
      period = null;
    } else {
      reportError9(ParserErrorCode.MISSING_IDENTIFIER, _currentToken, [_currentToken.lexeme]);
      functionName = createSyntheticIdentifier();
    }
    if (identical(_currentToken.type, TokenType.OPEN_PAREN)) {
      while (identical(_currentToken.type, TokenType.OPEN_PAREN)) {
        if (functionName != null) {
          expression = new MethodInvocation.full(expression, period, functionName, parseArgumentList());
          period = null;
          functionName = null;
        } else if (expression == null) {
          expression = new MethodInvocation.full(expression, period, createSyntheticIdentifier(), parseArgumentList());
        } else {
          expression = new FunctionExpressionInvocation.full(expression, parseArgumentList());
        }
      }
    } else if (functionName != null) {
      expression = new PropertyAccess.full(expression, period, functionName);
      period = null;
    }
    bool progress = true;
    while (progress) {
      progress = false;
      Expression selector = parseAssignableSelector(expression, true);
      if (selector != expression) {
        expression = selector;
        progress = true;
        while (identical(_currentToken.type, TokenType.OPEN_PAREN)) {
          expression = new FunctionExpressionInvocation.full(expression, parseArgumentList());
        }
      }
    }
    if (_currentToken.type.isAssignmentOperator) {
      Token operator = andAdvance;
      ensureAssignable(expression);
      expression = new AssignmentExpression.full(expression, operator, parseExpressionWithoutCascade());
    }
    return expression;
  }

  /**
   * Parse a class declaration.
   *
   * <pre>
   * classDeclaration ::=
   *     metadata 'abstract'? 'class' name typeParameterList? (extendsClause withClause?)? implementsClause? '{' classMembers '}'
   * </pre>
   *
   * @param commentAndMetadata the metadata to be associated with the member
   * @param abstractKeyword the token for the keyword 'abstract', or `null` if the keyword was
   *          not given
   * @return the class declaration that was parsed
   */
  ClassDeclaration parseClassDeclaration(CommentAndMetadata commentAndMetadata, Token abstractKeyword) {
    Token keyword = expect(Keyword.CLASS);
    SimpleIdentifier name = parseSimpleIdentifier();
    String className = name.name;
    TypeParameterList typeParameters = null;
    if (matches5(TokenType.LT)) {
      typeParameters = parseTypeParameterList();
    }
    ExtendsClause extendsClause = null;
    WithClause withClause = null;
    ImplementsClause implementsClause = null;
    bool foundClause = true;
    while (foundClause) {
      if (matches(Keyword.EXTENDS)) {
        if (extendsClause == null) {
          extendsClause = parseExtendsClause();
          if (withClause != null) {
            reportError9(ParserErrorCode.WITH_BEFORE_EXTENDS, withClause.withKeyword, []);
          } else if (implementsClause != null) {
            reportError9(ParserErrorCode.IMPLEMENTS_BEFORE_EXTENDS, implementsClause.keyword, []);
          }
        } else {
          reportError9(ParserErrorCode.MULTIPLE_EXTENDS_CLAUSES, extendsClause.keyword, []);
          parseExtendsClause();
        }
      } else if (matches(Keyword.WITH)) {
        if (withClause == null) {
          withClause = parseWithClause();
          if (implementsClause != null) {
            reportError9(ParserErrorCode.IMPLEMENTS_BEFORE_WITH, implementsClause.keyword, []);
          }
        } else {
          reportError9(ParserErrorCode.MULTIPLE_WITH_CLAUSES, withClause.withKeyword, []);
          parseWithClause();
        }
      } else if (matches(Keyword.IMPLEMENTS)) {
        if (implementsClause == null) {
          implementsClause = parseImplementsClause();
        } else {
          reportError9(ParserErrorCode.MULTIPLE_IMPLEMENTS_CLAUSES, implementsClause.keyword, []);
          parseImplementsClause();
        }
      } else {
        foundClause = false;
      }
    }
    if (withClause != null && extendsClause == null) {
      reportError9(ParserErrorCode.WITH_WITHOUT_EXTENDS, withClause.withKeyword, []);
    }
    NativeClause nativeClause = null;
    if (matches2(_NATIVE) && matches4(peek(), TokenType.STRING)) {
      nativeClause = parseNativeClause();
    }
    Token leftBracket = null;
    List<ClassMember> members = null;
    Token rightBracket = null;
    if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
      leftBracket = expect2(TokenType.OPEN_CURLY_BRACKET);
      members = parseClassMembers(className, getEndToken(leftBracket));
      rightBracket = expect2(TokenType.CLOSE_CURLY_BRACKET);
    } else {
      leftBracket = createSyntheticToken2(TokenType.OPEN_CURLY_BRACKET);
      rightBracket = createSyntheticToken2(TokenType.CLOSE_CURLY_BRACKET);
      reportError8(ParserErrorCode.MISSING_CLASS_BODY, []);
    }
    ClassDeclaration classDeclaration = new ClassDeclaration.full(commentAndMetadata.comment, commentAndMetadata.metadata, abstractKeyword, keyword, name, typeParameters, extendsClause, withClause, implementsClause, leftBracket, members, rightBracket);
    classDeclaration.nativeClause = nativeClause;
    return classDeclaration;
  }

  /**
   * Parse a class member.
   *
   * <pre>
   * classMemberDefinition ::=
   *     declaration ';'
   *   | methodSignature functionBody
   * </pre>
   *
   * @param className 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
   */
  ClassMember parseClassMember(String className) {
    CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
    Modifiers modifiers = parseModifiers();
    if (matches(Keyword.VOID)) {
      TypeName returnType = parseReturnType();
      if (matches(Keyword.GET) && matchesIdentifier2(peek())) {
        validateModifiersForGetterOrSetterOrMethod(modifiers);
        return parseGetter(commentAndMetadata, modifiers.externalKeyword, modifiers.staticKeyword, returnType);
      } else if (matches(Keyword.SET) && matchesIdentifier2(peek())) {
        validateModifiersForGetterOrSetterOrMethod(modifiers);
        return parseSetter(commentAndMetadata, modifiers.externalKeyword, modifiers.staticKeyword, returnType);
      } else if (matches(Keyword.OPERATOR) && isOperator(peek())) {
        validateModifiersForOperator(modifiers);
        return parseOperator(commentAndMetadata, modifiers.externalKeyword, returnType);
      } else if (matchesIdentifier() && matchesAny(peek(), [
          TokenType.OPEN_PAREN,
          TokenType.OPEN_CURLY_BRACKET,
          TokenType.FUNCTION])) {
        validateModifiersForGetterOrSetterOrMethod(modifiers);
        return parseMethodDeclaration(commentAndMetadata, modifiers.externalKeyword, modifiers.staticKeyword, returnType);
      } else {
        if (matchesIdentifier()) {
          if (matchesAny(peek(), [TokenType.EQ, TokenType.COMMA, TokenType.SEMICOLON])) {
            reportError(ParserErrorCode.VOID_VARIABLE, returnType, []);
            return parseInitializedIdentifierList(commentAndMetadata, modifiers.staticKeyword, validateModifiersForField(modifiers), returnType);
          }
        }
        if (isOperator(_currentToken)) {
          validateModifiersForOperator(modifiers);
          return parseOperator(commentAndMetadata, modifiers.externalKeyword, returnType);
        }
        reportError9(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken, []);
        return null;
      }
    } else if (matches(Keyword.GET) && matchesIdentifier2(peek())) {
      validateModifiersForGetterOrSetterOrMethod(modifiers);
      return parseGetter(commentAndMetadata, modifiers.externalKeyword, modifiers.staticKeyword, null);
    } else if (matches(Keyword.SET) && matchesIdentifier2(peek())) {
      validateModifiersForGetterOrSetterOrMethod(modifiers);
      return parseSetter(commentAndMetadata, modifiers.externalKeyword, modifiers.staticKeyword, null);
    } else if (matches(Keyword.OPERATOR) && isOperator(peek())) {
      validateModifiersForOperator(modifiers);
      return parseOperator(commentAndMetadata, modifiers.externalKeyword, null);
    } else if (!matchesIdentifier()) {
      if (isOperator(_currentToken)) {
        validateModifiersForOperator(modifiers);
        return parseOperator(commentAndMetadata, modifiers.externalKeyword, null);
      }
      reportError9(ParserErrorCode.EXPECTED_CLASS_MEMBER, _currentToken, []);
      return null;
    } else if (matches4(peek(), TokenType.PERIOD) && matchesIdentifier2(peek2(2)) && matches4(peek2(3), TokenType.OPEN_PAREN)) {
      return parseConstructor(commentAndMetadata, modifiers.externalKeyword, validateModifiersForConstructor(modifiers), modifiers.factoryKeyword, parseSimpleIdentifier(), andAdvance, parseSimpleIdentifier(), parseFormalParameterList());
    } else if (matches4(peek(), TokenType.OPEN_PAREN)) {
      SimpleIdentifier methodName = parseSimpleIdentifier();
      FormalParameterList parameters = parseFormalParameterList();
      if (matches5(TokenType.COLON) || modifiers.factoryKeyword != null || methodName.name == className) {
        return parseConstructor(commentAndMetadata, modifiers.externalKeyword, validateModifiersForConstructor(modifiers), modifiers.factoryKeyword, methodName, null, null, parameters);
      }
      validateModifiersForGetterOrSetterOrMethod(modifiers);
      validateFormalParameterList(parameters);
      return parseMethodDeclaration2(commentAndMetadata, modifiers.externalKeyword, modifiers.staticKeyword, null, methodName, parameters);
    } else if (matchesAny(peek(), [TokenType.EQ, TokenType.COMMA, TokenType.SEMICOLON])) {
      if (modifiers.constKeyword == null && modifiers.finalKeyword == null && modifiers.varKeyword == null) {
        reportError8(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, []);
      }
      return parseInitializedIdentifierList(commentAndMetadata, modifiers.staticKeyword, validateModifiersForField(modifiers), null);
    }
    TypeName type = parseTypeName();
    if (matches(Keyword.GET) && matchesIdentifier2(peek())) {
      validateModifiersForGetterOrSetterOrMethod(modifiers);
      return parseGetter(commentAndMetadata, modifiers.externalKeyword, modifiers.staticKeyword, type);
    } else if (matches(Keyword.SET) && matchesIdentifier2(peek())) {
      validateModifiersForGetterOrSetterOrMethod(modifiers);
      return parseSetter(commentAndMetadata, modifiers.externalKeyword, modifiers.staticKeyword, type);
    } else if (matches(Keyword.OPERATOR) && isOperator(peek())) {
      validateModifiersForOperator(modifiers);
      return parseOperator(commentAndMetadata, modifiers.externalKeyword, type);
    } else if (!matchesIdentifier()) {
      if (matches5(TokenType.CLOSE_CURLY_BRACKET)) {
        return parseInitializedIdentifierList(commentAndMetadata, modifiers.staticKeyword, validateModifiersForField(modifiers), type);
      }
      if (isOperator(_currentToken)) {
        validateModifiersForOperator(modifiers);
        return parseOperator(commentAndMetadata, modifiers.externalKeyword, type);
      }
      reportError9(ParserErrorCode.EXPECTED_CLASS_MEMBER, _currentToken, []);
      return null;
    } else if (matches4(peek(), TokenType.OPEN_PAREN)) {
      SimpleIdentifier methodName = parseSimpleIdentifier();
      FormalParameterList parameters = parseFormalParameterList();
      if (methodName.name == className) {
        reportError(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, type, []);
        return parseConstructor(commentAndMetadata, modifiers.externalKeyword, validateModifiersForConstructor(modifiers), modifiers.factoryKeyword, methodName, null, null, parameters);
      }
      validateModifiersForGetterOrSetterOrMethod(modifiers);
      validateFormalParameterList(parameters);
      return parseMethodDeclaration2(commentAndMetadata, modifiers.externalKeyword, modifiers.staticKeyword, type, methodName, parameters);
    }
    return parseInitializedIdentifierList(commentAndMetadata, modifiers.staticKeyword, validateModifiersForField(modifiers), type);
  }

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

  /**
   * Parse a class type alias.
   *
   * <pre>
   * classTypeAlias ::=
   *     identifier typeParameters? '=' 'abstract'? mixinApplication
   *
   * mixinApplication ::=
   *     type withClause implementsClause? ';'
   * </pre>
   *
   * @param commentAndMetadata the metadata to be associated with the member
   * @param keyword the token representing the 'typedef' keyword
   * @return the class type alias that was parsed
   */
  ClassTypeAlias parseClassTypeAlias(CommentAndMetadata commentAndMetadata, Token keyword) {
    SimpleIdentifier className = parseSimpleIdentifier();
    TypeParameterList typeParameters = null;
    if (matches5(TokenType.LT)) {
      typeParameters = parseTypeParameterList();
    }
    Token equals = expect2(TokenType.EQ);
    Token abstractKeyword = null;
    if (matches(Keyword.ABSTRACT)) {
      abstractKeyword = andAdvance;
    }
    TypeName superclass = parseTypeName();
    WithClause withClause = null;
    if (matches(Keyword.WITH)) {
      withClause = parseWithClause();
    }
    ImplementsClause implementsClause = null;
    if (matches(Keyword.IMPLEMENTS)) {
      implementsClause = parseImplementsClause();
    }
    Token semicolon;
    if (matches5(TokenType.SEMICOLON)) {
      semicolon = andAdvance;
    } else {
      if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
        reportError8(ParserErrorCode.EXPECTED_TOKEN, [TokenType.SEMICOLON.lexeme]);
        Token leftBracket = andAdvance;
        parseClassMembers(className.name, getEndToken(leftBracket));
        expect2(TokenType.CLOSE_CURLY_BRACKET);
      } else {
        reportError9(ParserErrorCode.EXPECTED_TOKEN, _currentToken.previous, [TokenType.SEMICOLON.lexeme]);
      }
      semicolon = createSyntheticToken2(TokenType.SEMICOLON);
    }
    return new ClassTypeAlias.full(commentAndMetadata.comment, commentAndMetadata.metadata, keyword, className, typeParameters, equals, abstractKeyword, superclass, withClause, implementsClause, semicolon);
  }

  /**
   * Parse a list of combinators in a directive.
   *
   * <pre>
   * combinator ::=
   *     'show' identifier (',' identifier)*
   *   | 'hide' identifier (',' identifier)*
   * </pre>
   *
   * @return the combinators that were parsed
   */
  List<Combinator> parseCombinators() {
    List<Combinator> combinators = new List<Combinator>();
    while (matches2(_SHOW) || matches2(_HIDE)) {
      Token keyword = expect2(TokenType.IDENTIFIER);
      if (keyword.lexeme == _SHOW) {
        List<SimpleIdentifier> shownNames = parseIdentifierList();
        combinators.add(new ShowCombinator.full(keyword, shownNames));
      } else {
        List<SimpleIdentifier> hiddenNames = parseIdentifierList();
        combinators.add(new HideCombinator.full(keyword, hiddenNames));
      }
    }
    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.
   *
   * <pre>
   * metadata ::=
   *     annotation*
   * </pre>
   *
   * @return the documentation comment and metadata that were parsed
   */
  CommentAndMetadata parseCommentAndMetadata() {
    Comment comment = parseDocumentationComment();
    List<Annotation> metadata = new List<Annotation>();
    while (matches5(TokenType.AT)) {
      metadata.add(parseAnnotation());
      Comment optionalComment = parseDocumentationComment();
      if (optionalComment != null) {
        comment = optionalComment;
      }
    }
    return new CommentAndMetadata(comment, metadata);
  }

  /**
   * Parse a comment reference from the source between square brackets.
   *
   * <pre>
   * commentReference ::=
   *     'new'? prefixedIdentifier
   * </pre>
   *
   * @param referenceSource the source occurring between the square brackets within a documentation
   *          comment
   * @param sourceOffset 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 parseCommentReference(String referenceSource, int sourceOffset) {
    if (referenceSource.length == 0) {
      return null;
    }
    try {
      List<bool> errorFound = [false];
      AnalysisErrorListener listener = new AnalysisErrorListener_14(errorFound);
      StringScanner scanner = new StringScanner(null, referenceSource, listener);
      scanner.setSourceStart(1, 1, sourceOffset);
      Token firstToken = scanner.tokenize();
      if (errorFound[0]) {
        return null;
      }
      Token newKeyword = null;
      if (matches3(firstToken, Keyword.NEW)) {
        newKeyword = firstToken;
        firstToken = firstToken.next;
      }
      if (matchesIdentifier2(firstToken)) {
        Token secondToken = firstToken.next;
        Token thirdToken = secondToken.next;
        Token nextToken;
        Identifier identifier;
        if (matches4(secondToken, TokenType.PERIOD) && matchesIdentifier2(thirdToken)) {
          identifier = new PrefixedIdentifier.full(new SimpleIdentifier.full(firstToken), secondToken, new SimpleIdentifier.full(thirdToken));
          nextToken = thirdToken.next;
        } else {
          identifier = new SimpleIdentifier.full(firstToken);
          nextToken = firstToken.next;
        }
        if (nextToken.type != TokenType.EOF) {
          return null;
        }
        return new CommentReference.full(newKeyword, identifier);
      } else if (matches3(firstToken, Keyword.THIS) || matches3(firstToken, Keyword.NULL) || matches3(firstToken, Keyword.TRUE) || matches3(firstToken, Keyword.FALSE)) {
        return null;
      }
    } on JavaException catch (exception) {
    }
    return null;
  }

  /**
   * Parse all of the comment references occurring in the given array of documentation comments.
   *
   * <pre>
   * commentReference ::=
   *     '[' 'new'? qualified ']' libraryReference?
   *
   * libraryReference ::=
   *      '(' stringLiteral ')'
   * </pre>
   *
   * @param tokens the comment tokens representing the documentation comments to be parsed
   * @return the comment references that were parsed
   */
  List<CommentReference> parseCommentReferences(List<Token> tokens) {
    List<CommentReference> references = new List<CommentReference>();
    for (Token token in tokens) {
      String comment = token.lexeme;
      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 rightIndex = JavaString.indexOf(comment, ']', leftIndex);
          if (rightIndex >= 0) {
            int firstChar = comment.codeUnitAt(leftIndex + 1);
            if (firstChar != 0x27 && firstChar != 0x22) {
              if (isLinkText(comment, rightIndex)) {
              } else {
                CommentReference reference = parseCommentReference(comment.substring(leftIndex + 1, rightIndex), token.offset + leftIndex + 1);
                if (reference != null) {
                  references.add(reference);
                }
              }
            }
          } else {
            rightIndex = leftIndex + 1;
          }
          leftIndex = JavaString.indexOf(comment, '[', rightIndex);
        } else {
          leftIndex = JavaString.indexOf(comment, '[', range[1] + 1);
        }
      }
    }
    return references;
  }

  /**
   * Parse a compilation unit.
   *
   * Specified:
   *
   * <pre>
   * compilationUnit ::=
   *     scriptTag? directive* topLevelDeclaration*
   * </pre>
   * Actual:
   *
   * <pre>
   * compilationUnit ::=
   *     scriptTag? topLevelElement*
   *
   * topLevelElement ::=
   *     directive
   *   | topLevelDeclaration
   * </pre>
   *
   * @return the compilation unit that was parsed
   */
  CompilationUnit parseCompilationUnit2() {
    Token firstToken = _currentToken;
    ScriptTag scriptTag = null;
    if (matches5(TokenType.SCRIPT_TAG)) {
      scriptTag = new ScriptTag.full(andAdvance);
    }
    bool libraryDirectiveFound = false;
    bool partOfDirectiveFound = false;
    bool partDirectiveFound = false;
    bool directiveFoundAfterDeclaration = false;
    List<Directive> directives = new List<Directive>();
    List<CompilationUnitMember> declarations = new List<CompilationUnitMember>();
    Token memberStart = _currentToken;
    while (!matches5(TokenType.EOF)) {
      CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
      if ((matches(Keyword.IMPORT) || matches(Keyword.EXPORT) || matches(Keyword.LIBRARY) || matches(Keyword.PART)) && !matches4(peek(), TokenType.PERIOD) && !matches4(peek(), TokenType.LT)) {
        Directive directive = parseDirective(commentAndMetadata);
        if (declarations.length > 0 && !directiveFoundAfterDeclaration) {
          reportError8(ParserErrorCode.DIRECTIVE_AFTER_DECLARATION, []);
          directiveFoundAfterDeclaration = true;
        }
        if (directive is LibraryDirective) {
          if (libraryDirectiveFound) {
            reportError8(ParserErrorCode.MULTIPLE_LIBRARY_DIRECTIVES, []);
          } else {
            if (directives.length > 0) {
              reportError8(ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST, []);
            }
            libraryDirectiveFound = true;
          }
        } else if (directive is PartDirective) {
          partDirectiveFound = true;
        } else if (partDirectiveFound) {
          if (directive is ExportDirective) {
            reportError9(ParserErrorCode.EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE, ((directive as NamespaceDirective)).keyword, []);
          } else if (directive is ImportDirective) {
            reportError9(ParserErrorCode.IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE, ((directive as NamespaceDirective)).keyword, []);
          }
        }
        if (directive is PartOfDirective) {
          if (partOfDirectiveFound) {
            reportError8(ParserErrorCode.MULTIPLE_PART_OF_DIRECTIVES, []);
          } else {
            for (Directive precedingDirective in directives) {
              reportError9(ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART, precedingDirective.keyword, []);
            }
            partOfDirectiveFound = true;
          }
        } else {
          if (partOfDirectiveFound) {
            reportError9(ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART, directive.keyword, []);
          }
        }
        directives.add(directive);
      } else if (matches5(TokenType.SEMICOLON)) {
        reportError9(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_currentToken.lexeme]);
        advance();
      } else {
        CompilationUnitMember member = parseCompilationUnitMember(commentAndMetadata);
        if (member != null) {
          declarations.add(member);
        }
      }
      if (identical(_currentToken, memberStart)) {
        reportError9(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_currentToken.lexeme]);
        advance();
        while (!matches5(TokenType.EOF) && !couldBeStartOfCompilationUnitMember()) {
          advance();
        }
      }
      memberStart = _currentToken;
    }
    return new CompilationUnit.full(firstToken, scriptTag, directives, declarations, _currentToken);
  }

  /**
   * Parse a compilation unit member.
   *
   * <pre>
   * compilationUnitMember ::=
   *     classDefinition
   *   | functionTypeAlias
   *   | external functionSignature
   *   | external getterSignature
   *   | external setterSignature
   *   | functionSignature functionBody
   *   | returnType? getOrSet identifier formalParameterList functionBody
   *   | (final | const) type? staticFinalDeclarationList ';'
   *   | variableDeclaration ';'
   * </pre>
   *
   * @param commentAndMetadata 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 parseCompilationUnitMember(CommentAndMetadata commentAndMetadata) {
    Modifiers modifiers = parseModifiers();
    if (matches(Keyword.CLASS)) {
      return parseClassDeclaration(commentAndMetadata, validateModifiersForClass(modifiers));
    } else if (matches(Keyword.TYPEDEF) && !matches4(peek(), TokenType.PERIOD) && !matches4(peek(), TokenType.LT)) {
      validateModifiersForTypedef(modifiers);
      return parseTypeAlias(commentAndMetadata);
    }
    if (matches(Keyword.VOID)) {
      TypeName returnType = parseReturnType();
      if ((matches(Keyword.GET) || matches(Keyword.SET)) && matchesIdentifier2(peek())) {
        validateModifiersForTopLevelFunction(modifiers);
        return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKeyword, null);
      } else if (matches(Keyword.OPERATOR) && isOperator(peek())) {
        reportError9(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken, []);
        return convertToFunctionDeclaration(parseOperator(commentAndMetadata, modifiers.externalKeyword, returnType));
      } else if (matchesIdentifier() && matchesAny(peek(), [
          TokenType.OPEN_PAREN,
          TokenType.OPEN_CURLY_BRACKET,
          TokenType.FUNCTION])) {
        validateModifiersForTopLevelFunction(modifiers);
        return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKeyword, returnType);
      } else {
        if (matchesIdentifier()) {
          if (matchesAny(peek(), [TokenType.EQ, TokenType.COMMA, TokenType.SEMICOLON])) {
            reportError(ParserErrorCode.VOID_VARIABLE, returnType, []);
            return new TopLevelVariableDeclaration.full(commentAndMetadata.comment, commentAndMetadata.metadata, parseVariableDeclarationList2(null, validateModifiersForTopLevelVariable(modifiers), null), expect2(TokenType.SEMICOLON));
          }
        }
        reportError9(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken, []);
        return null;
      }
    } else if ((matches(Keyword.GET) || matches(Keyword.SET)) && matchesIdentifier2(peek())) {
      validateModifiersForTopLevelFunction(modifiers);
      return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKeyword, null);
    } else if (matches(Keyword.OPERATOR) && isOperator(peek())) {
      reportError9(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken, []);
      return convertToFunctionDeclaration(parseOperator(commentAndMetadata, modifiers.externalKeyword, null));
    } else if (!matchesIdentifier()) {
      reportError9(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken, []);
      return null;
    } else if (matches4(peek(), TokenType.OPEN_PAREN)) {
      validateModifiersForTopLevelFunction(modifiers);
      return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKeyword, null);
    } else if (matchesAny(peek(), [TokenType.EQ, TokenType.COMMA, TokenType.SEMICOLON])) {
      if (modifiers.constKeyword == null && modifiers.finalKeyword == null && modifiers.varKeyword == null) {
        reportError8(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, []);
      }
      return new TopLevelVariableDeclaration.full(commentAndMetadata.comment, commentAndMetadata.metadata, parseVariableDeclarationList2(null, validateModifiersForTopLevelVariable(modifiers), null), expect2(TokenType.SEMICOLON));
    }
    TypeName returnType = parseReturnType();
    if ((matches(Keyword.GET) || matches(Keyword.SET)) && matchesIdentifier2(peek())) {
      validateModifiersForTopLevelFunction(modifiers);
      return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKeyword, returnType);
    } else if (matches(Keyword.OPERATOR) && isOperator(peek())) {
      reportError9(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken, []);
      return convertToFunctionDeclaration(parseOperator(commentAndMetadata, modifiers.externalKeyword, returnType));
    } else if (matches5(TokenType.AT)) {
      return new TopLevelVariableDeclaration.full(commentAndMetadata.comment, commentAndMetadata.metadata, parseVariableDeclarationList2(null, validateModifiersForTopLevelVariable(modifiers), returnType), expect2(TokenType.SEMICOLON));
    } else if (!matchesIdentifier()) {
      reportError9(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken, []);
      Token semicolon;
      if (matches5(TokenType.SEMICOLON)) {
        semicolon = andAdvance;
      } else {
        semicolon = createSyntheticToken2(TokenType.SEMICOLON);
      }
      List<VariableDeclaration> variables = new List<VariableDeclaration>();
      variables.add(new VariableDeclaration.full(null, null, createSyntheticIdentifier(), null, null));
      return new TopLevelVariableDeclaration.full(commentAndMetadata.comment, commentAndMetadata.metadata, new VariableDeclarationList.full(null, null, null, returnType, variables), semicolon);
    }
    if (matchesAny(peek(), [
        TokenType.OPEN_PAREN,
        TokenType.FUNCTION,
        TokenType.OPEN_CURLY_BRACKET])) {
      validateModifiersForTopLevelFunction(modifiers);
      return parseFunctionDeclaration(commentAndMetadata, modifiers.externalKeyword, returnType);
    }
    return new TopLevelVariableDeclaration.full(commentAndMetadata.comment, commentAndMetadata.metadata, parseVariableDeclarationList2(null, validateModifiersForTopLevelVariable(modifiers), returnType), expect2(TokenType.SEMICOLON));
  }

  /**
   * Parse a conditional expression.
   *
   * <pre>
   * conditionalExpression ::=
   *     logicalOrExpression ('?' expressionWithoutCascade ':' expressionWithoutCascade)?
   * </pre>
   *
   * @return the conditional expression that was parsed
   */
  Expression parseConditionalExpression() {
    Expression condition = parseLogicalOrExpression();
    if (!matches5(TokenType.QUESTION)) {
      return condition;
    }
    Token question = andAdvance;
    Expression thenExpression = parseExpressionWithoutCascade();
    Token colon = expect2(TokenType.COLON);
    Expression elseExpression = parseExpressionWithoutCascade();
    return new ConditionalExpression.full(condition, question, thenExpression, colon, elseExpression);
  }

  /**
   * Parse a const expression.
   *
   * <pre>
   * constExpression ::=
   *     instanceCreationExpression
   *   | listLiteral
   *   | mapLiteral
   * </pre>
   *
   * @return the const expression that was parsed
   */
  Expression parseConstExpression() {
    Token keyword = expect(Keyword.CONST);
    if (matches5(TokenType.OPEN_SQUARE_BRACKET) || matches5(TokenType.INDEX)) {
      return parseListLiteral(keyword, null);
    } else if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
      return parseMapLiteral(keyword, null);
    } else if (matches5(TokenType.LT)) {
      return parseListOrMapLiteral(keyword);
    }
    return parseInstanceCreationExpression(keyword);
  }
  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 (matches5(TokenType.COLON)) {
      separator = andAdvance;
      initializers = new List<ConstructorInitializer>();
      do {
        if (matches(Keyword.THIS)) {
          if (matches4(peek(), TokenType.OPEN_PAREN)) {
            bodyAllowed = false;
            initializers.add(parseRedirectingConstructorInvocation());
          } else if (matches4(peek(), TokenType.PERIOD) && matches4(peek2(3), TokenType.OPEN_PAREN)) {
            bodyAllowed = false;
            initializers.add(parseRedirectingConstructorInvocation());
          } else {
            initializers.add(parseConstructorFieldInitializer());
          }
        } else if (matches(Keyword.SUPER)) {
          initializers.add(parseSuperConstructorInvocation());
        } else {
          initializers.add(parseConstructorFieldInitializer());
        }
      } while (optional(TokenType.COMMA));
    }
    ConstructorName redirectedConstructor = null;
    FunctionBody body;
    if (matches5(TokenType.EQ)) {
      separator = andAdvance;
      redirectedConstructor = parseConstructorName();
      body = new EmptyFunctionBody.full(expect2(TokenType.SEMICOLON));
      if (factoryKeyword == null) {
        reportError(ParserErrorCode.REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR, redirectedConstructor, []);
      }
    } else {
      body = parseFunctionBody(true, ParserErrorCode.MISSING_FUNCTION_BODY, false);
      if (constKeyword != null && factoryKeyword != null) {
        reportError9(ParserErrorCode.CONST_FACTORY, factoryKeyword, []);
      } else if (body is EmptyFunctionBody) {
        if (factoryKeyword != null && externalKeyword == null) {
          reportError9(ParserErrorCode.FACTORY_WITHOUT_BODY, factoryKeyword, []);
        }
      } else {
        if (constKeyword != null) {
          reportError(ParserErrorCode.CONST_CONSTRUCTOR_WITH_BODY, body, []);
        } else if (!bodyAllowed) {
          reportError(ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_BODY, body, []);
        }
      }
    }
    return new ConstructorDeclaration.full(commentAndMetadata.comment, commentAndMetadata.metadata, externalKeyword, constKeyword, factoryKeyword, returnType, period, name, parameters, separator, initializers, redirectedConstructor, body);
  }

  /**
   * Parse a field initializer within a constructor.
   *
   * <pre>
   * fieldInitializer:
   *     ('this' '.')? identifier '=' conditionalExpression cascadeSection*
   * </pre>
   *
   * @return the field initializer that was parsed
   */
  ConstructorFieldInitializer parseConstructorFieldInitializer() {
    Token keyword = null;
    Token period = null;
    if (matches(Keyword.THIS)) {
      keyword = andAdvance;
      period = expect2(TokenType.PERIOD);
    }
    SimpleIdentifier fieldName = parseSimpleIdentifier();
    Token equals = expect2(TokenType.EQ);
    Expression expression = parseConditionalExpression();
    TokenType tokenType = _currentToken.type;
    if (identical(tokenType, TokenType.PERIOD_PERIOD)) {
      List<Expression> cascadeSections = new List<Expression>();
      while (identical(tokenType, TokenType.PERIOD_PERIOD)) {
        Expression section = parseCascadeSection();
        if (section != null) {
          cascadeSections.add(section);
        }
        tokenType = _currentToken.type;
      }
      expression = new CascadeExpression.full(expression, cascadeSections);
    }
    return new ConstructorFieldInitializer.full(keyword, period, fieldName, equals, expression);
  }

  /**
   * Parse the name of a constructor.
   *
   * <pre>
   * constructorName:
   *     type ('.' identifier)?
   * </pre>
   *
   * @return the constructor name that was parsed
   */
  ConstructorName parseConstructorName() {
    TypeName type = parseTypeName();
    Token period = null;
    SimpleIdentifier name = null;
    if (matches5(TokenType.PERIOD)) {
      period = andAdvance;
      name = parseSimpleIdentifier();
    }
    return new ConstructorName.full(type, period, name);
  }

  /**
   * Parse a continue statement.
   *
   * <pre>
   * continueStatement ::=
   *     'continue' identifier? ';'
   * </pre>
   *
   * @return the continue statement that was parsed
   */
  Statement parseContinueStatement() {
    Token continueKeyword = expect(Keyword.CONTINUE);
    if (!_inLoop && !_inSwitch) {
      reportError9(ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP, continueKeyword, []);
    }
    SimpleIdentifier label = null;
    if (matchesIdentifier()) {
      label = parseSimpleIdentifier();
    }
    if (_inSwitch && !_inLoop && label == null) {
      reportError9(ParserErrorCode.CONTINUE_WITHOUT_LABEL_IN_CASE, continueKeyword, []);
    }
    Token semicolon = expect2(TokenType.SEMICOLON);
    return new ContinueStatement.full(continueKeyword, label, semicolon);
  }

  /**
   * Parse a directive.
   *
   * <pre>
   * directive ::=
   *     exportDirective
   *   | libraryDirective
   *   | importDirective
   *   | partDirective
   * </pre>
   *
   * @param commentAndMetadata the metadata to be associated with the directive
   * @return the directive that was parsed
   */
  Directive parseDirective(CommentAndMetadata commentAndMetadata) {
    if (matches(Keyword.IMPORT)) {
      return parseImportDirective(commentAndMetadata);
    } else if (matches(Keyword.EXPORT)) {
      return parseExportDirective(commentAndMetadata);
    } else if (matches(Keyword.LIBRARY)) {
      return parseLibraryDirective(commentAndMetadata);
    } else if (matches(Keyword.PART)) {
      return parsePartDirective(commentAndMetadata);
    } else {
      throw new IllegalStateException("parseDirective invoked in an invalid state; currentToken = ${_currentToken}");
    }
  }

  /**
   * Parse a documentation comment.
   *
   * <pre>
   * documentationComment ::=
   *     multiLineComment?
   *   | singleLineComment*
   * </pre>
   *
   * @return the documentation comment that was parsed, or `null` if there was no comment
   */
  Comment parseDocumentationComment() {
    List<Token> commentTokens = new List<Token>();
    Token commentToken = _currentToken.precedingComments;
    while (commentToken != null) {
      if (identical(commentToken.type, TokenType.SINGLE_LINE_COMMENT)) {
        if (commentToken.lexeme.startsWith("///")) {
          if (commentTokens.length == 1 && commentTokens[0].lexeme.startsWith("/**")) {
            commentTokens.clear();
          }
          commentTokens.add(commentToken);
        }
      } else {
        if (commentToken.lexeme.startsWith("/**")) {
          commentTokens.clear();
          commentTokens.add(commentToken);
        }
      }
      commentToken = commentToken.next;
    }
    if (commentTokens.isEmpty) {
      return null;
    }
    List<Token> tokens = new List.from(commentTokens);
    List<CommentReference> references = parseCommentReferences(tokens);
    return Comment.createDocumentationComment2(tokens, references);
  }

  /**
   * Parse a do statement.
   *
   * <pre>
   * doStatement ::=
   *     'do' statement 'while' '(' expression ')' ';'
   * </pre>
   *
   * @return the do statement that was parsed
   */
  Statement parseDoStatement() {
    bool wasInLoop = _inLoop;
    _inLoop = true;
    try {
      Token doKeyword = expect(Keyword.DO);
      Statement body = parseStatement2();
      Token whileKeyword = expect(Keyword.WHILE);
      Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
      Expression condition = parseExpression2();
      Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
      Token semicolon = expect2(TokenType.SEMICOLON);
      return new DoStatement.full(doKeyword, body, whileKeyword, leftParenthesis, condition, rightParenthesis, semicolon);
    } finally {
      _inLoop = wasInLoop;
    }
  }

  /**
   * Parse an empty statement.
   *
   * <pre>
   * emptyStatement ::=
   *     ';'
   * </pre>
   *
   * @return the empty statement that was parsed
   */
  Statement parseEmptyStatement() => new EmptyStatement.full(andAdvance);

  /**
   * Parse an equality expression.
   *
   * <pre>
   * equalityExpression ::=
   *     relationalExpression (equalityOperator relationalExpression)?
   *   | 'super' equalityOperator relationalExpression
   * </pre>
   *
   * @return the equality expression that was parsed
   */
  Expression parseEqualityExpression() {
    Expression expression;
    if (matches(Keyword.SUPER) && _currentToken.next.type.isEqualityOperator) {
      expression = new SuperExpression.full(andAdvance);
    } else {
      expression = parseRelationalExpression();
    }
    bool leftEqualityExpression = false;
    while (_currentToken.type.isEqualityOperator) {
      Token operator = andAdvance;
      if (leftEqualityExpression) {
        reportError(ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND, expression, []);
      }
      expression = new BinaryExpression.full(expression, operator, parseRelationalExpression());
      leftEqualityExpression = true;
    }
    return expression;
  }

  /**
   * Parse an export directive.
   *
   * <pre>
   * exportDirective ::=
   *     metadata 'export' stringLiteral combinator*';'
   * </pre>
   *
   * @param commentAndMetadata the metadata to be associated with the directive
   * @return the export directive that was parsed
   */
  ExportDirective parseExportDirective(CommentAndMetadata commentAndMetadata) {
    Token exportKeyword = expect(Keyword.EXPORT);
    StringLiteral libraryUri = parseStringLiteral();
    List<Combinator> combinators = parseCombinators();
    Token semicolon = expect2(TokenType.SEMICOLON);
    return new ExportDirective.full(commentAndMetadata.comment, commentAndMetadata.metadata, exportKeyword, libraryUri, combinators, semicolon);
  }

  /**
   * Parse an expression that does not contain any cascades.
   *
   * <pre>
   * expression ::=
   *     assignableExpression assignmentOperator expression
   *   | conditionalExpression cascadeSection*
   *   | throwExpression
   * </pre>
   *
   * @return the expression that was parsed
   */
  Expression parseExpression2() {
    if (matches(Keyword.THROW)) {
      return parseThrowExpression();
    } else if (matches(Keyword.RETHROW)) {
      return parseRethrowExpression();
    }
    Expression expression = parseConditionalExpression();
    TokenType tokenType = _currentToken.type;
    if (identical(tokenType, TokenType.PERIOD_PERIOD)) {
      List<Expression> cascadeSections = new List<Expression>();
      while (identical(tokenType, TokenType.PERIOD_PERIOD)) {
        Expression section = parseCascadeSection();
        if (section != null) {
          cascadeSections.add(section);
        }
        tokenType = _currentToken.type;
      }
      return new CascadeExpression.full(expression, cascadeSections);
    } else if (tokenType.isAssignmentOperator) {
      Token operator = andAdvance;
      ensureAssignable(expression);
      return new AssignmentExpression.full(expression, operator, parseExpression2());
    }
    return expression;
  }

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

  /**
   * Parse an expression that does not contain any cascades.
   *
   * <pre>
   * expressionWithoutCascade ::=
   *     assignableExpression assignmentOperator expressionWithoutCascade
   *   | conditionalExpression
   *   | throwExpressionWithoutCascade
   * </pre>
   *
   * @return the expression that was parsed
   */
  Expression parseExpressionWithoutCascade() {
    if (matches(Keyword.THROW)) {
      return parseThrowExpressionWithoutCascade();
    } else if (matches(Keyword.RETHROW)) {
      return parseRethrowExpression();
    }
    Expression expression = parseConditionalExpression();
    if (_currentToken.type.isAssignmentOperator) {
      Token operator = andAdvance;
      ensureAssignable(expression);
      expression = new AssignmentExpression.full(expression, operator, parseExpressionWithoutCascade());
    }
    return expression;
  }

  /**
   * Parse a class extends clause.
   *
   * <pre>
   * classExtendsClause ::=
   *     'extends' type
   * </pre>
   *
   * @return the class extends clause that was parsed
   */
  ExtendsClause parseExtendsClause() {
    Token keyword = expect(Keyword.EXTENDS);
    TypeName superclass = parseTypeName();
    return new ExtendsClause.full(keyword, superclass);
  }

  /**
   * Parse the 'final', 'const', 'var' or type preceding a variable declaration.
   *
   * <pre>
   * finalConstVarOrType ::=
   *   | 'final' type?
   *   | 'const' type?
   *   | 'var'
   *   | type
   * </pre>
   *
   * @param optional `true` if the keyword and type are optional
   * @return the 'final', 'const', 'var' or type that was parsed
   */
  FinalConstVarOrType parseFinalConstVarOrType(bool optional) {
    Token keyword = null;
    TypeName type = null;
    if (matches(Keyword.FINAL) || matches(Keyword.CONST)) {
      keyword = andAdvance;
      if (isTypedIdentifier(_currentToken)) {
        type = parseTypeName();
      }
    } else if (matches(Keyword.VAR)) {
      keyword = andAdvance;
    } else {
      if (isTypedIdentifier(_currentToken)) {
        type = parseReturnType();
      } else if (!optional) {
        reportError8(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, []);
      }
    }
    return new FinalConstVarOrType(keyword, type);
  }

  /**
   * Parse a formal parameter. At most one of `isOptional` and `isNamed` can be
   * `true`.
   *
   * <pre>
   * defaultFormalParameter ::=
   *     normalFormalParameter ('=' expression)?
   *
   * defaultNamedParameter ::=
   *     normalFormalParameter (':' expression)?
   * </pre>
   *
   * @param kind the kind of parameter being expected based on the presence or absence of group
   *          delimiters
   * @return the formal parameter that was parsed
   */
  FormalParameter parseFormalParameter(ParameterKind kind) {
    NormalFormalParameter parameter = parseNormalFormalParameter();
    if (matches5(TokenType.EQ)) {
      Token seperator = andAdvance;
      Expression defaultValue = parseExpression2();
      if (identical(kind, ParameterKind.NAMED)) {
        reportError9(ParserErrorCode.WRONG_SEPARATOR_FOR_NAMED_PARAMETER, seperator, []);
      } else if (identical(kind, ParameterKind.REQUIRED)) {
        reportError(ParserErrorCode.POSITIONAL_PARAMETER_OUTSIDE_GROUP, parameter, []);
      }
      return new DefaultFormalParameter.full(parameter, kind, seperator, defaultValue);
    } else if (matches5(TokenType.COLON)) {
      Token seperator = andAdvance;
      Expression defaultValue = parseExpression2();
      if (identical(kind, ParameterKind.POSITIONAL)) {
        reportError9(ParserErrorCode.WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER, seperator, []);
      } else if (identical(kind, ParameterKind.REQUIRED)) {
        reportError(ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP, parameter, []);
      }
      return new DefaultFormalParameter.full(parameter, kind, seperator, defaultValue);
    } else if (kind != ParameterKind.REQUIRED) {
      return new DefaultFormalParameter.full(parameter, kind, null, null);
    }
    return parameter;
  }

  /**
   * Parse a list of formal parameters.
   *
   * <pre>
   * formalParameterList ::=
   *     '(' ')'
   *   | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
   *   | '(' optionalFormalParameters ')'
   *
   * normalFormalParameters ::=
   *     normalFormalParameter (',' normalFormalParameter)*
   *
   * optionalFormalParameters ::=
   *     optionalPositionalFormalParameters
   *   | namedFormalParameters
   *
   * optionalPositionalFormalParameters ::=
   *     '[' defaultFormalParameter (',' defaultFormalParameter)* ']'
   *
   * namedFormalParameters ::=
   *     '{' defaultNamedParameter (',' defaultNamedParameter)* '}'
   * </pre>
   *
   * @return the formal parameters that were parsed
   */
  FormalParameterList parseFormalParameterList() {
    Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
    if (matches5(TokenType.CLOSE_PAREN)) {
      return new FormalParameterList.full(leftParenthesis, null, null, null, andAdvance);
    }
    List<FormalParameter> parameters = new List<FormalParameter>();
    List<FormalParameter> normalParameters = new List<FormalParameter>();
    List<FormalParameter> positionalParameters = new List<FormalParameter>();
    List<FormalParameter> namedParameters = new List<FormalParameter>();
    List<FormalParameter> currentParameters = normalParameters;
    Token leftSquareBracket = null;
    Token rightSquareBracket = null;
    Token leftCurlyBracket = null;
    Token rightCurlyBracket = null;
    ParameterKind kind = ParameterKind.REQUIRED;
    bool firstParameter = true;
    bool reportedMuliplePositionalGroups = false;
    bool reportedMulipleNamedGroups = false;
    bool reportedMixedGroups = false;
    bool wasOptionalParameter = false;
    Token initialToken = null;
    do {
      if (firstParameter) {
        firstParameter = false;
      } else if (!optional(TokenType.COMMA)) {
        if (getEndToken(leftParenthesis) != null) {
          reportError8(ParserErrorCode.EXPECTED_TOKEN, [TokenType.COMMA.lexeme]);
        } else {
          reportError9(ParserErrorCode.MISSING_CLOSING_PARENTHESIS, _currentToken.previous, []);
          break;
        }
      }
      initialToken = _currentToken;
      if (matches5(TokenType.OPEN_SQUARE_BRACKET)) {
        wasOptionalParameter = true;
        if (leftSquareBracket != null && !reportedMuliplePositionalGroups) {
          reportError8(ParserErrorCode.MULTIPLE_POSITIONAL_PARAMETER_GROUPS, []);
          reportedMuliplePositionalGroups = true;
        }
        if (leftCurlyBracket != null && !reportedMixedGroups) {
          reportError8(ParserErrorCode.MIXED_PARAMETER_GROUPS, []);
          reportedMixedGroups = true;
        }
        leftSquareBracket = andAdvance;
        currentParameters = positionalParameters;
        kind = ParameterKind.POSITIONAL;
      } else if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
        wasOptionalParameter = true;
        if (leftCurlyBracket != null && !reportedMulipleNamedGroups) {
          reportError8(ParserErrorCode.MULTIPLE_NAMED_PARAMETER_GROUPS, []);
          reportedMulipleNamedGroups = true;
        }
        if (leftSquareBracket != null && !reportedMixedGroups) {
          reportError8(ParserErrorCode.MIXED_PARAMETER_GROUPS, []);
          reportedMixedGroups = true;
        }
        leftCurlyBracket = andAdvance;
        currentParameters = namedParameters;
        kind = ParameterKind.NAMED;
      }
      FormalParameter parameter = parseFormalParameter(kind);
      parameters.add(parameter);
      currentParameters.add(parameter);
      if (identical(kind, ParameterKind.REQUIRED) && wasOptionalParameter) {
        reportError(ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS, parameter, []);
      }
      if (matches5(TokenType.CLOSE_SQUARE_BRACKET)) {
        rightSquareBracket = andAdvance;
        currentParameters = normalParameters;
        if (leftSquareBracket == null) {
          if (leftCurlyBracket != null) {
            reportError8(ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP, ["}"]);
            rightCurlyBracket = rightSquareBracket;
            rightSquareBracket = null;
          } else {
            reportError8(ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP, ["["]);
          }
        }
        kind = ParameterKind.REQUIRED;
      } else if (matches5(TokenType.CLOSE_CURLY_BRACKET)) {
        rightCurlyBracket = andAdvance;
        currentParameters = normalParameters;
        if (leftCurlyBracket == null) {
          if (leftSquareBracket != null) {
            reportError8(ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP, ["]"]);
            rightSquareBracket = rightCurlyBracket;
            rightCurlyBracket = null;
          } else {
            reportError8(ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP, ["{"]);
          }
        }
        kind = ParameterKind.REQUIRED;
      }
    } while (!matches5(TokenType.CLOSE_PAREN) && initialToken != _currentToken);
    Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
    if (leftSquareBracket != null && rightSquareBracket == null) {
      reportError8(ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP, ["]"]);
    }
    if (leftCurlyBracket != null && rightCurlyBracket == null) {
      reportError8(ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP, ["}"]);
    }
    if (leftSquareBracket == null) {
      leftSquareBracket = leftCurlyBracket;
    }
    if (rightSquareBracket == null) {
      rightSquareBracket = rightCurlyBracket;
    }
    return new FormalParameterList.full(leftParenthesis, parameters, leftSquareBracket, rightSquareBracket, rightParenthesis);
  }

  /**
   * Parse a for statement.
   *
   * <pre>
   * forStatement ::=
   *     'for' '(' forLoopParts ')' statement
   *
   * forLoopParts ::=
   *     forInitializerStatement expression? ';' expressionList?
   *   | declaredIdentifier 'in' expression
   *   | identifier 'in' expression
   *
   * forInitializerStatement ::=
   *     localVariableDeclaration ';'
   *   | expression? ';'
   * </pre>
   *
   * @return the for statement that was parsed
   */
  Statement parseForStatement() {
    bool wasInLoop = _inLoop;
    _inLoop = true;
    try {
      Token forKeyword = expect(Keyword.FOR);
      Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
      VariableDeclarationList variableList = null;
      Expression initialization = null;
      if (!matches5(TokenType.SEMICOLON)) {
        CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
        if (matchesIdentifier() && matches3(peek(), Keyword.IN)) {
          List<VariableDeclaration> variables = new List<VariableDeclaration>();
          SimpleIdentifier variableName = parseSimpleIdentifier();
          variables.add(new VariableDeclaration.full(null, null, variableName, null, null));
          variableList = new VariableDeclarationList.full(commentAndMetadata.comment, commentAndMetadata.metadata, null, null, variables);
        } else if (isInitializedVariableDeclaration()) {
          variableList = parseVariableDeclarationList(commentAndMetadata);
        } else {
          initialization = parseExpression2();
        }
        if (matches(Keyword.IN)) {
          DeclaredIdentifier loopVariable = null;
          SimpleIdentifier identifier = null;
          if (variableList == null) {
            reportError8(ParserErrorCode.MISSING_VARIABLE_IN_FOR_EACH, []);
          } else {
            NodeList<VariableDeclaration> variables = variableList.variables;
            if (variables.length > 1) {
              reportError8(ParserErrorCode.MULTIPLE_VARIABLES_IN_FOR_EACH, [variables.length.toString()]);
            }
            VariableDeclaration variable = variables[0];
            if (variable.initializer != null) {
              reportError8(ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH, []);
            }
            Token keyword = variableList.keyword;
            TypeName type = variableList.type;
            if (keyword != null || type != null) {
              loopVariable = new DeclaredIdentifier.full(commentAndMetadata.comment, commentAndMetadata.metadata, keyword, type, variable.name);
            } else {
              if (!commentAndMetadata.metadata.isEmpty) {
              }
              identifier = variable.name;
            }
          }
          Token inKeyword = expect(Keyword.IN);
          Expression iterator = parseExpression2();
          Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
          Statement body = parseStatement2();
          if (loopVariable == null) {
            return new ForEachStatement.con2_full(forKeyword, leftParenthesis, identifier, inKeyword, iterator, rightParenthesis, body);
          }
          return new ForEachStatement.con1_full(forKeyword, leftParenthesis, loopVariable, inKeyword, iterator, rightParenthesis, body);
        }
      }
      Token leftSeparator = expect2(TokenType.SEMICOLON);
      Expression condition = null;
      if (!matches5(TokenType.SEMICOLON)) {
        condition = parseExpression2();
      }
      Token rightSeparator = expect2(TokenType.SEMICOLON);
      List<Expression> updaters = null;
      if (!matches5(TokenType.CLOSE_PAREN)) {
        updaters = parseExpressionList();
      }
      Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
      Statement body = parseStatement2();
      return new ForStatement.full(forKeyword, leftParenthesis, variableList, initialization, leftSeparator, condition, rightSeparator, updaters, rightParenthesis, body);
    } finally {
      _inLoop = wasInLoop;
    }
  }

  /**
   * Parse a function body.
   *
   * <pre>
   * functionBody ::=
   *     '=>' expression ';'
   *   | block
   *
   * functionExpressionBody ::=
   *     '=>' expression
   *   | block
   * </pre>
   *
   * @param mayBeEmpty `true` if the function body is allowed to be empty
   * @param emptyErrorCode the error code to report if function body expecte, but not found
   * @param inExpression `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 parseFunctionBody(bool mayBeEmpty, ParserErrorCode emptyErrorCode, bool inExpression) {
    bool wasInLoop = _inLoop;
    bool wasInSwitch = _inSwitch;
    _inLoop = false;
    _inSwitch = false;
    try {
      if (matches5(TokenType.SEMICOLON)) {
        if (!mayBeEmpty) {
          reportError8(emptyErrorCode, []);
        }
        return new EmptyFunctionBody.full(andAdvance);
      } else if (matches5(TokenType.FUNCTION)) {
        Token functionDefinition = andAdvance;
        Expression expression = parseExpression2();
        Token semicolon = null;
        if (!inExpression) {
          semicolon = expect2(TokenType.SEMICOLON);
        }
        return new ExpressionFunctionBody.full(functionDefinition, expression, semicolon);
      } else if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
        return new BlockFunctionBody.full(parseBlock());
      } else if (matches2(_NATIVE)) {
        Token nativeToken = andAdvance;
        StringLiteral stringLiteral = null;
        if (matches5(TokenType.STRING)) {
          stringLiteral = parseStringLiteral();
        }
        return new NativeFunctionBody.full(nativeToken, stringLiteral, expect2(TokenType.SEMICOLON));
      } else {
        reportError8(emptyErrorCode, []);
        return new EmptyFunctionBody.full(createSyntheticToken2(TokenType.SEMICOLON));
      }
    } finally {
      _inLoop = wasInLoop;
      _inSwitch = wasInSwitch;
    }
  }

  /**
   * Parse a function declaration.
   *
   * <pre>
   * functionDeclaration ::=
   *     functionSignature functionBody
   *   | returnType? getOrSet identifier formalParameterList functionBody
   * </pre>
   *
   * @param commentAndMetadata the documentation comment and metadata to be associated with the
   *          declaration
   * @param externalKeyword the 'external' keyword, or `null` if the function is not external
   * @param returnType the return type, or `null` if there is no return type
   * @param isStatement `true` if the function declaration is being parsed as a statement
   * @return the function declaration that was parsed
   */
  FunctionDeclaration parseFunctionDeclaration(CommentAndMetadata commentAndMetadata, Token externalKeyword, TypeName returnType) {
    Token keyword = null;
    bool isGetter = false;
    if (matches(Keyword.GET) && !matches4(peek(), TokenType.OPEN_PAREN)) {
      keyword = andAdvance;
      isGetter = true;
    } else if (matches(Keyword.SET) && !matches4(peek(), TokenType.OPEN_PAREN)) {
      keyword = andAdvance;
    }
    SimpleIdentifier name = parseSimpleIdentifier();
    FormalParameterList parameters = null;
    if (!isGetter) {
      if (matches5(TokenType.OPEN_PAREN)) {
        parameters = parseFormalParameterList();
        validateFormalParameterList(parameters);
      } else {
        reportError8(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, []);
      }
    } else if (matches5(TokenType.OPEN_PAREN)) {
      reportError8(ParserErrorCode.GETTER_WITH_PARAMETERS, []);
      parseFormalParameterList();
    }
    FunctionBody body;
    if (externalKeyword == null) {
      body = parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTION_BODY, false);
    } else {
      body = new EmptyFunctionBody.full(expect2(TokenType.SEMICOLON));
    }
    return new FunctionDeclaration.full(commentAndMetadata.comment, commentAndMetadata.metadata, externalKeyword, returnType, keyword, name, new FunctionExpression.full(parameters, body));
  }

  /**
   * Parse a function declaration statement.
   *
   * <pre>
   * functionDeclarationStatement ::=
   *     functionSignature functionBody
   * </pre>
   *
   * @return the function declaration statement that was parsed
   */
  Statement parseFunctionDeclarationStatement() {
    Modifiers modifiers = parseModifiers();
    validateModifiersForFunctionDeclarationStatement(modifiers);
    return parseFunctionDeclarationStatement2(parseCommentAndMetadata(), parseOptionalReturnType());
  }

  /**
   * Parse a function declaration statement.
   *
   * <pre>
   * functionDeclarationStatement ::=
   *     functionSignature functionBody
   * </pre>
   *
   * @param commentAndMetadata the documentation comment and metadata to be associated with the
   *          declaration
   * @param returnType the return type, or `null` if there is no return type
   * @return the function declaration statement that was parsed
   */
  Statement parseFunctionDeclarationStatement2(CommentAndMetadata commentAndMetadata, TypeName returnType) {
    FunctionDeclaration declaration = parseFunctionDeclaration(commentAndMetadata, null, returnType);
    Token propertyKeyword = declaration.propertyKeyword;
    if (propertyKeyword != null) {
      if (identical(((propertyKeyword as KeywordToken)).keyword, Keyword.GET)) {
        reportError9(ParserErrorCode.GETTER_IN_FUNCTION, propertyKeyword, []);
      } else {
        reportError9(ParserErrorCode.SETTER_IN_FUNCTION, propertyKeyword, []);
      }
    }
    return new FunctionDeclarationStatement.full(declaration);
  }

  /**
   * Parse a function expression.
   *
   * <pre>
   * functionExpression ::=
   *     formalParameterList functionExpressionBody
   * </pre>
   *
   * @return the function expression that was parsed
   */
  FunctionExpression parseFunctionExpression() {
    FormalParameterList parameters = parseFormalParameterList();
    validateFormalParameterList(parameters);
    FunctionBody body = parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTION_BODY, true);
    return new FunctionExpression.full(parameters, body);
  }

  /**
   * Parse a function type alias.
   *
   * <pre>
   * functionTypeAlias ::=
   *     functionPrefix typeParameterList? formalParameterList ';'
   *
   * functionPrefix ::=
   *     returnType? name
   * </pre>
   *
   * @param commentAndMetadata the metadata to be associated with the member
   * @param keyword the token representing the 'typedef' keyword
   * @return the function type alias that was parsed
   */
  FunctionTypeAlias parseFunctionTypeAlias(CommentAndMetadata commentAndMetadata, Token keyword) {
    TypeName returnType = null;
    if (hasReturnTypeInTypeAlias()) {
      returnType = parseReturnType();
    }
    SimpleIdentifier name = parseSimpleIdentifier();
    TypeParameterList typeParameters = null;
    if (matches5(TokenType.LT)) {
      typeParameters = parseTypeParameterList();
    }
    if (matches5(TokenType.SEMICOLON) || matches5(TokenType.EOF)) {
      reportError8(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, []);
      FormalParameterList parameters = new FormalParameterList.full(createSyntheticToken2(TokenType.OPEN_PAREN), null, null, null, createSyntheticToken2(TokenType.CLOSE_PAREN));
      Token semicolon = expect2(TokenType.SEMICOLON);
      return new FunctionTypeAlias.full(commentAndMetadata.comment, commentAndMetadata.metadata, keyword, returnType, name, typeParameters, parameters, semicolon);
    } else if (!matches5(TokenType.OPEN_PAREN)) {
      reportError8(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, []);
      return new FunctionTypeAlias.full(commentAndMetadata.comment, commentAndMetadata.metadata, keyword, returnType, name, typeParameters, new FormalParameterList.full(createSyntheticToken2(TokenType.OPEN_PAREN), null, null, null, createSyntheticToken2(TokenType.CLOSE_PAREN)), createSyntheticToken2(TokenType.SEMICOLON));
    }
    FormalParameterList parameters = parseFormalParameterList();
    validateFormalParameterList(parameters);
    Token semicolon = expect2(TokenType.SEMICOLON);
    return new FunctionTypeAlias.full(commentAndMetadata.comment, commentAndMetadata.metadata, keyword, returnType, name, typeParameters, parameters, semicolon);
  }

  /**
   * Parse a getter.
   *
   * <pre>
   * getter ::=
   *     getterSignature functionBody?
   *
   * getterSignature ::=
   *     'external'? 'static'? returnType? 'get' identifier
   * </pre>
   *
   * @param commentAndMetadata the documentation comment and metadata to be associated with the
   *          declaration
   * @param externalKeyword the 'external' token
   * @param staticKeyword the static keyword, or `null` if the getter is not static
   * @param the return type that has already been parsed, or `null` if there was no return
   *          type
   * @return the getter that was parsed
   */
  MethodDeclaration parseGetter(CommentAndMetadata commentAndMetadata, Token externalKeyword, Token staticKeyword, TypeName returnType) {
    Token propertyKeyword = expect(Keyword.GET);
    SimpleIdentifier name = parseSimpleIdentifier();
    if (matches5(TokenType.OPEN_PAREN) && matches4(peek(), TokenType.CLOSE_PAREN)) {
      reportError8(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) {
      reportError8(ParserErrorCode.EXTERNAL_GETTER_WITH_BODY, []);
    }
    return new MethodDeclaration.full(commentAndMetadata.comment, commentAndMetadata.metadata, externalKeyword, staticKeyword, returnType, propertyKeyword, null, name, null, body);
  }

  /**
   * Parse a list of identifiers.
   *
   * <pre>
   * identifierList ::=
   *     identifier (',' identifier)*
   * </pre>
   *
   * @return the list of identifiers that were parsed
   */
  List<SimpleIdentifier> parseIdentifierList() {
    List<SimpleIdentifier> identifiers = new List<SimpleIdentifier>();
    identifiers.add(parseSimpleIdentifier());
    while (matches5(TokenType.COMMA)) {
      advance();
      identifiers.add(parseSimpleIdentifier());
    }
    return identifiers;
  }

  /**
   * Parse an if statement.
   *
   * <pre>
   * ifStatement ::=
   *     'if' '(' expression ')' statement ('else' statement)?
   * </pre>
   *
   * @return the if statement that was parsed
   */
  Statement parseIfStatement() {
    Token ifKeyword = expect(Keyword.IF);
    Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
    Expression condition = parseExpression2();
    Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
    Statement thenStatement = parseStatement2();
    Token elseKeyword = null;
    Statement elseStatement = null;
    if (matches(Keyword.ELSE)) {
      elseKeyword = andAdvance;
      elseStatement = parseStatement2();
    }
    return new IfStatement.full(ifKeyword, leftParenthesis, condition, rightParenthesis, thenStatement, elseKeyword, elseStatement);
  }

  /**
   * Parse an implements clause.
   *
   * <pre>
   * implementsClause ::=
   *     'implements' type (',' type)*
   * </pre>
   *
   * @return the implements clause that was parsed
   */
  ImplementsClause parseImplementsClause() {
    Token keyword = expect(Keyword.IMPLEMENTS);
    List<TypeName> interfaces = new List<TypeName>();
    interfaces.add(parseTypeName());
    while (optional(TokenType.COMMA)) {
      interfaces.add(parseTypeName());
    }
    return new ImplementsClause.full(keyword, interfaces);
  }

  /**
   * Parse an import directive.
   *
   * <pre>
   * importDirective ::=
   *     metadata 'import' stringLiteral ('as' identifier)? combinator*';'
   * </pre>
   *
   * @param commentAndMetadata the metadata to be associated with the directive
   * @return the import directive that was parsed
   */
  ImportDirective parseImportDirective(CommentAndMetadata commentAndMetadata) {
    Token importKeyword = expect(Keyword.IMPORT);
    StringLiteral libraryUri = parseStringLiteral();
    Token asToken = null;
    SimpleIdentifier prefix = null;
    if (matches(Keyword.AS)) {
      asToken = andAdvance;
      prefix = parseSimpleIdentifier();
    }
    List<Combinator> combinators = parseCombinators();
    Token semicolon = expect2(TokenType.SEMICOLON);
    return new ImportDirective.full(commentAndMetadata.comment, commentAndMetadata.metadata, importKeyword, libraryUri, asToken, prefix, combinators, semicolon);
  }

  /**
   * Parse a list of initialized identifiers.
   *
   * <pre>
   * ?? ::=
   *     'static'? ('var' | type) initializedIdentifierList ';'
   *   | 'final' type? initializedIdentifierList ';'
   *
   * initializedIdentifierList ::=
   *     initializedIdentifier (',' initializedIdentifier)*
   *
   * initializedIdentifier ::=
   *     identifier ('=' expression)?
   * </pre>
   *
   * @param commentAndMetadata the documentation comment and metadata to be associated with the
   *          declaration
   * @param staticKeyword the static keyword, or `null` if the getter is not static
   * @param keyword the token representing the 'final', 'const' or 'var' keyword, or `null` if
   *          there is no keyword
   * @param type the type that has already been parsed, or `null` if 'var' was provided
   * @return the getter that was parsed
   */
  FieldDeclaration parseInitializedIdentifierList(CommentAndMetadata commentAndMetadata, Token staticKeyword, Token keyword, TypeName type) {
    VariableDeclarationList fieldList = parseVariableDeclarationList2(null, keyword, type);
    return new FieldDeclaration.full(commentAndMetadata.comment, commentAndMetadata.metadata, staticKeyword, fieldList, expect2(TokenType.SEMICOLON));
  }

  /**
   * Parse an instance creation expression.
   *
   * <pre>
   * instanceCreationExpression ::=
   *     ('new' | 'const') type ('.' identifier)? argumentList
   * </pre>
   *
   * @param keyword the 'new' or 'const' keyword that introduces the expression
   * @return the instance creation expression that was parsed
   */
  InstanceCreationExpression parseInstanceCreationExpression(Token keyword) {
    ConstructorName constructorName = parseConstructorName();
    ArgumentList argumentList = parseArgumentList();
    return new InstanceCreationExpression.full(keyword, constructorName, argumentList);
  }

  /**
   * Parse a library directive.
   *
   * <pre>
   * libraryDirective ::=
   *     metadata 'library' identifier ';'
   * </pre>
   *
   * @param commentAndMetadata the metadata to be associated with the directive
   * @return the library directive that was parsed
   */
  LibraryDirective parseLibraryDirective(CommentAndMetadata commentAndMetadata) {
    Token keyword = expect(Keyword.LIBRARY);
    LibraryIdentifier libraryName = parseLibraryName(ParserErrorCode.MISSING_NAME_IN_LIBRARY_DIRECTIVE, keyword);
    Token semicolon = expect2(TokenType.SEMICOLON);
    return new LibraryDirective.full(commentAndMetadata.comment, commentAndMetadata.metadata, keyword, libraryName, semicolon);
  }

  /**
   * Parse a library identifier.
   *
   * <pre>
   * libraryIdentifier ::=
   *     identifier ('.' identifier)*
   * </pre>
   *
   * @return the library identifier that was parsed
   */
  LibraryIdentifier parseLibraryIdentifier() {
    List<SimpleIdentifier> components = new List<SimpleIdentifier>();
    components.add(parseSimpleIdentifier());
    while (matches5(TokenType.PERIOD)) {
      advance();
      components.add(parseSimpleIdentifier());
    }
    return new LibraryIdentifier.full(components);
  }

  /**
   * Parse a library name.
   *
   * <pre>
   * libraryName ::=
   *     libraryIdentifier
   * </pre>
   *
   * @param missingNameError the error code to be used if the library name is missing
   * @param missingNameToken the token associated with the error produced if the library name is
   *          missing
   * @return the library name that was parsed
   */
  LibraryIdentifier parseLibraryName(ParserErrorCode missingNameError, Token missingNameToken) {
    if (matchesIdentifier()) {
      return parseLibraryIdentifier();
    } else if (matches5(TokenType.STRING)) {
      StringLiteral string = parseStringLiteral();
      reportError(ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME, string, []);
    } else {
      reportError9(missingNameError, missingNameToken, []);
    }
    List<SimpleIdentifier> components = new List<SimpleIdentifier>();
    components.add(createSyntheticIdentifier());
    return new LibraryIdentifier.full(components);
  }

  /**
   * Parse a list literal.
   *
   * <pre>
   * listLiteral ::=
   *     'const'? typeArguments? '[' (expressionList ','?)? ']'
   * </pre>
   *
   * @param modifier the 'const' modifier appearing before the literal, or `null` if there is
   *          no modifier
   * @param typeArguments the type arguments appearing before the literal, or `null` if there
   *          are no type arguments
   * @return the list literal that was parsed
   */
  ListLiteral parseListLiteral(Token modifier, TypeArgumentList typeArguments) {
    if (typeArguments != null) {
      int num = typeArguments.arguments.length;
      if (num != 1) {
        reportError(ParserErrorCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS, typeArguments, [num]);
      }
    }
    if (matches5(TokenType.INDEX)) {
      BeginToken leftBracket = new BeginToken(TokenType.OPEN_SQUARE_BRACKET, _currentToken.offset);
      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 = _currentToken.next;
      return new ListLiteral.full(modifier, typeArguments, leftBracket, null, rightBracket);
    }
    Token leftBracket = expect2(TokenType.OPEN_SQUARE_BRACKET);
    if (matches5(TokenType.CLOSE_SQUARE_BRACKET)) {
      return new ListLiteral.full(modifier, typeArguments, leftBracket, null, andAdvance);
    }
    List<Expression> elements = new List<Expression>();
    elements.add(parseExpression2());
    while (optional(TokenType.COMMA)) {
      if (matches5(TokenType.CLOSE_SQUARE_BRACKET)) {
        return new ListLiteral.full(modifier, typeArguments, leftBracket, elements, andAdvance);
      }
      elements.add(parseExpression2());
    }
    Token rightBracket = expect2(TokenType.CLOSE_SQUARE_BRACKET);
    return new ListLiteral.full(modifier, typeArguments, leftBracket, elements, rightBracket);
  }

  /**
   * Parse a list or map literal.
   *
   * <pre>
   * listOrMapLiteral ::=
   *     listLiteral
   *   | mapLiteral
   * </pre>
   *
   * @param modifier the 'const' modifier appearing before the literal, or `null` if there is
   *          no modifier
   * @return the list or map literal that was parsed
   */
  TypedLiteral parseListOrMapLiteral(Token modifier) {
    TypeArgumentList typeArguments = null;
    if (matches5(TokenType.LT)) {
      typeArguments = parseTypeArgumentList();
    }
    if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
      return parseMapLiteral(modifier, typeArguments);
    } else if (matches5(TokenType.OPEN_SQUARE_BRACKET) || matches5(TokenType.INDEX)) {
      return parseListLiteral(modifier, typeArguments);
    }
    reportError8(ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL, []);
    return new ListLiteral.full(modifier, typeArguments, createSyntheticToken2(TokenType.OPEN_SQUARE_BRACKET), null, createSyntheticToken2(TokenType.CLOSE_SQUARE_BRACKET));
  }

  /**
   * Parse a logical and expression.
   *
   * <pre>
   * logicalAndExpression ::=
   *     equalityExpression ('&&' equalityExpression)*
   * </pre>
   *
   * @return the logical and expression that was parsed
   */
  Expression parseLogicalAndExpression() {
    Expression expression = parseEqualityExpression();
    while (matches5(TokenType.AMPERSAND_AMPERSAND)) {
      Token operator = andAdvance;
      expression = new BinaryExpression.full(expression, operator, parseEqualityExpression());
    }
    return expression;
  }

  /**
   * Parse a logical or expression.
   *
   * <pre>
   * logicalOrExpression ::=
   *     logicalAndExpression ('||' logicalAndExpression)*
   * </pre>
   *
   * @return the logical or expression that was parsed
   */
  Expression parseLogicalOrExpression() {
    Expression expression = parseLogicalAndExpression();
    while (matches5(TokenType.BAR_BAR)) {
      Token operator = andAdvance;
      expression = new BinaryExpression.full(expression, operator, parseLogicalAndExpression());
    }
    return expression;
  }

  /**
   * Parse a map literal.
   *
   * <pre>
   * mapLiteral ::=
   *     'const'? typeArguments? '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}'
   * </pre>
   *
   * @param modifier the 'const' modifier appearing before the literal, or `null` if there is
   *          no modifier
   * @param typeArguments the type arguments that were declared, or `null` if there are no
   *          type arguments
   * @return the map literal that was parsed
   */
  MapLiteral parseMapLiteral(Token modifier, TypeArgumentList typeArguments) {
    if (typeArguments != null) {
      int num = typeArguments.arguments.length;
      if (num != 2) {
        reportError(ParserErrorCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS, typeArguments, [num]);
      }
    }
    Token leftBracket = expect2(TokenType.OPEN_CURLY_BRACKET);
    List<MapLiteralEntry> entries = new List<MapLiteralEntry>();
    if (matches5(TokenType.CLOSE_CURLY_BRACKET)) {
      return new MapLiteral.full(modifier, typeArguments, leftBracket, entries, andAdvance);
    }
    entries.add(parseMapLiteralEntry());
    while (optional(TokenType.COMMA)) {
      if (matches5(TokenType.CLOSE_CURLY_BRACKET)) {
        return new MapLiteral.full(modifier, typeArguments, leftBracket, entries, andAdvance);
      }
      entries.add(parseMapLiteralEntry());
    }
    Token rightBracket = expect2(TokenType.CLOSE_CURLY_BRACKET);
    return new MapLiteral.full(modifier, typeArguments, leftBracket, entries, rightBracket);
  }

  /**
   * Parse a map literal entry.
   *
   * <pre>
   * mapLiteralEntry ::=
   *     expression ':' expression
   * </pre>
   *
   * @return the map literal entry that was parsed
   */
  MapLiteralEntry parseMapLiteralEntry() {
    Expression key = parseExpression2();
    Token separator = expect2(TokenType.COLON);
    Expression value = parseExpression2();
    return new MapLiteralEntry.full(key, separator, value);
  }

  /**
   * Parse a method declaration.
   *
   * <pre>
   * functionDeclaration ::=
   *     'external'? 'static'? functionSignature functionBody
   *   | 'external'? functionSignature ';'
   * </pre>
   *
   * @param commentAndMetadata the documentation comment and metadata to be associated with the
   *          declaration
   * @param externalKeyword the 'external' token
   * @param staticKeyword the static keyword, or `null` if the getter is not static
   * @param returnType the return type of the method
   * @return the method declaration that was parsed
   */
  MethodDeclaration parseMethodDeclaration(CommentAndMetadata commentAndMetadata, Token externalKeyword, Token staticKeyword, TypeName returnType) {
    SimpleIdentifier methodName = parseSimpleIdentifier();
    FormalParameterList parameters = parseFormalParameterList();
    validateFormalParameterList(parameters);
    return parseMethodDeclaration2(commentAndMetadata, externalKeyword, staticKeyword, returnType, methodName, parameters);
  }

  /**
   * Parse a method declaration.
   *
   * <pre>
   * functionDeclaration ::=
   *     ('external' 'static'?)? functionSignature functionBody
   *   | 'external'? functionSignature ';'
   * </pre>
   *
   * @param commentAndMetadata the documentation comment and metadata to be associated with the
   *          declaration
   * @param externalKeyword the 'external' token
   * @param staticKeyword the static keyword, or `null` if the getter is not static
   * @param returnType the return type of the method
   * @param name the name of the method
   * @param parameters the parameters to the method
   * @return the method declaration that was parsed
   */
  MethodDeclaration parseMethodDeclaration2(CommentAndMetadata commentAndMetadata, Token externalKeyword, Token staticKeyword, TypeName returnType, SimpleIdentifier name, FormalParameterList parameters) {
    FunctionBody body = parseFunctionBody(externalKeyword != null || staticKeyword == null, ParserErrorCode.MISSING_FUNCTION_BODY, false);
    if (externalKeyword != null) {
      if (body is! EmptyFunctionBody) {
        reportError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, body, []);
      }
    } else if (staticKeyword != null) {
      if (body is EmptyFunctionBody) {
        reportError(ParserErrorCode.ABSTRACT_STATIC_METHOD, body, []);
      }
    }
    return new MethodDeclaration.full(commentAndMetadata.comment, commentAndMetadata.metadata, externalKeyword, staticKeyword, returnType, null, null, name, parameters, body);
  }

  /**
   * 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`.
   *
   * <pre>
   * modifiers ::=
   *     ('abstract' | 'const' | 'external' | 'factory' | 'final' | 'static' | 'var')*
   * </pre>
   *
   * @return the modifiers that were parsed
   */
  Modifiers parseModifiers() {
    Modifiers modifiers = new Modifiers();
    bool progress = true;
    while (progress) {
      if (matches(Keyword.ABSTRACT) && !matches4(peek(), TokenType.PERIOD) && !matches4(peek(), TokenType.LT)) {
        if (modifiers.abstractKeyword != null) {
          reportError8(ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          advance();
        } else {
          modifiers.abstractKeyword = andAdvance;
        }
      } else if (matches(Keyword.CONST)) {
        if (modifiers.constKeyword != null) {
          reportError8(ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          advance();
        } else {
          modifiers.constKeyword = andAdvance;
        }
      } else if (matches(Keyword.EXTERNAL) && !matches4(peek(), TokenType.PERIOD) && !matches4(peek(), TokenType.LT)) {
        if (modifiers.externalKeyword != null) {
          reportError8(ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          advance();
        } else {
          modifiers.externalKeyword = andAdvance;
        }
      } else if (matches(Keyword.FACTORY) && !matches4(peek(), TokenType.PERIOD) && !matches4(peek(), TokenType.LT)) {
        if (modifiers.factoryKeyword != null) {
          reportError8(ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          advance();
        } else {
          modifiers.factoryKeyword = andAdvance;
        }
      } else if (matches(Keyword.FINAL)) {
        if (modifiers.finalKeyword != null) {
          reportError8(ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          advance();
        } else {
          modifiers.finalKeyword = andAdvance;
        }
      } else if (matches(Keyword.STATIC) && !matches4(peek(), TokenType.PERIOD) && !matches4(peek(), TokenType.LT)) {
        if (modifiers.staticKeyword != null) {
          reportError8(ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          advance();
        } else {
          modifiers.staticKeyword = andAdvance;
        }
      } else if (matches(Keyword.VAR)) {
        if (modifiers.varKeyword != null) {
          reportError8(ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
          advance();
        } else {
          modifiers.varKeyword = andAdvance;
        }
      } else {
        progress = false;
      }
    }
    return modifiers;
  }

  /**
   * Parse a multiplicative expression.
   *
   * <pre>
   * multiplicativeExpression ::=
   *     unaryExpression (multiplicativeOperator unaryExpression)*
   *   | 'super' (multiplicativeOperator unaryExpression)+
   * </pre>
   *
   * @return the multiplicative expression that was parsed
   */
  Expression parseMultiplicativeExpression() {
    Expression expression;
    if (matches(Keyword.SUPER) && _currentToken.next.type.isMultiplicativeOperator) {
      expression = new SuperExpression.full(andAdvance);
    } else {
      expression = parseUnaryExpression();
    }
    while (_currentToken.type.isMultiplicativeOperator) {
      Token operator = andAdvance;
      expression = new BinaryExpression.full(expression, operator, parseUnaryExpression());
    }
    return expression;
  }

  /**
   * Parse a class native clause.
   *
   * <pre>
   * classNativeClause ::=
   *     'native' name
   * </pre>
   *
   * @return the class native clause that was parsed
   */
  NativeClause parseNativeClause() {
    Token keyword = andAdvance;
    StringLiteral name = parseStringLiteral();
    return new NativeClause.full(keyword, name);
  }

  /**
   * Parse a new expression.
   *
   * <pre>
   * newExpression ::=
   *     instanceCreationExpression
   * </pre>
   *
   * @return the new expression that was parsed
   */
  InstanceCreationExpression parseNewExpression() => parseInstanceCreationExpression(expect(Keyword.NEW));

  /**
   * Parse a non-labeled statement.
   *
   * <pre>
   * nonLabeledStatement ::=
   *     block
   *   | assertStatement
   *   | breakStatement
   *   | continueStatement
   *   | doStatement
   *   | forStatement
   *   | ifStatement
   *   | returnStatement
   *   | switchStatement
   *   | tryStatement
   *   | whileStatement
   *   | variableDeclarationList ';'
   *   | expressionStatement
   *   | functionSignature functionBody
   * </pre>
   *
   * @return the non-labeled statement that was parsed
   */
  Statement parseNonLabeledStatement() {
    CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
    if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
      if (matches4(peek(), TokenType.STRING)) {
        Token afterString = skipStringLiteral(_currentToken.next);
        if (afterString != null && identical(afterString.type, TokenType.COLON)) {
          return new ExpressionStatement.full(parseExpression2(), expect2(TokenType.SEMICOLON));
        }
      }
      return parseBlock();
    } else if (matches5(TokenType.KEYWORD) && !((_currentToken as KeywordToken)).keyword.isPseudoKeyword) {
      Keyword keyword = ((_currentToken as KeywordToken)).keyword;
      if (identical(keyword, Keyword.ASSERT)) {
        return parseAssertStatement();
      } else if (identical(keyword, Keyword.BREAK)) {
        return parseBreakStatement();
      } else if (identical(keyword, Keyword.CONTINUE)) {
        return parseContinueStatement();
      } else if (identical(keyword, Keyword.DO)) {
        return parseDoStatement();
      } else if (identical(keyword, Keyword.FOR)) {
        return parseForStatement();
      } else if (identical(keyword, Keyword.IF)) {
        return parseIfStatement();
      } else if (identical(keyword, Keyword.RETHROW)) {
        return new ExpressionStatement.full(parseRethrowExpression(), expect2(TokenType.SEMICOLON));
      } else if (identical(keyword, Keyword.RETURN)) {
        return parseReturnStatement();
      } else if (identical(keyword, Keyword.SWITCH)) {
        return parseSwitchStatement();
      } else if (identical(keyword, Keyword.THROW)) {
        return new ExpressionStatement.full(parseThrowExpression(), expect2(TokenType.SEMICOLON));
      } else if (identical(keyword, Keyword.TRY)) {
        return parseTryStatement();
      } else if (identical(keyword, Keyword.WHILE)) {
        return parseWhileStatement();
      } else if (identical(keyword, Keyword.VAR) || identical(keyword, Keyword.FINAL)) {
        return parseVariableDeclarationStatement(commentAndMetadata);
      } else if (identical(keyword, Keyword.VOID)) {
        TypeName returnType = parseReturnType();
        if (matchesIdentifier() && matchesAny(peek(), [
            TokenType.OPEN_PAREN,
            TokenType.OPEN_CURLY_BRACKET,
            TokenType.FUNCTION])) {
          return parseFunctionDeclarationStatement2(commentAndMetadata, returnType);
        } else {
          if (matchesIdentifier()) {
            if (matchesAny(peek(), [TokenType.EQ, TokenType.COMMA, TokenType.SEMICOLON])) {
              reportError(ParserErrorCode.VOID_VARIABLE, returnType, []);
              return parseVariableDeclarationStatement(commentAndMetadata);
            }
          } else if (matches5(TokenType.CLOSE_CURLY_BRACKET)) {
            return parseVariableDeclarationStatement2(commentAndMetadata, null, returnType);
          }
          reportError8(ParserErrorCode.MISSING_STATEMENT, []);
          return new EmptyStatement.full(createSyntheticToken2(TokenType.SEMICOLON));
        }
      } else if (identical(keyword, Keyword.CONST)) {
        if (matchesAny(peek(), [
            TokenType.LT,
            TokenType.OPEN_CURLY_BRACKET,
            TokenType.OPEN_SQUARE_BRACKET,
            TokenType.INDEX])) {
          return new ExpressionStatement.full(parseExpression2(), expect2(TokenType.SEMICOLON));
        } else if (matches4(peek(), TokenType.IDENTIFIER)) {
          Token afterType = skipTypeName(peek());
          if (afterType != null) {
            if (matches4(afterType, TokenType.OPEN_PAREN) || (matches4(afterType, TokenType.PERIOD) && matches4(afterType.next, TokenType.IDENTIFIER) && matches4(afterType.next.next, TokenType.OPEN_PAREN))) {
              return new ExpressionStatement.full(parseExpression2(), expect2(TokenType.SEMICOLON));
            }
          }
        }
        return parseVariableDeclarationStatement(commentAndMetadata);
      } else if (identical(keyword, Keyword.NEW) || identical(keyword, Keyword.TRUE) || identical(keyword, Keyword.FALSE) || identical(keyword, Keyword.NULL) || identical(keyword, Keyword.SUPER) || identical(keyword, Keyword.THIS)) {
        return new ExpressionStatement.full(parseExpression2(), expect2(TokenType.SEMICOLON));
      } else {
        reportError8(ParserErrorCode.MISSING_STATEMENT, []);
        return new EmptyStatement.full(createSyntheticToken2(TokenType.SEMICOLON));
      }
    } else if (matches5(TokenType.SEMICOLON)) {
      return parseEmptyStatement();
    } else if (isInitializedVariableDeclaration()) {
      return parseVariableDeclarationStatement(commentAndMetadata);
    } else if (isFunctionDeclaration()) {
      return parseFunctionDeclarationStatement();
    } else if (matches5(TokenType.CLOSE_CURLY_BRACKET)) {
      reportError8(ParserErrorCode.MISSING_STATEMENT, []);
      return new EmptyStatement.full(createSyntheticToken2(TokenType.SEMICOLON));
    } else {
      return new ExpressionStatement.full(parseExpression2(), expect2(TokenType.SEMICOLON));
    }
  }

  /**
   * Parse a normal formal parameter.
   *
   * <pre>
   * normalFormalParameter ::=
   *     functionSignature
   *   | fieldFormalParameter
   *   | simpleFormalParameter
   *
   * functionSignature:
   *     metadata returnType? identifier formalParameterList
   *
   * fieldFormalParameter ::=
   *     metadata finalConstVarOrType? 'this' '.' identifier
   *
   * simpleFormalParameter ::=
   *     declaredIdentifier
   *   | metadata identifier
   * </pre>
   *
   * @return the normal formal parameter that was parsed
   */
  NormalFormalParameter parseNormalFormalParameter() {
    CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
    FinalConstVarOrType holder = parseFinalConstVarOrType(true);
    Token thisKeyword = null;
    Token period = null;
    if (matches(Keyword.THIS)) {
      thisKeyword = andAdvance;
      period = expect2(TokenType.PERIOD);
    }
    SimpleIdentifier identifier = parseSimpleIdentifier();
    if (matches5(TokenType.OPEN_PAREN)) {
      FormalParameterList parameters = parseFormalParameterList();
      if (thisKeyword == null) {
        if (holder.keyword != null) {
          reportError9(ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, holder.keyword, []);
        }
        return new FunctionTypedFormalParameter.full(commentAndMetadata.comment, commentAndMetadata.metadata, holder.type, identifier, parameters);
      } else {
        return new FieldFormalParameter.full(commentAndMetadata.comment, commentAndMetadata.metadata, holder.keyword, holder.type, thisKeyword, period, identifier, parameters);
      }
    }
    TypeName type = holder.type;
    if (type != null) {
      if (matches3(type.name.beginToken, Keyword.VOID)) {
        reportError9(ParserErrorCode.VOID_PARAMETER, type.name.beginToken, []);
      } else if (holder.keyword != null && matches3(holder.keyword, Keyword.VAR)) {
        reportError9(ParserErrorCode.VAR_AND_TYPE, holder.keyword, []);
      }
    }
    if (thisKeyword != null) {
      return new FieldFormalParameter.full(commentAndMetadata.comment, commentAndMetadata.metadata, holder.keyword, holder.type, thisKeyword, period, identifier, null);
    }
    return new SimpleFormalParameter.full(commentAndMetadata.comment, commentAndMetadata.metadata, holder.keyword, holder.type, identifier);
  }

  /**
   * Parse an operator declaration.
   *
   * <pre>
   * operatorDeclaration ::=
   *     operatorSignature (';' | functionBody)
   *
   * operatorSignature ::=
   *     'external'? returnType? 'operator' operator formalParameterList
   * </pre>
   *
   * @param commentAndMetadata the documentation comment and metadata to be associated with the
   *          declaration
   * @param externalKeyword the 'external' token
   * @param the return type that has already been parsed, or `null` if there was no return
   *          type
   * @return the operator declaration that was parsed
   */
  MethodDeclaration parseOperator(CommentAndMetadata commentAndMetadata, Token externalKeyword, TypeName returnType) {
    Token operatorKeyword;
    if (matches(Keyword.OPERATOR)) {
      operatorKeyword = andAdvance;
    } else {
      reportError9(ParserErrorCode.MISSING_KEYWORD_OPERATOR, _currentToken, []);
      operatorKeyword = createSyntheticToken(Keyword.OPERATOR);
    }
    if (!_currentToken.isUserDefinableOperator) {
      reportError8(ParserErrorCode.NON_USER_DEFINABLE_OPERATOR, [_currentToken.lexeme]);
    }
    SimpleIdentifier name = new SimpleIdentifier.full(andAdvance);
    if (matches5(TokenType.EQ)) {
      Token previous = _currentToken.previous;
      if ((matches4(previous, TokenType.EQ_EQ) || matches4(previous, TokenType.BANG_EQ)) && _currentToken.offset == previous.offset + 2) {
        reportError8(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) {
      reportError8(ParserErrorCode.EXTERNAL_OPERATOR_WITH_BODY, []);
    }
    return new MethodDeclaration.full(commentAndMetadata.comment, commentAndMetadata.metadata, externalKeyword, null, returnType, null, operatorKeyword, name, parameters, body);
  }

  /**
   * Parse a return type if one is given, otherwise return `null` without advancing.
   *
   * @return the return type that was parsed
   */
  TypeName parseOptionalReturnType() {
    if (matches(Keyword.VOID)) {
      return parseReturnType();
    } else if (matchesIdentifier() && !matches(Keyword.GET) && !matches(Keyword.SET) && !matches(Keyword.OPERATOR) && (matchesIdentifier2(peek()) || matches4(peek(), TokenType.LT))) {
      return parseReturnType();
    } else if (matchesIdentifier() && matches4(peek(), TokenType.PERIOD) && matchesIdentifier2(peek2(2)) && (matchesIdentifier2(peek2(3)) || matches4(peek2(3), TokenType.LT))) {
      return parseReturnType();
    }
    return null;
  }

  /**
   * Parse a part or part-of directive.
   *
   * <pre>
   * partDirective ::=
   *     metadata 'part' stringLiteral ';'
   *
   * partOfDirective ::=
   *     metadata 'part' 'of' identifier ';'
   * </pre>
   *
   * @param commentAndMetadata the metadata to be associated with the directive
   * @return the part or part-of directive that was parsed
   */
  Directive parsePartDirective(CommentAndMetadata commentAndMetadata) {
    Token partKeyword = expect(Keyword.PART);
    if (matches2(_OF)) {
      Token ofKeyword = andAdvance;
      LibraryIdentifier libraryName = parseLibraryName(ParserErrorCode.MISSING_NAME_IN_PART_OF_DIRECTIVE, ofKeyword);
      Token semicolon = expect2(TokenType.SEMICOLON);
      return new PartOfDirective.full(commentAndMetadata.comment, commentAndMetadata.metadata, partKeyword, ofKeyword, libraryName, semicolon);
    }
    StringLiteral partUri = parseStringLiteral();
    Token semicolon = expect2(TokenType.SEMICOLON);
    return new PartDirective.full(commentAndMetadata.comment, commentAndMetadata.metadata, partKeyword, partUri, semicolon);
  }

  /**
   * Parse a postfix expression.
   *
   * <pre>
   * postfixExpression ::=
   *     assignableExpression postfixOperator
   *   | primary selector*
   *
   * selector ::=
   *     assignableSelector
   *   | argumentList
   * </pre>
   *
   * @return the postfix expression that was parsed
   */
  Expression parsePostfixExpression() {
    Expression operand = parseAssignableExpression(true);
    if (matches5(TokenType.OPEN_SQUARE_BRACKET) || matches5(TokenType.PERIOD) || matches5(TokenType.OPEN_PAREN)) {
      do {
        if (matches5(TokenType.OPEN_PAREN)) {
          ArgumentList argumentList = parseArgumentList();
          if (operand is PropertyAccess) {
            PropertyAccess access = operand as PropertyAccess;
            operand = new MethodInvocation.full(access.target, access.operator, access.propertyName, argumentList);
          } else {
            operand = new FunctionExpressionInvocation.full(operand, argumentList);
          }
        } else {
          operand = parseAssignableSelector(operand, true);
        }
      } while (matches5(TokenType.OPEN_SQUARE_BRACKET) || matches5(TokenType.PERIOD) || matches5(TokenType.OPEN_PAREN));
      return operand;
    }
    if (!_currentToken.type.isIncrementOperator) {
      return operand;
    }
    if (operand is Literal || operand is FunctionExpressionInvocation) {
      reportError8(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, []);
    }
    Token operator = andAdvance;
    return new PostfixExpression.full(operand, operator);
  }

  /**
   * Parse a prefixed identifier.
   *
   * <pre>
   * prefixedIdentifier ::=
   *     identifier ('.' identifier)?
   * </pre>
   *
   * @return the prefixed identifier that was parsed
   */
  Identifier parsePrefixedIdentifier() {
    SimpleIdentifier qualifier = parseSimpleIdentifier();
    if (!matches5(TokenType.PERIOD)) {
      return qualifier;
    }
    Token period = andAdvance;
    SimpleIdentifier qualified = parseSimpleIdentifier();
    return new PrefixedIdentifier.full(qualifier, period, qualified);
  }

  /**
   * Parse a primary expression.
   *
   * <pre>
   * primary ::=
   *     thisExpression
   *   | 'super' assignableSelector
   *   | functionExpression
   *   | literal
   *   | identifier
   *   | newExpression
   *   | constObjectExpression
   *   | '(' expression ')'
   *   | argumentDefinitionTest
   *
   * literal ::=
   *     nullLiteral
   *   | booleanLiteral
   *   | numericLiteral
   *   | stringLiteral
   *   | symbolLiteral
   *   | mapLiteral
   *   | listLiteral
   * </pre>
   *
   * @return the primary expression that was parsed
   */
  Expression parsePrimaryExpression() {
    if (matches(Keyword.THIS)) {
      return new ThisExpression.full(andAdvance);
    } else if (matches(Keyword.SUPER)) {
      return parseAssignableSelector(new SuperExpression.full(andAdvance), false);
    } else if (matches(Keyword.NULL)) {
      return new NullLiteral.full(andAdvance);
    } else if (matches(Keyword.FALSE)) {
      return new BooleanLiteral.full(andAdvance, false);
    } else if (matches(Keyword.TRUE)) {
      return new BooleanLiteral.full(andAdvance, true);
    } else if (matches5(TokenType.DOUBLE)) {
      Token token = andAdvance;
      double value = 0.0;
      try {
        value = double.parse(token.lexeme);
      } on FormatException catch (exception) {
      }
      return new DoubleLiteral.full(token, value);
    } else if (matches5(TokenType.HEXADECIMAL)) {
      Token token = andAdvance;
      int value = null;
      try {
        value = int.parse(token.lexeme.substring(2), radix: 16);
      } on FormatException catch (exception) {
      }
      return new IntegerLiteral.full(token, value);
    } else if (matches5(TokenType.INT)) {
      Token token = andAdvance;
      int value = null;
      try {
        value = int.parse(token.lexeme);
      } on FormatException catch (exception) {
      }
      return new IntegerLiteral.full(token, value);
    } else if (matches5(TokenType.STRING)) {
      return parseStringLiteral();
    } else if (matches5(TokenType.OPEN_CURLY_BRACKET)) {
      return parseMapLiteral(null, null);
    } else if (matches5(TokenType.OPEN_SQUARE_BRACKET) || matches5(TokenType.INDEX)) {
      return parseListLiteral(null, null);
    } else if (matchesIdentifier()) {
      return parsePrefixedIdentifier();
    } else if (matches(Keyword.NEW)) {
      return parseNewExpression();
    } else if (matches(Keyword.CONST)) {
      return parseConstExpression();
    } else if (matches5(TokenType.OPEN_PAREN)) {
      if (isFunctionExpression(_currentToken)) {
        return parseFunctionExpression();
      }
      Token leftParenthesis = andAdvance;
      Expression expression = parseExpression2();
      Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
      return new ParenthesizedExpression.full(leftParenthesis, expression, rightParenthesis);
    } else if (matches5(TokenType.LT)) {
      return parseListOrMapLiteral(null);
    } else if (matches5(TokenType.QUESTION)) {
      return parseArgumentDefinitionTest();
    } else if (matches(Keyword.VOID)) {
      reportError8(ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken.lexeme]);
      advance();
      return parsePrimaryExpression();
    } else if (matches5(TokenType.HASH)) {
      return parseSymbolLiteral();
    } else {
      reportError8(ParserErrorCode.MISSING_IDENTIFIER, []);
      return createSyntheticIdentifier();
    }
  }

  /**
   * Parse a redirecting constructor invocation.
   *
   * <pre>
   * redirectingConstructorInvocation ::=
   *     'this' ('.' identifier)? arguments
   * </pre>
   *
   * @return the redirecting constructor invocation that was parsed
   */
  RedirectingConstructorInvocation parseRedirectingConstructorInvocation() {
    Token keyword = expect(Keyword.THIS);
    Token period = null;
    SimpleIdentifier constructorName = null;
    if (matches5(TokenType.PERIOD)) {
      period = andAdvance;
      constructorName = parseSimpleIdentifier();
    }
    ArgumentList argumentList = parseArgumentList();
    return new RedirectingConstructorInvocation.full(keyword, period, constructorName, argumentList);
  }

  /**
   * Parse a relational expression.
   *
   * <pre>
   * relationalExpression ::=
   *     bitwiseOrExpression ('is' '!'? type | 'as' type | relationalOperator bitwiseOrExpression)?
   *   | 'super' relationalOperator bitwiseOrExpression
   * </pre>
   *
   * @return the relational expression that was parsed
   */
  Expression parseRelationalExpression() {
    if (matches(Keyword.SUPER) && _currentToken.next.type.isRelationalOperator) {
      Expression expression = new SuperExpression.full(andAdvance);
      Token operator = andAdvance;
      expression = new BinaryExpression.full(expression, operator, parseBitwiseOrExpression());
      return expression;
    }
    Expression expression = parseBitwiseOrExpression();
    if (matches(Keyword.AS)) {
      Token asOperator = andAdvance;
      expression = new AsExpression.full(expression, asOperator, parseTypeName());
    } else if (matches(Keyword.IS)) {
      Token isOperator = andAdvance;
      Token notOperator = null;
      if (matches5(TokenType.BANG)) {
        notOperator = andAdvance;
      }
      expression = new IsExpression.full(expression, isOperator, notOperator, parseTypeName());
    } else if (_currentToken.type.isRelationalOperator) {
      Token operator = andAdvance;
      expression = new BinaryExpression.full(expression, operator, parseBitwiseOrExpression());
    }
    return expression;
  }

  /**
   * Parse a rethrow expression.
   *
   * <pre>
   * rethrowExpression ::=
   *     'rethrow'
   * </pre>
   *
   * @return the rethrow expression that was parsed
   */
  Expression parseRethrowExpression() => new RethrowExpression.full(expect(Keyword.RETHROW));

  /**
   * Parse a return statement.
   *
   * <pre>
   * returnStatement ::=
   *     'return' expression? ';'
   * </pre>
   *
   * @return the return statement that was parsed
   */
  Statement parseReturnStatement() {
    Token returnKeyword = expect(Keyword.RETURN);
    if (matches5(TokenType.SEMICOLON)) {
      return new ReturnStatement.full(returnKeyword, null, andAdvance);
    }
    Expression expression = parseExpression2();
    Token semicolon = expect2(TokenType.SEMICOLON);
    return new ReturnStatement.full(returnKeyword, expression, semicolon);
  }

  /**
   * Parse a return type.
   *
   * <pre>
   * returnType ::=
   *     'void'
   *   | type
   * </pre>
   *
   * @return the return type that was parsed
   */
  TypeName parseReturnType() {
    if (matches(Keyword.VOID)) {
      return new TypeName.full(new SimpleIdentifier.full(andAdvance), null);
    } else {
      return parseTypeName();
    }
  }

  /**
   * Parse a setter.
   *
   * <pre>
   * setter ::=
   *     setterSignature functionBody?
   *
   * setterSignature ::=
   *     'external'? 'static'? returnType? 'set' identifier formalParameterList
   * </pre>
   *
   * @param commentAndMetadata the documentation comment and metadata to be associated with the
   *          declaration
   * @param externalKeyword the 'external' token
   * @param staticKeyword the static keyword, or `null` if the setter is not static
   * @param the return type that has already been parsed, or `null` if there was no return
   *          type
   * @return the setter that was parsed
   */
  MethodDeclaration parseSetter(CommentAndMetadata commentAndMetadata, Token externalKeyword, Token staticKeyword, TypeName returnType) {
    Token propertyKeyword = expect(Keyword.SET);
    SimpleIdentifier name = parseSimpleIdentifier();
    FormalParameterList parameters = parseFormalParameterList();
    validateFormalParameterList(parameters);
    FunctionBody body = parseFunctionBody(externalKeyword != null || staticKeyword == null, ParserErrorCode.STATIC_SETTER_WITHOUT_BODY, false);
    if (externalKeyword != null && body is! EmptyFunctionBody) {
      reportError8(ParserErrorCode.EXTERNAL_SETTER_WITH_BODY, []);
    }
    return new MethodDeclaration.full(commentAndMetadata.comment, commentAndMetadata.metadata, externalKeyword, staticKeyword, returnType, propertyKeyword, null, name, parameters, body);
  }

  /**
   * Parse a shift expression.
   *
   * <pre>
   * shiftExpression ::=
   *     additiveExpression (shiftOperator additiveExpression)*
   *   | 'super' (shiftOperator additiveExpression)+
   * </pre>
   *
   * @return the shift expression that was parsed
   */
  Expression parseShiftExpression() {
    Expression expression;
    if (matches(Keyword.SUPER) && _currentToken.next.type.isShiftOperator) {
      expression = new SuperExpression.full(andAdvance);
    } else {
      expression = parseAdditiveExpression();
    }
    while (_currentToken.type.isShiftOperator) {
      Token operator = andAdvance;
      expression = new BinaryExpression.full(expression, operator, parseAdditiveExpression());
    }
    return expression;
  }

  /**
   * Parse a simple identifier.
   *
   * <pre>
   * identifier ::=
   *     IDENTIFIER
   * </pre>
   *
   * @return the simple identifier that was parsed
   */
  SimpleIdentifier parseSimpleIdentifier() {
    if (matchesIdentifier()) {
      return new SimpleIdentifier.full(andAdvance);
    }
    reportError8(ParserErrorCode.MISSING_IDENTIFIER, []);
    return createSyntheticIdentifier();
  }

  /**
   * Parse a statement.
   *
   * <pre>
   * statement ::=
   *     label* nonLabeledStatement
   * </pre>
   *
   * @return the statement that was parsed
   */
  Statement parseStatement2() {
    List<Label> labels = new List<Label>();
    while (matchesIdentifier() && matches4(peek(), TokenType.COLON)) {
      SimpleIdentifier label = parseSimpleIdentifier();
      Token colon = expect2(TokenType.COLON);
      labels.add(new Label.full(label, colon));
    }
    Statement statement = parseNonLabeledStatement();
    if (labels.isEmpty) {
      return statement;
    }
    return new LabeledStatement.full(labels, statement);
  }

  /**
   * Parse a list of statements within a switch statement.
   *
   * <pre>
   * statements ::=
   *     statement*
   * </pre>
   *
   * @return the statements that were parsed
   */
  List<Statement> parseStatements2() {
    List<Statement> statements = new List<Statement>();
    Token statementStart = _currentToken;
    while (!matches5(TokenType.EOF) && !matches5(TokenType.CLOSE_CURLY_BRACKET) && !isSwitchMember()) {
      statements.add(parseStatement2());
      if (identical(_currentToken, statementStart)) {
        reportError9(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [_currentToken.lexeme]);
        advance();
      }
      statementStart = _currentToken;
    }
    return statements;
  }

  /**
   * Parse a string literal that contains interpolations.
   *
   * @return the string literal that was parsed
   */
  StringInterpolation parseStringInterpolation(Token string) {
    List<InterpolationElement> elements = new List<InterpolationElement>();
    bool hasMore = matches5(TokenType.STRING_INTERPOLATION_EXPRESSION) || matches5(TokenType.STRING_INTERPOLATION_IDENTIFIER);
    elements.add(new InterpolationString.full(string, computeStringValue(string.lexeme, true, !hasMore)));
    while (hasMore) {
      if (matches5(TokenType.STRING_INTERPOLATION_EXPRESSION)) {
        Token openToken = andAdvance;
        Expression expression = parseExpression2();
        Token rightBracket = expect2(TokenType.CLOSE_CURLY_BRACKET);
        elements.add(new InterpolationExpression.full(openToken, expression, rightBracket));
      } else {
        Token openToken = andAdvance;
        Expression expression = null;
        if (matches(Keyword.THIS)) {
          expression = new ThisExpression.full(andAdvance);
        } else {
          expression = parseSimpleIdentifier();
        }
        elements.add(new InterpolationExpression.full(openToken, expression, null));
      }
      if (matches5(TokenType.STRING)) {
        string = andAdvance;
        hasMore = matches5(TokenType.STRING_INTERPOLATION_EXPRESSION) || matches5(TokenType.STRING_INTERPOLATION_IDENTIFIER);
        elements.add(new InterpolationString.full(string, computeStringValue(string.lexeme, false, !hasMore)));
      }
    }
    return new StringInterpolation.full(elements);
  }

  /**
   * Parse a string literal.
   *
   * <pre>
   * stringLiteral ::=
   *     MULTI_LINE_STRING+
   *   | SINGLE_LINE_STRING+
   * </pre>
   *
   * @return the string literal that was parsed
   */
  StringLiteral parseStringLiteral() {
    List<StringLiteral> strings = new List<StringLiteral>();
    while (matches5(TokenType.STRING)) {
      Token string = andAdvance;
      if (matches5(TokenType.STRING_INTERPOLATION_EXPRESSION) || matches5(TokenType.STRING_INTERPOLATION_IDENTIFIER)) {
        strings.add(parseStringInterpolation(string));
      } else {
        strings.add(new SimpleStringLiteral.full(string, computeStringValue(string.lexeme, true, true)));
      }
    }
    if (strings.length < 1) {
      reportError8(ParserErrorCode.EXPECTED_STRING_LITERAL, []);
      return createSyntheticStringLiteral();
    } else if (strings.length == 1) {
      return strings[0];
    } else {
      return new AdjacentStrings.full(strings);
    }
  }

  /**
   * Parse a super constructor invocation.
   *
   * <pre>
   * superConstructorInvocation ::=
   *     'super' ('.' identifier)? arguments
   * </pre>
   *
   * @return the super constructor invocation that was parsed
   */
  SuperConstructorInvocation parseSuperConstructorInvocation() {
    Token keyword = expect(Keyword.SUPER);
    Token period = null;
    SimpleIdentifier constructorName = null;
    if (matches5(TokenType.PERIOD)) {
      period = andAdvance;
      constructorName = parseSimpleIdentifier();
    }
    ArgumentList argumentList = parseArgumentList();
    return new SuperConstructorInvocation.full(keyword, period, constructorName, argumentList);
  }

  /**
   * Parse a switch statement.
   *
   * <pre>
   * switchStatement ::=
   *     'switch' '(' expression ')' '{' switchCase* defaultCase? '}'
   *
   * switchCase ::=
   *     label* ('case' expression ':') statements
   *
   * defaultCase ::=
   *     label* 'default' ':' statements
   * </pre>
   *
   * @return the switch statement that was parsed
   */
  SwitchStatement parseSwitchStatement() {
    bool wasInSwitch = _inSwitch;
    _inSwitch = true;
    try {
      Set<String> definedLabels = new Set<String>();
      Token keyword = expect(Keyword.SWITCH);
      Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
      Expression expression = parseExpression2();
      Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
      Token leftBracket = expect2(TokenType.OPEN_CURLY_BRACKET);
      Token defaultKeyword = null;
      List<SwitchMember> members = new List<SwitchMember>();
      while (!matches5(TokenType.EOF) && !matches5(TokenType.CLOSE_CURLY_BRACKET)) {
        List<Label> labels = new List<Label>();
        while (matchesIdentifier() && matches4(peek(), TokenType.COLON)) {
          SimpleIdentifier identifier = parseSimpleIdentifier();
          String label = identifier.token.lexeme;
          if (definedLabels.contains(label)) {
            reportError9(ParserErrorCode.DUPLICATE_LABEL_IN_SWITCH_STATEMENT, identifier.token, [label]);
          } else {
            javaSetAdd(definedLabels, label);
          }
          Token colon = expect2(TokenType.COLON);
          labels.add(new Label.full(identifier, colon));
        }
        if (matches(Keyword.CASE)) {
          Token caseKeyword = andAdvance;
          Expression caseExpression = parseExpression2();
          Token colon = expect2(TokenType.COLON);
          members.add(new SwitchCase.full(labels, caseKeyword, caseExpression, colon, parseStatements2()));
          if (defaultKeyword != null) {
            reportError9(ParserErrorCode.SWITCH_HAS_CASE_AFTER_DEFAULT_CASE, caseKeyword, []);
          }
        } else if (matches(Keyword.DEFAULT)) {
          if (defaultKeyword != null) {
            reportError9(ParserErrorCode.SWITCH_HAS_MULTIPLE_DEFAULT_CASES, peek(), []);
          }
          defaultKeyword = andAdvance;
          Token colon = expect2(TokenType.COLON);
          members.add(new SwitchDefault.full(labels, defaultKeyword, colon, parseStatements2()));
        } else {
          reportError8(ParserErrorCode.EXPECTED_CASE_OR_DEFAULT, []);
          while (!matches5(TokenType.EOF) && !matches5(TokenType.CLOSE_CURLY_BRACKET) && !matches(Keyword.CASE) && !matches(Keyword.DEFAULT)) {
            advance();
          }
        }
      }
      Token rightBracket = expect2(TokenType.CLOSE_CURLY_BRACKET);
      return new SwitchStatement.full(keyword, leftParenthesis, expression, rightParenthesis, leftBracket, members, rightBracket);
    } finally {
      _inSwitch = wasInSwitch;
    }
  }

  /**
   * Parse a symbol literal.
   *
   * <pre>
   * symbolLiteral ::=
   *     '#' identifier ('.' identifier)*
   * </pre>
   *
   * @return the symbol literal that was parsed
   */
  SymbolLiteral parseSymbolLiteral() {
    Token poundSign = andAdvance;
    List<Token> components = new List<Token>();
    if (matchesIdentifier()) {
      components.add(andAdvance);
      while (matches5(TokenType.PERIOD)) {
        advance();
        if (matchesIdentifier()) {
          components.add(andAdvance);
        } else {
          reportError8(ParserErrorCode.MISSING_IDENTIFIER, []);
          components.add(createSyntheticToken2(TokenType.IDENTIFIER));
          break;
        }
      }
    } else if (_currentToken.isOperator) {
      components.add(andAdvance);
    } else {
      reportError8(ParserErrorCode.MISSING_IDENTIFIER, []);
      components.add(createSyntheticToken2(TokenType.IDENTIFIER));
    }
    return new SymbolLiteral.full(poundSign, new List.from(components));
  }

  /**
   * Parse a throw expression.
   *
   * <pre>
   * throwExpression ::=
   *     'throw' expression
   * </pre>
   *
   * @return the throw expression that was parsed
   */
  Expression parseThrowExpression() {
    Token keyword = expect(Keyword.THROW);
    if (matches5(TokenType.SEMICOLON) || matches5(TokenType.CLOSE_PAREN)) {
      reportError9(ParserErrorCode.MISSING_EXPRESSION_IN_THROW, _currentToken, []);
      return new ThrowExpression.full(keyword, createSyntheticIdentifier());
    }
    Expression expression = parseExpression2();
    return new ThrowExpression.full(keyword, expression);
  }

  /**
   * Parse a throw expression.
   *
   * <pre>
   * throwExpressionWithoutCascade ::=
   *     'throw' expressionWithoutCascade
   * </pre>
   *
   * @return the throw expression that was parsed
   */
  Expression parseThrowExpressionWithoutCascade() {
    Token keyword = expect(Keyword.THROW);
    if (matches5(TokenType.SEMICOLON) || matches5(TokenType.CLOSE_PAREN)) {
      reportError9(ParserErrorCode.MISSING_EXPRESSION_IN_THROW, _currentToken, []);
      return new ThrowExpression.full(keyword, createSyntheticIdentifier());
    }
    Expression expression = parseExpressionWithoutCascade();
    return new ThrowExpression.full(keyword, expression);
  }

  /**
   * Parse a try statement.
   *
   * <pre>
   * tryStatement ::=
   *     'try' block (onPart+ finallyPart? | finallyPart)
   *
   * onPart ::=
   *     catchPart block
   *   | 'on' type catchPart? block
   *
   * catchPart ::=
   *     'catch' '(' identifier (',' identifier)? ')'
   *
   * finallyPart ::=
   *     'finally' block
   * </pre>
   *
   * @return the try statement that was parsed
   */
  Statement parseTryStatement() {
    Token tryKeyword = expect(Keyword.TRY);
    Block body = parseBlock();
    List<CatchClause> catchClauses = new List<CatchClause>();
    Block finallyClause = null;
    while (matches2(_ON) || matches(Keyword.CATCH)) {
      Token onKeyword = null;
      TypeName exceptionType = null;
      if (matches2(_ON)) {
        onKeyword = andAdvance;
        exceptionType = parseTypeName();
      }
      Token catchKeyword = null;
      Token leftParenthesis = null;
      SimpleIdentifier exceptionParameter = null;
      Token comma = null;
      SimpleIdentifier stackTraceParameter = null;
      Token rightParenthesis = null;
      if (matches(Keyword.CATCH)) {
        catchKeyword = andAdvance;
        leftParenthesis = expect2(TokenType.OPEN_PAREN);
        exceptionParameter = parseSimpleIdentifier();
        if (matches5(TokenType.COMMA)) {
          comma = andAdvance;
          stackTraceParameter = parseSimpleIdentifier();
        }
        rightParenthesis = expect2(TokenType.CLOSE_PAREN);
      }
      Block catchBody = parseBlock();
      catchClauses.add(new CatchClause.full(onKeyword, exceptionType, catchKeyword, leftParenthesis, exceptionParameter, comma, stackTraceParameter, rightParenthesis, catchBody));
    }
    Token finallyKeyword = null;
    if (matches(Keyword.FINALLY)) {
      finallyKeyword = andAdvance;
      finallyClause = parseBlock();
    } else {
      if (catchClauses.isEmpty) {
        reportError8(ParserErrorCode.MISSING_CATCH_OR_FINALLY, []);
      }
    }
    return new TryStatement.full(tryKeyword, body, catchClauses, finallyKeyword, finallyClause);
  }

  /**
   * Parse a type alias.
   *
   * <pre>
   * typeAlias ::=
   *     'typedef' typeAliasBody
   *
   * typeAliasBody ::=
   *     classTypeAlias
   *   | functionTypeAlias
   *
   * classTypeAlias ::=
   *     identifier typeParameters? '=' 'abstract'? mixinApplication
   *
   * mixinApplication ::=
   *     qualified withClause implementsClause? ';'
   *
   * functionTypeAlias ::=
   *     functionPrefix typeParameterList? formalParameterList ';'
   *
   * functionPrefix ::=
   *     returnType? name
   * </pre>
   *
   * @param commentAndMetadata the metadata to be associated with the member
   * @return the type alias that was parsed
   */
  TypeAlias parseTypeAlias(CommentAndMetadata commentAndMetadata) {
    Token keyword = expect(Keyword.TYPEDEF);
    if (matchesIdentifier()) {
      Token next = peek();
      if (matches4(next, TokenType.LT)) {
        next = skipTypeParameterList(next);
        if (next != null && matches4(next, TokenType.EQ)) {
          return parseClassTypeAlias(commentAndMetadata, keyword);
        }
      } else if (matches4(next, TokenType.EQ)) {
        return parseClassTypeAlias(commentAndMetadata, keyword);
      }
    }
    return parseFunctionTypeAlias(commentAndMetadata, keyword);
  }

  /**
   * Parse a list of type arguments.
   *
   * <pre>
   * typeArguments ::=
   *     '<' typeList '>'
   *
   * typeList ::=
   *     type (',' type)*
   * </pre>
   *
   * @return the type argument list that was parsed
   */
  TypeArgumentList parseTypeArgumentList() {
    Token leftBracket = expect2(TokenType.LT);
    List<TypeName> arguments = new List<TypeName>();
    arguments.add(parseTypeName());
    while (optional(TokenType.COMMA)) {
      arguments.add(parseTypeName());
    }
    Token rightBracket = expect2(TokenType.GT);
    return new TypeArgumentList.full(leftBracket, arguments, rightBracket);
  }

  /**
   * Parse a type name.
   *
   * <pre>
   * type ::=
   *     qualified typeArguments?
   * </pre>
   *
   * @return the type name that was parsed
   */
  TypeName parseTypeName() {
    Identifier typeName;
    if (matches(Keyword.VAR)) {
      reportError8(ParserErrorCode.VAR_AS_TYPE_NAME, []);
      typeName = new SimpleIdentifier.full(andAdvance);
    } else if (matchesIdentifier()) {
      typeName = parsePrefixedIdentifier();
    } else {
      typeName = createSyntheticIdentifier();
      reportError8(ParserErrorCode.EXPECTED_TYPE_NAME, []);
    }
    TypeArgumentList typeArguments = null;
    if (matches5(TokenType.LT)) {
      typeArguments = parseTypeArgumentList();
    }
    return new TypeName.full(typeName, typeArguments);
  }

  /**
   * Parse a type parameter.
   *
   * <pre>
   * typeParameter ::=
   *     metadata name ('extends' bound)?
   * </pre>
   *
   * @return the type parameter that was parsed
   */
  TypeParameter parseTypeParameter() {
    CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
    SimpleIdentifier name = parseSimpleIdentifier();
    if (matches(Keyword.EXTENDS)) {
      Token keyword = andAdvance;
      TypeName bound = parseTypeName();
      return new TypeParameter.full(commentAndMetadata.comment, commentAndMetadata.metadata, name, keyword, bound);
    }
    return new TypeParameter.full(commentAndMetadata.comment, commentAndMetadata.metadata, name, null, null);
  }

  /**
   * Parse a list of type parameters.
   *
   * <pre>
   * typeParameterList ::=
   *     '<' typeParameter (',' typeParameter)* '>'
   * </pre>
   *
   * @return the list of type parameters that were parsed
   */
  TypeParameterList parseTypeParameterList() {
    Token leftBracket = expect2(TokenType.LT);
    List<TypeParameter> typeParameters = new List<TypeParameter>();
    typeParameters.add(parseTypeParameter());
    while (optional(TokenType.COMMA)) {
      typeParameters.add(parseTypeParameter());
    }
    Token rightBracket = expect2(TokenType.GT);
    return new TypeParameterList.full(leftBracket, typeParameters, rightBracket);
  }

  /**
   * Parse a unary expression.
   *
   * <pre>
   * unaryExpression ::=
   *     prefixOperator unaryExpression
   *   | postfixExpression
   *   | unaryOperator 'super'
   *   | '-' 'super'
   *   | incrementOperator assignableExpression
   * </pre>
   *
   * @return the unary expression that was parsed
   */
  Expression parseUnaryExpression() {
    if (matches5(TokenType.MINUS) || matches5(TokenType.BANG) || matches5(TokenType.TILDE)) {
      Token operator = andAdvance;
      if (matches(Keyword.SUPER)) {
        if (matches4(peek(), TokenType.OPEN_SQUARE_BRACKET) || matches4(peek(), TokenType.PERIOD)) {
          return new PrefixExpression.full(operator, parseUnaryExpression());
        }
        return new PrefixExpression.full(operator, new SuperExpression.full(andAdvance));
      }
      return new PrefixExpression.full(operator, parseUnaryExpression());
    } else if (_currentToken.type.isIncrementOperator) {
      Token operator = andAdvance;
      if (matches(Keyword.SUPER)) {
        if (matches4(peek(), TokenType.OPEN_SQUARE_BRACKET) || matches4(peek(), TokenType.PERIOD)) {
          return new PrefixExpression.full(operator, parseUnaryExpression());
        }
        if (identical(operator.type, TokenType.MINUS_MINUS)) {
          int offset = operator.offset;
          Token firstOperator = new Token(TokenType.MINUS, offset);
          Token secondOperator = new Token(TokenType.MINUS, offset + 1);
          secondOperator.setNext(_currentToken);
          firstOperator.setNext(secondOperator);
          operator.previous.setNext(firstOperator);
          return new PrefixExpression.full(firstOperator, new PrefixExpression.full(secondOperator, new SuperExpression.full(andAdvance)));
        } else {
          reportError8(ParserErrorCode.INVALID_OPERATOR_FOR_SUPER, [operator.lexeme]);
          return new PrefixExpression.full(operator, new SuperExpression.full(andAdvance));
        }
      }
      return new PrefixExpression.full(operator, parseAssignableExpression(false));
    } else if (matches5(TokenType.PLUS)) {
      reportError8(ParserErrorCode.MISSING_IDENTIFIER, []);
      return createSyntheticIdentifier();
    }
    return parsePostfixExpression();
  }

  /**
   * Parse a variable declaration.
   *
   * <pre>
   * variableDeclaration ::=
   *     identifier ('=' expression)?
   * </pre>
   *
   * @return the variable declaration that was parsed
   */
  VariableDeclaration parseVariableDeclaration() {
    CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
    SimpleIdentifier name = parseSimpleIdentifier();
    Token equals = null;
    Expression initializer = null;
    if (matches5(TokenType.EQ)) {
      equals = andAdvance;
      initializer = parseExpression2();
    }
    return new VariableDeclaration.full(commentAndMetadata.comment, commentAndMetadata.metadata, name, equals, initializer);
  }

  /**
   * Parse a variable declaration list.
   *
   * <pre>
   * variableDeclarationList ::=
   *     finalConstVarOrType variableDeclaration (',' variableDeclaration)*
   * </pre>
   *
   * @param commentAndMetadata the metadata to be associated with the variable declaration list
   * @return the variable declaration list that was parsed
   */
  VariableDeclarationList parseVariableDeclarationList(CommentAndMetadata commentAndMetadata) {
    FinalConstVarOrType holder = parseFinalConstVarOrType(false);
    return parseVariableDeclarationList2(commentAndMetadata, holder.keyword, holder.type);
  }

  /**
   * Parse a variable declaration list.
   *
   * <pre>
   * variableDeclarationList ::=
   *     finalConstVarOrType variableDeclaration (',' variableDeclaration)*
   * </pre>
   *
   * @param commentAndMetadata the metadata to be associated with the variable declaration list, or
   *          `null` if there is no attempt at parsing the comment and metadata
   * @param keyword the token representing the 'final', 'const' or 'var' keyword, or `null` if
   *          there is no keyword
   * @param type the type of the variables in the list
   * @return the variable declaration list that was parsed
   */
  VariableDeclarationList parseVariableDeclarationList2(CommentAndMetadata commentAndMetadata, Token keyword, TypeName type) {
    if (type != null && keyword != null && matches3(keyword, Keyword.VAR)) {
      reportError9(ParserErrorCode.VAR_AND_TYPE, keyword, []);
    }
    List<VariableDeclaration> variables = new List<VariableDeclaration>();
    variables.add(parseVariableDeclaration());
    while (matches5(TokenType.COMMA)) {
      advance();
      variables.add(parseVariableDeclaration());
    }
    return new VariableDeclarationList.full(commentAndMetadata != null ? commentAndMetadata.comment : null, commentAndMetadata != null ? commentAndMetadata.metadata : null, keyword, type, variables);
  }

  /**
   * Parse a variable declaration statement.
   *
   * <pre>
   * variableDeclarationStatement ::=
   *     variableDeclarationList ';'
   * </pre>
   *
   * @param commentAndMetadata 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 parseVariableDeclarationStatement(CommentAndMetadata commentAndMetadata) {
    VariableDeclarationList variableList = parseVariableDeclarationList(commentAndMetadata);
    Token semicolon = expect2(TokenType.SEMICOLON);
    return new VariableDeclarationStatement.full(variableList, semicolon);
  }

  /**
   * Parse a variable declaration statement.
   *
   * <pre>
   * variableDeclarationStatement ::=
   *     variableDeclarationList ';'
   * </pre>
   *
   * @param commentAndMetadata the metadata to be associated with the variable declaration
   *          statement, or `null` if there is no attempt at parsing the comment and metadata
   * @param keyword the token representing the 'final', 'const' or 'var' keyword, or `null` if
   *          there is no keyword
   * @param type the type of the variables in the list
   * @return the variable declaration statement that was parsed
   */
  VariableDeclarationStatement parseVariableDeclarationStatement2(CommentAndMetadata commentAndMetadata, Token keyword, TypeName type) {
    VariableDeclarationList variableList = parseVariableDeclarationList2(commentAndMetadata, keyword, type);
    Token semicolon = expect2(TokenType.SEMICOLON);
    return new VariableDeclarationStatement.full(variableList, semicolon);
  }

  /**
   * Parse a while statement.
   *
   * <pre>
   * whileStatement ::=
   *     'while' '(' expression ')' statement
   * </pre>
   *
   * @return the while statement that was parsed
   */
  Statement parseWhileStatement() {
    bool wasInLoop = _inLoop;
    _inLoop = true;
    try {
      Token keyword = expect(Keyword.WHILE);
      Token leftParenthesis = expect2(TokenType.OPEN_PAREN);
      Expression condition = parseExpression2();
      Token rightParenthesis = expect2(TokenType.CLOSE_PAREN);
      Statement body = parseStatement2();
      return new WhileStatement.full(keyword, leftParenthesis, condition, rightParenthesis, body);
    } finally {
      _inLoop = wasInLoop;
    }
  }

  /**
   * Parse a with clause.
   *
   * <pre>
   * withClause ::=
   *     'with' typeName (',' typeName)*
   * </pre>
   *
   * @return the with clause that was parsed
   */
  WithClause parseWithClause() {
    Token with2 = expect(Keyword.WITH);
    List<TypeName> types = new List<TypeName>();
    types.add(parseTypeName());
    while (optional(TokenType.COMMA)) {
      types.add(parseTypeName());
    }
    return new WithClause.full(with2, types);
  }

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

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

  /**
   * Report an error with the given error code and arguments.
   *
   * @param errorCode the error code of the error to be reported
   * @param node the node specifying the location of the error
   * @param arguments the arguments to the error, used to compose the error message
   */
  void reportError(ParserErrorCode errorCode, ASTNode node, List<Object> arguments) {
    _errorListener.onError(new AnalysisError.con2(_source, node.offset, node.length, errorCode, arguments));
  }

  /**
   * Report an error with the given error code and arguments.
   *
   * @param errorCode the error code of the error to be reported
   * @param arguments the arguments to the error, used to compose the error message
   */
  void reportError8(ParserErrorCode errorCode, List<Object> arguments) {
    reportError9(errorCode, _currentToken, arguments);
  }

  /**
   * Report an error with the given error code and arguments.
   *
   * @param errorCode the error code of the error to be reported
   * @param token the token specifying the location of the error
   * @param arguments the arguments to the error, used to compose the error message
   */
  void reportError9(ParserErrorCode errorCode, Token token, List<Object> arguments) {
    _errorListener.onError(new AnalysisError.con2(_source, token.offset, token.length, errorCode, arguments));
  }

  /**
   * Look for user defined tasks in comments and convert them into info level analysis issues.
   *
   * @param commentToken the comment token to analyze
   */
  void scrapeTodoComment(Token commentToken) {
    JavaPatternMatcher matcher = new JavaPatternMatcher(TodoCode.TODO_REGEX, commentToken.lexeme);
    if (matcher.find()) {
      int offset = commentToken.offset + matcher.start() + matcher.group(1).length;
      int length = matcher.group(2).length;
      // _errorListener.onError(new AnalysisError.con2(_source, offset, length, TodoCode.TODO, [matcher.group(2)]));
    }
  }

  /**
   * 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.
   *
   * <pre>
   * finalConstVarOrType ::=
   *   | 'final' type?
   *   | 'const' type?
   *   | 'var'
   *   | type
   * </pre>
   *
   * @param startToken the token at which parsing is to begin
   * @return the token following the type that was parsed
   */
  Token skipFinalConstVarOrType(Token startToken) {
    if (matches3(startToken, Keyword.FINAL) || matches3(startToken, Keyword.CONST)) {
      Token next = startToken.next;
      if (matchesIdentifier2(next.next) || matches4(next.next, TokenType.LT) || matches3(next.next, Keyword.THIS)) {
        return skipTypeName(next);
      }
    } else if (matches3(startToken, Keyword.VAR)) {
      return startToken.next;
    } else if (matchesIdentifier2(startToken)) {
      Token next = startToken.next;
      if (matchesIdentifier2(next) || matches4(next, TokenType.LT) || matches3(next, Keyword.THIS) || (matches4(next, TokenType.PERIOD) && matchesIdentifier2(next.next) && (matchesIdentifier2(next.next.next) || matches4(next.next.next, TokenType.LT) || matches3(next.next.next, Keyword.THIS)))) {
        return skipReturnType(startToken);
      }
    }
    return null;
  }

  /**
   * Parse a list of formal parameters, starting at the given token, 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].
   *
   * <pre>
   * formalParameterList ::=
   *     '(' ')'
   *   | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
   *   | '(' optionalFormalParameters ')'
   *
   * normalFormalParameters ::=
   *     normalFormalParameter (',' normalFormalParameter)*
   *
   * optionalFormalParameters ::=
   *     optionalPositionalFormalParameters
   *   | namedFormalParameters
   *
   * optionalPositionalFormalParameters ::=
   *     '[' defaultFormalParameter (',' defaultFormalParameter)* ']'
   *
   * namedFormalParameters ::=
   *     '{' defaultNamedParameter (',' defaultNamedParameter)* '}'
   * </pre>
   *
   * @param startToken the token at which parsing is to begin
   * @return the token following the formal parameter list that was parsed
   */
  Token skipFormalParameterList(Token startToken) {
    if (!matches4(startToken, TokenType.OPEN_PAREN)) {
      return null;
    }
    Token next = startToken.next;
    if (matches4(next, TokenType.CLOSE_PAREN)) {
      return next.next;
    }
    if (matchesAny(next, [
        TokenType.AT,
        TokenType.OPEN_SQUARE_BRACKET,
        TokenType.OPEN_CURLY_BRACKET]) || matches3(next, Keyword.VOID) || (matchesIdentifier2(next) && (matchesAny(next.next, [TokenType.COMMA, TokenType.CLOSE_PAREN])))) {
      return skipPastMatchingToken(startToken);
    }
    if (matchesIdentifier2(next) && matches4(next.next, TokenType.OPEN_PAREN)) {
      Token afterParameters = skipFormalParameterList(next.next);
      if (afterParameters != null && (matchesAny(afterParameters, [TokenType.COMMA, TokenType.CLOSE_PAREN]))) {
        return skipPastMatchingToken(startToken);
      }
    }
    Token afterType = skipFinalConstVarOrType(next);
    if (afterType == null) {
      return null;
    }
    if (skipSimpleIdentifier(afterType) == null) {
      return null;
    }
    return skipPastMatchingToken(startToken);
  }

  /**
   * If the given token is a begin token with an associated end token, then return the token
   * following the end token. Otherwise, return `null`.
   *
   * @param startToken the token that is assumed to be a being token
   * @return the token following the matching end token
   */
  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 prefixed identifier, starting at the given token, 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].
   *
   * <pre>
   * prefixedIdentifier ::=
   *     identifier ('.' identifier)?
   * </pre>
   *
   * @param startToken the token at which parsing is to begin
   * @return the token following the prefixed identifier that was parsed
   */
  Token skipPrefixedIdentifier(Token startToken) {
    Token token = skipSimpleIdentifier(startToken);
    if (token == null) {
      return null;
    } else if (!matches4(token, TokenType.PERIOD)) {
      return token;
    }
    return skipSimpleIdentifier(token.next);
  }

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

  /**
   * Parse a simple identifier, starting at the given token, 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].
   *
   * <pre>
   * identifier ::=
   *     IDENTIFIER
   * </pre>
   *
   * @param startToken the token at which parsing is to begin
   * @return the token following the simple identifier that was parsed
   */
  Token skipSimpleIdentifier(Token startToken) {
    if (matches4(startToken, TokenType.IDENTIFIER) || (matches4(startToken, TokenType.KEYWORD) && ((startToken as KeywordToken)).keyword.isPseudoKeyword)) {
      return startToken.next;
    }
    return null;
  }

  /**
   * Parse a string literal that contains interpolations, starting at the given token, 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].
   *
   * @param startToken the token at which parsing is to begin
   * @return the string literal that was parsed
   */
  Token skipStringInterpolation(Token startToken) {
    Token token = startToken;
    TokenType type = token.type;
    while (identical(type, TokenType.STRING_INTERPOLATION_EXPRESSION) || identical(type, TokenType.STRING_INTERPOLATION_IDENTIFIER)) {
      if (identical(type, TokenType.STRING_INTERPOLATION_EXPRESSION)) {
        token = token.next;
        type = token.type;
        int bracketNestingLevel = 1;
        while (bracketNestingLevel > 0) {
          if (identical(type, TokenType.EOF)) {
            return null;
          } else if (identical(type, TokenType.OPEN_CURLY_BRACKET)) {
            bracketNestingLevel++;
          } else if (identical(type, TokenType.CLOSE_CURLY_BRACKET)) {
            bracketNestingLevel--;
          } else if (identical(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 (identical(type, TokenType.STRING)) {
        token = token.next;
        type = token.type;
      }
    }
    return token;
  }

  /**
   * Parse a string literal, starting at the given token, 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].
   *
   * <pre>
   * stringLiteral ::=
   *     MULTI_LINE_STRING+
   *   | SINGLE_LINE_STRING+
   * </pre>
   *
   * @param startToken the token at which parsing is to begin
   * @return the token following the string literal that was parsed
   */
  Token skipStringLiteral(Token startToken) {
    Token token = startToken;
    while (token != null && matches4(token, TokenType.STRING)) {
      token = token.next;
      TokenType type = token.type;
      if (identical(type, TokenType.STRING_INTERPOLATION_EXPRESSION) || identical(type, TokenType.STRING_INTERPOLATION_IDENTIFIER)) {
        token = skipStringInterpolation(token);
      }
    }
    if (identical(token, startToken)) {
      return null;
    }
    return token;
  }

  /**
   * Parse a list of type arguments, starting at the given token, 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].
   *
   * <pre>
   * typeArguments ::=
   *     '<' typeList '>'
   *
   * typeList ::=
   *     type (',' type)*
   * </pre>
   *
   * @param startToken the token at which parsing is to begin
   * @return the token following the type argument list that was parsed
   */
  Token skipTypeArgumentList(Token startToken) {
    Token token = startToken;
    if (!matches4(token, TokenType.LT)) {
      return null;
    }
    token = skipTypeName(token.next);
    if (token == null) {
      return null;
    }
    while (matches4(token, TokenType.COMMA)) {
      token = skipTypeName(token.next);
      if (token == null) {
        return null;
      }
    }
    if (identical(token.type, TokenType.GT)) {
      return token.next;
    } else if (identical(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 given token, 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].
   *
   * <pre>
   * type ::=
   *     qualified typeArguments?
   * </pre>
   *
   * @param startToken the token at which parsing is to begin
   * @return the token following the type name that was parsed
   */
  Token skipTypeName(Token startToken) {
    Token token = skipPrefixedIdentifier(startToken);
    if (token == null) {
      return null;
    }
    if (matches4(token, TokenType.LT)) {
      token = skipTypeArgumentList(token);
    }
    return token;
  }

  /**
   * Parse a list of type parameters, starting at the given token, 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].
   *
   * <pre>
   * typeParameterList ::=
   *     '<' typeParameter (',' typeParameter)* '>'
   * </pre>
   *
   * @param startToken the token at which parsing is to begin
   * @return the token following the type parameter list that was parsed
   */
  Token skipTypeParameterList(Token startToken) {
    if (!matches4(startToken, TokenType.LT)) {
      return null;
    }
    int depth = 1;
    Token next = startToken.next;
    while (depth > 0) {
      if (matches4(next, TokenType.EOF)) {
        return null;
      } else if (matches4(next, TokenType.LT)) {
        depth++;
      } else if (matches4(next, TokenType.GT)) {
        depth--;
      } else if (matches4(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 (matches4(next, TokenType.GT_GT)) {
        depth -= 2;
      } else if (matches4(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;
  }

  /**
   * Translate the characters at the given index in the given string, appending the translated
   * character to the given builder. The index is assumed to be valid.
   *
   * @param builder the builder to which the translated character is to be appended
   * @param lexeme the string containing the character(s) to be translated
   * @param index the index of the character to be translated
   * @return the index of the next character to be translated
   */
  int translateCharacter(JavaStringBuilder builder, String lexeme, int index) {
    int currentChar = lexeme.codeUnitAt(index);
    if (currentChar != 0x5C) {
      builder.appendChar(currentChar);
      return index + 1;
    }
    int length = lexeme.length;
    int currentIndex = index + 1;
    if (currentIndex >= length) {
      return length;
    }
    currentChar = lexeme.codeUnitAt(currentIndex);
    if (currentChar == 0x6E) {
      builder.appendChar(0xA);
    } else if (currentChar == 0x72) {
      builder.appendChar(0xD);
    } else if (currentChar == 0x66) {
      builder.appendChar(0xC);
    } else if (currentChar == 0x62) {
      builder.appendChar(0x8);
    } else if (currentChar == 0x74) {
      builder.appendChar(0x9);
    } else if (currentChar == 0x76) {
      builder.appendChar(0xB);
    } else if (currentChar == 0x78) {
      if (currentIndex + 2 >= length) {
        reportError8(ParserErrorCode.INVALID_HEX_ESCAPE, []);
        return length;
      }
      int firstDigit = lexeme.codeUnitAt(currentIndex + 1);
      int secondDigit = lexeme.codeUnitAt(currentIndex + 2);
      if (!isHexDigit(firstDigit) || !isHexDigit(secondDigit)) {
        reportError8(ParserErrorCode.INVALID_HEX_ESCAPE, []);
      } else {
        builder.appendChar(((Character.digit(firstDigit, 16) << 4) + Character.digit(secondDigit, 16)) as int);
      }
      return currentIndex + 3;
    } else if (currentChar == 0x75) {
      currentIndex++;
      if (currentIndex >= length) {
        reportError8(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
        return length;
      }
      currentChar = lexeme.codeUnitAt(currentIndex);
      if (currentChar == 0x7B) {
        currentIndex++;
        if (currentIndex >= length) {
          reportError8(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
          return length;
        }
        currentChar = lexeme.codeUnitAt(currentIndex);
        int digitCount = 0;
        int value = 0;
        while (currentChar != 0x7D) {
          if (!isHexDigit(currentChar)) {
            reportError8(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) {
            reportError8(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
            return length;
          }
          currentChar = lexeme.codeUnitAt(currentIndex);
        }
        if (digitCount < 1 || digitCount > 6) {
          reportError8(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
        }
        appendScalarValue(builder, lexeme.substring(index, currentIndex + 1), value, index, currentIndex);
        return currentIndex + 1;
      } else {
        if (currentIndex + 3 >= length) {
          reportError8(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)) {
          reportError8(ParserErrorCode.INVALID_UNICODE_ESCAPE, []);
        } else {
          appendScalarValue(builder, lexeme.substring(index, currentIndex + 1), (((((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 {
      builder.appendChar(currentChar);
    }
    return currentIndex + 1;
  }

  /**
   * Validate that the given parameter list does not contain any field initializers.
   *
   * @param parameterList the parameter list to be validated
   */
  void validateFormalParameterList(FormalParameterList parameterList) {
    for (FormalParameter parameter in parameterList.parameters) {
      if (parameter is FieldFormalParameter) {
        reportError(ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR, ((parameter as FieldFormalParameter)).identifier, []);
      }
    }
  }

  /**
   * Validate that the given set of modifiers is appropriate for a class and return the 'abstract'
   * keyword if there is one.
   *
   * @param modifiers the modifiers being validated
   */
  Token validateModifiersForClass(Modifiers modifiers) {
    validateModifiersForTopLevelDeclaration(modifiers);
    if (modifiers.constKeyword != null) {
      reportError9(ParserErrorCode.CONST_CLASS, modifiers.constKeyword, []);
    }
    if (modifiers.externalKeyword != null) {
      reportError9(ParserErrorCode.EXTERNAL_CLASS, modifiers.externalKeyword, []);
    }
    if (modifiers.finalKeyword != null) {
      reportError9(ParserErrorCode.FINAL_CLASS, modifiers.finalKeyword, []);
    }
    if (modifiers.varKeyword != null) {
      reportError9(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.
   *
   * @param modifiers the modifiers being validated
   * @return the 'const' or 'final' keyword associated with the constructor
   */
  Token validateModifiersForConstructor(Modifiers modifiers) {
    if (modifiers.abstractKeyword != null) {
      reportError8(ParserErrorCode.ABSTRACT_CLASS_MEMBER, []);
    }
    if (modifiers.finalKeyword != null) {
      reportError9(ParserErrorCode.FINAL_CONSTRUCTOR, modifiers.finalKeyword, []);
    }
    if (modifiers.staticKeyword != null) {
      reportError9(ParserErrorCode.STATIC_CONSTRUCTOR, modifiers.staticKeyword, []);
    }
    if (modifiers.varKeyword != null) {
      reportError9(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) {
      reportError9(ParserErrorCode.EXTERNAL_AFTER_CONST, externalKeyword, []);
    }
    if (externalKeyword != null && factoryKeyword != null && factoryKeyword.offset < externalKeyword.offset) {
      reportError9(ParserErrorCode.EXTERNAL_AFTER_FACTORY, externalKeyword, []);
    }
    return constKeyword;
  }

  /**
   * Validate that the given set of modifiers is appropriate for a field and return the 'final',
   * 'const' or 'var' keyword if there is one.
   *
   * @param modifiers the modifiers being validated
   * @return the 'final', 'const' or 'var' keyword associated with the field
   */
  Token validateModifiersForField(Modifiers modifiers) {
    if (modifiers.abstractKeyword != null) {
      reportError8(ParserErrorCode.ABSTRACT_CLASS_MEMBER, []);
    }
    if (modifiers.externalKeyword != null) {
      reportError9(ParserErrorCode.EXTERNAL_FIELD, modifiers.externalKeyword, []);
    }
    if (modifiers.factoryKeyword != null) {
      reportError9(ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.factoryKeyword, []);
    }
    Token staticKeyword = modifiers.staticKeyword;
    Token constKeyword = modifiers.constKeyword;
    Token finalKeyword = modifiers.finalKeyword;
    Token varKeyword = modifiers.varKeyword;
    if (constKeyword != null) {
      if (finalKeyword != null) {
        reportError9(ParserErrorCode.CONST_AND_FINAL, finalKeyword, []);
      }
      if (varKeyword != null) {
        reportError9(ParserErrorCode.CONST_AND_VAR, varKeyword, []);
      }
      if (staticKeyword != null && constKeyword.offset < staticKeyword.offset) {
        reportError9(ParserErrorCode.STATIC_AFTER_CONST, staticKeyword, []);
      }
    } else if (finalKeyword != null) {
      if (varKeyword != null) {
        reportError9(ParserErrorCode.FINAL_AND_VAR, varKeyword, []);
      }
      if (staticKeyword != null && finalKeyword.offset < staticKeyword.offset) {
        reportError9(ParserErrorCode.STATIC_AFTER_FINAL, staticKeyword, []);
      }
    } else if (varKeyword != null && staticKeyword != null && varKeyword.offset < staticKeyword.offset) {
      reportError9(ParserErrorCode.STATIC_AFTER_VAR, staticKeyword, []);
    }
    return lexicallyFirst([constKeyword, finalKeyword, varKeyword]);
  }

  /**
   * Validate that the given set of modifiers is appropriate for a local function.
   *
   * @param modifiers the modifiers being validated
   */
  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) {
      reportError8(ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER, []);
    }
  }

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

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

  /**
   * Validate that the given set of modifiers is appropriate for a top-level declaration.
   *
   * @param modifiers the modifiers being validated
   */
  void validateModifiersForTopLevelDeclaration(Modifiers modifiers) {
    if (modifiers.factoryKeyword != null) {
      reportError9(ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION, modifiers.factoryKeyword, []);
    }
    if (modifiers.staticKeyword != null) {
      reportError9(ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION, modifiers.staticKeyword, []);
    }
  }

  /**
   * Validate that the given set of modifiers is appropriate for a top-level function.
   *
   * @param modifiers the modifiers being validated
   */
  void validateModifiersForTopLevelFunction(Modifiers modifiers) {
    validateModifiersForTopLevelDeclaration(modifiers);
    if (modifiers.abstractKeyword != null) {
      reportError8(ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION, []);
    }
    if (modifiers.constKeyword != null) {
      reportError9(ParserErrorCode.CONST_CLASS, modifiers.constKeyword, []);
    }
    if (modifiers.finalKeyword != null) {
      reportError9(ParserErrorCode.FINAL_CLASS, modifiers.finalKeyword, []);
    }
    if (modifiers.varKeyword != null) {
      reportError9(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.
   *
   * @param modifiers the modifiers being validated
   * @return the 'final', 'const' or 'var' keyword associated with the field
   */
  Token validateModifiersForTopLevelVariable(Modifiers modifiers) {
    validateModifiersForTopLevelDeclaration(modifiers);
    if (modifiers.abstractKeyword != null) {
      reportError8(ParserErrorCode.ABSTRACT_TOP_LEVEL_VARIABLE, []);
    }
    if (modifiers.externalKeyword != null) {
      reportError9(ParserErrorCode.EXTERNAL_FIELD, modifiers.externalKeyword, []);
    }
    Token constKeyword = modifiers.constKeyword;
    Token finalKeyword = modifiers.finalKeyword;
    Token varKeyword = modifiers.varKeyword;
    if (constKeyword != null) {
      if (finalKeyword != null) {
        reportError9(ParserErrorCode.CONST_AND_FINAL, finalKeyword, []);
      }
      if (varKeyword != null) {
        reportError9(ParserErrorCode.CONST_AND_VAR, varKeyword, []);
      }
    } else if (finalKeyword != null) {
      if (varKeyword != null) {
        reportError9(ParserErrorCode.FINAL_AND_VAR, varKeyword, []);
      }
    }
    return 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.
   *
   * @param modifiers the modifiers being validated
   */
  void validateModifiersForTypedef(Modifiers modifiers) {
    validateModifiersForTopLevelDeclaration(modifiers);
    if (modifiers.abstractKeyword != null) {
      reportError9(ParserErrorCode.ABSTRACT_TYPEDEF, modifiers.abstractKeyword, []);
    }
    if (modifiers.constKeyword != null) {
      reportError9(ParserErrorCode.CONST_TYPEDEF, modifiers.constKeyword, []);
    }
    if (modifiers.externalKeyword != null) {
      reportError9(ParserErrorCode.EXTERNAL_TYPEDEF, modifiers.externalKeyword, []);
    }
    if (modifiers.finalKeyword != null) {
      reportError9(ParserErrorCode.FINAL_TYPEDEF, modifiers.finalKeyword, []);
    }
    if (modifiers.varKeyword != null) {
      reportError9(ParserErrorCode.VAR_TYPEDEF, modifiers.varKeyword, []);
    }
  }
}
class KeywordToken_13 extends KeywordToken {
  KeywordToken_13(Keyword arg0, int arg1) : super(arg0, arg1);
  int get length => 0;
}
class AnalysisErrorListener_14 implements AnalysisErrorListener {
  List<bool> errorFound;
  AnalysisErrorListener_14(this.errorFound);
  void onError(AnalysisError error) {
    errorFound[0] = true;
  }
}
/**
 * The enumeration `ParserErrorCode` defines the error codes used for errors detected by the
 * parser. The convention for this class is for the name of the error code to indicate the problem
 * that caused the error to be generated and for the error message to explain what is wrong and,
 * when appropriate, how the problem can be corrected.
 *
 * @coverage dart.engine.parser
 */
class ParserErrorCode extends Enum<ParserErrorCode> implements ErrorCode {
  static final ParserErrorCode ABSTRACT_CLASS_MEMBER = new ParserErrorCode.con3('ABSTRACT_CLASS_MEMBER', 0, "Members of classes cannot be declared to be 'abstract'");
  static final ParserErrorCode ABSTRACT_STATIC_METHOD = new ParserErrorCode.con3('ABSTRACT_STATIC_METHOD', 1, "Static methods cannot be declared to be 'abstract'");
  static final ParserErrorCode ABSTRACT_TOP_LEVEL_FUNCTION = new ParserErrorCode.con3('ABSTRACT_TOP_LEVEL_FUNCTION', 2, "Top-level functions cannot be declared to be 'abstract'");
  static final ParserErrorCode ABSTRACT_TOP_LEVEL_VARIABLE = new ParserErrorCode.con3('ABSTRACT_TOP_LEVEL_VARIABLE', 3, "Top-level variables cannot be declared to be 'abstract'");
  static final ParserErrorCode ABSTRACT_TYPEDEF = new ParserErrorCode.con3('ABSTRACT_TYPEDEF', 4, "Type aliases cannot be declared to be 'abstract'");
  static final ParserErrorCode ASSERT_DOES_NOT_TAKE_ASSIGNMENT = new ParserErrorCode.con3('ASSERT_DOES_NOT_TAKE_ASSIGNMENT', 5, "Assert cannot be called on an assignment");
  static final ParserErrorCode ASSERT_DOES_NOT_TAKE_CASCADE = new ParserErrorCode.con3('ASSERT_DOES_NOT_TAKE_CASCADE', 6, "Assert cannot be called on cascade");
  static final ParserErrorCode ASSERT_DOES_NOT_TAKE_THROW = new ParserErrorCode.con3('ASSERT_DOES_NOT_TAKE_THROW', 7, "Assert cannot be called on throws");
  static final ParserErrorCode ASSERT_DOES_NOT_TAKE_RETHROW = new ParserErrorCode.con3('ASSERT_DOES_NOT_TAKE_RETHROW', 8, "Assert cannot be called on rethrows");
  static final ParserErrorCode BREAK_OUTSIDE_OF_LOOP = new ParserErrorCode.con3('BREAK_OUTSIDE_OF_LOOP', 9, "A break statement cannot be used outside of a loop or switch statement");
  static final ParserErrorCode CONST_AND_FINAL = new ParserErrorCode.con3('CONST_AND_FINAL', 10, "Members cannot be declared to be both 'const' and 'final'");
  static final ParserErrorCode CONST_AND_VAR = new ParserErrorCode.con3('CONST_AND_VAR', 11, "Members cannot be declared to be both 'const' and 'var'");
  static final ParserErrorCode CONST_CLASS = new ParserErrorCode.con3('CONST_CLASS', 12, "Classes cannot be declared to be 'const'");
  static final ParserErrorCode CONST_CONSTRUCTOR_WITH_BODY = new ParserErrorCode.con3('CONST_CONSTRUCTOR_WITH_BODY', 13, "'const' constructors cannot have a body");
  static final ParserErrorCode CONST_FACTORY = new ParserErrorCode.con3('CONST_FACTORY', 14, "Only redirecting factory constructors can be declared to be 'const'");
  static final ParserErrorCode CONST_METHOD = new ParserErrorCode.con3('CONST_METHOD', 15, "Getters, setters and methods cannot be declared to be 'const'");
  static final ParserErrorCode CONST_TYPEDEF = new ParserErrorCode.con3('CONST_TYPEDEF', 16, "Type aliases cannot be declared to be 'const'");
  static final ParserErrorCode CONSTRUCTOR_WITH_RETURN_TYPE = new ParserErrorCode.con3('CONSTRUCTOR_WITH_RETURN_TYPE', 17, "Constructors cannot have a return type");
  static final ParserErrorCode CONTINUE_OUTSIDE_OF_LOOP = new ParserErrorCode.con3('CONTINUE_OUTSIDE_OF_LOOP', 18, "A continue statement cannot be used outside of a loop or switch statement");
  static final ParserErrorCode CONTINUE_WITHOUT_LABEL_IN_CASE = new ParserErrorCode.con3('CONTINUE_WITHOUT_LABEL_IN_CASE', 19, "A continue statement in a switch statement must have a label as a target");
  static final ParserErrorCode DEPRECATED_ARGUMENT_DEFINITION_TEST = new ParserErrorCode.con3('DEPRECATED_ARGUMENT_DEFINITION_TEST', 20, "The argument definition test ('?' operator) has been deprecated");
  static final ParserErrorCode DIRECTIVE_AFTER_DECLARATION = new ParserErrorCode.con3('DIRECTIVE_AFTER_DECLARATION', 21, "Directives must appear before any declarations");
  static final ParserErrorCode DUPLICATE_LABEL_IN_SWITCH_STATEMENT = new ParserErrorCode.con3('DUPLICATE_LABEL_IN_SWITCH_STATEMENT', 22, "The label %s was already used in this switch statement");
  static final ParserErrorCode DUPLICATED_MODIFIER = new ParserErrorCode.con3('DUPLICATED_MODIFIER', 23, "The modifier '%s' was already specified.");
  static final ParserErrorCode EQUALITY_CANNOT_BE_EQUALITY_OPERAND = new ParserErrorCode.con3('EQUALITY_CANNOT_BE_EQUALITY_OPERAND', 24, "Equality expression cannot be operand of another equality expression.");
  static final ParserErrorCode EXPECTED_CASE_OR_DEFAULT = new ParserErrorCode.con3('EXPECTED_CASE_OR_DEFAULT', 25, "Expected 'case' or 'default'");
  static final ParserErrorCode EXPECTED_CLASS_MEMBER = new ParserErrorCode.con3('EXPECTED_CLASS_MEMBER', 26, "Expected a class member");
  static final ParserErrorCode EXPECTED_EXECUTABLE = new ParserErrorCode.con3('EXPECTED_EXECUTABLE', 27, "Expected a method, getter, setter or operator declaration");
  static final ParserErrorCode EXPECTED_LIST_OR_MAP_LITERAL = new ParserErrorCode.con3('EXPECTED_LIST_OR_MAP_LITERAL', 28, "Expected a list or map literal");
  static final ParserErrorCode EXPECTED_STRING_LITERAL = new ParserErrorCode.con3('EXPECTED_STRING_LITERAL', 29, "Expected a string literal");
  static final ParserErrorCode EXPECTED_TOKEN = new ParserErrorCode.con3('EXPECTED_TOKEN', 30, "Expected to find '%s'");
  static final ParserErrorCode EXPECTED_ONE_LIST_TYPE_ARGUMENTS = new ParserErrorCode.con3('EXPECTED_ONE_LIST_TYPE_ARGUMENTS', 31, "List literal requires exactly one type arguments or none, but %d found");
  static final ParserErrorCode EXPECTED_TWO_MAP_TYPE_ARGUMENTS = new ParserErrorCode.con3('EXPECTED_TWO_MAP_TYPE_ARGUMENTS', 32, "Map literal requires exactly two type arguments or none, but %d found");
  static final ParserErrorCode EXPECTED_TYPE_NAME = new ParserErrorCode.con3('EXPECTED_TYPE_NAME', 33, "Expected a type name");
  static final ParserErrorCode EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE = new ParserErrorCode.con3('EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE', 34, "Export directives must preceed part directives");
  static final ParserErrorCode EXTERNAL_AFTER_CONST = new ParserErrorCode.con3('EXTERNAL_AFTER_CONST', 35, "The modifier 'external' should be before the modifier 'const'");
  static final ParserErrorCode EXTERNAL_AFTER_FACTORY = new ParserErrorCode.con3('EXTERNAL_AFTER_FACTORY', 36, "The modifier 'external' should be before the modifier 'factory'");
  static final ParserErrorCode EXTERNAL_AFTER_STATIC = new ParserErrorCode.con3('EXTERNAL_AFTER_STATIC', 37, "The modifier 'external' should be before the modifier 'static'");
  static final ParserErrorCode EXTERNAL_CLASS = new ParserErrorCode.con3('EXTERNAL_CLASS', 38, "Classes cannot be declared to be 'external'");
  static final ParserErrorCode EXTERNAL_CONSTRUCTOR_WITH_BODY = new ParserErrorCode.con3('EXTERNAL_CONSTRUCTOR_WITH_BODY', 39, "External constructors cannot have a body");
  static final ParserErrorCode EXTERNAL_FIELD = new ParserErrorCode.con3('EXTERNAL_FIELD', 40, "Fields cannot be declared to be 'external'");
  static final ParserErrorCode EXTERNAL_GETTER_WITH_BODY = new ParserErrorCode.con3('EXTERNAL_GETTER_WITH_BODY', 41, "External getters cannot have a body");
  static final ParserErrorCode EXTERNAL_METHOD_WITH_BODY = new ParserErrorCode.con3('EXTERNAL_METHOD_WITH_BODY', 42, "External methods cannot have a body");
  static final ParserErrorCode EXTERNAL_OPERATOR_WITH_BODY = new ParserErrorCode.con3('EXTERNAL_OPERATOR_WITH_BODY', 43, "External operators cannot have a body");
  static final ParserErrorCode EXTERNAL_SETTER_WITH_BODY = new ParserErrorCode.con3('EXTERNAL_SETTER_WITH_BODY', 44, "External setters cannot have a body");
  static final ParserErrorCode EXTERNAL_TYPEDEF = new ParserErrorCode.con3('EXTERNAL_TYPEDEF', 45, "Type aliases cannot be declared to be 'external'");
  static final ParserErrorCode FACTORY_TOP_LEVEL_DECLARATION = new ParserErrorCode.con3('FACTORY_TOP_LEVEL_DECLARATION', 46, "Top-level declarations cannot be declared to be 'factory'");
  static final ParserErrorCode FACTORY_WITHOUT_BODY = new ParserErrorCode.con3('FACTORY_WITHOUT_BODY', 47, "A non-redirecting 'factory' constructor must have a body");
  static final ParserErrorCode FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR = new ParserErrorCode.con3('FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR', 48, "Field initializers can only be used in a constructor");
  static final ParserErrorCode FINAL_AND_VAR = new ParserErrorCode.con3('FINAL_AND_VAR', 49, "Members cannot be declared to be both 'final' and 'var'");
  static final ParserErrorCode FINAL_CLASS = new ParserErrorCode.con3('FINAL_CLASS', 50, "Classes cannot be declared to be 'final'");
  static final ParserErrorCode FINAL_CONSTRUCTOR = new ParserErrorCode.con3('FINAL_CONSTRUCTOR', 51, "A constructor cannot be declared to be 'final'");
  static final ParserErrorCode FINAL_METHOD = new ParserErrorCode.con3('FINAL_METHOD', 52, "Getters, setters and methods cannot be declared to be 'final'");
  static final ParserErrorCode FINAL_TYPEDEF = new ParserErrorCode.con3('FINAL_TYPEDEF', 53, "Type aliases cannot be declared to be 'final'");
  static final ParserErrorCode FUNCTION_TYPED_PARAMETER_VAR = new ParserErrorCode.con3('FUNCTION_TYPED_PARAMETER_VAR', 54, "Function typed parameters cannot specify 'const', 'final' or 'var' instead of return type");
  static final ParserErrorCode GETTER_IN_FUNCTION = new ParserErrorCode.con3('GETTER_IN_FUNCTION', 55, "Getters cannot be defined within methods or functions");
  static final ParserErrorCode GETTER_WITH_PARAMETERS = new ParserErrorCode.con3('GETTER_WITH_PARAMETERS', 56, "Getter should be declared without a parameter list");
  static final ParserErrorCode ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE = new ParserErrorCode.con3('ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE', 57, "Illegal assignment to non-assignable expression");
  static final ParserErrorCode IMPLEMENTS_BEFORE_EXTENDS = new ParserErrorCode.con3('IMPLEMENTS_BEFORE_EXTENDS', 58, "The extends clause must be before the implements clause");
  static final ParserErrorCode IMPLEMENTS_BEFORE_WITH = new ParserErrorCode.con3('IMPLEMENTS_BEFORE_WITH', 59, "The with clause must be before the implements clause");
  static final ParserErrorCode IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE = new ParserErrorCode.con3('IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE', 60, "Import directives must preceed part directives");
  static final ParserErrorCode INITIALIZED_VARIABLE_IN_FOR_EACH = new ParserErrorCode.con3('INITIALIZED_VARIABLE_IN_FOR_EACH', 61, "The loop variable in a for-each loop cannot be initialized");
  static final ParserErrorCode INVALID_CODE_POINT = new ParserErrorCode.con3('INVALID_CODE_POINT', 62, "The escape sequence '%s' is not a valid code point");
  static final ParserErrorCode INVALID_COMMENT_REFERENCE = new ParserErrorCode.con3('INVALID_COMMENT_REFERENCE', 63, "Comment references should contain a possibly prefixed identifier and can start with 'new', but should not contain anything else");
  static final ParserErrorCode INVALID_HEX_ESCAPE = new ParserErrorCode.con3('INVALID_HEX_ESCAPE', 64, "An escape sequence starting with '\\x' must be followed by 2 hexidecimal digits");
  static final ParserErrorCode INVALID_OPERATOR = new ParserErrorCode.con3('INVALID_OPERATOR', 65, "The string '%s' is not a valid operator");
  static final ParserErrorCode INVALID_OPERATOR_FOR_SUPER = new ParserErrorCode.con3('INVALID_OPERATOR_FOR_SUPER', 66, "The operator '%s' cannot be used with 'super'");
  static final ParserErrorCode INVALID_UNICODE_ESCAPE = new ParserErrorCode.con3('INVALID_UNICODE_ESCAPE', 67, "An escape sequence starting with '\\u' must be followed by 4 hexidecimal digits or from 1 to 6 digits between '{' and '}'");
  static final ParserErrorCode LIBRARY_DIRECTIVE_NOT_FIRST = new ParserErrorCode.con3('LIBRARY_DIRECTIVE_NOT_FIRST', 68, "The library directive must appear before all other directives");
  static final ParserErrorCode LOCAL_FUNCTION_DECLARATION_MODIFIER = new ParserErrorCode.con3('LOCAL_FUNCTION_DECLARATION_MODIFIER', 69, "Local function declarations cannot specify any modifier");
  static final ParserErrorCode MISSING_ASSIGNABLE_SELECTOR = new ParserErrorCode.con3('MISSING_ASSIGNABLE_SELECTOR', 70, "Missing selector such as \".<identifier>\" or \"[0]\"");
  static final ParserErrorCode MISSING_CATCH_OR_FINALLY = new ParserErrorCode.con3('MISSING_CATCH_OR_FINALLY', 71, "A try statement must have either a catch or finally clause");
  static final ParserErrorCode MISSING_CLASS_BODY = new ParserErrorCode.con3('MISSING_CLASS_BODY', 72, "A class definition must have a body, even if it is empty");
  static final ParserErrorCode MISSING_CLOSING_PARENTHESIS = new ParserErrorCode.con3('MISSING_CLOSING_PARENTHESIS', 73, "The closing parenthesis is missing");
  static final ParserErrorCode MISSING_CONST_FINAL_VAR_OR_TYPE = new ParserErrorCode.con3('MISSING_CONST_FINAL_VAR_OR_TYPE', 74, "Variables must be declared using the keywords 'const', 'final', 'var' or a type name");
  static final ParserErrorCode MISSING_EXPRESSION_IN_THROW = new ParserErrorCode.con3('MISSING_EXPRESSION_IN_THROW', 75, "Throw expressions must compute the object to be thrown");
  static final ParserErrorCode MISSING_FUNCTION_BODY = new ParserErrorCode.con3('MISSING_FUNCTION_BODY', 76, "A function body must be provided");
  static final ParserErrorCode MISSING_FUNCTION_PARAMETERS = new ParserErrorCode.con3('MISSING_FUNCTION_PARAMETERS', 77, "Functions must have an explicit list of parameters");
  static final ParserErrorCode MISSING_IDENTIFIER = new ParserErrorCode.con3('MISSING_IDENTIFIER', 78, "Expected an identifier");
  static final ParserErrorCode MISSING_KEYWORD_OPERATOR = new ParserErrorCode.con3('MISSING_KEYWORD_OPERATOR', 79, "Operator declarations must be preceeded by the keyword 'operator'");
  static final ParserErrorCode MISSING_NAME_IN_LIBRARY_DIRECTIVE = new ParserErrorCode.con3('MISSING_NAME_IN_LIBRARY_DIRECTIVE', 80, "Library directives must include a library name");
  static final ParserErrorCode MISSING_NAME_IN_PART_OF_DIRECTIVE = new ParserErrorCode.con3('MISSING_NAME_IN_PART_OF_DIRECTIVE', 81, "Library directives must include a library name");
  static final ParserErrorCode MISSING_STATEMENT = new ParserErrorCode.con3('MISSING_STATEMENT', 82, "Expected a statement");
  static final ParserErrorCode MISSING_TERMINATOR_FOR_PARAMETER_GROUP = new ParserErrorCode.con3('MISSING_TERMINATOR_FOR_PARAMETER_GROUP', 83, "There is no '%s' to close the parameter group");
  static final ParserErrorCode MISSING_TYPEDEF_PARAMETERS = new ParserErrorCode.con3('MISSING_TYPEDEF_PARAMETERS', 84, "Type aliases for functions must have an explicit list of parameters");
  static final ParserErrorCode MISSING_VARIABLE_IN_FOR_EACH = new ParserErrorCode.con3('MISSING_VARIABLE_IN_FOR_EACH', 85, "A loop variable must be declared in a for-each loop before the 'in', but none were found");
  static final ParserErrorCode MIXED_PARAMETER_GROUPS = new ParserErrorCode.con3('MIXED_PARAMETER_GROUPS', 86, "Cannot have both positional and named parameters in a single parameter list");
  static final ParserErrorCode MULTIPLE_EXTENDS_CLAUSES = new ParserErrorCode.con3('MULTIPLE_EXTENDS_CLAUSES', 87, "Each class definition can have at most one extends clause");
  static final ParserErrorCode MULTIPLE_IMPLEMENTS_CLAUSES = new ParserErrorCode.con3('MULTIPLE_IMPLEMENTS_CLAUSES', 88, "Each class definition can have at most one implements clause");
  static final ParserErrorCode MULTIPLE_LIBRARY_DIRECTIVES = new ParserErrorCode.con3('MULTIPLE_LIBRARY_DIRECTIVES', 89, "Only one library directive may be declared in a file");
  static final ParserErrorCode MULTIPLE_NAMED_PARAMETER_GROUPS = new ParserErrorCode.con3('MULTIPLE_NAMED_PARAMETER_GROUPS', 90, "Cannot have multiple groups of named parameters in a single parameter list");
  static final ParserErrorCode MULTIPLE_PART_OF_DIRECTIVES = new ParserErrorCode.con3('MULTIPLE_PART_OF_DIRECTIVES', 91, "Only one part-of directive may be declared in a file");
  static final ParserErrorCode MULTIPLE_POSITIONAL_PARAMETER_GROUPS = new ParserErrorCode.con3('MULTIPLE_POSITIONAL_PARAMETER_GROUPS', 92, "Cannot have multiple groups of positional parameters in a single parameter list");
  static final ParserErrorCode MULTIPLE_VARIABLES_IN_FOR_EACH = new ParserErrorCode.con3('MULTIPLE_VARIABLES_IN_FOR_EACH', 93, "A single loop variable must be declared in a for-each loop before the 'in', but %s were found");
  static final ParserErrorCode MULTIPLE_WITH_CLAUSES = new ParserErrorCode.con3('MULTIPLE_WITH_CLAUSES', 94, "Each class definition can have at most one with clause");
  static final ParserErrorCode NAMED_FUNCTION_EXPRESSION = new ParserErrorCode.con3('NAMED_FUNCTION_EXPRESSION', 95, "Function expressions cannot be named");
  static final ParserErrorCode NAMED_PARAMETER_OUTSIDE_GROUP = new ParserErrorCode.con3('NAMED_PARAMETER_OUTSIDE_GROUP', 96, "Named parameters must be enclosed in curly braces ('{' and '}')");
  static final ParserErrorCode NATIVE_CLAUSE_IN_NON_SDK_CODE = new ParserErrorCode.con3('NATIVE_CLAUSE_IN_NON_SDK_CODE', 97, "Native clause can only be used in the SDK and code that is loaded through native extensions");
  static final ParserErrorCode NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE = new ParserErrorCode.con3('NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE', 98, "Native functions can only be declared in the SDK and code that is loaded through native extensions");
  static final ParserErrorCode NON_CONSTRUCTOR_FACTORY = new ParserErrorCode.con3('NON_CONSTRUCTOR_FACTORY', 99, "Only constructors can be declared to be a 'factory'");
  static final ParserErrorCode NON_IDENTIFIER_LIBRARY_NAME = new ParserErrorCode.con3('NON_IDENTIFIER_LIBRARY_NAME', 100, "The name of a library must be an identifier");
  static final ParserErrorCode NON_PART_OF_DIRECTIVE_IN_PART = new ParserErrorCode.con3('NON_PART_OF_DIRECTIVE_IN_PART', 101, "The part-of directive must be the only directive in a part");
  static final ParserErrorCode NON_USER_DEFINABLE_OPERATOR = new ParserErrorCode.con3('NON_USER_DEFINABLE_OPERATOR', 102, "The operator '%s' is not user definable");
  static final ParserErrorCode NORMAL_BEFORE_OPTIONAL_PARAMETERS = new ParserErrorCode.con3('NORMAL_BEFORE_OPTIONAL_PARAMETERS', 103, "Normal parameters must occur before optional parameters");
  static final ParserErrorCode POSITIONAL_AFTER_NAMED_ARGUMENT = new ParserErrorCode.con3('POSITIONAL_AFTER_NAMED_ARGUMENT', 104, "Positional arguments must occur before named arguments");
  static final ParserErrorCode POSITIONAL_PARAMETER_OUTSIDE_GROUP = new ParserErrorCode.con3('POSITIONAL_PARAMETER_OUTSIDE_GROUP', 105, "Positional parameters must be enclosed in square brackets ('[' and ']')");
  static final ParserErrorCode REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR = new ParserErrorCode.con3('REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR', 106, "Only factory constructor can specify '=' redirection.");
  static final ParserErrorCode SETTER_IN_FUNCTION = new ParserErrorCode.con3('SETTER_IN_FUNCTION', 107, "Setters cannot be defined within methods or functions");
  static final ParserErrorCode STATIC_AFTER_CONST = new ParserErrorCode.con3('STATIC_AFTER_CONST', 108, "The modifier 'static' should be before the modifier 'const'");
  static final ParserErrorCode STATIC_AFTER_FINAL = new ParserErrorCode.con3('STATIC_AFTER_FINAL', 109, "The modifier 'static' should be before the modifier 'final'");
  static final ParserErrorCode STATIC_AFTER_VAR = new ParserErrorCode.con3('STATIC_AFTER_VAR', 110, "The modifier 'static' should be before the modifier 'var'");
  static final ParserErrorCode STATIC_CONSTRUCTOR = new ParserErrorCode.con3('STATIC_CONSTRUCTOR', 111, "Constructors cannot be static");
  static final ParserErrorCode STATIC_GETTER_WITHOUT_BODY = new ParserErrorCode.con3('STATIC_GETTER_WITHOUT_BODY', 112, "A 'static' getter must have a body");
  static final ParserErrorCode STATIC_OPERATOR = new ParserErrorCode.con3('STATIC_OPERATOR', 113, "Operators cannot be static");
  static final ParserErrorCode STATIC_SETTER_WITHOUT_BODY = new ParserErrorCode.con3('STATIC_SETTER_WITHOUT_BODY', 114, "A 'static' setter must have a body");
  static final ParserErrorCode STATIC_TOP_LEVEL_DECLARATION = new ParserErrorCode.con3('STATIC_TOP_LEVEL_DECLARATION', 115, "Top-level declarations cannot be declared to be 'static'");
  static final ParserErrorCode SWITCH_HAS_CASE_AFTER_DEFAULT_CASE = new ParserErrorCode.con3('SWITCH_HAS_CASE_AFTER_DEFAULT_CASE', 116, "The 'default' case should be the last case in a switch statement");
  static final ParserErrorCode SWITCH_HAS_MULTIPLE_DEFAULT_CASES = new ParserErrorCode.con3('SWITCH_HAS_MULTIPLE_DEFAULT_CASES', 117, "The 'default' case can only be declared once");
  static final ParserErrorCode TOP_LEVEL_OPERATOR = new ParserErrorCode.con3('TOP_LEVEL_OPERATOR', 118, "Operators must be declared within a class");
  static final ParserErrorCode UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP = new ParserErrorCode.con3('UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP', 119, "There is no '%s' to open a parameter group");
  static final ParserErrorCode UNEXPECTED_TOKEN = new ParserErrorCode.con3('UNEXPECTED_TOKEN', 120, "Unexpected token '%s'");
  static final ParserErrorCode WITH_BEFORE_EXTENDS = new ParserErrorCode.con3('WITH_BEFORE_EXTENDS', 121, "The extends clause must be before the with clause");
  static final ParserErrorCode WITH_WITHOUT_EXTENDS = new ParserErrorCode.con3('WITH_WITHOUT_EXTENDS', 122, "The with clause cannot be used without an extends clause");
  static final ParserErrorCode WRONG_SEPARATOR_FOR_NAMED_PARAMETER = new ParserErrorCode.con3('WRONG_SEPARATOR_FOR_NAMED_PARAMETER', 123, "The default value of a named parameter should be preceeded by ':'");
  static final ParserErrorCode WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER = new ParserErrorCode.con3('WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER', 124, "The default value of a positional parameter should be preceeded by '='");
  static final ParserErrorCode WRONG_TERMINATOR_FOR_PARAMETER_GROUP = new ParserErrorCode.con3('WRONG_TERMINATOR_FOR_PARAMETER_GROUP', 125, "Expected '%s' to close parameter group");
  static final ParserErrorCode VAR_AND_TYPE = new ParserErrorCode.con3('VAR_AND_TYPE', 126, "Variables cannot be declared using both 'var' and a type name; remove the 'var'");
  static final ParserErrorCode VAR_AS_TYPE_NAME = new ParserErrorCode.con3('VAR_AS_TYPE_NAME', 127, "The keyword 'var' cannot be used as a type name");
  static final ParserErrorCode VAR_CLASS = new ParserErrorCode.con3('VAR_CLASS', 128, "Classes cannot be declared to be 'var'");
  static final ParserErrorCode VAR_RETURN_TYPE = new ParserErrorCode.con3('VAR_RETURN_TYPE', 129, "The return type cannot be 'var'");
  static final ParserErrorCode VAR_TYPEDEF = new ParserErrorCode.con3('VAR_TYPEDEF', 130, "Type aliases cannot be declared to be 'var'");
  static final ParserErrorCode VOID_PARAMETER = new ParserErrorCode.con3('VOID_PARAMETER', 131, "Parameters cannot have a type of 'void'");
  static final ParserErrorCode VOID_VARIABLE = new ParserErrorCode.con3('VOID_VARIABLE', 132, "Variables cannot have a type of 'void'");
  static final List<ParserErrorCode> values = [
      ABSTRACT_CLASS_MEMBER,
      ABSTRACT_STATIC_METHOD,
      ABSTRACT_TOP_LEVEL_FUNCTION,
      ABSTRACT_TOP_LEVEL_VARIABLE,
      ABSTRACT_TYPEDEF,
      ASSERT_DOES_NOT_TAKE_ASSIGNMENT,
      ASSERT_DOES_NOT_TAKE_CASCADE,
      ASSERT_DOES_NOT_TAKE_THROW,
      ASSERT_DOES_NOT_TAKE_RETHROW,
      BREAK_OUTSIDE_OF_LOOP,
      CONST_AND_FINAL,
      CONST_AND_VAR,
      CONST_CLASS,
      CONST_CONSTRUCTOR_WITH_BODY,
      CONST_FACTORY,
      CONST_METHOD,
      CONST_TYPEDEF,
      CONSTRUCTOR_WITH_RETURN_TYPE,
      CONTINUE_OUTSIDE_OF_LOOP,
      CONTINUE_WITHOUT_LABEL_IN_CASE,
      DEPRECATED_ARGUMENT_DEFINITION_TEST,
      DIRECTIVE_AFTER_DECLARATION,
      DUPLICATE_LABEL_IN_SWITCH_STATEMENT,
      DUPLICATED_MODIFIER,
      EQUALITY_CANNOT_BE_EQUALITY_OPERAND,
      EXPECTED_CASE_OR_DEFAULT,
      EXPECTED_CLASS_MEMBER,
      EXPECTED_EXECUTABLE,
      EXPECTED_LIST_OR_MAP_LITERAL,
      EXPECTED_STRING_LITERAL,
      EXPECTED_TOKEN,
      EXPECTED_ONE_LIST_TYPE_ARGUMENTS,
      EXPECTED_TWO_MAP_TYPE_ARGUMENTS,
      EXPECTED_TYPE_NAME,
      EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE,
      EXTERNAL_AFTER_CONST,
      EXTERNAL_AFTER_FACTORY,
      EXTERNAL_AFTER_STATIC,
      EXTERNAL_CLASS,
      EXTERNAL_CONSTRUCTOR_WITH_BODY,
      EXTERNAL_FIELD,
      EXTERNAL_GETTER_WITH_BODY,
      EXTERNAL_METHOD_WITH_BODY,
      EXTERNAL_OPERATOR_WITH_BODY,
      EXTERNAL_SETTER_WITH_BODY,
      EXTERNAL_TYPEDEF,
      FACTORY_TOP_LEVEL_DECLARATION,
      FACTORY_WITHOUT_BODY,
      FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR,
      FINAL_AND_VAR,
      FINAL_CLASS,
      FINAL_CONSTRUCTOR,
      FINAL_METHOD,
      FINAL_TYPEDEF,
      FUNCTION_TYPED_PARAMETER_VAR,
      GETTER_IN_FUNCTION,
      GETTER_WITH_PARAMETERS,
      ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE,
      IMPLEMENTS_BEFORE_EXTENDS,
      IMPLEMENTS_BEFORE_WITH,
      IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE,
      INITIALIZED_VARIABLE_IN_FOR_EACH,
      INVALID_CODE_POINT,
      INVALID_COMMENT_REFERENCE,
      INVALID_HEX_ESCAPE,
      INVALID_OPERATOR,
      INVALID_OPERATOR_FOR_SUPER,
      INVALID_UNICODE_ESCAPE,
      LIBRARY_DIRECTIVE_NOT_FIRST,
      LOCAL_FUNCTION_DECLARATION_MODIFIER,
      MISSING_ASSIGNABLE_SELECTOR,
      MISSING_CATCH_OR_FINALLY,
      MISSING_CLASS_BODY,
      MISSING_CLOSING_PARENTHESIS,
      MISSING_CONST_FINAL_VAR_OR_TYPE,
      MISSING_EXPRESSION_IN_THROW,
      MISSING_FUNCTION_BODY,
      MISSING_FUNCTION_PARAMETERS,
      MISSING_IDENTIFIER,
      MISSING_KEYWORD_OPERATOR,
      MISSING_NAME_IN_LIBRARY_DIRECTIVE,
      MISSING_NAME_IN_PART_OF_DIRECTIVE,
      MISSING_STATEMENT,
      MISSING_TERMINATOR_FOR_PARAMETER_GROUP,
      MISSING_TYPEDEF_PARAMETERS,
      MISSING_VARIABLE_IN_FOR_EACH,
      MIXED_PARAMETER_GROUPS,
      MULTIPLE_EXTENDS_CLAUSES,
      MULTIPLE_IMPLEMENTS_CLAUSES,
      MULTIPLE_LIBRARY_DIRECTIVES,
      MULTIPLE_NAMED_PARAMETER_GROUPS,
      MULTIPLE_PART_OF_DIRECTIVES,
      MULTIPLE_POSITIONAL_PARAMETER_GROUPS,
      MULTIPLE_VARIABLES_IN_FOR_EACH,
      MULTIPLE_WITH_CLAUSES,
      NAMED_FUNCTION_EXPRESSION,
      NAMED_PARAMETER_OUTSIDE_GROUP,
      NATIVE_CLAUSE_IN_NON_SDK_CODE,
      NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE,
      NON_CONSTRUCTOR_FACTORY,
      NON_IDENTIFIER_LIBRARY_NAME,
      NON_PART_OF_DIRECTIVE_IN_PART,
      NON_USER_DEFINABLE_OPERATOR,
      NORMAL_BEFORE_OPTIONAL_PARAMETERS,
      POSITIONAL_AFTER_NAMED_ARGUMENT,
      POSITIONAL_PARAMETER_OUTSIDE_GROUP,
      REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR,
      SETTER_IN_FUNCTION,
      STATIC_AFTER_CONST,
      STATIC_AFTER_FINAL,
      STATIC_AFTER_VAR,
      STATIC_CONSTRUCTOR,
      STATIC_GETTER_WITHOUT_BODY,
      STATIC_OPERATOR,
      STATIC_SETTER_WITHOUT_BODY,
      STATIC_TOP_LEVEL_DECLARATION,
      SWITCH_HAS_CASE_AFTER_DEFAULT_CASE,
      SWITCH_HAS_MULTIPLE_DEFAULT_CASES,
      TOP_LEVEL_OPERATOR,
      UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP,
      UNEXPECTED_TOKEN,
      WITH_BEFORE_EXTENDS,
      WITH_WITHOUT_EXTENDS,
      WRONG_SEPARATOR_FOR_NAMED_PARAMETER,
      WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER,
      WRONG_TERMINATOR_FOR_PARAMETER_GROUP,
      VAR_AND_TYPE,
      VAR_AS_TYPE_NAME,
      VAR_CLASS,
      VAR_RETURN_TYPE,
      VAR_TYPEDEF,
      VOID_PARAMETER,
      VOID_VARIABLE];

  /**
   * The severity of this error.
   */
  ErrorSeverity _severity;

  /**
   * The template used to create the message to be displayed for this error.
   */
  String _message;

  /**
   * The template used to create the correction to be displayed for this error, or `null` if
   * there is no correction information for this error.
   */
  String correction8;

  /**
   * Initialize a newly created error code to have the given severity and message.
   *
   * @param severity the severity of the error
   * @param message the message template used to create the message to be displayed for the error
   */
  ParserErrorCode.con1(String name, int ordinal, ErrorSeverity severity, String message) : super(name, ordinal) {
    this._severity = severity;
    this._message = message;
  }

  /**
   * Initialize a newly created error code to have the given severity, message and correction.
   *
   * @param severity the severity of the error
   * @param message the template used to create the message to be displayed for the error
   * @param correction the template used to create the correction to be displayed for the error
   */
  ParserErrorCode.con2(String name, int ordinal, ErrorSeverity severity, String message, String correction) : super(name, ordinal) {
    this._severity = severity;
    this._message = message;
    this.correction8 = correction;
  }

  /**
   * Initialize a newly created error code to have the given message and a severity of ERROR.
   *
   * @param message the message template used to create the message to be displayed for the error
   */
  ParserErrorCode.con3(String name, int ordinal, String message) : this.con1(name, ordinal, ErrorSeverity.ERROR, message);
  String get correction => correction8;
  ErrorSeverity get errorSeverity => _severity;
  String get message => _message;
  ErrorType get type => ErrorType.SYNTACTIC_ERROR;
}
/**
 * Instances of the class {link ToFormattedSourceVisitor} write a source representation of a visited
 * AST node (and all of it's children) to a writer.
 */
class ToFormattedSourceVisitor implements ASTVisitor<Object> {

  /**
   * The writer to which the source is to be written.
   */
  PrintWriter _writer;
  int _indentLevel = 0;
  String _indentString = "";

  /**
   * Initialize a newly created visitor to write source code representing the visited nodes to the
   * given writer.
   *
   * @param writer the writer to which the source is to be written
   */
  ToFormattedSourceVisitor(PrintWriter writer) {
    this._writer = writer;
  }
  Object visitAdjacentStrings(AdjacentStrings node) {
    visitList5(node.strings, " ");
    return null;
  }
  Object visitAnnotation(Annotation node) {
    _writer.print('@');
    visit(node.name);
    visit7(".", node.constructorName);
    visit(node.arguments);
    return null;
  }
  Object visitArgumentDefinitionTest(ArgumentDefinitionTest node) {
    _writer.print('?');
    visit(node.identifier);
    return null;
  }
  Object visitArgumentList(ArgumentList node) {
    _writer.print('(');
    visitList5(node.arguments, ", ");
    _writer.print(')');
    return null;
  }
  Object visitAsExpression(AsExpression node) {
    visit(node.expression);
    _writer.print(" as ");
    visit(node.type);
    return null;
  }
  Object visitAssertStatement(AssertStatement node) {
    _writer.print("assert(");
    visit(node.condition);
    _writer.print(");");
    return null;
  }
  Object visitAssignmentExpression(AssignmentExpression node) {
    visit(node.leftHandSide);
    _writer.print(' ');
    _writer.print(node.operator.lexeme);
    _writer.print(' ');
    visit(node.rightHandSide);
    return null;
  }
  Object visitBinaryExpression(BinaryExpression node) {
    visit(node.leftOperand);
    _writer.print(' ');
    _writer.print(node.operator.lexeme);
    _writer.print(' ');
    visit(node.rightOperand);
    return null;
  }
  Object visitBlock(Block node) {
    _writer.print('{');
    {
      indentInc();
      visitList5(node.statements, "\n");
      indentDec();
    }
    nl2();
    _writer.print('}');
    return null;
  }
  Object visitBlockFunctionBody(BlockFunctionBody node) {
    visit(node.block);
    return null;
  }
  Object visitBooleanLiteral(BooleanLiteral node) {
    _writer.print(node.literal.lexeme);
    return null;
  }
  Object visitBreakStatement(BreakStatement node) {
    _writer.print("break");
    visit7(" ", node.label);
    _writer.print(";");
    return null;
  }
  Object visitCascadeExpression(CascadeExpression node) {
    visit(node.target);
    visitList(node.cascadeSections);
    return null;
  }
  Object visitCatchClause(CatchClause node) {
    visit7("on ", node.exceptionType);
    if (node.catchKeyword != null) {
      if (node.exceptionType != null) {
        _writer.print(' ');
      }
      _writer.print("catch (");
      visit(node.exceptionParameter);
      visit7(", ", node.stackTraceParameter);
      _writer.print(") ");
    } else {
      _writer.print(" ");
    }
    visit(node.body);
    return null;
  }
  Object visitClassDeclaration(ClassDeclaration node) {
    visit(node.documentationComment);
    visit8(node.abstractKeyword, " ");
    _writer.print("class ");
    visit(node.name);
    visit(node.typeParameters);
    visit7(" ", node.extendsClause);
    visit7(" ", node.withClause);
    visit7(" ", node.implementsClause);
    _writer.print(" {");
    {
      indentInc();
      visitList5(node.members, "\n");
      indentDec();
    }
    nl2();
    _writer.print("}");
    return null;
  }
  Object visitClassTypeAlias(ClassTypeAlias node) {
    _writer.print("typedef ");
    visit(node.name);
    visit(node.typeParameters);
    _writer.print(" = ");
    if (node.abstractKeyword != null) {
      _writer.print("abstract ");
    }
    visit(node.superclass);
    visit7(" ", node.withClause);
    visit7(" ", node.implementsClause);
    _writer.print(";");
    return null;
  }
  Object visitComment(Comment node) {
    Token token = node.beginToken;
    while (token != null) {
      bool firstLine = true;
      for (String line in StringUtils.split(token.lexeme, "\n")) {
        if (firstLine) {
          firstLine = false;
          if (node.isDocumentation) {
            nl2();
          }
        } else {
          line = " ${line.trim()}";
          line = StringUtils.replace(line, "/*", "/ *");
        }
        _writer.print(line);
        nl2();
      }
      if (identical(token, node.endToken)) {
        break;
      }
    }
    return null;
  }
  Object visitCommentReference(CommentReference node) => null;
  Object visitCompilationUnit(CompilationUnit node) {
    ScriptTag scriptTag = node.scriptTag;
    NodeList<Directive> directives = node.directives;
    visit(scriptTag);
    String prefix = scriptTag == null ? "" : " ";
    visitList7(prefix, directives, "\n");
    prefix = scriptTag == null && directives.isEmpty ? "" : "\n\n";
    visitList7(prefix, node.declarations, "\n");
    return null;
  }
  Object visitConditionalExpression(ConditionalExpression node) {
    visit(node.condition);
    _writer.print(" ? ");
    visit(node.thenExpression);
    _writer.print(" : ");
    visit(node.elseExpression);
    return null;
  }
  Object visitConstructorDeclaration(ConstructorDeclaration node) {
    visit(node.documentationComment);
    visit8(node.externalKeyword, " ");
    visit8(node.constKeyword, " ");
    visit8(node.factoryKeyword, " ");
    visit(node.returnType);
    visit7(".", node.name);
    visit(node.parameters);
    visitList7(" : ", node.initializers, ", ");
    visit7(" = ", node.redirectedConstructor);
    if (node.body is! EmptyFunctionBody) {
      _writer.print(' ');
    }
    visit(node.body);
    return null;
  }
  Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
    visit8(node.keyword, ".");
    visit(node.fieldName);
    _writer.print(" = ");
    visit(node.expression);
    return null;
  }
  Object visitConstructorName(ConstructorName node) {
    visit(node.type);
    visit7(".", node.name);
    return null;
  }
  Object visitContinueStatement(ContinueStatement node) {
    _writer.print("continue");
    visit7(" ", node.label);
    _writer.print(";");
    return null;
  }
  Object visitDeclaredIdentifier(DeclaredIdentifier node) {
    visit8(node.keyword, " ");
    visit6(node.type, " ");
    visit(node.identifier);
    return null;
  }
  Object visitDefaultFormalParameter(DefaultFormalParameter node) {
    visit(node.parameter);
    if (node.separator != null) {
      _writer.print(" ");
      _writer.print(node.separator.lexeme);
      visit7(" ", node.defaultValue);
    }
    return null;
  }
  Object visitDoStatement(DoStatement node) {
    _writer.print("do ");
    visit(node.body);
    _writer.print(" while (");
    visit(node.condition);
    _writer.print(");");
    return null;
  }
  Object visitDoubleLiteral(DoubleLiteral node) {
    _writer.print(node.literal.lexeme);
    return null;
  }
  Object visitEmptyFunctionBody(EmptyFunctionBody node) {
    _writer.print(';');
    return null;
  }
  Object visitEmptyStatement(EmptyStatement node) {
    _writer.print(';');
    return null;
  }
  Object visitExportDirective(ExportDirective node) {
    _writer.print("export ");
    visit(node.uri);
    visitList7(" ", node.combinators, " ");
    _writer.print(';');
    return null;
  }
  Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
    _writer.print("=> ");
    visit(node.expression);
    if (node.semicolon != null) {
      _writer.print(';');
    }
    return null;
  }
  Object visitExpressionStatement(ExpressionStatement node) {
    visit(node.expression);
    _writer.print(';');
    return null;
  }
  Object visitExtendsClause(ExtendsClause node) {
    _writer.print("extends ");
    visit(node.superclass);
    return null;
  }
  Object visitFieldDeclaration(FieldDeclaration node) {
    visit(node.documentationComment);
    visit8(node.staticKeyword, " ");
    visit(node.fields);
    _writer.print(";");
    return null;
  }
  Object visitFieldFormalParameter(FieldFormalParameter node) {
    visit8(node.keyword, " ");
    visit6(node.type, " ");
    _writer.print("this.");
    visit(node.identifier);
    visit(node.parameters);
    return null;
  }
  Object visitForEachStatement(ForEachStatement node) {
    DeclaredIdentifier loopVariable = node.loopVariable;
    _writer.print("for (");
    if (loopVariable == null) {
      visit(node.identifier);
    } else {
      visit(loopVariable);
    }
    _writer.print(" in ");
    visit(node.iterator);
    _writer.print(") ");
    visit(node.body);
    return null;
  }
  Object visitFormalParameterList(FormalParameterList node) {
    String groupEnd = null;
    _writer.print('(');
    NodeList<FormalParameter> parameters = node.parameters;
    int size = parameters.length;
    for (int i = 0; i < size; i++) {
      FormalParameter parameter = parameters[i];
      if (i > 0) {
        _writer.print(", ");
      }
      if (groupEnd == null && parameter is DefaultFormalParameter) {
        if (identical(parameter.kind, ParameterKind.NAMED)) {
          groupEnd = "}";
          _writer.print('{');
        } else {
          groupEnd = "]";
          _writer.print('[');
        }
      }
      parameter.accept(this);
    }
    if (groupEnd != null) {
      _writer.print(groupEnd);
    }
    _writer.print(')');
    return null;
  }
  Object visitForStatement(ForStatement node) {
    Expression initialization = node.initialization;
    _writer.print("for (");
    if (initialization != null) {
      visit(initialization);
    } else {
      visit(node.variables);
    }
    _writer.print(";");
    visit7(" ", node.condition);
    _writer.print(";");
    visitList7(" ", node.updaters, ", ");
    _writer.print(") ");
    visit(node.body);
    return null;
  }
  Object visitFunctionDeclaration(FunctionDeclaration node) {
    visit6(node.returnType, " ");
    visit8(node.propertyKeyword, " ");
    visit(node.name);
    visit(node.functionExpression);
    return null;
  }
  Object visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
    visit(node.functionDeclaration);
    _writer.print(';');
    return null;
  }
  Object visitFunctionExpression(FunctionExpression node) {
    visit(node.parameters);
    _writer.print(' ');
    visit(node.body);
    return null;
  }
  Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
    visit(node.function);
    visit(node.argumentList);
    return null;
  }
  Object visitFunctionTypeAlias(FunctionTypeAlias node) {
    _writer.print("typedef ");
    visit6(node.returnType, " ");
    visit(node.name);
    visit(node.typeParameters);
    visit(node.parameters);
    _writer.print(";");
    return null;
  }
  Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
    visit6(node.returnType, " ");
    visit(node.identifier);
    visit(node.parameters);
    return null;
  }
  Object visitHideCombinator(HideCombinator node) {
    _writer.print("hide ");
    visitList5(node.hiddenNames, ", ");
    return null;
  }
  Object visitIfStatement(IfStatement node) {
    _writer.print("if (");
    visit(node.condition);
    _writer.print(") ");
    visit(node.thenStatement);
    visit7(" else ", node.elseStatement);
    return null;
  }
  Object visitImplementsClause(ImplementsClause node) {
    _writer.print("implements ");
    visitList5(node.interfaces, ", ");
    return null;
  }
  Object visitImportDirective(ImportDirective node) {
    _writer.print("import ");
    visit(node.uri);
    visit7(" as ", node.prefix);
    visitList7(" ", node.combinators, " ");
    _writer.print(';');
    return null;
  }
  Object visitIndexExpression(IndexExpression node) {
    if (node.isCascaded) {
      _writer.print("..");
    } else {
      visit(node.target);
    }
    _writer.print('[');
    visit(node.index);
    _writer.print(']');
    return null;
  }
  Object visitInstanceCreationExpression(InstanceCreationExpression node) {
    visit8(node.keyword, " ");
    visit(node.constructorName);
    visit(node.argumentList);
    return null;
  }
  Object visitIntegerLiteral(IntegerLiteral node) {
    _writer.print(node.literal.lexeme);
    return null;
  }
  Object visitInterpolationExpression(InterpolationExpression node) {
    if (node.rightBracket != null) {
      _writer.print("\${");
      visit(node.expression);
      _writer.print("}");
    } else {
      _writer.print("\$");
      visit(node.expression);
    }
    return null;
  }
  Object visitInterpolationString(InterpolationString node) {
    _writer.print(node.contents.lexeme);
    return null;
  }
  Object visitIsExpression(IsExpression node) {
    visit(node.expression);
    if (node.notOperator == null) {
      _writer.print(" is ");
    } else {
      _writer.print(" is! ");
    }
    visit(node.type);
    return null;
  }
  Object visitLabel(Label node) {
    visit(node.label);
    _writer.print(":");
    return null;
  }
  Object visitLabeledStatement(LabeledStatement node) {
    visitList6(node.labels, " ", " ");
    visit(node.statement);
    return null;
  }
  Object visitLibraryDirective(LibraryDirective node) {
    _writer.print("library ");
    visit(node.name);
    _writer.print(';');
    nl();
    return null;
  }
  Object visitLibraryIdentifier(LibraryIdentifier node) {
    _writer.print(node.name);
    return null;
  }
  Object visitListLiteral(ListLiteral node) {
    if (node.constKeyword != null) {
      _writer.print(node.constKeyword.lexeme);
      _writer.print(' ');
    }
    visit6(node.typeArguments, " ");
    _writer.print("[");
    {
      NodeList<Expression> elements = node.elements;
      if (elements.length < 2 || elements.toString().length < 60) {
        visitList5(elements, ", ");
      } else {
        String elementIndent = "${_indentString}    ";
        _writer.print("\n");
        _writer.print(elementIndent);
        visitList5(elements, ",\n${elementIndent}");
      }
    }
    _writer.print("]");
    return null;
  }
  Object visitMapLiteral(MapLiteral node) {
    if (node.constKeyword != null) {
      _writer.print(node.constKeyword.lexeme);
      _writer.print(' ');
    }
    visit6(node.typeArguments, " ");
    _writer.print("{");
    visitList5(node.entries, ", ");
    _writer.print("}");
    return null;
  }
  Object visitMapLiteralEntry(MapLiteralEntry node) {
    visit(node.key);
    _writer.print(" : ");
    visit(node.value);
    return null;
  }
  Object visitMethodDeclaration(MethodDeclaration node) {
    visit(node.documentationComment);
    visit8(node.externalKeyword, " ");
    visit8(node.modifierKeyword, " ");
    visit6(node.returnType, " ");
    visit8(node.propertyKeyword, " ");
    visit8(node.operatorKeyword, " ");
    visit(node.name);
    if (!node.isGetter) {
      visit(node.parameters);
    }
    if (node.body is! EmptyFunctionBody) {
      _writer.print(' ');
    }
    visit(node.body);
    return null;
  }
  Object visitMethodInvocation(MethodInvocation node) {
    if (node.isCascaded) {
      _writer.print("..");
    } else {
      visit6(node.target, ".");
    }
    visit(node.methodName);
    visit(node.argumentList);
    return null;
  }
  Object visitNamedExpression(NamedExpression node) {
    visit(node.name);
    visit7(" ", node.expression);
    return null;
  }
  Object visitNativeClause(NativeClause node) {
    _writer.print("native ");
    visit(node.name);
    return null;
  }
  Object visitNativeFunctionBody(NativeFunctionBody node) {
    _writer.print("native ");
    visit(node.stringLiteral);
    _writer.print(';');
    return null;
  }
  Object visitNullLiteral(NullLiteral node) {
    _writer.print("null");
    return null;
  }
  Object visitParenthesizedExpression(ParenthesizedExpression node) {
    _writer.print('(');
    visit(node.expression);
    _writer.print(')');
    return null;
  }
  Object visitPartDirective(PartDirective node) {
    _writer.print("part ");
    visit(node.uri);
    _writer.print(';');
    return null;
  }
  Object visitPartOfDirective(PartOfDirective node) {
    _writer.print("part of ");
    visit(node.libraryName);
    _writer.print(';');
    return null;
  }
  Object visitPostfixExpression(PostfixExpression node) {
    visit(node.operand);
    _writer.print(node.operator.lexeme);
    return null;
  }
  Object visitPrefixedIdentifier(PrefixedIdentifier node) {
    visit(node.prefix);
    _writer.print('.');
    visit(node.identifier);
    return null;
  }
  Object visitPrefixExpression(PrefixExpression node) {
    _writer.print(node.operator.lexeme);
    visit(node.operand);
    return null;
  }
  Object visitPropertyAccess(PropertyAccess node) {
    if (node.isCascaded) {
      _writer.print("..");
    } else {
      visit6(node.target, ".");
    }
    visit(node.propertyName);
    return null;
  }
  Object visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
    _writer.print("this");
    visit7(".", node.constructorName);
    visit(node.argumentList);
    return null;
  }
  Object visitRethrowExpression(RethrowExpression node) {
    _writer.print("rethrow");
    return null;
  }
  Object visitReturnStatement(ReturnStatement node) {
    Expression expression = node.expression;
    if (expression == null) {
      _writer.print("return;");
    } else {
      _writer.print("return ");
      expression.accept(this);
      _writer.print(";");
    }
    return null;
  }
  Object visitScriptTag(ScriptTag node) {
    _writer.print(node.scriptTag.lexeme);
    return null;
  }
  Object visitShowCombinator(ShowCombinator node) {
    _writer.print("show ");
    visitList5(node.shownNames, ", ");
    return null;
  }
  Object visitSimpleFormalParameter(SimpleFormalParameter node) {
    visit8(node.keyword, " ");
    visit6(node.type, " ");
    visit(node.identifier);
    return null;
  }
  Object visitSimpleIdentifier(SimpleIdentifier node) {
    _writer.print(node.token.lexeme);
    return null;
  }
  Object visitSimpleStringLiteral(SimpleStringLiteral node) {
    _writer.print(node.literal.lexeme);
    return null;
  }
  Object visitStringInterpolation(StringInterpolation node) {
    visitList(node.elements);
    return null;
  }
  Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
    _writer.print("super");
    visit7(".", node.constructorName);
    visit(node.argumentList);
    return null;
  }
  Object visitSuperExpression(SuperExpression node) {
    _writer.print("super");
    return null;
  }
  Object visitSwitchCase(SwitchCase node) {
    visitList6(node.labels, " ", " ");
    _writer.print("case ");
    visit(node.expression);
    _writer.print(": ");
    {
      indentInc();
      visitList5(node.statements, "\n");
      indentDec();
    }
    return null;
  }
  Object visitSwitchDefault(SwitchDefault node) {
    visitList6(node.labels, " ", " ");
    _writer.print("default: ");
    {
      indentInc();
      visitList5(node.statements, "\n");
      indentDec();
    }
    return null;
  }
  Object visitSwitchStatement(SwitchStatement node) {
    _writer.print("switch (");
    visit(node.expression);
    _writer.print(") {");
    {
      indentInc();
      visitList5(node.members, "\n");
      indentDec();
    }
    nl2();
    _writer.print('}');
    return null;
  }
  Object visitSymbolLiteral(SymbolLiteral node) {
    _writer.print("#");
    visitList8(node.components, ".");
    return null;
  }
  Object visitThisExpression(ThisExpression node) {
    _writer.print("this");
    return null;
  }
  Object visitThrowExpression(ThrowExpression node) {
    _writer.print("throw ");
    visit(node.expression);
    return null;
  }
  Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
    visit6(node.variables, ";");
    return null;
  }
  Object visitTryStatement(TryStatement node) {
    _writer.print("try ");
    visit(node.body);
    visitList7(" ", node.catchClauses, " ");
    visit7(" finally ", node.finallyBlock);
    return null;
  }
  Object visitTypeArgumentList(TypeArgumentList node) {
    _writer.print('<');
    visitList5(node.arguments, ", ");
    _writer.print('>');
    return null;
  }
  Object visitTypeName(TypeName node) {
    visit(node.name);
    visit(node.typeArguments);
    return null;
  }
  Object visitTypeParameter(TypeParameter node) {
    visit(node.name);
    visit7(" extends ", node.bound);
    return null;
  }
  Object visitTypeParameterList(TypeParameterList node) {
    _writer.print('<');
    visitList5(node.typeParameters, ", ");
    _writer.print('>');
    return null;
  }
  Object visitVariableDeclaration(VariableDeclaration node) {
    visit(node.name);
    visit7(" = ", node.initializer);
    return null;
  }
  Object visitVariableDeclarationList(VariableDeclarationList node) {
    visit8(node.keyword, " ");
    visit6(node.type, " ");
    visitList5(node.variables, ", ");
    return null;
  }
  Object visitVariableDeclarationStatement(VariableDeclarationStatement node) {
    visit(node.variables);
    _writer.print(";");
    return null;
  }
  Object visitWhileStatement(WhileStatement node) {
    _writer.print("while (");
    visit(node.condition);
    _writer.print(") ");
    visit(node.body);
    return null;
  }
  Object visitWithClause(WithClause node) {
    _writer.print("with ");
    visitList5(node.mixinTypes, ", ");
    return null;
  }
  void indent() {
    _writer.print(_indentString);
  }
  void indentDec() {
    _indentLevel -= 2;
    _indentString = StringUtils.repeat(" ", _indentLevel);
  }
  void indentInc() {
    _indentLevel += 2;
    _indentString = StringUtils.repeat(" ", _indentLevel);
  }
  void nl() {
    _writer.print("\n");
  }
  void nl2() {
    nl();
    indent();
  }

  /**
   * Safely visit the given node.
   *
   * @param node the node to be visited
   */
  void visit(ASTNode node) {
    if (node != null) {
      node.accept(this);
    }
  }

  /**
   * Safely visit the given node, printing the suffix after the node if it is non-<code>null</code>.
   *
   * @param suffix the suffix to be printed if there is a node to visit
   * @param node the node to be visited
   */
  void visit6(ASTNode node, String suffix) {
    if (node != null) {
      node.accept(this);
      _writer.print(suffix);
    }
  }

  /**
   * Safely visit the given node, printing the prefix before the node if it is non-<code>null</code>
   * .
   *
   * @param prefix the prefix to be printed if there is a node to visit
   * @param node the node to be visited
   */
  void visit7(String prefix, ASTNode node) {
    if (node != null) {
      _writer.print(prefix);
      node.accept(this);
    }
  }

  /**
   * Safely visit the given node, printing the suffix after the node if it is non-<code>null</code>.
   *
   * @param suffix the suffix to be printed if there is a node to visit
   * @param node the node to be visited
   */
  void visit8(Token token, String suffix) {
    if (token != null) {
      _writer.print(token.lexeme);
      _writer.print(suffix);
    }
  }

  /**
   * Print a list of nodes without any separation.
   *
   * @param nodes the nodes to be printed
   * @param separator the separator to be printed between adjacent nodes
   */
  void visitList(NodeList<ASTNode> nodes) {
    visitList5(nodes, "");
  }

  /**
   * Print a list of nodes, separated by the given separator.
   *
   * @param nodes the nodes to be printed
   * @param separator the separator to be printed between adjacent nodes
   */
  void visitList5(NodeList<ASTNode> nodes, String separator) {
    if (nodes != null) {
      int size = nodes.length;
      for (int i = 0; i < size; i++) {
        if ("\n" == separator) {
          _writer.print("\n");
          indent();
        } else if (i > 0) {
          _writer.print(separator);
        }
        nodes[i].accept(this);
      }
    }
  }

  /**
   * Print a list of nodes, separated by the given separator.
   *
   * @param nodes the nodes to be printed
   * @param separator the separator to be printed between adjacent nodes
   * @param suffix the suffix to be printed if the list is not empty
   */
  void visitList6(NodeList<ASTNode> nodes, String separator, String suffix) {
    if (nodes != null) {
      int size = nodes.length;
      if (size > 0) {
        for (int i = 0; i < size; i++) {
          if (i > 0) {
            _writer.print(separator);
          }
          nodes[i].accept(this);
        }
        _writer.print(suffix);
      }
    }
  }

  /**
   * Print a list of nodes, separated by the given separator.
   *
   * @param prefix the prefix to be printed if the list is not empty
   * @param nodes the nodes to be printed
   * @param separator the separator to be printed between adjacent nodes
   */
  void visitList7(String prefix, NodeList<ASTNode> nodes, String separator) {
    if (nodes != null) {
      int size = nodes.length;
      if (size > 0) {
        _writer.print(prefix);
        for (int i = 0; i < size; i++) {
          if (i > 0) {
            _writer.print(separator);
          }
          nodes[i].accept(this);
        }
      }
    }
  }

  /**
   * Print a list of tokens, separated by the given separator.
   *
   * @param tokens the tokens to be printed
   * @param separator the separator to be printed between adjacent tokens
   */
  void visitList8(List<Token> tokens, String separator) {
    int size = tokens.length;
    for (int i = 0; i < size; i++) {
      if ("\n" == separator) {
        _writer.print("\n");
        indent();
      } else if (i > 0) {
        _writer.print(separator);
      }
      _writer.print(tokens[i].lexeme);
    }
  }
}