// 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.scanner;
import 'dart:collection';
import 'java_core.dart';
import 'java_engine.dart';
import 'source.dart';
import 'error.dart';
import 'instrumentation.dart';
import 'utilities_collection.dart' show TokenMap;
/**
 * Instances of the abstract class `KeywordState` represent a state in a state machine used to
 * scan keywords.
 *
 * @coverage dart.engine.parser
 */
class KeywordState {

  /**
   * An empty transition table used by leaf states.
   */
  static List<KeywordState> _EMPTY_TABLE = new List<KeywordState>(26);

  /**
   * The initial state in the state machine.
   */
  static KeywordState KEYWORD_STATE = createKeywordStateTable();

  /**
   * Create the next state in the state machine where we have already recognized the subset of
   * strings in the given array of strings starting at the given offset and having the given length.
   * All of these strings have a common prefix and the next character is at the given start index.
   *
   * @param start the index of the character in the strings used to transition to a new state
   * @param strings an array containing all of the strings that will be recognized by the state
   *          machine
   * @param offset the offset of the first string in the array that has the prefix that is assumed
   *          to have been recognized by the time we reach the state being built
   * @param length the number of strings in the array that pass through the state being built
   * @return the state that was created
   */
  static KeywordState computeKeywordStateTable(int start, List<String> strings, int offset, int length) {
    List<KeywordState> result = new List<KeywordState>(26);
    assert(length != 0);
    int chunk = 0x0;
    int chunkStart = -1;
    bool isLeaf = false;
    for (int i = offset; i < offset + length; i++) {
      if (strings[i].length == start) {
        isLeaf = true;
      }
      if (strings[i].length > start) {
        int c = strings[i].codeUnitAt(start);
        if (chunk != c) {
          if (chunkStart != -1) {
            result[chunk - 0x61] = computeKeywordStateTable(start + 1, strings, chunkStart, i - chunkStart);
          }
          chunkStart = i;
          chunk = c;
        }
      }
    }
    if (chunkStart != -1) {
      assert(result[chunk - 0x61] == null);
      result[chunk - 0x61] = computeKeywordStateTable(start + 1, strings, chunkStart, offset + length - chunkStart);
    } else {
      assert(length == 1);
      return new KeywordState(_EMPTY_TABLE, strings[offset]);
    }
    if (isLeaf) {
      return new KeywordState(result, strings[offset]);
    } else {
      return new KeywordState(result, null);
    }
  }

  /**
   * Create the initial state in the state machine.
   *
   * @return the state that was created
   */
  static KeywordState createKeywordStateTable() {
    List<Keyword> values = Keyword.values;
    List<String> strings = new List<String>(values.length);
    for (int i = 0; i < values.length; i++) {
      strings[i] = values[i].syntax;
    }
    strings.sort();
    return computeKeywordStateTable(0, strings, 0, strings.length);
  }

  /**
   * A table mapping characters to the states to which those characters will transition. (The index
   * into the array is the offset from the character `'a'` to the transitioning character.)
   */
  List<KeywordState> _table;

  /**
   * The keyword that is recognized by this state, or `null` if this state is not a terminal
   * state.
   */
  Keyword _keyword2;

  /**
   * Initialize a newly created state to have the given transitions and to recognize the keyword
   * with the given syntax.
   *
   * @param table a table mapping characters to the states to which those characters will transition
   * @param syntax the syntax of the keyword that is recognized by the state
   */
  KeywordState(List<KeywordState> table, String syntax) {
    this._table = table;
    this._keyword2 = (syntax == null) ? null : Keyword.keywords[syntax];
  }

  /**
   * Return the keyword that was recognized by this state, or `null` if this state does not
   * recognized a keyword.
   *
   * @return the keyword that was matched by reaching this state
   */
  Keyword keyword() => _keyword2;

  /**
   * Return the state that follows this state on a transition of the given character, or
   * `null` if there is no valid state reachable from this state with such a transition.
   *
   * @param c the character used to transition from this state to another state
   * @return the state that follows this state on a transition of the given character
   */
  KeywordState next(int c) => _table[c - 0x61];
}
/**
 * The enumeration `ScannerErrorCode` defines the error codes used for errors detected by the
 * scanner.
 *
 * @coverage dart.engine.parser
 */
class ScannerErrorCode extends Enum<ScannerErrorCode> implements ErrorCode {
  static final ScannerErrorCode ILLEGAL_CHARACTER = new ScannerErrorCode.con1('ILLEGAL_CHARACTER', 0, "Illegal character %x");
  static final ScannerErrorCode MISSING_DIGIT = new ScannerErrorCode.con1('MISSING_DIGIT', 1, "Decimal digit expected");
  static final ScannerErrorCode MISSING_HEX_DIGIT = new ScannerErrorCode.con1('MISSING_HEX_DIGIT', 2, "Hexidecimal digit expected");
  static final ScannerErrorCode MISSING_QUOTE = new ScannerErrorCode.con1('MISSING_QUOTE', 3, "Expected quote (' or \")");
  static final ScannerErrorCode UNTERMINATED_MULTI_LINE_COMMENT = new ScannerErrorCode.con1('UNTERMINATED_MULTI_LINE_COMMENT', 4, "Unterminated multi-line comment");
  static final ScannerErrorCode UNTERMINATED_STRING_LITERAL = new ScannerErrorCode.con1('UNTERMINATED_STRING_LITERAL', 5, "Unterminated string literal");
  static final List<ScannerErrorCode> values = [
      ILLEGAL_CHARACTER,
      MISSING_DIGIT,
      MISSING_HEX_DIGIT,
      MISSING_QUOTE,
      UNTERMINATED_MULTI_LINE_COMMENT,
      UNTERMINATED_STRING_LITERAL];

  /**
   * 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 correction10;

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

  /**
   * Initialize a newly created error code to have the given message and correction.
   *
   * @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
   */
  ScannerErrorCode.con2(String name, int ordinal, String message, String correction) : super(name, ordinal) {
    this._message = message;
    this.correction10 = correction;
  }
  String get correction => correction10;
  ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;
  String get message => _message;
  ErrorType get type => ErrorType.SYNTACTIC_ERROR;
}
/**
 * Instances of the class `SubSequenceReader` implement a [CharacterReader] that reads
 * characters from a character sequence, but adds a delta when reporting the current character
 * offset so that the character sequence can be a subsequence from a larger sequence.
 */
class SubSequenceReader extends CharSequenceReader {

  /**
   * The offset from the beginning of the file to the beginning of the source being scanned.
   */
  int _offsetDelta = 0;

  /**
   * Initialize a newly created reader to read the characters in the given sequence.
   *
   * @param sequence the sequence from which characters will be read
   * @param offsetDelta the offset from the beginning of the file to the beginning of the source
   *          being scanned
   */
  SubSequenceReader(CharSequence sequence, int offsetDelta) : super(sequence) {
    this._offsetDelta = offsetDelta;
  }
  int get offset => _offsetDelta + super.offset;
  String getString(int start, int endDelta) => super.getString(start - _offsetDelta, endDelta);
  void set offset(int offset) {
    super.offset = offset - _offsetDelta;
  }
}
/**
 * Instances of the class `TokenWithComment` represent a string token that is preceded by
 * comments.
 *
 * @coverage dart.engine.parser
 */
class StringTokenWithComment extends StringToken {

  /**
   * The first comment in the list of comments that precede this token.
   */
  Token _precedingComment;

  /**
   * Initialize a newly created token to have the given type and offset and to be preceded by the
   * comments reachable from the given comment.
   *
   * @param type the type of the token
   * @param offset the offset from the beginning of the file to the first character in the token
   * @param precedingComment the first comment in the list of comments that precede this token
   */
  StringTokenWithComment(TokenType type, String value, int offset, Token precedingComment) : super(type, value, offset) {
    this._precedingComment = precedingComment;
  }
  Token copy() => new StringTokenWithComment(type, lexeme, offset, copyComments(_precedingComment));
  Token get precedingComments => _precedingComment;
  void applyDelta(int delta) {
    super.applyDelta(delta);
    Token token = _precedingComment;
    while (token != null) {
      token.applyDelta(delta);
      token = token.next;
    }
  }
}
/**
 * The enumeration `Keyword` defines the keywords in the Dart programming language.
 *
 * @coverage dart.engine.parser
 */
class Keyword extends Enum<Keyword> {
  static final Keyword ASSERT = new Keyword.con1('ASSERT', 0, "assert");
  static final Keyword BREAK = new Keyword.con1('BREAK', 1, "break");
  static final Keyword CASE = new Keyword.con1('CASE', 2, "case");
  static final Keyword CATCH = new Keyword.con1('CATCH', 3, "catch");
  static final Keyword CLASS = new Keyword.con1('CLASS', 4, "class");
  static final Keyword CONST = new Keyword.con1('CONST', 5, "const");
  static final Keyword CONTINUE = new Keyword.con1('CONTINUE', 6, "continue");
  static final Keyword DEFAULT = new Keyword.con1('DEFAULT', 7, "default");
  static final Keyword DO = new Keyword.con1('DO', 8, "do");
  static final Keyword ELSE = new Keyword.con1('ELSE', 9, "else");
  static final Keyword ENUM = new Keyword.con1('ENUM', 10, "enum");
  static final Keyword EXTENDS = new Keyword.con1('EXTENDS', 11, "extends");
  static final Keyword FALSE = new Keyword.con1('FALSE', 12, "false");
  static final Keyword FINAL = new Keyword.con1('FINAL', 13, "final");
  static final Keyword FINALLY = new Keyword.con1('FINALLY', 14, "finally");
  static final Keyword FOR = new Keyword.con1('FOR', 15, "for");
  static final Keyword IF = new Keyword.con1('IF', 16, "if");
  static final Keyword IN = new Keyword.con1('IN', 17, "in");
  static final Keyword IS = new Keyword.con1('IS', 18, "is");
  static final Keyword NEW = new Keyword.con1('NEW', 19, "new");
  static final Keyword NULL = new Keyword.con1('NULL', 20, "null");
  static final Keyword RETHROW = new Keyword.con1('RETHROW', 21, "rethrow");
  static final Keyword RETURN = new Keyword.con1('RETURN', 22, "return");
  static final Keyword SUPER = new Keyword.con1('SUPER', 23, "super");
  static final Keyword SWITCH = new Keyword.con1('SWITCH', 24, "switch");
  static final Keyword THIS = new Keyword.con1('THIS', 25, "this");
  static final Keyword THROW = new Keyword.con1('THROW', 26, "throw");
  static final Keyword TRUE = new Keyword.con1('TRUE', 27, "true");
  static final Keyword TRY = new Keyword.con1('TRY', 28, "try");
  static final Keyword VAR = new Keyword.con1('VAR', 29, "var");
  static final Keyword VOID = new Keyword.con1('VOID', 30, "void");
  static final Keyword WHILE = new Keyword.con1('WHILE', 31, "while");
  static final Keyword WITH = new Keyword.con1('WITH', 32, "with");
  static final Keyword ABSTRACT = new Keyword.con2('ABSTRACT', 33, "abstract", true);
  static final Keyword AS = new Keyword.con2('AS', 34, "as", true);
  static final Keyword DYNAMIC = new Keyword.con2('DYNAMIC', 35, "dynamic", true);
  static final Keyword EXPORT = new Keyword.con2('EXPORT', 36, "export", true);
  static final Keyword EXTERNAL = new Keyword.con2('EXTERNAL', 37, "external", true);
  static final Keyword FACTORY = new Keyword.con2('FACTORY', 38, "factory", true);
  static final Keyword GET = new Keyword.con2('GET', 39, "get", true);
  static final Keyword IMPLEMENTS = new Keyword.con2('IMPLEMENTS', 40, "implements", true);
  static final Keyword IMPORT = new Keyword.con2('IMPORT', 41, "import", true);
  static final Keyword LIBRARY = new Keyword.con2('LIBRARY', 42, "library", true);
  static final Keyword OPERATOR = new Keyword.con2('OPERATOR', 43, "operator", true);
  static final Keyword PART = new Keyword.con2('PART', 44, "part", true);
  static final Keyword SET = new Keyword.con2('SET', 45, "set", true);
  static final Keyword STATIC = new Keyword.con2('STATIC', 46, "static", true);
  static final Keyword TYPEDEF = new Keyword.con2('TYPEDEF', 47, "typedef", true);
  static final List<Keyword> values = [
      ASSERT,
      BREAK,
      CASE,
      CATCH,
      CLASS,
      CONST,
      CONTINUE,
      DEFAULT,
      DO,
      ELSE,
      ENUM,
      EXTENDS,
      FALSE,
      FINAL,
      FINALLY,
      FOR,
      IF,
      IN,
      IS,
      NEW,
      NULL,
      RETHROW,
      RETURN,
      SUPER,
      SWITCH,
      THIS,
      THROW,
      TRUE,
      TRY,
      VAR,
      VOID,
      WHILE,
      WITH,
      ABSTRACT,
      AS,
      DYNAMIC,
      EXPORT,
      EXTERNAL,
      FACTORY,
      GET,
      IMPLEMENTS,
      IMPORT,
      LIBRARY,
      OPERATOR,
      PART,
      SET,
      STATIC,
      TYPEDEF];

  /**
   * The lexeme for the keyword.
   */
  String syntax;

  /**
   * A flag indicating whether the keyword is a pseudo-keyword. Pseudo keywords can be used as
   * identifiers.
   */
  bool isPseudoKeyword = false;

  /**
   * A table mapping the lexemes of keywords to the corresponding keyword.
   */
  static Map<String, Keyword> keywords = createKeywordMap();

  /**
   * Create a table mapping the lexemes of keywords to the corresponding keyword.
   *
   * @return the table that was created
   */
  static Map<String, Keyword> createKeywordMap() {
    LinkedHashMap<String, Keyword> result = new LinkedHashMap<String, Keyword>();
    for (Keyword keyword in values) {
      result[keyword.syntax] = keyword;
    }
    return result;
  }

  /**
   * Initialize a newly created keyword to have the given syntax. The keyword is not a
   * pseudo-keyword.
   *
   * @param syntax the lexeme for the keyword
   */
  Keyword.con1(String name, int ordinal, String syntax) : this.con2(name, ordinal, syntax, false);

  /**
   * Initialize a newly created keyword to have the given syntax. The keyword is a pseudo-keyword if
   * the given flag is `true`.
   *
   * @param syntax the lexeme for the keyword
   * @param isPseudoKeyword `true` if this keyword is a pseudo-keyword
   */
  Keyword.con2(String name, int ordinal, String syntax, bool isPseudoKeyword) : super(name, ordinal) {
    this.syntax = syntax;
    this.isPseudoKeyword = isPseudoKeyword;
  }
}
/**
 * Instances of the class `CharSequenceReader` implement a [CharacterReader] that reads
 * characters from a character sequence.
 */
class CharSequenceReader implements CharacterReader {

  /**
   * The sequence from which characters will be read.
   */
  CharSequence _sequence;

  /**
   * The number of characters in the string.
   */
  int _stringLength = 0;

  /**
   * The index, relative to the string, of the last character that was read.
   */
  int _charOffset = 0;

  /**
   * Initialize a newly created reader to read the characters in the given sequence.
   *
   * @param sequence the sequence from which characters will be read
   */
  CharSequenceReader(CharSequence sequence) {
    this._sequence = sequence;
    this._stringLength = sequence.length();
    this._charOffset = -1;
  }
  int advance() {
    if (_charOffset + 1 >= _stringLength) {
      return -1;
    }
    return _sequence.charAt(++_charOffset);
  }
  int get offset => _charOffset;
  String getString(int start, int endDelta) => _sequence.subSequence(start, _charOffset + 1 + endDelta).toString();
  int peek() {
    if (_charOffset + 1 >= _sequence.length()) {
      return -1;
    }
    return _sequence.charAt(_charOffset + 1);
  }
  void set offset(int offset) {
    _charOffset = offset;
  }
}
/**
 * Instances of the class `IncrementalScanner` implement a scanner that scans a subset of a
 * string and inserts the resulting tokens into the middle of an existing token stream.
 *
 * @coverage dart.engine.parser
 */
class IncrementalScanner extends Scanner {

  /**
   * The reader used to access the characters in the source.
   */
  CharacterReader _reader;

  /**
   * A map from tokens that were copied to the copies of the tokens.
   */
  final TokenMap tokenMap = new TokenMap();

  /**
   * The first token in the range of tokens that are different from the tokens in the original token
   * stream.
   */
  Token _firstToken;

  /**
   * The last token in the range of tokens that are different from the tokens in the original token
   * stream.
   */
  Token lastToken;

  /**
   * Initialize a newly created scanner.
   *
   * @param source the source being scanned
   * @param reader the character reader used to read the characters in the source
   * @param errorListener the error listener that will be informed of any errors that are found
   */
  IncrementalScanner(Source source, CharacterReader reader, AnalysisErrorListener errorListener) : super(source, reader, errorListener) {
    this._reader = reader;
  }

  /**
   * Return the first token in the range of tokens that are different from the tokens in the
   * original token stream or `null` if the new tokens are the same as the original tokens
   * except for offset.
   *
   * @return the first token in the range of new tokens
   */
  Token get firstToken => _firstToken;

  /**
   * Given the stream of tokens scanned from the original source, the modified source (the result of
   * replacing one contiguous range of characters with another string of characters), and a
   * specification of the modification that was made, return a stream of tokens scanned from the
   * modified source. The original stream of tokens will not be modified.
   *
   * @param originalStream the stream of tokens scanned from the original source
   * @param index the index of the first character in both the original and modified source that was
   *          affected by the modification
   * @param removedLength the number of characters removed from the original source
   * @param insertedLength the number of characters added to the modified source
   */
  Token rescan(Token originalStream, int index, int removedLength, int insertedLength) {
    while (originalStream.type != TokenType.EOF && originalStream.end < index) {
      originalStream = copyAndAdvance(originalStream, 0);
    }
    Token lastCopied = tail;
    int modifiedEnd = index + insertedLength - 1;
    if (originalStream.offset < index) {
      modifiedEnd += originalStream.end - index - removedLength;
    }
    _reader.offset = Math.min(originalStream.offset, index) - 1;
    int next = _reader.advance();
    while (next != -1 && _reader.offset <= modifiedEnd) {
      next = bigSwitch(next);
    }
    _firstToken = lastCopied.next;
    lastToken = tail;
    if (_firstToken == null || identical(_firstToken.type, TokenType.EOF)) {
      _firstToken = null;
      lastToken = null;
    } else if (originalStream.end == index && _firstToken.end == index) {
      tokenMap.put(originalStream, _firstToken);
      if (identical(lastToken, _firstToken)) {
        lastToken = lastToken.next;
      }
      _firstToken = _firstToken.next;
    }
    int removedEnd = index + removedLength - 1 + Math.max(0, tail.end - index - insertedLength);
    while (originalStream.offset <= removedEnd) {
      originalStream = originalStream.next;
    }
    int delta = insertedLength - removedLength;
    while (originalStream.type != TokenType.EOF) {
      originalStream = copyAndAdvance(originalStream, delta);
    }
    Token eof = copyAndAdvance(originalStream, delta);
    eof.setNextWithoutSettingPrevious(eof);
    return super.firstToken;
  }
  Token copyAndAdvance(Token originalToken, int delta) {
    Token copiedToken = originalToken.copy();
    tokenMap.put(originalToken, copiedToken);
    copiedToken.applyDelta(delta);
    appendToken(copiedToken);
    Token originalComment = originalToken.precedingComments;
    Token copiedComment = originalToken.precedingComments;
    while (originalComment != null) {
      tokenMap.put(originalComment, copiedComment);
      originalComment = originalComment.next;
      copiedComment = copiedComment.next;
    }
    return originalToken.next;
  }
}
/**
 * The class `Scanner` implements a scanner for Dart code.
 *
 * The lexical structure of Dart is ambiguous without knowledge of the context in which a token is
 * being scanned. For example, without context we cannot determine whether source of the form "<<"
 * should be scanned as a single left-shift operator or as two left angle brackets. This scanner
 * does not have any context, so it always resolves such conflicts by scanning the longest possible
 * token.
 *
 * @coverage dart.engine.parser
 */
class Scanner {

  /**
   * The source being scanned.
   */
  Source source;

  /**
   * The reader used to access the characters in the source.
   */
  CharacterReader _reader;

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

  /**
   * The token pointing to the head of the linked list of tokens.
   */
  Token _tokens;

  /**
   * The last token that was scanned.
   */
  Token tail;

  /**
   * The first token in the list of comment tokens found since the last non-comment token.
   */
  Token _firstComment;

  /**
   * The last token in the list of comment tokens found since the last non-comment token.
   */
  Token _lastComment;

  /**
   * The index of the first character of the current token.
   */
  int _tokenStart = 0;

  /**
   * A list containing the offsets of the first character of each line in the source code.
   */
  List<int> _lineStarts = new List<int>();

  /**
   * A list, treated something like a stack, of tokens representing the beginning of a matched pair.
   * It is used to pair the end tokens with the begin tokens.
   */
  List<BeginToken> _groupingStack = new List<BeginToken>();

  /**
   * The index of the last item in the [groupingStack], or `-1` if the stack is empty.
   */
  int _stackEnd = -1;

  /**
   * A flag indicating whether any unmatched groups were found during the parse.
   */
  bool _hasUnmatchedGroups2 = false;

  /**
   * Initialize a newly created scanner.
   *
   * @param source the source being scanned
   * @param reader the character reader used to read the characters in the source
   * @param errorListener the error listener that will be informed of any errors that are found
   */
  Scanner(Source source, CharacterReader reader, AnalysisErrorListener errorListener) {
    this.source = source;
    this._reader = reader;
    this._errorListener = errorListener;
    _tokens = new Token(TokenType.EOF, -1);
    _tokens.setNext(_tokens);
    tail = _tokens;
    _tokenStart = -1;
    _lineStarts.add(0);
  }

  /**
   * Return an array containing the offsets of the first character of each line in the source code.
   *
   * @return an array containing the offsets of the first character of each line in the source code
   */
  List<int> get lineStarts => _lineStarts;

  /**
   * Return `true` if any unmatched groups were found during the parse.
   *
   * @return `true` if any unmatched groups were found during the parse
   */
  bool hasUnmatchedGroups() => _hasUnmatchedGroups2;

  /**
   * Record that the source begins on the given line and column at the current offset as given by
   * the reader. The line starts for lines before the given line will not be correct.
   *
   * This method must be invoked at most one time and must be invoked before scanning begins. The
   * values provided must be sensible. The results are undefined if these conditions are violated.
   *
   * @param line the one-based index of the line containing the first character of the source
   * @param column the one-based index of the column in which the first character of the source
   *          occurs
   */
  void setSourceStart(int line, int column) {
    int offset = _reader.offset;
    if (line < 1 || column < 1 || offset < 0 || (line + column - 2) >= offset) {
      return;
    }
    for (int i = 2; i < line; i++) {
      _lineStarts.add(1);
    }
    _lineStarts.add(offset - column + 1);
  }

  /**
   * Scan the source code to produce a list of tokens representing the source.
   *
   * @return the first token in the list of tokens that were produced
   */
  Token tokenize() {
    InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engine.AbstractScanner.tokenize");
    int tokenCounter = 0;
    try {
      int next = _reader.advance();
      while (next != -1) {
        tokenCounter++;
        next = bigSwitch(next);
      }
      appendEofToken();
      instrumentation.metric2("tokensCount", tokenCounter);
      return firstToken;
    } finally {
      instrumentation.log2(2);
    }
  }

  /**
   * Append the given token to the end of the token stream being scanned. This method is intended to
   * be used by subclasses that copy existing tokens and should not normally be used because it will
   * fail to correctly associate any comments with the token being passed in.
   *
   * @param token the token to be appended
   */
  void appendToken(Token token) {
    tail = tail.setNext(token);
  }
  int bigSwitch(int next) {
    beginToken();
    if (next == 0xD) {
      next = _reader.advance();
      if (next == 0xA) {
        next = _reader.advance();
      }
      recordStartOfLine();
      return next;
    } else if (next == 0xA) {
      next = _reader.advance();
      recordStartOfLine();
      return next;
    } else if (next == 0x9 || next == 0x20) {
      return _reader.advance();
    }
    if (next == 0x72) {
      int peek = _reader.peek();
      if (peek == 0x22 || peek == 0x27) {
        int start = _reader.offset;
        return tokenizeString(_reader.advance(), start, true);
      }
    }
    if (0x61 <= next && next <= 0x7A) {
      return tokenizeKeywordOrIdentifier(next, true);
    }
    if ((0x41 <= next && next <= 0x5A) || next == 0x5F || next == 0x24) {
      return tokenizeIdentifier(next, _reader.offset, true);
    }
    if (next == 0x3C) {
      return tokenizeLessThan(next);
    }
    if (next == 0x3E) {
      return tokenizeGreaterThan(next);
    }
    if (next == 0x3D) {
      return tokenizeEquals(next);
    }
    if (next == 0x21) {
      return tokenizeExclamation(next);
    }
    if (next == 0x2B) {
      return tokenizePlus(next);
    }
    if (next == 0x2D) {
      return tokenizeMinus(next);
    }
    if (next == 0x2A) {
      return tokenizeMultiply(next);
    }
    if (next == 0x25) {
      return tokenizePercent(next);
    }
    if (next == 0x26) {
      return tokenizeAmpersand(next);
    }
    if (next == 0x7C) {
      return tokenizeBar(next);
    }
    if (next == 0x5E) {
      return tokenizeCaret(next);
    }
    if (next == 0x5B) {
      return tokenizeOpenSquareBracket(next);
    }
    if (next == 0x7E) {
      return tokenizeTilde(next);
    }
    if (next == 0x5C) {
      appendToken2(TokenType.BACKSLASH);
      return _reader.advance();
    }
    if (next == 0x23) {
      return tokenizeTag(next);
    }
    if (next == 0x28) {
      appendBeginToken(TokenType.OPEN_PAREN);
      return _reader.advance();
    }
    if (next == 0x29) {
      appendEndToken(TokenType.CLOSE_PAREN, TokenType.OPEN_PAREN);
      return _reader.advance();
    }
    if (next == 0x2C) {
      appendToken2(TokenType.COMMA);
      return _reader.advance();
    }
    if (next == 0x3A) {
      appendToken2(TokenType.COLON);
      return _reader.advance();
    }
    if (next == 0x3B) {
      appendToken2(TokenType.SEMICOLON);
      return _reader.advance();
    }
    if (next == 0x3F) {
      appendToken2(TokenType.QUESTION);
      return _reader.advance();
    }
    if (next == 0x5D) {
      appendEndToken(TokenType.CLOSE_SQUARE_BRACKET, TokenType.OPEN_SQUARE_BRACKET);
      return _reader.advance();
    }
    if (next == 0x60) {
      appendToken2(TokenType.BACKPING);
      return _reader.advance();
    }
    if (next == 0x7B) {
      appendBeginToken(TokenType.OPEN_CURLY_BRACKET);
      return _reader.advance();
    }
    if (next == 0x7D) {
      appendEndToken(TokenType.CLOSE_CURLY_BRACKET, TokenType.OPEN_CURLY_BRACKET);
      return _reader.advance();
    }
    if (next == 0x2F) {
      return tokenizeSlashOrComment(next);
    }
    if (next == 0x40) {
      appendToken2(TokenType.AT);
      return _reader.advance();
    }
    if (next == 0x22 || next == 0x27) {
      return tokenizeString(next, _reader.offset, false);
    }
    if (next == 0x2E) {
      return tokenizeDotOrNumber(next);
    }
    if (next == 0x30) {
      return tokenizeHexOrNumber(next);
    }
    if (0x31 <= next && next <= 0x39) {
      return tokenizeNumber(next);
    }
    if (next == -1) {
      return -1;
    }
    reportError(ScannerErrorCode.ILLEGAL_CHARACTER, [next]);
    return _reader.advance();
  }

  /**
   * Return the first token in the token stream that was scanned.
   *
   * @return the first token in the token stream that was scanned
   */
  Token get firstToken => _tokens.next;

  /**
   * Record the fact that we are at the beginning of a new line in the source.
   */
  void recordStartOfLine() {
    _lineStarts.add(_reader.offset);
  }
  void appendBeginToken(TokenType type) {
    BeginToken token;
    if (_firstComment == null) {
      token = new BeginToken(type, _tokenStart);
    } else {
      token = new BeginTokenWithComment(type, _tokenStart, _firstComment);
      _firstComment = null;
      _lastComment = null;
    }
    tail = tail.setNext(token);
    _groupingStack.add(token);
    _stackEnd++;
  }
  void appendCommentToken(TokenType type, String value) {
    if (_firstComment == null) {
      _firstComment = new StringToken(type, value, _tokenStart);
      _lastComment = _firstComment;
    } else {
      _lastComment = _lastComment.setNext(new StringToken(type, value, _tokenStart));
    }
  }
  void appendEndToken(TokenType type, TokenType beginType) {
    Token token;
    if (_firstComment == null) {
      token = new Token(type, _tokenStart);
    } else {
      token = new TokenWithComment(type, _tokenStart, _firstComment);
      _firstComment = null;
      _lastComment = null;
    }
    tail = tail.setNext(token);
    if (_stackEnd >= 0) {
      BeginToken begin = _groupingStack[_stackEnd];
      if (identical(begin.type, beginType)) {
        begin.endToken = token;
        _groupingStack.removeAt(_stackEnd--);
      }
    }
  }
  void appendEofToken() {
    Token eofToken;
    if (_firstComment == null) {
      eofToken = new Token(TokenType.EOF, _reader.offset + 1);
    } else {
      eofToken = new TokenWithComment(TokenType.EOF, _reader.offset + 1, _firstComment);
      _firstComment = null;
      _lastComment = null;
    }
    eofToken.setNext(eofToken);
    tail = tail.setNext(eofToken);
    if (_stackEnd >= 0) {
      _hasUnmatchedGroups2 = true;
    }
  }
  void appendKeywordToken(Keyword keyword) {
    if (_firstComment == null) {
      tail = tail.setNext(new KeywordToken(keyword, _tokenStart));
    } else {
      tail = tail.setNext(new KeywordTokenWithComment(keyword, _tokenStart, _firstComment));
      _firstComment = null;
      _lastComment = null;
    }
  }
  void appendStringToken(TokenType type, String value) {
    if (_firstComment == null) {
      tail = tail.setNext(new StringToken(type, value, _tokenStart));
    } else {
      tail = tail.setNext(new StringTokenWithComment(type, value, _tokenStart, _firstComment));
      _firstComment = null;
      _lastComment = null;
    }
  }
  void appendStringToken2(TokenType type, String value, int offset) {
    if (_firstComment == null) {
      tail = tail.setNext(new StringToken(type, value, _tokenStart + offset));
    } else {
      tail = tail.setNext(new StringTokenWithComment(type, value, _tokenStart + offset, _firstComment));
      _firstComment = null;
      _lastComment = null;
    }
  }
  void appendToken2(TokenType type) {
    if (_firstComment == null) {
      tail = tail.setNext(new Token(type, _tokenStart));
    } else {
      tail = tail.setNext(new TokenWithComment(type, _tokenStart, _firstComment));
      _firstComment = null;
      _lastComment = null;
    }
  }
  void appendToken3(TokenType type, int offset) {
    if (_firstComment == null) {
      tail = tail.setNext(new Token(type, offset));
    } else {
      tail = tail.setNext(new TokenWithComment(type, offset, _firstComment));
      _firstComment = null;
      _lastComment = null;
    }
  }
  void beginToken() {
    _tokenStart = _reader.offset;
  }

  /**
   * Return the beginning token corresponding to a closing brace that was found while scanning
   * inside a string interpolation expression. Tokens that cannot be matched with the closing brace
   * will be dropped from the stack.
   *
   * @return the token to be paired with the closing brace
   */
  BeginToken findTokenMatchingClosingBraceInInterpolationExpression() {
    while (_stackEnd >= 0) {
      BeginToken begin = _groupingStack[_stackEnd];
      if (identical(begin.type, TokenType.OPEN_CURLY_BRACKET) || identical(begin.type, TokenType.STRING_INTERPOLATION_EXPRESSION)) {
        return begin;
      }
      _hasUnmatchedGroups2 = true;
      _groupingStack.removeAt(_stackEnd--);
    }
    return null;
  }

  /**
   * Report an error at the current offset.
   *
   * @param errorCode the error code indicating the nature of the error
   * @param arguments any arguments needed to complete the error message
   */
  void reportError(ScannerErrorCode errorCode, List<Object> arguments) {
    _errorListener.onError(new AnalysisError.con2(source, _reader.offset, 1, errorCode, arguments));
  }
  int select(int choice, TokenType yesType, TokenType noType) {
    int next = _reader.advance();
    if (next == choice) {
      appendToken2(yesType);
      return _reader.advance();
    } else {
      appendToken2(noType);
      return next;
    }
  }
  int select2(int choice, TokenType yesType, TokenType noType, int offset) {
    int next = _reader.advance();
    if (next == choice) {
      appendToken3(yesType, offset);
      return _reader.advance();
    } else {
      appendToken3(noType, offset);
      return next;
    }
  }
  int tokenizeAmpersand(int next) {
    next = _reader.advance();
    if (next == 0x26) {
      appendToken2(TokenType.AMPERSAND_AMPERSAND);
      return _reader.advance();
    } else if (next == 0x3D) {
      appendToken2(TokenType.AMPERSAND_EQ);
      return _reader.advance();
    } else {
      appendToken2(TokenType.AMPERSAND);
      return next;
    }
  }
  int tokenizeBar(int next) {
    next = _reader.advance();
    if (next == 0x7C) {
      appendToken2(TokenType.BAR_BAR);
      return _reader.advance();
    } else if (next == 0x3D) {
      appendToken2(TokenType.BAR_EQ);
      return _reader.advance();
    } else {
      appendToken2(TokenType.BAR);
      return next;
    }
  }
  int tokenizeCaret(int next) => select(0x3D, TokenType.CARET_EQ, TokenType.CARET);
  int tokenizeDotOrNumber(int next) {
    int start = _reader.offset;
    next = _reader.advance();
    if (0x30 <= next && next <= 0x39) {
      return tokenizeFractionPart(next, start);
    } else if (0x2E == next) {
      return select(0x2E, TokenType.PERIOD_PERIOD_PERIOD, TokenType.PERIOD_PERIOD);
    } else {
      appendToken2(TokenType.PERIOD);
      return next;
    }
  }
  int tokenizeEquals(int next) {
    next = _reader.advance();
    if (next == 0x3D) {
      appendToken2(TokenType.EQ_EQ);
      return _reader.advance();
    } else if (next == 0x3E) {
      appendToken2(TokenType.FUNCTION);
      return _reader.advance();
    }
    appendToken2(TokenType.EQ);
    return next;
  }
  int tokenizeExclamation(int next) {
    next = _reader.advance();
    if (next == 0x3D) {
      appendToken2(TokenType.BANG_EQ);
      return _reader.advance();
    }
    appendToken2(TokenType.BANG);
    return next;
  }
  int tokenizeExponent(int next) {
    if (next == 0x2B || next == 0x2D) {
      next = _reader.advance();
    }
    bool hasDigits = false;
    while (true) {
      if (0x30 <= next && next <= 0x39) {
        hasDigits = true;
      } else {
        if (!hasDigits) {
          reportError(ScannerErrorCode.MISSING_DIGIT, []);
        }
        return next;
      }
      next = _reader.advance();
    }
  }
  int tokenizeFractionPart(int next, int start) {
    bool done = false;
    bool hasDigit = false;
    LOOP: while (!done) {
      if (0x30 <= next && next <= 0x39) {
        hasDigit = true;
      } else if (0x65 == next || 0x45 == next) {
        hasDigit = true;
        next = tokenizeExponent(_reader.advance());
        done = true;
        continue LOOP;
      } else {
        done = true;
        continue LOOP;
      }
      next = _reader.advance();
    }
    if (!hasDigit) {
      appendStringToken(TokenType.INT, _reader.getString(start, -2));
      if (0x2E == next) {
        return select2(0x2E, TokenType.PERIOD_PERIOD_PERIOD, TokenType.PERIOD_PERIOD, _reader.offset - 1);
      }
      appendToken3(TokenType.PERIOD, _reader.offset - 1);
      return bigSwitch(next);
    }
    appendStringToken(TokenType.DOUBLE, _reader.getString(start, next < 0 ? 0 : -1));
    return next;
  }
  int tokenizeGreaterThan(int next) {
    next = _reader.advance();
    if (0x3D == next) {
      appendToken2(TokenType.GT_EQ);
      return _reader.advance();
    } else if (0x3E == next) {
      next = _reader.advance();
      if (0x3D == next) {
        appendToken2(TokenType.GT_GT_EQ);
        return _reader.advance();
      } else {
        appendToken2(TokenType.GT_GT);
        return next;
      }
    } else {
      appendToken2(TokenType.GT);
      return next;
    }
  }
  int tokenizeHex(int next) {
    int start = _reader.offset - 1;
    bool hasDigits = false;
    while (true) {
      next = _reader.advance();
      if ((0x30 <= next && next <= 0x39) || (0x41 <= next && next <= 0x46) || (0x61 <= next && next <= 0x66)) {
        hasDigits = true;
      } else {
        if (!hasDigits) {
          reportError(ScannerErrorCode.MISSING_HEX_DIGIT, []);
        }
        appendStringToken(TokenType.HEXADECIMAL, _reader.getString(start, next < 0 ? 0 : -1));
        return next;
      }
    }
  }
  int tokenizeHexOrNumber(int next) {
    int x = _reader.peek();
    if (x == 0x78 || x == 0x58) {
      _reader.advance();
      return tokenizeHex(x);
    }
    return tokenizeNumber(next);
  }
  int tokenizeIdentifier(int next, int start, bool allowDollar) {
    while ((0x61 <= next && next <= 0x7A) || (0x41 <= next && next <= 0x5A) || (0x30 <= next && next <= 0x39) || next == 0x5F || (next == 0x24 && allowDollar)) {
      next = _reader.advance();
    }
    appendStringToken(TokenType.IDENTIFIER, _reader.getString(start, next < 0 ? 0 : -1));
    return next;
  }
  int tokenizeInterpolatedExpression(int next, int start) {
    appendBeginToken(TokenType.STRING_INTERPOLATION_EXPRESSION);
    next = _reader.advance();
    while (next != -1) {
      if (next == 0x7D) {
        BeginToken begin = findTokenMatchingClosingBraceInInterpolationExpression();
        if (begin == null) {
          beginToken();
          appendToken2(TokenType.CLOSE_CURLY_BRACKET);
          next = _reader.advance();
          beginToken();
          return next;
        } else if (identical(begin.type, TokenType.OPEN_CURLY_BRACKET)) {
          beginToken();
          appendEndToken(TokenType.CLOSE_CURLY_BRACKET, TokenType.OPEN_CURLY_BRACKET);
          next = _reader.advance();
          beginToken();
        } else if (identical(begin.type, TokenType.STRING_INTERPOLATION_EXPRESSION)) {
          beginToken();
          appendEndToken(TokenType.CLOSE_CURLY_BRACKET, TokenType.STRING_INTERPOLATION_EXPRESSION);
          next = _reader.advance();
          beginToken();
          return next;
        }
      } else {
        next = bigSwitch(next);
      }
    }
    if (next == -1) {
      return next;
    }
    next = _reader.advance();
    beginToken();
    return next;
  }
  int tokenizeInterpolatedIdentifier(int next, int start) {
    appendStringToken2(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 0);
    if ((0x41 <= next && next <= 0x5A) || (0x61 <= next && next <= 0x7A) || next == 0x5F) {
      beginToken();
      next = tokenizeKeywordOrIdentifier(next, false);
    }
    beginToken();
    return next;
  }
  int tokenizeKeywordOrIdentifier(int next, bool allowDollar) {
    KeywordState state = KeywordState.KEYWORD_STATE;
    int start = _reader.offset;
    while (state != null && 0x61 <= next && next <= 0x7A) {
      state = state.next(next as int);
      next = _reader.advance();
    }
    if (state == null || state.keyword() == null) {
      return tokenizeIdentifier(next, start, allowDollar);
    }
    if ((0x41 <= next && next <= 0x5A) || (0x30 <= next && next <= 0x39) || next == 0x5F || next == 0x24) {
      return tokenizeIdentifier(next, start, allowDollar);
    } else if (next < 128) {
      appendKeywordToken(state.keyword());
      return next;
    } else {
      return tokenizeIdentifier(next, start, allowDollar);
    }
  }
  int tokenizeLessThan(int next) {
    next = _reader.advance();
    if (0x3D == next) {
      appendToken2(TokenType.LT_EQ);
      return _reader.advance();
    } else if (0x3C == next) {
      return select(0x3D, TokenType.LT_LT_EQ, TokenType.LT_LT);
    } else {
      appendToken2(TokenType.LT);
      return next;
    }
  }
  int tokenizeMinus(int next) {
    next = _reader.advance();
    if (next == 0x2D) {
      appendToken2(TokenType.MINUS_MINUS);
      return _reader.advance();
    } else if (next == 0x3D) {
      appendToken2(TokenType.MINUS_EQ);
      return _reader.advance();
    } else {
      appendToken2(TokenType.MINUS);
      return next;
    }
  }
  int tokenizeMultiLineComment(int next) {
    int nesting = 1;
    next = _reader.advance();
    while (true) {
      if (-1 == next) {
        reportError(ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT, []);
        appendCommentToken(TokenType.MULTI_LINE_COMMENT, _reader.getString(_tokenStart, 0));
        return next;
      } else if (0x2A == next) {
        next = _reader.advance();
        if (0x2F == next) {
          --nesting;
          if (0 == nesting) {
            appendCommentToken(TokenType.MULTI_LINE_COMMENT, _reader.getString(_tokenStart, 0));
            return _reader.advance();
          } else {
            next = _reader.advance();
          }
        }
      } else if (0x2F == next) {
        next = _reader.advance();
        if (0x2A == next) {
          next = _reader.advance();
          ++nesting;
        }
      } else if (next == 0xD) {
        next = _reader.advance();
        if (next == 0xA) {
          next = _reader.advance();
        }
        recordStartOfLine();
      } else if (next == 0xA) {
        recordStartOfLine();
        next = _reader.advance();
      } else {
        next = _reader.advance();
      }
    }
  }
  int tokenizeMultiLineRawString(int quoteChar, int start) {
    int next = _reader.advance();
    outer: while (next != -1) {
      while (next != quoteChar) {
        next = _reader.advance();
        if (next == -1) {
          break outer;
        } else if (next == 0xD) {
          next = _reader.advance();
          if (next == 0xA) {
            next = _reader.advance();
          }
          recordStartOfLine();
        } else if (next == 0xA) {
          recordStartOfLine();
          next = _reader.advance();
        }
      }
      next = _reader.advance();
      if (next == quoteChar) {
        next = _reader.advance();
        if (next == quoteChar) {
          appendStringToken(TokenType.STRING, _reader.getString(start, 0));
          return _reader.advance();
        }
      }
    }
    reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, []);
    appendStringToken(TokenType.STRING, _reader.getString(start, 0));
    return _reader.advance();
  }
  int tokenizeMultiLineString(int quoteChar, int start, bool raw) {
    if (raw) {
      return tokenizeMultiLineRawString(quoteChar, start);
    }
    int next = _reader.advance();
    while (next != -1) {
      if (next == 0x24) {
        appendStringToken(TokenType.STRING, _reader.getString(start, -1));
        beginToken();
        next = tokenizeStringInterpolation(start);
        start = _reader.offset;
        continue;
      }
      if (next == quoteChar) {
        next = _reader.advance();
        if (next == quoteChar) {
          next = _reader.advance();
          if (next == quoteChar) {
            appendStringToken(TokenType.STRING, _reader.getString(start, 0));
            return _reader.advance();
          }
        }
        continue;
      }
      if (next == 0x5C) {
        next = _reader.advance();
        if (next == -1) {
          break;
        }
        if (next == 0xD) {
          next = _reader.advance();
          if (next == 0xA) {
            next = _reader.advance();
          }
          recordStartOfLine();
        } else if (next == 0xA) {
          recordStartOfLine();
          next = _reader.advance();
        } else {
          next = _reader.advance();
        }
      } else if (next == 0xD) {
        next = _reader.advance();
        if (next == 0xA) {
          next = _reader.advance();
        }
        recordStartOfLine();
      } else if (next == 0xA) {
        recordStartOfLine();
        next = _reader.advance();
      } else {
        next = _reader.advance();
      }
    }
    reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, []);
    appendStringToken(TokenType.STRING, _reader.getString(start, 0));
    return _reader.advance();
  }
  int tokenizeMultiply(int next) => select(0x3D, TokenType.STAR_EQ, TokenType.STAR);
  int tokenizeNumber(int next) {
    int start = _reader.offset;
    while (true) {
      next = _reader.advance();
      if (0x30 <= next && next <= 0x39) {
        continue;
      } else if (next == 0x2E) {
        return tokenizeFractionPart(_reader.advance(), start);
      } else if (next == 0x65 || next == 0x45) {
        return tokenizeFractionPart(next, start);
      } else {
        appendStringToken(TokenType.INT, _reader.getString(start, next < 0 ? 0 : -1));
        return next;
      }
    }
  }
  int tokenizeOpenSquareBracket(int next) {
    next = _reader.advance();
    if (next == 0x5D) {
      return select(0x3D, TokenType.INDEX_EQ, TokenType.INDEX);
    } else {
      appendBeginToken(TokenType.OPEN_SQUARE_BRACKET);
      return next;
    }
  }
  int tokenizePercent(int next) => select(0x3D, TokenType.PERCENT_EQ, TokenType.PERCENT);
  int tokenizePlus(int next) {
    next = _reader.advance();
    if (0x2B == next) {
      appendToken2(TokenType.PLUS_PLUS);
      return _reader.advance();
    } else if (0x3D == next) {
      appendToken2(TokenType.PLUS_EQ);
      return _reader.advance();
    } else {
      appendToken2(TokenType.PLUS);
      return next;
    }
  }
  int tokenizeSingleLineComment(int next) {
    while (true) {
      next = _reader.advance();
      if (-1 == next) {
        appendCommentToken(TokenType.SINGLE_LINE_COMMENT, _reader.getString(_tokenStart, 0));
        return next;
      } else if (0xA == next || 0xD == next) {
        appendCommentToken(TokenType.SINGLE_LINE_COMMENT, _reader.getString(_tokenStart, -1));
        return next;
      }
    }
  }
  int tokenizeSingleLineRawString(int next, int quoteChar, int start) {
    next = _reader.advance();
    while (next != -1) {
      if (next == quoteChar) {
        appendStringToken(TokenType.STRING, _reader.getString(start, 0));
        return _reader.advance();
      } else if (next == 0xD || next == 0xA) {
        reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, []);
        appendStringToken(TokenType.STRING, _reader.getString(start, 0));
        return _reader.advance();
      }
      next = _reader.advance();
    }
    reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, []);
    appendStringToken(TokenType.STRING, _reader.getString(start, 0));
    return _reader.advance();
  }
  int tokenizeSingleLineString(int next, int quoteChar, int start) {
    while (next != quoteChar) {
      if (next == 0x5C) {
        next = _reader.advance();
      } else if (next == 0x24) {
        appendStringToken(TokenType.STRING, _reader.getString(start, -1));
        beginToken();
        next = tokenizeStringInterpolation(start);
        start = _reader.offset;
        continue;
      }
      if (next <= 0xD && (next == 0xA || next == 0xD || next == -1)) {
        reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, []);
        appendStringToken(TokenType.STRING, _reader.getString(start, 0));
        return _reader.advance();
      }
      next = _reader.advance();
    }
    appendStringToken(TokenType.STRING, _reader.getString(start, 0));
    return _reader.advance();
  }
  int tokenizeSlashOrComment(int next) {
    next = _reader.advance();
    if (0x2A == next) {
      return tokenizeMultiLineComment(next);
    } else if (0x2F == next) {
      return tokenizeSingleLineComment(next);
    } else if (0x3D == next) {
      appendToken2(TokenType.SLASH_EQ);
      return _reader.advance();
    } else {
      appendToken2(TokenType.SLASH);
      return next;
    }
  }
  int tokenizeString(int next, int start, bool raw) {
    int quoteChar = next;
    next = _reader.advance();
    if (quoteChar == next) {
      next = _reader.advance();
      if (quoteChar == next) {
        return tokenizeMultiLineString(quoteChar, start, raw);
      } else {
        appendStringToken(TokenType.STRING, _reader.getString(start, -1));
        return next;
      }
    }
    if (raw) {
      return tokenizeSingleLineRawString(next, quoteChar, start);
    } else {
      return tokenizeSingleLineString(next, quoteChar, start);
    }
  }
  int tokenizeStringInterpolation(int start) {
    beginToken();
    int next = _reader.advance();
    if (next == 0x7B) {
      return tokenizeInterpolatedExpression(next, start);
    } else {
      return tokenizeInterpolatedIdentifier(next, start);
    }
  }
  int tokenizeTag(int next) {
    if (_reader.offset == 0) {
      if (_reader.peek() == 0x21) {
        do {
          next = _reader.advance();
        } while (next != 0xA && next != 0xD && next > 0);
        appendStringToken(TokenType.SCRIPT_TAG, _reader.getString(_tokenStart, 0));
        return next;
      }
    }
    appendToken2(TokenType.HASH);
    return _reader.advance();
  }
  int tokenizeTilde(int next) {
    next = _reader.advance();
    if (next == 0x2F) {
      return select(0x3D, TokenType.TILDE_SLASH_EQ, TokenType.TILDE_SLASH);
    } else {
      appendToken2(TokenType.TILDE);
      return next;
    }
  }
}
/**
 * Instances of the class `StringToken` represent a token whose value is independent of it's
 * type.
 *
 * @coverage dart.engine.parser
 */
class StringToken extends Token {

  /**
   * The lexeme represented by this token.
   */
  String _value2;

  /**
   * Initialize a newly created token to represent a token of the given type with the given value.
   *
   * @param type the type of the token
   * @param value the lexeme represented by this token
   * @param offset the offset from the beginning of the file to the first character in the token
   */
  StringToken(TokenType type, String value, int offset) : super(type, offset) {
    this._value2 = StringUtilities.intern(value);
  }
  Token copy() => new StringToken(type, _value2, offset);
  String get lexeme => _value2;
  String value() => _value2;
}
/**
 * Instances of the class `TokenWithComment` represent a normal token that is preceded by
 * comments.
 *
 * @coverage dart.engine.parser
 */
class TokenWithComment extends Token {

  /**
   * The first comment in the list of comments that precede this token.
   */
  Token _precedingComment;

  /**
   * Initialize a newly created token to have the given type and offset and to be preceded by the
   * comments reachable from the given comment.
   *
   * @param type the type of the token
   * @param offset the offset from the beginning of the file to the first character in the token
   * @param precedingComment the first comment in the list of comments that precede this token
   */
  TokenWithComment(TokenType type, int offset, Token precedingComment) : super(type, offset) {
    this._precedingComment = precedingComment;
  }
  Token copy() => new TokenWithComment(type, offset, _precedingComment);
  Token get precedingComments => _precedingComment;
}
/**
 * Instances of the class `Token` represent a token that was scanned from the input. Each
 * token knows which token follows it, acting as the head of a linked list of tokens.
 *
 * @coverage dart.engine.parser
 */
class Token {

  /**
   * The type of the token.
   */
  TokenType type;

  /**
   * The offset from the beginning of the file to the first character in the token.
   */
  int offset = 0;

  /**
   * The previous token in the token stream.
   */
  Token previous;

  /**
   * The next token in the token stream.
   */
  Token next;

  /**
   * Initialize a newly created token to have the given type and offset.
   *
   * @param type the type of the token
   * @param offset the offset from the beginning of the file to the first character in the token
   */
  Token(TokenType type, int offset) {
    this.type = type;
    this.offset = offset;
  }

  /**
   * Return a newly created token that is a copy of this token but that is not a part of any token
   * stream.
   *
   * @return a newly created token that is a copy of this token
   */
  Token copy() => new Token(type, offset);

  /**
   * Return the offset from the beginning of the file to the character after last character of the
   * token.
   *
   * @return the offset from the beginning of the file to the first character after last character
   *         of the token
   */
  int get end => offset + length;

  /**
   * Return the number of characters in the node's source range.
   *
   * @return the number of characters in the node's source range
   */
  int get length => lexeme.length;

  /**
   * Return the lexeme that represents this token.
   *
   * @return the lexeme that represents this token
   */
  String get lexeme => type.lexeme;

  /**
   * Return the first comment in the list of comments that precede this token, or `null` if
   * there are no comments preceding this token. Additional comments can be reached by following the
   * token stream using [getNext] until `null` is returned.
   *
   * @return the first comment in the list of comments that precede this token
   */
  Token get precedingComments => null;

  /**
   * Return `true` if this token represents an operator.
   *
   * @return `true` if this token represents an operator
   */
  bool get isOperator => type.isOperator;

  /**
   * Return `true` if this token is a synthetic token. A synthetic token is a token that was
   * introduced by the parser in order to recover from an error in the code. Synthetic tokens always
   * have a length of zero (`0`).
   *
   * @return `true` if this token is a synthetic token
   */
  bool get isSynthetic => length == 0;

  /**
   * Return `true` if this token represents an operator that can be defined by users.
   *
   * @return `true` if this token represents an operator that can be defined by users
   */
  bool get isUserDefinableOperator => type.isUserDefinableOperator;

  /**
   * Set the next token in the token stream to the given token. This has the side-effect of setting
   * this token to be the previous token for the given token.
   *
   * @param token the next token in the token stream
   * @return the token that was passed in
   */
  Token setNext(Token token) {
    next = token;
    token.previous = this;
    return token;
  }

  /**
   * Set the next token in the token stream to the given token without changing which token is the
   * previous token for the given token.
   *
   * @param token the next token in the token stream
   * @return the token that was passed in
   */
  Token setNextWithoutSettingPrevious(Token token) {
    next = token;
    return token;
  }
  String toString() => lexeme;

  /**
   * Return the value of this token. For keyword tokens, this is the keyword associated with the
   * token, for other tokens it is the lexeme associated with the token.
   *
   * @return the value of this token
   */
  Object value() => type.lexeme;

  /**
   * Apply (add) the given delta to this token's offset.
   *
   * @param delta the amount by which the offset is to be adjusted
   */
  void applyDelta(int delta) {
    offset += delta;
  }

  /**
   * Copy a linked list of comment tokens identical to the given comment tokens.
   *
   * @param token the first token in the list, or `null` if there are no tokens to be copied
   * @return the tokens that were created
   */
  Token copyComments(Token token) {
    if (token == null) {
      return null;
    }
    Token head = token.copy();
    Token tail = head;
    token = token.next;
    while (token != null) {
      tail = tail.setNext(token.copy());
      token = token.next;
    }
    return head;
  }
}
/**
 * The interface `CharacterReader`
 */
abstract class CharacterReader {

  /**
   * Advance the current position and return the character at the new current position.
   *
   * @return the character at the new current position
   */
  int advance();

  /**
   * Return the current offset relative to the beginning of the source. Return the initial offset if
   * the scanner has not yet scanned the source code, and one (1) past the end of the source code if
   * the entire source code has been scanned.
   *
   * @return the current offset of the scanner in the source
   */
  int get offset;

  /**
   * Return the substring of the source code between the start offset and the modified current
   * position. The current position is modified by adding the end delta.
   *
   * @param start the offset to the beginning of the string, relative to the start of the file
   * @param endDelta the number of characters after the current location to be included in the
   *          string, or the number of characters before the current location to be excluded if the
   *          offset is negative
   * @return the specified substring of the source code
   */
  String getString(int start, int endDelta);

  /**
   * Return the character at the current position without changing the current position.
   *
   * @return the character at the current position
   */
  int peek();

  /**
   * Set the current offset relative to the beginning of the source. The new offset must be between
   * the initial offset and one (1) past the end of the source code.
   *
   * @param offset the new offset in the source
   */
  void set offset(int offset);
}
/**
 * Instances of the class `BeginTokenWithComment` represent a begin token that is preceded by
 * comments.
 *
 * @coverage dart.engine.parser
 */
class BeginTokenWithComment extends BeginToken {

  /**
   * The first comment in the list of comments that precede this token.
   */
  Token _precedingComment;

  /**
   * Initialize a newly created token to have the given type and offset and to be preceded by the
   * comments reachable from the given comment.
   *
   * @param type the type of the token
   * @param offset the offset from the beginning of the file to the first character in the token
   * @param precedingComment the first comment in the list of comments that precede this token
   */
  BeginTokenWithComment(TokenType type, int offset, Token precedingComment) : super(type, offset) {
    this._precedingComment = precedingComment;
  }
  Token copy() => new BeginTokenWithComment(type, offset, copyComments(_precedingComment));
  Token get precedingComments => _precedingComment;
  void applyDelta(int delta) {
    super.applyDelta(delta);
    Token token = _precedingComment;
    while (token != null) {
      token.applyDelta(delta);
      token = token.next;
    }
  }
}
/**
 * Instances of the class `KeywordToken` represent a keyword in the language.
 *
 * @coverage dart.engine.parser
 */
class KeywordToken extends Token {

  /**
   * The keyword being represented by this token.
   */
  Keyword keyword;

  /**
   * Initialize a newly created token to represent the given keyword.
   *
   * @param keyword the keyword being represented by this token
   * @param offset the offset from the beginning of the file to the first character in the token
   */
  KeywordToken(Keyword keyword, int offset) : super(TokenType.KEYWORD, offset) {
    this.keyword = keyword;
  }
  Token copy() => new KeywordToken(keyword, offset);
  String get lexeme => keyword.syntax;
  Keyword value() => keyword;
}
/**
 * Instances of the class `BeginToken` represent the opening half of a grouping pair of
 * tokens. This is used for curly brackets ('{'), parentheses ('('), and square brackets ('[').
 *
 * @coverage dart.engine.parser
 */
class BeginToken extends Token {

  /**
   * The token that corresponds to this token.
   */
  Token endToken;

  /**
   * Initialize a newly created token representing the opening half of a grouping pair of tokens.
   *
   * @param type the type of the token
   * @param offset the offset from the beginning of the file to the first character in the token
   */
  BeginToken(TokenType type, int offset) : super(type, offset) {
    assert((identical(type, TokenType.OPEN_CURLY_BRACKET) || identical(type, TokenType.OPEN_PAREN) || identical(type, TokenType.OPEN_SQUARE_BRACKET) || identical(type, TokenType.STRING_INTERPOLATION_EXPRESSION)));
  }
  Token copy() => new BeginToken(type, offset);
}
/**
 * The enumeration `TokenClass` represents classes (or groups) of tokens with a similar use.
 *
 * @coverage dart.engine.parser
 */
class TokenClass extends Enum<TokenClass> {

  /**
   * A value used to indicate that the token type is not part of any specific class of token.
   */
  static final TokenClass NO_CLASS = new TokenClass.con1('NO_CLASS', 0);

  /**
   * A value used to indicate that the token type is an additive operator.
   */
  static final TokenClass ADDITIVE_OPERATOR = new TokenClass.con2('ADDITIVE_OPERATOR', 1, 12);

  /**
   * A value used to indicate that the token type is an assignment operator.
   */
  static final TokenClass ASSIGNMENT_OPERATOR = new TokenClass.con2('ASSIGNMENT_OPERATOR', 2, 1);

  /**
   * A value used to indicate that the token type is a bitwise-and operator.
   */
  static final TokenClass BITWISE_AND_OPERATOR = new TokenClass.con2('BITWISE_AND_OPERATOR', 3, 8);

  /**
   * A value used to indicate that the token type is a bitwise-or operator.
   */
  static final TokenClass BITWISE_OR_OPERATOR = new TokenClass.con2('BITWISE_OR_OPERATOR', 4, 6);

  /**
   * A value used to indicate that the token type is a bitwise-xor operator.
   */
  static final TokenClass BITWISE_XOR_OPERATOR = new TokenClass.con2('BITWISE_XOR_OPERATOR', 5, 7);

  /**
   * A value used to indicate that the token type is a cascade operator.
   */
  static final TokenClass CASCADE_OPERATOR = new TokenClass.con2('CASCADE_OPERATOR', 6, 2);

  /**
   * A value used to indicate that the token type is a conditional operator.
   */
  static final TokenClass CONDITIONAL_OPERATOR = new TokenClass.con2('CONDITIONAL_OPERATOR', 7, 3);

  /**
   * A value used to indicate that the token type is an equality operator.
   */
  static final TokenClass EQUALITY_OPERATOR = new TokenClass.con2('EQUALITY_OPERATOR', 8, 9);

  /**
   * A value used to indicate that the token type is a logical-and operator.
   */
  static final TokenClass LOGICAL_AND_OPERATOR = new TokenClass.con2('LOGICAL_AND_OPERATOR', 9, 5);

  /**
   * A value used to indicate that the token type is a logical-or operator.
   */
  static final TokenClass LOGICAL_OR_OPERATOR = new TokenClass.con2('LOGICAL_OR_OPERATOR', 10, 4);

  /**
   * A value used to indicate that the token type is a multiplicative operator.
   */
  static final TokenClass MULTIPLICATIVE_OPERATOR = new TokenClass.con2('MULTIPLICATIVE_OPERATOR', 11, 13);

  /**
   * A value used to indicate that the token type is a relational operator.
   */
  static final TokenClass RELATIONAL_OPERATOR = new TokenClass.con2('RELATIONAL_OPERATOR', 12, 10);

  /**
   * A value used to indicate that the token type is a shift operator.
   */
  static final TokenClass SHIFT_OPERATOR = new TokenClass.con2('SHIFT_OPERATOR', 13, 11);

  /**
   * A value used to indicate that the token type is a unary operator.
   */
  static final TokenClass UNARY_POSTFIX_OPERATOR = new TokenClass.con2('UNARY_POSTFIX_OPERATOR', 14, 15);

  /**
   * A value used to indicate that the token type is a unary operator.
   */
  static final TokenClass UNARY_PREFIX_OPERATOR = new TokenClass.con2('UNARY_PREFIX_OPERATOR', 15, 14);
  static final List<TokenClass> values = [
      NO_CLASS,
      ADDITIVE_OPERATOR,
      ASSIGNMENT_OPERATOR,
      BITWISE_AND_OPERATOR,
      BITWISE_OR_OPERATOR,
      BITWISE_XOR_OPERATOR,
      CASCADE_OPERATOR,
      CONDITIONAL_OPERATOR,
      EQUALITY_OPERATOR,
      LOGICAL_AND_OPERATOR,
      LOGICAL_OR_OPERATOR,
      MULTIPLICATIVE_OPERATOR,
      RELATIONAL_OPERATOR,
      SHIFT_OPERATOR,
      UNARY_POSTFIX_OPERATOR,
      UNARY_PREFIX_OPERATOR];

  /**
   * The precedence of tokens of this class, or `0` if the such tokens do not represent an
   * operator.
   */
  int precedence = 0;
  TokenClass.con1(String name, int ordinal) : this.con2(name, ordinal, 0);
  TokenClass.con2(String name, int ordinal, int precedence) : super(name, ordinal) {
    this.precedence = precedence;
  }
}
/**
 * Instances of the class `KeywordTokenWithComment` implement a keyword token that is preceded
 * by comments.
 *
 * @coverage dart.engine.parser
 */
class KeywordTokenWithComment extends KeywordToken {

  /**
   * The first comment in the list of comments that precede this token.
   */
  Token _precedingComment;

  /**
   * Initialize a newly created token to to represent the given keyword and to be preceded by the
   * comments reachable from the given comment.
   *
   * @param keyword the keyword being represented by this token
   * @param offset the offset from the beginning of the file to the first character in the token
   * @param precedingComment the first comment in the list of comments that precede this token
   */
  KeywordTokenWithComment(Keyword keyword, int offset, Token precedingComment) : super(keyword, offset) {
    this._precedingComment = precedingComment;
  }
  Token copy() => new KeywordTokenWithComment(keyword, offset, copyComments(_precedingComment));
  Token get precedingComments => _precedingComment;
  void applyDelta(int delta) {
    super.applyDelta(delta);
    Token token = _precedingComment;
    while (token != null) {
      token.applyDelta(delta);
      token = token.next;
    }
  }
}
/**
 * The enumeration `TokenType` defines the types of tokens that can be returned by the
 * scanner.
 *
 * @coverage dart.engine.parser
 */
class TokenType extends Enum<TokenType> {

  /**
   * The type of the token that marks the end of the input.
   */
  static final TokenType EOF = new TokenType_EOF('EOF', 0, null, "");
  static final TokenType DOUBLE = new TokenType.con1('DOUBLE', 1);
  static final TokenType HEXADECIMAL = new TokenType.con1('HEXADECIMAL', 2);
  static final TokenType IDENTIFIER = new TokenType.con1('IDENTIFIER', 3);
  static final TokenType INT = new TokenType.con1('INT', 4);
  static final TokenType KEYWORD = new TokenType.con1('KEYWORD', 5);
  static final TokenType MULTI_LINE_COMMENT = new TokenType.con1('MULTI_LINE_COMMENT', 6);
  static final TokenType SCRIPT_TAG = new TokenType.con1('SCRIPT_TAG', 7);
  static final TokenType SINGLE_LINE_COMMENT = new TokenType.con1('SINGLE_LINE_COMMENT', 8);
  static final TokenType STRING = new TokenType.con1('STRING', 9);
  static final TokenType AMPERSAND = new TokenType.con2('AMPERSAND', 10, TokenClass.BITWISE_AND_OPERATOR, "&");
  static final TokenType AMPERSAND_AMPERSAND = new TokenType.con2('AMPERSAND_AMPERSAND', 11, TokenClass.LOGICAL_AND_OPERATOR, "&&");
  static final TokenType AMPERSAND_EQ = new TokenType.con2('AMPERSAND_EQ', 12, TokenClass.ASSIGNMENT_OPERATOR, "&=");
  static final TokenType AT = new TokenType.con2('AT', 13, null, "@");
  static final TokenType BANG = new TokenType.con2('BANG', 14, TokenClass.UNARY_PREFIX_OPERATOR, "!");
  static final TokenType BANG_EQ = new TokenType.con2('BANG_EQ', 15, TokenClass.EQUALITY_OPERATOR, "!=");
  static final TokenType BAR = new TokenType.con2('BAR', 16, TokenClass.BITWISE_OR_OPERATOR, "|");
  static final TokenType BAR_BAR = new TokenType.con2('BAR_BAR', 17, TokenClass.LOGICAL_OR_OPERATOR, "||");
  static final TokenType BAR_EQ = new TokenType.con2('BAR_EQ', 18, TokenClass.ASSIGNMENT_OPERATOR, "|=");
  static final TokenType COLON = new TokenType.con2('COLON', 19, null, ":");
  static final TokenType COMMA = new TokenType.con2('COMMA', 20, null, ",");
  static final TokenType CARET = new TokenType.con2('CARET', 21, TokenClass.BITWISE_XOR_OPERATOR, "^");
  static final TokenType CARET_EQ = new TokenType.con2('CARET_EQ', 22, TokenClass.ASSIGNMENT_OPERATOR, "^=");
  static final TokenType CLOSE_CURLY_BRACKET = new TokenType.con2('CLOSE_CURLY_BRACKET', 23, null, "}");
  static final TokenType CLOSE_PAREN = new TokenType.con2('CLOSE_PAREN', 24, null, ")");
  static final TokenType CLOSE_SQUARE_BRACKET = new TokenType.con2('CLOSE_SQUARE_BRACKET', 25, null, "]");
  static final TokenType EQ = new TokenType.con2('EQ', 26, TokenClass.ASSIGNMENT_OPERATOR, "=");
  static final TokenType EQ_EQ = new TokenType.con2('EQ_EQ', 27, TokenClass.EQUALITY_OPERATOR, "==");
  static final TokenType FUNCTION = new TokenType.con2('FUNCTION', 28, null, "=>");
  static final TokenType GT = new TokenType.con2('GT', 29, TokenClass.RELATIONAL_OPERATOR, ">");
  static final TokenType GT_EQ = new TokenType.con2('GT_EQ', 30, TokenClass.RELATIONAL_OPERATOR, ">=");
  static final TokenType GT_GT = new TokenType.con2('GT_GT', 31, TokenClass.SHIFT_OPERATOR, ">>");
  static final TokenType GT_GT_EQ = new TokenType.con2('GT_GT_EQ', 32, TokenClass.ASSIGNMENT_OPERATOR, ">>=");
  static final TokenType HASH = new TokenType.con2('HASH', 33, null, "#");
  static final TokenType INDEX = new TokenType.con2('INDEX', 34, TokenClass.UNARY_POSTFIX_OPERATOR, "[]");
  static final TokenType INDEX_EQ = new TokenType.con2('INDEX_EQ', 35, TokenClass.UNARY_POSTFIX_OPERATOR, "[]=");
  static final TokenType IS = new TokenType.con2('IS', 36, TokenClass.RELATIONAL_OPERATOR, "is");
  static final TokenType LT = new TokenType.con2('LT', 37, TokenClass.RELATIONAL_OPERATOR, "<");
  static final TokenType LT_EQ = new TokenType.con2('LT_EQ', 38, TokenClass.RELATIONAL_OPERATOR, "<=");
  static final TokenType LT_LT = new TokenType.con2('LT_LT', 39, TokenClass.SHIFT_OPERATOR, "<<");
  static final TokenType LT_LT_EQ = new TokenType.con2('LT_LT_EQ', 40, TokenClass.ASSIGNMENT_OPERATOR, "<<=");
  static final TokenType MINUS = new TokenType.con2('MINUS', 41, TokenClass.ADDITIVE_OPERATOR, "-");
  static final TokenType MINUS_EQ = new TokenType.con2('MINUS_EQ', 42, TokenClass.ASSIGNMENT_OPERATOR, "-=");
  static final TokenType MINUS_MINUS = new TokenType.con2('MINUS_MINUS', 43, TokenClass.UNARY_PREFIX_OPERATOR, "--");
  static final TokenType OPEN_CURLY_BRACKET = new TokenType.con2('OPEN_CURLY_BRACKET', 44, null, "{");
  static final TokenType OPEN_PAREN = new TokenType.con2('OPEN_PAREN', 45, TokenClass.UNARY_POSTFIX_OPERATOR, "(");
  static final TokenType OPEN_SQUARE_BRACKET = new TokenType.con2('OPEN_SQUARE_BRACKET', 46, TokenClass.UNARY_POSTFIX_OPERATOR, "[");
  static final TokenType PERCENT = new TokenType.con2('PERCENT', 47, TokenClass.MULTIPLICATIVE_OPERATOR, "%");
  static final TokenType PERCENT_EQ = new TokenType.con2('PERCENT_EQ', 48, TokenClass.ASSIGNMENT_OPERATOR, "%=");
  static final TokenType PERIOD = new TokenType.con2('PERIOD', 49, TokenClass.UNARY_POSTFIX_OPERATOR, ".");
  static final TokenType PERIOD_PERIOD = new TokenType.con2('PERIOD_PERIOD', 50, TokenClass.CASCADE_OPERATOR, "..");
  static final TokenType PLUS = new TokenType.con2('PLUS', 51, TokenClass.ADDITIVE_OPERATOR, "+");
  static final TokenType PLUS_EQ = new TokenType.con2('PLUS_EQ', 52, TokenClass.ASSIGNMENT_OPERATOR, "+=");
  static final TokenType PLUS_PLUS = new TokenType.con2('PLUS_PLUS', 53, TokenClass.UNARY_PREFIX_OPERATOR, "++");
  static final TokenType QUESTION = new TokenType.con2('QUESTION', 54, TokenClass.CONDITIONAL_OPERATOR, "?");
  static final TokenType SEMICOLON = new TokenType.con2('SEMICOLON', 55, null, ";");
  static final TokenType SLASH = new TokenType.con2('SLASH', 56, TokenClass.MULTIPLICATIVE_OPERATOR, "/");
  static final TokenType SLASH_EQ = new TokenType.con2('SLASH_EQ', 57, TokenClass.ASSIGNMENT_OPERATOR, "/=");
  static final TokenType STAR = new TokenType.con2('STAR', 58, TokenClass.MULTIPLICATIVE_OPERATOR, "*");
  static final TokenType STAR_EQ = new TokenType.con2('STAR_EQ', 59, TokenClass.ASSIGNMENT_OPERATOR, "*=");
  static final TokenType STRING_INTERPOLATION_EXPRESSION = new TokenType.con2('STRING_INTERPOLATION_EXPRESSION', 60, null, "\${");
  static final TokenType STRING_INTERPOLATION_IDENTIFIER = new TokenType.con2('STRING_INTERPOLATION_IDENTIFIER', 61, null, "\$");
  static final TokenType TILDE = new TokenType.con2('TILDE', 62, TokenClass.UNARY_PREFIX_OPERATOR, "~");
  static final TokenType TILDE_SLASH = new TokenType.con2('TILDE_SLASH', 63, TokenClass.MULTIPLICATIVE_OPERATOR, "~/");
  static final TokenType TILDE_SLASH_EQ = new TokenType.con2('TILDE_SLASH_EQ', 64, TokenClass.ASSIGNMENT_OPERATOR, "~/=");
  static final TokenType BACKPING = new TokenType.con2('BACKPING', 65, null, "`");
  static final TokenType BACKSLASH = new TokenType.con2('BACKSLASH', 66, null, "\\");
  static final TokenType PERIOD_PERIOD_PERIOD = new TokenType.con2('PERIOD_PERIOD_PERIOD', 67, null, "...");
  static final List<TokenType> values = [
      EOF,
      DOUBLE,
      HEXADECIMAL,
      IDENTIFIER,
      INT,
      KEYWORD,
      MULTI_LINE_COMMENT,
      SCRIPT_TAG,
      SINGLE_LINE_COMMENT,
      STRING,
      AMPERSAND,
      AMPERSAND_AMPERSAND,
      AMPERSAND_EQ,
      AT,
      BANG,
      BANG_EQ,
      BAR,
      BAR_BAR,
      BAR_EQ,
      COLON,
      COMMA,
      CARET,
      CARET_EQ,
      CLOSE_CURLY_BRACKET,
      CLOSE_PAREN,
      CLOSE_SQUARE_BRACKET,
      EQ,
      EQ_EQ,
      FUNCTION,
      GT,
      GT_EQ,
      GT_GT,
      GT_GT_EQ,
      HASH,
      INDEX,
      INDEX_EQ,
      IS,
      LT,
      LT_EQ,
      LT_LT,
      LT_LT_EQ,
      MINUS,
      MINUS_EQ,
      MINUS_MINUS,
      OPEN_CURLY_BRACKET,
      OPEN_PAREN,
      OPEN_SQUARE_BRACKET,
      PERCENT,
      PERCENT_EQ,
      PERIOD,
      PERIOD_PERIOD,
      PLUS,
      PLUS_EQ,
      PLUS_PLUS,
      QUESTION,
      SEMICOLON,
      SLASH,
      SLASH_EQ,
      STAR,
      STAR_EQ,
      STRING_INTERPOLATION_EXPRESSION,
      STRING_INTERPOLATION_IDENTIFIER,
      TILDE,
      TILDE_SLASH,
      TILDE_SLASH_EQ,
      BACKPING,
      BACKSLASH,
      PERIOD_PERIOD_PERIOD];

  /**
   * The class of the token.
   */
  TokenClass _tokenClass;

  /**
   * The lexeme that defines this type of token, or `null` if there is more than one possible
   * lexeme for this type of token.
   */
  String lexeme;
  TokenType.con1(String name, int ordinal) : this.con2(name, ordinal, TokenClass.NO_CLASS, null);
  TokenType.con2(String name, int ordinal, TokenClass tokenClass, String lexeme) : super(name, ordinal) {
    this._tokenClass = tokenClass == null ? TokenClass.NO_CLASS : tokenClass;
    this.lexeme = lexeme;
  }

  /**
   * Return the precedence of the token, or `0` if the token does not represent an operator.
   *
   * @return the precedence of the token
   */
  int get precedence => _tokenClass.precedence;

  /**
   * Return `true` if this type of token represents an additive operator.
   *
   * @return `true` if this type of token represents an additive operator
   */
  bool get isAdditiveOperator => identical(_tokenClass, TokenClass.ADDITIVE_OPERATOR);

  /**
   * Return `true` if this type of token represents an assignment operator.
   *
   * @return `true` if this type of token represents an assignment operator
   */
  bool get isAssignmentOperator => identical(_tokenClass, TokenClass.ASSIGNMENT_OPERATOR);

  /**
   * Return `true` if this type of token represents an associative operator. An associative
   * operator is an operator for which the following equality is true:
   * `(a * b) * c == a * (b * c)`. In other words, if the result of applying the operator to
   * multiple operands does not depend on the order in which those applications occur.
   *
   * Note: This method considers the logical-and and logical-or operators to be associative, even
   * though the order in which the application of those operators can have an effect because
   * evaluation of the right-hand operand is conditional.
   *
   * @return `true` if this type of token represents an associative operator
   */
  bool get isAssociativeOperator => identical(this, AMPERSAND) || identical(this, AMPERSAND_AMPERSAND) || identical(this, BAR) || identical(this, BAR_BAR) || identical(this, CARET) || identical(this, PLUS) || identical(this, STAR);

  /**
   * Return `true` if this type of token represents an equality operator.
   *
   * @return `true` if this type of token represents an equality operator
   */
  bool get isEqualityOperator => identical(_tokenClass, TokenClass.EQUALITY_OPERATOR);

  /**
   * Return `true` if this type of token represents an increment operator.
   *
   * @return `true` if this type of token represents an increment operator
   */
  bool get isIncrementOperator => identical(lexeme, "++") || identical(lexeme, "--");

  /**
   * Return `true` if this type of token represents a multiplicative operator.
   *
   * @return `true` if this type of token represents a multiplicative operator
   */
  bool get isMultiplicativeOperator => identical(_tokenClass, TokenClass.MULTIPLICATIVE_OPERATOR);

  /**
   * Return `true` if this token type represents an operator.
   *
   * @return `true` if this token type represents an operator
   */
  bool get isOperator => _tokenClass != TokenClass.NO_CLASS && this != OPEN_PAREN && this != OPEN_SQUARE_BRACKET && this != PERIOD;

  /**
   * Return `true` if this type of token represents a relational operator.
   *
   * @return `true` if this type of token represents a relational operator
   */
  bool get isRelationalOperator => identical(_tokenClass, TokenClass.RELATIONAL_OPERATOR);

  /**
   * Return `true` if this type of token represents a shift operator.
   *
   * @return `true` if this type of token represents a shift operator
   */
  bool get isShiftOperator => identical(_tokenClass, TokenClass.SHIFT_OPERATOR);

  /**
   * Return `true` if this type of token represents a unary postfix operator.
   *
   * @return `true` if this type of token represents a unary postfix operator
   */
  bool get isUnaryPostfixOperator => identical(_tokenClass, TokenClass.UNARY_POSTFIX_OPERATOR);

  /**
   * Return `true` if this type of token represents a unary prefix operator.
   *
   * @return `true` if this type of token represents a unary prefix operator
   */
  bool get isUnaryPrefixOperator => identical(_tokenClass, TokenClass.UNARY_PREFIX_OPERATOR);

  /**
   * Return `true` if this token type represents an operator that can be defined by users.
   *
   * @return `true` if this token type represents an operator that can be defined by users
   */
  bool get isUserDefinableOperator => identical(lexeme, "==") || identical(lexeme, "~") || identical(lexeme, "[]") || identical(lexeme, "[]=") || identical(lexeme, "*") || identical(lexeme, "/") || identical(lexeme, "%") || identical(lexeme, "~/") || identical(lexeme, "+") || identical(lexeme, "-") || identical(lexeme, "<<") || identical(lexeme, ">>") || identical(lexeme, ">=") || identical(lexeme, ">") || identical(lexeme, "<=") || identical(lexeme, "<") || identical(lexeme, "&") || identical(lexeme, "^") || identical(lexeme, "|");
}
class TokenType_EOF extends TokenType {
  TokenType_EOF(String name, int ordinal, TokenClass arg0, String arg1) : super.con2(name, ordinal, arg0, arg1);
  String toString() => "-eof-";
}