Blame src/ast.hpp

Packit Service 7770af
#ifndef SASS_AST_H
Packit Service 7770af
#define SASS_AST_H
Packit Service 7770af
Packit Service 7770af
#include "sass.hpp"
Packit Service 7770af
#include <set>
Packit Service 7770af
#include <deque>
Packit Service 7770af
#include <vector>
Packit Service 7770af
#include <string>
Packit Service 7770af
#include <sstream>
Packit Service 7770af
#include <iostream>
Packit Service 7770af
#include <typeinfo>
Packit Service 7770af
#include <algorithm>
Packit Service 7770af
#include "sass/base.h"
Packit Service 7770af
#include "ast_fwd_decl.hpp"
Packit Service 7770af
Packit Service 7770af
#ifdef DEBUG_SHARED_PTR
Packit Service 7770af
Packit Service 7770af
#define ATTACH_VIRTUAL_AST_OPERATIONS(klass) \
Packit Service 7770af
  virtual klass##_Ptr copy(std::string, size_t) const = 0; \
Packit Service 7770af
  virtual klass##_Ptr clone(std::string, size_t) const = 0; \
Packit Service 7770af
Packit Service 7770af
#define ATTACH_AST_OPERATIONS(klass) \
Packit Service 7770af
  virtual klass##_Ptr copy(std::string, size_t) const; \
Packit Service 7770af
  virtual klass##_Ptr clone(std::string, size_t) const; \
Packit Service 7770af
Packit Service 7770af
#else
Packit Service 7770af
Packit Service 7770af
#define ATTACH_VIRTUAL_AST_OPERATIONS(klass) \
Packit Service 7770af
  virtual klass##_Ptr copy() const = 0; \
Packit Service 7770af
  virtual klass##_Ptr clone() const = 0; \
Packit Service 7770af
Packit Service 7770af
#define ATTACH_AST_OPERATIONS(klass) \
Packit Service 7770af
  virtual klass##_Ptr copy() const; \
Packit Service 7770af
  virtual klass##_Ptr clone() const; \
Packit Service 7770af
Packit Service 7770af
#endif
Packit Service 7770af
Packit Service 7770af
#ifdef __clang__
Packit Service 7770af
Packit Service 7770af
/*
Packit Service 7770af
 * There are some overloads used here that trigger the clang overload
Packit Service 7770af
 * hiding warning. Specifically:
Packit Service 7770af
 *
Packit Service 7770af
 * Type type() which hides string type() from Expression
Packit Service 7770af
 *
Packit Service 7770af
 */
Packit Service 7770af
#pragma clang diagnostic push
Packit Service 7770af
#pragma clang diagnostic ignored "-Woverloaded-virtual"
Packit Service 7770af
Packit Service 7770af
#endif
Packit Service 7770af
Packit Service 7770af
#include "util.hpp"
Packit Service 7770af
#include "units.hpp"
Packit Service 7770af
#include "context.hpp"
Packit Service 7770af
#include "position.hpp"
Packit Service 7770af
#include "constants.hpp"
Packit Service 7770af
#include "operation.hpp"
Packit Service 7770af
#include "position.hpp"
Packit Service 7770af
#include "inspect.hpp"
Packit Service 7770af
#include "source_map.hpp"
Packit Service 7770af
#include "environment.hpp"
Packit Service 7770af
#include "error_handling.hpp"
Packit Service 7770af
#include "ast_def_macros.hpp"
Packit Service 7770af
#include "ast_fwd_decl.hpp"
Packit Service 7770af
#include "source_map.hpp"
Packit Service 7770af
Packit Service 7770af
#include "sass.h"
Packit Service 7770af
Packit Service 7770af
namespace Sass {
Packit Service 7770af
Packit Service 7770af
  // easier to search with name
Packit Service 7770af
  const bool DELAYED = true;
Packit Service 7770af
Packit Service 7770af
  // ToDo: should this really be hardcoded
Packit Service 7770af
  // Note: most methods follow precision option
Packit Service 7770af
  const double NUMBER_EPSILON = 0.00000000000001;
Packit Service 7770af
Packit Service 7770af
  // ToDo: where does this fit best?
Packit Service 7770af
  // We don't share this with C-API?
Packit Service 7770af
  class Operand {
Packit Service 7770af
    public:
Packit Service 7770af
      Operand(Sass_OP operand, bool ws_before = false, bool ws_after = false)
Packit Service 7770af
      : operand(operand), ws_before(ws_before), ws_after(ws_after)
Packit Service 7770af
      { }
Packit Service 7770af
    public:
Packit Service 7770af
      enum Sass_OP operand;
Packit Service 7770af
      bool ws_before;
Packit Service 7770af
      bool ws_after;
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  //////////////////////////////////////////////////////////
Packit Service 7770af
  // `hash_combine` comes from boost (functional/hash):
Packit Service 7770af
  // http://www.boost.org/doc/libs/1_35_0/doc/html/hash/combine.html
Packit Service 7770af
  // Boost Software License - Version 1.0
Packit Service 7770af
  // http://www.boost.org/users/license.html
Packit Service 7770af
  template <typename T>
Packit Service 7770af
  void hash_combine (std::size_t& seed, const T& val)
Packit Service 7770af
  {
Packit Service 7770af
    seed ^= std::hash<T>()(val) + 0x9e3779b9
Packit Service 7770af
             + (seed<<6) + (seed>>2);
Packit Service 7770af
  }
Packit Service 7770af
  //////////////////////////////////////////////////////////
Packit Service 7770af
Packit Service 7770af
  //////////////////////////////////////////////////////////
Packit Service 7770af
  // Abstract base class for all abstract syntax tree nodes.
Packit Service 7770af
  //////////////////////////////////////////////////////////
Packit Service 7770af
  class AST_Node : public SharedObj {
Packit Service 7770af
    ADD_PROPERTY(ParserState, pstate)
Packit Service 7770af
  public:
Packit Service 7770af
    AST_Node(ParserState pstate)
Packit Service 7770af
    : pstate_(pstate)
Packit Service 7770af
    { }
Packit Service 7770af
    AST_Node(const AST_Node* ptr)
Packit Service 7770af
    : pstate_(ptr->pstate_)
Packit Service 7770af
    { }
Packit Service 7770af
Packit Service 7770af
    // AST_Node(AST_Node& ptr) = delete;
Packit Service 7770af
Packit Service 7770af
    virtual ~AST_Node() = 0;
Packit Service 7770af
    virtual size_t hash() { return 0; }
Packit Service 7770af
    ATTACH_VIRTUAL_AST_OPERATIONS(AST_Node);
Packit Service 7770af
    virtual std::string inspect() const { return to_string({ INSPECT, 5 }); }
Packit Service 7770af
    virtual std::string to_sass() const { return to_string({ TO_SASS, 5 }); }
Packit Service 7770af
    virtual const std::string to_string(Sass_Inspect_Options opt) const;
Packit Service 7770af
    virtual const std::string to_string() const;
Packit Service 7770af
    virtual void cloneChildren() {};
Packit Service 7770af
    // generic find function (not fully implemented yet)
Packit Service 7770af
    // ToDo: add specific implementions to all children
Packit Service 7770af
    virtual bool find ( bool (*f)(AST_Node_Obj) ) { return f(this); };
Packit Service 7770af
  public:
Packit Service 7770af
    void update_pstate(const ParserState& pstate);
Packit Service 7770af
  public:
Packit Service 7770af
    Offset off() { return pstate(); }
Packit Service 7770af
    Position pos() { return pstate(); }
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
  inline AST_Node::~AST_Node() { }
Packit Service 7770af
Packit Service 7770af
  //////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // define cast template now (need complete type)
Packit Service 7770af
  //////////////////////////////////////////////////////////////////////
Packit Service 7770af
Packit Service 7770af
  template<class T>
Packit Service 7770af
  T* Cast(AST_Node* ptr) {
Packit Service 7770af
    return ptr && typeid(T) == typeid(*ptr) ?
Packit Service 7770af
           static_cast<T*>(ptr) : NULL;
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  template<class T>
Packit Service 7770af
  const T* Cast(const AST_Node* ptr) {
Packit Service 7770af
    return ptr && typeid(T) == typeid(*ptr) ?
Packit Service 7770af
           static_cast<const T*>(ptr) : NULL;
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  //////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Abstract base class for expressions. This side of the AST hierarchy
Packit Service 7770af
  // represents elements in value contexts, which exist primarily to be
Packit Service 7770af
  // evaluated and returned.
Packit Service 7770af
  //////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class Expression : public AST_Node {
Packit Service 7770af
  public:
Packit Service 7770af
    enum Concrete_Type {
Packit Service 7770af
      NONE,
Packit Service 7770af
      BOOLEAN,
Packit Service 7770af
      NUMBER,
Packit Service 7770af
      COLOR,
Packit Service 7770af
      STRING,
Packit Service 7770af
      LIST,
Packit Service 7770af
      MAP,
Packit Service 7770af
      SELECTOR,
Packit Service 7770af
      NULL_VAL,
Packit Service 7770af
      C_WARNING,
Packit Service 7770af
      C_ERROR,
Packit Service 7770af
      FUNCTION,
Packit Service 7770af
      VARIABLE,
Packit Service 7770af
      NUM_TYPES
Packit Service 7770af
    };
Packit Service 7770af
    enum Simple_Type {
Packit Service 7770af
      SIMPLE,
Packit Service 7770af
      ATTR_SEL,
Packit Service 7770af
      PSEUDO_SEL,
Packit Service 7770af
      WRAPPED_SEL,
Packit Service 7770af
    };
Packit Service 7770af
  private:
Packit Service 7770af
    // expressions in some contexts shouldn't be evaluated
Packit Service 7770af
    ADD_PROPERTY(bool, is_delayed)
Packit Service 7770af
    ADD_PROPERTY(bool, is_expanded)
Packit Service 7770af
    ADD_PROPERTY(bool, is_interpolant)
Packit Service 7770af
    ADD_PROPERTY(Concrete_Type, concrete_type)
Packit Service 7770af
  public:
Packit Service 7770af
    Expression(ParserState pstate,
Packit Service 7770af
               bool d = false, bool e = false, bool i = false, Concrete_Type ct = NONE)
Packit Service 7770af
    : AST_Node(pstate),
Packit Service 7770af
      is_delayed_(d),
Packit Service 7770af
      is_expanded_(e),
Packit Service 7770af
      is_interpolant_(i),
Packit Service 7770af
      concrete_type_(ct)
Packit Service 7770af
    { }
Packit Service 7770af
    Expression(const Expression* ptr)
Packit Service 7770af
    : AST_Node(ptr),
Packit Service 7770af
      is_delayed_(ptr->is_delayed_),
Packit Service 7770af
      is_expanded_(ptr->is_expanded_),
Packit Service 7770af
      is_interpolant_(ptr->is_interpolant_),
Packit Service 7770af
      concrete_type_(ptr->concrete_type_)
Packit Service 7770af
    { }
Packit Service 7770af
    virtual operator bool() { return true; }
Packit Service 7770af
    virtual ~Expression() { }
Packit Service 7770af
    virtual std::string type() const { return ""; /* TODO: raise an error? */ }
Packit Service 7770af
    virtual bool is_invisible() const { return false; }
Packit Service 7770af
    static std::string type_name() { return ""; }
Packit Service 7770af
    virtual bool is_false() { return false; }
Packit Service 7770af
    // virtual bool is_true() { return !is_false(); }
Packit Service 7770af
    virtual bool operator== (const Expression& rhs) const { return false; }
Packit Service 7770af
    virtual bool eq(const Expression& rhs) const { return *this == rhs; };
Packit Service 7770af
    virtual void set_delayed(bool delayed) { is_delayed(delayed); }
Packit Service 7770af
    virtual bool has_interpolant() const { return is_interpolant(); }
Packit Service 7770af
    virtual bool is_left_interpolant() const { return is_interpolant(); }
Packit Service 7770af
    virtual bool is_right_interpolant() const { return is_interpolant(); }
Packit Service 7770af
    virtual std::string inspect() const { return to_string({ INSPECT, 5 }); }
Packit Service 7770af
    virtual std::string to_sass() const { return to_string({ TO_SASS, 5 }); }
Packit Service 7770af
    ATTACH_VIRTUAL_AST_OPERATIONS(Expression);
Packit Service 7770af
    virtual size_t hash() { return 0; }
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  //////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Still just an expression, but with a to_string method
Packit Service 7770af
  //////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class PreValue : public Expression {
Packit Service 7770af
  public:
Packit Service 7770af
    PreValue(ParserState pstate,
Packit Service 7770af
               bool d = false, bool e = false, bool i = false, Concrete_Type ct = NONE)
Packit Service 7770af
    : Expression(pstate, d, e, i, ct)
Packit Service 7770af
    { }
Packit Service 7770af
    PreValue(const PreValue* ptr)
Packit Service 7770af
    : Expression(ptr)
Packit Service 7770af
    { }
Packit Service 7770af
    ATTACH_VIRTUAL_AST_OPERATIONS(PreValue);
Packit Service 7770af
    virtual ~PreValue() { }
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  //////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // base class for values that support operations
Packit Service 7770af
  //////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class Value : public Expression {
Packit Service 7770af
  public:
Packit Service 7770af
    Value(ParserState pstate,
Packit Service 7770af
          bool d = false, bool e = false, bool i = false, Concrete_Type ct = NONE)
Packit Service 7770af
    : Expression(pstate, d, e, i, ct)
Packit Service 7770af
    { }
Packit Service 7770af
    Value(const Value* ptr)
Packit Service 7770af
    : Expression(ptr)
Packit Service 7770af
    { }
Packit Service 7770af
    ATTACH_VIRTUAL_AST_OPERATIONS(Value);
Packit Service 7770af
    virtual bool operator== (const Expression& rhs) const = 0;
Packit Service 7770af
  };
Packit Service 7770af
}
Packit Service 7770af
Packit Service 7770af
/////////////////////////////////////////////////////////////////////////////////////
Packit Service 7770af
// Hash method specializations for std::unordered_map to work with Sass::Expression
Packit Service 7770af
/////////////////////////////////////////////////////////////////////////////////////
Packit Service 7770af
Packit Service 7770af
namespace std {
Packit Service 7770af
  template<>
Packit Service 7770af
  struct hash<Sass::Expression_Obj>
Packit Service 7770af
  {
Packit Service 7770af
    size_t operator()(Sass::Expression_Obj s) const
Packit Service 7770af
    {
Packit Service 7770af
      return s->hash();
Packit Service 7770af
    }
Packit Service 7770af
  };
Packit Service 7770af
  template<>
Packit Service 7770af
  struct equal_to<Sass::Expression_Obj>
Packit Service 7770af
  {
Packit Service 7770af
    bool operator()( Sass::Expression_Obj lhs,  Sass::Expression_Obj rhs) const
Packit Service 7770af
    {
Packit Service 7770af
      return lhs->hash() == rhs->hash();
Packit Service 7770af
    }
Packit Service 7770af
  };
Packit Service 7770af
}
Packit Service 7770af
Packit Service 7770af
namespace Sass {
Packit Service 7770af
Packit Service 7770af
  /////////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Mixin class for AST nodes that should behave like vectors. Uses the
Packit Service 7770af
  // "Template Method" design pattern to allow subclasses to adjust their flags
Packit Service 7770af
  // when certain objects are pushed.
Packit Service 7770af
  /////////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  template <typename T>
Packit Service 7770af
  class Vectorized {
Packit Service 7770af
    std::vector<T> elements_;
Packit Service 7770af
  protected:
Packit Service 7770af
    size_t hash_;
Packit Service 7770af
    void reset_hash() { hash_ = 0; }
Packit Service 7770af
    virtual void adjust_after_pushing(T element) { }
Packit Service 7770af
  public:
Packit Service 7770af
    Vectorized(size_t s = 0) : elements_(std::vector<T>()), hash_(0)
Packit Service 7770af
    { elements_.reserve(s); }
Packit Service 7770af
    virtual ~Vectorized() = 0;
Packit Service 7770af
    size_t length() const   { return elements_.size(); }
Packit Service 7770af
    bool empty() const      { return elements_.empty(); }
Packit Service 7770af
    void clear()            { return elements_.clear(); }
Packit Service 7770af
    T last() const          { return elements_.back(); }
Packit Service 7770af
    T first() const         { return elements_.front(); }
Packit Service 7770af
    T& operator[](size_t i) { return elements_[i]; }
Packit Service 7770af
    virtual const T& at(size_t i) const { return elements_.at(i); }
Packit Service 7770af
    virtual T& at(size_t i) { return elements_.at(i); }
Packit Service 7770af
    const T& operator[](size_t i) const { return elements_[i]; }
Packit Service 7770af
    virtual void append(T element)
Packit Service 7770af
    {
Packit Service 7770af
      if (element) {
Packit Service 7770af
        reset_hash();
Packit Service 7770af
        elements_.push_back(element);
Packit Service 7770af
        adjust_after_pushing(element);
Packit Service 7770af
      }
Packit Service 7770af
    }
Packit Service 7770af
    virtual void concat(Vectorized* v)
Packit Service 7770af
    {
Packit Service 7770af
      for (size_t i = 0, L = v->length(); i < L; ++i) this->append((*v)[i]);
Packit Service 7770af
    }
Packit Service 7770af
    Vectorized& unshift(T element)
Packit Service 7770af
    {
Packit Service 7770af
      elements_.insert(elements_.begin(), element);
Packit Service 7770af
      return *this;
Packit Service 7770af
    }
Packit Service 7770af
    std::vector<T>& elements() { return elements_; }
Packit Service 7770af
    const std::vector<T>& elements() const { return elements_; }
Packit Service 7770af
    std::vector<T>& elements(std::vector<T>& e) { elements_ = e; return elements_; }
Packit Service 7770af
Packit Service 7770af
    virtual size_t hash()
Packit Service 7770af
    {
Packit Service 7770af
      if (hash_ == 0) {
Packit Service 7770af
        for (T& el : elements_) {
Packit Service 7770af
          hash_combine(hash_, el->hash());
Packit Service 7770af
        }
Packit Service 7770af
      }
Packit Service 7770af
      return hash_;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    typename std::vector<T>::iterator end() { return elements_.end(); }
Packit Service 7770af
    typename std::vector<T>::iterator begin() { return elements_.begin(); }
Packit Service 7770af
    typename std::vector<T>::const_iterator end() const { return elements_.end(); }
Packit Service 7770af
    typename std::vector<T>::const_iterator begin() const { return elements_.begin(); }
Packit Service 7770af
    typename std::vector<T>::iterator erase(typename std::vector<T>::iterator el) { return elements_.erase(el); }
Packit Service 7770af
    typename std::vector<T>::const_iterator erase(typename std::vector<T>::const_iterator el) { return elements_.erase(el); }
Packit Service 7770af
Packit Service 7770af
  };
Packit Service 7770af
  template <typename T>
Packit Service 7770af
  inline Vectorized<T>::~Vectorized() { }
Packit Service 7770af
Packit Service 7770af
  /////////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Mixin class for AST nodes that should behave like a hash table. Uses an
Packit Service 7770af
  // extra <std::vector> internally to maintain insertion order for interation.
Packit Service 7770af
  /////////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class Hashed {
Packit Service 7770af
  private:
Packit Service 7770af
    ExpressionMap elements_;
Packit Service 7770af
    std::vector<Expression_Obj> list_;
Packit Service 7770af
  protected:
Packit Service 7770af
    size_t hash_;
Packit Service 7770af
    Expression_Obj duplicate_key_;
Packit Service 7770af
    void reset_hash() { hash_ = 0; }
Packit Service 7770af
    void reset_duplicate_key() { duplicate_key_ = 0; }
Packit Service 7770af
    virtual void adjust_after_pushing(std::pair<Expression_Obj, Expression_Obj> p) { }
Packit Service 7770af
  public:
Packit Service 7770af
    Hashed(size_t s = 0)
Packit Service 7770af
    : elements_(ExpressionMap(s)),
Packit Service 7770af
      list_(std::vector<Expression_Obj>()),
Packit Service 7770af
      hash_(0), duplicate_key_(NULL)
Packit Service 7770af
    { elements_.reserve(s); list_.reserve(s); }
Packit Service 7770af
    virtual ~Hashed();
Packit Service 7770af
    size_t length() const                  { return list_.size(); }
Packit Service 7770af
    bool empty() const                     { return list_.empty(); }
Packit Service 7770af
    bool has(Expression_Obj k) const          { return elements_.count(k) == 1; }
Packit Service 7770af
    Expression_Obj at(Expression_Obj k) const;
Packit Service 7770af
    bool has_duplicate_key() const         { return duplicate_key_ != 0; }
Packit Service 7770af
    Expression_Obj get_duplicate_key() const  { return duplicate_key_; }
Packit Service 7770af
    const ExpressionMap elements() { return elements_; }
Packit Service 7770af
    Hashed& operator<<(std::pair<Expression_Obj, Expression_Obj> p)
Packit Service 7770af
    {
Packit Service 7770af
      reset_hash();
Packit Service 7770af
Packit Service 7770af
      if (!has(p.first)) list_.push_back(p.first);
Packit Service 7770af
      else if (!duplicate_key_) duplicate_key_ = p.first;
Packit Service 7770af
Packit Service 7770af
      elements_[p.first] = p.second;
Packit Service 7770af
Packit Service 7770af
      adjust_after_pushing(p);
Packit Service 7770af
      return *this;
Packit Service 7770af
    }
Packit Service 7770af
    Hashed& operator+=(Hashed* h)
Packit Service 7770af
    {
Packit Service 7770af
      if (length() == 0) {
Packit Service 7770af
        this->elements_ = h->elements_;
Packit Service 7770af
        this->list_ = h->list_;
Packit Service 7770af
        return *this;
Packit Service 7770af
      }
Packit Service 7770af
Packit Service 7770af
      for (auto key : h->keys()) {
Packit Service 7770af
        *this << std::make_pair(key, h->at(key));
Packit Service 7770af
      }
Packit Service 7770af
Packit Service 7770af
      reset_duplicate_key();
Packit Service 7770af
      return *this;
Packit Service 7770af
    }
Packit Service 7770af
    const ExpressionMap& pairs() const { return elements_; }
Packit Service 7770af
    const std::vector<Expression_Obj>& keys() const { return list_; }
Packit Service 7770af
Packit Service 7770af
//    std::unordered_map<Expression_Obj, Expression_Obj>::iterator end() { return elements_.end(); }
Packit Service 7770af
//    std::unordered_map<Expression_Obj, Expression_Obj>::iterator begin() { return elements_.begin(); }
Packit Service 7770af
//    std::unordered_map<Expression_Obj, Expression_Obj>::const_iterator end() const { return elements_.end(); }
Packit Service 7770af
//    std::unordered_map<Expression_Obj, Expression_Obj>::const_iterator begin() const { return elements_.begin(); }
Packit Service 7770af
Packit Service 7770af
  };
Packit Service 7770af
  inline Hashed::~Hashed() { }
Packit Service 7770af
Packit Service 7770af
Packit Service 7770af
  /////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Abstract base class for statements. This side of the AST hierarchy
Packit Service 7770af
  // represents elements in expansion contexts, which exist primarily to be
Packit Service 7770af
  // rewritten and macro-expanded.
Packit Service 7770af
  /////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class Statement : public AST_Node {
Packit Service 7770af
  public:
Packit Service 7770af
    enum Statement_Type {
Packit Service 7770af
      NONE,
Packit Service 7770af
      RULESET,
Packit Service 7770af
      MEDIA,
Packit Service 7770af
      DIRECTIVE,
Packit Service 7770af
      SUPPORTS,
Packit Service 7770af
      ATROOT,
Packit Service 7770af
      BUBBLE,
Packit Service 7770af
      CONTENT,
Packit Service 7770af
      KEYFRAMERULE,
Packit Service 7770af
      DECLARATION,
Packit Service 7770af
      ASSIGNMENT,
Packit Service 7770af
      IMPORT_STUB,
Packit Service 7770af
      IMPORT,
Packit Service 7770af
      COMMENT,
Packit Service 7770af
      WARNING,
Packit Service 7770af
      RETURN,
Packit Service 7770af
      EXTEND,
Packit Service 7770af
      ERROR,
Packit Service 7770af
      DEBUGSTMT,
Packit Service 7770af
      WHILE,
Packit Service 7770af
      EACH,
Packit Service 7770af
      FOR,
Packit Service 7770af
      IF
Packit Service 7770af
    };
Packit Service 7770af
  private:
Packit Service 7770af
    ADD_PROPERTY(Statement_Type, statement_type)
Packit Service 7770af
    ADD_PROPERTY(size_t, tabs)
Packit Service 7770af
    ADD_PROPERTY(bool, group_end)
Packit Service 7770af
  public:
Packit Service 7770af
    Statement(ParserState pstate, Statement_Type st = NONE, size_t t = 0)
Packit Service 7770af
    : AST_Node(pstate), statement_type_(st), tabs_(t), group_end_(false)
Packit Service 7770af
     { }
Packit Service 7770af
    Statement(const Statement* ptr)
Packit Service 7770af
    : AST_Node(ptr),
Packit Service 7770af
      statement_type_(ptr->statement_type_),
Packit Service 7770af
      tabs_(ptr->tabs_),
Packit Service 7770af
      group_end_(ptr->group_end_)
Packit Service 7770af
     { }
Packit Service 7770af
    virtual ~Statement() = 0;
Packit Service 7770af
    // needed for rearranging nested rulesets during CSS emission
Packit Service 7770af
    virtual bool   is_invisible() const { return false; }
Packit Service 7770af
    virtual bool   bubbles() { return false; }
Packit Service 7770af
    virtual bool has_content()
Packit Service 7770af
    {
Packit Service 7770af
      return statement_type_ == CONTENT;
Packit Service 7770af
    }
Packit Service 7770af
  };
Packit Service 7770af
  inline Statement::~Statement() { }
Packit Service 7770af
Packit Service 7770af
  ////////////////////////
Packit Service 7770af
  // Blocks of statements.
Packit Service 7770af
  ////////////////////////
Packit Service 7770af
  class Block : public Statement, public Vectorized<Statement_Obj> {
Packit Service 7770af
    ADD_PROPERTY(bool, is_root)
Packit Service 7770af
    // needed for properly formatted CSS emission
Packit Service 7770af
  protected:
Packit Service 7770af
    void adjust_after_pushing(Statement_Obj s)
Packit Service 7770af
    {
Packit Service 7770af
    }
Packit Service 7770af
  public:
Packit Service 7770af
    Block(ParserState pstate, size_t s = 0, bool r = false)
Packit Service 7770af
    : Statement(pstate),
Packit Service 7770af
      Vectorized<Statement_Obj>(s),
Packit Service 7770af
      is_root_(r)
Packit Service 7770af
    { }
Packit Service 7770af
    Block(const Block* ptr)
Packit Service 7770af
    : Statement(ptr),
Packit Service 7770af
      Vectorized<Statement_Obj>(*ptr),
Packit Service 7770af
      is_root_(ptr->is_root_)
Packit Service 7770af
    { }
Packit Service 7770af
    virtual bool has_content()
Packit Service 7770af
    {
Packit Service 7770af
      for (size_t i = 0, L = elements().size(); i < L; ++i) {
Packit Service 7770af
        if (elements()[i]->has_content()) return true;
Packit Service 7770af
      }
Packit Service 7770af
      return Statement::has_content();
Packit Service 7770af
    }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Block)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Abstract base class for statements that contain blocks of statements.
Packit Service 7770af
  ////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class Has_Block : public Statement {
Packit Service 7770af
    ADD_PROPERTY(Block_Obj, block)
Packit Service 7770af
  public:
Packit Service 7770af
    Has_Block(ParserState pstate, Block_Obj b)
Packit Service 7770af
    : Statement(pstate), block_(b)
Packit Service 7770af
    { }
Packit Service 7770af
    Has_Block(const Has_Block* ptr)
Packit Service 7770af
    : Statement(ptr), block_(ptr->block_)
Packit Service 7770af
    { }
Packit Service 7770af
    virtual bool has_content()
Packit Service 7770af
    {
Packit Service 7770af
      return (block_ && block_->has_content()) || Statement::has_content();
Packit Service 7770af
    }
Packit Service 7770af
    virtual ~Has_Block() = 0;
Packit Service 7770af
  };
Packit Service 7770af
  inline Has_Block::~Has_Block() { }
Packit Service 7770af
Packit Service 7770af
  /////////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Rulesets (i.e., sets of styles headed by a selector and containing a block
Packit Service 7770af
  // of style declarations.
Packit Service 7770af
  /////////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class Ruleset : public Has_Block {
Packit Service 7770af
    ADD_PROPERTY(Selector_List_Obj, selector)
Packit Service 7770af
    ADD_PROPERTY(bool, is_root);
Packit Service 7770af
  public:
Packit Service 7770af
    Ruleset(ParserState pstate, Selector_List_Obj s = 0, Block_Obj b = 0)
Packit Service 7770af
    : Has_Block(pstate, b), selector_(s), is_root_(false)
Packit Service 7770af
    { statement_type(RULESET); }
Packit Service 7770af
    Ruleset(const Ruleset* ptr)
Packit Service 7770af
    : Has_Block(ptr),
Packit Service 7770af
      selector_(ptr->selector_),
Packit Service 7770af
      is_root_(ptr->is_root_)
Packit Service 7770af
    { statement_type(RULESET); }
Packit Service 7770af
    bool is_invisible() const;
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Ruleset)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  /////////////////
Packit Service 7770af
  // Bubble.
Packit Service 7770af
  /////////////////
Packit Service 7770af
  class Bubble : public Statement {
Packit Service 7770af
    ADD_PROPERTY(Statement_Obj, node)
Packit Service 7770af
    ADD_PROPERTY(bool, group_end)
Packit Service 7770af
  public:
Packit Service 7770af
    Bubble(ParserState pstate, Statement_Obj n, Statement_Obj g = 0, size_t t = 0)
Packit Service 7770af
    : Statement(pstate, Statement::BUBBLE, t), node_(n), group_end_(g == 0)
Packit Service 7770af
    { }
Packit Service 7770af
    Bubble(const Bubble* ptr)
Packit Service 7770af
    : Statement(ptr),
Packit Service 7770af
      node_(ptr->node_),
Packit Service 7770af
      group_end_(ptr->group_end_)
Packit Service 7770af
    { }
Packit Service 7770af
    bool bubbles() { return true; }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Bubble)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  /////////////////
Packit Service 7770af
  // Trace.
Packit Service 7770af
  /////////////////
Packit Service 7770af
  class Trace : public Has_Block {
Packit Service 7770af
    ADD_CONSTREF(std::string, name)
Packit Service 7770af
  public:
Packit Service 7770af
    Trace(ParserState pstate, std::string n, Block_Obj b = 0)
Packit Service 7770af
    : Has_Block(pstate, b), name_(n)
Packit Service 7770af
    { }
Packit Service 7770af
    Trace(const Trace* ptr)
Packit Service 7770af
    : Has_Block(ptr),
Packit Service 7770af
      name_(ptr->name_)
Packit Service 7770af
    { }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Trace)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  /////////////////
Packit Service 7770af
  // Media queries.
Packit Service 7770af
  /////////////////
Packit Service 7770af
  class Media_Block : public Has_Block {
Packit Service 7770af
    ADD_PROPERTY(List_Obj, media_queries)
Packit Service 7770af
  public:
Packit Service 7770af
    Media_Block(ParserState pstate, List_Obj mqs, Block_Obj b)
Packit Service 7770af
    : Has_Block(pstate, b), media_queries_(mqs)
Packit Service 7770af
    { statement_type(MEDIA); }
Packit Service 7770af
    Media_Block(const Media_Block* ptr)
Packit Service 7770af
    : Has_Block(ptr), media_queries_(ptr->media_queries_)
Packit Service 7770af
    { statement_type(MEDIA); }
Packit Service 7770af
    bool bubbles() { return true; }
Packit Service 7770af
    bool is_invisible() const;
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Media_Block)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ///////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // At-rules -- arbitrary directives beginning with "@" that may have an
Packit Service 7770af
  // optional statement block.
Packit Service 7770af
  ///////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class Directive : public Has_Block {
Packit Service 7770af
    ADD_CONSTREF(std::string, keyword)
Packit Service 7770af
    ADD_PROPERTY(Selector_List_Obj, selector)
Packit Service 7770af
    ADD_PROPERTY(Expression_Obj, value)
Packit Service 7770af
  public:
Packit Service 7770af
    Directive(ParserState pstate, std::string kwd, Selector_List_Obj sel = 0, Block_Obj b = 0, Expression_Obj val = 0)
Packit Service 7770af
    : Has_Block(pstate, b), keyword_(kwd), selector_(sel), value_(val) // set value manually if needed
Packit Service 7770af
    { statement_type(DIRECTIVE); }
Packit Service 7770af
    Directive(const Directive* ptr)
Packit Service 7770af
    : Has_Block(ptr),
Packit Service 7770af
      keyword_(ptr->keyword_),
Packit Service 7770af
      selector_(ptr->selector_),
Packit Service 7770af
      value_(ptr->value_) // set value manually if needed
Packit Service 7770af
    { statement_type(DIRECTIVE); }
Packit Service 7770af
    bool bubbles() { return is_keyframes() || is_media(); }
Packit Service 7770af
    bool is_media() {
Packit Service 7770af
      return keyword_.compare("@-webkit-media") == 0 ||
Packit Service 7770af
             keyword_.compare("@-moz-media") == 0 ||
Packit Service 7770af
             keyword_.compare("@-o-media") == 0 ||
Packit Service 7770af
             keyword_.compare("@media") == 0;
Packit Service 7770af
    }
Packit Service 7770af
    bool is_keyframes() {
Packit Service 7770af
      return keyword_.compare("@-webkit-keyframes") == 0 ||
Packit Service 7770af
             keyword_.compare("@-moz-keyframes") == 0 ||
Packit Service 7770af
             keyword_.compare("@-o-keyframes") == 0 ||
Packit Service 7770af
             keyword_.compare("@keyframes") == 0;
Packit Service 7770af
    }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Directive)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ///////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Keyframe-rules -- the child blocks of "@keyframes" nodes.
Packit Service 7770af
  ///////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class Keyframe_Rule : public Has_Block {
Packit Service 7770af
    // according to css spec, this should be <keyframes-name>
Packit Service 7770af
    // <keyframes-name> = <custom-ident> | <string>
Packit Service 7770af
    ADD_PROPERTY(Selector_List_Obj, name)
Packit Service 7770af
  public:
Packit Service 7770af
    Keyframe_Rule(ParserState pstate, Block_Obj b)
Packit Service 7770af
    : Has_Block(pstate, b), name_()
Packit Service 7770af
    { statement_type(KEYFRAMERULE); }
Packit Service 7770af
    Keyframe_Rule(const Keyframe_Rule* ptr)
Packit Service 7770af
    : Has_Block(ptr), name_(ptr->name_)
Packit Service 7770af
    { statement_type(KEYFRAMERULE); }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Keyframe_Rule)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Declarations -- style rules consisting of a property name and values.
Packit Service 7770af
  ////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class Declaration : public Has_Block {
Packit Service 7770af
    ADD_PROPERTY(String_Obj, property)
Packit Service 7770af
    ADD_PROPERTY(Expression_Obj, value)
Packit Service 7770af
    ADD_PROPERTY(bool, is_important)
Packit Service 7770af
    ADD_PROPERTY(bool, is_indented)
Packit Service 7770af
  public:
Packit Service 7770af
    Declaration(ParserState pstate,
Packit Service 7770af
                String_Obj prop, Expression_Obj val, bool i = false, Block_Obj b = 0)
Packit Service 7770af
    : Has_Block(pstate, b), property_(prop), value_(val), is_important_(i), is_indented_(false)
Packit Service 7770af
    { statement_type(DECLARATION); }
Packit Service 7770af
    Declaration(const Declaration* ptr)
Packit Service 7770af
    : Has_Block(ptr),
Packit Service 7770af
      property_(ptr->property_),
Packit Service 7770af
      value_(ptr->value_),
Packit Service 7770af
      is_important_(ptr->is_important_),
Packit Service 7770af
      is_indented_(ptr->is_indented_)
Packit Service 7770af
    { statement_type(DECLARATION); }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Declaration)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  /////////////////////////////////////
Packit Service 7770af
  // Assignments -- variable and value.
Packit Service 7770af
  /////////////////////////////////////
Packit Service 7770af
  class Assignment : public Statement {
Packit Service 7770af
    ADD_CONSTREF(std::string, variable)
Packit Service 7770af
    ADD_PROPERTY(Expression_Obj, value)
Packit Service 7770af
    ADD_PROPERTY(bool, is_default)
Packit Service 7770af
    ADD_PROPERTY(bool, is_global)
Packit Service 7770af
  public:
Packit Service 7770af
    Assignment(ParserState pstate,
Packit Service 7770af
               std::string var, Expression_Obj val,
Packit Service 7770af
               bool is_default = false,
Packit Service 7770af
               bool is_global = false)
Packit Service 7770af
    : Statement(pstate), variable_(var), value_(val), is_default_(is_default), is_global_(is_global)
Packit Service 7770af
    { statement_type(ASSIGNMENT); }
Packit Service 7770af
    Assignment(const Assignment* ptr)
Packit Service 7770af
    : Statement(ptr),
Packit Service 7770af
      variable_(ptr->variable_),
Packit Service 7770af
      value_(ptr->value_),
Packit Service 7770af
      is_default_(ptr->is_default_),
Packit Service 7770af
      is_global_(ptr->is_global_)
Packit Service 7770af
    { statement_type(ASSIGNMENT); }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Assignment)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ////////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Import directives. CSS and Sass import lists can be intermingled, so it's
Packit Service 7770af
  // necessary to store a list of each in an Import node.
Packit Service 7770af
  ////////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class Import : public Statement {
Packit Service 7770af
    std::vector<Expression_Obj> urls_;
Packit Service 7770af
    std::vector<Include>     incs_;
Packit Service 7770af
    ADD_PROPERTY(List_Obj,      import_queries);
Packit Service 7770af
  public:
Packit Service 7770af
    Import(ParserState pstate)
Packit Service 7770af
    : Statement(pstate),
Packit Service 7770af
      urls_(std::vector<Expression_Obj>()),
Packit Service 7770af
      incs_(std::vector<Include>()),
Packit Service 7770af
      import_queries_()
Packit Service 7770af
    { statement_type(IMPORT); }
Packit Service 7770af
    Import(const Import* ptr)
Packit Service 7770af
    : Statement(ptr),
Packit Service 7770af
      urls_(ptr->urls_),
Packit Service 7770af
      incs_(ptr->incs_),
Packit Service 7770af
      import_queries_(ptr->import_queries_)
Packit Service 7770af
    { statement_type(IMPORT); }
Packit Service 7770af
    std::vector<Expression_Obj>& urls() { return urls_; }
Packit Service 7770af
    std::vector<Include>& incs() { return incs_; }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Import)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  // not yet resolved single import
Packit Service 7770af
  // so far we only know requested name
Packit Service 7770af
  class Import_Stub : public Statement {
Packit Service 7770af
    Include resource_;
Packit Service 7770af
  public:
Packit Service 7770af
    std::string abs_path() { return resource_.abs_path; };
Packit Service 7770af
    std::string imp_path() { return resource_.imp_path; };
Packit Service 7770af
    Include resource() { return resource_; };
Packit Service 7770af
Packit Service 7770af
    Import_Stub(ParserState pstate, Include res)
Packit Service 7770af
    : Statement(pstate), resource_(res)
Packit Service 7770af
    { statement_type(IMPORT_STUB); }
Packit Service 7770af
    Import_Stub(const Import_Stub* ptr)
Packit Service 7770af
    : Statement(ptr), resource_(ptr->resource_)
Packit Service 7770af
    { statement_type(IMPORT_STUB); }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Import_Stub)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  //////////////////////////////
Packit Service 7770af
  // The Sass `@warn` directive.
Packit Service 7770af
  //////////////////////////////
Packit Service 7770af
  class Warning : public Statement {
Packit Service 7770af
    ADD_PROPERTY(Expression_Obj, message)
Packit Service 7770af
  public:
Packit Service 7770af
    Warning(ParserState pstate, Expression_Obj msg)
Packit Service 7770af
    : Statement(pstate), message_(msg)
Packit Service 7770af
    { statement_type(WARNING); }
Packit Service 7770af
    Warning(const Warning* ptr)
Packit Service 7770af
    : Statement(ptr), message_(ptr->message_)
Packit Service 7770af
    { statement_type(WARNING); }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Warning)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ///////////////////////////////
Packit Service 7770af
  // The Sass `@error` directive.
Packit Service 7770af
  ///////////////////////////////
Packit Service 7770af
  class Error : public Statement {
Packit Service 7770af
    ADD_PROPERTY(Expression_Obj, message)
Packit Service 7770af
  public:
Packit Service 7770af
    Error(ParserState pstate, Expression_Obj msg)
Packit Service 7770af
    : Statement(pstate), message_(msg)
Packit Service 7770af
    { statement_type(ERROR); }
Packit Service 7770af
    Error(const Error* ptr)
Packit Service 7770af
    : Statement(ptr), message_(ptr->message_)
Packit Service 7770af
    { statement_type(ERROR); }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Error)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ///////////////////////////////
Packit Service 7770af
  // The Sass `@debug` directive.
Packit Service 7770af
  ///////////////////////////////
Packit Service 7770af
  class Debug : public Statement {
Packit Service 7770af
    ADD_PROPERTY(Expression_Obj, value)
Packit Service 7770af
  public:
Packit Service 7770af
    Debug(ParserState pstate, Expression_Obj val)
Packit Service 7770af
    : Statement(pstate), value_(val)
Packit Service 7770af
    { statement_type(DEBUGSTMT); }
Packit Service 7770af
    Debug(const Debug* ptr)
Packit Service 7770af
    : Statement(ptr), value_(ptr->value_)
Packit Service 7770af
    { statement_type(DEBUGSTMT); }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Debug)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ///////////////////////////////////////////
Packit Service 7770af
  // CSS comments. These may be interpolated.
Packit Service 7770af
  ///////////////////////////////////////////
Packit Service 7770af
  class Comment : public Statement {
Packit Service 7770af
    ADD_PROPERTY(String_Obj, text)
Packit Service 7770af
    ADD_PROPERTY(bool, is_important)
Packit Service 7770af
  public:
Packit Service 7770af
    Comment(ParserState pstate, String_Obj txt, bool is_important)
Packit Service 7770af
    : Statement(pstate), text_(txt), is_important_(is_important)
Packit Service 7770af
    { statement_type(COMMENT); }
Packit Service 7770af
    Comment(const Comment* ptr)
Packit Service 7770af
    : Statement(ptr),
Packit Service 7770af
      text_(ptr->text_),
Packit Service 7770af
      is_important_(ptr->is_important_)
Packit Service 7770af
    { statement_type(COMMENT); }
Packit Service 7770af
    virtual bool is_invisible() const
Packit Service 7770af
    { return /* is_important() == */ false; }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Comment)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ////////////////////////////////////
Packit Service 7770af
  // The Sass `@if` control directive.
Packit Service 7770af
  ////////////////////////////////////
Packit Service 7770af
  class If : public Has_Block {
Packit Service 7770af
    ADD_PROPERTY(Expression_Obj, predicate)
Packit Service 7770af
    ADD_PROPERTY(Block_Obj, alternative)
Packit Service 7770af
  public:
Packit Service 7770af
    If(ParserState pstate, Expression_Obj pred, Block_Obj con, Block_Obj alt = 0)
Packit Service 7770af
    : Has_Block(pstate, con), predicate_(pred), alternative_(alt)
Packit Service 7770af
    { statement_type(IF); }
Packit Service 7770af
    If(const If* ptr)
Packit Service 7770af
    : Has_Block(ptr),
Packit Service 7770af
      predicate_(ptr->predicate_),
Packit Service 7770af
      alternative_(ptr->alternative_)
Packit Service 7770af
    { statement_type(IF); }
Packit Service 7770af
    virtual bool has_content()
Packit Service 7770af
    {
Packit Service 7770af
      return Has_Block::has_content() || (alternative_ && alternative_->has_content());
Packit Service 7770af
    }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(If)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  /////////////////////////////////////
Packit Service 7770af
  // The Sass `@for` control directive.
Packit Service 7770af
  /////////////////////////////////////
Packit Service 7770af
  class For : public Has_Block {
Packit Service 7770af
    ADD_CONSTREF(std::string, variable)
Packit Service 7770af
    ADD_PROPERTY(Expression_Obj, lower_bound)
Packit Service 7770af
    ADD_PROPERTY(Expression_Obj, upper_bound)
Packit Service 7770af
    ADD_PROPERTY(bool, is_inclusive)
Packit Service 7770af
  public:
Packit Service 7770af
    For(ParserState pstate,
Packit Service 7770af
        std::string var, Expression_Obj lo, Expression_Obj hi, Block_Obj b, bool inc)
Packit Service 7770af
    : Has_Block(pstate, b),
Packit Service 7770af
      variable_(var), lower_bound_(lo), upper_bound_(hi), is_inclusive_(inc)
Packit Service 7770af
    { statement_type(FOR); }
Packit Service 7770af
    For(const For* ptr)
Packit Service 7770af
    : Has_Block(ptr),
Packit Service 7770af
      variable_(ptr->variable_),
Packit Service 7770af
      lower_bound_(ptr->lower_bound_),
Packit Service 7770af
      upper_bound_(ptr->upper_bound_),
Packit Service 7770af
      is_inclusive_(ptr->is_inclusive_)
Packit Service 7770af
    { statement_type(FOR); }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(For)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  //////////////////////////////////////
Packit Service 7770af
  // The Sass `@each` control directive.
Packit Service 7770af
  //////////////////////////////////////
Packit Service 7770af
  class Each : public Has_Block {
Packit Service 7770af
    ADD_PROPERTY(std::vector<std::string>, variables)
Packit Service 7770af
    ADD_PROPERTY(Expression_Obj, list)
Packit Service 7770af
  public:
Packit Service 7770af
    Each(ParserState pstate, std::vector<std::string> vars, Expression_Obj lst, Block_Obj b)
Packit Service 7770af
    : Has_Block(pstate, b), variables_(vars), list_(lst)
Packit Service 7770af
    { statement_type(EACH); }
Packit Service 7770af
    Each(const Each* ptr)
Packit Service 7770af
    : Has_Block(ptr), variables_(ptr->variables_), list_(ptr->list_)
Packit Service 7770af
    { statement_type(EACH); }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Each)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ///////////////////////////////////////
Packit Service 7770af
  // The Sass `@while` control directive.
Packit Service 7770af
  ///////////////////////////////////////
Packit Service 7770af
  class While : public Has_Block {
Packit Service 7770af
    ADD_PROPERTY(Expression_Obj, predicate)
Packit Service 7770af
  public:
Packit Service 7770af
    While(ParserState pstate, Expression_Obj pred, Block_Obj b)
Packit Service 7770af
    : Has_Block(pstate, b), predicate_(pred)
Packit Service 7770af
    { statement_type(WHILE); }
Packit Service 7770af
    While(const While* ptr)
Packit Service 7770af
    : Has_Block(ptr), predicate_(ptr->predicate_)
Packit Service 7770af
    { statement_type(WHILE); }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(While)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  /////////////////////////////////////////////////////////////
Packit Service 7770af
  // The @return directive for use inside SassScript functions.
Packit Service 7770af
  /////////////////////////////////////////////////////////////
Packit Service 7770af
  class Return : public Statement {
Packit Service 7770af
    ADD_PROPERTY(Expression_Obj, value)
Packit Service 7770af
  public:
Packit Service 7770af
    Return(ParserState pstate, Expression_Obj val)
Packit Service 7770af
    : Statement(pstate), value_(val)
Packit Service 7770af
    { statement_type(RETURN); }
Packit Service 7770af
    Return(const Return* ptr)
Packit Service 7770af
    : Statement(ptr), value_(ptr->value_)
Packit Service 7770af
    { statement_type(RETURN); }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Return)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ////////////////////////////////
Packit Service 7770af
  // The Sass `@extend` directive.
Packit Service 7770af
  ////////////////////////////////
Packit Service 7770af
  class Extension : public Statement {
Packit Service 7770af
    ADD_PROPERTY(Selector_List_Obj, selector)
Packit Service 7770af
  public:
Packit Service 7770af
    Extension(ParserState pstate, Selector_List_Obj s)
Packit Service 7770af
    : Statement(pstate), selector_(s)
Packit Service 7770af
    { statement_type(EXTEND); }
Packit Service 7770af
    Extension(const Extension* ptr)
Packit Service 7770af
    : Statement(ptr), selector_(ptr->selector_)
Packit Service 7770af
    { statement_type(EXTEND); }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Extension)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  /////////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Definitions for both mixins and functions. The two cases are distinguished
Packit Service 7770af
  // by a type tag.
Packit Service 7770af
  /////////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  struct Backtrace;
Packit Service 7770af
  typedef const char* Signature;
Packit Service 7770af
  typedef Expression_Ptr (*Native_Function)(Env&, Env&, Context&, Signature, ParserState, Backtrace*, std::vector<Selector_List_Obj>);
Packit Service 7770af
  class Definition : public Has_Block {
Packit Service 7770af
  public:
Packit Service 7770af
    enum Type { MIXIN, FUNCTION };
Packit Service 7770af
    ADD_CONSTREF(std::string, name)
Packit Service 7770af
    ADD_PROPERTY(Parameters_Obj, parameters)
Packit Service 7770af
    ADD_PROPERTY(Env*, environment)
Packit Service 7770af
    ADD_PROPERTY(Type, type)
Packit Service 7770af
    ADD_PROPERTY(Native_Function, native_function)
Packit Service 7770af
    ADD_PROPERTY(Sass_Function_Entry, c_function)
Packit Service 7770af
    ADD_PROPERTY(void*, cookie)
Packit Service 7770af
    ADD_PROPERTY(bool, is_overload_stub)
Packit Service 7770af
    ADD_PROPERTY(Signature, signature)
Packit Service 7770af
  public:
Packit Service 7770af
    Definition(const Definition* ptr)
Packit Service 7770af
    : Has_Block(ptr),
Packit Service 7770af
      name_(ptr->name_),
Packit Service 7770af
      parameters_(ptr->parameters_),
Packit Service 7770af
      environment_(ptr->environment_),
Packit Service 7770af
      type_(ptr->type_),
Packit Service 7770af
      native_function_(ptr->native_function_),
Packit Service 7770af
      c_function_(ptr->c_function_),
Packit Service 7770af
      cookie_(ptr->cookie_),
Packit Service 7770af
      is_overload_stub_(ptr->is_overload_stub_),
Packit Service 7770af
      signature_(ptr->signature_)
Packit Service 7770af
    { }
Packit Service 7770af
Packit Service 7770af
    Definition(ParserState pstate,
Packit Service 7770af
               std::string n,
Packit Service 7770af
               Parameters_Obj params,
Packit Service 7770af
               Block_Obj b,
Packit Service 7770af
               Type t)
Packit Service 7770af
    : Has_Block(pstate, b),
Packit Service 7770af
      name_(n),
Packit Service 7770af
      parameters_(params),
Packit Service 7770af
      environment_(0),
Packit Service 7770af
      type_(t),
Packit Service 7770af
      native_function_(0),
Packit Service 7770af
      c_function_(0),
Packit Service 7770af
      cookie_(0),
Packit Service 7770af
      is_overload_stub_(false),
Packit Service 7770af
      signature_(0)
Packit Service 7770af
    { }
Packit Service 7770af
    Definition(ParserState pstate,
Packit Service 7770af
               Signature sig,
Packit Service 7770af
               std::string n,
Packit Service 7770af
               Parameters_Obj params,
Packit Service 7770af
               Native_Function func_ptr,
Packit Service 7770af
               bool overload_stub = false)
Packit Service 7770af
    : Has_Block(pstate, 0),
Packit Service 7770af
      name_(n),
Packit Service 7770af
      parameters_(params),
Packit Service 7770af
      environment_(0),
Packit Service 7770af
      type_(FUNCTION),
Packit Service 7770af
      native_function_(func_ptr),
Packit Service 7770af
      c_function_(0),
Packit Service 7770af
      cookie_(0),
Packit Service 7770af
      is_overload_stub_(overload_stub),
Packit Service 7770af
      signature_(sig)
Packit Service 7770af
    { }
Packit Service 7770af
    Definition(ParserState pstate,
Packit Service 7770af
               Signature sig,
Packit Service 7770af
               std::string n,
Packit Service 7770af
               Parameters_Obj params,
Packit Service 7770af
               Sass_Function_Entry c_func,
Packit Service 7770af
               bool whatever,
Packit Service 7770af
               bool whatever2)
Packit Service 7770af
    : Has_Block(pstate, 0),
Packit Service 7770af
      name_(n),
Packit Service 7770af
      parameters_(params),
Packit Service 7770af
      environment_(0),
Packit Service 7770af
      type_(FUNCTION),
Packit Service 7770af
      native_function_(0),
Packit Service 7770af
      c_function_(c_func),
Packit Service 7770af
      cookie_(sass_function_get_cookie(c_func)),
Packit Service 7770af
      is_overload_stub_(false),
Packit Service 7770af
      signature_(sig)
Packit Service 7770af
    { }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Definition)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  //////////////////////////////////////
Packit Service 7770af
  // Mixin calls (i.e., `@include ...`).
Packit Service 7770af
  //////////////////////////////////////
Packit Service 7770af
  class Mixin_Call : public Has_Block {
Packit Service 7770af
    ADD_CONSTREF(std::string, name)
Packit Service 7770af
    ADD_PROPERTY(Arguments_Obj, arguments)
Packit Service 7770af
  public:
Packit Service 7770af
    Mixin_Call(ParserState pstate, std::string n, Arguments_Obj args, Block_Obj b = 0)
Packit Service 7770af
    : Has_Block(pstate, b), name_(n), arguments_(args)
Packit Service 7770af
    { }
Packit Service 7770af
    Mixin_Call(const Mixin_Call* ptr)
Packit Service 7770af
    : Has_Block(ptr),
Packit Service 7770af
      name_(ptr->name_),
Packit Service 7770af
      arguments_(ptr->arguments_)
Packit Service 7770af
    { }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Mixin_Call)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ///////////////////////////////////////////////////
Packit Service 7770af
  // The @content directive for mixin content blocks.
Packit Service 7770af
  ///////////////////////////////////////////////////
Packit Service 7770af
  class Content : public Statement {
Packit Service 7770af
    ADD_PROPERTY(Media_Block_Ptr, media_block)
Packit Service 7770af
  public:
Packit Service 7770af
    Content(ParserState pstate)
Packit Service 7770af
    : Statement(pstate),
Packit Service 7770af
      media_block_(NULL)
Packit Service 7770af
    { statement_type(CONTENT); }
Packit Service 7770af
    Content(const Content* ptr)
Packit Service 7770af
    : Statement(ptr),
Packit Service 7770af
      media_block_(ptr->media_block_)
Packit Service 7770af
    { statement_type(CONTENT); }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Content)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ///////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Lists of values, both comma- and space-separated (distinguished by a
Packit Service 7770af
  // type-tag.) Also used to represent variable-length argument lists.
Packit Service 7770af
  ///////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class List : public Value, public Vectorized<Expression_Obj> {
Packit Service 7770af
    void adjust_after_pushing(Expression_Obj e) { is_expanded(false); }
Packit Service 7770af
  private:
Packit Service 7770af
    ADD_PROPERTY(enum Sass_Separator, separator)
Packit Service 7770af
    ADD_PROPERTY(bool, is_arglist)
Packit Service 7770af
    ADD_PROPERTY(bool, from_selector)
Packit Service 7770af
  public:
Packit Service 7770af
    List(ParserState pstate,
Packit Service 7770af
         size_t size = 0, enum Sass_Separator sep = SASS_SPACE, bool argl = false)
Packit Service 7770af
    : Value(pstate),
Packit Service 7770af
      Vectorized<Expression_Obj>(size),
Packit Service 7770af
      separator_(sep),
Packit Service 7770af
      is_arglist_(argl),
Packit Service 7770af
      from_selector_(false)
Packit Service 7770af
    { concrete_type(LIST); }
Packit Service 7770af
    List(const List* ptr)
Packit Service 7770af
    : Value(ptr),
Packit Service 7770af
      Vectorized<Expression_Obj>(*ptr),
Packit Service 7770af
      separator_(ptr->separator_),
Packit Service 7770af
      is_arglist_(ptr->is_arglist_),
Packit Service 7770af
      from_selector_(ptr->from_selector_)
Packit Service 7770af
    { concrete_type(LIST); }
Packit Service 7770af
    std::string type() const { return is_arglist_ ? "arglist" : "list"; }
Packit Service 7770af
    static std::string type_name() { return "list"; }
Packit Service 7770af
    const char* sep_string(bool compressed = false) const {
Packit Service 7770af
      return separator() == SASS_SPACE ?
Packit Service 7770af
        " " : (compressed ? "," : ", ");
Packit Service 7770af
    }
Packit Service 7770af
    bool is_invisible() const { return empty(); }
Packit Service 7770af
    Expression_Obj value_at_index(size_t i);
Packit Service 7770af
Packit Service 7770af
    virtual size_t size() const;
Packit Service 7770af
Packit Service 7770af
    virtual size_t hash()
Packit Service 7770af
    {
Packit Service 7770af
      if (hash_ == 0) {
Packit Service 7770af
        hash_ = std::hash<std::string>()(sep_string());
Packit Service 7770af
        for (size_t i = 0, L = length(); i < L; ++i)
Packit Service 7770af
          hash_combine(hash_, (elements()[i])->hash());
Packit Service 7770af
      }
Packit Service 7770af
      return hash_;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    virtual void set_delayed(bool delayed)
Packit Service 7770af
    {
Packit Service 7770af
      is_delayed(delayed);
Packit Service 7770af
      // don't set children
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    virtual bool operator== (const Expression& rhs) const;
Packit Service 7770af
Packit Service 7770af
    ATTACH_AST_OPERATIONS(List)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ///////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Key value paris.
Packit Service 7770af
  ///////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class Map : public Value, public Hashed {
Packit Service 7770af
    void adjust_after_pushing(std::pair<Expression_Obj, Expression_Obj> p) { is_expanded(false); }
Packit Service 7770af
  public:
Packit Service 7770af
    Map(ParserState pstate,
Packit Service 7770af
         size_t size = 0)
Packit Service 7770af
    : Value(pstate),
Packit Service 7770af
      Hashed(size)
Packit Service 7770af
    { concrete_type(MAP); }
Packit Service 7770af
    Map(const Map* ptr)
Packit Service 7770af
    : Value(ptr),
Packit Service 7770af
      Hashed(*ptr)
Packit Service 7770af
    { concrete_type(MAP); }
Packit Service 7770af
    std::string type() const { return "map"; }
Packit Service 7770af
    static std::string type_name() { return "map"; }
Packit Service 7770af
    bool is_invisible() const { return empty(); }
Packit Service 7770af
    List_Obj to_list(ParserState& pstate);
Packit Service 7770af
Packit Service 7770af
    virtual size_t hash()
Packit Service 7770af
    {
Packit Service 7770af
      if (hash_ == 0) {
Packit Service 7770af
        for (auto key : keys()) {
Packit Service 7770af
          hash_combine(hash_, key->hash());
Packit Service 7770af
          hash_combine(hash_, at(key)->hash());
Packit Service 7770af
        }
Packit Service 7770af
      }
Packit Service 7770af
Packit Service 7770af
      return hash_;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    virtual bool operator== (const Expression& rhs) const;
Packit Service 7770af
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Map)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  inline static const std::string sass_op_to_name(enum Sass_OP op) {
Packit Service 7770af
    switch (op) {
Packit Service 7770af
      case AND: return "and";
Packit Service 7770af
      case OR: return "or";
Packit Service 7770af
      case EQ: return "eq";
Packit Service 7770af
      case NEQ: return "neq";
Packit Service 7770af
      case GT: return "gt";
Packit Service 7770af
      case GTE: return "gte";
Packit Service 7770af
      case LT: return "lt";
Packit Service 7770af
      case LTE: return "lte";
Packit Service 7770af
      case ADD: return "plus";
Packit Service 7770af
      case SUB: return "sub";
Packit Service 7770af
      case MUL: return "times";
Packit Service 7770af
      case DIV: return "div";
Packit Service 7770af
      case MOD: return "mod";
Packit Service 7770af
      // this is only used internally!
Packit Service 7770af
      case NUM_OPS: return "[OPS]";
Packit Service 7770af
      default: return "invalid";
Packit Service 7770af
    }
Packit Service 7770af
  }
Packit Service 7770af
Packit Service 7770af
  //////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Binary expressions. Represents logical, relational, and arithmetic
Packit Service 7770af
  // operations. Templatized to avoid large switch statements and repetitive
Packit Service 7770af
  // subclassing.
Packit Service 7770af
  //////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class Binary_Expression : public PreValue {
Packit Service 7770af
  private:
Packit Service 7770af
    HASH_PROPERTY(Operand, op)
Packit Service 7770af
    HASH_PROPERTY(Expression_Obj, left)
Packit Service 7770af
    HASH_PROPERTY(Expression_Obj, right)
Packit Service 7770af
    size_t hash_;
Packit Service 7770af
  public:
Packit Service 7770af
    Binary_Expression(ParserState pstate,
Packit Service 7770af
                      Operand op, Expression_Obj lhs, Expression_Obj rhs)
Packit Service 7770af
    : PreValue(pstate), op_(op), left_(lhs), right_(rhs), hash_(0)
Packit Service 7770af
    { }
Packit Service 7770af
    Binary_Expression(const Binary_Expression* ptr)
Packit Service 7770af
    : PreValue(ptr),
Packit Service 7770af
      op_(ptr->op_),
Packit Service 7770af
      left_(ptr->left_),
Packit Service 7770af
      right_(ptr->right_),
Packit Service 7770af
      hash_(ptr->hash_)
Packit Service 7770af
    { }
Packit Service 7770af
    const std::string type_name() {
Packit Service 7770af
      switch (optype()) {
Packit Service 7770af
        case AND: return "and";
Packit Service 7770af
        case OR: return "or";
Packit Service 7770af
        case EQ: return "eq";
Packit Service 7770af
        case NEQ: return "neq";
Packit Service 7770af
        case GT: return "gt";
Packit Service 7770af
        case GTE: return "gte";
Packit Service 7770af
        case LT: return "lt";
Packit Service 7770af
        case LTE: return "lte";
Packit Service 7770af
        case ADD: return "add";
Packit Service 7770af
        case SUB: return "sub";
Packit Service 7770af
        case MUL: return "mul";
Packit Service 7770af
        case DIV: return "div";
Packit Service 7770af
        case MOD: return "mod";
Packit Service 7770af
        // this is only used internally!
Packit Service 7770af
        case NUM_OPS: return "[OPS]";
Packit Service 7770af
        default: return "invalid";
Packit Service 7770af
      }
Packit Service 7770af
    }
Packit Service 7770af
    const std::string separator() {
Packit Service 7770af
      switch (optype()) {
Packit Service 7770af
        case AND: return "&&";
Packit Service 7770af
        case OR: return "||";
Packit Service 7770af
        case EQ: return "==";
Packit Service 7770af
        case NEQ: return "!=";
Packit Service 7770af
        case GT: return ">";
Packit Service 7770af
        case GTE: return ">=";
Packit Service 7770af
        case LT: return "<";
Packit Service 7770af
        case LTE: return "<=";
Packit Service 7770af
        case ADD: return "+";
Packit Service 7770af
        case SUB: return "-";
Packit Service 7770af
        case MUL: return "*";
Packit Service 7770af
        case DIV: return "/";
Packit Service 7770af
        case MOD: return "%";
Packit Service 7770af
        // this is only used internally!
Packit Service 7770af
        case NUM_OPS: return "[OPS]";
Packit Service 7770af
        default: return "invalid";
Packit Service 7770af
      }
Packit Service 7770af
    }
Packit Service 7770af
    bool is_left_interpolant(void) const;
Packit Service 7770af
    bool is_right_interpolant(void) const;
Packit Service 7770af
    bool has_interpolant() const
Packit Service 7770af
    {
Packit Service 7770af
      return is_left_interpolant() ||
Packit Service 7770af
             is_right_interpolant();
Packit Service 7770af
    }
Packit Service 7770af
    virtual void set_delayed(bool delayed)
Packit Service 7770af
    {
Packit Service 7770af
      right()->set_delayed(delayed);
Packit Service 7770af
      left()->set_delayed(delayed);
Packit Service 7770af
      is_delayed(delayed);
Packit Service 7770af
    }
Packit Service 7770af
    virtual bool operator==(const Expression& rhs) const
Packit Service 7770af
    {
Packit Service 7770af
      try
Packit Service 7770af
      {
Packit Service 7770af
        Binary_Expression_Ptr_Const m = Cast<Binary_Expression>(&rhs;;
Packit Service 7770af
        if (m == 0) return false;
Packit Service 7770af
        return type() == m->type() &&
Packit Service 7770af
               *left() == *m->left() &&
Packit Service 7770af
               *right() == *m->right();
Packit Service 7770af
      }
Packit Service 7770af
      catch (std::bad_cast&)
Packit Service 7770af
      {
Packit Service 7770af
        return false;
Packit Service 7770af
      }
Packit Service 7770af
      catch (...) { throw; }
Packit Service 7770af
    }
Packit Service 7770af
    virtual size_t hash()
Packit Service 7770af
    {
Packit Service 7770af
      if (hash_ == 0) {
Packit Service 7770af
        hash_ = std::hash<size_t>()(optype());
Packit Service 7770af
        hash_combine(hash_, left()->hash());
Packit Service 7770af
        hash_combine(hash_, right()->hash());
Packit Service 7770af
      }
Packit Service 7770af
      return hash_;
Packit Service 7770af
    }
Packit Service 7770af
    enum Sass_OP optype() const { return op_.operand; }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Binary_Expression)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ////////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Arithmetic negation (logical negation is just an ordinary function call).
Packit Service 7770af
  ////////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class Unary_Expression : public Expression {
Packit Service 7770af
  public:
Packit Service 7770af
    enum Type { PLUS, MINUS, NOT, SLASH };
Packit Service 7770af
  private:
Packit Service 7770af
    HASH_PROPERTY(Type, optype)
Packit Service 7770af
    HASH_PROPERTY(Expression_Obj, operand)
Packit Service 7770af
    size_t hash_;
Packit Service 7770af
  public:
Packit Service 7770af
    Unary_Expression(ParserState pstate, Type t, Expression_Obj o)
Packit Service 7770af
    : Expression(pstate), optype_(t), operand_(o), hash_(0)
Packit Service 7770af
    { }
Packit Service 7770af
    Unary_Expression(const Unary_Expression* ptr)
Packit Service 7770af
    : Expression(ptr),
Packit Service 7770af
      optype_(ptr->optype_),
Packit Service 7770af
      operand_(ptr->operand_),
Packit Service 7770af
      hash_(ptr->hash_)
Packit Service 7770af
    { }
Packit Service 7770af
    const std::string type_name() {
Packit Service 7770af
      switch (optype_) {
Packit Service 7770af
        case PLUS: return "plus";
Packit Service 7770af
        case MINUS: return "minus";
Packit Service 7770af
        case SLASH: return "slash";
Packit Service 7770af
        case NOT: return "not";
Packit Service 7770af
        default: return "invalid";
Packit Service 7770af
      }
Packit Service 7770af
    }
Packit Service 7770af
    virtual bool operator==(const Expression& rhs) const
Packit Service 7770af
    {
Packit Service 7770af
      try
Packit Service 7770af
      {
Packit Service 7770af
        Unary_Expression_Ptr_Const m = Cast<Unary_Expression>(&rhs;;
Packit Service 7770af
        if (m == 0) return false;
Packit Service 7770af
        return type() == m->type() &&
Packit Service 7770af
               *operand() == *m->operand();
Packit Service 7770af
      }
Packit Service 7770af
      catch (std::bad_cast&)
Packit Service 7770af
      {
Packit Service 7770af
        return false;
Packit Service 7770af
      }
Packit Service 7770af
      catch (...) { throw; }
Packit Service 7770af
    }
Packit Service 7770af
    virtual size_t hash()
Packit Service 7770af
    {
Packit Service 7770af
      if (hash_ == 0) {
Packit Service 7770af
        hash_ = std::hash<size_t>()(optype_);
Packit Service 7770af
        hash_combine(hash_, operand()->hash());
Packit Service 7770af
      };
Packit Service 7770af
      return hash_;
Packit Service 7770af
    }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Unary_Expression)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ////////////////////////////////////////////////////////////
Packit Service 7770af
  // Individual argument objects for mixin and function calls.
Packit Service 7770af
  ////////////////////////////////////////////////////////////
Packit Service 7770af
  class Argument : public Expression {
Packit Service 7770af
    HASH_PROPERTY(Expression_Obj, value)
Packit Service 7770af
    HASH_CONSTREF(std::string, name)
Packit Service 7770af
    ADD_PROPERTY(bool, is_rest_argument)
Packit Service 7770af
    ADD_PROPERTY(bool, is_keyword_argument)
Packit Service 7770af
    size_t hash_;
Packit Service 7770af
  public:
Packit Service 7770af
    Argument(ParserState pstate, Expression_Obj val, std::string n = "", bool rest = false, bool keyword = false)
Packit Service 7770af
    : Expression(pstate), value_(val), name_(n), is_rest_argument_(rest), is_keyword_argument_(keyword), hash_(0)
Packit Service 7770af
    {
Packit Service 7770af
      if (!name_.empty() && is_rest_argument_) {
Packit Service 7770af
        error("variable-length argument may not be passed by name", pstate_);
Packit Service 7770af
      }
Packit Service 7770af
    }
Packit Service 7770af
    Argument(const Argument* ptr)
Packit Service 7770af
    : Expression(ptr),
Packit Service 7770af
      value_(ptr->value_),
Packit Service 7770af
      name_(ptr->name_),
Packit Service 7770af
      is_rest_argument_(ptr->is_rest_argument_),
Packit Service 7770af
      is_keyword_argument_(ptr->is_keyword_argument_),
Packit Service 7770af
      hash_(ptr->hash_)
Packit Service 7770af
    {
Packit Service 7770af
      if (!name_.empty() && is_rest_argument_) {
Packit Service 7770af
        error("variable-length argument may not be passed by name", pstate_);
Packit Service 7770af
      }
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    virtual void set_delayed(bool delayed);
Packit Service 7770af
    virtual bool operator==(const Expression& rhs) const
Packit Service 7770af
    {
Packit Service 7770af
      try
Packit Service 7770af
      {
Packit Service 7770af
        Argument_Ptr_Const m = Cast<Argument>(&rhs;;
Packit Service 7770af
        if (!(m && name() == m->name())) return false;
Packit Service 7770af
        return *value() == *m->value();
Packit Service 7770af
      }
Packit Service 7770af
      catch (std::bad_cast&)
Packit Service 7770af
      {
Packit Service 7770af
        return false;
Packit Service 7770af
      }
Packit Service 7770af
      catch (...) { throw; }
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    virtual size_t hash()
Packit Service 7770af
    {
Packit Service 7770af
      if (hash_ == 0) {
Packit Service 7770af
        hash_ = std::hash<std::string>()(name());
Packit Service 7770af
        hash_combine(hash_, value()->hash());
Packit Service 7770af
      }
Packit Service 7770af
      return hash_;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Argument)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Argument lists -- in their own class to facilitate context-sensitive
Packit Service 7770af
  // error checking (e.g., ensuring that all ordinal arguments precede all
Packit Service 7770af
  // named arguments).
Packit Service 7770af
  ////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class Arguments : public Expression, public Vectorized<Argument_Obj> {
Packit Service 7770af
    ADD_PROPERTY(bool, has_named_arguments)
Packit Service 7770af
    ADD_PROPERTY(bool, has_rest_argument)
Packit Service 7770af
    ADD_PROPERTY(bool, has_keyword_argument)
Packit Service 7770af
  protected:
Packit Service 7770af
    void adjust_after_pushing(Argument_Obj a);
Packit Service 7770af
  public:
Packit Service 7770af
    Arguments(ParserState pstate)
Packit Service 7770af
    : Expression(pstate),
Packit Service 7770af
      Vectorized<Argument_Obj>(),
Packit Service 7770af
      has_named_arguments_(false),
Packit Service 7770af
      has_rest_argument_(false),
Packit Service 7770af
      has_keyword_argument_(false)
Packit Service 7770af
    { }
Packit Service 7770af
    Arguments(const Arguments* ptr)
Packit Service 7770af
    : Expression(ptr),
Packit Service 7770af
      Vectorized<Argument_Obj>(*ptr),
Packit Service 7770af
      has_named_arguments_(ptr->has_named_arguments_),
Packit Service 7770af
      has_rest_argument_(ptr->has_rest_argument_),
Packit Service 7770af
      has_keyword_argument_(ptr->has_keyword_argument_)
Packit Service 7770af
    { }
Packit Service 7770af
Packit Service 7770af
    virtual void set_delayed(bool delayed);
Packit Service 7770af
Packit Service 7770af
    Argument_Obj get_rest_argument();
Packit Service 7770af
    Argument_Obj get_keyword_argument();
Packit Service 7770af
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Arguments)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  //////////////////
Packit Service 7770af
  // Function calls.
Packit Service 7770af
  //////////////////
Packit Service 7770af
  class Function_Call : public PreValue {
Packit Service 7770af
    HASH_CONSTREF(std::string, name)
Packit Service 7770af
    HASH_PROPERTY(Arguments_Obj, arguments)
Packit Service 7770af
    ADD_PROPERTY(bool, via_call)
Packit Service 7770af
    ADD_PROPERTY(void*, cookie)
Packit Service 7770af
    size_t hash_;
Packit Service 7770af
  public:
Packit Service 7770af
    Function_Call(ParserState pstate, std::string n, Arguments_Obj args, void* cookie)
Packit Service 7770af
    : PreValue(pstate), name_(n), arguments_(args), via_call_(false), cookie_(cookie), hash_(0)
Packit Service 7770af
    { concrete_type(FUNCTION); }
Packit Service 7770af
    Function_Call(ParserState pstate, std::string n, Arguments_Obj args)
Packit Service 7770af
    : PreValue(pstate), name_(n), arguments_(args), via_call_(false), cookie_(0), hash_(0)
Packit Service 7770af
    { concrete_type(FUNCTION); }
Packit Service 7770af
    Function_Call(const Function_Call* ptr)
Packit Service 7770af
    : PreValue(ptr),
Packit Service 7770af
      name_(ptr->name_),
Packit Service 7770af
      arguments_(ptr->arguments_),
Packit Service 7770af
      via_call_(ptr->via_call_),
Packit Service 7770af
      cookie_(ptr->cookie_),
Packit Service 7770af
      hash_(ptr->hash_)
Packit Service 7770af
    { concrete_type(FUNCTION); }
Packit Service 7770af
Packit Service 7770af
    virtual bool operator==(const Expression& rhs) const
Packit Service 7770af
    {
Packit Service 7770af
      try
Packit Service 7770af
      {
Packit Service 7770af
        Function_Call_Ptr_Const m = Cast<Function_Call>(&rhs;;
Packit Service 7770af
        if (!(m && name() == m->name())) return false;
Packit Service 7770af
        if (!(m && arguments()->length() == m->arguments()->length())) return false;
Packit Service 7770af
        for (size_t i =0, L = arguments()->length(); i < L; ++i)
Packit Service 7770af
          if (!(*(*arguments())[i] == *(*m->arguments())[i])) return false;
Packit Service 7770af
        return true;
Packit Service 7770af
      }
Packit Service 7770af
      catch (std::bad_cast&)
Packit Service 7770af
      {
Packit Service 7770af
        return false;
Packit Service 7770af
      }
Packit Service 7770af
      catch (...) { throw; }
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    virtual size_t hash()
Packit Service 7770af
    {
Packit Service 7770af
      if (hash_ == 0) {
Packit Service 7770af
        hash_ = std::hash<std::string>()(name());
Packit Service 7770af
        for (auto argument : arguments()->elements())
Packit Service 7770af
          hash_combine(hash_, argument->hash());
Packit Service 7770af
      }
Packit Service 7770af
      return hash_;
Packit Service 7770af
    }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Function_Call)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  /////////////////////////
Packit Service 7770af
  // Function call schemas.
Packit Service 7770af
  /////////////////////////
Packit Service 7770af
  class Function_Call_Schema : public Expression {
Packit Service 7770af
    ADD_PROPERTY(String_Obj, name)
Packit Service 7770af
    ADD_PROPERTY(Arguments_Obj, arguments)
Packit Service 7770af
  public:
Packit Service 7770af
    Function_Call_Schema(ParserState pstate, String_Obj n, Arguments_Obj args)
Packit Service 7770af
    : Expression(pstate), name_(n), arguments_(args)
Packit Service 7770af
    { concrete_type(STRING); }
Packit Service 7770af
    Function_Call_Schema(const Function_Call_Schema* ptr)
Packit Service 7770af
    : Expression(ptr),
Packit Service 7770af
      name_(ptr->name_),
Packit Service 7770af
      arguments_(ptr->arguments_)
Packit Service 7770af
    { concrete_type(STRING); }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Function_Call_Schema)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ///////////////////////
Packit Service 7770af
  // Variable references.
Packit Service 7770af
  ///////////////////////
Packit Service 7770af
  class Variable : public PreValue {
Packit Service 7770af
    ADD_CONSTREF(std::string, name)
Packit Service 7770af
  public:
Packit Service 7770af
    Variable(ParserState pstate, std::string n)
Packit Service 7770af
    : PreValue(pstate), name_(n)
Packit Service 7770af
    { concrete_type(VARIABLE); }
Packit Service 7770af
    Variable(const Variable* ptr)
Packit Service 7770af
    : PreValue(ptr), name_(ptr->name_)
Packit Service 7770af
    { concrete_type(VARIABLE); }
Packit Service 7770af
Packit Service 7770af
    virtual bool operator==(const Expression& rhs) const
Packit Service 7770af
    {
Packit Service 7770af
      try
Packit Service 7770af
      {
Packit Service 7770af
        Variable_Ptr_Const e = Cast<Variable>(&rhs;;
Packit Service 7770af
        return e && name() == e->name();
Packit Service 7770af
      }
Packit Service 7770af
      catch (std::bad_cast&)
Packit Service 7770af
      {
Packit Service 7770af
        return false;
Packit Service 7770af
      }
Packit Service 7770af
      catch (...) { throw; }
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    virtual size_t hash()
Packit Service 7770af
    {
Packit Service 7770af
      return std::hash<std::string>()(name());
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Variable)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ////////////////////////////////////////////////
Packit Service 7770af
  // Numbers, percentages, dimensions, and colors.
Packit Service 7770af
  ////////////////////////////////////////////////
Packit Service 7770af
  class Number : public Value {
Packit Service 7770af
    HASH_PROPERTY(double, value)
Packit Service 7770af
    ADD_PROPERTY(bool, zero)
Packit Service 7770af
    std::vector<std::string> numerator_units_;
Packit Service 7770af
    std::vector<std::string> denominator_units_;
Packit Service 7770af
    size_t hash_;
Packit Service 7770af
  public:
Packit Service 7770af
    Number(ParserState pstate, double val, std::string u = "", bool zero = true);
Packit Service 7770af
Packit Service 7770af
    Number(const Number* ptr)
Packit Service 7770af
    : Value(ptr),
Packit Service 7770af
      value_(ptr->value_), zero_(ptr->zero_),
Packit Service 7770af
      numerator_units_(ptr->numerator_units_),
Packit Service 7770af
      denominator_units_(ptr->denominator_units_),
Packit Service 7770af
      hash_(ptr->hash_)
Packit Service 7770af
    { concrete_type(NUMBER); }
Packit Service 7770af
Packit Service 7770af
    bool zero() { return zero_; }
Packit Service 7770af
    bool is_valid_css_unit() const;
Packit Service 7770af
    std::vector<std::string>& numerator_units()   { return numerator_units_; }
Packit Service 7770af
    std::vector<std::string>& denominator_units() { return denominator_units_; }
Packit Service 7770af
    const std::vector<std::string>& numerator_units() const   { return numerator_units_; }
Packit Service 7770af
    const std::vector<std::string>& denominator_units() const { return denominator_units_; }
Packit Service 7770af
    std::string type() const { return "number"; }
Packit Service 7770af
    static std::string type_name() { return "number"; }
Packit Service 7770af
    std::string unit() const;
Packit Service 7770af
Packit Service 7770af
    bool is_unitless() const;
Packit Service 7770af
    double convert_factor(const Number&) const;
Packit Service 7770af
    bool convert(const std::string& unit = "", bool strict = false);
Packit Service 7770af
    void normalize(const std::string& unit = "", bool strict = false);
Packit Service 7770af
    // useful for making one number compatible with another
Packit Service 7770af
    std::string find_convertible_unit() const;
Packit Service 7770af
Packit Service 7770af
    virtual size_t hash()
Packit Service 7770af
    {
Packit Service 7770af
      if (hash_ == 0) {
Packit Service 7770af
        hash_ = std::hash<double>()(value_);
Packit Service 7770af
        for (const auto numerator : numerator_units())
Packit Service 7770af
          hash_combine(hash_, std::hash<std::string>()(numerator));
Packit Service 7770af
        for (const auto denominator : denominator_units())
Packit Service 7770af
          hash_combine(hash_, std::hash<std::string>()(denominator));
Packit Service 7770af
      }
Packit Service 7770af
      return hash_;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    virtual bool operator< (const Number& rhs) const;
Packit Service 7770af
    virtual bool operator== (const Expression& rhs) const;
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Number)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  //////////
Packit Service 7770af
  // Colors.
Packit Service 7770af
  //////////
Packit Service 7770af
  class Color : public Value {
Packit Service 7770af
    HASH_PROPERTY(double, r)
Packit Service 7770af
    HASH_PROPERTY(double, g)
Packit Service 7770af
    HASH_PROPERTY(double, b)
Packit Service 7770af
    HASH_PROPERTY(double, a)
Packit Service 7770af
    ADD_CONSTREF(std::string, disp)
Packit Service 7770af
    size_t hash_;
Packit Service 7770af
  public:
Packit Service 7770af
    Color(ParserState pstate, double r, double g, double b, double a = 1, const std::string disp = "")
Packit Service 7770af
    : Value(pstate), r_(r), g_(g), b_(b), a_(a), disp_(disp),
Packit Service 7770af
      hash_(0)
Packit Service 7770af
    { concrete_type(COLOR); }
Packit Service 7770af
    Color(const Color* ptr)
Packit Service 7770af
    : Value(ptr),
Packit Service 7770af
      r_(ptr->r_),
Packit Service 7770af
      g_(ptr->g_),
Packit Service 7770af
      b_(ptr->b_),
Packit Service 7770af
      a_(ptr->a_),
Packit Service 7770af
      disp_(ptr->disp_),
Packit Service 7770af
      hash_(ptr->hash_)
Packit Service 7770af
    { concrete_type(COLOR); }
Packit Service 7770af
    std::string type() const { return "color"; }
Packit Service 7770af
    static std::string type_name() { return "color"; }
Packit Service 7770af
Packit Service 7770af
    virtual size_t hash()
Packit Service 7770af
    {
Packit Service 7770af
      if (hash_ == 0) {
Packit Service 7770af
        hash_ = std::hash<double>()(a_);
Packit Service 7770af
        hash_combine(hash_, std::hash<double>()(r_));
Packit Service 7770af
        hash_combine(hash_, std::hash<double>()(g_));
Packit Service 7770af
        hash_combine(hash_, std::hash<double>()(b_));
Packit Service 7770af
      }
Packit Service 7770af
      return hash_;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    virtual bool operator== (const Expression& rhs) const;
Packit Service 7770af
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Color)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  //////////////////////////////
Packit Service 7770af
  // Errors from Sass_Values.
Packit Service 7770af
  //////////////////////////////
Packit Service 7770af
  class Custom_Error : public Value {
Packit Service 7770af
    ADD_CONSTREF(std::string, message)
Packit Service 7770af
  public:
Packit Service 7770af
    Custom_Error(ParserState pstate, std::string msg)
Packit Service 7770af
    : Value(pstate), message_(msg)
Packit Service 7770af
    { concrete_type(C_ERROR); }
Packit Service 7770af
    Custom_Error(const Custom_Error* ptr)
Packit Service 7770af
    : Value(ptr), message_(ptr->message_)
Packit Service 7770af
    { concrete_type(C_ERROR); }
Packit Service 7770af
    virtual bool operator== (const Expression& rhs) const;
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Custom_Error)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  //////////////////////////////
Packit Service 7770af
  // Warnings from Sass_Values.
Packit Service 7770af
  //////////////////////////////
Packit Service 7770af
  class Custom_Warning : public Value {
Packit Service 7770af
    ADD_CONSTREF(std::string, message)
Packit Service 7770af
  public:
Packit Service 7770af
    Custom_Warning(ParserState pstate, std::string msg)
Packit Service 7770af
    : Value(pstate), message_(msg)
Packit Service 7770af
    { concrete_type(C_WARNING); }
Packit Service 7770af
    Custom_Warning(const Custom_Warning* ptr)
Packit Service 7770af
    : Value(ptr), message_(ptr->message_)
Packit Service 7770af
    { concrete_type(C_WARNING); }
Packit Service 7770af
    virtual bool operator== (const Expression& rhs) const;
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Custom_Warning)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ////////////
Packit Service 7770af
  // Booleans.
Packit Service 7770af
  ////////////
Packit Service 7770af
  class Boolean : public Value {
Packit Service 7770af
    HASH_PROPERTY(bool, value)
Packit Service 7770af
    size_t hash_;
Packit Service 7770af
  public:
Packit Service 7770af
    Boolean(ParserState pstate, bool val)
Packit Service 7770af
    : Value(pstate), value_(val),
Packit Service 7770af
      hash_(0)
Packit Service 7770af
    { concrete_type(BOOLEAN); }
Packit Service 7770af
    Boolean(const Boolean* ptr)
Packit Service 7770af
    : Value(ptr),
Packit Service 7770af
      value_(ptr->value_),
Packit Service 7770af
      hash_(ptr->hash_)
Packit Service 7770af
    { concrete_type(BOOLEAN); }
Packit Service 7770af
    virtual operator bool() { return value_; }
Packit Service 7770af
    std::string type() const { return "bool"; }
Packit Service 7770af
    static std::string type_name() { return "bool"; }
Packit Service 7770af
    virtual bool is_false() { return !value_; }
Packit Service 7770af
Packit Service 7770af
    virtual size_t hash()
Packit Service 7770af
    {
Packit Service 7770af
      if (hash_ == 0) {
Packit Service 7770af
        hash_ = std::hash<bool>()(value_);
Packit Service 7770af
      }
Packit Service 7770af
      return hash_;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    virtual bool operator== (const Expression& rhs) const;
Packit Service 7770af
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Boolean)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Abstract base class for Sass string values. Includes interpolated and
Packit Service 7770af
  // "flat" strings.
Packit Service 7770af
  ////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class String : public Value {
Packit Service 7770af
  public:
Packit Service 7770af
    String(ParserState pstate, bool delayed = false)
Packit Service 7770af
    : Value(pstate, delayed)
Packit Service 7770af
    { concrete_type(STRING); }
Packit Service 7770af
    String(const String* ptr)
Packit Service 7770af
    : Value(ptr)
Packit Service 7770af
    { concrete_type(STRING); }
Packit Service 7770af
    static std::string type_name() { return "string"; }
Packit Service 7770af
    virtual ~String() = 0;
Packit Service 7770af
    virtual void rtrim() = 0;
Packit Service 7770af
    virtual bool operator==(const Expression& rhs) const = 0;
Packit Service 7770af
    virtual bool operator<(const Expression& rhs) const {
Packit Service 7770af
      return this->to_string() < rhs.to_string();
Packit Service 7770af
    };
Packit Service 7770af
    ATTACH_VIRTUAL_AST_OPERATIONS(String);
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
  inline String::~String() { };
Packit Service 7770af
Packit Service 7770af
  ///////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Interpolated strings. Meant to be reduced to flat strings during the
Packit Service 7770af
  // evaluation phase.
Packit Service 7770af
  ///////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class String_Schema : public String, public Vectorized<Expression_Obj> {
Packit Service 7770af
    // ADD_PROPERTY(bool, has_interpolants)
Packit Service 7770af
    size_t hash_;
Packit Service 7770af
  public:
Packit Service 7770af
    String_Schema(ParserState pstate, size_t size = 0, bool has_interpolants = false)
Packit Service 7770af
    : String(pstate), Vectorized<Expression_Obj>(size), hash_(0)
Packit Service 7770af
    { concrete_type(STRING); }
Packit Service 7770af
    String_Schema(const String_Schema* ptr)
Packit Service 7770af
    : String(ptr),
Packit Service 7770af
      Vectorized<Expression_Obj>(*ptr),
Packit Service 7770af
      hash_(ptr->hash_)
Packit Service 7770af
    { concrete_type(STRING); }
Packit Service 7770af
Packit Service 7770af
    std::string type() const { return "string"; }
Packit Service 7770af
    static std::string type_name() { return "string"; }
Packit Service 7770af
Packit Service 7770af
    bool is_left_interpolant(void) const;
Packit Service 7770af
    bool is_right_interpolant(void) const;
Packit Service 7770af
    // void has_interpolants(bool tc) { }
Packit Service 7770af
    bool has_interpolants() {
Packit Service 7770af
      for (auto el : elements()) {
Packit Service 7770af
        if (el->is_interpolant()) return true;
Packit Service 7770af
      }
Packit Service 7770af
      return false;
Packit Service 7770af
    }
Packit Service 7770af
    virtual void rtrim();
Packit Service 7770af
Packit Service 7770af
    virtual size_t hash()
Packit Service 7770af
    {
Packit Service 7770af
      if (hash_ == 0) {
Packit Service 7770af
        for (auto string : elements())
Packit Service 7770af
          hash_combine(hash_, string->hash());
Packit Service 7770af
      }
Packit Service 7770af
      return hash_;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    virtual void set_delayed(bool delayed) {
Packit Service 7770af
      is_delayed(delayed);
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    virtual bool operator==(const Expression& rhs) const;
Packit Service 7770af
    ATTACH_AST_OPERATIONS(String_Schema)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ////////////////////////////////////////////////////////
Packit Service 7770af
  // Flat strings -- the lowest level of raw textual data.
Packit Service 7770af
  ////////////////////////////////////////////////////////
Packit Service 7770af
  class String_Constant : public String {
Packit Service 7770af
    ADD_PROPERTY(char, quote_mark)
Packit Service 7770af
    ADD_PROPERTY(bool, can_compress_whitespace)
Packit Service 7770af
    HASH_CONSTREF(std::string, value)
Packit Service 7770af
  protected:
Packit Service 7770af
    size_t hash_;
Packit Service 7770af
  public:
Packit Service 7770af
    String_Constant(const String_Constant* ptr)
Packit Service 7770af
    : String(ptr),
Packit Service 7770af
      quote_mark_(ptr->quote_mark_),
Packit Service 7770af
      can_compress_whitespace_(ptr->can_compress_whitespace_),
Packit Service 7770af
      value_(ptr->value_),
Packit Service 7770af
      hash_(ptr->hash_)
Packit Service 7770af
    { }
Packit Service 7770af
    String_Constant(ParserState pstate, std::string val)
Packit Service 7770af
    : String(pstate), quote_mark_(0), can_compress_whitespace_(false), value_(read_css_string(val)), hash_(0)
Packit Service 7770af
    { }
Packit Service 7770af
    String_Constant(ParserState pstate, const char* beg)
Packit Service 7770af
    : String(pstate), quote_mark_(0), can_compress_whitespace_(false), value_(read_css_string(std::string(beg))), hash_(0)
Packit Service 7770af
    { }
Packit Service 7770af
    String_Constant(ParserState pstate, const char* beg, const char* end)
Packit Service 7770af
    : String(pstate), quote_mark_(0), can_compress_whitespace_(false), value_(read_css_string(std::string(beg, end-beg))), hash_(0)
Packit Service 7770af
    { }
Packit Service 7770af
    String_Constant(ParserState pstate, const Token& tok)
Packit Service 7770af
    : String(pstate), quote_mark_(0), can_compress_whitespace_(false), value_(read_css_string(std::string(tok.begin, tok.end))), hash_(0)
Packit Service 7770af
    { }
Packit Service 7770af
    std::string type() const { return "string"; }
Packit Service 7770af
    static std::string type_name() { return "string"; }
Packit Service 7770af
    virtual bool is_invisible() const;
Packit Service 7770af
    virtual void rtrim();
Packit Service 7770af
Packit Service 7770af
    virtual size_t hash()
Packit Service 7770af
    {
Packit Service 7770af
      if (hash_ == 0) {
Packit Service 7770af
        hash_ = std::hash<std::string>()(value_);
Packit Service 7770af
      }
Packit Service 7770af
      return hash_;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    virtual bool operator==(const Expression& rhs) const;
Packit Service 7770af
    virtual std::string inspect() const; // quotes are forced on inspection
Packit Service 7770af
Packit Service 7770af
    // static char auto_quote() { return '*'; }
Packit Service 7770af
    static char double_quote() { return '"'; }
Packit Service 7770af
    static char single_quote() { return '\''; }
Packit Service 7770af
Packit Service 7770af
    ATTACH_AST_OPERATIONS(String_Constant)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ////////////////////////////////////////////////////////
Packit Service 7770af
  // Possibly quoted string (unquote on instantiation)
Packit Service 7770af
  ////////////////////////////////////////////////////////
Packit Service 7770af
  class String_Quoted : public String_Constant {
Packit Service 7770af
  public:
Packit Service 7770af
    String_Quoted(ParserState pstate, std::string val, char q = 0,
Packit Service 7770af
      bool keep_utf8_escapes = false, bool skip_unquoting = false,
Packit Service 7770af
      bool strict_unquoting = true)
Packit Service 7770af
    : String_Constant(pstate, val)
Packit Service 7770af
    {
Packit Service 7770af
      if (skip_unquoting == false) {
Packit Service 7770af
        value_ = unquote(value_, &quote_mark_, keep_utf8_escapes, strict_unquoting);
Packit Service 7770af
      }
Packit Service 7770af
      if (q && quote_mark_) quote_mark_ = q;
Packit Service 7770af
    }
Packit Service 7770af
    String_Quoted(const String_Quoted* ptr)
Packit Service 7770af
    : String_Constant(ptr)
Packit Service 7770af
    { }
Packit Service 7770af
    virtual bool operator==(const Expression& rhs) const;
Packit Service 7770af
    virtual std::string inspect() const; // quotes are forced on inspection
Packit Service 7770af
    ATTACH_AST_OPERATIONS(String_Quoted)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  /////////////////
Packit Service 7770af
  // Media queries.
Packit Service 7770af
  /////////////////
Packit Service 7770af
  class Media_Query : public Expression,
Packit Service 7770af
                      public Vectorized<Media_Query_Expression_Obj> {
Packit Service 7770af
    ADD_PROPERTY(String_Obj, media_type)
Packit Service 7770af
    ADD_PROPERTY(bool, is_negated)
Packit Service 7770af
    ADD_PROPERTY(bool, is_restricted)
Packit Service 7770af
  public:
Packit Service 7770af
    Media_Query(ParserState pstate,
Packit Service 7770af
                String_Obj t = 0, size_t s = 0, bool n = false, bool r = false)
Packit Service 7770af
    : Expression(pstate), Vectorized<Media_Query_Expression_Obj>(s),
Packit Service 7770af
      media_type_(t), is_negated_(n), is_restricted_(r)
Packit Service 7770af
    { }
Packit Service 7770af
    Media_Query(const Media_Query* ptr)
Packit Service 7770af
    : Expression(ptr),
Packit Service 7770af
      Vectorized<Media_Query_Expression_Obj>(*ptr),
Packit Service 7770af
      media_type_(ptr->media_type_),
Packit Service 7770af
      is_negated_(ptr->is_negated_),
Packit Service 7770af
      is_restricted_(ptr->is_restricted_)
Packit Service 7770af
    { }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Media_Query)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ////////////////////////////////////////////////////
Packit Service 7770af
  // Media expressions (for use inside media queries).
Packit Service 7770af
  ////////////////////////////////////////////////////
Packit Service 7770af
  class Media_Query_Expression : public Expression {
Packit Service 7770af
    ADD_PROPERTY(Expression_Obj, feature)
Packit Service 7770af
    ADD_PROPERTY(Expression_Obj, value)
Packit Service 7770af
    ADD_PROPERTY(bool, is_interpolated)
Packit Service 7770af
  public:
Packit Service 7770af
    Media_Query_Expression(ParserState pstate,
Packit Service 7770af
                           Expression_Obj f, Expression_Obj v, bool i = false)
Packit Service 7770af
    : Expression(pstate), feature_(f), value_(v), is_interpolated_(i)
Packit Service 7770af
    { }
Packit Service 7770af
    Media_Query_Expression(const Media_Query_Expression* ptr)
Packit Service 7770af
    : Expression(ptr),
Packit Service 7770af
      feature_(ptr->feature_),
Packit Service 7770af
      value_(ptr->value_),
Packit Service 7770af
      is_interpolated_(ptr->is_interpolated_)
Packit Service 7770af
    { }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Media_Query_Expression)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ////////////////////
Packit Service 7770af
  // `@supports` rule.
Packit Service 7770af
  ////////////////////
Packit Service 7770af
  class Supports_Block : public Has_Block {
Packit Service 7770af
    ADD_PROPERTY(Supports_Condition_Obj, condition)
Packit Service 7770af
  public:
Packit Service 7770af
    Supports_Block(ParserState pstate, Supports_Condition_Obj condition, Block_Obj block = 0)
Packit Service 7770af
    : Has_Block(pstate, block), condition_(condition)
Packit Service 7770af
    { statement_type(SUPPORTS); }
Packit Service 7770af
    Supports_Block(const Supports_Block* ptr)
Packit Service 7770af
    : Has_Block(ptr), condition_(ptr->condition_)
Packit Service 7770af
    { statement_type(SUPPORTS); }
Packit Service 7770af
    bool bubbles() { return true; }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Supports_Block)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  //////////////////////////////////////////////////////
Packit Service 7770af
  // The abstract superclass of all Supports conditions.
Packit Service 7770af
  //////////////////////////////////////////////////////
Packit Service 7770af
  class Supports_Condition : public Expression {
Packit Service 7770af
  public:
Packit Service 7770af
    Supports_Condition(ParserState pstate)
Packit Service 7770af
    : Expression(pstate)
Packit Service 7770af
    { }
Packit Service 7770af
    Supports_Condition(const Supports_Condition* ptr)
Packit Service 7770af
    : Expression(ptr)
Packit Service 7770af
    { }
Packit Service 7770af
    virtual bool needs_parens(Supports_Condition_Obj cond) const { return false; }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Supports_Condition)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ////////////////////////////////////////////////////////////
Packit Service 7770af
  // An operator condition (e.g. `CONDITION1 and CONDITION2`).
Packit Service 7770af
  ////////////////////////////////////////////////////////////
Packit Service 7770af
  class Supports_Operator : public Supports_Condition {
Packit Service 7770af
  public:
Packit Service 7770af
    enum Operand { AND, OR };
Packit Service 7770af
  private:
Packit Service 7770af
    ADD_PROPERTY(Supports_Condition_Obj, left);
Packit Service 7770af
    ADD_PROPERTY(Supports_Condition_Obj, right);
Packit Service 7770af
    ADD_PROPERTY(Operand, operand);
Packit Service 7770af
  public:
Packit Service 7770af
    Supports_Operator(ParserState pstate, Supports_Condition_Obj l, Supports_Condition_Obj r, Operand o)
Packit Service 7770af
    : Supports_Condition(pstate), left_(l), right_(r), operand_(o)
Packit Service 7770af
    { }
Packit Service 7770af
    Supports_Operator(const Supports_Operator* ptr)
Packit Service 7770af
    : Supports_Condition(ptr),
Packit Service 7770af
      left_(ptr->left_),
Packit Service 7770af
      right_(ptr->right_),
Packit Service 7770af
      operand_(ptr->operand_)
Packit Service 7770af
    { }
Packit Service 7770af
    virtual bool needs_parens(Supports_Condition_Obj cond) const;
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Supports_Operator)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  //////////////////////////////////////////
Packit Service 7770af
  // A negation condition (`not CONDITION`).
Packit Service 7770af
  //////////////////////////////////////////
Packit Service 7770af
  class Supports_Negation : public Supports_Condition {
Packit Service 7770af
  private:
Packit Service 7770af
    ADD_PROPERTY(Supports_Condition_Obj, condition);
Packit Service 7770af
  public:
Packit Service 7770af
    Supports_Negation(ParserState pstate, Supports_Condition_Obj c)
Packit Service 7770af
    : Supports_Condition(pstate), condition_(c)
Packit Service 7770af
    { }
Packit Service 7770af
    Supports_Negation(const Supports_Negation* ptr)
Packit Service 7770af
    : Supports_Condition(ptr), condition_(ptr->condition_)
Packit Service 7770af
    { }
Packit Service 7770af
    virtual bool needs_parens(Supports_Condition_Obj cond) const;
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Supports_Negation)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  /////////////////////////////////////////////////////
Packit Service 7770af
  // A declaration condition (e.g. `(feature: value)`).
Packit Service 7770af
  /////////////////////////////////////////////////////
Packit Service 7770af
  class Supports_Declaration : public Supports_Condition {
Packit Service 7770af
  private:
Packit Service 7770af
    ADD_PROPERTY(Expression_Obj, feature);
Packit Service 7770af
    ADD_PROPERTY(Expression_Obj, value);
Packit Service 7770af
  public:
Packit Service 7770af
    Supports_Declaration(ParserState pstate, Expression_Obj f, Expression_Obj v)
Packit Service 7770af
    : Supports_Condition(pstate), feature_(f), value_(v)
Packit Service 7770af
    { }
Packit Service 7770af
    Supports_Declaration(const Supports_Declaration* ptr)
Packit Service 7770af
    : Supports_Condition(ptr),
Packit Service 7770af
      feature_(ptr->feature_),
Packit Service 7770af
      value_(ptr->value_)
Packit Service 7770af
    { }
Packit Service 7770af
    virtual bool needs_parens(Supports_Condition_Obj cond) const { return false; }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Supports_Declaration)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ///////////////////////////////////////////////
Packit Service 7770af
  // An interpolation condition (e.g. `#{$var}`).
Packit Service 7770af
  ///////////////////////////////////////////////
Packit Service 7770af
  class Supports_Interpolation : public Supports_Condition {
Packit Service 7770af
  private:
Packit Service 7770af
    ADD_PROPERTY(Expression_Obj, value);
Packit Service 7770af
  public:
Packit Service 7770af
    Supports_Interpolation(ParserState pstate, Expression_Obj v)
Packit Service 7770af
    : Supports_Condition(pstate), value_(v)
Packit Service 7770af
    { }
Packit Service 7770af
    Supports_Interpolation(const Supports_Interpolation* ptr)
Packit Service 7770af
    : Supports_Condition(ptr),
Packit Service 7770af
      value_(ptr->value_)
Packit Service 7770af
    { }
Packit Service 7770af
    virtual bool needs_parens(Supports_Condition_Obj cond) const { return false; }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Supports_Interpolation)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  /////////////////////////////////////////////////
Packit Service 7770af
  // At root expressions (for use inside @at-root).
Packit Service 7770af
  /////////////////////////////////////////////////
Packit Service 7770af
  class At_Root_Query : public Expression {
Packit Service 7770af
  private:
Packit Service 7770af
    ADD_PROPERTY(Expression_Obj, feature)
Packit Service 7770af
    ADD_PROPERTY(Expression_Obj, value)
Packit Service 7770af
  public:
Packit Service 7770af
    At_Root_Query(ParserState pstate, Expression_Obj f = 0, Expression_Obj v = 0, bool i = false)
Packit Service 7770af
    : Expression(pstate), feature_(f), value_(v)
Packit Service 7770af
    { }
Packit Service 7770af
    At_Root_Query(const At_Root_Query* ptr)
Packit Service 7770af
    : Expression(ptr),
Packit Service 7770af
      feature_(ptr->feature_),
Packit Service 7770af
      value_(ptr->value_)
Packit Service 7770af
    { }
Packit Service 7770af
    bool exclude(std::string str);
Packit Service 7770af
    ATTACH_AST_OPERATIONS(At_Root_Query)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ///////////
Packit Service 7770af
  // At-root.
Packit Service 7770af
  ///////////
Packit Service 7770af
  class At_Root_Block : public Has_Block {
Packit Service 7770af
    ADD_PROPERTY(At_Root_Query_Obj, expression)
Packit Service 7770af
  public:
Packit Service 7770af
    At_Root_Block(ParserState pstate, Block_Obj b = 0, At_Root_Query_Obj e = 0)
Packit Service 7770af
    : Has_Block(pstate, b), expression_(e)
Packit Service 7770af
    { statement_type(ATROOT); }
Packit Service 7770af
    At_Root_Block(const At_Root_Block* ptr)
Packit Service 7770af
    : Has_Block(ptr), expression_(ptr->expression_)
Packit Service 7770af
    { statement_type(ATROOT); }
Packit Service 7770af
    bool bubbles() { return true; }
Packit Service 7770af
    bool exclude_node(Statement_Obj s) {
Packit Service 7770af
      if (expression() == 0)
Packit Service 7770af
      {
Packit Service 7770af
        return s->statement_type() == Statement::RULESET;
Packit Service 7770af
      }
Packit Service 7770af
Packit Service 7770af
      if (s->statement_type() == Statement::DIRECTIVE)
Packit Service 7770af
      {
Packit Service 7770af
        if (Directive_Obj dir = Cast<Directive>(s))
Packit Service 7770af
        {
Packit Service 7770af
          std::string keyword(dir->keyword());
Packit Service 7770af
          if (keyword.length() > 0) keyword.erase(0, 1);
Packit Service 7770af
          return expression()->exclude(keyword);
Packit Service 7770af
        }
Packit Service 7770af
      }
Packit Service 7770af
      if (s->statement_type() == Statement::MEDIA)
Packit Service 7770af
      {
Packit Service 7770af
        return expression()->exclude("media");
Packit Service 7770af
      }
Packit Service 7770af
      if (s->statement_type() == Statement::RULESET)
Packit Service 7770af
      {
Packit Service 7770af
        return expression()->exclude("rule");
Packit Service 7770af
      }
Packit Service 7770af
      if (s->statement_type() == Statement::SUPPORTS)
Packit Service 7770af
      {
Packit Service 7770af
        return expression()->exclude("supports");
Packit Service 7770af
      }
Packit Service 7770af
      if (Directive_Obj dir = Cast<Directive>(s))
Packit Service 7770af
      {
Packit Service 7770af
        if (dir->is_keyframes()) return expression()->exclude("keyframes");
Packit Service 7770af
      }
Packit Service 7770af
      return false;
Packit Service 7770af
    }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(At_Root_Block)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  //////////////////
Packit Service 7770af
  // The null value.
Packit Service 7770af
  //////////////////
Packit Service 7770af
  class Null : public Value {
Packit Service 7770af
  public:
Packit Service 7770af
    Null(ParserState pstate) : Value(pstate) { concrete_type(NULL_VAL); }
Packit Service 7770af
    Null(const Null* ptr) : Value(ptr) { concrete_type(NULL_VAL); }
Packit Service 7770af
    std::string type() const { return "null"; }
Packit Service 7770af
    static std::string type_name() { return "null"; }
Packit Service 7770af
    bool is_invisible() const { return true; }
Packit Service 7770af
    operator bool() { return false; }
Packit Service 7770af
    bool is_false() { return true; }
Packit Service 7770af
Packit Service 7770af
    virtual size_t hash()
Packit Service 7770af
    {
Packit Service 7770af
      return -1;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    virtual bool operator== (const Expression& rhs) const;
Packit Service 7770af
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Null)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  /////////////////////////////////
Packit Service 7770af
  // Thunks for delayed evaluation.
Packit Service 7770af
  /////////////////////////////////
Packit Service 7770af
  class Thunk : public Expression {
Packit Service 7770af
    ADD_PROPERTY(Expression_Obj, expression)
Packit Service 7770af
    ADD_PROPERTY(Env*, environment)
Packit Service 7770af
  public:
Packit Service 7770af
    Thunk(ParserState pstate, Expression_Obj exp, Env* env = 0)
Packit Service 7770af
    : Expression(pstate), expression_(exp), environment_(env)
Packit Service 7770af
    { }
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  /////////////////////////////////////////////////////////
Packit Service 7770af
  // Individual parameter objects for mixins and functions.
Packit Service 7770af
  /////////////////////////////////////////////////////////
Packit Service 7770af
  class Parameter : public AST_Node {
Packit Service 7770af
    ADD_CONSTREF(std::string, name)
Packit Service 7770af
    ADD_PROPERTY(Expression_Obj, default_value)
Packit Service 7770af
    ADD_PROPERTY(bool, is_rest_parameter)
Packit Service 7770af
  public:
Packit Service 7770af
    Parameter(ParserState pstate,
Packit Service 7770af
              std::string n, Expression_Obj def = 0, bool rest = false)
Packit Service 7770af
    : AST_Node(pstate), name_(n), default_value_(def), is_rest_parameter_(rest)
Packit Service 7770af
    {
Packit Service 7770af
      // tried to come up with a spec test for this, but it does no longer
Packit Service 7770af
      // get  past the parser (it error out earlier). A spec test was added!
Packit Service 7770af
      // if (default_value_ && is_rest_parameter_) {
Packit Service 7770af
      //   error("variable-length parameter may not have a default value", pstate_);
Packit Service 7770af
      // }
Packit Service 7770af
    }
Packit Service 7770af
    Parameter(const Parameter* ptr)
Packit Service 7770af
    : AST_Node(ptr),
Packit Service 7770af
      name_(ptr->name_),
Packit Service 7770af
      default_value_(ptr->default_value_),
Packit Service 7770af
      is_rest_parameter_(ptr->is_rest_parameter_)
Packit Service 7770af
    {
Packit Service 7770af
      // tried to come up with a spec test for this, but it does no longer
Packit Service 7770af
      // get  past the parser (it error out earlier). A spec test was added!
Packit Service 7770af
      // if (default_value_ && is_rest_parameter_) {
Packit Service 7770af
      //   error("variable-length parameter may not have a default value", pstate_);
Packit Service 7770af
      // }
Packit Service 7770af
    }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Parameter)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  /////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Parameter lists -- in their own class to facilitate context-sensitive
Packit Service 7770af
  // error checking (e.g., ensuring that all optional parameters follow all
Packit Service 7770af
  // required parameters).
Packit Service 7770af
  /////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class Parameters : public AST_Node, public Vectorized<Parameter_Obj> {
Packit Service 7770af
    ADD_PROPERTY(bool, has_optional_parameters)
Packit Service 7770af
    ADD_PROPERTY(bool, has_rest_parameter)
Packit Service 7770af
  protected:
Packit Service 7770af
    void adjust_after_pushing(Parameter_Obj p)
Packit Service 7770af
    {
Packit Service 7770af
      if (p->default_value()) {
Packit Service 7770af
        if (has_rest_parameter()) {
Packit Service 7770af
          error("optional parameters may not be combined with variable-length parameters", p->pstate());
Packit Service 7770af
        }
Packit Service 7770af
        has_optional_parameters(true);
Packit Service 7770af
      }
Packit Service 7770af
      else if (p->is_rest_parameter()) {
Packit Service 7770af
        if (has_rest_parameter()) {
Packit Service 7770af
          error("functions and mixins cannot have more than one variable-length parameter", p->pstate());
Packit Service 7770af
        }
Packit Service 7770af
        has_rest_parameter(true);
Packit Service 7770af
      }
Packit Service 7770af
      else {
Packit Service 7770af
        if (has_rest_parameter()) {
Packit Service 7770af
          error("required parameters must precede variable-length parameters", p->pstate());
Packit Service 7770af
        }
Packit Service 7770af
        if (has_optional_parameters()) {
Packit Service 7770af
          error("required parameters must precede optional parameters", p->pstate());
Packit Service 7770af
        }
Packit Service 7770af
      }
Packit Service 7770af
    }
Packit Service 7770af
  public:
Packit Service 7770af
    Parameters(ParserState pstate)
Packit Service 7770af
    : AST_Node(pstate),
Packit Service 7770af
      Vectorized<Parameter_Obj>(),
Packit Service 7770af
      has_optional_parameters_(false),
Packit Service 7770af
      has_rest_parameter_(false)
Packit Service 7770af
    { }
Packit Service 7770af
    Parameters(const Parameters* ptr)
Packit Service 7770af
    : AST_Node(ptr),
Packit Service 7770af
      Vectorized<Parameter_Obj>(*ptr),
Packit Service 7770af
      has_optional_parameters_(ptr->has_optional_parameters_),
Packit Service 7770af
      has_rest_parameter_(ptr->has_rest_parameter_)
Packit Service 7770af
    { }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Parameters)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  /////////////////////////////////////////
Packit Service 7770af
  // Abstract base class for CSS selectors.
Packit Service 7770af
  /////////////////////////////////////////
Packit Service 7770af
  class Selector : public Expression {
Packit Service 7770af
    // ADD_PROPERTY(bool, has_reference)
Packit Service 7770af
    // line break before list separator
Packit Service 7770af
    ADD_PROPERTY(bool, has_line_feed)
Packit Service 7770af
    // line break after list separator
Packit Service 7770af
    ADD_PROPERTY(bool, has_line_break)
Packit Service 7770af
    // maybe we have optional flag
Packit Service 7770af
    ADD_PROPERTY(bool, is_optional)
Packit Service 7770af
    // parent block pointers
Packit Service 7770af
Packit Service 7770af
    // must not be a reference counted object
Packit Service 7770af
    // otherwise we create circular references
Packit Service 7770af
    ADD_PROPERTY(Media_Block_Ptr, media_block)
Packit Service 7770af
  protected:
Packit Service 7770af
    size_t hash_;
Packit Service 7770af
  public:
Packit Service 7770af
    Selector(ParserState pstate)
Packit Service 7770af
    : Expression(pstate),
Packit Service 7770af
      has_line_feed_(false),
Packit Service 7770af
      has_line_break_(false),
Packit Service 7770af
      is_optional_(false),
Packit Service 7770af
      media_block_(0),
Packit Service 7770af
      hash_(0)
Packit Service 7770af
    { concrete_type(SELECTOR); }
Packit Service 7770af
    Selector(const Selector* ptr)
Packit Service 7770af
    : Expression(ptr),
Packit Service 7770af
      // has_reference_(ptr->has_reference_),
Packit Service 7770af
      has_line_feed_(ptr->has_line_feed_),
Packit Service 7770af
      has_line_break_(ptr->has_line_break_),
Packit Service 7770af
      is_optional_(ptr->is_optional_),
Packit Service 7770af
      media_block_(ptr->media_block_),
Packit Service 7770af
      hash_(ptr->hash_)
Packit Service 7770af
    { concrete_type(SELECTOR); }
Packit Service 7770af
    virtual ~Selector() = 0;
Packit Service 7770af
    virtual size_t hash() = 0;
Packit Service 7770af
    virtual unsigned long specificity() const = 0;
Packit Service 7770af
    virtual void set_media_block(Media_Block_Ptr mb) {
Packit Service 7770af
      media_block(mb);
Packit Service 7770af
    }
Packit Service 7770af
    virtual bool has_parent_ref() const {
Packit Service 7770af
      return false;
Packit Service 7770af
    }
Packit Service 7770af
    virtual bool has_real_parent_ref() const {
Packit Service 7770af
      return false;
Packit Service 7770af
    }
Packit Service 7770af
    // dispatch to correct handlers
Packit Service 7770af
    virtual bool operator<(const Selector& rhs) const = 0;
Packit Service 7770af
    virtual bool operator==(const Selector& rhs) const = 0;
Packit Service 7770af
    ATTACH_VIRTUAL_AST_OPERATIONS(Selector);
Packit Service 7770af
  };
Packit Service 7770af
  inline Selector::~Selector() { }
Packit Service 7770af
Packit Service 7770af
  /////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Interpolated selectors -- the interpolated String will be expanded and
Packit Service 7770af
  // re-parsed into a normal selector class.
Packit Service 7770af
  /////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class Selector_Schema : public AST_Node {
Packit Service 7770af
    ADD_PROPERTY(String_Obj, contents)
Packit Service 7770af
    ADD_PROPERTY(bool, connect_parent);
Packit Service 7770af
    // must not be a reference counted object
Packit Service 7770af
    // otherwise we create circular references
Packit Service 7770af
    ADD_PROPERTY(Media_Block_Ptr, media_block)
Packit Service 7770af
    // store computed hash
Packit Service 7770af
    size_t hash_;
Packit Service 7770af
  public:
Packit Service 7770af
    Selector_Schema(ParserState pstate, String_Obj c)
Packit Service 7770af
    : AST_Node(pstate),
Packit Service 7770af
      contents_(c),
Packit Service 7770af
      connect_parent_(true),
Packit Service 7770af
      media_block_(NULL),
Packit Service 7770af
      hash_(0)
Packit Service 7770af
    { }
Packit Service 7770af
    Selector_Schema(const Selector_Schema* ptr)
Packit Service 7770af
    : AST_Node(ptr),
Packit Service 7770af
      contents_(ptr->contents_),
Packit Service 7770af
      connect_parent_(ptr->connect_parent_),
Packit Service 7770af
      media_block_(ptr->media_block_),
Packit Service 7770af
      hash_(ptr->hash_)
Packit Service 7770af
    { }
Packit Service 7770af
    virtual bool has_parent_ref() const;
Packit Service 7770af
    virtual bool has_real_parent_ref() const;
Packit Service 7770af
    virtual bool operator<(const Selector& rhs) const;
Packit Service 7770af
    virtual bool operator==(const Selector& rhs) const;
Packit Service 7770af
    // selector schema is not yet a final selector, so we do not
Packit Service 7770af
    // have a specificity for it yet. We need to
Packit Service 7770af
    virtual unsigned long specificity() const { return 0; }
Packit Service 7770af
    virtual size_t hash() {
Packit Service 7770af
      if (hash_ == 0) {
Packit Service 7770af
        hash_combine(hash_, contents_->hash());
Packit Service 7770af
      }
Packit Service 7770af
      return hash_;
Packit Service 7770af
    }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Selector_Schema)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ////////////////////////////////////////////
Packit Service 7770af
  // Abstract base class for simple selectors.
Packit Service 7770af
  ////////////////////////////////////////////
Packit Service 7770af
  class Simple_Selector : public Selector {
Packit Service 7770af
    ADD_CONSTREF(std::string, ns)
Packit Service 7770af
    ADD_CONSTREF(std::string, name)
Packit Service 7770af
    ADD_PROPERTY(Simple_Type, simple_type)
Packit Service 7770af
    ADD_PROPERTY(bool, has_ns)
Packit Service 7770af
  public:
Packit Service 7770af
    Simple_Selector(ParserState pstate, std::string n = "")
Packit Service 7770af
    : Selector(pstate), ns_(""), name_(n), has_ns_(false)
Packit Service 7770af
    {
Packit Service 7770af
      simple_type(SIMPLE);
Packit Service 7770af
      size_t pos = n.find('|');
Packit Service 7770af
      // found some namespace
Packit Service 7770af
      if (pos != std::string::npos) {
Packit Service 7770af
        has_ns_ = true;
Packit Service 7770af
        ns_ = n.substr(0, pos);
Packit Service 7770af
        name_ = n.substr(pos + 1);
Packit Service 7770af
      }
Packit Service 7770af
    }
Packit Service 7770af
    Simple_Selector(const Simple_Selector* ptr)
Packit Service 7770af
    : Selector(ptr),
Packit Service 7770af
      ns_(ptr->ns_),
Packit Service 7770af
      name_(ptr->name_),
Packit Service 7770af
      has_ns_(ptr->has_ns_)
Packit Service 7770af
    { simple_type(SIMPLE); }
Packit Service 7770af
    virtual std::string ns_name() const
Packit Service 7770af
    {
Packit Service 7770af
      std::string name("");
Packit Service 7770af
      if (has_ns_)
Packit Service 7770af
        name += ns_ + "|";
Packit Service 7770af
      return name + name_;
Packit Service 7770af
    }
Packit Service 7770af
    virtual size_t hash()
Packit Service 7770af
    {
Packit Service 7770af
      if (hash_ == 0) {
Packit Service 7770af
        hash_combine(hash_, std::hash<int>()(SELECTOR));
Packit Service 7770af
        hash_combine(hash_, std::hash<std::string>()(ns()));
Packit Service 7770af
        hash_combine(hash_, std::hash<std::string>()(name()));
Packit Service 7770af
      }
Packit Service 7770af
      return hash_;
Packit Service 7770af
    }
Packit Service 7770af
    // namespace compare functions
Packit Service 7770af
    bool is_ns_eq(const Simple_Selector& r) const;
Packit Service 7770af
    // namespace query functions
Packit Service 7770af
    bool is_universal_ns() const
Packit Service 7770af
    {
Packit Service 7770af
      return has_ns_ && ns_ == "*";
Packit Service 7770af
    }
Packit Service 7770af
    bool has_universal_ns() const
Packit Service 7770af
    {
Packit Service 7770af
      return !has_ns_ || ns_ == "*";
Packit Service 7770af
    }
Packit Service 7770af
    bool is_empty_ns() const
Packit Service 7770af
    {
Packit Service 7770af
      return !has_ns_ || ns_ == "";
Packit Service 7770af
    }
Packit Service 7770af
    bool has_empty_ns() const
Packit Service 7770af
    {
Packit Service 7770af
      return has_ns_ && ns_ == "";
Packit Service 7770af
    }
Packit Service 7770af
    bool has_qualified_ns() const
Packit Service 7770af
    {
Packit Service 7770af
      return has_ns_ && ns_ != "" && ns_ != "*";
Packit Service 7770af
    }
Packit Service 7770af
    // name query functions
Packit Service 7770af
    bool is_universal() const
Packit Service 7770af
    {
Packit Service 7770af
      return name_ == "*";
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    virtual bool has_placeholder() {
Packit Service 7770af
      return false;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    virtual ~Simple_Selector() = 0;
Packit Service 7770af
    virtual Compound_Selector_Ptr unify_with(Compound_Selector_Ptr);
Packit Service 7770af
    virtual bool has_parent_ref() const { return false; };
Packit Service 7770af
    virtual bool has_real_parent_ref() const  { return false; };
Packit Service 7770af
    virtual bool is_pseudo_element() const { return false; }
Packit Service 7770af
Packit Service 7770af
    virtual bool is_superselector_of(Compound_Selector_Obj sub) { return false; }
Packit Service 7770af
Packit Service 7770af
    virtual bool operator==(const Selector& rhs) const;
Packit Service 7770af
    virtual bool operator==(const Simple_Selector& rhs) const;
Packit Service 7770af
    inline bool operator!=(const Simple_Selector& rhs) const { return !(*this == rhs); }
Packit Service 7770af
Packit Service 7770af
    bool operator<(const Selector& rhs) const;
Packit Service 7770af
    bool operator<(const Simple_Selector& rhs) const;
Packit Service 7770af
    // default implementation should work for most of the simple selectors (otherwise overload)
Packit Service 7770af
    ATTACH_VIRTUAL_AST_OPERATIONS(Simple_Selector);
Packit Service 7770af
    ATTACH_OPERATIONS();
Packit Service 7770af
  };
Packit Service 7770af
  inline Simple_Selector::~Simple_Selector() { }
Packit Service 7770af
Packit Service 7770af
Packit Service 7770af
  //////////////////////////////////
Packit Service 7770af
  // The Parent Selector Expression.
Packit Service 7770af
  //////////////////////////////////
Packit Service 7770af
  // parent selectors can occur in selectors but also
Packit Service 7770af
  // inside strings in declarations (Compound_Selector).
Packit Service 7770af
  // only one simple parent selector means the first case.
Packit Service 7770af
  class Parent_Selector : public Simple_Selector {
Packit Service 7770af
    ADD_PROPERTY(bool, real)
Packit Service 7770af
  public:
Packit Service 7770af
    Parent_Selector(ParserState pstate, bool r = true)
Packit Service 7770af
    : Simple_Selector(pstate, "&"), real_(r)
Packit Service 7770af
    { /* has_reference(true); */ }
Packit Service 7770af
    Parent_Selector(const Parent_Selector* ptr)
Packit Service 7770af
    : Simple_Selector(ptr), real_(ptr->real_)
Packit Service 7770af
    { /* has_reference(true); */ }
Packit Service 7770af
    bool is_real_parent_ref() const { return real(); };
Packit Service 7770af
    virtual bool has_parent_ref() const { return true; };
Packit Service 7770af
    virtual bool has_real_parent_ref() const { return is_real_parent_ref(); };
Packit Service 7770af
    virtual unsigned long specificity() const
Packit Service 7770af
    {
Packit Service 7770af
      return 0;
Packit Service 7770af
    }
Packit Service 7770af
    std::string type() const { return "selector"; }
Packit Service 7770af
    static std::string type_name() { return "selector"; }
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Parent_Selector)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  /////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Placeholder selectors (e.g., "%foo") for use in extend-only selectors.
Packit Service 7770af
  /////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class Placeholder_Selector : public Simple_Selector {
Packit Service 7770af
  public:
Packit Service 7770af
    Placeholder_Selector(ParserState pstate, std::string n)
Packit Service 7770af
    : Simple_Selector(pstate, n)
Packit Service 7770af
    { }
Packit Service 7770af
    Placeholder_Selector(const Placeholder_Selector* ptr)
Packit Service 7770af
    : Simple_Selector(ptr)
Packit Service 7770af
    { }
Packit Service 7770af
    virtual unsigned long specificity() const
Packit Service 7770af
    {
Packit Service 7770af
      return Constants::Specificity_Base;
Packit Service 7770af
    }
Packit Service 7770af
    virtual bool has_placeholder() {
Packit Service 7770af
      return true;
Packit Service 7770af
    }
Packit Service 7770af
    virtual ~Placeholder_Selector() {};
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Placeholder_Selector)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  /////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Element selectors (and the universal selector) -- e.g., div, span, *.
Packit Service 7770af
  /////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class Element_Selector : public Simple_Selector {
Packit Service 7770af
  public:
Packit Service 7770af
    Element_Selector(ParserState pstate, std::string n)
Packit Service 7770af
    : Simple_Selector(pstate, n)
Packit Service 7770af
    { }
Packit Service 7770af
    Element_Selector(const Element_Selector* ptr)
Packit Service 7770af
    : Simple_Selector(ptr)
Packit Service 7770af
    { }
Packit Service 7770af
    virtual unsigned long specificity() const
Packit Service 7770af
    {
Packit Service 7770af
      if (name() == "*") return 0;
Packit Service 7770af
      else               return Constants::Specificity_Element;
Packit Service 7770af
    }
Packit Service 7770af
    virtual Simple_Selector_Ptr unify_with(Simple_Selector_Ptr);
Packit Service 7770af
    virtual Compound_Selector_Ptr unify_with(Compound_Selector_Ptr);
Packit Service 7770af
    virtual bool operator==(const Simple_Selector& rhs) const;
Packit Service 7770af
    virtual bool operator==(const Element_Selector& rhs) const;
Packit Service 7770af
    virtual bool operator<(const Simple_Selector& rhs) const;
Packit Service 7770af
    virtual bool operator<(const Element_Selector& rhs) const;
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Element_Selector)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ////////////////////////////////////////////////
Packit Service 7770af
  // Class selectors  -- i.e., .foo.
Packit Service 7770af
  ////////////////////////////////////////////////
Packit Service 7770af
  class Class_Selector : public Simple_Selector {
Packit Service 7770af
  public:
Packit Service 7770af
    Class_Selector(ParserState pstate, std::string n)
Packit Service 7770af
    : Simple_Selector(pstate, n)
Packit Service 7770af
    { }
Packit Service 7770af
    Class_Selector(const Class_Selector* ptr)
Packit Service 7770af
    : Simple_Selector(ptr)
Packit Service 7770af
    { }
Packit Service 7770af
    virtual unsigned long specificity() const
Packit Service 7770af
    {
Packit Service 7770af
      return Constants::Specificity_Class;
Packit Service 7770af
    }
Packit Service 7770af
    virtual Compound_Selector_Ptr unify_with(Compound_Selector_Ptr);
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Class_Selector)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ////////////////////////////////////////////////
Packit Service 7770af
  // ID selectors -- i.e., #foo.
Packit Service 7770af
  ////////////////////////////////////////////////
Packit Service 7770af
  class Id_Selector : public Simple_Selector {
Packit Service 7770af
  public:
Packit Service 7770af
    Id_Selector(ParserState pstate, std::string n)
Packit Service 7770af
    : Simple_Selector(pstate, n)
Packit Service 7770af
    { }
Packit Service 7770af
    Id_Selector(const Id_Selector* ptr)
Packit Service 7770af
    : Simple_Selector(ptr)
Packit Service 7770af
    { }
Packit Service 7770af
    virtual unsigned long specificity() const
Packit Service 7770af
    {
Packit Service 7770af
      return Constants::Specificity_ID;
Packit Service 7770af
    }
Packit Service 7770af
    virtual Compound_Selector_Ptr unify_with(Compound_Selector_Ptr);
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Id_Selector)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ///////////////////////////////////////////////////
Packit Service 7770af
  // Attribute selectors -- e.g., [src*=".jpg"], etc.
Packit Service 7770af
  ///////////////////////////////////////////////////
Packit Service 7770af
  class Attribute_Selector : public Simple_Selector {
Packit Service 7770af
    ADD_CONSTREF(std::string, matcher)
Packit Service 7770af
    // this cannot be changed to obj atm!!!!!!????!!!!!!!
Packit Service 7770af
    ADD_PROPERTY(String_Obj, value) // might be interpolated
Packit Service 7770af
  public:
Packit Service 7770af
    Attribute_Selector(ParserState pstate, std::string n, std::string m, String_Obj v)
Packit Service 7770af
    : Simple_Selector(pstate, n), matcher_(m), value_(v)
Packit Service 7770af
    { simple_type(ATTR_SEL); }
Packit Service 7770af
    Attribute_Selector(const Attribute_Selector* ptr)
Packit Service 7770af
    : Simple_Selector(ptr),
Packit Service 7770af
      matcher_(ptr->matcher_),
Packit Service 7770af
      value_(ptr->value_)
Packit Service 7770af
    { simple_type(ATTR_SEL); }
Packit Service 7770af
    virtual size_t hash()
Packit Service 7770af
    {
Packit Service 7770af
      if (hash_ == 0) {
Packit Service 7770af
        hash_combine(hash_, Simple_Selector::hash());
Packit Service 7770af
        hash_combine(hash_, std::hash<std::string>()(matcher()));
Packit Service 7770af
        if (value_) hash_combine(hash_, value_->hash());
Packit Service 7770af
      }
Packit Service 7770af
      return hash_;
Packit Service 7770af
    }
Packit Service 7770af
    virtual unsigned long specificity() const
Packit Service 7770af
    {
Packit Service 7770af
      return Constants::Specificity_Attr;
Packit Service 7770af
    }
Packit Service 7770af
    virtual bool operator==(const Simple_Selector& rhs) const;
Packit Service 7770af
    virtual bool operator==(const Attribute_Selector& rhs) const;
Packit Service 7770af
    virtual bool operator<(const Simple_Selector& rhs) const;
Packit Service 7770af
    virtual bool operator<(const Attribute_Selector& rhs) const;
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Attribute_Selector)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  //////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Pseudo selectors -- e.g., :first-child, :nth-of-type(...), etc.
Packit Service 7770af
  //////////////////////////////////////////////////////////////////
Packit Service 7770af
  /* '::' starts a pseudo-element, ':' a pseudo-class */
Packit Service 7770af
  /* Except :first-line, :first-letter, :before and :after */
Packit Service 7770af
  /* Note that pseudo-elements are restricted to one per selector */
Packit Service 7770af
  /* and occur only in the last simple_selector_sequence. */
Packit Service 7770af
  inline bool is_pseudo_class_element(const std::string& name)
Packit Service 7770af
  {
Packit Service 7770af
    return name == ":before"       ||
Packit Service 7770af
           name == ":after"        ||
Packit Service 7770af
           name == ":first-line"   ||
Packit Service 7770af
           name == ":first-letter";
Packit Service 7770af
  }
Packit Service 7770af
Packit Service 7770af
  // Pseudo Selector cannot have any namespace?
Packit Service 7770af
  class Pseudo_Selector : public Simple_Selector {
Packit Service 7770af
    ADD_PROPERTY(String_Obj, expression)
Packit Service 7770af
  public:
Packit Service 7770af
    Pseudo_Selector(ParserState pstate, std::string n, String_Obj expr = 0)
Packit Service 7770af
    : Simple_Selector(pstate, n), expression_(expr)
Packit Service 7770af
    { simple_type(PSEUDO_SEL); }
Packit Service 7770af
    Pseudo_Selector(const Pseudo_Selector* ptr)
Packit Service 7770af
    : Simple_Selector(ptr), expression_(ptr->expression_)
Packit Service 7770af
    { simple_type(PSEUDO_SEL); }
Packit Service 7770af
Packit Service 7770af
    // A pseudo-element is made of two colons (::) followed by the name.
Packit Service 7770af
    // The `::` notation is introduced by the current document in order to
Packit Service 7770af
    // establish a discrimination between pseudo-classes and pseudo-elements.
Packit Service 7770af
    // For compatibility with existing style sheets, user agents must also
Packit Service 7770af
    // accept the previous one-colon notation for pseudo-elements introduced
Packit Service 7770af
    // in CSS levels 1 and 2 (namely, :first-line, :first-letter, :before and
Packit Service 7770af
    // :after). This compatibility is not allowed for the new pseudo-elements
Packit Service 7770af
    // introduced in this specification.
Packit Service 7770af
    virtual bool is_pseudo_element() const
Packit Service 7770af
    {
Packit Service 7770af
      return (name_[0] == ':' && name_[1] == ':')
Packit Service 7770af
             || is_pseudo_class_element(name_);
Packit Service 7770af
    }
Packit Service 7770af
    virtual size_t hash()
Packit Service 7770af
    {
Packit Service 7770af
      if (hash_ == 0) {
Packit Service 7770af
        hash_combine(hash_, Simple_Selector::hash());
Packit Service 7770af
        if (expression_) hash_combine(hash_, expression_->hash());
Packit Service 7770af
      }
Packit Service 7770af
      return hash_;
Packit Service 7770af
    }
Packit Service 7770af
    virtual unsigned long specificity() const
Packit Service 7770af
    {
Packit Service 7770af
      if (is_pseudo_element())
Packit Service 7770af
        return Constants::Specificity_Element;
Packit Service 7770af
      return Constants::Specificity_Pseudo;
Packit Service 7770af
    }
Packit Service 7770af
    virtual bool operator==(const Simple_Selector& rhs) const;
Packit Service 7770af
    virtual bool operator==(const Pseudo_Selector& rhs) const;
Packit Service 7770af
    virtual bool operator<(const Simple_Selector& rhs) const;
Packit Service 7770af
    virtual bool operator<(const Pseudo_Selector& rhs) const;
Packit Service 7770af
    virtual Compound_Selector_Ptr unify_with(Compound_Selector_Ptr);
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Pseudo_Selector)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  /////////////////////////////////////////////////
Packit Service 7770af
  // Wrapped selector -- pseudo selector that takes a list of selectors as argument(s) e.g., :not(:first-of-type), :-moz-any(ol p.blah, ul, menu, dir)
Packit Service 7770af
  /////////////////////////////////////////////////
Packit Service 7770af
  class Wrapped_Selector : public Simple_Selector {
Packit Service 7770af
    ADD_PROPERTY(Selector_List_Obj, selector)
Packit Service 7770af
  public:
Packit Service 7770af
    Wrapped_Selector(ParserState pstate, std::string n, Selector_List_Obj sel)
Packit Service 7770af
    : Simple_Selector(pstate, n), selector_(sel)
Packit Service 7770af
    { simple_type(WRAPPED_SEL); }
Packit Service 7770af
    Wrapped_Selector(const Wrapped_Selector* ptr)
Packit Service 7770af
    : Simple_Selector(ptr), selector_(ptr->selector_)
Packit Service 7770af
    { simple_type(WRAPPED_SEL); }
Packit Service 7770af
    virtual bool is_superselector_of(Wrapped_Selector_Obj sub);
Packit Service 7770af
    // Selectors inside the negation pseudo-class are counted like any
Packit Service 7770af
    // other, but the negation itself does not count as a pseudo-class.
Packit Service 7770af
    virtual size_t hash();
Packit Service 7770af
    virtual bool has_parent_ref() const;
Packit Service 7770af
    virtual bool has_real_parent_ref() const;
Packit Service 7770af
    virtual unsigned long specificity() const;
Packit Service 7770af
    virtual bool find ( bool (*f)(AST_Node_Obj) );
Packit Service 7770af
    virtual bool operator==(const Simple_Selector& rhs) const;
Packit Service 7770af
    virtual bool operator==(const Wrapped_Selector& rhs) const;
Packit Service 7770af
    virtual bool operator<(const Simple_Selector& rhs) const;
Packit Service 7770af
    virtual bool operator<(const Wrapped_Selector& rhs) const;
Packit Service 7770af
    virtual void cloneChildren();
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Wrapped_Selector)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ////////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // Simple selector sequences. Maintains flags indicating whether it contains
Packit Service 7770af
  // any parent references or placeholders, to simplify expansion.
Packit Service 7770af
  ////////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class Compound_Selector : public Selector, public Vectorized<Simple_Selector_Obj> {
Packit Service 7770af
  private:
Packit Service 7770af
    ComplexSelectorSet sources_;
Packit Service 7770af
    ADD_PROPERTY(bool, extended);
Packit Service 7770af
    ADD_PROPERTY(bool, has_parent_reference);
Packit Service 7770af
  protected:
Packit Service 7770af
    void adjust_after_pushing(Simple_Selector_Obj s)
Packit Service 7770af
    {
Packit Service 7770af
      // if (s->has_reference())   has_reference(true);
Packit Service 7770af
      // if (s->has_placeholder()) has_placeholder(true);
Packit Service 7770af
    }
Packit Service 7770af
  public:
Packit Service 7770af
    Compound_Selector(ParserState pstate, size_t s = 0)
Packit Service 7770af
    : Selector(pstate),
Packit Service 7770af
      Vectorized<Simple_Selector_Obj>(s),
Packit Service 7770af
      extended_(false),
Packit Service 7770af
      has_parent_reference_(false)
Packit Service 7770af
    { }
Packit Service 7770af
    Compound_Selector(const Compound_Selector* ptr)
Packit Service 7770af
    : Selector(ptr),
Packit Service 7770af
      Vectorized<Simple_Selector_Obj>(*ptr),
Packit Service 7770af
      extended_(ptr->extended_),
Packit Service 7770af
      has_parent_reference_(ptr->has_parent_reference_)
Packit Service 7770af
    { }
Packit Service 7770af
    bool contains_placeholder() {
Packit Service 7770af
      for (size_t i = 0, L = length(); i < L; ++i) {
Packit Service 7770af
        if ((*this)[i]->has_placeholder()) return true;
Packit Service 7770af
      }
Packit Service 7770af
      return false;
Packit Service 7770af
    };
Packit Service 7770af
Packit Service 7770af
    void append(Simple_Selector_Ptr element);
Packit Service 7770af
Packit Service 7770af
    bool is_universal() const
Packit Service 7770af
    {
Packit Service 7770af
      return length() == 1 && (*this)[0]->is_universal();
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    Complex_Selector_Obj to_complex();
Packit Service 7770af
    Compound_Selector_Ptr unify_with(Compound_Selector_Ptr rhs);
Packit Service 7770af
    // virtual Placeholder_Selector_Ptr find_placeholder();
Packit Service 7770af
    virtual bool has_parent_ref() const;
Packit Service 7770af
    virtual bool has_real_parent_ref() const;
Packit Service 7770af
    Simple_Selector_Ptr base() const {
Packit Service 7770af
      if (length() == 0) return 0;
Packit Service 7770af
      // ToDo: why is this needed?
Packit Service 7770af
      if (Cast<Element_Selector>((*this)[0]))
Packit Service 7770af
        return (*this)[0];
Packit Service 7770af
      return 0;
Packit Service 7770af
    }
Packit Service 7770af
    virtual bool is_superselector_of(Compound_Selector_Obj sub, std::string wrapped = "");
Packit Service 7770af
    virtual bool is_superselector_of(Complex_Selector_Obj sub, std::string wrapped = "");
Packit Service 7770af
    virtual bool is_superselector_of(Selector_List_Obj sub, std::string wrapped = "");
Packit Service 7770af
    virtual size_t hash()
Packit Service 7770af
    {
Packit Service 7770af
      if (Selector::hash_ == 0) {
Packit Service 7770af
        hash_combine(Selector::hash_, std::hash<int>()(SELECTOR));
Packit Service 7770af
        if (length()) hash_combine(Selector::hash_, Vectorized::hash());
Packit Service 7770af
      }
Packit Service 7770af
      return Selector::hash_;
Packit Service 7770af
    }
Packit Service 7770af
    virtual unsigned long specificity() const
Packit Service 7770af
    {
Packit Service 7770af
      int sum = 0;
Packit Service 7770af
      for (size_t i = 0, L = length(); i < L; ++i)
Packit Service 7770af
      { sum += (*this)[i]->specificity(); }
Packit Service 7770af
      return sum;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    virtual bool has_placeholder()
Packit Service 7770af
    {
Packit Service 7770af
      if (length() == 0) return false;
Packit Service 7770af
      if (Simple_Selector_Obj ss = elements().front()) {
Packit Service 7770af
        if (ss->has_placeholder()) return true;
Packit Service 7770af
      }
Packit Service 7770af
      return false;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    bool is_empty_reference()
Packit Service 7770af
    {
Packit Service 7770af
      return length() == 1 &&
Packit Service 7770af
             Cast<Parent_Selector>((*this)[0]);
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    virtual bool find ( bool (*f)(AST_Node_Obj) );
Packit Service 7770af
    virtual bool operator<(const Selector& rhs) const;
Packit Service 7770af
    virtual bool operator==(const Selector& rhs) const;
Packit Service 7770af
    virtual bool operator<(const Compound_Selector& rhs) const;
Packit Service 7770af
    virtual bool operator==(const Compound_Selector& rhs) const;
Packit Service 7770af
    inline bool operator!=(const Compound_Selector& rhs) const { return !(*this == rhs); }
Packit Service 7770af
Packit Service 7770af
    ComplexSelectorSet& sources() { return sources_; }
Packit Service 7770af
    void clearSources() { sources_.clear(); }
Packit Service 7770af
    void mergeSources(ComplexSelectorSet& sources);
Packit Service 7770af
Packit Service 7770af
    Compound_Selector_Ptr minus(Compound_Selector_Ptr rhs);
Packit Service 7770af
    virtual void cloneChildren();
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Compound_Selector)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ////////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  // General selectors -- i.e., simple sequences combined with one of the four
Packit Service 7770af
  // CSS selector combinators (">", "+", "~", and whitespace). Essentially a
Packit Service 7770af
  // linked list.
Packit Service 7770af
  ////////////////////////////////////////////////////////////////////////////
Packit Service 7770af
  class Complex_Selector : public Selector {
Packit Service 7770af
  public:
Packit Service 7770af
    enum Combinator { ANCESTOR_OF, PARENT_OF, PRECEDES, ADJACENT_TO, REFERENCE };
Packit Service 7770af
  private:
Packit Service 7770af
    HASH_CONSTREF(Combinator, combinator)
Packit Service 7770af
    HASH_PROPERTY(Compound_Selector_Obj, head)
Packit Service 7770af
    HASH_PROPERTY(Complex_Selector_Obj, tail)
Packit Service 7770af
    HASH_PROPERTY(String_Obj, reference);
Packit Service 7770af
  public:
Packit Service 7770af
    bool contains_placeholder() {
Packit Service 7770af
      if (head() && head()->contains_placeholder()) return true;
Packit Service 7770af
      if (tail() && tail()->contains_placeholder()) return true;
Packit Service 7770af
      return false;
Packit Service 7770af
    };
Packit Service 7770af
    Complex_Selector(ParserState pstate,
Packit Service 7770af
                     Combinator c = ANCESTOR_OF,
Packit Service 7770af
                     Compound_Selector_Obj h = 0,
Packit Service 7770af
                     Complex_Selector_Obj t = 0,
Packit Service 7770af
                     String_Obj r = 0)
Packit Service 7770af
    : Selector(pstate),
Packit Service 7770af
      combinator_(c),
Packit Service 7770af
      head_(h), tail_(t),
Packit Service 7770af
      reference_(r)
Packit Service 7770af
    {}
Packit Service 7770af
    Complex_Selector(const Complex_Selector* ptr)
Packit Service 7770af
    : Selector(ptr),
Packit Service 7770af
      combinator_(ptr->combinator_),
Packit Service 7770af
      head_(ptr->head_), tail_(ptr->tail_),
Packit Service 7770af
      reference_(ptr->reference_)
Packit Service 7770af
    {};
Packit Service 7770af
    virtual bool has_parent_ref() const;
Packit Service 7770af
    virtual bool has_real_parent_ref() const;
Packit Service 7770af
Packit Service 7770af
    Complex_Selector_Obj skip_empty_reference()
Packit Service 7770af
    {
Packit Service 7770af
      if ((!head_ || !head_->length() || head_->is_empty_reference()) &&
Packit Service 7770af
          combinator() == Combinator::ANCESTOR_OF)
Packit Service 7770af
      {
Packit Service 7770af
        if (!tail_) return 0;
Packit Service 7770af
        tail_->has_line_feed_ = this->has_line_feed_;
Packit Service 7770af
        // tail_->has_line_break_ = this->has_line_break_;
Packit Service 7770af
        return tail_->skip_empty_reference();
Packit Service 7770af
      }
Packit Service 7770af
      return this;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    // can still have a tail
Packit Service 7770af
    bool is_empty_ancestor() const
Packit Service 7770af
    {
Packit Service 7770af
      return (!head() || head()->length() == 0) &&
Packit Service 7770af
             combinator() == Combinator::ANCESTOR_OF;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    Selector_List_Ptr tails(Selector_List_Ptr tails);
Packit Service 7770af
Packit Service 7770af
    // front returns the first real tail
Packit Service 7770af
    // skips over parent and empty ones
Packit Service 7770af
    Complex_Selector_Obj first();
Packit Service 7770af
    // last returns the last real tail
Packit Service 7770af
    Complex_Selector_Obj last();
Packit Service 7770af
Packit Service 7770af
    // some shortcuts that should be removed
Packit Service 7770af
    Complex_Selector_Obj innermost() { return last(); };
Packit Service 7770af
Packit Service 7770af
    size_t length() const;
Packit Service 7770af
    Selector_List_Ptr resolve_parent_refs(std::vector<Selector_List_Obj>& pstack, bool implicit_parent = true);
Packit Service 7770af
    virtual bool is_superselector_of(Compound_Selector_Obj sub, std::string wrapping = "");
Packit Service 7770af
    virtual bool is_superselector_of(Complex_Selector_Obj sub, std::string wrapping = "");
Packit Service 7770af
    virtual bool is_superselector_of(Selector_List_Obj sub, std::string wrapping = "");
Packit Service 7770af
    Selector_List_Ptr unify_with(Complex_Selector_Ptr rhs);
Packit Service 7770af
    Combinator clear_innermost();
Packit Service 7770af
    void append(Complex_Selector_Obj);
Packit Service 7770af
    void set_innermost(Complex_Selector_Obj, Combinator);
Packit Service 7770af
    virtual size_t hash()
Packit Service 7770af
    {
Packit Service 7770af
      if (hash_ == 0) {
Packit Service 7770af
        hash_combine(hash_, std::hash<int>()(SELECTOR));
Packit Service 7770af
        hash_combine(hash_, std::hash<int>()(combinator_));
Packit Service 7770af
        if (head_) hash_combine(hash_, head_->hash());
Packit Service 7770af
        if (tail_) hash_combine(hash_, tail_->hash());
Packit Service 7770af
      }
Packit Service 7770af
      return hash_;
Packit Service 7770af
    }
Packit Service 7770af
    virtual unsigned long specificity() const
Packit Service 7770af
    {
Packit Service 7770af
      int sum = 0;
Packit Service 7770af
      if (head()) sum += head()->specificity();
Packit Service 7770af
      if (tail()) sum += tail()->specificity();
Packit Service 7770af
      return sum;
Packit Service 7770af
    }
Packit Service 7770af
    virtual void set_media_block(Media_Block_Ptr mb) {
Packit Service 7770af
      media_block(mb);
Packit Service 7770af
      if (tail_) tail_->set_media_block(mb);
Packit Service 7770af
      if (head_) head_->set_media_block(mb);
Packit Service 7770af
    }
Packit Service 7770af
    virtual bool has_placeholder() {
Packit Service 7770af
      if (head_ && head_->has_placeholder()) return true;
Packit Service 7770af
      if (tail_ && tail_->has_placeholder()) return true;
Packit Service 7770af
      return false;
Packit Service 7770af
    }
Packit Service 7770af
    virtual bool find ( bool (*f)(AST_Node_Obj) );
Packit Service 7770af
    virtual bool operator<(const Selector& rhs) const;
Packit Service 7770af
    virtual bool operator==(const Selector& rhs) const;
Packit Service 7770af
    virtual bool operator<(const Complex_Selector& rhs) const;
Packit Service 7770af
    virtual bool operator==(const Complex_Selector& rhs) const;
Packit Service 7770af
    inline bool operator!=(const Complex_Selector& rhs) const { return !(*this == rhs); }
Packit Service 7770af
    const ComplexSelectorSet sources()
Packit Service 7770af
    {
Packit Service 7770af
      //s = Set.new
Packit Service 7770af
      //seq.map {|sseq_or_op| s.merge sseq_or_op.sources if sseq_or_op.is_a?(SimpleSequence)}
Packit Service 7770af
      //s
Packit Service 7770af
Packit Service 7770af
      ComplexSelectorSet srcs;
Packit Service 7770af
Packit Service 7770af
      Compound_Selector_Obj pHead = head();
Packit Service 7770af
      Complex_Selector_Obj  pTail = tail();
Packit Service 7770af
Packit Service 7770af
      if (pHead) {
Packit Service 7770af
        const ComplexSelectorSet& headSources = pHead->sources();
Packit Service 7770af
        srcs.insert(headSources.begin(), headSources.end());
Packit Service 7770af
      }
Packit Service 7770af
Packit Service 7770af
      if (pTail) {
Packit Service 7770af
        const ComplexSelectorSet& tailSources = pTail->sources();
Packit Service 7770af
        srcs.insert(tailSources.begin(), tailSources.end());
Packit Service 7770af
      }
Packit Service 7770af
Packit Service 7770af
      return srcs;
Packit Service 7770af
    }
Packit Service 7770af
    void addSources(ComplexSelectorSet& sources) {
Packit Service 7770af
      // members.map! {|m| m.is_a?(SimpleSequence) ? m.with_more_sources(sources) : m}
Packit Service 7770af
      Complex_Selector_Ptr pIter = this;
Packit Service 7770af
      while (pIter) {
Packit Service 7770af
        Compound_Selector_Ptr pHead = pIter->head();
Packit Service 7770af
Packit Service 7770af
        if (pHead) {
Packit Service 7770af
          pHead->mergeSources(sources);
Packit Service 7770af
        }
Packit Service 7770af
Packit Service 7770af
        pIter = pIter->tail();
Packit Service 7770af
      }
Packit Service 7770af
    }
Packit Service 7770af
    void clearSources() {
Packit Service 7770af
      Complex_Selector_Ptr pIter = this;
Packit Service 7770af
      while (pIter) {
Packit Service 7770af
        Compound_Selector_Ptr pHead = pIter->head();
Packit Service 7770af
Packit Service 7770af
        if (pHead) {
Packit Service 7770af
          pHead->clearSources();
Packit Service 7770af
        }
Packit Service 7770af
Packit Service 7770af
        pIter = pIter->tail();
Packit Service 7770af
      }
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    virtual void cloneChildren();
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Complex_Selector)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  ///////////////////////////////////
Packit Service 7770af
  // Comma-separated selector groups.
Packit Service 7770af
  ///////////////////////////////////
Packit Service 7770af
  class Selector_List : public Selector, public Vectorized<Complex_Selector_Obj> {
Packit Service 7770af
    ADD_PROPERTY(Selector_Schema_Obj, schema)
Packit Service 7770af
    ADD_CONSTREF(std::vector<std::string>, wspace)
Packit Service 7770af
  protected:
Packit Service 7770af
    void adjust_after_pushing(Complex_Selector_Obj c);
Packit Service 7770af
  public:
Packit Service 7770af
    Selector_List(ParserState pstate, size_t s = 0)
Packit Service 7770af
    : Selector(pstate),
Packit Service 7770af
      Vectorized<Complex_Selector_Obj>(s),
Packit Service 7770af
      schema_(NULL),
Packit Service 7770af
      wspace_(0)
Packit Service 7770af
    { }
Packit Service 7770af
    Selector_List(const Selector_List* ptr)
Packit Service 7770af
    : Selector(ptr),
Packit Service 7770af
      Vectorized<Complex_Selector_Obj>(*ptr),
Packit Service 7770af
      schema_(ptr->schema_),
Packit Service 7770af
      wspace_(ptr->wspace_)
Packit Service 7770af
    { }
Packit Service 7770af
    std::string type() const { return "list"; }
Packit Service 7770af
    // remove parent selector references
Packit Service 7770af
    // basically unwraps parsed selectors
Packit Service 7770af
    virtual bool has_parent_ref() const;
Packit Service 7770af
    virtual bool has_real_parent_ref() const;
Packit Service 7770af
    void remove_parent_selectors();
Packit Service 7770af
    Selector_List_Ptr resolve_parent_refs(std::vector<Selector_List_Obj>& pstack, bool implicit_parent = true);
Packit Service 7770af
    virtual bool is_superselector_of(Compound_Selector_Obj sub, std::string wrapping = "");
Packit Service 7770af
    virtual bool is_superselector_of(Complex_Selector_Obj sub, std::string wrapping = "");
Packit Service 7770af
    virtual bool is_superselector_of(Selector_List_Obj sub, std::string wrapping = "");
Packit Service 7770af
    Selector_List_Ptr unify_with(Selector_List_Ptr);
Packit Service 7770af
    void populate_extends(Selector_List_Obj, Subset_Map&);
Packit Service 7770af
    Selector_List_Obj eval(Eval& eval);
Packit Service 7770af
    virtual size_t hash()
Packit Service 7770af
    {
Packit Service 7770af
      if (Selector::hash_ == 0) {
Packit Service 7770af
        hash_combine(Selector::hash_, std::hash<int>()(SELECTOR));
Packit Service 7770af
        hash_combine(Selector::hash_, Vectorized::hash());
Packit Service 7770af
      }
Packit Service 7770af
      return Selector::hash_;
Packit Service 7770af
    }
Packit Service 7770af
    virtual unsigned long specificity() const
Packit Service 7770af
    {
Packit Service 7770af
      unsigned long sum = 0;
Packit Service 7770af
      unsigned long specificity;
Packit Service 7770af
      for (size_t i = 0, L = length(); i < L; ++i)
Packit Service 7770af
      {
Packit Service 7770af
        specificity = (*this)[i]->specificity();
Packit Service 7770af
        if (sum < specificity) sum = specificity;
Packit Service 7770af
      }
Packit Service 7770af
      return sum;
Packit Service 7770af
    }
Packit Service 7770af
    virtual void set_media_block(Media_Block_Ptr mb) {
Packit Service 7770af
      media_block(mb);
Packit Service 7770af
      for (Complex_Selector_Obj cs : elements()) {
Packit Service 7770af
        cs->set_media_block(mb);
Packit Service 7770af
      }
Packit Service 7770af
    }
Packit Service 7770af
    virtual bool has_placeholder() {
Packit Service 7770af
      for (Complex_Selector_Obj cs : elements()) {
Packit Service 7770af
        if (cs->has_placeholder()) return true;
Packit Service 7770af
      }
Packit Service 7770af
      return false;
Packit Service 7770af
    }
Packit Service 7770af
    virtual bool find ( bool (*f)(AST_Node_Obj) );
Packit Service 7770af
    virtual bool operator<(const Selector& rhs) const;
Packit Service 7770af
    virtual bool operator==(const Selector& rhs) const;
Packit Service 7770af
    virtual bool operator<(const Selector_List& rhs) const;
Packit Service 7770af
    virtual bool operator==(const Selector_List& rhs) const;
Packit Service 7770af
    // Selector Lists can be compared to comma lists
Packit Service 7770af
    virtual bool operator==(const Expression& rhs) const;
Packit Service 7770af
    virtual void cloneChildren();
Packit Service 7770af
    ATTACH_AST_OPERATIONS(Selector_List)
Packit Service 7770af
    ATTACH_OPERATIONS()
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
  // compare function for sorting and probably other other uses
Packit Service 7770af
  struct cmp_complex_selector { inline bool operator() (const Complex_Selector_Obj l, const Complex_Selector_Obj r) { return (*l < *r); } };
Packit Service 7770af
  struct cmp_compound_selector { inline bool operator() (const Compound_Selector_Obj l, const Compound_Selector_Obj r) { return (*l < *r); } };
Packit Service 7770af
  struct cmp_simple_selector { inline bool operator() (const Simple_Selector_Obj l, const Simple_Selector_Obj r) { return (*l < *r); } };
Packit Service 7770af
Packit Service 7770af
}
Packit Service 7770af
Packit Service 7770af
#ifdef __clang__
Packit Service 7770af
Packit Service 7770af
#pragma clang diagnostic pop
Packit Service 7770af
Packit Service 7770af
#endif
Packit Service 7770af
Packit Service 7770af
#endif