// 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 'error.dart';
import 'instrumentation.dart';
import 'element.dart' show HtmlElementImpl;
/**
 * Instances of the class {@code 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 {@code null})
   * @param offset the offset from the beginning of the file to the first character in the token
   */
  Token.con1(TokenType type, int offset) {
    _jtd_constructor_155_impl(type, offset);
  }
  _jtd_constructor_155_impl(TokenType type, int offset) {
    _jtd_constructor_156_impl(type, offset, type.lexeme);
  }

  /**
   * Initialize a newly created token.
   * @param type the token type (not {@code 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 {@code null})
   */
  Token.con2(TokenType type2, int offset2, String value2) {
    _jtd_constructor_156_impl(type2, offset2, value2);
  }
  _jtd_constructor_156_impl(TokenType type2, int offset2, String value2) {
    this._type = type2;
    this._value = StringUtilities.intern(value2);
    this._offset = offset2;
  }

  /**
   * 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 {@code 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 {@code null})
   */
  TokenType get type => _type;

  /**
   * Return {@code 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 ({@code 0}).
   * @return {@code true} if this token is a synthetic token
   */
  bool 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 {@code HtmlParseResult} hold the result of parsing an HTML file.
 * @coverage dart.engine.html
 */
class HtmlParseResult extends HtmlScanResult {

  /**
   * The unit containing the parsed information (not {@code 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 {@code null})
   */
  HtmlUnit get htmlUnit => _unit;
}
/**
 * Instances of the class {@code 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 {@link XmlTagNode} will also cause all of the contained {@link XmlAttributeNode}s and{@link XmlTagNode}s to be visited.
 * <p>
 * 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 {@code XmlNode} defines behavior common to all XML/HTML nodes.
 * @coverage dart.engine.html
 */
abstract class XmlNode {

  /**
   * The parent of the node, or {@code 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 {@code 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 {@code 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 {@code 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 beginToken2 = beginToken;
    Token endToken2 = endToken;
    if (beginToken2 == null || endToken2 == null) {
      return -1;
    }
    return endToken2.offset + endToken2.length - beginToken2.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 beginToken2 = beginToken;
    if (beginToken2 == null) {
      return -1;
    }
    return beginToken.offset;
  }

  /**
   * Return this node's parent node, or {@code null} if this node is the root of an AST structure.
   * <p>
   * 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 {@code 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<Object> 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;
  }

  /**
   * 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) {
    _parent = newParent;
  }
}
/**
 * Instances of the class {@code 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 {@code 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 {@code 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;
    bool passThrough = false;
    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) {
                passThrough = true;
                break;
              }
            }
          }
        }
      } else if (c == 0x3E) {
        emit2(TokenType.GT, start);
        inBrackets = false;
        c = advance();
        if (passThrough) {
          while (c >= 0 && (c != 0x3C || peek() != 0x2F)) {
            c = recordStartOfLineAndAdvance(c);
          }
          if (start + 1 < offset) {
            emit3(TokenType.TEXT, start + 1, -1);
          }
          passThrough = false;
        }
      } 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 {@code 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 {@code 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 {@code 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 {@code null})
   */
  Token get token => _token;
}
/**
 * Instances of the class {@code 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 {@code 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 {@code 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 name2 = node.name.lexeme;
    Token value2 = node.value;
    if (name2.length == 0) {
      _writer.print("__");
    } else {
      _writer.print(name2);
    }
    _writer.print("=");
    if (value2 == null) {
      _writer.print("__");
    } else {
      _writer.print(value2.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 {@code TokenType} defines the types of tokens that can be returned by the
 * scanner.
 * @coverage dart.engine.html
 */
class TokenType implements Comparable<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 name of this enum constant, as declared in the enum declaration.
  final String name;

  /// The position in the enum declaration.
  final int ordinal;

  /**
   * The lexeme that defines this type of token, or {@code null} if there is more than one possible
   * lexeme for this type of token.
   */
  String _lexeme;
  TokenType(this.name, this.ordinal, String lexeme) {
    this._lexeme = lexeme;
  }

  /**
   * Return the lexeme that defines this type of token, or {@code 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;
  int compareTo(TokenType other) => ordinal - other.ordinal;
  String toString() => name;
}
class TokenType_EOF extends TokenType {
  TokenType_EOF(String name, int ordinal, String arg0) : super(name, ordinal, arg0);
  String toString() => "-eof-";
}
/**
 * Instances of {@code XmlAttributeNode} represent name/value pairs owned by an {@link 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 {@code null}). This may be a zero length token if the attribute
   * is badly formed.
   * @param equals the equals sign or {@code null} if none
   * @param value the value token (not {@code 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{@code null} if the attribute is badly formed.
   * @return the token or {@code 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 {@code null})
   */
  Token get name => _name;

  /**
   * Answer the lexeme for the value token without the leading and trailing quotes.
   * @return the text or {@code 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 {@code null} if this represents a badly formed attribute
   */
  Token get value => _value;
  void visitChildren(XmlVisitor<Object> visitor) {
  }
}
/**
 * The interface {@code XmlVisitor} defines the behavior of objects that can be used to visit an{@link XmlNode} structure.
 * @coverage dart.engine.html
 */
abstract class XmlVisitor<R> {
  R visitHtmlUnit(HtmlUnit htmlUnit);
  R visitXmlAttributeNode(XmlAttributeNode xmlAttributeNode);
  R visitXmlTagNode(XmlTagNode xmlTagNode);
}
/**
 * Instances of {@code HtmlScanner} receive and scan HTML content from a {@link 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 {@code 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 {@code 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 {@code null})
   */
  HtmlScanResult get result => new HtmlScanResult(_modificationTime, _token, _scanner.lineStarts);
}
/**
 * Instances of the class {@code XmlParser} are used to parse tokens into a AST structure comprised
 * of {@link 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 {@code true} if the specified tag is self closing and thus should never have content or
   * child tag nodes.
   * @param tag the tag (not {@code null})
   * @return {@code 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 {@code null}, contains no {@code 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 {@code null})
   * @return the synthetic token that was inserted (not {@code 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 {@link #currentToken} is not {@link TokenType#TAG}.
   * @return the attribute (not {@code 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 {@link TokenType#GT}, {@link TokenType#SLASH_GT}, or {@link TokenType#EOF}.
   * @return a collection of zero or more attributes (not {@code null}, contains no {@code null}s)
   */
  List<XmlAttributeNode> parseAttributes() {
    TokenType type2 = _currentToken.type;
    if (identical(type2, TokenType.GT) || identical(type2, TokenType.SLASH_GT) || identical(type2, 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 {@link TokenType#LT_SLASH} or {@link TokenType#EOF}.
   * @return a list of nodes (not {@code null}, contains no {@code null}s)
   */
  List<XmlTagNode> parseChildTagNodes() {
    TokenType type2 = _currentToken.type;
    if (identical(type2, TokenType.LT_SLASH) || identical(type2, 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 {@link TokenType#LT}
   * @return the tag node or {@code 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 {@code XmlTagNode} represent XML or HTML elements such as {@code <p>} and{@code <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 {@link TokenType#LT} token (not {@code null}).
   */
  Token _nodeStart;

  /**
   * The {@link TokenType#TAG} token after the starting '&lt;' (not {@code null}).
   */
  Token _tag;

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

  /**
   * The {@link TokenType#GT} or {@link TokenType#SLASH_GT} token after the attributes (not{@code null}). The token may be the same token as {@link #nodeEnd} if there are no child{@link #tagNodes}.
   */
  Token _attributeEnd;

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

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

  /**
   * The closing {@link TokenType#TAG} after the child elements or {@code null} if there is no
   * content and the attributes ended with {@link TokenType#SLASH_GT}
   */
  Token _closingTag;

  /**
   * The ending {@link TokenType#GT} or {@link TokenType#SLASH_GT} token (not {@code null}).
   */
  Token _nodeEnd;

  /**
   * Construct a new instance representing an XML or HTML element
   * @param nodeStart the starting {@link TokenType#LT} token (not {@code null})
   * @param tag the {@link TokenType#TAG} token after the starting '&lt;' (not {@code null}).
   * @param attributes the attributes associated with this element or {@link #NO_ATTRIBUTES} (not{@code null}, contains no {@code null}s)
   * @param attributeEnd The {@link TokenType#GT} or {@link TokenType#SLASH_GT} token after the
   * attributes (not {@code null}). The token may be the same token as {@link #nodeEnd} if
   * there are no child {@link #tagNodes}.
   * @param tagNodes child tag nodes of the receiver or {@link #NO_TAG_NODES} (not {@code null},
   * contains no {@code null}s)
   * @param contentEnd the token (not {@code null}) after the content, which may be
   * <ul>
   * <li>(1) {@link TokenType#LT_SLASH} for nodes with open and close tags, or</li>
   * <li>(2) the {@link TokenType#LT} nodeStart of the next sibling node if this node is
   * self closing or the attributeEnd is {@link TokenType#SLASH_GT}, or</li>
   * <li>(3) {@link TokenType#EOF} if the node does not have a closing tag and is the last
   * node in the stream {@link TokenType#LT_SLASH} token after the content, or {@code null}if there is no content and the attributes ended with {@link TokenType#SLASH_GT}.</li>
   * </ul>
   * @param closingTag the closing {@link TokenType#TAG} after the child elements or {@code null} if
   * there is no content and the attributes ended with {@link TokenType#SLASH_GT}
   * @param nodeEnd the ending {@link TokenType#GT} or {@link TokenType#SLASH_GT} token (not{@code 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 {@code 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 {@link TokenType#GT} or {@link TokenType#SLASH_GT} token after the attributes (not{@code null}). The token may be the same token as {@link #nodeEnd} if there are no child{@link #tagNodes}.
   * @return the token (not {@code 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 {@code null}, contains no {@code null}s)
   */
  List<XmlAttributeNode> get attributes => _attributes;

  /**
   * Find the attribute with the given name (see {@link #getAttribute(String)} and answer the lexeme
   * for the attribute's value token without the leading and trailing quotes (see{@link XmlAttributeNode#getText()}).
   * @param name the attribute name
   * @return the attribute text or {@code 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 {@link TokenType#TAG} after the child elements or {@code null} if there is no
   * content and the attributes ended with {@link TokenType#SLASH_GT}
   * @return the closing tag or {@code 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 ({@link #getTagNodes()}). Whitespace between '&lt;',
   * '&lt;/', and '>', '/>' is discarded, but all other whitespace is preserved.
   * @return the content (not {@code 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 {@code null}) after the content, which may be
   * <ul>
   * <li>(1) {@link TokenType#LT_SLASH} for nodes with open and close tags, or</li>
   * <li>(2) the {@link TokenType#LT} nodeStart of the next sibling node if this node is self
   * closing or the attributeEnd is {@link TokenType#SLASH_GT}, or</li>
   * <li>(3) {@link TokenType#EOF} if the node does not have a closing tag and is the last node in
   * the stream {@link TokenType#LT_SLASH} token after the content, or {@code null} if there is no
   * content and the attributes ended with {@link TokenType#SLASH_GT}.</li>
   * </ul>
   * @return the token (not {@code 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 {@link TokenType#GT} or {@link TokenType#SLASH_GT} token.
   * @return the token (not {@code null})
   */
  Token get nodeEnd => _nodeEnd;

  /**
   * Answer the starting {@link TokenType#LT} token.
   * @return the token (not {@code null})
   */
  Token get nodeStart => _nodeStart;

  /**
   * Answer the {@link TokenType#TAG} token after the starting '&lt;'.
   * @return the token (not {@code 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 {@code null}, contains no {@code null}s)
   */
  List<XmlTagNode> get tagNodes => _tagNodes;
  void visitChildren(XmlVisitor<Object> visitor) {
    for (XmlAttributeNode node in _attributes) {
      node.accept(visitor);
    }
    for (XmlTagNode node in _tagNodes) {
      node.accept(visitor);
    }
  }

  /**
   * Same as {@link #becomeParentOf(List)}, 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 {@code HtmlParser} are used to parse tokens into a AST structure comprised
 * of {@link 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 {@code null})
   * @return the parse result (not {@code 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 {@code null})
   * @return the parse result (not {@code 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 {@code 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 {@link TokenType.EOF}.
   */
  Token _endToken;

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

  /**
   * The element associated with this HTML unit or {@code 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 {@code null})
   * @param tagNodes child tag nodes of the receiver (not {@code null}, contains no {@code null}s)
   * @param endToken the last token in the token stream which should be of type{@link 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 {@code 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 {@code null}, contains no {@code 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<Object> visitor) {
    for (XmlTagNode node in _tagNodes) {
      node.accept(visitor);
    }
  }
}