// 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.html;
import 'dart:collection';
import 'java_core.dart';
import 'java_engine.dart';
import 'source.dart';
import 'element.dart' show HtmlElementImpl;
import 'engine.dart' show AnalysisEngine;
/**
 * 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.html
 */
class Token {

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

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

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

  /**
   * Initialize a newly created token.
   *
   * @param type the token type (not `null`)
   * @param offset the offset from the beginning of the file to the first character in the token
   */
  Token.con1(TokenType type, int offset) : this.con2(type, offset, type.lexeme);

  /**
   * Initialize a newly created token.
   *
   * @param type the token type (not `null`)
   * @param offset the offset from the beginning of the file to the first character in the token
   * @param value the lexeme represented by this token (not `null`)
   */
  Token.con2(TokenType type, int offset, String value) {
    this._type = type;
    this._value = StringUtilities.intern(value);
    this._offset = 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 (not `null`)
   */
  String get lexeme => _value;

  /**
   * Return the next token in the token stream.
   *
   * @return the next token in the token stream
   */
  Token get next => _next;

  /**
   * Return the offset from the beginning of the file to the first character in the token.
   *
   * @return the offset from the beginning of the file to the first character in the token
   */
  int get offset => _offset;

  /**
   * Return the previous token in the token stream.
   *
   * @return the previous token in the token stream
   */
  Token get previous => _previous;

  /**
   * Answer the token type for the receiver.
   *
   * @return the token type (not `null`)
   */
  TokenType get type => _type;

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

  /**
   * 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;
  }
  String toString() => lexeme;

  /**
   * Set the previous token in the token stream to the given token.
   *
   * @param previous the previous token in the token stream
   */
  void set previous(Token previous2) {
    this._previous = previous2;
  }
}
/**
 * Instances of `HtmlParseResult` hold the result of parsing an HTML file.
 *
 * @coverage dart.engine.html
 */
class HtmlParseResult extends HtmlScanResult {

  /**
   * The unit containing the parsed information (not `null`).
   */
  HtmlUnit _unit;
  HtmlParseResult(int modificationTime, Token token, List<int> lineStarts, HtmlUnit unit) : super(modificationTime, token, lineStarts) {
    this._unit = unit;
  }

  /**
   * Answer the unit generated by parsing the source
   *
   * @return the unit (not `null`)
   */
  HtmlUnit get htmlUnit => _unit;
}
/**
 * Instances of the class `RecursiveXmlVisitor` implement an XML visitor that will recursively
 * visit all of the nodes in an XML structure. For example, using an instance of this class to visit
 * a [XmlTagNode] will also cause all of the contained [XmlAttributeNode]s and
 * [XmlTagNode]s to be visited.
 *
 * Subclasses that override a visit method must either invoke the overridden visit method or must
 * explicitly ask the visited node to visit its children. Failure to do so will cause the children
 * of the visited node to not be visited.
 *
 * @coverage dart.engine.html
 */
class RecursiveXmlVisitor<R> implements XmlVisitor<R> {
  R visitHtmlUnit(HtmlUnit node) {
    node.visitChildren(this);
    return null;
  }
  R visitXmlAttributeNode(XmlAttributeNode node) {
    node.visitChildren(this);
    return null;
  }
  R visitXmlTagNode(XmlTagNode node) {
    node.visitChildren(this);
    return null;
  }
}
/**
 * The abstract class `XmlNode` defines behavior common to all XML/HTML nodes.
 *
 * @coverage dart.engine.html
 */
abstract class XmlNode {

  /**
   * The parent of the node, or `null` if the node is the root of an AST structure.
   */
  XmlNode _parent;

  /**
   * Use the given visitor to visit this node.
   *
   * @param visitor the visitor that will visit this node
   * @return the value returned by the visitor as a result of visiting this node
   */
  accept(XmlVisitor visitor);

  /**
   * Return the first token included in this node's source range.
   *
   * @return the first token or `null` if none
   */
  Token get beginToken;

  /**
   * Return the offset of the character immediately following the last character of this node's
   * source range. This is equivalent to `node.getOffset() + node.getLength()`. For an html
   * unit this will be equal to the length of the unit's source.
   *
   * @return the offset of the character just past the node's source range
   */
  int get end => offset + length;

  /**
   * Return the last token included in this node's source range.
   *
   * @return the last token or `null` if none
   */
  Token get endToken;

  /**
   * 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 {
    Token beginToken = this.beginToken;
    Token endToken = this.endToken;
    if (beginToken == null || endToken == null) {
      return -1;
    }
    return endToken.offset + endToken.length - beginToken.offset;
  }

  /**
   * Return the offset from the beginning of the file to the first character in the node's source
   * range.
   *
   * @return the offset from the beginning of the file to the first character in the node's source
   *         range
   */
  int get offset {
    Token beginToken = this.beginToken;
    if (beginToken == null) {
      return -1;
    }
    return beginToken.offset;
  }

  /**
   * Return this node's parent node, or `null` if this node is the root of an AST structure.
   *
   * Note that the relationship between an AST node and its parent node may change over the lifetime
   * of a node.
   *
   * @return the parent of this node, or `null` if none
   */
  XmlNode get parent => _parent;
  String toString() {
    PrintStringWriter writer = new PrintStringWriter();
    accept(new ToSourceVisitor(writer));
    return writer.toString();
  }

  /**
   * Use the given visitor to visit all of the children of this node. The children will be visited
   * in source order.
   *
   * @param visitor the visitor that will be used to visit the children of this node
   */
  void visitChildren(XmlVisitor visitor);

  /**
   * Make this node the parent of the given child nodes.
   *
   * @param children the nodes that will become the children of this node
   * @return the nodes that were made children of this node
   */
  List becomeParentOf(List children) {
    if (children != null) {
      for (JavaIterator iter = new JavaIterator(children); iter.hasNext;) {
        XmlNode node = iter.next();
        node.parent = this;
      }
      return new List.from(children);
    }
    return children;
  }

  /**
   * Make this node the parent of the given child node.
   *
   * @param child the node that will become a child of this node
   * @return the node that was made a child of this node
   */
  XmlNode becomeParentOf2(XmlNode child) {
    if (child != null) {
      XmlNode node = child;
      node.parent = this;
    }
    return child;
  }

  /**
   * This method exists for debugging purposes only.
   */
  void appendIdentifier(JavaStringBuilder builder, XmlNode node) {
    if (node is XmlTagNode) {
      builder.append(((node as XmlTagNode)).tag.lexeme);
    } else if (node is XmlAttributeNode) {
      builder.append(((node as XmlAttributeNode)).name.lexeme);
    } else {
      builder.append("htmlUnit");
    }
  }

  /**
   * This method exists for debugging purposes only.
   */
  String buildRecursiveStructureMessage(XmlNode newParent) {
    JavaStringBuilder builder = new JavaStringBuilder();
    builder.append("Attempt to create recursive structure: ");
    XmlNode current = newParent;
    while (current != null) {
      if (current != newParent) {
        builder.append(" -> ");
      }
      if (identical(current, this)) {
        builder.appendChar(0x2A);
        appendIdentifier(builder, current);
        builder.appendChar(0x2A);
      } else {
        appendIdentifier(builder, current);
      }
      current = current.parent;
    }
    return builder.toString();
  }

  /**
   * Set the parent of this node to the given node.
   *
   * @param newParent the node that is to be made the parent of this node
   */
  void set parent(XmlNode newParent) {
    XmlNode current = newParent;
    while (current != null) {
      if (identical(current, this)) {
        AnalysisEngine.instance.logger.logError3(new IllegalArgumentException(buildRecursiveStructureMessage(newParent)));
        return;
      }
      current = current.parent;
    }
    _parent = newParent;
  }
}
/**
 * Instances of the class `SimpleXmlVisitor` implement an AST visitor that will do nothing
 * when visiting an AST node. It is intended to be a superclass for classes that use the visitor
 * pattern primarily as a dispatch mechanism (and hence don't need to recursively visit a whole
 * structure) and that only need to visit a small number of node types.
 */
class SimpleXmlVisitor<R> implements XmlVisitor<R> {
  R visitHtmlUnit(HtmlUnit htmlUnit) => null;
  R visitXmlAttributeNode(XmlAttributeNode xmlAttributeNode) => null;
  R visitXmlTagNode(XmlTagNode xmlTagNode) => null;
}
/**
 * The abstract class `AbstractScanner` implements a scanner for HTML code. Subclasses are
 * required to implement the interface used to access the characters being scanned.
 *
 * @coverage dart.engine.html
 */
abstract class AbstractScanner {
  static List<String> _NO_PASS_THROUGH_ELEMENTS = <String> [];

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

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

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

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

  /**
   * An array of element tags for which the content between tags should be consider a single token.
   */
  List<String> _passThroughElements = _NO_PASS_THROUGH_ELEMENTS;

  /**
   * Initialize a newly created scanner.
   *
   * @param source the source being scanned
   */
  AbstractScanner(Source source) {
    this._source = source;
    _tokens = new Token.con1(TokenType.EOF, -1);
    _tokens.setNext(_tokens);
    _tail = _tokens;
    recordStartOfLine();
  }

  /**
   * 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 the current offset relative to the beginning of the file. 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 source code has been scanned.
   *
   * @return the current offset of the scanner in the source
   */
  int get offset;

  /**
   * Answer the source being scanned.
   *
   * @return the source or `null` if undefined
   */
  Source get source => _source;

  /**
   * Set array of element tags for which the content between tags should be consider a single token.
   */
  void set passThroughElements(List<String> passThroughElements2) {
    this._passThroughElements = passThroughElements2 != null ? passThroughElements2 : _NO_PASS_THROUGH_ELEMENTS;
  }

  /**
   * 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() {
    scan();
    appendEofToken();
    return firstToken();
  }

  /**
   * 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 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 character 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();

  /**
   * Record the fact that we are at the beginning of a new line in the source.
   */
  void recordStartOfLine() {
    _lineStarts.add(offset);
  }
  void appendEofToken() {
    Token eofToken = new Token.con1(TokenType.EOF, offset);
    eofToken.setNext(eofToken);
    _tail = _tail.setNext(eofToken);
  }
  Token emit(Token token) {
    _tail.setNext(token);
    _tail = token;
    return token;
  }
  Token emit2(TokenType type, int start) => emit(new Token.con1(type, start));
  Token emit3(TokenType type, int start, int count) => emit(new Token.con2(type, start, getString(start, count)));
  Token firstToken() => _tokens.next;
  int recordStartOfLineAndAdvance(int c) {
    if (c == 0xD) {
      c = advance();
      if (c == 0xA) {
        c = advance();
      }
      recordStartOfLine();
    } else if (c == 0xA) {
      c = advance();
      recordStartOfLine();
    } else {
      c = advance();
    }
    return c;
  }
  void scan() {
    bool inBrackets = false;
    String endPassThrough = null;
    int c = advance();
    while (c >= 0) {
      int start = offset;
      if (c == 0x3C) {
        c = advance();
        if (c == 0x21) {
          c = advance();
          if (c == 0x2D && peek() == 0x2D) {
            c = advance();
            int dashCount = 1;
            while (c >= 0) {
              if (c == 0x2D) {
                dashCount++;
              } else if (c == 0x3E && dashCount >= 2) {
                c = advance();
                break;
              } else {
                dashCount = 0;
              }
              c = recordStartOfLineAndAdvance(c);
            }
            emit3(TokenType.COMMENT, start, -1);
            if (_tail.length < 7) {
            }
          } else {
            while (c >= 0) {
              if (c == 0x3E) {
                c = advance();
                break;
              }
              c = recordStartOfLineAndAdvance(c);
            }
            emit3(TokenType.DECLARATION, start, -1);
            if (!_tail.lexeme.endsWith(">")) {
            }
          }
        } else if (c == 0x3F) {
          while (c >= 0) {
            if (c == 0x3F) {
              c = advance();
              if (c == 0x3E) {
                c = advance();
                break;
              }
            } else {
              c = recordStartOfLineAndAdvance(c);
            }
          }
          emit3(TokenType.DIRECTIVE, start, -1);
          if (_tail.length < 4) {
          }
        } else if (c == 0x2F) {
          emit2(TokenType.LT_SLASH, start);
          inBrackets = true;
          c = advance();
        } else {
          inBrackets = true;
          emit2(TokenType.LT, start);
          while (Character.isWhitespace(c)) {
            c = recordStartOfLineAndAdvance(c);
          }
          if (Character.isLetterOrDigit(c)) {
            int tagStart = offset;
            c = advance();
            while (Character.isLetterOrDigit(c) || c == 0x2D || c == 0x5F) {
              c = advance();
            }
            emit3(TokenType.TAG, tagStart, -1);
            String tag = _tail.lexeme;
            for (String str in _passThroughElements) {
              if (str == tag) {
                endPassThrough = "</${str}>";
                break;
              }
            }
          }
        }
      } else if (c == 0x3E) {
        emit2(TokenType.GT, start);
        inBrackets = false;
        c = advance();
        if (endPassThrough != null) {
          bool endFound = false;
          int len = endPassThrough.length;
          int firstC = endPassThrough.codeUnitAt(0);
          int index = 0;
          int nextC = firstC;
          while (c >= 0) {
            if (c == nextC) {
              index++;
              if (index == len) {
                endFound = true;
                break;
              }
              nextC = endPassThrough.codeUnitAt(index);
            } else if (c == firstC) {
              index = 1;
              nextC = endPassThrough.codeUnitAt(1);
            } else {
              index = 0;
              nextC = firstC;
            }
            c = recordStartOfLineAndAdvance(c);
          }
          if (start + 1 < offset) {
            if (endFound) {
              emit3(TokenType.TEXT, start + 1, -len);
              emit2(TokenType.LT_SLASH, offset - len + 1);
              emit3(TokenType.TAG, offset - len + 3, -1);
            } else {
              emit3(TokenType.TEXT, start + 1, -1);
            }
          }
          endPassThrough = null;
        }
      } else if (c == 0x2F && peek() == 0x3E) {
        advance();
        emit2(TokenType.SLASH_GT, start);
        inBrackets = false;
        c = advance();
      } else if (!inBrackets) {
        c = recordStartOfLineAndAdvance(c);
        while (c != 0x3C && c >= 0) {
          c = recordStartOfLineAndAdvance(c);
        }
        emit3(TokenType.TEXT, start, -1);
      } else if (c == 0x22 || c == 0x27) {
        int endQuote = c;
        c = advance();
        while (c >= 0) {
          if (c == endQuote) {
            c = advance();
            break;
          }
          c = recordStartOfLineAndAdvance(c);
        }
        emit3(TokenType.STRING, start, -1);
      } else if (c == 0x3D) {
        emit2(TokenType.EQ, start);
        c = advance();
      } else if (Character.isWhitespace(c)) {
        do {
          c = recordStartOfLineAndAdvance(c);
        } while (Character.isWhitespace(c));
      } else if (Character.isLetterOrDigit(c)) {
        c = advance();
        while (Character.isLetterOrDigit(c) || c == 0x2D || c == 0x5F) {
          c = advance();
        }
        emit3(TokenType.TAG, start, -1);
      } else {
        emit3(TokenType.TEXT, start, 0);
        c = advance();
      }
    }
  }
}
/**
 * Instances of `HtmlScanResult` hold the result of scanning an HTML file.
 *
 * @coverage dart.engine.html
 */
class HtmlScanResult {

  /**
   * The time at which the contents of the source were last set.
   */
  int _modificationTime = 0;

  /**
   * The first token in the token stream (not `null`).
   */
  Token _token;

  /**
   * The line start information that was produced.
   */
  List<int> _lineStarts;
  HtmlScanResult(int modificationTime, Token token, List<int> lineStarts) {
    this._modificationTime = modificationTime;
    this._token = token;
    this._lineStarts = lineStarts;
  }

  /**
   * Answer the line start information that was produced.
   *
   * @return an array of line starts (not `null`)
   */
  List<int> get lineStarts => _lineStarts;

  /**
   * Return the time at which the contents of the source were last set.
   *
   * @return the time at which the contents of the source were last set
   */
  int get modificationTime => _modificationTime;

  /**
   * Answer the first token in the token stream.
   *
   * @return the token (not `null`)
   */
  Token get token => _token;
}
/**
 * Instances of the class `StringScanner` implement a scanner that reads from a string. The
 * scanning logic is in the superclass.
 *
 * @coverage dart.engine.html
 */
class StringScanner extends AbstractScanner {

  /**
   * The string from which characters will be read.
   */
  String _string;

  /**
   * 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 scanner to scan the characters in the given string.
   *
   * @param source the source being scanned
   * @param string the string from which characters will be read
   */
  StringScanner(Source source, String string) : super(source) {
    this._string = string;
    this._stringLength = string.length;
    this._charOffset = -1;
  }
  int get offset => _charOffset;
  void set offset(int offset2) {
    _charOffset = offset2;
  }
  int advance() {
    if (++_charOffset < _stringLength) {
      return _string.codeUnitAt(_charOffset);
    }
    _charOffset = _stringLength;
    return -1;
  }
  String getString(int start, int endDelta) => _string.substring(start, _charOffset + 1 + endDelta);
  int peek() {
    if (_charOffset + 1 < _stringLength) {
      return _string.codeUnitAt(_charOffset + 1);
    }
    return -1;
  }
}
/**
 * Instances of the class `CharBufferScanner` implement a scanner that reads from a character
 * buffer. The scanning logic is in the superclass.
 *
 * @coverage dart.engine.html
 */
class CharBufferScanner extends AbstractScanner {

  /**
   * The buffer from which characters will be read.
   */
  CharSequence _buffer;

  /**
   * The number of characters in the buffer.
   */
  int _bufferLength = 0;

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

  /**
   * Initialize a newly created scanner to scan the characters in the given character buffer.
   *
   * @param source the source being scanned
   * @param buffer the buffer from which characters will be read
   */
  CharBufferScanner(Source source, CharSequence buffer) : super(source) {
    this._buffer = buffer;
    this._bufferLength = buffer.length();
    this._charOffset = -1;
  }
  int get offset => _charOffset;
  int advance() {
    if (++_charOffset < _bufferLength) {
      return _buffer.charAt(_charOffset);
    }
    _charOffset = _bufferLength;
    return -1;
  }
  String getString(int start, int endDelta) => _buffer.subSequence(start, _charOffset + 1 + endDelta).toString();
  int peek() {
    if (_charOffset + 1 < _bufferLength) {
      return _buffer.charAt(_charOffset + 1);
    }
    return -1;
  }
}
/**
 * Instances of the class `ToSourceVisitor` write a source representation of a visited XML
 * node (and all of it's children) to a writer.
 *
 * @coverage dart.engine.html
 */
class ToSourceVisitor implements XmlVisitor<Object> {

  /**
   * The writer to which the source is to be written.
   */
  PrintWriter _writer;

  /**
   * 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
   */
  ToSourceVisitor(PrintWriter writer) {
    this._writer = writer;
  }
  Object visitHtmlUnit(HtmlUnit node) {
    for (XmlTagNode child in node.tagNodes) {
      visit(child);
    }
    return null;
  }
  Object visitXmlAttributeNode(XmlAttributeNode node) {
    String name = node.name.lexeme;
    Token value = node.value;
    if (name.length == 0) {
      _writer.print("__");
    } else {
      _writer.print(name);
    }
    _writer.print("=");
    if (value == null) {
      _writer.print("__");
    } else {
      _writer.print(value.lexeme);
    }
    return null;
  }
  Object visitXmlTagNode(XmlTagNode node) {
    _writer.print("<");
    String tagName = node.tag.lexeme;
    _writer.print(tagName);
    for (XmlAttributeNode attribute in node.attributes) {
      _writer.print(" ");
      visit(attribute);
    }
    _writer.print(node.attributeEnd.lexeme);
    if (node.closingTag != null) {
      for (XmlTagNode child in node.tagNodes) {
        visit(child);
      }
      _writer.print("</");
      _writer.print(tagName);
      _writer.print(">");
    }
    return null;
  }

  /**
   * Safely visit the given node.
   *
   * @param node the node to be visited
   */
  void visit(XmlNode node) {
    if (node != null) {
      node.accept(this);
    }
  }
}
/**
 * The enumeration `TokenType` defines the types of tokens that can be returned by the
 * scanner.
 *
 * @coverage dart.engine.html
 */
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, "");
  static final TokenType EQ = new TokenType('EQ', 1, "=");
  static final TokenType GT = new TokenType('GT', 2, ">");
  static final TokenType LT_SLASH = new TokenType('LT_SLASH', 3, "</");
  static final TokenType LT = new TokenType('LT', 4, "<");
  static final TokenType SLASH_GT = new TokenType('SLASH_GT', 5, "/>");
  static final TokenType COMMENT = new TokenType('COMMENT', 6, null);
  static final TokenType DECLARATION = new TokenType('DECLARATION', 7, null);
  static final TokenType DIRECTIVE = new TokenType('DIRECTIVE', 8, null);
  static final TokenType STRING = new TokenType('STRING', 9, null);
  static final TokenType TAG = new TokenType('TAG', 10, null);
  static final TokenType TEXT = new TokenType('TEXT', 11, null);
  static final List<TokenType> values = [
      EOF,
      EQ,
      GT,
      LT_SLASH,
      LT,
      SLASH_GT,
      COMMENT,
      DECLARATION,
      DIRECTIVE,
      STRING,
      TAG,
      TEXT];

  /**
   * 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(String name, int ordinal, String lexeme) : super(name, ordinal) {
    this._lexeme = lexeme;
  }

  /**
   * Return the lexeme that defines this type of token, or `null` if there is more than one
   * possible lexeme for this type of token.
   *
   * @return the lexeme that defines this type of token
   */
  String get lexeme => _lexeme;
}
class TokenType_EOF extends TokenType {
  TokenType_EOF(String name, int ordinal, String arg0) : super(name, ordinal, arg0);
  String toString() => "-eof-";
}
/**
 * Instances of `XmlAttributeNode` represent name/value pairs owned by an [XmlTagNode].
 *
 * @coverage dart.engine.html
 */
class XmlAttributeNode extends XmlNode {
  Token _name;
  Token _equals;
  Token _value;

  /**
   * Construct a new instance representing an XML attribute.
   *
   * @param name the name token (not `null`). This may be a zero length token if the attribute
   *          is badly formed.
   * @param equals the equals sign or `null` if none
   * @param value the value token (not `null`)
   */
  XmlAttributeNode(Token name, Token equals, Token value) {
    this._name = name;
    this._equals = equals;
    this._value = value;
  }
  accept(XmlVisitor visitor) => visitor.visitXmlAttributeNode(this);
  Token get beginToken => _name;
  Token get endToken => _value;

  /**
   * Answer the equals sign token that appears between the name and value tokens. This may be
   * `null` if the attribute is badly formed.
   *
   * @return the token or `null` if there is no equals sign between the name and value
   */
  Token get equals => _equals;

  /**
   * Answer the attribute name. This may be a zero length token if the attribute is badly formed.
   *
   * @return the name (not `null`)
   */
  Token get name => _name;

  /**
   * Answer the lexeme for the value token without the leading and trailing quotes.
   *
   * @return the text or `null` if the value is not specified
   */
  String get text {
    if (_value == null) {
      return null;
    }
    String text = _value.lexeme;
    int len = text.length;
    if (len > 0) {
      if (text.codeUnitAt(0) == 0x22) {
        if (len > 1 && text.codeUnitAt(len - 1) == 0x22) {
          return text.substring(1, len - 1);
        } else {
          return text.substring(1);
        }
      } else if (text.codeUnitAt(0) == 0x27) {
        if (len > 1 && text.codeUnitAt(len - 1) == 0x27) {
          return text.substring(1, len - 1);
        } else {
          return text.substring(1);
        }
      }
    }
    return text;
  }

  /**
   * Answer the attribute value. A properly formed value will start and end with matching quote
   * characters, but the value returned may not be properly formed.
   *
   * @return the value or `null` if this represents a badly formed attribute
   */
  Token get value => _value;
  void visitChildren(XmlVisitor visitor) {
  }
}
/**
 * The interface `XmlVisitor` defines the behavior of objects that can be used to visit an
 * [XmlNode] structure.
 *
 * @coverage dart.engine.html
 */
abstract class XmlVisitor<R> {
  R visitHtmlUnit(HtmlUnit htmlUnit);
  R visitXmlAttributeNode(XmlAttributeNode xmlAttributeNode);
  R visitXmlTagNode(XmlTagNode xmlTagNode);
}
/**
 * Instances of `HtmlScanner` receive and scan HTML content from a [Source].<br/>
 * For example, the following code scans HTML source and returns the result:
 *
 * <pre>
 *   HtmlScanner scanner = new HtmlScanner(source);
 *   source.getContents(scanner);
 *   return scanner.getResult();
 * </pre>
 *
 * @coverage dart.engine.html
 */
class HtmlScanner implements Source_ContentReceiver {
  List<String> _SCRIPT_TAG = <String> ["script"];

  /**
   * The source being scanned (not `null`)
   */
  Source _source;

  /**
   * The time at which the contents of the source were last set.
   */
  int _modificationTime = 0;

  /**
   * The scanner used to scan the source
   */
  AbstractScanner _scanner;

  /**
   * The first token in the token stream.
   */
  Token _token;

  /**
   * Construct a new instance to scan the specified source.
   *
   * @param source the source to be scanned (not `null`)
   */
  HtmlScanner(Source source) {
    this._source = source;
  }
  void accept(CharBuffer contents, int modificationTime2) {
    this._modificationTime = modificationTime2;
    _scanner = new CharBufferScanner(_source, contents);
    _scanner.passThroughElements = _SCRIPT_TAG;
    _token = _scanner.tokenize();
  }
  void accept2(String contents, int modificationTime2) {
    this._modificationTime = modificationTime2;
    _scanner = new StringScanner(_source, contents);
    _scanner.passThroughElements = _SCRIPT_TAG;
    _token = _scanner.tokenize();
  }

  /**
   * Answer the result of scanning the source
   *
   * @return the result (not `null`)
   */
  HtmlScanResult get result => new HtmlScanResult(_modificationTime, _token, _scanner.lineStarts);
}
/**
 * Instances of the class `XmlParser` are used to parse tokens into a AST structure comprised
 * of [XmlNode]s.
 *
 * @coverage dart.engine.html
 */
class XmlParser {

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

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

  /**
   * Construct a parser for the specified source.
   *
   * @param source the source being parsed
   */
  XmlParser(Source source) {
    this._source = source;
  }

  /**
   * Answer the source being parsed.
   *
   * @return the source
   */
  Source get source => _source;

  /**
   * Answer `true` if the specified tag is self closing and thus should never have content or
   * child tag nodes.
   *
   * @param tag the tag (not `null`)
   * @return `true` if self closing
   */
  bool isSelfClosing(Token tag) => false;

  /**
   * Parse the entire token stream and in the process, advance the current token to the end of the
   * token stream.
   *
   * @return the list of tag nodes found (not `null`, contains no `null`)
   */
  List<XmlTagNode> parseTopTagNodes(Token firstToken) {
    _currentToken = firstToken;
    List<XmlTagNode> tagNodes = new List<XmlTagNode>();
    while (true) {
      while (true) {
        if (_currentToken.type == TokenType.LT) {
          tagNodes.add(parseTagNode());
        } else if (_currentToken.type == TokenType.DECLARATION || _currentToken.type == TokenType.DIRECTIVE || _currentToken.type == TokenType.COMMENT) {
          _currentToken = _currentToken.next;
        } else if (_currentToken.type == TokenType.EOF) {
          return tagNodes;
        } else {
          reportUnexpectedToken();
          _currentToken = _currentToken.next;
        }
        break;
      }
    }
  }

  /**
   * Answer the current token.
   *
   * @return the current token
   */
  Token get currentToken => _currentToken;

  /**
   * Insert a synthetic token of the specified type before the current token
   *
   * @param type the type of token to be inserted (not `null`)
   * @return the synthetic token that was inserted (not `null`)
   */
  Token insertSyntheticToken(TokenType type) {
    Token token = new Token.con2(type, _currentToken.offset, "");
    _currentToken.previous.setNext(token);
    token.setNext(_currentToken);
    return token;
  }

  /**
   * Parse the token stream for an attribute. This method advances the current token over the
   * attribute, but should not be called if the [currentToken] is not [TokenType#TAG].
   *
   * @return the attribute (not `null`)
   */
  XmlAttributeNode parseAttribute() {
    Token name = _currentToken;
    _currentToken = _currentToken.next;
    Token equals;
    if (identical(_currentToken.type, TokenType.EQ)) {
      equals = _currentToken;
      _currentToken = _currentToken.next;
    } else {
      reportUnexpectedToken();
      equals = insertSyntheticToken(TokenType.EQ);
    }
    Token value;
    if (identical(_currentToken.type, TokenType.STRING)) {
      value = _currentToken;
      _currentToken = _currentToken.next;
    } else {
      reportUnexpectedToken();
      value = insertSyntheticToken(TokenType.STRING);
    }
    return new XmlAttributeNode(name, equals, value);
  }

  /**
   * Parse the stream for a sequence of attributes. This method advances the current token to the
   * next [TokenType#GT], [TokenType#SLASH_GT], or [TokenType#EOF].
   *
   * @return a collection of zero or more attributes (not `null`, contains no `null`s)
   */
  List<XmlAttributeNode> parseAttributes() {
    TokenType type = _currentToken.type;
    if (identical(type, TokenType.GT) || identical(type, TokenType.SLASH_GT) || identical(type, TokenType.EOF)) {
      return XmlTagNode.NO_ATTRIBUTES;
    }
    List<XmlAttributeNode> attributes = new List<XmlAttributeNode>();
    while (true) {
      while (true) {
        if (_currentToken.type == TokenType.GT || _currentToken.type == TokenType.SLASH_GT || _currentToken.type == TokenType.EOF) {
          return attributes;
        } else if (_currentToken.type == TokenType.TAG) {
          attributes.add(parseAttribute());
        } else {
          reportUnexpectedToken();
          _currentToken = _currentToken.next;
        }
        break;
      }
    }
  }

  /**
   * Parse the stream for a sequence of tag nodes existing within a parent tag node. This method
   * advances the current token to the next [TokenType#LT_SLASH] or [TokenType#EOF].
   *
   * @return a list of nodes (not `null`, contains no `null`s)
   */
  List<XmlTagNode> parseChildTagNodes() {
    TokenType type = _currentToken.type;
    if (identical(type, TokenType.LT_SLASH) || identical(type, TokenType.EOF)) {
      return XmlTagNode.NO_TAG_NODES;
    }
    List<XmlTagNode> nodes = new List<XmlTagNode>();
    while (true) {
      while (true) {
        if (_currentToken.type == TokenType.LT) {
          nodes.add(parseTagNode());
        } else if (_currentToken.type == TokenType.LT_SLASH || _currentToken.type == TokenType.EOF) {
          return nodes;
        } else if (_currentToken.type == TokenType.COMMENT) {
          _currentToken = _currentToken.next;
        } else {
          reportUnexpectedToken();
          _currentToken = _currentToken.next;
        }
        break;
      }
    }
  }

  /**
   * Parse the token stream for the next tag node. This method advances current token over the
   * parsed tag node, but should only be called if the current token is [TokenType#LT]
   *
   * @return the tag node or `null` if none found
   */
  XmlTagNode parseTagNode() {
    Token nodeStart = _currentToken;
    _currentToken = _currentToken.next;
    Token tag;
    if (identical(_currentToken.type, TokenType.TAG)) {
      tag = _currentToken;
      _currentToken = _currentToken.next;
    } else {
      reportUnexpectedToken();
      tag = insertSyntheticToken(TokenType.TAG);
    }
    List<XmlAttributeNode> attributes = parseAttributes();
    Token attributeEnd;
    if (identical(_currentToken.type, TokenType.GT) || identical(_currentToken.type, TokenType.SLASH_GT)) {
      attributeEnd = _currentToken;
      _currentToken = _currentToken.next;
    } else {
      reportUnexpectedToken();
      attributeEnd = insertSyntheticToken(TokenType.SLASH_GT);
    }
    if (identical(attributeEnd.type, TokenType.SLASH_GT) || isSelfClosing(tag)) {
      return new XmlTagNode(nodeStart, tag, attributes, attributeEnd, XmlTagNode.NO_TAG_NODES, _currentToken, null, attributeEnd);
    }
    List<XmlTagNode> tagNodes = parseChildTagNodes();
    Token contentEnd;
    if (identical(_currentToken.type, TokenType.LT_SLASH)) {
      contentEnd = _currentToken;
      _currentToken = _currentToken.next;
    } else {
      reportUnexpectedToken();
      contentEnd = insertSyntheticToken(TokenType.LT_SLASH);
    }
    Token closingTag;
    if (identical(_currentToken.type, TokenType.TAG)) {
      closingTag = _currentToken;
      _currentToken = _currentToken.next;
    } else {
      reportUnexpectedToken();
      closingTag = insertSyntheticToken(TokenType.TAG);
    }
    Token nodeEnd;
    if (identical(_currentToken.type, TokenType.GT)) {
      nodeEnd = _currentToken;
      _currentToken = _currentToken.next;
    } else {
      reportUnexpectedToken();
      nodeEnd = insertSyntheticToken(TokenType.GT);
    }
    return new XmlTagNode(nodeStart, tag, attributes, attributeEnd, tagNodes, contentEnd, closingTag, nodeEnd);
  }

  /**
   * Report the current token as unexpected
   */
  void reportUnexpectedToken() {
  }
}
/**
 * Instances of `XmlTagNode` represent XML or HTML elements such as `` and
 * `<body foo="bar"> ... </body>`.
 *
 * @coverage dart.engine.html
 */
class XmlTagNode extends XmlNode {

  /**
   * Constant representing empty list of attributes.
   */
  static List<XmlAttributeNode> NO_ATTRIBUTES = new UnmodifiableListView(new List<XmlAttributeNode>());

  /**
   * Constant representing empty list of tag nodes.
   */
  static List<XmlTagNode> NO_TAG_NODES = new UnmodifiableListView(new List<XmlTagNode>());

  /**
   * The starting [TokenType#LT] token (not `null`).
   */
  Token _nodeStart;

  /**
   * The [TokenType#TAG] token after the starting '&lt;' (not `null`).
   */
  Token _tag;

  /**
   * The attributes contained by the receiver (not `null`, contains no `null`s).
   */
  List<XmlAttributeNode> _attributes;

  /**
   * The [TokenType#GT] or [TokenType#SLASH_GT] token after the attributes (not
   * `null`). The token may be the same token as [nodeEnd] if there are no child
   * [tagNodes].
   */
  Token _attributeEnd;

  /**
   * The tag nodes contained in the receiver (not `null`, contains no `null`s).
   */
  List<XmlTagNode> _tagNodes;

  /**
   * The token (not `null`) after the content, which may be
   *
   * * (1) [TokenType#LT_SLASH] for nodes with open and close tags, or
   * * (2) the [TokenType#LT] nodeStart of the next sibling node if this node is self
   * closing or the attributeEnd is [TokenType#SLASH_GT], or
   * * (3) [TokenType#EOF] if the node does not have a closing tag and is the last node in
   * the stream [TokenType#LT_SLASH] token after the content, or `null` if there is no
   * content and the attributes ended with [TokenType#SLASH_GT].
   *
   */
  Token _contentEnd;

  /**
   * The closing [TokenType#TAG] after the child elements or `null` if there is no
   * content and the attributes ended with [TokenType#SLASH_GT]
   */
  Token _closingTag;

  /**
   * The ending [TokenType#GT] or [TokenType#SLASH_GT] token (not `null`).
   */
  Token _nodeEnd;

  /**
   * Construct a new instance representing an XML or HTML element
   *
   * @param nodeStart the starting [TokenType#LT] token (not `null`)
   * @param tag the [TokenType#TAG] token after the starting '&lt;' (not `null`).
   * @param attributes the attributes associated with this element or [NO_ATTRIBUTES] (not
   *          `null`, contains no `null`s)
   * @param attributeEnd The [TokenType#GT] or [TokenType#SLASH_GT] token after the
   *          attributes (not `null`). The token may be the same token as [nodeEnd] if
   *          there are no child [tagNodes].
   * @param tagNodes child tag nodes of the receiver or [NO_TAG_NODES] (not `null`,
   *          contains no `null`s)
   * @param contentEnd the token (not `null`) after the content, which may be
   *
   *          * (1) [TokenType#LT_SLASH] for nodes with open and close tags, or
   *          * (2) the [TokenType#LT] nodeStart of the next sibling node if this node is
   *          self closing or the attributeEnd is [TokenType#SLASH_GT], or
   *          * (3) [TokenType#EOF] if the node does not have a closing tag and is the last
   *          node in the stream [TokenType#LT_SLASH] token after the content, or `null`
   *          if there is no content and the attributes ended with [TokenType#SLASH_GT].
   *
   * @param closingTag the closing [TokenType#TAG] after the child elements or `null` if
   *          there is no content and the attributes ended with [TokenType#SLASH_GT]
   * @param nodeEnd the ending [TokenType#GT] or [TokenType#SLASH_GT] token (not
   *          `null`)
   */
  XmlTagNode(Token nodeStart, Token tag, List<XmlAttributeNode> attributes, Token attributeEnd, List<XmlTagNode> tagNodes, Token contentEnd, Token closingTag, Token nodeEnd) {
    this._nodeStart = nodeStart;
    this._tag = tag;
    this._attributes = becomeParentOfEmpty(attributes, NO_ATTRIBUTES);
    this._attributeEnd = attributeEnd;
    this._tagNodes = becomeParentOfEmpty(tagNodes, NO_TAG_NODES);
    this._contentEnd = contentEnd;
    this._closingTag = closingTag;
    this._nodeEnd = nodeEnd;
  }
  accept(XmlVisitor visitor) => visitor.visitXmlTagNode(this);

  /**
   * Answer the attribute with the specified name.
   *
   * @param name the attribute name
   * @return the attribute or `null` if no matching attribute is found
   */
  XmlAttributeNode getAttribute(String name2) {
    for (XmlAttributeNode attribute in _attributes) {
      if (attribute.name.lexeme == name2) {
        return attribute;
      }
    }
    return null;
  }

  /**
   * The [TokenType#GT] or [TokenType#SLASH_GT] token after the attributes (not
   * `null`). The token may be the same token as [nodeEnd] if there are no child
   * [tagNodes].
   *
   * @return the token (not `null`)
   */
  Token get attributeEnd => _attributeEnd;

  /**
   * Answer the receiver's attributes. Callers should not manipulate the returned list to edit the
   * AST structure.
   *
   * @return the attributes (not `null`, contains no `null`s)
   */
  List<XmlAttributeNode> get attributes => _attributes;

  /**
   * Find the attribute with the given name (see [getAttribute] and answer the lexeme
   * for the attribute's value token without the leading and trailing quotes (see
   * [XmlAttributeNode#getText]).
   *
   * @param name the attribute name
   * @return the attribute text or `null` if no matching attribute is found
   */
  String getAttributeText(String name) {
    XmlAttributeNode attribute = getAttribute(name);
    return attribute != null ? attribute.text : null;
  }
  Token get beginToken => _nodeStart;

  /**
   * The the closing [TokenType#TAG] after the child elements or `null` if there is no
   * content and the attributes ended with [TokenType#SLASH_GT]
   *
   * @return the closing tag or `null`
   */
  Token get closingTag => _closingTag;

  /**
   * Answer a string representing the content contained in the receiver. This includes the textual
   * representation of any child tag nodes ([getTagNodes]). Whitespace between '&lt;',
   * '&lt;/', and '>', '/>' is discarded, but all other whitespace is preserved.
   *
   * @return the content (not `null`)
   */
  String get content {
    Token token = _attributeEnd.next;
    if (identical(token, _contentEnd)) {
      return "";
    }
    String content = token.lexeme;
    token = token.next;
    if (identical(token, _contentEnd)) {
      return content;
    }
    JavaStringBuilder buffer = new JavaStringBuilder();
    while (token != _contentEnd) {
      buffer.append(token.lexeme);
      token = token.next;
    }
    return buffer.toString();
  }

  /**
   * Answer the token (not `null`) after the content, which may be
   *
   * * (1) [TokenType#LT_SLASH] for nodes with open and close tags, or
   * * (2) the [TokenType#LT] nodeStart of the next sibling node if this node is self
   * closing or the attributeEnd is [TokenType#SLASH_GT], or
   * * (3) [TokenType#EOF] if the node does not have a closing tag and is the last node in
   * the stream [TokenType#LT_SLASH] token after the content, or `null` if there is no
   * content and the attributes ended with [TokenType#SLASH_GT].
   *
   *
   * @return the token (not `null`)
   */
  Token get contentEnd => _contentEnd;
  Token get endToken {
    if (_nodeEnd != null) {
      return _nodeEnd;
    }
    if (_closingTag != null) {
      return _closingTag;
    }
    if (_contentEnd != null) {
      return _contentEnd;
    }
    if (!_tagNodes.isEmpty) {
      return _tagNodes[_tagNodes.length - 1].endToken;
    }
    if (_attributeEnd != null) {
      return _attributeEnd;
    }
    if (!_attributes.isEmpty) {
      return _attributes[_attributes.length - 1].endToken;
    }
    return _tag;
  }

  /**
   * Answer the ending [TokenType#GT] or [TokenType#SLASH_GT] token.
   *
   * @return the token (not `null`)
   */
  Token get nodeEnd => _nodeEnd;

  /**
   * Answer the starting [TokenType#LT] token.
   *
   * @return the token (not `null`)
   */
  Token get nodeStart => _nodeStart;

  /**
   * Answer the [TokenType#TAG] token after the starting '&lt;'.
   *
   * @return the token (not `null`)
   */
  Token get tag => _tag;

  /**
   * Answer the tag nodes contained in the receiver. Callers should not manipulate the returned list
   * to edit the AST structure.
   *
   * @return the children (not `null`, contains no `null`s)
   */
  List<XmlTagNode> get tagNodes => _tagNodes;
  void visitChildren(XmlVisitor visitor) {
    for (XmlAttributeNode node in _attributes) {
      node.accept(visitor);
    }
    for (XmlTagNode node in _tagNodes) {
      node.accept(visitor);
    }
  }

  /**
   * Same as [becomeParentOf], but returns given "ifEmpty" if "children" is empty
   */
  List becomeParentOfEmpty(List children, List ifEmpty) {
    if (children != null && children.isEmpty) {
      return ifEmpty;
    }
    return becomeParentOf(children);
  }
}
/**
 * Instances of the class `HtmlParser` are used to parse tokens into a AST structure comprised
 * of [XmlNode]s.
 *
 * @coverage dart.engine.html
 */
class HtmlParser extends XmlParser {
  static Set<String> SELF_CLOSING = new Set<String>();

  /**
   * Construct a parser for the specified source.
   *
   * @param source the source being parsed
   */
  HtmlParser(Source source) : super(source);

  /**
   * Parse the tokens specified by the given scan result.
   *
   * @param scanResult the result of scanning an HTML source (not `null`)
   * @return the parse result (not `null`)
   */
  HtmlParseResult parse(HtmlScanResult scanResult) {
    Token firstToken = scanResult.token;
    List<XmlTagNode> tagNodes = parseTopTagNodes(firstToken);
    HtmlUnit unit = new HtmlUnit(firstToken, tagNodes, currentToken);
    return new HtmlParseResult(scanResult.modificationTime, firstToken, scanResult.lineStarts, unit);
  }

  /**
   * Scan then parse the specified source.
   *
   * @param source the source to be scanned and parsed (not `null`)
   * @return the parse result (not `null`)
   */
  HtmlParseResult parse2(Source source) {
    HtmlScanner scanner = new HtmlScanner(source);
    source.getContents(scanner);
    return parse(scanner.result);
  }
  bool isSelfClosing(Token tag) => SELF_CLOSING.contains(tag.lexeme);
}
/**
 * Instances of the class `HtmlUnit` represent the contents of an HTML file.
 *
 * @coverage dart.engine.html
 */
class HtmlUnit extends XmlNode {

  /**
   * The first token in the token stream that was parsed to form this HTML unit.
   */
  Token _beginToken;

  /**
   * The last token in the token stream that was parsed to form this compilation unit. This token
   * should always have a type of [TokenType.EOF].
   */
  Token _endToken;

  /**
   * The tag nodes contained in the receiver (not `null`, contains no `null`s).
   */
  List<XmlTagNode> _tagNodes;

  /**
   * The element associated with this HTML unit or `null` if the receiver is not resolved.
   */
  HtmlElementImpl _element;

  /**
   * Construct a new instance representing the content of an HTML file.
   *
   * @param beginToken the first token in the file (not `null`)
   * @param tagNodes child tag nodes of the receiver (not `null`, contains no `null`s)
   * @param endToken the last token in the token stream which should be of type
   *          [TokenType.EOF]
   */
  HtmlUnit(Token beginToken, List<XmlTagNode> tagNodes, Token endToken) {
    this._beginToken = beginToken;
    this._tagNodes = becomeParentOf(tagNodes);
    this._endToken = endToken;
  }
  accept(XmlVisitor visitor) => visitor.visitHtmlUnit(this);
  Token get beginToken => _beginToken;

  /**
   * Return the element associated with this HTML unit.
   *
   * @return the element or `null` if the receiver is not resolved
   */
  HtmlElementImpl get element => _element;
  Token get endToken => _endToken;

  /**
   * Answer the tag nodes contained in the receiver. Callers should not manipulate the returned list
   * to edit the AST structure.
   *
   * @return the children (not `null`, contains no `null`s)
   */
  List<XmlTagNode> get tagNodes => _tagNodes;

  /**
   * Set the element associated with this HTML unit.
   *
   * @param element the element
   */
  void set element(HtmlElementImpl element2) {
    this._element = element2;
  }
  void visitChildren(XmlVisitor visitor) {
    for (XmlTagNode node in _tagNodes) {
      node.accept(visitor);
    }
  }
}