// This code was auto-generated, is not intended to be edited, and is subject to
// significant change. Please see the README file for more information.
library engine.html;
import 'dart:collection';
import 'java_core.dart';
import 'java_engine.dart';
import 'source.dart';
import 'element.dart' show HtmlElementImpl;
import 'engine.dart' show AnalysisEngine;
/**
 * Instances of the class `Token` represent a token that was scanned from the input. Each
 * token knows which token follows it, acting as the head of a linked list of tokens.
 *
 * @coverage dart.engine.html
 */
class Token {

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

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

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

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

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

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

  /**
   * Initialize a newly created token.
   *
   * @param type the token type (not `null`)
   * @param offset the offset from the beginning of the file to the first character in the token
   * @param value the lexeme represented by this token (not `null`)
   */
  Token.con2(TokenType type, int offset, String value) {
    this.type = type;
    this.lexeme = StringUtilities.intern(value);
    this.offset = offset;
  }

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

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

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

  /**
   * Set the next token in the token stream to the given token. This has the side-effect of setting
   * this token to be the previous token for the given token.
   *
   * @param token the next token in the token stream
   * @return the token that was passed in
   */
  Token setNext(Token token) {
    next = token;
    token.previous = this;
    return token;
  }
  String toString() => lexeme;
}
/**
 * Instances of `HtmlParseResult` hold the result of parsing an HTML file.
 *
 * @coverage dart.engine.html
 */
class HtmlParseResult extends HtmlScanResult {

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

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

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

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

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

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

  /**
   * Return the number of characters in the node's source range.
   *
   * @return the number of characters in the node's source range
   */
  int get length {
    Token beginToken = this.beginToken;
    Token endToken = this.endToken;
    if (beginToken == null || endToken == null) {
      return -1;
    }
    return endToken.offset + endToken.length - beginToken.offset;
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  /**
   * Scan the source code to produce a list of tokens representing the source.
   *
   * @return the first token in the list of tokens that were produced
   */
  Token tokenize() {
    scan();
    appendEofToken();
    return firstToken();
  }

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

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

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

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

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

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

  /**
   * The line start information that was produced.
   */
  List<int> lineStarts;
  HtmlScanResult(int modificationTime, Token token, List<int> lineStarts) {
    this.modificationTime = modificationTime;
    this.token = token;
    this.lineStarts = lineStarts;
  }
}
/**
 * Instances of the class `StringScanner` implement a scanner that reads from a string. The
 * scanning logic is in the superclass.
 *
 * @coverage dart.engine.html
 */
class StringScanner extends AbstractScanner {

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

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

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

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

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

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

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

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

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

  /**
   * Initialize a newly created visitor to write source code representing the visited nodes to the
   * given writer.
   *
   * @param writer the writer to which the source is to be written
   */
  ToSourceVisitor(PrintWriter writer) {
    this._writer = writer;
  }
  Object visitHtmlUnit(HtmlUnit node) {
    for (XmlTagNode child in node.tagNodes) {
      visit(child);
    }
    return null;
  }
  Object visitXmlAttributeNode(XmlAttributeNode node) {
    String name = node.name.lexeme;
    Token value = node.value;
    if (name.length == 0) {
      _writer.print("__");
    } else {
      _writer.print(name);
    }
    _writer.print("=");
    if (value == null) {
      _writer.print("__");
    } else {
      _writer.print(value.lexeme);
    }
    return null;
  }
  Object visitXmlTagNode(XmlTagNode node) {
    _writer.print("<");
    String tagName = node.tag.lexeme;
    _writer.print(tagName);
    for (XmlAttributeNode attribute in node.attributes) {
      _writer.print(" ");
      visit(attribute);
    }
    _writer.print(node.attributeEnd.lexeme);
    if (node.closingTag != null) {
      for (XmlTagNode child in node.tagNodes) {
        visit(child);
      }
      _writer.print("</");
      _writer.print(tagName);
      _writer.print(">");
    }
    return null;
  }

  /**
   * Safely visit the given node.
   *
   * @param node the node to be visited
   */
  void visit(XmlNode node) {
    if (node != null) {
      node.accept(this);
    }
  }
}
/**
 * The enumeration `TokenType` defines the types of tokens that can be returned by the
 * scanner.
 *
 * @coverage dart.engine.html
 */
class TokenType extends Enum<TokenType> {

  /**
   * The type of the token that marks the end of the input.
   */
  static final TokenType EOF = new TokenType_EOF('EOF', 0, "");
  static final TokenType EQ = new TokenType('EQ', 1, "=");
  static final TokenType GT = new TokenType('GT', 2, ">");
  static final TokenType LT_SLASH = new TokenType('LT_SLASH', 3, "</");
  static final TokenType LT = new TokenType('LT', 4, "<");
  static final TokenType SLASH_GT = new TokenType('SLASH_GT', 5, "/>");
  static final TokenType COMMENT = new TokenType('COMMENT', 6, null);
  static final TokenType DECLARATION = new TokenType('DECLARATION', 7, null);
  static final TokenType DIRECTIVE = new TokenType('DIRECTIVE', 8, null);
  static final TokenType STRING = new TokenType('STRING', 9, null);
  static final TokenType TAG = new TokenType('TAG', 10, null);
  static final TokenType TEXT = new TokenType('TEXT', 11, null);
  static final List<TokenType> values = [
      EOF,
      EQ,
      GT,
      LT_SLASH,
      LT,
      SLASH_GT,
      COMMENT,
      DECLARATION,
      DIRECTIVE,
      STRING,
      TAG,
      TEXT];

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

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

  /**
   * Answer the lexeme for the value token without the leading and trailing quotes.
   *
   * @return the text or `null` if the value is not specified
   */
  String get text {
    if (value == null) {
      return null;
    }
    String text = value.lexeme;
    int len = text.length;
    if (len > 0) {
      if (text.codeUnitAt(0) == 0x22) {
        if (len > 1 && text.codeUnitAt(len - 1) == 0x22) {
          return text.substring(1, len - 1);
        } else {
          return text.substring(1);
        }
      } else if (text.codeUnitAt(0) == 0x27) {
        if (len > 1 && text.codeUnitAt(len - 1) == 0x27) {
          return text.substring(1, len - 1);
        } else {
          return text.substring(1);
        }
      }
    }
    return text;
  }
  void visitChildren(XmlVisitor visitor) {
  }
}
/**
 * The interface `XmlVisitor` defines the behavior of objects that can be used to visit an
 * [XmlNode] structure.
 *
 * @coverage dart.engine.html
 */
abstract class XmlVisitor<R> {
  R visitHtmlUnit(HtmlUnit htmlUnit);
  R visitXmlAttributeNode(XmlAttributeNode xmlAttributeNode);
  R visitXmlTagNode(XmlTagNode xmlTagNode);
}
/**
 * Instances of `HtmlScanner` receive and scan HTML content from a [Source].<br/>
 * For example, the following code scans HTML source and returns the result:
 *
 * <pre>
 *   HtmlScanner scanner = new HtmlScanner(source);
 *   source.getContents(scanner);
 *   return scanner.getResult();
 * </pre>
 *
 * @coverage dart.engine.html
 */
class HtmlScanner implements Source_ContentReceiver {
  List<String> _SCRIPT_TAG = <String> ["script"];

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  /**
   * Answer a string representing the content contained in the receiver. This includes the textual
   * representation of any child tag nodes ([getTagNodes]). Whitespace between '&lt;',
   * '&lt;/', and '>', '/>' is discarded, but all other whitespace is preserved.
   *
   * @return the content (not `null`)
   */
  String get content {
    Token token = attributeEnd.next;
    if (identical(token, contentEnd)) {
      return "";
    }
    String content = token.lexeme;
    token = token.next;
    if (identical(token, contentEnd)) {
      return content;
    }
    JavaStringBuilder buffer = new JavaStringBuilder();
    while (token != contentEnd) {
      buffer.append(token.lexeme);
      token = token.next;
    }
    return buffer.toString();
  }
  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;
  }
  void visitChildren(XmlVisitor visitor) {
    for (XmlAttributeNode node in attributes) {
      node.accept(visitor);
    }
    for (XmlTagNode node in tagNodes) {
      node.accept(visitor);
    }
  }

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

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

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

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

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

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

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

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

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