Blame src/node.hpp

Packit Service 7770af
#ifndef SASS_NODE_H
Packit Service 7770af
#define SASS_NODE_H
Packit Service 7770af
Packit Service 7770af
#include <deque>
Packit Service 7770af
#include <memory>
Packit Service 7770af
Packit Service 7770af
#include "ast.hpp"
Packit Service 7770af
Packit Service 7770af
Packit Service 7770af
namespace Sass {
Packit Service 7770af
Packit Service 7770af
Packit Service 7770af
Packit Service 7770af
Packit Service 7770af
  class Context;
Packit Service 7770af
Packit Service 7770af
  /*
Packit Service 7770af
   There are a lot of stumbling blocks when trying to port the ruby extend code to C++. The biggest is the choice of
Packit Service 7770af
   data type. The ruby code will pretty seamlessly switch types between an Array<SimpleSequence or Op> (libsass'
Packit Service 7770af
   equivalent is the Complex_Selector) to a Sequence, which contains more metadata about the sequence than just the
Packit Service 7770af
   selector info. They also have the ability to have arbitrary nestings of arrays like [1, [2]], which is hard to
Packit Service 7770af
   implement using Array equivalents in C++ (like the deque or vector). They also have the ability to include nil
Packit Service 7770af
   in the arrays, like [1, nil, 3], which has potential semantic differences than an empty array [1, [], 3]. To be
Packit Service 7770af
   able to represent all of these as unique cases, we need to create a tree of variant objects. The tree nature allows
Packit Service 7770af
   the inconsistent nesting levels. The variant nature (while making some of the C++ code uglier) allows the code to
Packit Service 7770af
   more closely match the ruby code, which is a huge benefit when attempting to implement an complex algorithm like
Packit Service 7770af
   the Extend operator.
Packit Service 7770af
Packit Service 7770af
   Note that the current libsass data model also pairs the combinator with the Complex_Selector that follows it, but
Packit Service 7770af
   ruby sass has no such restriction, so we attempt to create a data structure that can handle them split apart.
Packit Service 7770af
   */
Packit Service 7770af
Packit Service 7770af
  class Node;
Packit Service 7770af
  typedef std::deque<Node> NodeDeque;
Packit Service 7770af
  typedef std::shared_ptr<NodeDeque> NodeDequePtr;
Packit Service 7770af
Packit Service 7770af
  class Node {
Packit Service 7770af
  public:
Packit Service 7770af
    enum TYPE {
Packit Service 7770af
      SELECTOR,
Packit Service 7770af
      COMBINATOR,
Packit Service 7770af
      COLLECTION,
Packit Service 7770af
      NIL
Packit Service 7770af
    };
Packit Service 7770af
Packit Service 7770af
    TYPE type() const { return mType; }
Packit Service 7770af
    bool isCombinator() const { return mType == COMBINATOR; }
Packit Service 7770af
    bool isSelector() const { return mType == SELECTOR; }
Packit Service 7770af
    bool isCollection() const { return mType == COLLECTION; }
Packit Service 7770af
    bool isNil() const { return mType == NIL; }
Packit Service 7770af
    bool got_line_feed;
Packit Service 7770af
Packit Service 7770af
    Complex_Selector::Combinator combinator() const { return mCombinator; }
Packit Service 7770af
Packit Service 7770af
    Complex_Selector_Obj selector() { return mpSelector; }
Packit Service 7770af
    Complex_Selector_Obj selector() const { return mpSelector; }
Packit Service 7770af
Packit Service 7770af
    NodeDequePtr collection() { return mpCollection; }
Packit Service 7770af
    const NodeDequePtr collection() const { return mpCollection; }
Packit Service 7770af
Packit Service 7770af
    static Node createCombinator(const Complex_Selector::Combinator& combinator);
Packit Service 7770af
Packit Service 7770af
    // This method will klone the selector, stripping off the tail and combinator
Packit Service 7770af
    static Node createSelector(const Complex_Selector& pSelector);
Packit Service 7770af
Packit Service 7770af
    static Node createCollection();
Packit Service 7770af
    static Node createCollection(const NodeDeque& values);
Packit Service 7770af
Packit Service 7770af
    static Node createNil();
Packit Service 7770af
    static Node naiveTrim(Node& seqses);
Packit Service 7770af
Packit Service 7770af
    Node klone() const;
Packit Service 7770af
Packit Service 7770af
    bool operator==(const Node& rhs) const;
Packit Service 7770af
    inline bool operator!=(const Node& rhs) const { return !(*this == rhs); }
Packit Service 7770af
Packit Service 7770af
Packit Service 7770af
    /*
Packit Service 7770af
    COLLECTION FUNCTIONS
Packit Service 7770af
Packit Service 7770af
    Most types don't need any helper methods (nil and combinator due to their simplicity and
Packit Service 7770af
    selector due to the fact that we leverage the non-node selector code on the Complex_Selector
Packit Service 7770af
    whereever possible). The following methods are intended to be called on Node objects whose
Packit Service 7770af
    type is COLLECTION only.
Packit Service 7770af
    */
Packit Service 7770af
Packit Service 7770af
    // rhs and this must be node collections. Shallow copy the nodes from rhs to the end of this.
Packit Service 7770af
    // This function DOES NOT remove the nodes from rhs.
Packit Service 7770af
    void plus(Node& rhs);
Packit Service 7770af
Packit Service 7770af
    // potentialChild must be a node collection of selectors/combinators. this must be a collection
Packit Service 7770af
    // of collections of nodes/combinators. This method checks if potentialChild is a child of this
Packit Service 7770af
    // Node.
Packit Service 7770af
    bool contains(const Node& potentialChild) const;
Packit Service 7770af
Packit Service 7770af
  private:
Packit Service 7770af
    // Private constructor; Use the static methods (like createCombinator and createSelector)
Packit Service 7770af
    // to instantiate this object. This is more expressive, and it allows us to break apart each
Packit Service 7770af
    // case into separate functions.
Packit Service 7770af
    Node(const TYPE& type, Complex_Selector::Combinator combinator, Complex_Selector_Ptr pSelector, NodeDequePtr& pCollection);
Packit Service 7770af
Packit Service 7770af
    TYPE mType;
Packit Service 7770af
Packit Service 7770af
    // TODO: can we union these to save on memory?
Packit Service 7770af
    Complex_Selector::Combinator mCombinator;
Packit Service 7770af
    Complex_Selector_Obj mpSelector;
Packit Service 7770af
    NodeDequePtr mpCollection;
Packit Service 7770af
  };
Packit Service 7770af
Packit Service 7770af
#ifdef DEBUG
Packit Service 7770af
  std::ostream& operator<<(std::ostream& os, const Node& node);
Packit Service 7770af
#endif
Packit Service 7770af
  Node complexSelectorToNode(Complex_Selector_Ptr pToConvert);
Packit Service 7770af
  Complex_Selector_Ptr nodeToComplexSelector(const Node& toConvert);
Packit Service 7770af
Packit Service 7770af
}
Packit Service 7770af
Packit Service 7770af
#endif