1#ifndef SASS_AST_H
2#define SASS_AST_H
3
4// sass.hpp must go before all system headers to get the
5// __EXTENSIONS__ fix on Solaris.
6#include "sass.hpp"
7
8#include <typeinfo>
9#include <unordered_map>
10
11#include "sass/base.h"
12#include "ast_helpers.hpp"
13#include "ast_fwd_decl.hpp"
14#include "ast_def_macros.hpp"
15
16#include "file.hpp"
17#include "position.hpp"
18#include "operation.hpp"
19#include "environment.hpp"
20#include "fn_utils.hpp"
21
22namespace Sass {
23
24 // ToDo: where does this fit best?
25 // We don't share this with C-API?
26 class Operand {
27 public:
28 Operand(Sass_OP operand, bool ws_before = false, bool ws_after = false)
29 : operand(operand), ws_before(ws_before), ws_after(ws_after)
30 { }
31 public:
32 enum Sass_OP operand;
33 bool ws_before;
34 bool ws_after;
35 };
36
37 //////////////////////////////////////////////////////////
38 // `hash_combine` comes from boost (functional/hash):
39 // http://www.boost.org/doc/libs/1_35_0/doc/html/hash/combine.html
40 // Boost Software License - Version 1.0
41 // http://www.boost.org/users/license.html
42 template <typename T>
43 void hash_combine (std::size_t& seed, const T& val)
44 {
45 seed ^= std::hash<T>()(val) + 0x9e3779b9
46 + (seed<<6) + (seed>>2);
47 }
48 //////////////////////////////////////////////////////////
49
50 const char* sass_op_to_name(enum Sass_OP op);
51
52 const char* sass_op_separator(enum Sass_OP op);
53
54 //////////////////////////////////////////////////////////
55 // Abstract base class for all abstract syntax tree nodes.
56 //////////////////////////////////////////////////////////
57 class AST_Node : public SharedObj {
58 ADD_PROPERTY(SourceSpan, pstate)
59 public:
60 AST_Node(SourceSpan pstate)
61 : pstate_(pstate)
62 { }
63 AST_Node(const AST_Node* ptr)
64 : pstate_(ptr->pstate_)
65 { }
66
67 // allow implicit conversion to string
68 // needed for by SharedPtr implementation
69 operator sass::string() {
70 return to_string();
71 }
72
73 // AST_Node(AST_Node& ptr) = delete;
74
75 virtual ~AST_Node() = 0;
76 virtual size_t hash() const { return 0; }
77 virtual sass::string inspect() const { return to_string(opt: { INSPECT, 5 }); }
78 virtual sass::string to_sass() const { return to_string(opt: { TO_SASS, 5 }); }
79 virtual sass::string to_string(Sass_Inspect_Options opt) const;
80 virtual sass::string to_css(Sass_Inspect_Options opt) const;
81 virtual sass::string to_string() const;
82 virtual void cloneChildren() {};
83 // generic find function (not fully implemented yet)
84 // ToDo: add specific implementations to all children
85 virtual bool find ( bool (*f)(AST_Node_Obj) ) { return f(this); };
86 void update_pstate(const SourceSpan& pstate);
87
88 // Some objects are not meant to be compared
89 // ToDo: maybe fall-back to pointer comparison?
90 virtual bool operator== (const AST_Node& rhs) const {
91 throw std::runtime_error("operator== not implemented");
92 }
93
94 // We can give some reasonable implementations by using
95 // invert operators on the specialized implementations
96 virtual bool operator!= (const AST_Node& rhs) const {
97 // Unequal if not equal
98 return !(*this == rhs);
99 }
100
101 ATTACH_ABSTRACT_AST_OPERATIONS(AST_Node);
102 ATTACH_ABSTRACT_CRTP_PERFORM_METHODS()
103 };
104 inline AST_Node::~AST_Node() { }
105
106 //////////////////////////////////////////////////////////////////////
107 // define cast template now (need complete type)
108 //////////////////////////////////////////////////////////////////////
109
110 template<class T>
111 T* Cast(AST_Node* ptr) {
112 return ptr && typeid(T) == typeid(*ptr) ?
113 static_cast<T*>(ptr) : NULL;
114 };
115
116 template<class T>
117 const T* Cast(const AST_Node* ptr) {
118 return ptr && typeid(T) == typeid(*ptr) ?
119 static_cast<const T*>(ptr) : NULL;
120 };
121
122 //////////////////////////////////////////////////////////////////////
123 // Abstract base class for expressions. This side of the AST hierarchy
124 // represents elements in value contexts, which exist primarily to be
125 // evaluated and returned.
126 //////////////////////////////////////////////////////////////////////
127 class Expression : public AST_Node {
128 public:
129 enum Type {
130 NONE,
131 BOOLEAN,
132 NUMBER,
133 COLOR,
134 STRING,
135 LIST,
136 MAP,
137 SELECTOR,
138 NULL_VAL,
139 FUNCTION_VAL,
140 C_WARNING,
141 C_ERROR,
142 FUNCTION,
143 VARIABLE,
144 PARENT,
145 NUM_TYPES
146 };
147 private:
148 // expressions in some contexts shouldn't be evaluated
149 ADD_PROPERTY(bool, is_delayed)
150 ADD_PROPERTY(bool, is_expanded)
151 ADD_PROPERTY(bool, is_interpolant)
152 ADD_PROPERTY(Type, concrete_type)
153 public:
154 Expression(SourceSpan pstate, bool d = false, bool e = false, bool i = false, Type ct = NONE);
155 virtual operator bool() { return true; }
156 virtual ~Expression() { }
157 virtual bool is_invisible() const { return false; }
158
159 virtual sass::string type() const { return ""; }
160 static sass::string type_name() { return ""; }
161
162 virtual bool is_false() { return false; }
163 // virtual bool is_true() { return !is_false(); }
164 virtual bool operator< (const Expression& rhs) const { return false; }
165 virtual bool operator== (const Expression& rhs) const { return false; }
166 inline bool operator>(const Expression& rhs) const { return rhs < *this; }
167 inline bool operator!=(const Expression& rhs) const { return !(rhs == *this); }
168 virtual bool eq(const Expression& rhs) const { return *this == rhs; };
169 virtual void set_delayed(bool delayed) { is_delayed(is_delayed__: delayed); }
170 virtual bool has_interpolant() const { return is_interpolant(); }
171 virtual bool is_left_interpolant() const { return is_interpolant(); }
172 virtual bool is_right_interpolant() const { return is_interpolant(); }
173 ATTACH_VIRTUAL_AST_OPERATIONS(Expression);
174 size_t hash() const override { return 0; }
175 };
176
177}
178
179/////////////////////////////////////////////////////////////////////////////////////
180// Hash method specializations for std::unordered_map to work with Sass::Expression
181/////////////////////////////////////////////////////////////////////////////////////
182
183namespace std {
184 template<>
185 struct hash<Sass::ExpressionObj>
186 {
187 size_t operator()(Sass::ExpressionObj s) const
188 {
189 return s->hash();
190 }
191 };
192 template<>
193 struct equal_to<Sass::ExpressionObj>
194 {
195 bool operator()( Sass::ExpressionObj lhs, Sass::ExpressionObj rhs) const
196 {
197 return lhs->hash() == rhs->hash();
198 }
199 };
200}
201
202namespace Sass {
203
204 /////////////////////////////////////////////////////////////////////////////
205 // Mixin class for AST nodes that should behave like vectors. Uses the
206 // "Template Method" design pattern to allow subclasses to adjust their flags
207 // when certain objects are pushed.
208 /////////////////////////////////////////////////////////////////////////////
209 template <typename T>
210 class Vectorized {
211 sass::vector<T> elements_;
212 protected:
213 mutable size_t hash_;
214 void reset_hash() { hash_ = 0; }
215 virtual void adjust_after_pushing(T element) { }
216 public:
217 Vectorized(size_t s = 0) : hash_(0)
218 { elements_.reserve(s); }
219 Vectorized(sass::vector<T> vec) :
220 elements_(std::move(vec)),
221 hash_(0)
222 {}
223 virtual ~Vectorized() = 0;
224 size_t length() const { return elements_.size(); }
225 bool empty() const { return elements_.empty(); }
226 void clear() { return elements_.clear(); }
227 T& last() { return elements_.back(); }
228 T& first() { return elements_.front(); }
229 const T& last() const { return elements_.back(); }
230 const T& first() const { return elements_.front(); }
231
232 bool operator== (const Vectorized<T>& rhs) const {
233 // Abort early if sizes do not match
234 if (length() != rhs.length()) return false;
235 // Otherwise test each node for object equalicy in order
236 return std::equal(begin(), end(), rhs.begin(), ObjEqualityFn<T>);
237 }
238
239 bool operator!= (const Vectorized<T>& rhs) const {
240 return !(*this == rhs);
241 }
242
243 T& operator[](size_t i) { return elements_[i]; }
244 virtual const T& at(size_t i) const { return elements_.at(i); }
245 virtual T& at(size_t i) { return elements_.at(i); }
246 const T& get(size_t i) const { return elements_[i]; }
247 const T& operator[](size_t i) const { return elements_[i]; }
248
249 // Implicitly get the sass::vector from our object
250 // Makes the Vector directly assignable to sass::vector
251 // You are responsible to make a copy if needed
252 // Note: since this returns the real object, we can't
253 // Note: guarantee that the hash will not get out of sync
254 operator sass::vector<T>&() { return elements_; }
255 operator const sass::vector<T>&() const { return elements_; }
256
257 // Explicitly request all elements as a real sass::vector
258 // You are responsible to make a copy if needed
259 // Note: since this returns the real object, we can't
260 // Note: guarantee that the hash will not get out of sync
261 sass::vector<T>& elements() { return elements_; }
262 const sass::vector<T>& elements() const { return elements_; }
263
264 // Insert all items from compatible vector
265 void concat(const sass::vector<T>& v)
266 {
267 if (!v.empty()) reset_hash();
268 elements().insert(end(), v.begin(), v.end());
269 }
270
271 // Syntatic sugar for pointers
272 void concat(const Vectorized<T>* v)
273 {
274 if (v != nullptr) {
275 return concat(*v);
276 }
277 }
278
279 // Insert one item on the front
280 void unshift(T element)
281 {
282 reset_hash();
283 elements_.insert(begin(), element);
284 }
285
286 // Remove and return item on the front
287 // ToDo: handle empty vectors
288 T shift() {
289 reset_hash();
290 T first = get(i: 0);
291 elements_.erase(begin());
292 return first;
293 }
294
295 // Insert one item on the back
296 // ToDo: rename this to push
297 void append(T element)
298 {
299 reset_hash();
300 elements_.insert(end(), element);
301 // ToDo: Mostly used by parameters and arguments
302 // ToDo: Find a more elegant way to support this
303 adjust_after_pushing(element);
304 }
305
306 // Check if an item already exists
307 // Uses underlying object `operator==`
308 // E.g. compares the actual objects
309 bool contains(const T& el) const {
310 for (const T& rhs : elements_) {
311 // Test the underlying objects for equality
312 // A std::find checks for pointer equality
313 if (ObjEqualityFn(el, rhs)) {
314 return true;
315 }
316 }
317 return false;
318 }
319
320 // This might be better implemented as `operator=`?
321 void elements(sass::vector<T> e) {
322 reset_hash();
323 elements_ = std::move(e);
324 }
325
326 virtual size_t hash() const
327 {
328 if (hash_ == 0) {
329 for (const T& el : elements_) {
330 hash_combine(hash_, el->hash());
331 }
332 }
333 return hash_;
334 }
335
336 template <typename P, typename V>
337 typename sass::vector<T>::iterator insert(P position, const V& val) {
338 reset_hash();
339 return elements_.insert(position, val);
340 }
341
342 typename sass::vector<T>::iterator end() { return elements_.end(); }
343 typename sass::vector<T>::iterator begin() { return elements_.begin(); }
344 typename sass::vector<T>::const_iterator end() const { return elements_.end(); }
345 typename sass::vector<T>::const_iterator begin() const { return elements_.begin(); }
346 typename sass::vector<T>::iterator erase(typename sass::vector<T>::iterator el) { reset_hash(); return elements_.erase(el); }
347 typename sass::vector<T>::const_iterator erase(typename sass::vector<T>::const_iterator el) { reset_hash(); return elements_.erase(el); }
348
349 };
350 template <typename T>
351 inline Vectorized<T>::~Vectorized() { }
352
353 /////////////////////////////////////////////////////////////////////////////
354 // Mixin class for AST nodes that should behave like a hash table. Uses an
355 // extra <sass::vector> internally to maintain insertion order for interation.
356 /////////////////////////////////////////////////////////////////////////////
357 template <typename K, typename T, typename U>
358 class Hashed {
359 private:
360 std::unordered_map<
361 K, T, ObjHash, ObjEquality
362 > elements_;
363
364 sass::vector<K> _keys;
365 sass::vector<T> _values;
366 protected:
367 mutable size_t hash_;
368 K duplicate_key_;
369 void reset_hash() { hash_ = 0; }
370 void reset_duplicate_key() { duplicate_key_ = {}; }
371 virtual void adjust_after_pushing(std::pair<K, T> p) { }
372 public:
373 Hashed(size_t s = 0)
374 : elements_(),
375 _keys(),
376 _values(),
377 hash_(0), duplicate_key_({})
378 {
379 _keys.reserve(s);
380 _values.reserve(s);
381 elements_.reserve(s);
382 }
383 virtual ~Hashed();
384 size_t length() const { return _keys.size(); }
385 bool empty() const { return _keys.empty(); }
386 bool has(K k) const {
387 return elements_.find(k) != elements_.end();
388 }
389 T at(K k) const {
390 if (elements_.count(k))
391 {
392 return elements_.at(k);
393 }
394 else { return {}; }
395 }
396 bool has_duplicate_key() const { return duplicate_key_ != nullptr; }
397 K get_duplicate_key() const { return duplicate_key_; }
398 const std::unordered_map<
399 K, T, ObjHash, ObjEquality
400 >& elements() { return elements_; }
401 Hashed& operator<<(std::pair<K, T> p)
402 {
403 reset_hash();
404
405 if (!has(k: p.first)) {
406 _keys.push_back(p.first);
407 _values.push_back(p.second);
408 }
409 else if (!duplicate_key_) {
410 duplicate_key_ = p.first;
411 }
412
413 elements_[p.first] = p.second;
414
415 adjust_after_pushing(p);
416 return *this;
417 }
418 Hashed& operator+=(Hashed* h)
419 {
420 if (length() == 0) {
421 this->elements_ = h->elements_;
422 this->_values = h->_values;
423 this->_keys = h->_keys;
424 return *this;
425 }
426
427 for (auto key : h->keys()) {
428 *this << std::make_pair(key, h->at(key));
429 }
430
431 reset_duplicate_key();
432 return *this;
433 }
434 const std::unordered_map<
435 K, T, ObjHash, ObjEquality
436 >& pairs() const { return elements_; }
437
438 const sass::vector<K>& keys() const { return _keys; }
439 const sass::vector<T>& values() const { return _values; }
440
441// std::unordered_map<ExpressionObj, ExpressionObj>::iterator end() { return elements_.end(); }
442// std::unordered_map<ExpressionObj, ExpressionObj>::iterator begin() { return elements_.begin(); }
443// std::unordered_map<ExpressionObj, ExpressionObj>::const_iterator end() const { return elements_.end(); }
444// std::unordered_map<ExpressionObj, ExpressionObj>::const_iterator begin() const { return elements_.begin(); }
445
446 };
447 template <typename K, typename T, typename U>
448 inline Hashed<K, T, U>::~Hashed() { }
449
450 /////////////////////////////////////////////////////////////////////////
451 // Abstract base class for statements. This side of the AST hierarchy
452 // represents elements in expansion contexts, which exist primarily to be
453 // rewritten and macro-expanded.
454 /////////////////////////////////////////////////////////////////////////
455 class Statement : public AST_Node {
456 public:
457 enum Type {
458 NONE,
459 RULESET,
460 MEDIA,
461 DIRECTIVE,
462 SUPPORTS,
463 ATROOT,
464 BUBBLE,
465 CONTENT,
466 KEYFRAMERULE,
467 DECLARATION,
468 ASSIGNMENT,
469 IMPORT_STUB,
470 IMPORT,
471 COMMENT,
472 WARNING,
473 RETURN,
474 EXTEND,
475 ERROR,
476 DEBUGSTMT,
477 WHILE,
478 EACH,
479 FOR,
480 IF
481 };
482 private:
483 ADD_PROPERTY(Type, statement_type)
484 ADD_PROPERTY(size_t, tabs)
485 ADD_PROPERTY(bool, group_end)
486 public:
487 Statement(SourceSpan pstate, Type st = NONE, size_t t = 0);
488 virtual ~Statement() = 0; // virtual destructor
489 // needed for rearranging nested rulesets during CSS emission
490 virtual bool bubbles();
491 virtual bool has_content();
492 virtual bool is_invisible() const;
493 ATTACH_VIRTUAL_AST_OPERATIONS(Statement)
494 };
495 inline Statement::~Statement() { }
496
497 ////////////////////////
498 // Blocks of statements.
499 ////////////////////////
500 class Block final : public Statement, public Vectorized<Statement_Obj> {
501 ADD_PROPERTY(bool, is_root)
502 // needed for properly formatted CSS emission
503 protected:
504 void adjust_after_pushing(Statement_Obj s) override {}
505 public:
506 Block(SourceSpan pstate, size_t s = 0, bool r = false);
507 bool isInvisible() const;
508 bool has_content() override;
509 ATTACH_AST_OPERATIONS(Block)
510 ATTACH_CRTP_PERFORM_METHODS()
511 };
512
513 ////////////////////////////////////////////////////////////////////////
514 // Abstract base class for statements that contain blocks of statements.
515 ////////////////////////////////////////////////////////////////////////
516 class ParentStatement : public Statement {
517 ADD_PROPERTY(Block_Obj, block)
518 public:
519 ParentStatement(SourceSpan pstate, Block_Obj b);
520 ParentStatement(const ParentStatement* ptr); // copy constructor
521 virtual ~ParentStatement() = 0; // virtual destructor
522 virtual bool has_content() override;
523 };
524 inline ParentStatement::~ParentStatement() { }
525
526 /////////////////////////////////////////////////////////////////////////////
527 // Rulesets (i.e., sets of styles headed by a selector and containing a block
528 // of style declarations.
529 /////////////////////////////////////////////////////////////////////////////
530 class StyleRule final : public ParentStatement {
531 ADD_PROPERTY(SelectorListObj, selector)
532 ADD_PROPERTY(Selector_Schema_Obj, schema)
533 ADD_PROPERTY(bool, is_root);
534 public:
535 StyleRule(SourceSpan pstate, SelectorListObj s = {}, Block_Obj b = {});
536 bool is_invisible() const override;
537 ATTACH_AST_OPERATIONS(StyleRule)
538 ATTACH_CRTP_PERFORM_METHODS()
539 };
540
541 /////////////////
542 // Bubble.
543 /////////////////
544 class Bubble final : public Statement {
545 ADD_PROPERTY(Statement_Obj, node)
546 ADD_PROPERTY(bool, group_end)
547 public:
548 Bubble(SourceSpan pstate, Statement_Obj n, Statement_Obj g = {}, size_t t = 0);
549 bool bubbles() override;
550 ATTACH_AST_OPERATIONS(Bubble)
551 ATTACH_CRTP_PERFORM_METHODS()
552 };
553
554 /////////////////
555 // Trace.
556 /////////////////
557 class Trace final : public ParentStatement {
558 ADD_CONSTREF(char, type)
559 ADD_CONSTREF(sass::string, name)
560 public:
561 Trace(SourceSpan pstate, sass::string n, Block_Obj b = {}, char type = 'm');
562 ATTACH_AST_OPERATIONS(Trace)
563 ATTACH_CRTP_PERFORM_METHODS()
564 };
565
566 ///////////////////////////////////////////////////////////////////////
567 // At-rules -- arbitrary directives beginning with "@" that may have an
568 // optional statement block.
569 ///////////////////////////////////////////////////////////////////////
570 class AtRule final : public ParentStatement {
571 ADD_CONSTREF(sass::string, keyword)
572 ADD_PROPERTY(SelectorListObj, selector)
573 ADD_PROPERTY(ExpressionObj, value)
574 public:
575 AtRule(SourceSpan pstate, sass::string kwd, SelectorListObj sel = {}, Block_Obj b = {}, ExpressionObj val = {});
576 bool bubbles() override;
577 bool is_media();
578 bool is_keyframes();
579 ATTACH_AST_OPERATIONS(AtRule)
580 ATTACH_CRTP_PERFORM_METHODS()
581 };
582
583 ///////////////////////////////////////////////////////////////////////
584 // Keyframe-rules -- the child blocks of "@keyframes" nodes.
585 ///////////////////////////////////////////////////////////////////////
586 class Keyframe_Rule final : public ParentStatement {
587 // according to css spec, this should be <keyframes-name>
588 // <keyframes-name> = <custom-ident> | <string>
589 ADD_PROPERTY(SelectorListObj, name)
590 public:
591 Keyframe_Rule(SourceSpan pstate, Block_Obj b);
592 ATTACH_AST_OPERATIONS(Keyframe_Rule)
593 ATTACH_CRTP_PERFORM_METHODS()
594 };
595
596 ////////////////////////////////////////////////////////////////////////
597 // Declarations -- style rules consisting of a property name and values.
598 ////////////////////////////////////////////////////////////////////////
599 class Declaration final : public ParentStatement {
600 ADD_PROPERTY(String_Obj, property)
601 ADD_PROPERTY(ExpressionObj, value)
602 ADD_PROPERTY(bool, is_important)
603 ADD_PROPERTY(bool, is_custom_property)
604 ADD_PROPERTY(bool, is_indented)
605 public:
606 Declaration(SourceSpan pstate, String_Obj prop, ExpressionObj val, bool i = false, bool c = false, Block_Obj b = {});
607 bool is_invisible() const override;
608 ATTACH_AST_OPERATIONS(Declaration)
609 ATTACH_CRTP_PERFORM_METHODS()
610 };
611
612 /////////////////////////////////////
613 // Assignments -- variable and value.
614 /////////////////////////////////////
615 class Assignment final : public Statement {
616 ADD_CONSTREF(sass::string, variable)
617 ADD_PROPERTY(ExpressionObj, value)
618 ADD_PROPERTY(bool, is_default)
619 ADD_PROPERTY(bool, is_global)
620 public:
621 Assignment(SourceSpan pstate, sass::string var, ExpressionObj val, bool is_default = false, bool is_global = false);
622 ATTACH_AST_OPERATIONS(Assignment)
623 ATTACH_CRTP_PERFORM_METHODS()
624 };
625
626 ////////////////////////////////////////////////////////////////////////////
627 // Import directives. CSS and Sass import lists can be intermingled, so it's
628 // necessary to store a list of each in an Import node.
629 ////////////////////////////////////////////////////////////////////////////
630 class Import final : public Statement {
631 sass::vector<ExpressionObj> urls_;
632 sass::vector<Include> incs_;
633 ADD_PROPERTY(List_Obj, import_queries);
634 public:
635 Import(SourceSpan pstate);
636 sass::vector<Include>& incs();
637 sass::vector<ExpressionObj>& urls();
638 ATTACH_AST_OPERATIONS(Import)
639 ATTACH_CRTP_PERFORM_METHODS()
640 };
641
642 // not yet resolved single import
643 // so far we only know requested name
644 class Import_Stub final : public Statement {
645 Include resource_;
646 public:
647 Import_Stub(SourceSpan pstate, Include res);
648 Include resource();
649 sass::string imp_path();
650 sass::string abs_path();
651 ATTACH_AST_OPERATIONS(Import_Stub)
652 ATTACH_CRTP_PERFORM_METHODS()
653 };
654
655 //////////////////////////////
656 // The Sass `@warn` directive.
657 //////////////////////////////
658 class WarningRule final : public Statement {
659 ADD_PROPERTY(ExpressionObj, message)
660 public:
661 WarningRule(SourceSpan pstate, ExpressionObj msg);
662 ATTACH_AST_OPERATIONS(WarningRule)
663 ATTACH_CRTP_PERFORM_METHODS()
664 };
665
666 ///////////////////////////////
667 // The Sass `@error` directive.
668 ///////////////////////////////
669 class ErrorRule final : public Statement {
670 ADD_PROPERTY(ExpressionObj, message)
671 public:
672 ErrorRule(SourceSpan pstate, ExpressionObj msg);
673 ATTACH_AST_OPERATIONS(ErrorRule)
674 ATTACH_CRTP_PERFORM_METHODS()
675 };
676
677 ///////////////////////////////
678 // The Sass `@debug` directive.
679 ///////////////////////////////
680 class DebugRule final : public Statement {
681 ADD_PROPERTY(ExpressionObj, value)
682 public:
683 DebugRule(SourceSpan pstate, ExpressionObj val);
684 ATTACH_AST_OPERATIONS(DebugRule)
685 ATTACH_CRTP_PERFORM_METHODS()
686 };
687
688 ///////////////////////////////////////////
689 // CSS comments. These may be interpolated.
690 ///////////////////////////////////////////
691 class Comment final : public Statement {
692 ADD_PROPERTY(String_Obj, text)
693 ADD_PROPERTY(bool, is_important)
694 public:
695 Comment(SourceSpan pstate, String_Obj txt, bool is_important);
696 virtual bool is_invisible() const override;
697 ATTACH_AST_OPERATIONS(Comment)
698 ATTACH_CRTP_PERFORM_METHODS()
699 };
700
701 ////////////////////////////////////
702 // The Sass `@if` control directive.
703 ////////////////////////////////////
704 class If final : public ParentStatement {
705 ADD_PROPERTY(ExpressionObj, predicate)
706 ADD_PROPERTY(Block_Obj, alternative)
707 public:
708 If(SourceSpan pstate, ExpressionObj pred, Block_Obj con, Block_Obj alt = {});
709 virtual bool has_content() override;
710 ATTACH_AST_OPERATIONS(If)
711 ATTACH_CRTP_PERFORM_METHODS()
712 };
713
714 /////////////////////////////////////
715 // The Sass `@for` control directive.
716 /////////////////////////////////////
717 class ForRule final : public ParentStatement {
718 ADD_CONSTREF(sass::string, variable)
719 ADD_PROPERTY(ExpressionObj, lower_bound)
720 ADD_PROPERTY(ExpressionObj, upper_bound)
721 ADD_PROPERTY(bool, is_inclusive)
722 public:
723 ForRule(SourceSpan pstate, sass::string var, ExpressionObj lo, ExpressionObj hi, Block_Obj b, bool inc);
724 ATTACH_AST_OPERATIONS(ForRule)
725 ATTACH_CRTP_PERFORM_METHODS()
726 };
727
728 //////////////////////////////////////
729 // The Sass `@each` control directive.
730 //////////////////////////////////////
731 class EachRule final : public ParentStatement {
732 ADD_PROPERTY(sass::vector<sass::string>, variables)
733 ADD_PROPERTY(ExpressionObj, list)
734 public:
735 EachRule(SourceSpan pstate, sass::vector<sass::string> vars, ExpressionObj lst, Block_Obj b);
736 ATTACH_AST_OPERATIONS(EachRule)
737 ATTACH_CRTP_PERFORM_METHODS()
738 };
739
740 ///////////////////////////////////////
741 // The Sass `@while` control directive.
742 ///////////////////////////////////////
743 class WhileRule final : public ParentStatement {
744 ADD_PROPERTY(ExpressionObj, predicate)
745 public:
746 WhileRule(SourceSpan pstate, ExpressionObj pred, Block_Obj b);
747 ATTACH_AST_OPERATIONS(WhileRule)
748 ATTACH_CRTP_PERFORM_METHODS()
749 };
750
751 /////////////////////////////////////////////////////////////
752 // The @return directive for use inside SassScript functions.
753 /////////////////////////////////////////////////////////////
754 class Return final : public Statement {
755 ADD_PROPERTY(ExpressionObj, value)
756 public:
757 Return(SourceSpan pstate, ExpressionObj val);
758 ATTACH_AST_OPERATIONS(Return)
759 ATTACH_CRTP_PERFORM_METHODS()
760 };
761
762 /////////////////////////////////////////////////////////////////////////////
763 // Definitions for both mixins and functions. The two cases are distinguished
764 // by a type tag.
765 /////////////////////////////////////////////////////////////////////////////
766 class Definition final : public ParentStatement {
767 public:
768 enum Type { MIXIN, FUNCTION };
769 ADD_CONSTREF(sass::string, name)
770 ADD_PROPERTY(Parameters_Obj, parameters)
771 ADD_PROPERTY(Env*, environment)
772 ADD_PROPERTY(Type, type)
773 ADD_PROPERTY(Native_Function, native_function)
774 ADD_PROPERTY(Sass_Function_Entry, c_function)
775 ADD_PROPERTY(void*, cookie)
776 ADD_PROPERTY(bool, is_overload_stub)
777 ADD_PROPERTY(Signature, signature)
778 public:
779 Definition(SourceSpan pstate,
780 sass::string n,
781 Parameters_Obj params,
782 Block_Obj b,
783 Type t);
784 Definition(SourceSpan pstate,
785 Signature sig,
786 sass::string n,
787 Parameters_Obj params,
788 Native_Function func_ptr,
789 bool overload_stub = false);
790 Definition(SourceSpan pstate,
791 Signature sig,
792 sass::string n,
793 Parameters_Obj params,
794 Sass_Function_Entry c_func);
795 ATTACH_AST_OPERATIONS(Definition)
796 ATTACH_CRTP_PERFORM_METHODS()
797 };
798
799 //////////////////////////////////////
800 // Mixin calls (i.e., `@include ...`).
801 //////////////////////////////////////
802 class Mixin_Call final : public ParentStatement {
803 ADD_CONSTREF(sass::string, name)
804 ADD_PROPERTY(Arguments_Obj, arguments)
805 ADD_PROPERTY(Parameters_Obj, block_parameters)
806 public:
807 Mixin_Call(SourceSpan pstate, sass::string n, Arguments_Obj args, Parameters_Obj b_params = {}, Block_Obj b = {});
808 ATTACH_AST_OPERATIONS(Mixin_Call)
809 ATTACH_CRTP_PERFORM_METHODS()
810 };
811
812 ///////////////////////////////////////////////////
813 // The @content directive for mixin content blocks.
814 ///////////////////////////////////////////////////
815 class Content final : public Statement {
816 ADD_PROPERTY(Arguments_Obj, arguments)
817 public:
818 Content(SourceSpan pstate, Arguments_Obj args);
819 ATTACH_AST_OPERATIONS(Content)
820 ATTACH_CRTP_PERFORM_METHODS()
821 };
822
823 ////////////////////////////////////////////////////////////////////////////
824 // Arithmetic negation (logical negation is just an ordinary function call).
825 ////////////////////////////////////////////////////////////////////////////
826 class Unary_Expression final : public Expression {
827 public:
828 enum Type { PLUS, MINUS, NOT, SLASH };
829 private:
830 HASH_PROPERTY(Type, optype)
831 HASH_PROPERTY(ExpressionObj, operand)
832 mutable size_t hash_;
833 public:
834 Unary_Expression(SourceSpan pstate, Type t, ExpressionObj o);
835 const sass::string type_name();
836 virtual bool operator==(const Expression& rhs) const override;
837 size_t hash() const override;
838 ATTACH_AST_OPERATIONS(Unary_Expression)
839 ATTACH_CRTP_PERFORM_METHODS()
840 };
841
842 ////////////////////////////////////////////////////////////
843 // Individual argument objects for mixin and function calls.
844 ////////////////////////////////////////////////////////////
845 class Argument final : public Expression {
846 HASH_PROPERTY(ExpressionObj, value)
847 HASH_CONSTREF(sass::string, name)
848 ADD_PROPERTY(bool, is_rest_argument)
849 ADD_PROPERTY(bool, is_keyword_argument)
850 mutable size_t hash_;
851 public:
852 Argument(SourceSpan pstate, ExpressionObj val, sass::string n = "", bool rest = false, bool keyword = false);
853 void set_delayed(bool delayed) override;
854 bool operator==(const Expression& rhs) const override;
855 size_t hash() const override;
856 ATTACH_AST_OPERATIONS(Argument)
857 ATTACH_CRTP_PERFORM_METHODS()
858 };
859
860 ////////////////////////////////////////////////////////////////////////
861 // Argument lists -- in their own class to facilitate context-sensitive
862 // error checking (e.g., ensuring that all ordinal arguments precede all
863 // named arguments).
864 ////////////////////////////////////////////////////////////////////////
865 class Arguments final : public Expression, public Vectorized<Argument_Obj> {
866 ADD_PROPERTY(bool, has_named_arguments)
867 ADD_PROPERTY(bool, has_rest_argument)
868 ADD_PROPERTY(bool, has_keyword_argument)
869 protected:
870 void adjust_after_pushing(Argument_Obj a) override;
871 public:
872 Arguments(SourceSpan pstate);
873 void set_delayed(bool delayed) override;
874 Argument_Obj get_rest_argument();
875 Argument_Obj get_keyword_argument();
876 ATTACH_AST_OPERATIONS(Arguments)
877 ATTACH_CRTP_PERFORM_METHODS()
878 };
879
880
881 // A Media StyleRule before it has been evaluated
882 // Could be already final or an interpolation
883 class MediaRule final : public ParentStatement {
884 ADD_PROPERTY(List_Obj, schema)
885 public:
886 MediaRule(SourceSpan pstate, Block_Obj block = {});
887
888 bool bubbles() override { return true; };
889 bool is_invisible() const override { return false; };
890 ATTACH_AST_OPERATIONS(MediaRule)
891 ATTACH_CRTP_PERFORM_METHODS()
892 };
893
894 // A Media StyleRule after it has been evaluated
895 // Representing the static or resulting css
896 class CssMediaRule final : public ParentStatement,
897 public Vectorized<CssMediaQuery_Obj> {
898 public:
899 CssMediaRule(SourceSpan pstate, Block_Obj b);
900 bool bubbles() override { return true; };
901 bool isInvisible() const { return empty(); }
902 bool is_invisible() const override { return false; };
903
904 public:
905 // Hash and equality implemtation from vector
906 size_t hash() const override { return Vectorized::hash(); }
907 // Check if two instances are considered equal
908 bool operator== (const CssMediaRule& rhs) const {
909 return Vectorized::operator== (rhs);
910 }
911 bool operator!=(const CssMediaRule& rhs) const {
912 // Invert from equality
913 return !(*this == rhs);
914 }
915
916 ATTACH_AST_OPERATIONS(CssMediaRule)
917 ATTACH_CRTP_PERFORM_METHODS()
918 };
919
920 // Media Queries after they have been evaluated
921 // Representing the static or resulting css
922 class CssMediaQuery final : public AST_Node {
923
924 // The modifier, probably either "not" or "only".
925 // This may be `null` if no modifier is in use.
926 ADD_PROPERTY(sass::string, modifier);
927
928 // The media type, for example "screen" or "print".
929 // This may be `null`. If so, [features] will not be empty.
930 ADD_PROPERTY(sass::string, type);
931
932 // Feature queries, including parentheses.
933 ADD_PROPERTY(sass::vector<sass::string>, features);
934
935 public:
936 CssMediaQuery(SourceSpan pstate);
937
938 // Check if two instances are considered equal
939 bool operator== (const CssMediaQuery& rhs) const;
940 bool operator!=(const CssMediaQuery& rhs) const {
941 // Invert from equality
942 return !(*this == rhs);
943 }
944
945 // Returns true if this query is empty
946 // Meaning it has no type and features
947 bool empty() const {
948 return type_.empty()
949 && modifier_.empty()
950 && features_.empty();
951 }
952
953 // Whether this media query matches all media types.
954 bool matchesAllTypes() const {
955 return type_.empty() || Util::equalsLiteral(lit: "all", test: type_);
956 }
957
958 // Merges this with [other] and adds a query that matches the intersection
959 // of both inputs to [result]. Returns false if the result is unrepresentable
960 CssMediaQuery_Obj merge(CssMediaQuery_Obj& other);
961
962 ATTACH_AST_OPERATIONS(CssMediaQuery)
963 ATTACH_CRTP_PERFORM_METHODS()
964 };
965
966 ////////////////////////////////////////////////////
967 // Media queries (replaced by MediaRule at al).
968 // ToDo: only used for interpolation case
969 ////////////////////////////////////////////////////
970 class Media_Query final : public Expression,
971 public Vectorized<Media_Query_ExpressionObj> {
972 ADD_PROPERTY(String_Obj, media_type)
973 ADD_PROPERTY(bool, is_negated)
974 ADD_PROPERTY(bool, is_restricted)
975 public:
976 Media_Query(SourceSpan pstate, String_Obj t = {}, size_t s = 0, bool n = false, bool r = false);
977 ATTACH_AST_OPERATIONS(Media_Query)
978 ATTACH_CRTP_PERFORM_METHODS()
979 };
980
981 ////////////////////////////////////////////////////
982 // Media expressions (for use inside media queries).
983 // ToDo: only used for interpolation case
984 ////////////////////////////////////////////////////
985 class Media_Query_Expression final : public Expression {
986 ADD_PROPERTY(ExpressionObj, feature)
987 ADD_PROPERTY(ExpressionObj, value)
988 ADD_PROPERTY(bool, is_interpolated)
989 public:
990 Media_Query_Expression(SourceSpan pstate, ExpressionObj f, ExpressionObj v, bool i = false);
991 ATTACH_AST_OPERATIONS(Media_Query_Expression)
992 ATTACH_CRTP_PERFORM_METHODS()
993 };
994
995 /////////////////////////////////////////////////
996 // At root expressions (for use inside @at-root).
997 /////////////////////////////////////////////////
998 class At_Root_Query final : public Expression {
999 private:
1000 ADD_PROPERTY(ExpressionObj, feature)
1001 ADD_PROPERTY(ExpressionObj, value)
1002 public:
1003 At_Root_Query(SourceSpan pstate, ExpressionObj f = {}, ExpressionObj v = {}, bool i = false);
1004 bool exclude(sass::string str);
1005 ATTACH_AST_OPERATIONS(At_Root_Query)
1006 ATTACH_CRTP_PERFORM_METHODS()
1007 };
1008
1009 ///////////
1010 // At-root.
1011 ///////////
1012 class AtRootRule final : public ParentStatement {
1013 ADD_PROPERTY(At_Root_Query_Obj, expression)
1014 public:
1015 AtRootRule(SourceSpan pstate, Block_Obj b = {}, At_Root_Query_Obj e = {});
1016 bool bubbles() override;
1017 bool exclude_node(Statement_Obj s);
1018 ATTACH_AST_OPERATIONS(AtRootRule)
1019 ATTACH_CRTP_PERFORM_METHODS()
1020 };
1021
1022 /////////////////////////////////////////////////////////
1023 // Individual parameter objects for mixins and functions.
1024 /////////////////////////////////////////////////////////
1025 class Parameter final : public AST_Node {
1026 ADD_CONSTREF(sass::string, name)
1027 ADD_PROPERTY(ExpressionObj, default_value)
1028 ADD_PROPERTY(bool, is_rest_parameter)
1029 public:
1030 Parameter(SourceSpan pstate, sass::string n, ExpressionObj def = {}, bool rest = false);
1031 ATTACH_AST_OPERATIONS(Parameter)
1032 ATTACH_CRTP_PERFORM_METHODS()
1033 };
1034
1035 /////////////////////////////////////////////////////////////////////////
1036 // Parameter lists -- in their own class to facilitate context-sensitive
1037 // error checking (e.g., ensuring that all optional parameters follow all
1038 // required parameters).
1039 /////////////////////////////////////////////////////////////////////////
1040 class Parameters final : public AST_Node, public Vectorized<Parameter_Obj> {
1041 ADD_PROPERTY(bool, has_optional_parameters)
1042 ADD_PROPERTY(bool, has_rest_parameter)
1043 protected:
1044 void adjust_after_pushing(Parameter_Obj p) override;
1045 public:
1046 Parameters(SourceSpan pstate);
1047 ATTACH_AST_OPERATIONS(Parameters)
1048 ATTACH_CRTP_PERFORM_METHODS()
1049 };
1050
1051}
1052
1053#include "ast_values.hpp"
1054#include "ast_supports.hpp"
1055#include "ast_selectors.hpp"
1056
1057#ifdef __clang__
1058
1059// #pragma clang diagnostic pop
1060// #pragma clang diagnostic push
1061
1062#endif
1063
1064#endif
1065

source code of gtk/subprojects/libsass/src/ast.hpp