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

  /**
   * 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 {@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;
  int get hashCode => 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);
    }
  }
}