// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library engine.html;

import 'dart:collection';

import 'ast.dart';
import 'element.dart';
import 'engine.dart' show AnalysisOptions, AnalysisEngine;
import 'error.dart' show AnalysisErrorListener;
import 'java_core.dart';
import 'java_engine.dart';
import 'parser.dart' show Parser;
import 'scanner.dart' as sc show Scanner, SubSequenceReader, Token;
import 'source.dart';

/**
 * The abstract class `AbstractScanner` implements a scanner for HTML code. Subclasses are
 * required to implement the interface used to access the characters being scanned.
 */
abstract class AbstractScanner {
  static List<String> _NO_PASS_THROUGH_ELEMENTS = <String>[];

  /**
   * The source being scanned.
   */
  final 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(this.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> passThroughElements) {
    this._passThroughElements = passThroughElements != null
        ? passThroughElements
        : _NO_PASS_THROUGH_ELEMENTS;
  }

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

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

  void _appendEofToken() {
    Token eofToken = new Token.con1(TokenType.EOF, offset);
    // The EOF token points to itself so that there is always infinite
    // look-ahead.
    eofToken.setNext(eofToken);
    _tail = _tail.setNext(eofToken);
  }

  Token _emit(Token token) {
    _tail.setNext(token);
    _tail = token;
    return token;
  }

  Token _emitWithOffset(TokenType type, int start) =>
      _emit(new Token.con1(type, start));

  Token _emitWithOffsetAndLength(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) {
            // handle a comment
            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);
            }
            _emitWithOffsetAndLength(TokenType.COMMENT, start, -1);
            // Capture <!--> and <!---> as tokens but report an error
            if (_tail.length < 7) {
              // TODO (danrubel): Report invalid HTML comment
            }
          } else {
            // handle a declaration
            while (c >= 0) {
              if (c == 0x3E) {
                c = advance();
                break;
              }
              c = _recordStartOfLineAndAdvance(c);
            }
            _emitWithOffsetAndLength(TokenType.DECLARATION, start, -1);
            if (!StringUtilities.endsWithChar(_tail.lexeme, 0x3E)) {
              // TODO (danrubel): Report missing '>' in directive
            }
          }
        } else if (c == 0x3F) {
          // handle a directive
          while (c >= 0) {
            if (c == 0x3F) {
              c = advance();
              if (c == 0x3E) {
                c = advance();
                break;
              }
            } else {
              c = _recordStartOfLineAndAdvance(c);
            }
          }
          _emitWithOffsetAndLength(TokenType.DIRECTIVE, start, -1);
          if (_tail.length < 4) {
            // TODO (danrubel): Report invalid directive
          }
        } else if (c == 0x2F) {
          _emitWithOffset(TokenType.LT_SLASH, start);
          inBrackets = true;
          c = advance();
        } else {
          inBrackets = true;
          _emitWithOffset(TokenType.LT, start);
          // ignore whitespace in braces
          while (Character.isWhitespace(c)) {
            c = _recordStartOfLineAndAdvance(c);
          }
          // get tag
          if (Character.isLetterOrDigit(c)) {
            int tagStart = offset;
            c = advance();
            while (Character.isLetterOrDigit(c) || c == 0x2D || c == 0x5F) {
              c = advance();
            }
            _emitWithOffsetAndLength(TokenType.TAG, tagStart, -1);
            // check tag against passThrough elements
            String tag = _tail.lexeme;
            for (String str in _passThroughElements) {
              if (str == tag) {
                endPassThrough = "</$str>";
                break;
              }
            }
          }
        }
      } else if (c == 0x3E) {
        _emitWithOffset(TokenType.GT, start);
        inBrackets = false;
        c = advance();
        // if passThrough != null, read until we match it
        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) {
              _emitWithOffsetAndLength(TokenType.TEXT, start + 1, -len);
              _emitWithOffset(TokenType.LT_SLASH, offset - len + 1);
              _emitWithOffsetAndLength(TokenType.TAG, offset - len + 3, -1);
            } else {
              _emitWithOffsetAndLength(TokenType.TEXT, start + 1, -1);
            }
          }
          endPassThrough = null;
        }
      } else if (c == 0x2F && peek() == 0x3E) {
        advance();
        _emitWithOffset(TokenType.SLASH_GT, start);
        inBrackets = false;
        c = advance();
      } else if (!inBrackets) {
        c = _recordStartOfLineAndAdvance(c);
        while (c != 0x3C && c >= 0) {
          c = _recordStartOfLineAndAdvance(c);
        }
        _emitWithOffsetAndLength(TokenType.TEXT, start, -1);
      } else if (c == 0x22 || c == 0x27) {
        // read a string
        int endQuote = c;
        c = advance();
        while (c >= 0) {
          if (c == endQuote) {
            c = advance();
            break;
          }
          c = _recordStartOfLineAndAdvance(c);
        }
        _emitWithOffsetAndLength(TokenType.STRING, start, -1);
      } else if (c == 0x3D) {
        // a non-char token
        _emitWithOffset(TokenType.EQ, start);
        c = advance();
      } else if (Character.isWhitespace(c)) {
        // ignore whitespace in braces
        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();
        }
        _emitWithOffsetAndLength(TokenType.TAG, start, -1);
      } else {
        // a non-char token
        _emitWithOffsetAndLength(TokenType.TEXT, start, 0);
        c = advance();
      }
    }
  }
}

/**
 * Instances of the class `HtmlParser` are used to parse tokens into a AST structure comprised
 * of [XmlNode]s.
 */
class HtmlParser extends XmlParser {
  static String _APPLICATION_DART_IN_DOUBLE_QUOTES = "\"application/dart\"";

  static String _APPLICATION_DART_IN_SINGLE_QUOTES = "'application/dart'";

  static String _SCRIPT = "script";

  static String _TYPE = "type";

  /**
   * A set containing the names of tags that do not have a closing tag.
   */
  static Set<String> SELF_CLOSING = new HashSet<String>.from(<String>[
    "area",
    "base",
    "basefont",
    "br",
    "col",
    "frame",
    "hr",
    "img",
    "input",
    "link",
    "meta",
    "param",
    "!"
  ]);

  /**
   * The line information associated with the source being parsed.
   */
  LineInfo _lineInfo;

  /**
   * The error listener to which errors will be reported.
   */
  final AnalysisErrorListener _errorListener;

  final AnalysisOptions _options;

  /**
   * Construct a parser for the specified source.
   *
   * [source] is the source being parsed.  [_errorListener] is the error
   * listener to which errors will be reported.  [_options] is the analysis
   * options which should be used for parsing.
   */
  HtmlParser(Source source, this._errorListener, this._options) : super(source);

  @override
  XmlAttributeNode createAttributeNode(Token name, Token equals, Token value) =>
      new XmlAttributeNode(name, equals, value);

  @override
  XmlTagNode createTagNode(
      Token nodeStart,
      Token tag,
      List<XmlAttributeNode> attributes,
      Token attributeEnd,
      List<XmlTagNode> tagNodes,
      Token contentEnd,
      Token closingTag,
      Token nodeEnd) {
    if (_isScriptNode(tag, attributes, tagNodes)) {
      HtmlScriptTagNode tagNode = new HtmlScriptTagNode(nodeStart, tag,
          attributes, attributeEnd, tagNodes, contentEnd, closingTag, nodeEnd);
      String contents = tagNode.content;
      int contentOffset = attributeEnd.end;
      LineInfo_Location location = _lineInfo.getLocation(contentOffset);
      sc.Scanner scanner = new sc.Scanner(source,
          new sc.SubSequenceReader(contents, contentOffset), _errorListener);
      scanner.setSourceStart(location.lineNumber, location.columnNumber);
      sc.Token firstToken = scanner.tokenize();
      Parser parser = new Parser(source, _errorListener);
      CompilationUnit unit = parser.parseCompilationUnit(firstToken);
      unit.lineInfo = _lineInfo;
      tagNode.script = unit;
      return tagNode;
    }
    return new XmlTagNode(nodeStart, tag, attributes, attributeEnd, tagNodes,
        contentEnd, closingTag, nodeEnd);
  }

  @override
  bool isSelfClosing(Token tag) => SELF_CLOSING.contains(tag.lexeme);

  /**
   * Parse the given tokens.
   *
   * @param token the first token in the stream of tokens to be parsed
   * @param lineInfo the line information created by the scanner
   * @return the parse result (not `null`)
   */
  HtmlUnit parse(Token token, LineInfo lineInfo) {
    this._lineInfo = lineInfo;
    List<XmlTagNode> tagNodes = parseTopTagNodes(token);
    return new HtmlUnit(token, tagNodes, currentToken);
  }

  /**
   * Determine if the specified node is a Dart script.
   *
   * @param node the node to be tested (not `null`)
   * @return `true` if the node is a Dart script
   */
  bool _isScriptNode(
      Token tag, List<XmlAttributeNode> attributes, List<XmlTagNode> tagNodes) {
    if (tagNodes.length != 0 || tag.lexeme != _SCRIPT) {
      return false;
    }
    for (XmlAttributeNode attribute in attributes) {
      if (attribute.name == _TYPE) {
        Token valueToken = attribute.valueToken;
        if (valueToken != null) {
          String value = valueToken.lexeme;
          if (value == _APPLICATION_DART_IN_DOUBLE_QUOTES ||
              value == _APPLICATION_DART_IN_SINGLE_QUOTES) {
            return true;
          }
        }
      }
    }
    return false;
  }

  /**
   * Given the contents of an embedded expression that occurs at the given offset, parse it as a
   * Dart expression. The contents should not include the expression's delimiters.
   *
   * @param source the source that contains that given token
   * @param token the token to start parsing from
   * @return the Dart expression that was parsed
   */
  static Expression parseEmbeddedExpression(
      Source source, sc.Token token, AnalysisErrorListener errorListener) {
    Parser parser = new Parser(source, errorListener);
    return parser.parseExpression(token);
  }

  /**
   * Given the contents of an embedded expression that occurs at the given offset, scans it as a
   * Dart code.
   *
   * @param source the source of that contains the given contents
   * @param contents the contents to scan
   * @param contentOffset the offset of the contents in the larger file
   * @return the first Dart token
   */
  static sc.Token scanDartSource(Source source, LineInfo lineInfo,
      String contents, int contentOffset, AnalysisErrorListener errorListener) {
    LineInfo_Location location = lineInfo.getLocation(contentOffset);
    sc.Scanner scanner = new sc.Scanner(source,
        new sc.SubSequenceReader(contents, contentOffset), errorListener);
    scanner.setSourceStart(location.lineNumber, location.columnNumber);
    return scanner.tokenize();
  }
}

/**
 * Instances of the class `HtmlScriptTagNode` represent a script tag within an HTML file that
 * references a Dart script.
 */
@deprecated
class HtmlScriptTagNode extends XmlTagNode {
  /**
   * The AST structure representing the Dart code within this tag.
   */
  CompilationUnit _script;

  /**
   * The element representing this script.
   */
  HtmlScriptElement scriptElement;

  /**
   * Initialize a newly created node to represent a script tag within an HTML file that references a
   * Dart script.
   *
   * @param nodeStart the token marking the beginning of the tag
   * @param tag the name of the tag
   * @param attributes the attributes in the tag
   * @param attributeEnd the token terminating the region where attributes can be
   * @param tagNodes the children of the tag
   * @param contentEnd the token that starts the closing tag
   * @param closingTag the name of the tag that occurs in the closing tag
   * @param nodeEnd the last token in the tag
   */
  HtmlScriptTagNode(
      Token nodeStart,
      Token tag,
      List<XmlAttributeNode> attributes,
      Token attributeEnd,
      List<XmlTagNode> tagNodes,
      Token contentEnd,
      Token closingTag,
      Token nodeEnd)
      : super(nodeStart, tag, attributes, attributeEnd, tagNodes, contentEnd,
            closingTag, nodeEnd);

  /**
   * Return the AST structure representing the Dart code within this tag, or `null` if this
   * tag references an external script.
   *
   * @return the AST structure representing the Dart code within this tag
   */
  CompilationUnit get script => _script;

  /**
   * Set the AST structure representing the Dart code within this tag to the given compilation unit.
   *
   * @param unit the AST structure representing the Dart code within this tag
   */
  void set script(CompilationUnit unit) {
    _script = unit;
  }

  @override
  accept(XmlVisitor visitor) => visitor.visitHtmlScriptTagNode(this);
}

/**
 * Instances of the class `HtmlUnit` represent the contents of an HTML file.
 */
@deprecated
class HtmlUnit extends XmlNode {
  /**
   * The first token in the token stream that was parsed to form this HTML unit.
   */
  final 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].
   */
  final Token endToken;

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

  /**
   * 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(this.beginToken, List<XmlTagNode> tagNodes, this.endToken) {
    this._tagNodes = becomeParentOfAll(tagNodes);
  }

  /**
   * Return the element associated with this HTML unit.
   *
   * @return the element or `null` if the receiver is not resolved
   */
  @override
  HtmlElement get element => super.element as HtmlElement;

  @override
  void set element(Element element) {
    if (element != null && element is! HtmlElement) {
      throw new IllegalArgumentException(
          "HtmlElement expected, but ${element.runtimeType} given");
    }
    super.element = element;
  }

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

  @override
  accept(XmlVisitor visitor) => visitor.visitHtmlUnit(this);

  @override
  void visitChildren(XmlVisitor visitor) {
    for (XmlTagNode node in _tagNodes) {
      node.accept(visitor);
    }
  }
}

/**
 * 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.
 */
class RecursiveXmlVisitor<R> implements XmlVisitor<R> {
  @override
  R visitHtmlScriptTagNode(HtmlScriptTagNode node) {
    node.visitChildren(this);
    return null;
  }

  @override
  R visitHtmlUnit(HtmlUnit node) {
    node.visitChildren(this);
    return null;
  }

  @override
  R visitXmlAttributeNode(XmlAttributeNode node) {
    node.visitChildren(this);
    return null;
  }

  @override
  R visitXmlTagNode(XmlTagNode node) {
    node.visitChildren(this);
    return null;
  }
}

/**
 * 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> {
  @override
  R visitHtmlScriptTagNode(HtmlScriptTagNode node) => null;

  @override
  R visitHtmlUnit(HtmlUnit htmlUnit) => null;

  @override
  R visitXmlAttributeNode(XmlAttributeNode xmlAttributeNode) => null;

  @override
  R visitXmlTagNode(XmlTagNode xmlTagNode) => null;
}

/**
 * Instances of the class `StringScanner` implement a scanner that reads from a string. The
 * scanning logic is in the superclass.
 */
class StringScanner extends AbstractScanner {
  /**
   * The string from which characters will be read.
   */
  final 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, this._string) : super(source) {
    this._stringLength = _string.length;
    this._charOffset = -1;
  }

  @override
  int get offset => _charOffset;

  void set offset(int offset) {
    _charOffset = offset;
  }

  @override
  int advance() {
    if (++_charOffset < _stringLength) {
      return _string.codeUnitAt(_charOffset);
    }
    _charOffset = _stringLength;
    return -1;
  }

  @override
  String getString(int start, int endDelta) =>
      _string.substring(start, _charOffset + 1 + endDelta).toString();

  @override
  int peek() {
    if (_charOffset + 1 < _stringLength) {
      return _string.codeUnitAt(_charOffset + 1);
    }
    return -1;
  }
}

/**
 * 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.
 */
class Token {
  /**
   * The offset from the beginning of the file to the first character in the token.
   */
  final int offset;

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

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

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

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

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

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

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

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

  /**
   * Return the lexeme that represents this token.
   *
   * @return the lexeme (not `null`)
   */
  String get lexeme => _value;

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

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

  @override
  String toString() => lexeme;
}

/**
 * The enumeration `TokenType` defines the types of tokens that can be returned by the
 * scanner.
 */
class TokenType extends Enum<TokenType> {
  /**
   * The type of the token that marks the end of the input.
   */
  static const TokenType EOF = const TokenType_EOF('EOF', 0, "");

  static const TokenType EQ = const TokenType('EQ', 1, "=");

  static const TokenType GT = const TokenType('GT', 2, ">");

  static const TokenType LT_SLASH = const TokenType('LT_SLASH', 3, "</");

  static const TokenType LT = const TokenType('LT', 4, "<");

  static const TokenType SLASH_GT = const TokenType('SLASH_GT', 5, "/>");

  static const TokenType COMMENT = const TokenType('COMMENT', 6, null);

  static const TokenType DECLARATION = const TokenType('DECLARATION', 7, null);

  static const TokenType DIRECTIVE = const TokenType('DIRECTIVE', 8, null);

  static const TokenType STRING = const TokenType('STRING', 9, null);

  static const TokenType TAG = const TokenType('TAG', 10, null);

  static const TokenType TEXT = const TokenType('TEXT', 11, null);

  static const List<TokenType> values = const [
    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.
   */
  final String lexeme;

  const TokenType(String name, int ordinal, this.lexeme) : super(name, ordinal);
}

class TokenType_EOF extends TokenType {
  const TokenType_EOF(String name, int ordinal, String arg0)
      : super(name, ordinal, arg0);

  @override
  String toString() => "-eof-";
}

/**
 * Instances of the class `ToSourceVisitor` write a source representation of a visited XML
 * node (and all of it's children) to a writer.
 */
class ToSourceVisitor implements XmlVisitor<Object> {
  /**
   * The writer to which the source is to be written.
   */
  final 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(this._writer);

  @override
  Object visitHtmlScriptTagNode(HtmlScriptTagNode node) =>
      visitXmlTagNode(node);

  @override
  Object visitHtmlUnit(HtmlUnit node) {
    for (XmlTagNode child in node.tagNodes) {
      _visit(child);
    }
    return null;
  }

  @override
  Object visitXmlAttributeNode(XmlAttributeNode node) {
    String name = node.name;
    Token value = node.valueToken;
    if (name.length == 0) {
      _writer.print("__");
    } else {
      _writer.print(name);
    }
    _writer.print("=");
    if (value == null) {
      _writer.print("__");
    } else {
      _writer.print(value.lexeme);
    }
    return null;
  }

  @override
  Object visitXmlTagNode(XmlTagNode node) {
    _writer.print("<");
    String tagName = node.tag;
    _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);
    }
  }
}

/**
 * Instances of `XmlAttributeNode` represent name/value pairs owned by an [XmlTagNode].
 */
class XmlAttributeNode extends XmlNode {
  /**
   * An empty list of XML attribute nodes.
   */
  static const List<XmlAttributeNode> EMPTY_LIST = const <XmlAttributeNode>[];

  final Token _name;

  final Token equals;

  final Token _value;

  List<XmlExpression> expressions = XmlExpression.EMPTY_ARRAY;

  /**
   * 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(this._name, this.equals, this._value);

  @override
  Token get beginToken => _name;

  @override
  Token get endToken => _value;

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

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

  /**
   * Answer the lexeme for the value token without the leading and trailing quotes.
   *
   * @return the text or `null` if the value is not specified
   */
  String get text {
    if (_value == null) {
      return null;
    }
    //TODO (danrubel): replace HTML character encodings with the actual
    // characters
    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 offset of the value after the leading quote.
   *
   * @return the offset of the value, or `-1` if the value is not specified
   */
  int get textOffset {
    if (_value == null) {
      return -1;
    }
    String text = _value.lexeme;
    if (StringUtilities.startsWithChar(text, 0x22) ||
        StringUtilities.startsWithChar(text, 0x27)) {
      return _value.offset + 1;
    }
    return _value.offset;
  }

  /**
   * Answer the attribute value token. A properly formed value will start and end with matching
   * quote characters, but the value returned may not be properly formed.
   *
   * @return the value token or `null` if this represents a badly formed attribute
   */
  Token get valueToken => _value;

  @override
  accept(XmlVisitor visitor) => visitor.visitXmlAttributeNode(this);

  @override
  void visitChildren(XmlVisitor visitor) {
    // no children to visit
  }
}

/**
 * Instances of the class `XmlExpression` represent an abstract expression embedded into
 * [XmlNode].
 */
abstract class XmlExpression {
  /**
   * An empty list of expressions.
   */
  static const List<XmlExpression> EMPTY_ARRAY = const <XmlExpression>[];

  /**
   * Return the offset of the character immediately following the last character of this
   * expression's source range. This is equivalent to `getOffset() + getLength()`.
   *
   * @return the offset of the character just past the expression's source range
   */
  int get end;

  /**
   * Return the number of characters in the expression's source range.
   */
  int get length;

  /**
   * Return the offset of the first character in the expression's source range.
   */
  int get offset;

  /**
   * Check if the given offset belongs to the expression's source range.
   */
  bool contains(int offset) => this.offset <= offset && offset < end;

  /**
   * Return the [Reference] at the given offset.
   *
   * @param offset the offset from the beginning of the file
   * @return the [Reference] at the given offset, maybe `null`
   */
  XmlExpression_Reference getReference(int offset);
}

/**
 * The reference to the [Element].
 */
class XmlExpression_Reference {
  Element element;

  int offset = 0;

  int length = 0;

  XmlExpression_Reference(this.element, this.offset, this.length);
}

/**
 * The abstract class `XmlNode` defines behavior common to all XML/HTML nodes.
 */
abstract class XmlNode {
  /**
   * The parent of the node, or `null` if the node is the root of an AST structure.
   */
  XmlNode _parent;

  /**
   * The element associated with this node or `null` if the receiver is not resolved.
   */
  Element _element;

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

  /**
   * Return the element associated with this node.
   *
   * @return the element or `null` if the receiver is not resolved
   */
  Element get element => _element;

  /**
   * Set the element associated with this node.
   *
   * @param element the element
   */
  void set element(Element element) {
    this._element = element;
  }

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

  /**
   * 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.logError(
            "Circular structure while setting an XML node's parent",
            new CaughtException(
                new ArgumentError(_buildRecursiveStructureMessage(newParent)),
                null));
        return;
      }
      current = current.parent;
    }
    _parent = newParent;
  }

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

  /**
   * 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 becomeParentOf(XmlNode child) {
    if (child != null) {
      XmlNode node = child;
      node.parent = this;
    }
    return child;
  }

  /**
   * Make this node the parent of the given child nodes.
   *
   * @param children the nodes that will become the children of this node
   * @param ifEmpty the (empty) nodes to return if "children" is empty
   * @return the nodes that were made children of this node
   */
  List becomeParentOfAll(List children, {List ifEmpty}) {
    if (children == null || children.isEmpty) {
      if (ifEmpty != null) {
        return ifEmpty;
      }
    }
    if (children != null) {
      children.forEach((XmlNode node) {
        node.parent = this;
      });
    }
    return children;
  }

  @override
  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);

  /**
   * This method exists for debugging purposes only.
   */
  void _appendIdentifier(StringBuffer buffer, XmlNode node) {
    if (node is XmlTagNode) {
      buffer.write(node.tag);
    } else if (node is XmlAttributeNode) {
      buffer.write(node.name);
    } else {
      buffer.write("htmlUnit");
    }
  }

  /**
   * This method exists for debugging purposes only.
   */
  String _buildRecursiveStructureMessage(XmlNode newParent) {
    StringBuffer buffer = new StringBuffer();
    buffer.write("Attempt to create recursive structure: ");
    XmlNode current = newParent;
    while (current != null) {
      if (!identical(current, newParent)) {
        buffer.write(" -> ");
      }
      if (identical(current, this)) {
        buffer.writeCharCode(0x2A);
        _appendIdentifier(buffer, current);
        buffer.writeCharCode(0x2A);
      } else {
        _appendIdentifier(buffer, current);
      }
      current = current.parent;
    }
    return buffer.toString();
  }
}

/**
 * Instances of the class `XmlParser` are used to parse tokens into a AST structure comprised
 * of [XmlNode]s.
 */
class XmlParser {
  /**
   * The source being parsed.
   */
  final Source source;

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

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

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

  /**
   * Create a node representing an attribute.
   *
   * @param name the name of the attribute
   * @param equals the equals sign, or `null` if there is no value
   * @param value the value of the attribute
   * @return the node that was created
   */
  XmlAttributeNode createAttributeNode(Token name, Token equals, Token value) =>
      new XmlAttributeNode(name, equals, value);

  /**
   * Create a node representing a tag.
   *
   * @param nodeStart the token marking the beginning of the tag
   * @param tag the name of the tag
   * @param attributes the attributes in the tag
   * @param attributeEnd the token terminating the region where attributes can be
   * @param tagNodes the children of the tag
   * @param contentEnd the token that starts the closing tag
   * @param closingTag the name of the tag that occurs in the closing tag
   * @param nodeEnd the last token in the tag
   * @return the node that was created
   */
  XmlTagNode createTagNode(
          Token nodeStart,
          Token tag,
          List<XmlAttributeNode> attributes,
          Token attributeEnd,
          List<XmlTagNode> tagNodes,
          Token contentEnd,
          Token closingTag,
          Token nodeEnd) =>
      new XmlTagNode(nodeStart, tag, attributes, attributeEnd, tagNodes,
          contentEnd, closingTag, nodeEnd);

  /**
   * 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>();
    TokenType type = _currentToken.type;
    while (type != TokenType.EOF) {
      if (type == TokenType.LT) {
        tagNodes.add(_parseTagNode());
      } else if (type == TokenType.DECLARATION ||
          type == TokenType.DIRECTIVE ||
          type == TokenType.COMMENT) {
        // ignored tokens
        _currentToken = _currentToken.next;
      } else {
        _reportUnexpectedToken();
        _currentToken = _currentToken.next;
      }
      type = _currentToken.type;
    }
    return tagNodes;
  }

  /**
   * 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() {
    // Assume the current token is a tag
    Token name = _currentToken;
    _currentToken = _currentToken.next;
    // Equals sign
    Token equals;
    if (_currentToken.type == TokenType.EQ) {
      equals = _currentToken;
      _currentToken = _currentToken.next;
    } else {
      _reportUnexpectedToken();
      equals = _insertSyntheticToken(TokenType.EQ);
    }
    // String value
    Token value;
    if (_currentToken.type == TokenType.STRING) {
      value = _currentToken;
      _currentToken = _currentToken.next;
    } else {
      _reportUnexpectedToken();
      value = _insertSyntheticToken(TokenType.STRING);
    }
    return createAttributeNode(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 (type == TokenType.GT ||
        type == TokenType.SLASH_GT ||
        type == TokenType.EOF) {
      return XmlTagNode.NO_ATTRIBUTES;
    }
    List<XmlAttributeNode> attributes = new List<XmlAttributeNode>();
    while (type != TokenType.GT &&
        type != TokenType.SLASH_GT &&
        type != TokenType.EOF) {
      if (type == TokenType.TAG) {
        attributes.add(_parseAttribute());
      } else {
        _reportUnexpectedToken();
        _currentToken = _currentToken.next;
      }
      type = _currentToken.type;
    }
    return attributes;
  }

  /**
   * 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 (type == TokenType.LT_SLASH || type == TokenType.EOF) {
      return XmlTagNode.NO_TAG_NODES;
    }
    List<XmlTagNode> nodes = new List<XmlTagNode>();
    while (type != TokenType.LT_SLASH && type != TokenType.EOF) {
      if (type == TokenType.LT) {
        nodes.add(_parseTagNode());
      } else if (type == TokenType.COMMENT) {
        // ignored token
        _currentToken = _currentToken.next;
      } else {
        _reportUnexpectedToken();
        _currentToken = _currentToken.next;
      }
      type = _currentToken.type;
    }
    return nodes;
  }

  /**
   * 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() {
    // Assume that the current node is a tag node start TokenType.LT
    Token nodeStart = _currentToken;
    _currentToken = _currentToken.next;
    // Get the tag or create a synthetic tag and report an error
    Token tag;
    if (_currentToken.type == TokenType.TAG) {
      tag = _currentToken;
      _currentToken = _currentToken.next;
    } else {
      _reportUnexpectedToken();
      tag = _insertSyntheticToken(TokenType.TAG);
    }
    // Parse the attributes
    List<XmlAttributeNode> attributes = _parseAttributes();
    // Token ending attribute list
    Token attributeEnd;
    if (_currentToken.type == TokenType.GT ||
        _currentToken.type == TokenType.SLASH_GT) {
      attributeEnd = _currentToken;
      _currentToken = _currentToken.next;
    } else {
      _reportUnexpectedToken();
      attributeEnd = _insertSyntheticToken(TokenType.SLASH_GT);
    }
    // If the node has no children, then return the node
    if (attributeEnd.type == TokenType.SLASH_GT || isSelfClosing(tag)) {
      return createTagNode(nodeStart, tag, attributes, attributeEnd,
          XmlTagNode.NO_TAG_NODES, _currentToken, null, attributeEnd);
    }
    // Parse the child tag nodes
    List<XmlTagNode> tagNodes = _parseChildTagNodes();
    // Token ending child tag nodes
    Token contentEnd;
    if (_currentToken.type == TokenType.LT_SLASH) {
      contentEnd = _currentToken;
      _currentToken = _currentToken.next;
    } else {
      // TODO (danrubel): handle self closing HTML elements by inserting
      // synthetic tokens but not reporting an error
      _reportUnexpectedToken();
      contentEnd = _insertSyntheticToken(TokenType.LT_SLASH);
    }
    // Closing tag
    Token closingTag;
    if (_currentToken.type == TokenType.TAG) {
      closingTag = _currentToken;
      _currentToken = _currentToken.next;
    } else {
      _reportUnexpectedToken();
      closingTag = _insertSyntheticToken(TokenType.TAG);
    }
    // Token ending node
    Token nodeEnd;
    if (_currentToken.type == TokenType.GT) {
      nodeEnd = _currentToken;
      _currentToken = _currentToken.next;
    } else {
      _reportUnexpectedToken();
      nodeEnd = _insertSyntheticToken(TokenType.GT);
    }
    return createTagNode(nodeStart, tag, attributes, attributeEnd, tagNodes,
        contentEnd, closingTag, nodeEnd);
  }

  /**
   * Report the current token as unexpected
   */
  void _reportUnexpectedToken() {
    // TODO (danrubel): report unexpected token
  }
}

/**
 * Instances of `XmlTagNode` represent XML or HTML elements such as `` and
 * `<body foo="bar"> ... </body>`.
 */
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`).
   */
  final Token nodeStart;

  /**
   * The [TokenType.TAG] token after the starting '&lt;' (not `null`).
   */
  final 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].
   */
  final 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].
   */
  final 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]
   */
  final Token closingTag;

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

  /**
   * The expressions that are embedded in the tag's content.
   */
  List<XmlExpression> expressions = XmlExpression.EMPTY_ARRAY;

  /**
   * 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(
      this.nodeStart,
      this._tag,
      List<XmlAttributeNode> attributes,
      this.attributeEnd,
      List<XmlTagNode> tagNodes,
      this.contentEnd,
      this.closingTag,
      this.nodeEnd) {
    this._attributes = becomeParentOfAll(attributes, ifEmpty: NO_ATTRIBUTES);
    this._tagNodes = becomeParentOfAll(tagNodes, ifEmpty: NO_TAG_NODES);
  }

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

  @override
  Token get beginToken => nodeStart;

  /**
   * Return 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.
   */
  String get content {
    Token token = attributeEnd.next;
    if (identical(token, contentEnd)) {
      return "";
    }
    // TODO(danrubel) Handle CDATA and replace HTML character encodings with
    // the actual characters.
    String content = token.lexeme;
    token = token.next;
    if (identical(token, contentEnd)) {
      return content;
    }
    StringBuffer buffer = new StringBuffer();
    buffer.write(content);
    while (!identical(token, contentEnd)) {
      buffer.write(token.lexeme);
      token = token.next;
    }
    return buffer.toString();
  }

  @override
  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 tag name after the starting '&lt;'.
   *
   * @return the tag name (not `null`)
   */
  String get tag => _tag.lexeme;

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

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

  @override
  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 name) {
    for (XmlAttributeNode attribute in _attributes) {
      if (attribute.name == name) {
        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;
  }

  @override
  void visitChildren(XmlVisitor visitor) {
    for (XmlAttributeNode node in _attributes) {
      node.accept(visitor);
    }
    for (XmlTagNode node in _tagNodes) {
      node.accept(visitor);
    }
  }
}

/**
 * The interface `XmlVisitor` defines the behavior of objects that can be used to visit an
 * [XmlNode] structure.
 */
abstract class XmlVisitor<R> {
  R visitHtmlScriptTagNode(HtmlScriptTagNode node);

  R visitHtmlUnit(HtmlUnit htmlUnit);

  R visitXmlAttributeNode(XmlAttributeNode xmlAttributeNode);

  R visitXmlTagNode(XmlTagNode xmlTagNode);
}
