// Copyright (c) 2012, 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.

part of '../visitor.dart';

/////////////////////////////////////////////////////////////////////////
// CSS specific types:
/////////////////////////////////////////////////////////////////////////

class Identifier extends TreeNode {
  String name;

  Identifier(this.name, SourceSpan span) : super(span);

  @override
  Identifier clone() => Identifier(name, span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitIdentifier(this);

  @override
  String toString() {
    // Try to use the identifier's original lexeme to preserve any escape codes
    // as authored. The name, which may include escaped values, may no longer be
    // a valid identifier.
    return span?.text ?? name;
  }
}

class Wildcard extends TreeNode {
  Wildcard(SourceSpan span) : super(span);
  @override
  Wildcard clone() => Wildcard(span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitWildcard(this);

  String get name => '*';
}

class ThisOperator extends TreeNode {
  ThisOperator(SourceSpan span) : super(span);
  @override
  ThisOperator clone() => ThisOperator(span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitThisOperator(this);

  String get name => '&';
}

class Negation extends TreeNode {
  Negation(SourceSpan span) : super(span);
  @override
  Negation clone() => Negation(span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitNegation(this);

  String get name => 'not';
}

// calc(...)
// TODO(terry): Hack to handle calc however the expressions should be fully
//              parsed and in the AST.
class CalcTerm extends LiteralTerm {
  final LiteralTerm expr;

  CalcTerm(var value, String t, this.expr, SourceSpan span)
      : super(value, t, span);

  @override
  CalcTerm clone() => CalcTerm(value, text, expr.clone(), span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitCalcTerm(this);

  @override
  String toString() => '$text($expr)';
}

// /*  ....   */
class CssComment extends TreeNode {
  final String comment;

  CssComment(this.comment, SourceSpan span) : super(span);
  @override
  CssComment clone() => CssComment(comment, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitCssComment(this);
}

// CDO/CDC (Comment Definition Open <!-- and Comment Definition Close -->).
class CommentDefinition extends CssComment {
  CommentDefinition(String comment, SourceSpan span) : super(comment, span);
  @override
  CommentDefinition clone() => CommentDefinition(comment, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitCommentDefinition(this);
}

class SelectorGroup extends TreeNode {
  final List<Selector> selectors;

  SelectorGroup(this.selectors, SourceSpan span) : super(span);

  @override
  SelectorGroup clone() => SelectorGroup(selectors, span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitSelectorGroup(this);
}

class Selector extends TreeNode {
  final List<SimpleSelectorSequence> simpleSelectorSequences;

  Selector(this.simpleSelectorSequences, SourceSpan span) : super(span);

  void add(SimpleSelectorSequence seq) => simpleSelectorSequences.add(seq);

  int get length => simpleSelectorSequences.length;

  @override
  Selector clone() {
    var simpleSequences =
        simpleSelectorSequences.map((ss) => ss.clone()).toList();

    return Selector(simpleSequences, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitSelector(this);
}

class SimpleSelectorSequence extends TreeNode {
  /// +, >, ~, NONE
  int combinator;
  final SimpleSelector simpleSelector;

  SimpleSelectorSequence(this.simpleSelector, SourceSpan span,
      [int combinator = TokenKind.COMBINATOR_NONE])
      : combinator = combinator,
        super(span);

  bool get isCombinatorNone => combinator == TokenKind.COMBINATOR_NONE;
  bool get isCombinatorPlus => combinator == TokenKind.COMBINATOR_PLUS;
  bool get isCombinatorGreater => combinator == TokenKind.COMBINATOR_GREATER;
  bool get isCombinatorTilde => combinator == TokenKind.COMBINATOR_TILDE;
  bool get isCombinatorDescendant =>
      combinator == TokenKind.COMBINATOR_DESCENDANT;

  String get _combinatorToString {
    switch (combinator) {
      case TokenKind.COMBINATOR_DESCENDANT:
        return ' ';
      case TokenKind.COMBINATOR_GREATER:
        return ' > ';
      case TokenKind.COMBINATOR_PLUS:
        return ' + ';
      case TokenKind.COMBINATOR_TILDE:
        return ' ~ ';
      default:
        return '';
    }
  }

  @override
  SimpleSelectorSequence clone() =>
      SimpleSelectorSequence(simpleSelector, span, combinator);

  @override
  dynamic visit(VisitorBase visitor) =>
      visitor.visitSimpleSelectorSequence(this);

  @override
  String toString() => simpleSelector.name;
}

// All other selectors (element, #id, .class, attribute, pseudo, negation,
// namespace, *) are derived from this selector.
abstract class SimpleSelector extends TreeNode {
  final dynamic _name; // Wildcard, ThisOperator, Identifier, Negation, others?

  SimpleSelector(this._name, SourceSpan span) : super(span);

  String get name => _name.name;

  bool get isWildcard => _name is Wildcard;

  bool get isThis => _name is ThisOperator;

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitSimpleSelector(this);
}

// element name
class ElementSelector extends SimpleSelector {
  ElementSelector(name, SourceSpan span) : super(name, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitElementSelector(this);

  @override
  ElementSelector clone() => ElementSelector(_name, span);

  @override
  String toString() => name;
}

// namespace|element
class NamespaceSelector extends SimpleSelector {
  final dynamic _namespace; // null, Wildcard or Identifier

  NamespaceSelector(this._namespace, var name, SourceSpan span)
      : super(name, span);

  String get namespace =>
      _namespace is Wildcard ? '*' : _namespace == null ? '' : _namespace.name;

  bool get isNamespaceWildcard => _namespace is Wildcard;

  SimpleSelector get nameAsSimpleSelector => _name;

  @override
  NamespaceSelector clone() => NamespaceSelector(_namespace, '', span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitNamespaceSelector(this);

  @override
  String toString() => '$namespace|${nameAsSimpleSelector.name}';
}

// [attr op value]
class AttributeSelector extends SimpleSelector {
  final int _op;
  final dynamic value;

  AttributeSelector(Identifier name, this._op, this.value, SourceSpan span)
      : super(name, span);

  int get operatorKind => _op;

  String matchOperator() {
    switch (_op) {
      case TokenKind.EQUALS:
        return '=';
      case TokenKind.INCLUDES:
        return '~=';
      case TokenKind.DASH_MATCH:
        return '|=';
      case TokenKind.PREFIX_MATCH:
        return '^=';
      case TokenKind.SUFFIX_MATCH:
        return '\$=';
      case TokenKind.SUBSTRING_MATCH:
        return '*=';
      case TokenKind.NO_MATCH:
        return '';
    }
    return null;
  }

  // Return the TokenKind for operator used by visitAttributeSelector.
  String matchOperatorAsTokenString() {
    switch (_op) {
      case TokenKind.EQUALS:
        return 'EQUALS';
      case TokenKind.INCLUDES:
        return 'INCLUDES';
      case TokenKind.DASH_MATCH:
        return 'DASH_MATCH';
      case TokenKind.PREFIX_MATCH:
        return 'PREFIX_MATCH';
      case TokenKind.SUFFIX_MATCH:
        return 'SUFFIX_MATCH';
      case TokenKind.SUBSTRING_MATCH:
        return 'SUBSTRING_MATCH';
    }
    return null;
  }

  String valueToString() {
    if (value != null) {
      if (value is Identifier) {
        return value.toString();
      } else {
        return '"$value"';
      }
    } else {
      return '';
    }
  }

  @override
  AttributeSelector clone() => AttributeSelector(_name, _op, value, span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitAttributeSelector(this);

  @override
  String toString() => '[$name${matchOperator()}${valueToString()}]';
}

// #id
class IdSelector extends SimpleSelector {
  IdSelector(Identifier name, SourceSpan span) : super(name, span);
  @override
  IdSelector clone() => IdSelector(_name, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitIdSelector(this);

  @override
  String toString() => '#$_name';
}

// .class
class ClassSelector extends SimpleSelector {
  ClassSelector(Identifier name, SourceSpan span) : super(name, span);
  @override
  ClassSelector clone() => ClassSelector(_name, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitClassSelector(this);

  @override
  String toString() => '.$_name';
}

// :pseudoClass
class PseudoClassSelector extends SimpleSelector {
  PseudoClassSelector(Identifier name, SourceSpan span) : super(name, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitPseudoClassSelector(this);

  @override
  PseudoClassSelector clone() => PseudoClassSelector(_name, span);

  @override
  String toString() => ':$name';
}

// ::pseudoElement
class PseudoElementSelector extends SimpleSelector {
  // If true, this is a CSS2.1 pseudo-element with only a single ':'.
  final bool isLegacy;

  PseudoElementSelector(Identifier name, SourceSpan span,
      {this.isLegacy = false})
      : super(name, span);
  @override
  dynamic visit(VisitorBase visitor) =>
      visitor.visitPseudoElementSelector(this);

  @override
  PseudoElementSelector clone() => PseudoElementSelector(_name, span);

  @override
  String toString() => "${isLegacy ? ':' : '::'}$name";
}

// :pseudoClassFunction(argument)
class PseudoClassFunctionSelector extends PseudoClassSelector {
  final TreeNode _argument; // Selector, SelectorExpression

  PseudoClassFunctionSelector(Identifier name, this._argument, SourceSpan span)
      : super(name, span);

  @override
  PseudoClassFunctionSelector clone() =>
      PseudoClassFunctionSelector(_name, _argument, span);

  TreeNode get argument => _argument;
  Selector get selector => _argument as Selector;
  SelectorExpression get expression => _argument as SelectorExpression;

  @override
  dynamic visit(VisitorBase visitor) =>
      visitor.visitPseudoClassFunctionSelector(this);
}

// ::pseudoElementFunction(expression)
class PseudoElementFunctionSelector extends PseudoElementSelector {
  final SelectorExpression expression;

  PseudoElementFunctionSelector(
      Identifier name, this.expression, SourceSpan span)
      : super(name, span);

  @override
  PseudoElementFunctionSelector clone() =>
      PseudoElementFunctionSelector(_name, expression, span);

  @override
  dynamic visit(VisitorBase visitor) =>
      visitor.visitPseudoElementFunctionSelector(this);
}

class SelectorExpression extends TreeNode {
  final List<Expression> expressions;

  SelectorExpression(this.expressions, SourceSpan span) : super(span);

  @override
  SelectorExpression clone() {
    return SelectorExpression(expressions.map((e) => e.clone()).toList(), span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitSelectorExpression(this);
}

// :NOT(negation_arg)
class NegationSelector extends SimpleSelector {
  final SimpleSelector negationArg;

  NegationSelector(this.negationArg, SourceSpan span)
      : super(Negation(span), span);

  @override
  NegationSelector clone() => NegationSelector(negationArg, span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitNegationSelector(this);
}

class NoOp extends TreeNode {
  NoOp() : super(null);

  @override
  NoOp clone() => NoOp();

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitNoOp(this);
}

class StyleSheet extends TreeNode {
  /// Contains charset, ruleset, directives (media, page, etc.), and selectors.
  final List<TreeNode> topLevels;

  StyleSheet(this.topLevels, SourceSpan span) : super(span) {
    for (final node in topLevels) {
      assert(node is TopLevelProduction || node is Directive);
    }
  }

  /// Selectors only in this tree.
  StyleSheet.selector(this.topLevels, SourceSpan span) : super(span);

  @override
  StyleSheet clone() {
    var clonedTopLevels = topLevels.map((e) => e.clone()).toList();
    return StyleSheet(clonedTopLevels, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitStyleSheet(this);
}

class TopLevelProduction extends TreeNode {
  TopLevelProduction(SourceSpan span) : super(span);
  @override
  TopLevelProduction clone() => TopLevelProduction(span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitTopLevelProduction(this);
}

class RuleSet extends TopLevelProduction {
  final SelectorGroup _selectorGroup;
  final DeclarationGroup _declarationGroup;

  RuleSet(this._selectorGroup, this._declarationGroup, SourceSpan span)
      : super(span);

  SelectorGroup get selectorGroup => _selectorGroup;
  DeclarationGroup get declarationGroup => _declarationGroup;

  @override
  RuleSet clone() {
    var cloneSelectorGroup = _selectorGroup.clone();
    var cloneDeclarationGroup = _declarationGroup.clone();
    return RuleSet(cloneSelectorGroup, cloneDeclarationGroup, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitRuleSet(this);
}

class Directive extends TreeNode {
  Directive(SourceSpan span) : super(span);

  bool get isBuiltIn => true; // Known CSS directive?
  bool get isExtension => false; // SCSS extension?

  @override
  Directive clone() => Directive(span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitDirective(this);
}

class DocumentDirective extends Directive {
  final List<LiteralTerm> functions;
  final List<TreeNode> groupRuleBody;

  DocumentDirective(this.functions, this.groupRuleBody, SourceSpan span)
      : super(span);

  @override
  DocumentDirective clone() {
    var clonedFunctions = <LiteralTerm>[];
    for (var function in functions) {
      clonedFunctions.add(function.clone());
    }
    var clonedGroupRuleBody = <TreeNode>[];
    for (var rule in groupRuleBody) {
      clonedGroupRuleBody.add(rule.clone());
    }
    return DocumentDirective(clonedFunctions, clonedGroupRuleBody, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitDocumentDirective(this);
}

class SupportsDirective extends Directive {
  final SupportsCondition condition;
  final List<TreeNode> groupRuleBody;

  SupportsDirective(this.condition, this.groupRuleBody, SourceSpan span)
      : super(span);

  @override
  SupportsDirective clone() {
    var clonedCondition = condition.clone();
    var clonedGroupRuleBody = <TreeNode>[];
    for (var rule in groupRuleBody) {
      clonedGroupRuleBody.add(rule.clone());
    }
    return SupportsDirective(clonedCondition, clonedGroupRuleBody, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitSupportsDirective(this);
}

abstract class SupportsCondition extends TreeNode {
  SupportsCondition(SourceSpan span) : super(span);
}

class SupportsConditionInParens extends SupportsCondition {
  /// A [Declaration] or nested [SupportsCondition].
  final TreeNode condition;

  SupportsConditionInParens(Declaration declaration, SourceSpan span)
      : condition = declaration,
        super(span);

  SupportsConditionInParens.nested(SupportsCondition condition, SourceSpan span)
      : condition = condition,
        super(span);

  @override
  SupportsConditionInParens clone() =>
      SupportsConditionInParens(condition.clone(), span);

  @override
  dynamic visit(VisitorBase visitor) =>
      visitor.visitSupportsConditionInParens(this);
}

class SupportsNegation extends SupportsCondition {
  final SupportsConditionInParens condition;

  SupportsNegation(this.condition, SourceSpan span) : super(span);

  @override
  SupportsNegation clone() => SupportsNegation(condition.clone(), span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitSupportsNegation(this);
}

class SupportsConjunction extends SupportsCondition {
  final List<SupportsConditionInParens> conditions;

  SupportsConjunction(this.conditions, SourceSpan span) : super(span);

  @override
  SupportsConjunction clone() {
    var clonedConditions = <SupportsConditionInParens>[];
    for (var condition in conditions) {
      clonedConditions.add(condition.clone());
    }
    return SupportsConjunction(clonedConditions, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitSupportsConjunction(this);
}

class SupportsDisjunction extends SupportsCondition {
  final List<SupportsConditionInParens> conditions;

  SupportsDisjunction(this.conditions, SourceSpan span) : super(span);

  @override
  SupportsDisjunction clone() {
    var clonedConditions = <SupportsConditionInParens>[];
    for (var condition in conditions) {
      clonedConditions.add(condition.clone());
    }
    return SupportsDisjunction(clonedConditions, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitSupportsDisjunction(this);
}

class ViewportDirective extends Directive {
  final String name;
  final DeclarationGroup declarations;

  ViewportDirective(this.name, this.declarations, SourceSpan span)
      : super(span);

  @override
  ViewportDirective clone() =>
      ViewportDirective(name, declarations.clone(), span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitViewportDirective(this);
}

class ImportDirective extends Directive {
  /// import name specified.
  final String import;

  /// Any media queries for this import.
  final List<MediaQuery> mediaQueries;

  ImportDirective(this.import, this.mediaQueries, SourceSpan span)
      : super(span);

  @override
  ImportDirective clone() {
    var cloneMediaQueries = <MediaQuery>[];
    for (var mediaQuery in mediaQueries) {
      cloneMediaQueries.add(mediaQuery.clone());
    }
    return ImportDirective(import, cloneMediaQueries, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitImportDirective(this);
}

/// MediaExpression grammar:
///
///     '(' S* media_feature S* [ ':' S* expr ]? ')' S*
class MediaExpression extends TreeNode {
  final bool andOperator;
  final Identifier _mediaFeature;
  final Expressions exprs;

  MediaExpression(
      this.andOperator, this._mediaFeature, this.exprs, SourceSpan span)
      : super(span);

  String get mediaFeature => _mediaFeature.name;

  @override
  MediaExpression clone() {
    var clonedExprs = exprs.clone();
    return MediaExpression(andOperator, _mediaFeature, clonedExprs, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitMediaExpression(this);
}

/// MediaQuery grammar:
///
///      : [ONLY | NOT]? S* media_type S* [ AND S* media_expression ]*
///      | media_expression [ AND S* media_expression ]*
///     media_type
///      : IDENT
///     media_expression
///      : '(' S* media_feature S* [ ':' S* expr ]? ')' S*
///     media_feature
///      : IDENT
class MediaQuery extends TreeNode {
  /// not, only or no operator.
  final int _mediaUnary;
  final Identifier _mediaType;
  final List<MediaExpression> expressions;

  MediaQuery(
      this._mediaUnary, this._mediaType, this.expressions, SourceSpan span)
      : super(span);

  bool get hasMediaType => _mediaType != null;
  String get mediaType => _mediaType.name;

  bool get hasUnary => _mediaUnary != -1;
  String get unary =>
      TokenKind.idToValue(TokenKind.MEDIA_OPERATORS, _mediaUnary).toUpperCase();

  @override
  MediaQuery clone() {
    var cloneExpressions = <MediaExpression>[];
    for (var expr in expressions) {
      cloneExpressions.add(expr.clone());
    }
    return MediaQuery(_mediaUnary, _mediaType, cloneExpressions, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitMediaQuery(this);
}

class MediaDirective extends Directive {
  final List<MediaQuery> mediaQueries;
  final List<TreeNode> rules;

  MediaDirective(this.mediaQueries, this.rules, SourceSpan span) : super(span);

  @override
  MediaDirective clone() {
    var cloneQueries = <MediaQuery>[];
    for (var mediaQuery in mediaQueries) {
      cloneQueries.add(mediaQuery.clone());
    }
    var cloneRules = <TreeNode>[];
    for (var rule in rules) {
      cloneRules.add(rule.clone());
    }
    return MediaDirective(cloneQueries, cloneRules, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitMediaDirective(this);
}

class HostDirective extends Directive {
  final List<TreeNode> rules;

  HostDirective(this.rules, SourceSpan span) : super(span);

  @override
  HostDirective clone() {
    var cloneRules = <TreeNode>[];
    for (var rule in rules) {
      cloneRules.add(rule.clone());
    }
    return HostDirective(cloneRules, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitHostDirective(this);
}

class PageDirective extends Directive {
  final String _ident;
  final String _pseudoPage;
  final List<DeclarationGroup> _declsMargin;

  PageDirective(
      this._ident, this._pseudoPage, this._declsMargin, SourceSpan span)
      : super(span);

  @override
  PageDirective clone() {
    var cloneDeclsMargin = <DeclarationGroup>[];
    for (var declMargin in _declsMargin) {
      cloneDeclsMargin.add(declMargin.clone());
    }
    return PageDirective(_ident, _pseudoPage, cloneDeclsMargin, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitPageDirective(this);

  bool get hasIdent => _ident != null && _ident.isNotEmpty;
  bool get hasPseudoPage => _pseudoPage != null && _pseudoPage.isNotEmpty;
}

class CharsetDirective extends Directive {
  final String charEncoding;

  CharsetDirective(this.charEncoding, SourceSpan span) : super(span);
  @override
  CharsetDirective clone() => CharsetDirective(charEncoding, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitCharsetDirective(this);
}

class KeyFrameDirective extends Directive {
  // Either @keyframe or keyframe prefixed with @-webkit-, @-moz-, @-ms-, @-o-.
  final int _keyframeName;
  final Identifier name;
  final List<KeyFrameBlock> _blocks;

  KeyFrameDirective(this._keyframeName, this.name, SourceSpan span)
      : _blocks = [],
        super(span);

  void add(KeyFrameBlock block) {
    _blocks.add(block);
  }

  String get keyFrameName {
    switch (_keyframeName) {
      case TokenKind.DIRECTIVE_KEYFRAMES:
      case TokenKind.DIRECTIVE_MS_KEYFRAMES:
        return '@keyframes';
      case TokenKind.DIRECTIVE_WEB_KIT_KEYFRAMES:
        return '@-webkit-keyframes';
      case TokenKind.DIRECTIVE_MOZ_KEYFRAMES:
        return '@-moz-keyframes';
      case TokenKind.DIRECTIVE_O_KEYFRAMES:
        return '@-o-keyframes';
    }
    return null;
  }

  @override
  KeyFrameDirective clone() {
    var directive = KeyFrameDirective(_keyframeName, name.clone(), span);
    for (var block in _blocks) {
      directive.add(block.clone());
    }
    return directive;
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitKeyFrameDirective(this);
}

class KeyFrameBlock extends Expression {
  final Expressions _blockSelectors;
  final DeclarationGroup _declarations;

  KeyFrameBlock(this._blockSelectors, this._declarations, SourceSpan span)
      : super(span);

  @override
  KeyFrameBlock clone() =>
      KeyFrameBlock(_blockSelectors.clone(), _declarations.clone(), span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitKeyFrameBlock(this);
}

class FontFaceDirective extends Directive {
  final DeclarationGroup _declarations;

  FontFaceDirective(this._declarations, SourceSpan span) : super(span);

  @override
  FontFaceDirective clone() => FontFaceDirective(_declarations.clone(), span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitFontFaceDirective(this);
}

class StyletDirective extends Directive {
  final String dartClassName;
  final List<TreeNode> rules;

  StyletDirective(this.dartClassName, this.rules, SourceSpan span)
      : super(span);

  @override
  bool get isBuiltIn => false;
  @override
  bool get isExtension => true;

  @override
  StyletDirective clone() {
    var cloneRules = <TreeNode>[];
    for (var rule in rules) {
      cloneRules.add(rule.clone());
    }
    return StyletDirective(dartClassName, cloneRules, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitStyletDirective(this);
}

class NamespaceDirective extends Directive {
  /// Namespace prefix.
  final String _prefix;

  /// URI associated with this namespace.
  final String _uri;

  NamespaceDirective(this._prefix, this._uri, SourceSpan span) : super(span);

  @override
  NamespaceDirective clone() => NamespaceDirective(_prefix, _uri, span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitNamespaceDirective(this);

  String get prefix => _prefix.isNotEmpty ? '$_prefix ' : '';
}

/// To support Less syntax @name: expression
class VarDefinitionDirective extends Directive {
  final VarDefinition def;

  VarDefinitionDirective(this.def, SourceSpan span) : super(span);

  @override
  VarDefinitionDirective clone() => VarDefinitionDirective(def.clone(), span);

  @override
  dynamic visit(VisitorBase visitor) =>
      visitor.visitVarDefinitionDirective(this);
}

class MixinDefinition extends Directive {
  final String name;
  final List<TreeNode> definedArgs;
  final bool varArgs;

  MixinDefinition(this.name, this.definedArgs, this.varArgs, SourceSpan span)
      : super(span);

  @override
  MixinDefinition clone() {
    var cloneDefinedArgs = <TreeNode>[];
    for (var definedArg in definedArgs) {
      cloneDefinedArgs.add(definedArg.clone());
    }
    return MixinDefinition(name, cloneDefinedArgs, varArgs, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitMixinDefinition(this);
}

/// Support a Sass @mixin. See http://sass-lang.com for description.
class MixinRulesetDirective extends MixinDefinition {
  final List<TreeNode> rulesets;

  MixinRulesetDirective(String name, List<TreeNode> args, bool varArgs,
      this.rulesets, SourceSpan span)
      : super(name, args, varArgs, span);

  @override
  MixinRulesetDirective clone() {
    var clonedArgs = <VarDefinition>[];
    for (var arg in definedArgs) {
      clonedArgs.add(arg.clone());
    }
    var clonedRulesets = <TreeNode>[];
    for (var ruleset in rulesets) {
      clonedRulesets.add(ruleset.clone());
    }
    return MixinRulesetDirective(
        name, clonedArgs, varArgs, clonedRulesets, span);
  }

  @override
  dynamic visit(VisitorBase visitor) =>
      visitor.visitMixinRulesetDirective(this);
}

class MixinDeclarationDirective extends MixinDefinition {
  final DeclarationGroup declarations;

  MixinDeclarationDirective(String name, List<TreeNode> args, bool varArgs,
      this.declarations, SourceSpan span)
      : super(name, args, varArgs, span);

  @override
  MixinDeclarationDirective clone() {
    var clonedArgs = <TreeNode>[];
    for (var arg in definedArgs) {
      clonedArgs.add(arg.clone());
    }
    return MixinDeclarationDirective(
        name, clonedArgs, varArgs, declarations.clone(), span);
  }

  @override
  dynamic visit(VisitorBase visitor) =>
      visitor.visitMixinDeclarationDirective(this);
}

/// To support consuming a Sass mixin @include.
class IncludeDirective extends Directive {
  final String name;
  final List<List<Expression>> args;

  IncludeDirective(this.name, this.args, SourceSpan span) : super(span);

  @override
  IncludeDirective clone() {
    var cloneArgs = <List<Expression>>[];
    for (var arg in args) {
      cloneArgs.add(arg.map((term) => term.clone()).toList());
    }
    return IncludeDirective(name, cloneArgs, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitIncludeDirective(this);
}

/// To support Sass @content.
class ContentDirective extends Directive {
  ContentDirective(SourceSpan span) : super(span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitContentDirective(this);
}

class Declaration extends TreeNode {
  final Identifier _property;
  final Expression _expression;

  /// Style exposed to Dart.
  DartStyleExpression dartStyle;
  final bool important;

  /// IE CSS hacks that can only be read by a particular IE version.
  /// 7 implies IE 7 or older property (e.g., `*background: blue;`)
  ///
  /// * Note:  IE 8 or older property (e.g., `background: green\9;`) is handled
  ///   by IE8Term in declaration expression handling.
  /// * Note:  IE 6 only property with a leading underscore is a valid IDENT
  ///   since an ident can start with underscore (e.g., `_background: red;`)
  final bool isIE7;

  Declaration(this._property, this._expression, this.dartStyle, SourceSpan span,
      {this.important = false, bool ie7 = false})
      : isIE7 = ie7,
        super(span);

  String get property => isIE7 ? '*${_property.name}' : _property.name;
  Expression get expression => _expression;

  bool get hasDartStyle => dartStyle != null;

  @override
  Declaration clone() =>
      Declaration(_property.clone(), _expression.clone(), dartStyle, span,
          important: important);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitDeclaration(this);
}

// TODO(terry): Consider 2 kinds of VarDefinitions static at top-level and
//              dynamic when in a declaration.  Currently, Less syntax
//              '@foo: expression' and 'var-foo: expression' in a declaration
//              are statically resolved. Better solution, if @foo or var-foo
//              are top-level are then statically resolved and var-foo in a
//              declaration group (surrounded by a selector) would be dynamic.
class VarDefinition extends Declaration {
  bool badUsage = false;

  VarDefinition(Identifier definedName, Expression expr, SourceSpan span)
      : super(definedName, expr, null, span);

  String get definedName => _property.name;

  @override
  VarDefinition clone() => VarDefinition(
      _property.clone(), expression != null ? expression.clone() : null, span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitVarDefinition(this);
}

/// Node for usage of @include mixin[(args,...)] found in a declaration group
/// instead of at a ruleset (toplevel) e.g.,
///
///     div {
///       @include mixin1;
///     }
class IncludeMixinAtDeclaration extends Declaration {
  final IncludeDirective include;

  IncludeMixinAtDeclaration(this.include, SourceSpan span)
      : super(null, null, null, span);

  @override
  IncludeMixinAtDeclaration clone() =>
      IncludeMixinAtDeclaration(include.clone(), span);

  @override
  dynamic visit(VisitorBase visitor) =>
      visitor.visitIncludeMixinAtDeclaration(this);
}

class ExtendDeclaration extends Declaration {
  final List<TreeNode> selectors;

  ExtendDeclaration(this.selectors, SourceSpan span)
      : super(null, null, null, span);

  @override
  ExtendDeclaration clone() {
    var newSelector = selectors.map((s) => s.clone()).toList();
    return ExtendDeclaration(newSelector, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitExtendDeclaration(this);
}

class DeclarationGroup extends TreeNode {
  /// Can be either Declaration or RuleSet (if nested selector).
  final List<TreeNode> declarations;

  DeclarationGroup(this.declarations, SourceSpan span) : super(span);

  @override
  DeclarationGroup clone() {
    var clonedDecls = declarations.map((d) => d.clone()).toList();
    return DeclarationGroup(clonedDecls, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitDeclarationGroup(this);
}

class MarginGroup extends DeclarationGroup {
  final int margin_sym; // TokenType for for @margin sym.

  MarginGroup(this.margin_sym, List<TreeNode> decls, SourceSpan span)
      : super(decls, span);
  @override
  MarginGroup clone() =>
      MarginGroup(margin_sym, super.clone().declarations, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitMarginGroup(this);
}

class VarUsage extends Expression {
  final String name;
  final List<Expression> defaultValues;

  VarUsage(this.name, this.defaultValues, SourceSpan span) : super(span);

  @override
  VarUsage clone() {
    var clonedValues = <Expression>[];
    for (var expr in defaultValues) {
      clonedValues.add(expr.clone());
    }
    return VarUsage(name, clonedValues, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitVarUsage(this);
}

class OperatorSlash extends Expression {
  OperatorSlash(SourceSpan span) : super(span);
  @override
  OperatorSlash clone() => OperatorSlash(span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitOperatorSlash(this);
}

class OperatorComma extends Expression {
  OperatorComma(SourceSpan span) : super(span);
  @override
  OperatorComma clone() => OperatorComma(span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitOperatorComma(this);
}

class OperatorPlus extends Expression {
  OperatorPlus(SourceSpan span) : super(span);
  @override
  OperatorPlus clone() => OperatorPlus(span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitOperatorPlus(this);
}

class OperatorMinus extends Expression {
  OperatorMinus(SourceSpan span) : super(span);
  @override
  OperatorMinus clone() => OperatorMinus(span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitOperatorMinus(this);
}

class UnicodeRangeTerm extends Expression {
  final String first;
  final String second;

  UnicodeRangeTerm(this.first, this.second, SourceSpan span) : super(span);

  bool get hasSecond => second != null;

  @override
  UnicodeRangeTerm clone() => UnicodeRangeTerm(first, second, span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitUnicodeRangeTerm(this);
}

class LiteralTerm extends Expression {
  // TODO(terry): value and text fields can be made final once all CSS resources
  //              are copied/symlink'd in the build tool and UriVisitor in
  //              web_ui is removed.
  dynamic value;
  String text;

  LiteralTerm(this.value, this.text, SourceSpan span) : super(span);

  @override
  LiteralTerm clone() => LiteralTerm(value, text, span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitLiteralTerm(this);
}

class NumberTerm extends LiteralTerm {
  NumberTerm(value, String t, SourceSpan span) : super(value, t, span);
  @override
  NumberTerm clone() => NumberTerm(value, text, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitNumberTerm(this);
}

class UnitTerm extends LiteralTerm {
  final int unit;

  UnitTerm(value, String t, SourceSpan span, this.unit) : super(value, t, span);

  @override
  UnitTerm clone() => UnitTerm(value, text, span, unit);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitUnitTerm(this);

  String unitToString() => TokenKind.unitToString(unit);

  @override
  String toString() => '$text${unitToString()}';
}

class LengthTerm extends UnitTerm {
  LengthTerm(value, String t, SourceSpan span,
      [int unit = TokenKind.UNIT_LENGTH_PX])
      : super(value, t, span, unit) {
    assert(this.unit == TokenKind.UNIT_LENGTH_PX ||
        this.unit == TokenKind.UNIT_LENGTH_CM ||
        this.unit == TokenKind.UNIT_LENGTH_MM ||
        this.unit == TokenKind.UNIT_LENGTH_IN ||
        this.unit == TokenKind.UNIT_LENGTH_PT ||
        this.unit == TokenKind.UNIT_LENGTH_PC);
  }
  @override
  LengthTerm clone() => LengthTerm(value, text, span, unit);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitLengthTerm(this);
}

class PercentageTerm extends LiteralTerm {
  PercentageTerm(value, String t, SourceSpan span) : super(value, t, span);
  @override
  PercentageTerm clone() => PercentageTerm(value, text, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitPercentageTerm(this);
}

class EmTerm extends LiteralTerm {
  EmTerm(value, String t, SourceSpan span) : super(value, t, span);
  @override
  EmTerm clone() => EmTerm(value, text, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitEmTerm(this);
}

class ExTerm extends LiteralTerm {
  ExTerm(value, String t, SourceSpan span) : super(value, t, span);
  @override
  ExTerm clone() => ExTerm(value, text, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitExTerm(this);
}

class AngleTerm extends UnitTerm {
  AngleTerm(var value, String t, SourceSpan span,
      [int unit = TokenKind.UNIT_LENGTH_PX])
      : super(value, t, span, unit) {
    assert(this.unit == TokenKind.UNIT_ANGLE_DEG ||
        this.unit == TokenKind.UNIT_ANGLE_RAD ||
        this.unit == TokenKind.UNIT_ANGLE_GRAD ||
        this.unit == TokenKind.UNIT_ANGLE_TURN);
  }

  @override
  AngleTerm clone() => AngleTerm(value, text, span, unit);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitAngleTerm(this);
}

class TimeTerm extends UnitTerm {
  TimeTerm(var value, String t, SourceSpan span,
      [int unit = TokenKind.UNIT_LENGTH_PX])
      : super(value, t, span, unit) {
    assert(this.unit == TokenKind.UNIT_ANGLE_DEG ||
        this.unit == TokenKind.UNIT_TIME_MS ||
        this.unit == TokenKind.UNIT_TIME_S);
  }

  @override
  TimeTerm clone() => TimeTerm(value, text, span, unit);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitTimeTerm(this);
}

class FreqTerm extends UnitTerm {
  FreqTerm(var value, String t, SourceSpan span,
      [int unit = TokenKind.UNIT_LENGTH_PX])
      : super(value, t, span, unit) {
    assert(unit == TokenKind.UNIT_FREQ_HZ || unit == TokenKind.UNIT_FREQ_KHZ);
  }

  @override
  FreqTerm clone() => FreqTerm(value, text, span, unit);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitFreqTerm(this);
}

class FractionTerm extends LiteralTerm {
  FractionTerm(var value, String t, SourceSpan span) : super(value, t, span);

  @override
  FractionTerm clone() => FractionTerm(value, text, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitFractionTerm(this);
}

class UriTerm extends LiteralTerm {
  UriTerm(String value, SourceSpan span) : super(value, value, span);

  @override
  UriTerm clone() => UriTerm(value, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitUriTerm(this);
}

class ResolutionTerm extends UnitTerm {
  ResolutionTerm(var value, String t, SourceSpan span,
      [int unit = TokenKind.UNIT_LENGTH_PX])
      : super(value, t, span, unit) {
    assert(unit == TokenKind.UNIT_RESOLUTION_DPI ||
        unit == TokenKind.UNIT_RESOLUTION_DPCM ||
        unit == TokenKind.UNIT_RESOLUTION_DPPX);
  }

  @override
  ResolutionTerm clone() => ResolutionTerm(value, text, span, unit);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitResolutionTerm(this);
}

class ChTerm extends UnitTerm {
  ChTerm(var value, String t, SourceSpan span,
      [int unit = TokenKind.UNIT_LENGTH_PX])
      : super(value, t, span, unit) {
    assert(unit == TokenKind.UNIT_CH);
  }

  @override
  ChTerm clone() => ChTerm(value, text, span, unit);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitChTerm(this);
}

class RemTerm extends UnitTerm {
  RemTerm(var value, String t, SourceSpan span,
      [int unit = TokenKind.UNIT_LENGTH_PX])
      : super(value, t, span, unit) {
    assert(unit == TokenKind.UNIT_REM);
  }

  @override
  RemTerm clone() => RemTerm(value, text, span, unit);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitRemTerm(this);
}

class ViewportTerm extends UnitTerm {
  ViewportTerm(var value, String t, SourceSpan span,
      [int unit = TokenKind.UNIT_LENGTH_PX])
      : super(value, t, span, unit) {
    assert(unit == TokenKind.UNIT_VIEWPORT_VW ||
        unit == TokenKind.UNIT_VIEWPORT_VH ||
        unit == TokenKind.UNIT_VIEWPORT_VMIN ||
        unit == TokenKind.UNIT_VIEWPORT_VMAX);
  }

  @override
  ViewportTerm clone() => ViewportTerm(value, text, span, unit);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitViewportTerm(this);
}

/// Type to signal a bad hex value for HexColorTerm.value.
class BAD_HEX_VALUE {}

class HexColorTerm extends LiteralTerm {
  HexColorTerm(var value, String t, SourceSpan span) : super(value, t, span);

  @override
  HexColorTerm clone() => HexColorTerm(value, text, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitHexColorTerm(this);
}

class FunctionTerm extends LiteralTerm {
  final Expressions _params;

  FunctionTerm(var value, String t, this._params, SourceSpan span)
      : super(value, t, span);

  @override
  FunctionTerm clone() => FunctionTerm(value, text, _params.clone(), span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitFunctionTerm(this);
}

/// A "\9" was encountered at the end of the expression and before a semi-colon.
/// This is an IE trick to ignore a property or value except by IE 8 and older
/// browsers.
class IE8Term extends LiteralTerm {
  IE8Term(SourceSpan span) : super('\\9', '\\9', span);
  @override
  IE8Term clone() => IE8Term(span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitIE8Term(this);
}

class GroupTerm extends Expression {
  final List<LiteralTerm> _terms;

  GroupTerm(SourceSpan span)
      : _terms = [],
        super(span);

  void add(LiteralTerm term) {
    _terms.add(term);
  }

  @override
  GroupTerm clone() => GroupTerm(span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitGroupTerm(this);
}

class ItemTerm extends NumberTerm {
  ItemTerm(dynamic value, String t, SourceSpan span) : super(value, t, span);

  @override
  ItemTerm clone() => ItemTerm(value, text, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitItemTerm(this);
}

class Expressions extends Expression {
  final List<Expression> expressions = [];

  Expressions(SourceSpan span) : super(span);

  void add(Expression expression) {
    expressions.add(expression);
  }

  @override
  Expressions clone() {
    var clonedExprs = Expressions(span);
    for (var expr in expressions) {
      clonedExprs.add(expr.clone());
    }
    return clonedExprs;
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitExpressions(this);
}

class BinaryExpression extends Expression {
  final Token op;
  final Expression x;
  final Expression y;

  BinaryExpression(this.op, this.x, this.y, SourceSpan span) : super(span);

  @override
  BinaryExpression clone() => BinaryExpression(op, x.clone(), y.clone(), span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitBinaryExpression(this);
}

class UnaryExpression extends Expression {
  final Token op;
  final Expression self;

  UnaryExpression(this.op, this.self, SourceSpan span) : super(span);

  @override
  UnaryExpression clone() => UnaryExpression(op, self.clone(), span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitUnaryExpression(this);
}

abstract class DartStyleExpression extends TreeNode {
  static const int unknownType = 0;
  static const int fontStyle = 1;
  static const int marginStyle = 2;
  static const int borderStyle = 3;
  static const int paddingStyle = 4;
  static const int heightStyle = 5;
  static const int widthStyle = 6;

  final int _styleType;
  int priority;

  DartStyleExpression(this._styleType, SourceSpan span) : super(span);

  // Merges give 2 DartStyleExpression (or derived from DartStyleExpression,
  // e.g., FontExpression, etc.) will merge if the two expressions are of the
  // same property name (implies same exact type e.g, FontExpression).
  DartStyleExpression merged(DartStyleExpression newDartExpr);

  bool get isUnknown => _styleType == 0 || _styleType == null;
  bool get isFont => _styleType == fontStyle;
  bool get isMargin => _styleType == marginStyle;
  bool get isBorder => _styleType == borderStyle;
  bool get isPadding => _styleType == paddingStyle;
  bool get isHeight => _styleType == heightStyle;
  bool get isWidth => _styleType == widthStyle;
  bool get isBoxExpression => isMargin || isBorder || isPadding;

  bool isSame(DartStyleExpression other) => _styleType == other._styleType;

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitDartStyleExpression(this);
}

class FontExpression extends DartStyleExpression {
  final Font font;

  //   font-style font-variant font-weight font-size/line-height font-family
  // TODO(terry): Only px/pt for now need to handle all possible units to
  //              support calc expressions on units.
  FontExpression(SourceSpan span,
      {Object /* LengthTerm | num */ size,
      List<String> family,
      int weight,
      String style,
      String variant,
      LineHeight lineHeight})
      : font = Font(
            size: size is LengthTerm ? size.value : size as num,
            family: family,
            weight: weight,
            style: style,
            variant: variant,
            lineHeight: lineHeight),
        super(DartStyleExpression.fontStyle, span);

  @override
  FontExpression merged(DartStyleExpression newFontExpr) {
    if (newFontExpr is FontExpression && isFont && newFontExpr.isFont) {
      return FontExpression.merge(this, newFontExpr);
    }
    return null;
  }

  /// Merge the two FontExpression and return the result.
  factory FontExpression.merge(FontExpression x, FontExpression y) {
    return FontExpression._merge(x, y, y.span);
  }

  FontExpression._merge(FontExpression x, FontExpression y, SourceSpan span)
      : font = Font.merge(x.font, y.font),
        super(DartStyleExpression.fontStyle, span);

  @override
  FontExpression clone() => FontExpression(span,
      size: font.size,
      family: font.family,
      weight: font.weight,
      style: font.style,
      variant: font.variant,
      lineHeight: font.lineHeight);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitFontExpression(this);
}

abstract class BoxExpression extends DartStyleExpression {
  final BoxEdge box;

  BoxExpression(int styleType, SourceSpan span, this.box)
      : super(styleType, span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitBoxExpression(this);

  String get formattedBoxEdge {
    if (box.top == box.left && box.top == box.bottom && box.top == box.right) {
      return '.uniform(${box.top})';
    } else {
      var left = box.left ?? 0;
      var top = box.top ?? 0;
      var right = box.right ?? 0;
      var bottom = box.bottom ?? 0;
      return '.clockwiseFromTop($top,$right,$bottom,$left)';
    }
  }
}

class MarginExpression extends BoxExpression {
  // TODO(terry): Does auto for margin need to be exposed to Dart UI framework?
  /// Margin expression ripped apart.
  MarginExpression(SourceSpan span, {num top, num right, num bottom, num left})
      : super(DartStyleExpression.marginStyle, span,
            BoxEdge(left, top, right, bottom));

  MarginExpression.boxEdge(SourceSpan span, BoxEdge box)
      : super(DartStyleExpression.marginStyle, span, box);

  @override
  MarginExpression merged(DartStyleExpression newMarginExpr) {
    if (newMarginExpr is MarginExpression &&
        isMargin &&
        newMarginExpr.isMargin) {
      return MarginExpression.merge(this, newMarginExpr);
    }

    return null;
  }

  /// Merge the two MarginExpressions and return the result.
  factory MarginExpression.merge(MarginExpression x, MarginExpression y) {
    return MarginExpression._merge(x, y, y.span);
  }

  MarginExpression._merge(
      MarginExpression x, MarginExpression y, SourceSpan span)
      : super(x._styleType, span, BoxEdge.merge(x.box, y.box));

  @override
  MarginExpression clone() => MarginExpression(span,
      top: box.top, right: box.right, bottom: box.bottom, left: box.left);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitMarginExpression(this);
}

class BorderExpression extends BoxExpression {
  /// Border expression ripped apart.
  BorderExpression(SourceSpan span, {num top, num right, num bottom, num left})
      : super(DartStyleExpression.borderStyle, span,
            BoxEdge(left, top, right, bottom));

  BorderExpression.boxEdge(SourceSpan span, BoxEdge box)
      : super(DartStyleExpression.borderStyle, span, box);

  @override
  BorderExpression merged(DartStyleExpression newBorderExpr) {
    if (newBorderExpr is BorderExpression &&
        isBorder &&
        newBorderExpr.isBorder) {
      return BorderExpression.merge(this, newBorderExpr);
    }

    return null;
  }

  /// Merge the two BorderExpression and return the result.
  factory BorderExpression.merge(BorderExpression x, BorderExpression y) {
    return BorderExpression._merge(x, y, y.span);
  }

  BorderExpression._merge(
      BorderExpression x, BorderExpression y, SourceSpan span)
      : super(
            DartStyleExpression.borderStyle, span, BoxEdge.merge(x.box, y.box));

  @override
  BorderExpression clone() => BorderExpression(span,
      top: box.top, right: box.right, bottom: box.bottom, left: box.left);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitBorderExpression(this);
}

class HeightExpression extends DartStyleExpression {
  final dynamic height;

  HeightExpression(SourceSpan span, this.height)
      : super(DartStyleExpression.heightStyle, span);

  @override
  HeightExpression merged(DartStyleExpression newHeightExpr) {
    if (newHeightExpr is DartStyleExpression &&
        isHeight &&
        newHeightExpr.isHeight) {
      return newHeightExpr;
    }

    return null;
  }

  @override
  HeightExpression clone() => HeightExpression(span, height);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitHeightExpression(this);
}

class WidthExpression extends DartStyleExpression {
  final dynamic width;

  WidthExpression(SourceSpan span, this.width)
      : super(DartStyleExpression.widthStyle, span);

  @override
  WidthExpression merged(DartStyleExpression newWidthExpr) {
    if (newWidthExpr is WidthExpression && isWidth && newWidthExpr.isWidth) {
      return newWidthExpr;
    }

    return null;
  }

  @override
  WidthExpression clone() => WidthExpression(span, width);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitWidthExpression(this);
}

class PaddingExpression extends BoxExpression {
  /// Padding expression ripped apart.
  PaddingExpression(SourceSpan span, {num top, num right, num bottom, num left})
      : super(DartStyleExpression.paddingStyle, span,
            BoxEdge(left, top, right, bottom));

  PaddingExpression.boxEdge(SourceSpan span, BoxEdge box)
      : super(DartStyleExpression.paddingStyle, span, box);

  @override
  PaddingExpression merged(DartStyleExpression newPaddingExpr) {
    if (newPaddingExpr is PaddingExpression &&
        isPadding &&
        newPaddingExpr.isPadding) {
      return PaddingExpression.merge(this, newPaddingExpr);
    }

    return null;
  }

  /// Merge the two PaddingExpression and return the result.
  factory PaddingExpression.merge(PaddingExpression x, PaddingExpression y) {
    return PaddingExpression._merge(x, y, y.span);
  }

  PaddingExpression._merge(
      PaddingExpression x, PaddingExpression y, SourceSpan span)
      : super(DartStyleExpression.paddingStyle, span,
            BoxEdge.merge(x.box, y.box));

  @override
  PaddingExpression clone() => PaddingExpression(span,
      top: box.top, right: box.right, bottom: box.bottom, left: box.left);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitPaddingExpression(this);
}
