13 #include "sass/base.h"
14 #include "ast_fwd_decl.hpp"
16 #ifdef DEBUG_SHARED_PTR
18 #define ATTACH_VIRTUAL_AST_OPERATIONS(klass) \
19 virtual klass##_Ptr copy(std::string, size_t) const = 0; \
20 virtual klass##_Ptr clone(std::string, size_t) const = 0; \
22 #define ATTACH_AST_OPERATIONS(klass) \
23 virtual klass##_Ptr copy(std::string, size_t) const; \
24 virtual klass##_Ptr clone(std::string, size_t) const; \
28 #define ATTACH_VIRTUAL_AST_OPERATIONS(klass) \
29 virtual klass##_Ptr copy() const = 0; \
30 virtual klass##_Ptr clone() const = 0; \
32 #define ATTACH_AST_OPERATIONS(klass) \
33 virtual klass##_Ptr copy() const; \
34 virtual klass##_Ptr clone() const; \
41 * There are some overloads used here that trigger the clang overload
42 * hiding warning. Specifically:
44 * Type type() which hides string type() from Expression
47 #pragma clang diagnostic push
48 #pragma clang diagnostic ignored "-Woverloaded-virtual"
54 #include "context.hpp"
55 #include "position.hpp"
56 #include "constants.hpp"
57 #include "operation.hpp"
58 #include "position.hpp"
59 #include "inspect.hpp"
60 #include "source_map.hpp"
61 #include "environment.hpp"
62 #include "error_handling.hpp"
63 #include "ast_def_macros.hpp"
64 #include "ast_fwd_decl.hpp"
65 #include "source_map.hpp"
71 // easier to search with name
72 const bool DELAYED = true;
74 // ToDo: should this really be hardcoded
75 // Note: most methods follow precision option
76 const double NUMBER_EPSILON = 0.00000000000001;
78 // ToDo: where does this fit best?
79 // We don't share this with C-API?
82 Operand(Sass_OP operand, bool ws_before = false, bool ws_after = false)
83 : operand(operand), ws_before(ws_before), ws_after(ws_after)
91 //////////////////////////////////////////////////////////
92 // `hash_combine` comes from boost (functional/hash):
93 // http://www.boost.org/doc/libs/1_35_0/doc/html/hash/combine.html
94 // Boost Software License - Version 1.0
95 // http://www.boost.org/users/license.html
97 void hash_combine (std::size_t& seed, const T& val)
99 seed ^= std::hash<T>()(val) + 0x9e3779b9
100 + (seed<<6) + (seed>>2);
102 //////////////////////////////////////////////////////////
104 //////////////////////////////////////////////////////////
105 // Abstract base class for all abstract syntax tree nodes.
106 //////////////////////////////////////////////////////////
107 class AST_Node : public SharedObj {
108 ADD_PROPERTY(ParserState, pstate)
110 AST_Node(ParserState pstate)
113 AST_Node(const AST_Node* ptr)
114 : pstate_(ptr->pstate_)
117 // AST_Node(AST_Node& ptr) = delete;
119 virtual ~AST_Node() = 0;
120 virtual size_t hash() { return 0; }
121 ATTACH_VIRTUAL_AST_OPERATIONS(AST_Node);
122 virtual std::string inspect() const { return to_string({ INSPECT, 5 }); }
123 virtual std::string to_sass() const { return to_string({ TO_SASS, 5 }); }
124 virtual const std::string to_string(Sass_Inspect_Options opt) const;
125 virtual const std::string to_string() const;
126 virtual void cloneChildren() {};
128 void update_pstate(const ParserState& pstate);
130 Offset off() { return pstate(); }
131 Position pos() { return pstate(); }
134 inline AST_Node::~AST_Node() { }
136 //////////////////////////////////////////////////////////////////////
137 // define cast template now (need complete type)
138 //////////////////////////////////////////////////////////////////////
141 T* Cast(AST_Node* ptr) {
142 return ptr && typeid(T) == typeid(*ptr) ?
143 static_cast<T*>(ptr) : NULL;
147 const T* Cast(const AST_Node* ptr) {
148 return ptr && typeid(T) == typeid(*ptr) ?
149 static_cast<const T*>(ptr) : NULL;
152 //////////////////////////////////////////////////////////////////////
153 // Abstract base class for expressions. This side of the AST hierarchy
154 // represents elements in value contexts, which exist primarily to be
155 // evaluated and returned.
156 //////////////////////////////////////////////////////////////////////
157 class Expression : public AST_Node {
181 // expressions in some contexts shouldn't be evaluated
182 ADD_PROPERTY(bool, is_delayed)
183 ADD_PROPERTY(bool, is_expanded)
184 ADD_PROPERTY(bool, is_interpolant)
185 ADD_PROPERTY(Concrete_Type, concrete_type)
187 Expression(ParserState pstate,
188 bool d = false, bool e = false, bool i = false, Concrete_Type ct = NONE)
195 Expression(const Expression* ptr)
197 is_delayed_(ptr->is_delayed_),
198 is_expanded_(ptr->is_expanded_),
199 is_interpolant_(ptr->is_interpolant_),
200 concrete_type_(ptr->concrete_type_)
202 virtual operator bool() { return true; }
203 virtual ~Expression() { }
204 virtual std::string type() const { return ""; /* TODO: raise an error? */ }
205 virtual bool is_invisible() const { return false; }
206 static std::string type_name() { return ""; }
207 virtual bool is_false() { return false; }
208 // virtual bool is_true() { return !is_false(); }
209 virtual bool operator== (const Expression& rhs) const { return false; }
210 virtual bool eq(const Expression& rhs) const { return *this == rhs; };
211 virtual void set_delayed(bool delayed) { is_delayed(delayed); }
212 virtual bool has_interpolant() const { return is_interpolant(); }
213 virtual bool is_left_interpolant() const { return is_interpolant(); }
214 virtual bool is_right_interpolant() const { return is_interpolant(); }
215 virtual std::string inspect() const { return to_string({ INSPECT, 5 }); }
216 virtual std::string to_sass() const { return to_string({ TO_SASS, 5 }); }
217 ATTACH_VIRTUAL_AST_OPERATIONS(Expression);
218 virtual size_t hash() { return 0; }
221 //////////////////////////////////////////////////////////////////////
222 // Still just an expression, but with a to_string method
223 //////////////////////////////////////////////////////////////////////
224 class PreValue : public Expression {
226 PreValue(ParserState pstate,
227 bool d = false, bool e = false, bool i = false, Concrete_Type ct = NONE)
228 : Expression(pstate, d, e, i, ct)
230 PreValue(const PreValue* ptr)
233 ATTACH_VIRTUAL_AST_OPERATIONS(PreValue);
234 virtual ~PreValue() { }
237 //////////////////////////////////////////////////////////////////////
238 // base class for values that support operations
239 //////////////////////////////////////////////////////////////////////
240 class Value : public Expression {
242 Value(ParserState pstate,
243 bool d = false, bool e = false, bool i = false, Concrete_Type ct = NONE)
244 : Expression(pstate, d, e, i, ct)
246 Value(const Value* ptr)
249 ATTACH_VIRTUAL_AST_OPERATIONS(Value);
250 virtual bool operator== (const Expression& rhs) const = 0;
254 /////////////////////////////////////////////////////////////////////////////////////
255 // Hash method specializations for std::unordered_map to work with Sass::Expression
256 /////////////////////////////////////////////////////////////////////////////////////
260 struct hash<Sass::Expression_Obj>
262 size_t operator()(Sass::Expression_Obj s) const
268 struct equal_to<Sass::Expression_Obj>
270 bool operator()( Sass::Expression_Obj lhs, Sass::Expression_Obj rhs) const
272 return lhs->hash() == rhs->hash();
279 /////////////////////////////////////////////////////////////////////////////
280 // Mixin class for AST nodes that should behave like vectors. Uses the
281 // "Template Method" design pattern to allow subclasses to adjust their flags
282 // when certain objects are pushed.
283 /////////////////////////////////////////////////////////////////////////////
284 template <typename T>
286 std::vector<T> elements_;
289 void reset_hash() { hash_ = 0; }
290 virtual void adjust_after_pushing(T element) { }
292 Vectorized(size_t s = 0) : elements_(std::vector<T>()), hash_(0)
293 { elements_.reserve(s); }
294 virtual ~Vectorized() = 0;
295 size_t length() const { return elements_.size(); }
296 bool empty() const { return elements_.empty(); }
297 void clear() { return elements_.clear(); }
298 T last() const { return elements_.back(); }
299 T first() const { return elements_.front(); }
300 T& operator[](size_t i) { return elements_[i]; }
301 virtual const T& at(size_t i) const { return elements_.at(i); }
302 virtual T& at(size_t i) { return elements_.at(i); }
303 const T& operator[](size_t i) const { return elements_[i]; }
304 virtual void append(T element)
308 elements_.push_back(element);
309 adjust_after_pushing(element);
312 virtual void concat(Vectorized* v)
314 for (size_t i = 0, L = v->length(); i < L; ++i) this->append((*v)[i]);
316 Vectorized& unshift(T element)
318 elements_.insert(elements_.begin(), element);
321 std::vector<T>& elements() { return elements_; }
322 const std::vector<T>& elements() const { return elements_; }
323 std::vector<T>& elements(std::vector<T>& e) { elements_ = e; return elements_; }
325 virtual size_t hash()
328 for (T& el : elements_) {
329 hash_combine(hash_, el->hash());
335 typename std::vector<T>::iterator end() { return elements_.end(); }
336 typename std::vector<T>::iterator begin() { return elements_.begin(); }
337 typename std::vector<T>::const_iterator end() const { return elements_.end(); }
338 typename std::vector<T>::const_iterator begin() const { return elements_.begin(); }
339 typename std::vector<T>::iterator erase(typename std::vector<T>::iterator el) { return elements_.erase(el); }
340 typename std::vector<T>::const_iterator erase(typename std::vector<T>::const_iterator el) { return elements_.erase(el); }
343 template <typename T>
344 inline Vectorized<T>::~Vectorized() { }
346 /////////////////////////////////////////////////////////////////////////////
347 // Mixin class for AST nodes that should behave like a hash table. Uses an
348 // extra <std::vector> internally to maintain insertion order for interation.
349 /////////////////////////////////////////////////////////////////////////////
352 ExpressionMap elements_;
353 std::vector<Expression_Obj> list_;
356 Expression_Obj duplicate_key_;
357 void reset_hash() { hash_ = 0; }
358 void reset_duplicate_key() { duplicate_key_ = 0; }
359 virtual void adjust_after_pushing(std::pair<Expression_Obj, Expression_Obj> p) { }
361 Hashed(size_t s = 0) : elements_(ExpressionMap(s)), list_(std::vector<Expression_Obj>())
362 { elements_.reserve(s); list_.reserve(s); reset_duplicate_key(); }
364 size_t length() const { return list_.size(); }
365 bool empty() const { return list_.empty(); }
366 bool has(Expression_Obj k) const { return elements_.count(k) == 1; }
367 Expression_Obj at(Expression_Obj k) const;
368 bool has_duplicate_key() const { return duplicate_key_ != 0; }
369 Expression_Obj get_duplicate_key() const { return duplicate_key_; }
370 const ExpressionMap elements() { return elements_; }
371 Hashed& operator<<(std::pair<Expression_Obj, Expression_Obj> p)
375 if (!has(p.first)) list_.push_back(p.first);
376 else if (!duplicate_key_) duplicate_key_ = p.first;
378 elements_[p.first] = p.second;
380 adjust_after_pushing(p);
383 Hashed& operator+=(Hashed* h)
386 this->elements_ = h->elements_;
387 this->list_ = h->list_;
391 for (auto key : h->keys()) {
392 *this << std::make_pair(key, h->at(key));
395 reset_duplicate_key();
398 const ExpressionMap& pairs() const { return elements_; }
399 const std::vector<Expression_Obj>& keys() const { return list_; }
401 // std::unordered_map<Expression_Obj, Expression_Obj>::iterator end() { return elements_.end(); }
402 // std::unordered_map<Expression_Obj, Expression_Obj>::iterator begin() { return elements_.begin(); }
403 // std::unordered_map<Expression_Obj, Expression_Obj>::const_iterator end() const { return elements_.end(); }
404 // std::unordered_map<Expression_Obj, Expression_Obj>::const_iterator begin() const { return elements_.begin(); }
407 inline Hashed::~Hashed() { }
410 /////////////////////////////////////////////////////////////////////////
411 // Abstract base class for statements. This side of the AST hierarchy
412 // represents elements in expansion contexts, which exist primarily to be
413 // rewritten and macro-expanded.
414 /////////////////////////////////////////////////////////////////////////
415 class Statement : public AST_Node {
417 enum Statement_Type {
443 ADD_PROPERTY(Statement_Type, statement_type)
444 ADD_PROPERTY(size_t, tabs)
445 ADD_PROPERTY(bool, group_end)
447 Statement(ParserState pstate, Statement_Type st = NONE, size_t t = 0)
448 : AST_Node(pstate), statement_type_(st), tabs_(t), group_end_(false)
450 Statement(const Statement* ptr)
452 statement_type_(ptr->statement_type_),
454 group_end_(ptr->group_end_)
456 virtual ~Statement() = 0;
457 // needed for rearranging nested rulesets during CSS emission
458 virtual bool is_invisible() const { return false; }
459 virtual bool bubbles() { return false; }
460 virtual bool has_content()
462 return statement_type_ == CONTENT;
465 inline Statement::~Statement() { }
467 ////////////////////////
468 // Blocks of statements.
469 ////////////////////////
470 class Block : public Statement, public Vectorized<Statement_Obj> {
471 ADD_PROPERTY(bool, is_root)
472 // needed for properly formatted CSS emission
474 void adjust_after_pushing(Statement_Obj s)
478 Block(ParserState pstate, size_t s = 0, bool r = false)
480 Vectorized<Statement_Obj>(s),
483 Block(const Block* ptr)
485 Vectorized<Statement_Obj>(*ptr),
486 is_root_(ptr->is_root_)
488 virtual bool has_content()
490 for (size_t i = 0, L = elements().size(); i < L; ++i) {
491 if (elements()[i]->has_content()) return true;
493 return Statement::has_content();
495 ATTACH_AST_OPERATIONS(Block)
499 ////////////////////////////////////////////////////////////////////////
500 // Abstract base class for statements that contain blocks of statements.
501 ////////////////////////////////////////////////////////////////////////
502 class Has_Block : public Statement {
503 ADD_PROPERTY(Block_Obj, block)
505 Has_Block(ParserState pstate, Block_Obj b)
506 : Statement(pstate), block_(b)
508 Has_Block(const Has_Block* ptr)
509 : Statement(ptr), block_(ptr->block_)
511 virtual bool has_content()
513 return (block_ && block_->has_content()) || Statement::has_content();
515 virtual ~Has_Block() = 0;
517 inline Has_Block::~Has_Block() { }
519 /////////////////////////////////////////////////////////////////////////////
520 // Rulesets (i.e., sets of styles headed by a selector and containing a block
521 // of style declarations.
522 /////////////////////////////////////////////////////////////////////////////
523 class Ruleset : public Has_Block {
524 ADD_PROPERTY(Selector_List_Obj, selector)
525 ADD_PROPERTY(bool, is_root);
527 Ruleset(ParserState pstate, Selector_List_Obj s = 0, Block_Obj b = 0)
528 : Has_Block(pstate, b), selector_(s), is_root_(false)
529 { statement_type(RULESET); }
530 Ruleset(const Ruleset* ptr)
532 selector_(ptr->selector_),
533 is_root_(ptr->is_root_)
534 { statement_type(RULESET); }
535 bool is_invisible() const;
536 ATTACH_AST_OPERATIONS(Ruleset)
543 class Bubble : public Statement {
544 ADD_PROPERTY(Statement_Obj, node)
545 ADD_PROPERTY(bool, group_end)
547 Bubble(ParserState pstate, Statement_Obj n, Statement_Obj g = 0, size_t t = 0)
548 : Statement(pstate, Statement::BUBBLE, t), node_(n), group_end_(g == 0)
550 Bubble(const Bubble* ptr)
553 group_end_(ptr->group_end_)
555 bool bubbles() { return true; }
556 ATTACH_AST_OPERATIONS(Bubble)
563 class Trace : public Has_Block {
564 ADD_CONSTREF(std::string, name)
566 Trace(ParserState pstate, std::string n, Block_Obj b = 0)
567 : Has_Block(pstate, b), name_(n)
569 Trace(const Trace* ptr)
573 ATTACH_AST_OPERATIONS(Trace)
580 class Media_Block : public Has_Block {
581 ADD_PROPERTY(List_Obj, media_queries)
583 Media_Block(ParserState pstate, List_Obj mqs, Block_Obj b)
584 : Has_Block(pstate, b), media_queries_(mqs)
585 { statement_type(MEDIA); }
586 Media_Block(const Media_Block* ptr)
587 : Has_Block(ptr), media_queries_(ptr->media_queries_)
588 { statement_type(MEDIA); }
589 bool bubbles() { return true; }
590 bool is_invisible() const;
591 ATTACH_AST_OPERATIONS(Media_Block)
595 ///////////////////////////////////////////////////////////////////////
596 // At-rules -- arbitrary directives beginning with "@" that may have an
597 // optional statement block.
598 ///////////////////////////////////////////////////////////////////////
599 class Directive : public Has_Block {
600 ADD_CONSTREF(std::string, keyword)
601 ADD_PROPERTY(Selector_List_Obj, selector)
602 ADD_PROPERTY(Expression_Obj, value)
604 Directive(ParserState pstate, std::string kwd, Selector_List_Obj sel = 0, Block_Obj b = 0, Expression_Obj val = 0)
605 : Has_Block(pstate, b), keyword_(kwd), selector_(sel), value_(val) // set value manually if needed
606 { statement_type(DIRECTIVE); }
607 Directive(const Directive* ptr)
609 keyword_(ptr->keyword_),
610 selector_(ptr->selector_),
611 value_(ptr->value_) // set value manually if needed
612 { statement_type(DIRECTIVE); }
613 bool bubbles() { return is_keyframes() || is_media(); }
615 return keyword_.compare("@-webkit-media") == 0 ||
616 keyword_.compare("@-moz-media") == 0 ||
617 keyword_.compare("@-o-media") == 0 ||
618 keyword_.compare("@media") == 0;
620 bool is_keyframes() {
621 return keyword_.compare("@-webkit-keyframes") == 0 ||
622 keyword_.compare("@-moz-keyframes") == 0 ||
623 keyword_.compare("@-o-keyframes") == 0 ||
624 keyword_.compare("@keyframes") == 0;
626 ATTACH_AST_OPERATIONS(Directive)
630 ///////////////////////////////////////////////////////////////////////
631 // Keyframe-rules -- the child blocks of "@keyframes" nodes.
632 ///////////////////////////////////////////////////////////////////////
633 class Keyframe_Rule : public Has_Block {
634 // according to css spec, this should be <keyframes-name>
635 // <keyframes-name> = <custom-ident> | <string>
636 ADD_PROPERTY(Selector_List_Obj, name)
638 Keyframe_Rule(ParserState pstate, Block_Obj b)
639 : Has_Block(pstate, b), name_()
640 { statement_type(KEYFRAMERULE); }
641 Keyframe_Rule(const Keyframe_Rule* ptr)
642 : Has_Block(ptr), name_(ptr->name_)
643 { statement_type(KEYFRAMERULE); }
644 ATTACH_AST_OPERATIONS(Keyframe_Rule)
648 ////////////////////////////////////////////////////////////////////////
649 // Declarations -- style rules consisting of a property name and values.
650 ////////////////////////////////////////////////////////////////////////
651 class Declaration : public Has_Block {
652 ADD_PROPERTY(String_Obj, property)
653 ADD_PROPERTY(Expression_Obj, value)
654 ADD_PROPERTY(bool, is_important)
655 ADD_PROPERTY(bool, is_indented)
657 Declaration(ParserState pstate,
658 String_Obj prop, Expression_Obj val, bool i = false, Block_Obj b = 0)
659 : Has_Block(pstate, b), property_(prop), value_(val), is_important_(i), is_indented_(false)
660 { statement_type(DECLARATION); }
661 Declaration(const Declaration* ptr)
663 property_(ptr->property_),
665 is_important_(ptr->is_important_),
666 is_indented_(ptr->is_indented_)
667 { statement_type(DECLARATION); }
668 ATTACH_AST_OPERATIONS(Declaration)
672 /////////////////////////////////////
673 // Assignments -- variable and value.
674 /////////////////////////////////////
675 class Assignment : public Statement {
676 ADD_CONSTREF(std::string, variable)
677 ADD_PROPERTY(Expression_Obj, value)
678 ADD_PROPERTY(bool, is_default)
679 ADD_PROPERTY(bool, is_global)
681 Assignment(ParserState pstate,
682 std::string var, Expression_Obj val,
683 bool is_default = false,
684 bool is_global = false)
685 : Statement(pstate), variable_(var), value_(val), is_default_(is_default), is_global_(is_global)
686 { statement_type(ASSIGNMENT); }
687 Assignment(const Assignment* ptr)
689 variable_(ptr->variable_),
691 is_default_(ptr->is_default_),
692 is_global_(ptr->is_global_)
693 { statement_type(ASSIGNMENT); }
694 ATTACH_AST_OPERATIONS(Assignment)
698 ////////////////////////////////////////////////////////////////////////////
699 // Import directives. CSS and Sass import lists can be intermingled, so it's
700 // necessary to store a list of each in an Import node.
701 ////////////////////////////////////////////////////////////////////////////
702 class Import : public Statement {
703 std::vector<Expression_Obj> urls_;
704 std::vector<Include> incs_;
705 ADD_PROPERTY(List_Obj, import_queries);
707 Import(ParserState pstate)
709 urls_(std::vector<Expression_Obj>()),
710 incs_(std::vector<Include>()),
712 { statement_type(IMPORT); }
713 Import(const Import* ptr)
717 import_queries_(ptr->import_queries_)
718 { statement_type(IMPORT); }
719 std::vector<Expression_Obj>& urls() { return urls_; }
720 std::vector<Include>& incs() { return incs_; }
721 ATTACH_AST_OPERATIONS(Import)
725 // not yet resolved single import
726 // so far we only know requested name
727 class Import_Stub : public Statement {
730 std::string abs_path() { return resource_.abs_path; };
731 std::string imp_path() { return resource_.imp_path; };
732 Include resource() { return resource_; };
734 Import_Stub(ParserState pstate, Include res)
735 : Statement(pstate), resource_(res)
736 { statement_type(IMPORT_STUB); }
737 Import_Stub(const Import_Stub* ptr)
738 : Statement(ptr), resource_(ptr->resource_)
739 { statement_type(IMPORT_STUB); }
740 ATTACH_AST_OPERATIONS(Import_Stub)
744 //////////////////////////////
745 // The Sass `@warn` directive.
746 //////////////////////////////
747 class Warning : public Statement {
748 ADD_PROPERTY(Expression_Obj, message)
750 Warning(ParserState pstate, Expression_Obj msg)
751 : Statement(pstate), message_(msg)
752 { statement_type(WARNING); }
753 Warning(const Warning* ptr)
754 : Statement(ptr), message_(ptr->message_)
755 { statement_type(WARNING); }
756 ATTACH_AST_OPERATIONS(Warning)
760 ///////////////////////////////
761 // The Sass `@error` directive.
762 ///////////////////////////////
763 class Error : public Statement {
764 ADD_PROPERTY(Expression_Obj, message)
766 Error(ParserState pstate, Expression_Obj msg)
767 : Statement(pstate), message_(msg)
768 { statement_type(ERROR); }
769 Error(const Error* ptr)
770 : Statement(ptr), message_(ptr->message_)
771 { statement_type(ERROR); }
772 ATTACH_AST_OPERATIONS(Error)
776 ///////////////////////////////
777 // The Sass `@debug` directive.
778 ///////////////////////////////
779 class Debug : public Statement {
780 ADD_PROPERTY(Expression_Obj, value)
782 Debug(ParserState pstate, Expression_Obj val)
783 : Statement(pstate), value_(val)
784 { statement_type(DEBUGSTMT); }
785 Debug(const Debug* ptr)
786 : Statement(ptr), value_(ptr->value_)
787 { statement_type(DEBUGSTMT); }
788 ATTACH_AST_OPERATIONS(Debug)
792 ///////////////////////////////////////////
793 // CSS comments. These may be interpolated.
794 ///////////////////////////////////////////
795 class Comment : public Statement {
796 ADD_PROPERTY(String_Obj, text)
797 ADD_PROPERTY(bool, is_important)
799 Comment(ParserState pstate, String_Obj txt, bool is_important)
800 : Statement(pstate), text_(txt), is_important_(is_important)
801 { statement_type(COMMENT); }
802 Comment(const Comment* ptr)
805 is_important_(ptr->is_important_)
806 { statement_type(COMMENT); }
807 virtual bool is_invisible() const
808 { return /* is_important() == */ false; }
809 ATTACH_AST_OPERATIONS(Comment)
813 ////////////////////////////////////
814 // The Sass `@if` control directive.
815 ////////////////////////////////////
816 class If : public Has_Block {
817 ADD_PROPERTY(Expression_Obj, predicate)
818 ADD_PROPERTY(Block_Obj, alternative)
820 If(ParserState pstate, Expression_Obj pred, Block_Obj con, Block_Obj alt = 0)
821 : Has_Block(pstate, con), predicate_(pred), alternative_(alt)
822 { statement_type(IF); }
825 predicate_(ptr->predicate_),
826 alternative_(ptr->alternative_)
827 { statement_type(IF); }
828 virtual bool has_content()
830 return Has_Block::has_content() || (alternative_ && alternative_->has_content());
832 ATTACH_AST_OPERATIONS(If)
836 /////////////////////////////////////
837 // The Sass `@for` control directive.
838 /////////////////////////////////////
839 class For : public Has_Block {
840 ADD_CONSTREF(std::string, variable)
841 ADD_PROPERTY(Expression_Obj, lower_bound)
842 ADD_PROPERTY(Expression_Obj, upper_bound)
843 ADD_PROPERTY(bool, is_inclusive)
845 For(ParserState pstate,
846 std::string var, Expression_Obj lo, Expression_Obj hi, Block_Obj b, bool inc)
847 : Has_Block(pstate, b),
848 variable_(var), lower_bound_(lo), upper_bound_(hi), is_inclusive_(inc)
849 { statement_type(FOR); }
852 variable_(ptr->variable_),
853 lower_bound_(ptr->lower_bound_),
854 upper_bound_(ptr->upper_bound_),
855 is_inclusive_(ptr->is_inclusive_)
856 { statement_type(FOR); }
857 ATTACH_AST_OPERATIONS(For)
861 //////////////////////////////////////
862 // The Sass `@each` control directive.
863 //////////////////////////////////////
864 class Each : public Has_Block {
865 ADD_PROPERTY(std::vector<std::string>, variables)
866 ADD_PROPERTY(Expression_Obj, list)
868 Each(ParserState pstate, std::vector<std::string> vars, Expression_Obj lst, Block_Obj b)
869 : Has_Block(pstate, b), variables_(vars), list_(lst)
870 { statement_type(EACH); }
871 Each(const Each* ptr)
872 : Has_Block(ptr), variables_(ptr->variables_), list_(ptr->list_)
873 { statement_type(EACH); }
874 ATTACH_AST_OPERATIONS(Each)
878 ///////////////////////////////////////
879 // The Sass `@while` control directive.
880 ///////////////////////////////////////
881 class While : public Has_Block {
882 ADD_PROPERTY(Expression_Obj, predicate)
884 While(ParserState pstate, Expression_Obj pred, Block_Obj b)
885 : Has_Block(pstate, b), predicate_(pred)
886 { statement_type(WHILE); }
887 While(const While* ptr)
888 : Has_Block(ptr), predicate_(ptr->predicate_)
889 { statement_type(WHILE); }
890 ATTACH_AST_OPERATIONS(While)
894 /////////////////////////////////////////////////////////////
895 // The @return directive for use inside SassScript functions.
896 /////////////////////////////////////////////////////////////
897 class Return : public Statement {
898 ADD_PROPERTY(Expression_Obj, value)
900 Return(ParserState pstate, Expression_Obj val)
901 : Statement(pstate), value_(val)
902 { statement_type(RETURN); }
903 Return(const Return* ptr)
904 : Statement(ptr), value_(ptr->value_)
905 { statement_type(RETURN); }
906 ATTACH_AST_OPERATIONS(Return)
910 ////////////////////////////////
911 // The Sass `@extend` directive.
912 ////////////////////////////////
913 class Extension : public Statement {
914 ADD_PROPERTY(Selector_List_Obj, selector)
916 Extension(ParserState pstate, Selector_List_Obj s)
917 : Statement(pstate), selector_(s)
918 { statement_type(EXTEND); }
919 Extension(const Extension* ptr)
920 : Statement(ptr), selector_(ptr->selector_)
921 { statement_type(EXTEND); }
922 ATTACH_AST_OPERATIONS(Extension)
926 /////////////////////////////////////////////////////////////////////////////
927 // Definitions for both mixins and functions. The two cases are distinguished
929 /////////////////////////////////////////////////////////////////////////////
931 typedef const char* Signature;
932 typedef Expression_Ptr (*Native_Function)(Env&, Env&, Context&, Signature, ParserState, Backtrace*, std::vector<Selector_List_Obj>);
933 class Definition : public Has_Block {
935 enum Type { MIXIN, FUNCTION };
936 ADD_CONSTREF(std::string, name)
937 ADD_PROPERTY(Parameters_Obj, parameters)
938 ADD_PROPERTY(Env*, environment)
939 ADD_PROPERTY(Type, type)
940 ADD_PROPERTY(Native_Function, native_function)
941 ADD_PROPERTY(Sass_Function_Entry, c_function)
942 ADD_PROPERTY(void*, cookie)
943 ADD_PROPERTY(bool, is_overload_stub)
944 ADD_PROPERTY(Signature, signature)
946 Definition(const Definition* ptr)
949 parameters_(ptr->parameters_),
950 environment_(ptr->environment_),
952 native_function_(ptr->native_function_),
953 c_function_(ptr->c_function_),
954 cookie_(ptr->cookie_),
955 is_overload_stub_(ptr->is_overload_stub_),
956 signature_(ptr->signature_)
959 Definition(ParserState pstate,
961 Parameters_Obj params,
964 : Has_Block(pstate, b),
972 is_overload_stub_(false),
975 Definition(ParserState pstate,
978 Parameters_Obj params,
979 Native_Function func_ptr,
980 bool overload_stub = false)
981 : Has_Block(pstate, 0),
986 native_function_(func_ptr),
989 is_overload_stub_(overload_stub),
992 Definition(ParserState pstate,
995 Parameters_Obj params,
996 Sass_Function_Entry c_func,
999 : Has_Block(pstate, 0),
1001 parameters_(params),
1004 native_function_(0),
1005 c_function_(c_func),
1006 cookie_(sass_function_get_cookie(c_func)),
1007 is_overload_stub_(false),
1010 ATTACH_AST_OPERATIONS(Definition)
1014 //////////////////////////////////////
1015 // Mixin calls (i.e., `@include ...`).
1016 //////////////////////////////////////
1017 class Mixin_Call : public Has_Block {
1018 ADD_CONSTREF(std::string, name)
1019 ADD_PROPERTY(Arguments_Obj, arguments)
1021 Mixin_Call(ParserState pstate, std::string n, Arguments_Obj args, Block_Obj b = 0)
1022 : Has_Block(pstate, b), name_(n), arguments_(args)
1024 Mixin_Call(const Mixin_Call* ptr)
1027 arguments_(ptr->arguments_)
1029 ATTACH_AST_OPERATIONS(Mixin_Call)
1033 ///////////////////////////////////////////////////
1034 // The @content directive for mixin content blocks.
1035 ///////////////////////////////////////////////////
1036 class Content : public Statement {
1037 ADD_PROPERTY(Media_Block_Ptr, media_block)
1039 Content(ParserState pstate) : Statement(pstate)
1040 { statement_type(CONTENT); }
1041 Content(const Content* ptr) : Statement(ptr)
1042 { statement_type(CONTENT); }
1043 ATTACH_AST_OPERATIONS(Content)
1047 ///////////////////////////////////////////////////////////////////////
1048 // Lists of values, both comma- and space-separated (distinguished by a
1049 // type-tag.) Also used to represent variable-length argument lists.
1050 ///////////////////////////////////////////////////////////////////////
1051 class List : public Value, public Vectorized<Expression_Obj> {
1052 void adjust_after_pushing(Expression_Obj e) { is_expanded(false); }
1054 ADD_PROPERTY(enum Sass_Separator, separator)
1055 ADD_PROPERTY(bool, is_arglist)
1056 ADD_PROPERTY(bool, is_bracketed)
1057 ADD_PROPERTY(bool, from_selector)
1059 List(ParserState pstate,
1060 size_t size = 0, enum Sass_Separator sep = SASS_SPACE, bool argl = false, bool bracket = false)
1062 Vectorized<Expression_Obj>(size),
1065 is_bracketed_(bracket),
1066 from_selector_(false)
1067 { concrete_type(LIST); }
1068 List(const List* ptr)
1070 Vectorized<Expression_Obj>(*ptr),
1071 separator_(ptr->separator_),
1072 is_arglist_(ptr->is_arglist_),
1073 is_bracketed_(ptr->is_bracketed_),
1074 from_selector_(ptr->from_selector_)
1075 { concrete_type(LIST); }
1076 std::string type() const { return is_arglist_ ? "arglist" : "list"; }
1077 static std::string type_name() { return "list"; }
1078 const char* sep_string(bool compressed = false) const {
1079 return separator() == SASS_SPACE ?
1080 " " : (compressed ? "," : ", ");
1082 bool is_invisible() const { return empty() && !is_bracketed(); }
1083 Expression_Obj value_at_index(size_t i);
1085 virtual size_t size() const;
1087 virtual size_t hash()
1090 hash_ = std::hash<std::string>()(sep_string());
1091 hash_combine(hash_, std::hash<bool>()(is_bracketed()));
1092 for (size_t i = 0, L = length(); i < L; ++i)
1093 hash_combine(hash_, (elements()[i])->hash());
1098 virtual void set_delayed(bool delayed)
1100 is_delayed(delayed);
1101 // don't set children
1104 virtual bool operator== (const Expression& rhs) const;
1106 ATTACH_AST_OPERATIONS(List)
1110 ///////////////////////////////////////////////////////////////////////
1112 ///////////////////////////////////////////////////////////////////////
1113 class Map : public Value, public Hashed {
1114 void adjust_after_pushing(std::pair<Expression_Obj, Expression_Obj> p) { is_expanded(false); }
1116 Map(ParserState pstate,
1120 { concrete_type(MAP); }
1124 { concrete_type(MAP); }
1125 std::string type() const { return "map"; }
1126 static std::string type_name() { return "map"; }
1127 bool is_invisible() const { return empty(); }
1128 List_Obj to_list(Context& ctx, ParserState& pstate);
1130 virtual size_t hash()
1133 for (auto key : keys()) {
1134 hash_combine(hash_, key->hash());
1135 hash_combine(hash_, at(key)->hash());
1142 virtual bool operator== (const Expression& rhs) const;
1144 ATTACH_AST_OPERATIONS(Map)
1148 inline static const std::string sass_op_to_name(enum Sass_OP op) {
1150 case AND: return "and"; break;
1151 case OR: return "or"; break;
1152 case EQ: return "eq"; break;
1153 case NEQ: return "neq"; break;
1154 case GT: return "gt"; break;
1155 case GTE: return "gte"; break;
1156 case LT: return "lt"; break;
1157 case LTE: return "lte"; break;
1158 case ADD: return "plus"; break;
1159 case SUB: return "sub"; break;
1160 case MUL: return "times"; break;
1161 case DIV: return "div"; break;
1162 case MOD: return "mod"; break;
1163 // this is only used internally!
1164 case NUM_OPS: return "[OPS]"; break;
1165 default: return "invalid"; break;
1169 //////////////////////////////////////////////////////////////////////////
1170 // Binary expressions. Represents logical, relational, and arithmetic
1171 // operations. Templatized to avoid large switch statements and repetitive
1173 //////////////////////////////////////////////////////////////////////////
1174 class Binary_Expression : public PreValue {
1176 HASH_PROPERTY(Operand, op)
1177 HASH_PROPERTY(Expression_Obj, left)
1178 HASH_PROPERTY(Expression_Obj, right)
1181 Binary_Expression(ParserState pstate,
1182 Operand op, Expression_Obj lhs, Expression_Obj rhs)
1183 : PreValue(pstate), op_(op), left_(lhs), right_(rhs), hash_(0)
1185 Binary_Expression(const Binary_Expression* ptr)
1189 right_(ptr->right_),
1192 const std::string type_name() {
1194 case AND: return "and"; break;
1195 case OR: return "or"; break;
1196 case EQ: return "eq"; break;
1197 case NEQ: return "neq"; break;
1198 case GT: return "gt"; break;
1199 case GTE: return "gte"; break;
1200 case LT: return "lt"; break;
1201 case LTE: return "lte"; break;
1202 case ADD: return "add"; break;
1203 case SUB: return "sub"; break;
1204 case MUL: return "mul"; break;
1205 case DIV: return "div"; break;
1206 case MOD: return "mod"; break;
1207 // this is only used internally!
1208 case NUM_OPS: return "[OPS]"; break;
1209 default: return "invalid"; break;
1212 const std::string separator() {
1214 case AND: return "&&"; break;
1215 case OR: return "||"; break;
1216 case EQ: return "=="; break;
1217 case NEQ: return "!="; break;
1218 case GT: return ">"; break;
1219 case GTE: return ">="; break;
1220 case LT: return "<"; break;
1221 case LTE: return "<="; break;
1222 case ADD: return "+"; break;
1223 case SUB: return "-"; break;
1224 case MUL: return "*"; break;
1225 case DIV: return "/"; break;
1226 case MOD: return "%"; break;
1227 // this is only used internally!
1228 case NUM_OPS: return "[OPS]"; break;
1229 default: return "invalid"; break;
1232 bool is_left_interpolant(void) const;
1233 bool is_right_interpolant(void) const;
1234 bool has_interpolant() const
1236 return is_left_interpolant() ||
1237 is_right_interpolant();
1239 virtual void set_delayed(bool delayed)
1241 right()->set_delayed(delayed);
1242 left()->set_delayed(delayed);
1243 is_delayed(delayed);
1245 virtual bool operator==(const Expression& rhs) const
1249 Binary_Expression_Ptr_Const m = Cast<Binary_Expression>(&rhs);
1250 if (m == 0) return false;
1251 return type() == m->type() &&
1252 *left() == *m->left() &&
1253 *right() == *m->right();
1255 catch (std::bad_cast&)
1259 catch (...) { throw; }
1261 virtual size_t hash()
1264 hash_ = std::hash<size_t>()(optype());
1265 hash_combine(hash_, left()->hash());
1266 hash_combine(hash_, right()->hash());
1270 enum Sass_OP optype() const { return op_.operand; }
1271 ATTACH_AST_OPERATIONS(Binary_Expression)
1275 ////////////////////////////////////////////////////////////////////////////
1276 // Arithmetic negation (logical negation is just an ordinary function call).
1277 ////////////////////////////////////////////////////////////////////////////
1278 class Unary_Expression : public Expression {
1280 enum Type { PLUS, MINUS, NOT };
1282 HASH_PROPERTY(Type, optype)
1283 HASH_PROPERTY(Expression_Obj, operand)
1286 Unary_Expression(ParserState pstate, Type t, Expression_Obj o)
1287 : Expression(pstate), optype_(t), operand_(o), hash_(0)
1289 Unary_Expression(const Unary_Expression* ptr)
1291 optype_(ptr->optype_),
1292 operand_(ptr->operand_),
1295 const std::string type_name() {
1297 case PLUS: return "plus"; break;
1298 case MINUS: return "minus"; break;
1299 case NOT: return "not"; break;
1300 default: return "invalid"; break;
1303 virtual bool operator==(const Expression& rhs) const
1307 Unary_Expression_Ptr_Const m = Cast<Unary_Expression>(&rhs);
1308 if (m == 0) return false;
1309 return type() == m->type() &&
1310 *operand() == *m->operand();
1312 catch (std::bad_cast&)
1316 catch (...) { throw; }
1318 virtual size_t hash()
1321 hash_ = std::hash<size_t>()(optype_);
1322 hash_combine(hash_, operand()->hash());
1326 ATTACH_AST_OPERATIONS(Unary_Expression)
1330 ////////////////////////////////////////////////////////////
1331 // Individual argument objects for mixin and function calls.
1332 ////////////////////////////////////////////////////////////
1333 class Argument : public Expression {
1334 HASH_PROPERTY(Expression_Obj, value)
1335 HASH_CONSTREF(std::string, name)
1336 ADD_PROPERTY(bool, is_rest_argument)
1337 ADD_PROPERTY(bool, is_keyword_argument)
1340 Argument(ParserState pstate, Expression_Obj val, std::string n = "", bool rest = false, bool keyword = false)
1341 : Expression(pstate), value_(val), name_(n), is_rest_argument_(rest), is_keyword_argument_(keyword), hash_(0)
1343 if (!name_.empty() && is_rest_argument_) {
1344 error("variable-length argument may not be passed by name", pstate_);
1347 Argument(const Argument* ptr)
1349 value_(ptr->value_),
1351 is_rest_argument_(ptr->is_rest_argument_),
1352 is_keyword_argument_(ptr->is_keyword_argument_),
1355 if (!name_.empty() && is_rest_argument_) {
1356 error("variable-length argument may not be passed by name", pstate_);
1360 virtual void set_delayed(bool delayed);
1361 virtual bool operator==(const Expression& rhs) const
1365 Argument_Ptr_Const m = Cast<Argument>(&rhs);
1366 if (!(m && name() == m->name())) return false;
1367 return *value() == *m->value();
1369 catch (std::bad_cast&)
1373 catch (...) { throw; }
1376 virtual size_t hash()
1379 hash_ = std::hash<std::string>()(name());
1380 hash_combine(hash_, value()->hash());
1385 ATTACH_AST_OPERATIONS(Argument)
1389 ////////////////////////////////////////////////////////////////////////
1390 // Argument lists -- in their own class to facilitate context-sensitive
1391 // error checking (e.g., ensuring that all ordinal arguments precede all
1392 // named arguments).
1393 ////////////////////////////////////////////////////////////////////////
1394 class Arguments : public Expression, public Vectorized<Argument_Obj> {
1395 ADD_PROPERTY(bool, has_named_arguments)
1396 ADD_PROPERTY(bool, has_rest_argument)
1397 ADD_PROPERTY(bool, has_keyword_argument)
1399 void adjust_after_pushing(Argument_Obj a);
1401 Arguments(ParserState pstate)
1402 : Expression(pstate),
1403 Vectorized<Argument_Obj>(),
1404 has_named_arguments_(false),
1405 has_rest_argument_(false),
1406 has_keyword_argument_(false)
1408 Arguments(const Arguments* ptr)
1410 Vectorized<Argument_Obj>(*ptr),
1411 has_named_arguments_(ptr->has_named_arguments_),
1412 has_rest_argument_(ptr->has_rest_argument_),
1413 has_keyword_argument_(ptr->has_keyword_argument_)
1416 virtual void set_delayed(bool delayed);
1418 Argument_Obj get_rest_argument();
1419 Argument_Obj get_keyword_argument();
1421 ATTACH_AST_OPERATIONS(Arguments)
1428 class Function_Call : public PreValue {
1429 HASH_CONSTREF(std::string, name)
1430 HASH_PROPERTY(Arguments_Obj, arguments)
1431 ADD_PROPERTY(bool, via_call)
1432 ADD_PROPERTY(void*, cookie)
1435 Function_Call(ParserState pstate, std::string n, Arguments_Obj args, void* cookie)
1436 : PreValue(pstate), name_(n), arguments_(args), via_call_(false), cookie_(cookie), hash_(0)
1437 { concrete_type(FUNCTION); }
1438 Function_Call(ParserState pstate, std::string n, Arguments_Obj args)
1439 : PreValue(pstate), name_(n), arguments_(args), via_call_(false), cookie_(0), hash_(0)
1440 { concrete_type(FUNCTION); }
1441 Function_Call(const Function_Call* ptr)
1444 arguments_(ptr->arguments_),
1445 via_call_(ptr->via_call_),
1446 cookie_(ptr->cookie_),
1448 { concrete_type(FUNCTION); }
1450 virtual bool operator==(const Expression& rhs) const
1454 Function_Call_Ptr_Const m = Cast<Function_Call>(&rhs);
1455 if (!(m && name() == m->name())) return false;
1456 if (!(m && arguments()->length() == m->arguments()->length())) return false;
1457 for (size_t i =0, L = arguments()->length(); i < L; ++i)
1458 if (!(*(*arguments())[i] == *(*m->arguments())[i])) return false;
1461 catch (std::bad_cast&)
1465 catch (...) { throw; }
1468 virtual size_t hash()
1471 hash_ = std::hash<std::string>()(name());
1472 for (auto argument : arguments()->elements())
1473 hash_combine(hash_, argument->hash());
1477 ATTACH_AST_OPERATIONS(Function_Call)
1481 /////////////////////////
1482 // Function call schemas.
1483 /////////////////////////
1484 class Function_Call_Schema : public Expression {
1485 ADD_PROPERTY(String_Obj, name)
1486 ADD_PROPERTY(Arguments_Obj, arguments)
1488 Function_Call_Schema(ParserState pstate, String_Obj n, Arguments_Obj args)
1489 : Expression(pstate), name_(n), arguments_(args)
1490 { concrete_type(STRING); }
1491 Function_Call_Schema(const Function_Call_Schema* ptr)
1494 arguments_(ptr->arguments_)
1495 { concrete_type(STRING); }
1496 ATTACH_AST_OPERATIONS(Function_Call_Schema)
1500 ///////////////////////
1501 // Variable references.
1502 ///////////////////////
1503 class Variable : public PreValue {
1504 ADD_CONSTREF(std::string, name)
1506 Variable(ParserState pstate, std::string n)
1507 : PreValue(pstate), name_(n)
1509 Variable(const Variable* ptr)
1510 : PreValue(ptr), name_(ptr->name_)
1513 virtual bool operator==(const Expression& rhs) const
1517 Variable_Ptr_Const e = Cast<Variable>(&rhs);
1518 return e && name() == e->name();
1520 catch (std::bad_cast&)
1524 catch (...) { throw; }
1527 virtual size_t hash()
1529 return std::hash<std::string>()(name());
1532 ATTACH_AST_OPERATIONS(Variable)
1536 ////////////////////////////////////////////////////////////////////////////
1537 // Textual (i.e., unevaluated) numeric data. Variants are distinguished with
1539 ////////////////////////////////////////////////////////////////////////////
1540 class Textual : public Expression {
1542 enum Type { NUMBER, PERCENTAGE, DIMENSION, HEX };
1544 HASH_PROPERTY(Type, valtype)
1545 HASH_CONSTREF(std::string, value)
1548 Textual(ParserState pstate, Type t, std::string val)
1549 : Expression(pstate, DELAYED), valtype_(t), value_(val),
1552 Textual(const Textual* ptr)
1554 valtype_(ptr->valtype_),
1555 value_(ptr->value_),
1559 virtual bool operator==(const Expression& rhs) const
1563 Textual_Ptr_Const e = Cast<Textual>(&rhs);
1564 return e && value() == e->value() && type() == e->type();
1566 catch (std::bad_cast&)
1570 catch (...) { throw; }
1573 virtual size_t hash()
1576 hash_ = std::hash<std::string>()(value_);
1577 hash_combine(hash_, std::hash<int>()(valtype_));
1582 ATTACH_AST_OPERATIONS(Textual)
1586 ////////////////////////////////////////////////
1587 // Numbers, percentages, dimensions, and colors.
1588 ////////////////////////////////////////////////
1589 class Number : public Value {
1590 HASH_PROPERTY(double, value)
1591 ADD_PROPERTY(bool, zero)
1592 std::vector<std::string> numerator_units_;
1593 std::vector<std::string> denominator_units_;
1596 Number(ParserState pstate, double val, std::string u = "", bool zero = true);
1598 Number(const Number* ptr)
1600 value_(ptr->value_), zero_(ptr->zero_),
1601 numerator_units_(ptr->numerator_units_),
1602 denominator_units_(ptr->denominator_units_),
1604 { concrete_type(NUMBER); }
1606 bool zero() { return zero_; }
1607 bool is_valid_css_unit() const;
1608 std::vector<std::string>& numerator_units() { return numerator_units_; }
1609 std::vector<std::string>& denominator_units() { return denominator_units_; }
1610 const std::vector<std::string>& numerator_units() const { return numerator_units_; }
1611 const std::vector<std::string>& denominator_units() const { return denominator_units_; }
1612 std::string type() const { return "number"; }
1613 static std::string type_name() { return "number"; }
1614 std::string unit() const;
1616 bool is_unitless() const;
1617 double convert_factor(const Number&) const;
1618 bool convert(const std::string& unit = "", bool strict = false);
1619 void normalize(const std::string& unit = "", bool strict = false);
1620 // useful for making one number compatible with another
1621 std::string find_convertible_unit() const;
1623 virtual size_t hash()
1626 hash_ = std::hash<double>()(value_);
1627 for (const auto numerator : numerator_units())
1628 hash_combine(hash_, std::hash<std::string>()(numerator));
1629 for (const auto denominator : denominator_units())
1630 hash_combine(hash_, std::hash<std::string>()(denominator));
1635 virtual bool operator< (const Number& rhs) const;
1636 virtual bool operator== (const Expression& rhs) const;
1637 ATTACH_AST_OPERATIONS(Number)
1644 class Color : public Value {
1645 HASH_PROPERTY(double, r)
1646 HASH_PROPERTY(double, g)
1647 HASH_PROPERTY(double, b)
1648 HASH_PROPERTY(double, a)
1649 ADD_CONSTREF(std::string, disp)
1652 Color(ParserState pstate, double r, double g, double b, double a = 1, const std::string disp = "")
1653 : Value(pstate), r_(r), g_(g), b_(b), a_(a), disp_(disp),
1655 { concrete_type(COLOR); }
1656 Color(const Color* ptr)
1664 { concrete_type(COLOR); }
1665 std::string type() const { return "color"; }
1666 static std::string type_name() { return "color"; }
1668 virtual size_t hash()
1671 hash_ = std::hash<double>()(a_);
1672 hash_combine(hash_, std::hash<double>()(r_));
1673 hash_combine(hash_, std::hash<double>()(g_));
1674 hash_combine(hash_, std::hash<double>()(b_));
1679 virtual bool operator== (const Expression& rhs) const;
1681 ATTACH_AST_OPERATIONS(Color)
1685 //////////////////////////////
1686 // Errors from Sass_Values.
1687 //////////////////////////////
1688 class Custom_Error : public Value {
1689 ADD_CONSTREF(std::string, message)
1691 Custom_Error(ParserState pstate, std::string msg)
1692 : Value(pstate), message_(msg)
1693 { concrete_type(C_ERROR); }
1694 Custom_Error(const Custom_Error* ptr)
1695 : Value(ptr), message_(ptr->message_)
1696 { concrete_type(C_ERROR); }
1697 virtual bool operator== (const Expression& rhs) const;
1698 ATTACH_AST_OPERATIONS(Custom_Error)
1702 //////////////////////////////
1703 // Warnings from Sass_Values.
1704 //////////////////////////////
1705 class Custom_Warning : public Value {
1706 ADD_CONSTREF(std::string, message)
1708 Custom_Warning(ParserState pstate, std::string msg)
1709 : Value(pstate), message_(msg)
1710 { concrete_type(C_WARNING); }
1711 Custom_Warning(const Custom_Warning* ptr)
1712 : Value(ptr), message_(ptr->message_)
1713 { concrete_type(C_WARNING); }
1714 virtual bool operator== (const Expression& rhs) const;
1715 ATTACH_AST_OPERATIONS(Custom_Warning)
1722 class Boolean : public Value {
1723 HASH_PROPERTY(bool, value)
1726 Boolean(ParserState pstate, bool val)
1727 : Value(pstate), value_(val),
1729 { concrete_type(BOOLEAN); }
1730 Boolean(const Boolean* ptr)
1732 value_(ptr->value_),
1734 { concrete_type(BOOLEAN); }
1735 virtual operator bool() { return value_; }
1736 std::string type() const { return "bool"; }
1737 static std::string type_name() { return "bool"; }
1738 virtual bool is_false() { return !value_; }
1740 virtual size_t hash()
1743 hash_ = std::hash<bool>()(value_);
1748 virtual bool operator== (const Expression& rhs) const;
1750 ATTACH_AST_OPERATIONS(Boolean)
1754 ////////////////////////////////////////////////////////////////////////
1755 // Abstract base class for Sass string values. Includes interpolated and
1757 ////////////////////////////////////////////////////////////////////////
1758 class String : public Value {
1760 String(ParserState pstate, bool delayed = false)
1761 : Value(pstate, delayed)
1762 { concrete_type(STRING); }
1763 String(const String* ptr)
1765 { concrete_type(STRING); }
1766 static std::string type_name() { return "string"; }
1767 virtual ~String() = 0;
1768 virtual void rtrim() = 0;
1769 virtual bool operator==(const Expression& rhs) const = 0;
1770 virtual bool operator<(const Expression& rhs) const {
1771 return this->to_string() < rhs.to_string();
1773 ATTACH_VIRTUAL_AST_OPERATIONS(String);
1776 inline String::~String() { };
1778 ///////////////////////////////////////////////////////////////////////
1779 // Interpolated strings. Meant to be reduced to flat strings during the
1780 // evaluation phase.
1781 ///////////////////////////////////////////////////////////////////////
1782 class String_Schema : public String, public Vectorized<Expression_Obj> {
1783 // ADD_PROPERTY(bool, has_interpolants)
1786 String_Schema(ParserState pstate, size_t size = 0, bool has_interpolants = false)
1787 : String(pstate), Vectorized<Expression_Obj>(size), hash_(0)
1788 { concrete_type(STRING); }
1789 String_Schema(const String_Schema* ptr)
1791 Vectorized<Expression_Obj>(*ptr),
1793 { concrete_type(STRING); }
1795 std::string type() const { return "string"; }
1796 static std::string type_name() { return "string"; }
1798 bool is_left_interpolant(void) const;
1799 bool is_right_interpolant(void) const;
1800 // void has_interpolants(bool tc) { }
1801 bool has_interpolants() {
1802 for (auto el : elements()) {
1803 if (el->is_interpolant()) return true;
1807 virtual void rtrim();
1809 virtual size_t hash()
1812 for (auto string : elements())
1813 hash_combine(hash_, string->hash());
1818 virtual void set_delayed(bool delayed) {
1819 is_delayed(delayed);
1822 virtual bool operator==(const Expression& rhs) const;
1823 ATTACH_AST_OPERATIONS(String_Schema)
1827 ////////////////////////////////////////////////////////
1828 // Flat strings -- the lowest level of raw textual data.
1829 ////////////////////////////////////////////////////////
1830 class String_Constant : public String {
1831 ADD_PROPERTY(char, quote_mark)
1832 ADD_PROPERTY(bool, can_compress_whitespace)
1833 HASH_CONSTREF(std::string, value)
1837 String_Constant(const String_Constant* ptr)
1839 quote_mark_(ptr->quote_mark_),
1840 can_compress_whitespace_(ptr->can_compress_whitespace_),
1841 value_(ptr->value_),
1844 String_Constant(ParserState pstate, std::string val)
1845 : String(pstate), quote_mark_(0), can_compress_whitespace_(false), value_(read_css_string(val)), hash_(0)
1847 String_Constant(ParserState pstate, const char* beg)
1848 : String(pstate), quote_mark_(0), can_compress_whitespace_(false), value_(read_css_string(std::string(beg))), hash_(0)
1850 String_Constant(ParserState pstate, const char* beg, const char* end)
1851 : String(pstate), quote_mark_(0), can_compress_whitespace_(false), value_(read_css_string(std::string(beg, end-beg))), hash_(0)
1853 String_Constant(ParserState pstate, const Token& tok)
1854 : String(pstate), quote_mark_(0), can_compress_whitespace_(false), value_(read_css_string(std::string(tok.begin, tok.end))), hash_(0)
1856 std::string type() const { return "string"; }
1857 static std::string type_name() { return "string"; }
1858 virtual bool is_invisible() const;
1859 virtual void rtrim();
1861 virtual size_t hash()
1864 hash_ = std::hash<std::string>()(value_);
1869 virtual bool operator==(const Expression& rhs) const;
1870 virtual std::string inspect() const; // quotes are forced on inspection
1872 // static char auto_quote() { return '*'; }
1873 static char double_quote() { return '"'; }
1874 static char single_quote() { return '\''; }
1876 ATTACH_AST_OPERATIONS(String_Constant)
1880 ////////////////////////////////////////////////////////
1881 // Possibly quoted string (unquote on instantiation)
1882 ////////////////////////////////////////////////////////
1883 class String_Quoted : public String_Constant {
1885 String_Quoted(ParserState pstate, std::string val, char q = 0,
1886 bool keep_utf8_escapes = false, bool skip_unquoting = false,
1887 bool strict_unquoting = true)
1888 : String_Constant(pstate, val)
1890 if (skip_unquoting == false) {
1891 value_ = unquote(value_, "e_mark_, keep_utf8_escapes, strict_unquoting);
1893 if (q && quote_mark_) quote_mark_ = q;
1895 String_Quoted(const String_Quoted* ptr)
1896 : String_Constant(ptr)
1898 virtual bool operator==(const Expression& rhs) const;
1899 virtual std::string inspect() const; // quotes are forced on inspection
1900 ATTACH_AST_OPERATIONS(String_Quoted)
1907 class Media_Query : public Expression,
1908 public Vectorized<Media_Query_Expression_Obj> {
1909 ADD_PROPERTY(String_Obj, media_type)
1910 ADD_PROPERTY(bool, is_negated)
1911 ADD_PROPERTY(bool, is_restricted)
1913 Media_Query(ParserState pstate,
1914 String_Obj t = 0, size_t s = 0, bool n = false, bool r = false)
1915 : Expression(pstate), Vectorized<Media_Query_Expression_Obj>(s),
1916 media_type_(t), is_negated_(n), is_restricted_(r)
1918 Media_Query(const Media_Query* ptr)
1920 Vectorized<Media_Query_Expression_Obj>(*ptr),
1921 media_type_(ptr->media_type_),
1922 is_negated_(ptr->is_negated_),
1923 is_restricted_(ptr->is_restricted_)
1925 ATTACH_AST_OPERATIONS(Media_Query)
1929 ////////////////////////////////////////////////////
1930 // Media expressions (for use inside media queries).
1931 ////////////////////////////////////////////////////
1932 class Media_Query_Expression : public Expression {
1933 ADD_PROPERTY(Expression_Obj, feature)
1934 ADD_PROPERTY(Expression_Obj, value)
1935 ADD_PROPERTY(bool, is_interpolated)
1937 Media_Query_Expression(ParserState pstate,
1938 Expression_Obj f, Expression_Obj v, bool i = false)
1939 : Expression(pstate), feature_(f), value_(v), is_interpolated_(i)
1941 Media_Query_Expression(const Media_Query_Expression* ptr)
1943 feature_(ptr->feature_),
1944 value_(ptr->value_),
1945 is_interpolated_(ptr->is_interpolated_)
1947 ATTACH_AST_OPERATIONS(Media_Query_Expression)
1951 ////////////////////
1952 // `@supports` rule.
1953 ////////////////////
1954 class Supports_Block : public Has_Block {
1955 ADD_PROPERTY(Supports_Condition_Obj, condition)
1957 Supports_Block(ParserState pstate, Supports_Condition_Obj condition, Block_Obj block = 0)
1958 : Has_Block(pstate, block), condition_(condition)
1959 { statement_type(SUPPORTS); }
1960 Supports_Block(const Supports_Block* ptr)
1961 : Has_Block(ptr), condition_(ptr->condition_)
1962 { statement_type(SUPPORTS); }
1963 bool bubbles() { return true; }
1964 ATTACH_AST_OPERATIONS(Supports_Block)
1968 //////////////////////////////////////////////////////
1969 // The abstract superclass of all Supports conditions.
1970 //////////////////////////////////////////////////////
1971 class Supports_Condition : public Expression {
1973 Supports_Condition(ParserState pstate)
1974 : Expression(pstate)
1976 Supports_Condition(const Supports_Condition* ptr)
1979 virtual bool needs_parens(Supports_Condition_Obj cond) const { return false; }
1980 ATTACH_AST_OPERATIONS(Supports_Condition)
1984 ////////////////////////////////////////////////////////////
1985 // An operator condition (e.g. `CONDITION1 and CONDITION2`).
1986 ////////////////////////////////////////////////////////////
1987 class Supports_Operator : public Supports_Condition {
1989 enum Operand { AND, OR };
1991 ADD_PROPERTY(Supports_Condition_Obj, left);
1992 ADD_PROPERTY(Supports_Condition_Obj, right);
1993 ADD_PROPERTY(Operand, operand);
1995 Supports_Operator(ParserState pstate, Supports_Condition_Obj l, Supports_Condition_Obj r, Operand o)
1996 : Supports_Condition(pstate), left_(l), right_(r), operand_(o)
1998 Supports_Operator(const Supports_Operator* ptr)
1999 : Supports_Condition(ptr),
2001 right_(ptr->right_),
2002 operand_(ptr->operand_)
2004 virtual bool needs_parens(Supports_Condition_Obj cond) const;
2005 ATTACH_AST_OPERATIONS(Supports_Operator)
2009 //////////////////////////////////////////
2010 // A negation condition (`not CONDITION`).
2011 //////////////////////////////////////////
2012 class Supports_Negation : public Supports_Condition {
2014 ADD_PROPERTY(Supports_Condition_Obj, condition);
2016 Supports_Negation(ParserState pstate, Supports_Condition_Obj c)
2017 : Supports_Condition(pstate), condition_(c)
2019 Supports_Negation(const Supports_Negation* ptr)
2020 : Supports_Condition(ptr), condition_(ptr->condition_)
2022 virtual bool needs_parens(Supports_Condition_Obj cond) const;
2023 ATTACH_AST_OPERATIONS(Supports_Negation)
2027 /////////////////////////////////////////////////////
2028 // A declaration condition (e.g. `(feature: value)`).
2029 /////////////////////////////////////////////////////
2030 class Supports_Declaration : public Supports_Condition {
2032 ADD_PROPERTY(Expression_Obj, feature);
2033 ADD_PROPERTY(Expression_Obj, value);
2035 Supports_Declaration(ParserState pstate, Expression_Obj f, Expression_Obj v)
2036 : Supports_Condition(pstate), feature_(f), value_(v)
2038 Supports_Declaration(const Supports_Declaration* ptr)
2039 : Supports_Condition(ptr),
2040 feature_(ptr->feature_),
2043 virtual bool needs_parens(Supports_Condition_Obj cond) const { return false; }
2044 ATTACH_AST_OPERATIONS(Supports_Declaration)
2048 ///////////////////////////////////////////////
2049 // An interpolation condition (e.g. `#{$var}`).
2050 ///////////////////////////////////////////////
2051 class Supports_Interpolation : public Supports_Condition {
2053 ADD_PROPERTY(Expression_Obj, value);
2055 Supports_Interpolation(ParserState pstate, Expression_Obj v)
2056 : Supports_Condition(pstate), value_(v)
2058 Supports_Interpolation(const Supports_Interpolation* ptr)
2059 : Supports_Condition(ptr),
2062 virtual bool needs_parens(Supports_Condition_Obj cond) const { return false; }
2063 ATTACH_AST_OPERATIONS(Supports_Interpolation)
2067 /////////////////////////////////////////////////
2068 // At root expressions (for use inside @at-root).
2069 /////////////////////////////////////////////////
2070 class At_Root_Query : public Expression {
2072 ADD_PROPERTY(Expression_Obj, feature)
2073 ADD_PROPERTY(Expression_Obj, value)
2075 At_Root_Query(ParserState pstate, Expression_Obj f = 0, Expression_Obj v = 0, bool i = false)
2076 : Expression(pstate), feature_(f), value_(v)
2078 At_Root_Query(const At_Root_Query* ptr)
2080 feature_(ptr->feature_),
2083 bool exclude(std::string str);
2084 ATTACH_AST_OPERATIONS(At_Root_Query)
2091 class At_Root_Block : public Has_Block {
2092 ADD_PROPERTY(At_Root_Query_Obj, expression)
2094 At_Root_Block(ParserState pstate, Block_Obj b = 0, At_Root_Query_Obj e = 0)
2095 : Has_Block(pstate, b), expression_(e)
2096 { statement_type(ATROOT); }
2097 At_Root_Block(const At_Root_Block* ptr)
2098 : Has_Block(ptr), expression_(ptr->expression_)
2099 { statement_type(ATROOT); }
2100 bool bubbles() { return true; }
2101 bool exclude_node(Statement_Obj s) {
2102 if (expression() == 0)
2104 return s->statement_type() == Statement::RULESET;
2107 if (s->statement_type() == Statement::DIRECTIVE)
2109 if (Directive_Obj dir = Cast<Directive>(s))
2111 std::string keyword(dir->keyword());
2112 if (keyword.length() > 0) keyword.erase(0, 1);
2113 return expression()->exclude(keyword);
2116 if (s->statement_type() == Statement::MEDIA)
2118 return expression()->exclude("media");
2120 if (s->statement_type() == Statement::RULESET)
2122 return expression()->exclude("rule");
2124 if (s->statement_type() == Statement::SUPPORTS)
2126 return expression()->exclude("supports");
2128 if (Directive_Obj dir = Cast<Directive>(s))
2130 if (dir->is_keyframes()) return expression()->exclude("keyframes");
2134 ATTACH_AST_OPERATIONS(At_Root_Block)
2141 class Null : public Value {
2143 Null(ParserState pstate) : Value(pstate) { concrete_type(NULL_VAL); }
2144 Null(const Null* ptr) : Value(ptr) { concrete_type(NULL_VAL); }
2145 std::string type() const { return "null"; }
2146 static std::string type_name() { return "null"; }
2147 bool is_invisible() const { return true; }
2148 operator bool() { return false; }
2149 bool is_false() { return true; }
2151 virtual size_t hash()
2156 virtual bool operator== (const Expression& rhs) const;
2158 ATTACH_AST_OPERATIONS(Null)
2162 /////////////////////////////////
2163 // Thunks for delayed evaluation.
2164 /////////////////////////////////
2165 class Thunk : public Expression {
2166 ADD_PROPERTY(Expression_Obj, expression)
2167 ADD_PROPERTY(Env*, environment)
2169 Thunk(ParserState pstate, Expression_Obj exp, Env* env = 0)
2170 : Expression(pstate), expression_(exp), environment_(env)
2174 /////////////////////////////////////////////////////////
2175 // Individual parameter objects for mixins and functions.
2176 /////////////////////////////////////////////////////////
2177 class Parameter : public AST_Node {
2178 ADD_CONSTREF(std::string, name)
2179 ADD_PROPERTY(Expression_Obj, default_value)
2180 ADD_PROPERTY(bool, is_rest_parameter)
2182 Parameter(ParserState pstate,
2183 std::string n, Expression_Obj def = 0, bool rest = false)
2184 : AST_Node(pstate), name_(n), default_value_(def), is_rest_parameter_(rest)
2186 // tried to come up with a spec test for this, but it does no longer
2187 // get past the parser (it error out earlier). A spec test was added!
2188 // if (default_value_ && is_rest_parameter_) {
2189 // error("variable-length parameter may not have a default value", pstate_);
2192 Parameter(const Parameter* ptr)
2195 default_value_(ptr->default_value_),
2196 is_rest_parameter_(ptr->is_rest_parameter_)
2198 // tried to come up with a spec test for this, but it does no longer
2199 // get past the parser (it error out earlier). A spec test was added!
2200 // if (default_value_ && is_rest_parameter_) {
2201 // error("variable-length parameter may not have a default value", pstate_);
2204 ATTACH_AST_OPERATIONS(Parameter)
2208 /////////////////////////////////////////////////////////////////////////
2209 // Parameter lists -- in their own class to facilitate context-sensitive
2210 // error checking (e.g., ensuring that all optional parameters follow all
2211 // required parameters).
2212 /////////////////////////////////////////////////////////////////////////
2213 class Parameters : public AST_Node, public Vectorized<Parameter_Obj> {
2214 ADD_PROPERTY(bool, has_optional_parameters)
2215 ADD_PROPERTY(bool, has_rest_parameter)
2217 void adjust_after_pushing(Parameter_Obj p)
2219 if (p->default_value()) {
2220 if (has_rest_parameter_) {
2221 error("optional parameters may not be combined with variable-length parameters", p->pstate());
2223 has_optional_parameters_ = true;
2225 else if (p->is_rest_parameter()) {
2226 if (has_rest_parameter_) {
2227 error("functions and mixins cannot have more than one variable-length parameter", p->pstate());
2229 has_rest_parameter_ = true;
2232 if (has_rest_parameter_) {
2233 error("required parameters must precede variable-length parameters", p->pstate());
2235 if (has_optional_parameters_) {
2236 error("required parameters must precede optional parameters", p->pstate());
2241 Parameters(ParserState pstate)
2243 Vectorized<Parameter_Obj>(),
2244 has_optional_parameters_(false),
2245 has_rest_parameter_(false)
2247 Parameters(const Parameters* ptr)
2249 Vectorized<Parameter_Obj>(*ptr),
2250 has_optional_parameters_(ptr->has_optional_parameters_),
2251 has_rest_parameter_(ptr->has_rest_parameter_)
2253 ATTACH_AST_OPERATIONS(Parameters)
2257 /////////////////////////////////////////
2258 // Abstract base class for CSS selectors.
2259 /////////////////////////////////////////
2260 class Selector : public Expression {
2261 // ADD_PROPERTY(bool, has_reference)
2262 // line break before list separator
2263 ADD_PROPERTY(bool, has_line_feed)
2264 // line break after list separator
2265 ADD_PROPERTY(bool, has_line_break)
2266 // maybe we have optional flag
2267 ADD_PROPERTY(bool, is_optional)
2268 // parent block pointers
2270 // must not be a reference counted object
2271 // otherwise we create circular references
2272 ADD_PROPERTY(Media_Block_Ptr, media_block)
2276 Selector(ParserState pstate)
2277 : Expression(pstate),
2278 has_line_feed_(false),
2279 has_line_break_(false),
2280 is_optional_(false),
2283 { concrete_type(SELECTOR); }
2284 Selector(const Selector* ptr)
2286 // has_reference_(ptr->has_reference_),
2287 has_line_feed_(ptr->has_line_feed_),
2288 has_line_break_(ptr->has_line_break_),
2289 is_optional_(ptr->is_optional_),
2290 media_block_(ptr->media_block_),
2292 { concrete_type(SELECTOR); }
2293 virtual ~Selector() = 0;
2294 virtual size_t hash() = 0;
2295 virtual unsigned long specificity() const = 0;
2296 virtual void set_media_block(Media_Block_Ptr mb) {
2299 virtual bool has_parent_ref() const {
2302 virtual bool has_real_parent_ref() const {
2305 // dispatch to correct handlers
2306 virtual bool operator<(const Selector& rhs) const = 0;
2307 virtual bool operator==(const Selector& rhs) const = 0;
2308 ATTACH_VIRTUAL_AST_OPERATIONS(Selector);
2310 inline Selector::~Selector() { }
2312 /////////////////////////////////////////////////////////////////////////
2313 // Interpolated selectors -- the interpolated String will be expanded and
2314 // re-parsed into a normal selector class.
2315 /////////////////////////////////////////////////////////////////////////
2316 class Selector_Schema : public AST_Node {
2317 ADD_PROPERTY(String_Obj, contents)
2318 ADD_PROPERTY(bool, connect_parent);
2319 // must not be a reference counted object
2320 // otherwise we create circular references
2321 ADD_PROPERTY(Media_Block_Ptr, media_block)
2322 // store computed hash
2325 Selector_Schema(ParserState pstate, String_Obj c)
2328 connect_parent_(true),
2331 Selector_Schema(const Selector_Schema* ptr)
2333 contents_(ptr->contents_),
2334 connect_parent_(ptr->connect_parent_),
2335 media_block_(ptr->media_block_)
2337 virtual bool has_parent_ref() const;
2338 virtual bool has_real_parent_ref() const;
2339 virtual bool operator<(const Selector& rhs) const;
2340 virtual bool operator==(const Selector& rhs) const;
2341 // selector schema is not yet a final selector, so we do not
2342 // have a specificity for it yet. We need to
2343 virtual unsigned long specificity() const { return 0; }
2344 virtual size_t hash() {
2346 hash_combine(hash_, contents_->hash());
2350 ATTACH_AST_OPERATIONS(Selector_Schema)
2354 ////////////////////////////////////////////
2355 // Abstract base class for simple selectors.
2356 ////////////////////////////////////////////
2357 class Simple_Selector : public Selector {
2358 ADD_CONSTREF(std::string, ns)
2359 ADD_CONSTREF(std::string, name)
2360 ADD_PROPERTY(Simple_Type, simple_type)
2361 ADD_PROPERTY(bool, has_ns)
2363 Simple_Selector(ParserState pstate, std::string n = "")
2364 : Selector(pstate), ns_(""), name_(n), has_ns_(false)
2366 simple_type(SIMPLE);
2367 size_t pos = n.find('|');
2368 // found some namespace
2369 if (pos != std::string::npos) {
2371 ns_ = n.substr(0, pos);
2372 name_ = n.substr(pos + 1);
2375 Simple_Selector(const Simple_Selector* ptr)
2379 has_ns_(ptr->has_ns_)
2380 { simple_type(SIMPLE); }
2381 virtual std::string ns_name() const
2383 std::string name("");
2386 return name + name_;
2388 virtual size_t hash()
2391 hash_combine(hash_, std::hash<int>()(SELECTOR));
2392 hash_combine(hash_, std::hash<std::string>()(ns()));
2393 hash_combine(hash_, std::hash<std::string>()(name()));
2397 // namespace compare functions
2398 bool is_ns_eq(const Simple_Selector& r) const;
2399 // namespace query functions
2400 bool is_universal_ns() const
2402 return has_ns_ && ns_ == "*";
2404 bool has_universal_ns() const
2406 return !has_ns_ || ns_ == "*";
2408 bool is_empty_ns() const
2410 return !has_ns_ || ns_ == "";
2412 bool has_empty_ns() const
2414 return has_ns_ && ns_ == "";
2416 bool has_qualified_ns() const
2418 return has_ns_ && ns_ != "" && ns_ != "*";
2420 // name query functions
2421 bool is_universal() const
2423 return name_ == "*";
2426 virtual bool has_placeholder() {
2430 virtual ~Simple_Selector() = 0;
2431 virtual Compound_Selector_Ptr unify_with(Compound_Selector_Ptr, Context&);
2432 virtual bool has_parent_ref() const { return false; };
2433 virtual bool has_real_parent_ref() const { return false; };
2434 virtual bool is_pseudo_element() const { return false; }
2436 virtual bool is_superselector_of(Compound_Selector_Obj sub) { return false; }
2438 virtual bool operator==(const Selector& rhs) const;
2439 virtual bool operator==(const Simple_Selector& rhs) const;
2440 inline bool operator!=(const Simple_Selector& rhs) const { return !(*this == rhs); }
2442 bool operator<(const Selector& rhs) const;
2443 bool operator<(const Simple_Selector& rhs) const;
2444 // default implementation should work for most of the simple selectors (otherwise overload)
2445 ATTACH_VIRTUAL_AST_OPERATIONS(Simple_Selector);
2446 ATTACH_OPERATIONS();
2448 inline Simple_Selector::~Simple_Selector() { }
2451 //////////////////////////////////
2452 // The Parent Selector Expression.
2453 //////////////////////////////////
2454 // parent selectors can occur in selectors but also
2455 // inside strings in declarations (Compound_Selector).
2456 // only one simple parent selector means the first case.
2457 class Parent_Selector : public Simple_Selector {
2458 ADD_PROPERTY(bool, real)
2460 Parent_Selector(ParserState pstate, bool r = true)
2461 : Simple_Selector(pstate, "&"), real_(r)
2462 { /* has_reference(true); */ }
2463 Parent_Selector(const Parent_Selector* ptr)
2464 : Simple_Selector(ptr), real_(ptr->real_)
2465 { /* has_reference(true); */ }
2466 bool is_real_parent_ref() const { return real(); };
2467 virtual bool has_parent_ref() const { return true; };
2468 virtual bool has_real_parent_ref() const { return is_real_parent_ref(); };
2469 virtual unsigned long specificity() const
2473 std::string type() const { return "selector"; }
2474 static std::string type_name() { return "selector"; }
2475 ATTACH_AST_OPERATIONS(Parent_Selector)
2479 /////////////////////////////////////////////////////////////////////////
2480 // Placeholder selectors (e.g., "%foo") for use in extend-only selectors.
2481 /////////////////////////////////////////////////////////////////////////
2482 class Placeholder_Selector : public Simple_Selector {
2484 Placeholder_Selector(ParserState pstate, std::string n)
2485 : Simple_Selector(pstate, n)
2487 Placeholder_Selector(const Placeholder_Selector* ptr)
2488 : Simple_Selector(ptr)
2490 virtual unsigned long specificity() const
2492 return Constants::Specificity_Base;
2494 virtual bool has_placeholder() {
2497 virtual ~Placeholder_Selector() {};
2498 ATTACH_AST_OPERATIONS(Placeholder_Selector)
2502 /////////////////////////////////////////////////////////////////////
2503 // Element selectors (and the universal selector) -- e.g., div, span, *.
2504 /////////////////////////////////////////////////////////////////////
2505 class Element_Selector : public Simple_Selector {
2507 Element_Selector(ParserState pstate, std::string n)
2508 : Simple_Selector(pstate, n)
2510 Element_Selector(const Element_Selector* ptr)
2511 : Simple_Selector(ptr)
2513 virtual unsigned long specificity() const
2515 if (name() == "*") return 0;
2516 else return Constants::Specificity_Element;
2518 virtual Simple_Selector_Ptr unify_with(Simple_Selector_Ptr, Context&);
2519 virtual Compound_Selector_Ptr unify_with(Compound_Selector_Ptr, Context&);
2520 ATTACH_AST_OPERATIONS(Element_Selector)
2524 ////////////////////////////////////////////////
2525 // Class selectors -- i.e., .foo.
2526 ////////////////////////////////////////////////
2527 class Class_Selector : public Simple_Selector {
2529 Class_Selector(ParserState pstate, std::string n)
2530 : Simple_Selector(pstate, n)
2532 Class_Selector(const Class_Selector* ptr)
2533 : Simple_Selector(ptr)
2535 virtual unsigned long specificity() const
2537 return Constants::Specificity_Class;
2539 virtual Compound_Selector_Ptr unify_with(Compound_Selector_Ptr, Context&);
2540 ATTACH_AST_OPERATIONS(Class_Selector)
2544 ////////////////////////////////////////////////
2545 // ID selectors -- i.e., #foo.
2546 ////////////////////////////////////////////////
2547 class Id_Selector : public Simple_Selector {
2549 Id_Selector(ParserState pstate, std::string n)
2550 : Simple_Selector(pstate, n)
2552 Id_Selector(const Id_Selector* ptr)
2553 : Simple_Selector(ptr)
2555 virtual unsigned long specificity() const
2557 return Constants::Specificity_ID;
2559 virtual Compound_Selector_Ptr unify_with(Compound_Selector_Ptr, Context&);
2560 ATTACH_AST_OPERATIONS(Id_Selector)
2564 ///////////////////////////////////////////////////
2565 // Attribute selectors -- e.g., [src*=".jpg"], etc.
2566 ///////////////////////////////////////////////////
2567 class Attribute_Selector : public Simple_Selector {
2568 ADD_CONSTREF(std::string, matcher)
2569 // this cannot be changed to obj atm!!!!!!????!!!!!!!
2570 ADD_PROPERTY(String_Obj, value) // might be interpolated
2572 Attribute_Selector(ParserState pstate, std::string n, std::string m, String_Obj v)
2573 : Simple_Selector(pstate, n), matcher_(m), value_(v)
2574 { simple_type(ATTR_SEL); }
2575 Attribute_Selector(const Attribute_Selector* ptr)
2576 : Simple_Selector(ptr),
2577 matcher_(ptr->matcher_),
2579 { simple_type(ATTR_SEL); }
2580 virtual size_t hash()
2583 hash_combine(hash_, Simple_Selector::hash());
2584 hash_combine(hash_, std::hash<std::string>()(matcher()));
2585 if (value_) hash_combine(hash_, value_->hash());
2589 virtual unsigned long specificity() const
2591 return Constants::Specificity_Attr;
2593 virtual bool operator==(const Simple_Selector& rhs) const;
2594 virtual bool operator==(const Attribute_Selector& rhs) const;
2595 virtual bool operator<(const Simple_Selector& rhs) const;
2596 virtual bool operator<(const Attribute_Selector& rhs) const;
2597 ATTACH_AST_OPERATIONS(Attribute_Selector)
2601 //////////////////////////////////////////////////////////////////
2602 // Pseudo selectors -- e.g., :first-child, :nth-of-type(...), etc.
2603 //////////////////////////////////////////////////////////////////
2604 /* '::' starts a pseudo-element, ':' a pseudo-class */
2605 /* Except :first-line, :first-letter, :before and :after */
2606 /* Note that pseudo-elements are restricted to one per selector */
2607 /* and occur only in the last simple_selector_sequence. */
2608 inline bool is_pseudo_class_element(const std::string& name)
2610 return name == ":before" ||
2612 name == ":first-line" ||
2613 name == ":first-letter";
2616 // Pseudo Selector cannot have any namespace?
2617 class Pseudo_Selector : public Simple_Selector {
2618 ADD_PROPERTY(String_Obj, expression)
2620 Pseudo_Selector(ParserState pstate, std::string n, String_Obj expr = 0)
2621 : Simple_Selector(pstate, n), expression_(expr)
2622 { simple_type(PSEUDO_SEL); }
2623 Pseudo_Selector(const Pseudo_Selector* ptr)
2624 : Simple_Selector(ptr), expression_(ptr->expression_)
2625 { simple_type(PSEUDO_SEL); }
2627 // A pseudo-element is made of two colons (::) followed by the name.
2628 // The `::` notation is introduced by the current document in order to
2629 // establish a discrimination between pseudo-classes and pseudo-elements.
2630 // For compatibility with existing style sheets, user agents must also
2631 // accept the previous one-colon notation for pseudo-elements introduced
2632 // in CSS levels 1 and 2 (namely, :first-line, :first-letter, :before and
2633 // :after). This compatibility is not allowed for the new pseudo-elements
2634 // introduced in this specification.
2635 virtual bool is_pseudo_element() const
2637 return (name_[0] == ':' && name_[1] == ':')
2638 || is_pseudo_class_element(name_);
2640 virtual size_t hash()
2643 hash_combine(hash_, Simple_Selector::hash());
2644 if (expression_) hash_combine(hash_, expression_->hash());
2648 virtual unsigned long specificity() const
2650 if (is_pseudo_element())
2651 return Constants::Specificity_Element;
2652 return Constants::Specificity_Pseudo;
2654 virtual bool operator==(const Simple_Selector& rhs) const;
2655 virtual bool operator==(const Pseudo_Selector& rhs) const;
2656 virtual bool operator<(const Simple_Selector& rhs) const;
2657 virtual bool operator<(const Pseudo_Selector& rhs) const;
2658 virtual Compound_Selector_Ptr unify_with(Compound_Selector_Ptr, Context&);
2659 ATTACH_AST_OPERATIONS(Pseudo_Selector)
2663 /////////////////////////////////////////////////
2664 // 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)
2665 /////////////////////////////////////////////////
2666 class Wrapped_Selector : public Simple_Selector {
2667 ADD_PROPERTY(Selector_List_Obj, selector)
2669 Wrapped_Selector(ParserState pstate, std::string n, Selector_List_Obj sel)
2670 : Simple_Selector(pstate, n), selector_(sel)
2671 { simple_type(WRAPPED_SEL); }
2672 Wrapped_Selector(const Wrapped_Selector* ptr)
2673 : Simple_Selector(ptr), selector_(ptr->selector_)
2674 { simple_type(WRAPPED_SEL); }
2675 virtual bool is_superselector_of(Wrapped_Selector_Obj sub);
2676 // Selectors inside the negation pseudo-class are counted like any
2677 // other, but the negation itself does not count as a pseudo-class.
2678 virtual size_t hash();
2679 virtual bool has_parent_ref() const;
2680 virtual bool has_real_parent_ref() const;
2681 virtual unsigned long specificity() const;
2682 virtual bool operator==(const Simple_Selector& rhs) const;
2683 virtual bool operator==(const Wrapped_Selector& rhs) const;
2684 virtual bool operator<(const Simple_Selector& rhs) const;
2685 virtual bool operator<(const Wrapped_Selector& rhs) const;
2686 virtual void cloneChildren();
2687 ATTACH_AST_OPERATIONS(Wrapped_Selector)
2691 ////////////////////////////////////////////////////////////////////////////
2692 // Simple selector sequences. Maintains flags indicating whether it contains
2693 // any parent references or placeholders, to simplify expansion.
2694 ////////////////////////////////////////////////////////////////////////////
2695 class Compound_Selector : public Selector, public Vectorized<Simple_Selector_Obj> {
2697 ComplexSelectorSet sources_;
2698 ADD_PROPERTY(bool, extended);
2699 ADD_PROPERTY(bool, has_parent_reference);
2701 void adjust_after_pushing(Simple_Selector_Obj s)
2703 // if (s->has_reference()) has_reference(true);
2704 // if (s->has_placeholder()) has_placeholder(true);
2707 Compound_Selector(ParserState pstate, size_t s = 0)
2709 Vectorized<Simple_Selector_Obj>(s),
2711 has_parent_reference_(false)
2713 Compound_Selector(const Compound_Selector* ptr)
2715 Vectorized<Simple_Selector_Obj>(*ptr),
2716 extended_(ptr->extended_),
2717 has_parent_reference_(ptr->has_parent_reference_)
2719 bool contains_placeholder() {
2720 for (size_t i = 0, L = length(); i < L; ++i) {
2721 if ((*this)[i]->has_placeholder()) return true;
2726 void append(Simple_Selector_Ptr element);
2728 bool is_universal() const
2730 return length() == 1 && (*this)[0]->is_universal();
2733 Complex_Selector_Obj to_complex();
2734 Compound_Selector_Ptr unify_with(Compound_Selector_Ptr rhs, Context& ctx);
2735 // virtual Placeholder_Selector_Ptr find_placeholder();
2736 virtual bool has_parent_ref() const;
2737 virtual bool has_real_parent_ref() const;
2738 Simple_Selector_Ptr base() const {
2739 if (length() == 0) return 0;
2740 // ToDo: why is this needed?
2741 if (Cast<Element_Selector>((*this)[0]))
2745 virtual bool is_superselector_of(Compound_Selector_Obj sub, std::string wrapped = "");
2746 virtual bool is_superselector_of(Complex_Selector_Obj sub, std::string wrapped = "");
2747 virtual bool is_superselector_of(Selector_List_Obj sub, std::string wrapped = "");
2748 virtual size_t hash()
2750 if (Selector::hash_ == 0) {
2751 hash_combine(Selector::hash_, std::hash<int>()(SELECTOR));
2752 if (length()) hash_combine(Selector::hash_, Vectorized::hash());
2754 return Selector::hash_;
2756 virtual unsigned long specificity() const
2759 for (size_t i = 0, L = length(); i < L; ++i)
2760 { sum += (*this)[i]->specificity(); }
2764 virtual bool has_placeholder()
2766 if (length() == 0) return false;
2767 if (Simple_Selector_Obj ss = elements().front()) {
2768 if (ss->has_placeholder()) return true;
2773 bool is_empty_reference()
2775 return length() == 1 &&
2776 Cast<Parent_Selector>((*this)[0]);
2779 virtual bool operator<(const Selector& rhs) const;
2780 virtual bool operator==(const Selector& rhs) const;
2781 virtual bool operator<(const Compound_Selector& rhs) const;
2782 virtual bool operator==(const Compound_Selector& rhs) const;
2783 inline bool operator!=(const Compound_Selector& rhs) const { return !(*this == rhs); }
2785 ComplexSelectorSet& sources() { return sources_; }
2786 void clearSources() { sources_.clear(); }
2787 void mergeSources(ComplexSelectorSet& sources, Context& ctx);
2789 Compound_Selector_Ptr minus(Compound_Selector_Ptr rhs, Context& ctx);
2790 virtual void cloneChildren();
2791 ATTACH_AST_OPERATIONS(Compound_Selector)
2795 ////////////////////////////////////////////////////////////////////////////
2796 // General selectors -- i.e., simple sequences combined with one of the four
2797 // CSS selector combinators (">", "+", "~", and whitespace). Essentially a
2799 ////////////////////////////////////////////////////////////////////////////
2800 class Complex_Selector : public Selector {
2802 enum Combinator { ANCESTOR_OF, PARENT_OF, PRECEDES, ADJACENT_TO, REFERENCE };
2804 HASH_CONSTREF(Combinator, combinator)
2805 HASH_PROPERTY(Compound_Selector_Obj, head)
2806 HASH_PROPERTY(Complex_Selector_Obj, tail)
2807 HASH_PROPERTY(String_Obj, reference);
2809 bool contains_placeholder() {
2810 if (head() && head()->contains_placeholder()) return true;
2811 if (tail() && tail()->contains_placeholder()) return true;
2814 Complex_Selector(ParserState pstate,
2815 Combinator c = ANCESTOR_OF,
2816 Compound_Selector_Obj h = 0,
2817 Complex_Selector_Obj t = 0,
2824 Complex_Selector(const Complex_Selector* ptr)
2826 combinator_(ptr->combinator_),
2827 head_(ptr->head_), tail_(ptr->tail_),
2828 reference_(ptr->reference_)
2830 virtual bool has_parent_ref() const;
2831 virtual bool has_real_parent_ref() const;
2833 Complex_Selector_Obj skip_empty_reference()
2835 if ((!head_ || !head_->length() || head_->is_empty_reference()) &&
2836 combinator() == Combinator::ANCESTOR_OF)
2838 if (!tail_) return 0;
2839 tail_->has_line_feed_ = this->has_line_feed_;
2840 // tail_->has_line_break_ = this->has_line_break_;
2841 return tail_->skip_empty_reference();
2846 // can still have a tail
2847 bool is_empty_ancestor() const
2849 return (!head() || head()->length() == 0) &&
2850 combinator() == Combinator::ANCESTOR_OF;
2853 Selector_List_Ptr tails(Context& ctx, Selector_List_Ptr tails);
2855 // front returns the first real tail
2856 // skips over parent and empty ones
2857 Complex_Selector_Obj first();
2858 // last returns the last real tail
2859 Complex_Selector_Obj last();
2861 // some shortcuts that should be removed
2862 Complex_Selector_Obj innermost() { return last(); };
2864 size_t length() const;
2865 Selector_List_Ptr resolve_parent_refs(Context& ctx, std::vector<Selector_List_Obj>& pstack, bool implicit_parent = true);
2866 virtual bool is_superselector_of(Compound_Selector_Obj sub, std::string wrapping = "");
2867 virtual bool is_superselector_of(Complex_Selector_Obj sub, std::string wrapping = "");
2868 virtual bool is_superselector_of(Selector_List_Obj sub, std::string wrapping = "");
2869 Selector_List_Ptr unify_with(Complex_Selector_Ptr rhs, Context& ctx);
2870 Combinator clear_innermost();
2871 void append(Context&, Complex_Selector_Obj);
2872 void set_innermost(Complex_Selector_Obj, Combinator);
2873 virtual size_t hash()
2876 hash_combine(hash_, std::hash<int>()(SELECTOR));
2877 hash_combine(hash_, std::hash<int>()(combinator_));
2878 if (head_) hash_combine(hash_, head_->hash());
2879 if (tail_) hash_combine(hash_, tail_->hash());
2883 virtual unsigned long specificity() const
2886 if (head()) sum += head()->specificity();
2887 if (tail()) sum += tail()->specificity();
2890 virtual void set_media_block(Media_Block_Ptr mb) {
2892 if (tail_) tail_->set_media_block(mb);
2893 if (head_) head_->set_media_block(mb);
2895 virtual bool has_placeholder() {
2896 if (head_ && head_->has_placeholder()) return true;
2897 if (tail_ && tail_->has_placeholder()) return true;
2900 virtual bool operator<(const Selector& rhs) const;
2901 virtual bool operator==(const Selector& rhs) const;
2902 virtual bool operator<(const Complex_Selector& rhs) const;
2903 virtual bool operator==(const Complex_Selector& rhs) const;
2904 inline bool operator!=(const Complex_Selector& rhs) const { return !(*this == rhs); }
2905 const ComplexSelectorSet sources()
2908 //seq.map {|sseq_or_op| s.merge sseq_or_op.sources if sseq_or_op.is_a?(SimpleSequence)}
2911 ComplexSelectorSet srcs;
2913 Compound_Selector_Obj pHead = head();
2914 Complex_Selector_Obj pTail = tail();
2917 const ComplexSelectorSet& headSources = pHead->sources();
2918 srcs.insert(headSources.begin(), headSources.end());
2922 const ComplexSelectorSet& tailSources = pTail->sources();
2923 srcs.insert(tailSources.begin(), tailSources.end());
2928 void addSources(ComplexSelectorSet& sources, Context& ctx) {
2929 // members.map! {|m| m.is_a?(SimpleSequence) ? m.with_more_sources(sources) : m}
2930 Complex_Selector_Ptr pIter = this;
2932 Compound_Selector_Ptr pHead = pIter->head();
2935 pHead->mergeSources(sources, ctx);
2938 pIter = pIter->tail();
2941 void clearSources() {
2942 Complex_Selector_Ptr pIter = this;
2944 Compound_Selector_Ptr pHead = pIter->head();
2947 pHead->clearSources();
2950 pIter = pIter->tail();
2954 virtual void cloneChildren();
2955 ATTACH_AST_OPERATIONS(Complex_Selector)
2959 ///////////////////////////////////
2960 // Comma-separated selector groups.
2961 ///////////////////////////////////
2962 class Selector_List : public Selector, public Vectorized<Complex_Selector_Obj> {
2963 ADD_PROPERTY(Selector_Schema_Obj, schema)
2964 ADD_CONSTREF(std::vector<std::string>, wspace)
2966 void adjust_after_pushing(Complex_Selector_Obj c);
2968 Selector_List(ParserState pstate, size_t s = 0)
2970 Vectorized<Complex_Selector_Obj>(s),
2974 Selector_List(const Selector_List* ptr)
2976 Vectorized<Complex_Selector_Obj>(*ptr),
2977 schema_(ptr->schema_),
2978 wspace_(ptr->wspace_)
2980 std::string type() const { return "list"; }
2981 // remove parent selector references
2982 // basically unwraps parsed selectors
2983 virtual bool has_parent_ref() const;
2984 virtual bool has_real_parent_ref() const;
2985 void remove_parent_selectors();
2986 Selector_List_Ptr resolve_parent_refs(Context& ctx, std::vector<Selector_List_Obj>& pstack, bool implicit_parent = true);
2987 virtual bool is_superselector_of(Compound_Selector_Obj sub, std::string wrapping = "");
2988 virtual bool is_superselector_of(Complex_Selector_Obj sub, std::string wrapping = "");
2989 virtual bool is_superselector_of(Selector_List_Obj sub, std::string wrapping = "");
2990 Selector_List_Ptr unify_with(Selector_List_Ptr, Context&);
2991 void populate_extends(Selector_List_Obj, Context&, Subset_Map&);
2992 Selector_List_Obj eval(Eval& eval);
2993 virtual size_t hash()
2995 if (Selector::hash_ == 0) {
2996 hash_combine(Selector::hash_, std::hash<int>()(SELECTOR));
2997 hash_combine(Selector::hash_, Vectorized::hash());
2999 return Selector::hash_;
3001 virtual unsigned long specificity() const
3003 unsigned long sum = 0;
3004 unsigned long specificity = 0;
3005 for (size_t i = 0, L = length(); i < L; ++i)
3007 specificity = (*this)[i]->specificity();
3008 if (sum < specificity) sum = specificity;
3012 virtual void set_media_block(Media_Block_Ptr mb) {
3014 for (Complex_Selector_Obj cs : elements()) {
3015 cs->set_media_block(mb);
3018 virtual bool has_placeholder() {
3019 for (Complex_Selector_Obj cs : elements()) {
3020 if (cs->has_placeholder()) return true;
3024 virtual bool operator<(const Selector& rhs) const;
3025 virtual bool operator==(const Selector& rhs) const;
3026 virtual bool operator<(const Selector_List& rhs) const;
3027 virtual bool operator==(const Selector_List& rhs) const;
3028 // Selector Lists can be compared to comma lists
3029 virtual bool operator==(const Expression& rhs) const;
3030 virtual void cloneChildren();
3031 ATTACH_AST_OPERATIONS(Selector_List)
3035 // compare function for sorting and probably other other uses
3036 struct cmp_complex_selector { inline bool operator() (const Complex_Selector_Obj l, const Complex_Selector_Obj r) { return (*l < *r); } };
3037 struct cmp_compound_selector { inline bool operator() (const Compound_Selector_Obj l, const Compound_Selector_Obj r) { return (*l < *r); } };
3038 struct cmp_simple_selector { inline bool operator() (const Simple_Selector_Obj l, const Simple_Selector_Obj r) { return (*l < *r); } };
3044 #pragma clang diagnostic pop