diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000..78fdb708a7 --- /dev/null +++ b/.clang-format @@ -0,0 +1,48 @@ +AccessModifierOffset: 0 +AlignEscapedNewlinesLeft: true +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortFunctionsOnASingleLine: false +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: false +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackParameters: false +BreakBeforeBinaryOperators: false +BreakBeforeBraces: Allman +BreakBeforeTernaryOperators: false +BreakConstructorInitializersBeforeComma: false +ColumnLimit: 100 +CommentPragmas: '' +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 0 +ContinuationIndentWidth: 0 +Cpp11BracedListStyle: false +DerivePointerBinding: false +IndentCaseLabels: false +IndentFunctionDeclarationAfterType: false +IndentWidth: 2 +Language: Cpp +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: All +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true +PenaltyBreakBeforeFirstCallParameter: 100 +PenaltyBreakComment: 100 +PenaltyBreakFirstLessLess: 0 +PenaltyBreakString: 100 +PenaltyExcessCharacter: 1 +PenaltyReturnTypeOnItsOwnLine: 20 +PointerBindsToType: true +SortIncludes: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: false +SpacesInParentheses: false +Standard: Cpp11 +TabWidth: 2 +UseTab: Never diff --git a/contrib/plugin.cpp b/contrib/plugin.cpp index 2f67bb3714..8087b3b43b 100644 --- a/contrib/plugin.cpp +++ b/contrib/plugin.cpp @@ -6,7 +6,8 @@ // gcc: g++ -shared plugin.cpp -o plugin.so -fPIC -Llib -lsass // mingw: g++ -shared plugin.cpp -o plugin.dll -Llib -lsass -extern "C" const char* ADDCALL libsass_get_version() { +extern "C" const char* ADDCALL libsass_get_version() +{ return libsass_version(); } @@ -24,8 +25,7 @@ union Sass_Value* custom_function(const union Sass_Value* s_args, Sass_Function_ extern "C" Sass_Function_List ADDCALL libsass_load_functions() { // allocate a custom function caller - Sass_Function_Entry c_func = - sass_make_function("foo()", custom_function, (void*)42); + Sass_Function_Entry c_func = sass_make_function("foo()", custom_function, (void*)42); // create list of all custom functions Sass_Function_List fn_list = sass_make_function_list(1); // put the only function in this plugin to the list @@ -49,8 +49,7 @@ Sass_Import_List custom_importer(const char* cur_path, Sass_Importer_Entry cb, s extern "C" Sass_Importer_List ADDCALL libsass_load_importers() { // allocate a custom function caller - Sass_Importer_Entry c_imp = - sass_make_importer(custom_importer, - 99, (void*)42); + Sass_Importer_Entry c_imp = sass_make_importer(custom_importer, -99, (void*)42); // create list of all custom functions Sass_Importer_List imp_list = sass_make_importer_list(1); // put the only function in this plugin to the list diff --git a/src/ast.cpp b/src/ast.cpp index 7c42717a5c..468a0a9940 100644 --- a/src/ast.cpp +++ b/src/ast.cpp @@ -15,25 +15,28 @@ #include #include -namespace Sass { +namespace Sass +{ static Null sass_null(ParserState("null")); - bool Supports_Operator::needs_parens(Supports_Condition_Obj cond) const { - if (Supports_Operator_Obj op = Cast(cond)) { + bool Supports_Operator::needs_parens(Supports_Condition_Obj cond) const + { + if (Supports_Operator_Obj op = Cast(cond)) + { return op->operand() != operand(); } return Cast(cond) != NULL; } - bool Supports_Negation::needs_parens(Supports_Condition_Obj cond) const { - return Cast(cond) || - Cast(cond); + bool Supports_Negation::needs_parens(Supports_Condition_Obj cond) const + { + return Cast(cond) || Cast(cond); } void str_rtrim(std::string& str, const std::string& delimiters = " \f\n\r\t\v") { - str.erase( str.find_last_not_of( delimiters ) + 1 ); + str.erase(str.find_last_not_of(delimiters) + 1); } void String_Constant::rtrim() @@ -43,7 +46,8 @@ namespace Sass { void String_Schema::rtrim() { - if (!empty()) { + if (!empty()) + { if (String_Ptr str = Cast(last())) str->rtrim(); } } @@ -56,7 +60,8 @@ namespace Sass { void Arguments::set_delayed(bool delayed) { - for (Argument_Obj arg : elements()) { + for (Argument_Obj arg : elements()) + { if (arg) arg->set_delayed(delayed); } is_delayed(delayed); @@ -99,29 +104,35 @@ namespace Sass { bool Simple_Selector::is_ns_eq(const Simple_Selector& r) const { // https://github.com/sass/sass/issues/2229 - if ((has_ns_ == r.has_ns_) || - (has_ns_ && ns_.empty()) || - (r.has_ns_ && r.ns_.empty()) - ) { - if (ns_.empty() && r.ns() == "*") return false; - else if (r.ns().empty() && ns() == "*") return false; - else return ns() == r.ns(); + if ((has_ns_ == r.has_ns_) || (has_ns_ && ns_.empty()) || (r.has_ns_ && r.ns_.empty())) + { + if (ns_.empty() && r.ns() == "*") + return false; + else if (r.ns().empty() && ns() == "*") + return false; + else + return ns() == r.ns(); } return false; } - bool Compound_Selector::operator< (const Compound_Selector& rhs) const + bool Compound_Selector::operator<(const Compound_Selector& rhs) const { size_t L = std::min(length(), rhs.length()); for (size_t i = 0; i < L; ++i) { Simple_Selector_Obj l = (*this)[i]; Simple_Selector_Obj r = rhs[i]; - if (!l && !r) return false; - else if (!r) return false; - else if (!l) return true; + if (!l && !r) + return false; + else if (!r) + return false; + else if (!l) + return true; else if (*l != *r) - { return *l < *r; } + { + return *l < *r; + } } // just compare the length now return length() < rhs.length(); @@ -129,7 +140,8 @@ namespace Sass { bool Compound_Selector::has_parent_ref() const { - for (Simple_Selector_Obj s : *this) { + for (Simple_Selector_Obj s : *this) + { if (s && s->has_parent_ref()) return true; } return false; @@ -137,7 +149,8 @@ namespace Sass { bool Compound_Selector::has_real_parent_ref() const { - for (Simple_Selector_Obj s : *this) { + for (Simple_Selector_Obj s : *this) + { if (s && s->has_real_parent_ref()) return true; } return false; @@ -145,17 +158,15 @@ namespace Sass { bool Complex_Selector::has_parent_ref() const { - return (head() && head()->has_parent_ref()) || - (tail() && tail()->has_parent_ref()); + return (head() && head()->has_parent_ref()) || (tail() && tail()->has_parent_ref()); } bool Complex_Selector::has_real_parent_ref() const { - return (head() && head()->has_real_parent_ref()) || - (tail() && tail()->has_real_parent_ref()); + return (head() && head()->has_real_parent_ref()) || (tail() && tail()->has_real_parent_ref()); } - bool Complex_Selector::operator< (const Complex_Selector& rhs) const + bool Complex_Selector::operator<(const Complex_Selector& rhs) const { // const iterators for tails Complex_Selector_Ptr_Const l = this; @@ -167,13 +178,13 @@ namespace Sass { // process all tails while (true) { - #ifdef DEBUG +#ifdef DEBUG // skip empty ancestor first if (l && l->is_empty_ancestor()) { l_h = NULL; l = l->tail(); - if(l) l_h = l->head(); + if (l) l_h = l->head(); continue; } // skip empty ancestor first @@ -184,7 +195,7 @@ namespace Sass { if (r) r_h = r->head(); continue; } - #endif +#endif // check for valid selectors if (!l) return !!r; if (!r) return false; @@ -193,38 +204,47 @@ namespace Sass { { // check combinator after heads if (l->combinator() != r->combinator()) - { return l->combinator() < r->combinator(); } + { + return l->combinator() < r->combinator(); + } // advance to next tails l = l->tail(); r = r->tail(); // fetch the next headers - l_h = NULL; r_h = NULL; + l_h = NULL; + r_h = NULL; if (l) l_h = l->head(); if (r) r_h = r->head(); } // one side is null - else if (!r_h) return true; - else if (!l_h) return false; + else if (!r_h) + return true; + else if (!l_h) + return false; // heads ok and equal else if (*l_h == *r_h) { // check combinator after heads if (l->combinator() != r->combinator()) - { return l->combinator() < r->combinator(); } + { + return l->combinator() < r->combinator(); + } // advance to next tails l = l->tail(); r = r->tail(); // fetch the next headers - l_h = NULL; r_h = NULL; + l_h = NULL; + r_h = NULL; if (l) l_h = l->head(); if (r) r_h = r->head(); } // heads are not equal - else return *l_h < *r_h; + else + return *l_h < *r_h; } } - bool Complex_Selector::operator== (const Complex_Selector& rhs) const + bool Complex_Selector::operator==(const Complex_Selector& rhs) const { // const iterators for tails Complex_Selector_Ptr_Const l = this; @@ -236,7 +256,7 @@ namespace Sass { // process all tails while (true) { - #ifdef DEBUG +#ifdef DEBUG // skip empty ancestor first if (l && l->is_empty_ancestor()) { @@ -253,7 +273,7 @@ namespace Sass { if (r) r_h = r->head(); continue; } - #endif +#endif // check the pointers if (!r) return !l; if (!l) return !r; @@ -262,34 +282,39 @@ namespace Sass { { // check combinator after heads if (l->combinator() != r->combinator()) - { return l->combinator() < r->combinator(); } + { + return l->combinator() < r->combinator(); + } // advance to next tails l = l->tail(); r = r->tail(); // fetch the next heads - l_h = NULL; r_h = NULL; + l_h = NULL; + r_h = NULL; if (l) l_h = l->head(); if (r) r_h = r->head(); } // equals if other head is empty - else if ((!l_h && !r_h) || - (!l_h && r_h->empty()) || - (!r_h && l_h->empty()) || + else if ((!l_h && !r_h) || (!l_h && r_h->empty()) || (!r_h && l_h->empty()) || (l_h && r_h && *l_h == *r_h)) { // check combinator after heads if (l->combinator() != r->combinator()) - { return l->combinator() == r->combinator(); } + { + return l->combinator() == r->combinator(); + } // advance to next tails l = l->tail(); r = r->tail(); // fetch the next heads - l_h = NULL; r_h = NULL; + l_h = NULL; + r_h = NULL; if (l) l_h = l->head(); if (r) r_h = r->head(); } // abort - else break; + else + break; } // unreachable return false; @@ -307,7 +332,7 @@ namespace Sass { return unified.detach(); } - bool Complex_Selector::operator== (const Selector& rhs) const + bool Complex_Selector::operator==(const Selector& rhs) const { if (const Selector_List* sl = Cast(&rhs)) return *this == *sl; if (const Simple_Selector* sp = Cast(&rhs)) return *this == *sp; @@ -317,7 +342,7 @@ namespace Sass { } - bool Complex_Selector::operator< (const Selector& rhs) const + bool Complex_Selector::operator<(const Selector& rhs) const { if (const Selector_List* sl = Cast(&rhs)) return *this < *sl; if (const Simple_Selector* sp = Cast(&rhs)) return *this < *sp; @@ -326,7 +351,7 @@ namespace Sass { throw std::runtime_error("invalid selector base classes to compare"); } - bool Compound_Selector::operator== (const Selector& rhs) const + bool Compound_Selector::operator==(const Selector& rhs) const { if (const Selector_List* sl = Cast(&rhs)) return *this == *sl; if (const Simple_Selector* sp = Cast(&rhs)) return *this == *sp; @@ -335,7 +360,7 @@ namespace Sass { throw std::runtime_error("invalid selector base classes to compare"); } - bool Compound_Selector::operator< (const Selector& rhs) const + bool Compound_Selector::operator<(const Selector& rhs) const { if (const Selector_List* sl = Cast(&rhs)) return *this < *sl; if (const Simple_Selector* sp = Cast(&rhs)) return *this < *sp; @@ -344,7 +369,7 @@ namespace Sass { throw std::runtime_error("invalid selector base classes to compare"); } - bool Selector_Schema::operator== (const Selector& rhs) const + bool Selector_Schema::operator==(const Selector& rhs) const { if (const Selector_List* sl = Cast(&rhs)) return *this == *sl; if (const Simple_Selector* sp = Cast(&rhs)) return *this == *sp; @@ -353,7 +378,7 @@ namespace Sass { throw std::runtime_error("invalid selector base classes to compare"); } - bool Selector_Schema::operator< (const Selector& rhs) const + bool Selector_Schema::operator<(const Selector& rhs) const { if (const Selector_List* sl = Cast(&rhs)) return *this < *sl; if (const Simple_Selector* sp = Cast(&rhs)) return *this < *sp; @@ -362,46 +387,78 @@ namespace Sass { throw std::runtime_error("invalid selector base classes to compare"); } - bool Simple_Selector::operator== (const Selector& rhs) const + bool Simple_Selector::operator==(const Selector& rhs) const { if (Simple_Selector_Ptr_Const sp = Cast(&rhs)) return *this == *sp; return false; } - bool Simple_Selector::operator< (const Selector& rhs) const + bool Simple_Selector::operator<(const Selector& rhs) const { if (Simple_Selector_Ptr_Const sp = Cast(&rhs)) return *this < *sp; return false; } - bool Simple_Selector::operator== (const Simple_Selector& rhs) const + bool Simple_Selector::operator==(const Simple_Selector& rhs) const { // solve the double dispatch problem by using RTTI information via dynamic cast - if (const Pseudo_Selector* lhs = Cast(this)) {return *lhs == rhs; } - else if (const Wrapped_Selector* lhs = Cast(this)) {return *lhs == rhs; } - else if (const Attribute_Selector* lhs = Cast(this)) {return *lhs == rhs; } + if (const Pseudo_Selector* lhs = Cast(this)) + { + return *lhs == rhs; + } + else if (const Wrapped_Selector* lhs = Cast(this)) + { + return *lhs == rhs; + } + else if (const Attribute_Selector* lhs = Cast(this)) + { + return *lhs == rhs; + } else if (name_ == rhs.name_) - { return is_ns_eq(rhs); } - else return false; + { + return is_ns_eq(rhs); + } + else + return false; } - bool Simple_Selector::operator< (const Simple_Selector& rhs) const + bool Simple_Selector::operator<(const Simple_Selector& rhs) const { // solve the double dispatch problem by using RTTI information via dynamic cast - if (const Pseudo_Selector* lhs = Cast(this)) {return *lhs < rhs; } - else if (const Wrapped_Selector* lhs = Cast(this)) {return *lhs < rhs; } - else if (const Attribute_Selector* lhs = Cast(this)) {return *lhs < rhs; } + if (const Pseudo_Selector* lhs = Cast(this)) + { + return *lhs < rhs; + } + else if (const Wrapped_Selector* lhs = Cast(this)) + { + return *lhs < rhs; + } + else if (const Attribute_Selector* lhs = Cast(this)) + { + return *lhs < rhs; + } if (is_ns_eq(rhs)) - { return name_ < rhs.name_; } + { + return name_ < rhs.name_; + } return ns_ < rhs.ns_; } - bool Selector_List::operator== (const Selector& rhs) const + bool Selector_List::operator==(const Selector& rhs) const { // solve the double dispatch problem by using RTTI information via dynamic cast - if (Selector_List_Ptr_Const sl = Cast(&rhs)) { return *this == *sl; } - else if (Complex_Selector_Ptr_Const cpx = Cast(&rhs)) { return *this == *cpx; } - else if (Compound_Selector_Ptr_Const cpd = Cast(&rhs)) { return *this == *cpd; } + if (Selector_List_Ptr_Const sl = Cast(&rhs)) + { + return *this == *sl; + } + else if (Complex_Selector_Ptr_Const cpx = Cast(&rhs)) + { + return *this == *cpx; + } + else if (Compound_Selector_Ptr_Const cpd = Cast(&rhs)) + { + return *this == *cpd; + } // no compare method return this == &rhs; } @@ -410,13 +467,19 @@ namespace Sass { bool Selector_List::operator==(const Expression& rhs) const { // solve the double dispatch problem by using RTTI information via dynamic cast - if (List_Ptr_Const ls = Cast(&rhs)) { return *this == *ls; } - if (Selector_Ptr_Const ls = Cast(&rhs)) { return *this == *ls; } + if (List_Ptr_Const ls = Cast(&rhs)) + { + return *this == *ls; + } + if (Selector_Ptr_Const ls = Cast(&rhs)) + { + return *this == *ls; + } // compare invalid (maybe we should error?) return false; } - bool Selector_List::operator== (const Selector_List& rhs) const + bool Selector_List::operator==(const Selector_List& rhs) const { // for array access size_t i = 0, n = 0; @@ -431,34 +494,42 @@ namespace Sass { while (true) { // first check for valid index - if (i == iL) return iL == nL; - else if (n == nL) return iL == nL; + if (i == iL) + return iL == nL; + else if (n == nL) + return iL == nL; // the access the vector items Complex_Selector_Obj l = l_lst[i]; Complex_Selector_Obj r = r_lst[n]; // skip nulls - if (!l) ++i; - else if (!r) ++n; + if (!l) + ++i; + else if (!r) + ++n; // do the check else if (*l != *r) - { return false; } + { + return false; + } // advance - ++i; ++n; + ++i; + ++n; } // there is no break?! } - bool Selector_List::operator< (const Selector& rhs) const + bool Selector_List::operator<(const Selector& rhs) const { if (Selector_List_Ptr_Const sp = Cast(&rhs)) return *this < *sp; return false; } - bool Selector_List::operator< (const Selector_List& rhs) const + bool Selector_List::operator<(const Selector_List& rhs) const { size_t l = rhs.length(); if (length() < l) l = length(); - for (size_t i = 0; i < l; i ++) { + for (size_t i = 0; i < l; i++) + { if (*at(i) < *rhs.at(i)) return true; } return false; @@ -467,7 +538,9 @@ namespace Sass { Compound_Selector_Ptr Simple_Selector::unify_with(Compound_Selector_Ptr rhs) { for (size_t i = 0, L = rhs->length(); i < L; ++i) - { if (to_string() == rhs->at(i)->to_string()) return rhs; } + { + if (to_string() == rhs->at(i)->to_string()) return rhs; + } // check for pseudo elements because they are always last size_t i, L; @@ -476,8 +549,12 @@ namespace Sass { { for (i = 0, L = rhs->length(); i < L; ++i) { - if ((Cast((*rhs)[i]) || Cast((*rhs)[i])) && (*rhs)[L-1]->is_pseudo_element()) - { found = true; break; } + if ((Cast((*rhs)[i]) || Cast((*rhs)[i])) && + (*rhs)[L - 1]->is_pseudo_element()) + { + found = true; + break; + } } } else @@ -485,7 +562,10 @@ namespace Sass { for (i = 0, L = rhs->length(); i < L; ++i) { if (Cast((*rhs)[i]) || Cast((*rhs)[i])) - { found = true; break; } + { + found = true; + break; + } } } if (!found) @@ -508,9 +588,13 @@ namespace Sass { if (!rhs->is_universal_ns()) { // overwrite the name if star is given as name - if (this->name() == "*") { this->name(rhs->name()); } + if (this->name() == "*") + { + this->name(rhs->name()); + } // now overwrite the namespace name and flag - this->ns(rhs->ns()); this->has_ns(rhs->has_ns()); + this->ns(rhs->ns()); + this->has_ns(rhs->has_ns()); // return copy return this; } @@ -533,7 +617,8 @@ namespace Sass { // TODO: handle namespaces // if the rhs is empty, just return a copy of this - if (rhs->length() == 0) { + if (rhs->length() == 0) + { rhs->append(this); return rhs; } @@ -549,9 +634,11 @@ namespace Sass { rhs->at(0) = this->unify_with(ts); return rhs; } - else if (Cast(rhs_0) || Cast(rhs_0)) { + else if (Cast(rhs_0) || Cast(rhs_0)) + { // qualifier is `.class`, so we can prefix with `ns|*.class` - if (has_ns() && !rhs_0->has_ns()) { + if (has_ns() && !rhs_0->has_ns()) + { if (ns() != "*") rhs->elements().insert(rhs->begin(), this); } return rhs; @@ -568,7 +655,6 @@ namespace Sass { // otherwise create new compound and unify first simple selector rhs->at(0) = this->unify_with(rhs_0); return rhs; - } // else it's a tag name and a bunch of qualifiers -- just append them if (name() != "*") rhs->elements().insert(rhs->begin(), this); @@ -585,7 +671,8 @@ namespace Sass { { for (size_t i = 0, L = rhs->length(); i < L; ++i) { - if (Id_Selector_Ptr sel = Cast(rhs->at(i))) { + if (Id_Selector_Ptr sel = Cast(rhs->at(i))) + { if (sel->name() != name()) return 0; } } @@ -599,7 +686,8 @@ namespace Sass { { for (size_t i = 0, L = rhs->length(); i < L; ++i) { - if (Pseudo_Selector_Ptr sel = Cast(rhs->at(i))) { + if (Pseudo_Selector_Ptr sel = Cast(rhs->at(i))) + { if (sel->is_pseudo_element() && sel->name() != name()) return 0; } } @@ -607,147 +695,179 @@ namespace Sass { return Simple_Selector::unify_with(rhs); } - bool Attribute_Selector::operator< (const Attribute_Selector& rhs) const + bool Attribute_Selector::operator<(const Attribute_Selector& rhs) const { - if (is_ns_eq(rhs)) { - if (name() == rhs.name()) { - if (matcher() == rhs.matcher()) { + if (is_ns_eq(rhs)) + { + if (name() == rhs.name()) + { + if (matcher() == rhs.matcher()) + { bool no_lhs_val = value().isNull(); bool no_rhs_val = rhs.value().isNull(); - if (no_lhs_val && no_rhs_val) return false; // equal - else if (no_lhs_val) return true; // lhs is null - else if (no_rhs_val) return false; // rhs is null + if (no_lhs_val && no_rhs_val) + return false; // equal + else if (no_lhs_val) + return true; // lhs is null + else if (no_rhs_val) + return false; // rhs is null return *value() < *rhs.value(); // both are given - } else { return matcher() < rhs.matcher(); } - } else { return name() < rhs.name(); } - } else { return ns() < rhs.ns(); } + } + else + { + return matcher() < rhs.matcher(); + } + } + else + { + return name() < rhs.name(); + } + } + else + { + return ns() < rhs.ns(); + } } - bool Attribute_Selector::operator< (const Simple_Selector& rhs) const + bool Attribute_Selector::operator<(const Simple_Selector& rhs) const { if (Attribute_Selector_Ptr_Const w = Cast(&rhs)) { return *this < *w; } if (is_ns_eq(rhs)) - { return name() < rhs.name(); } + { + return name() < rhs.name(); + } return ns() < rhs.ns(); } - bool Attribute_Selector::operator== (const Attribute_Selector& rhs) const + bool Attribute_Selector::operator==(const Attribute_Selector& rhs) const { // get optional value state bool no_lhs_val = value().isNull(); bool no_rhs_val = rhs.value().isNull(); // both are null, therefore equal - if (no_lhs_val && no_rhs_val) { - return (name() == rhs.name()) - && (matcher() == rhs.matcher()) - && (is_ns_eq(rhs)); + if (no_lhs_val && no_rhs_val) + { + return (name() == rhs.name()) && (matcher() == rhs.matcher()) && (is_ns_eq(rhs)); } // both are defined, evaluate - if (no_lhs_val == no_rhs_val) { - return (name() == rhs.name()) - && (matcher() == rhs.matcher()) - && (is_ns_eq(rhs)) - && (*value() == *rhs.value()); + if (no_lhs_val == no_rhs_val) + { + return (name() == rhs.name()) && (matcher() == rhs.matcher()) && (is_ns_eq(rhs)) && + (*value() == *rhs.value()); } // not equal return false; - } - bool Attribute_Selector::operator== (const Simple_Selector& rhs) const + bool Attribute_Selector::operator==(const Simple_Selector& rhs) const { if (Attribute_Selector_Ptr_Const w = Cast(&rhs)) { return *this == *w; } - return is_ns_eq(rhs) && - name() == rhs.name(); + return is_ns_eq(rhs) && name() == rhs.name(); } - bool Pseudo_Selector::operator== (const Pseudo_Selector& rhs) const + bool Pseudo_Selector::operator==(const Pseudo_Selector& rhs) const { if (is_ns_eq(rhs) && name() == rhs.name()) { String_Obj lhs_ex = expression(); String_Obj rhs_ex = rhs.expression(); - if (rhs_ex && lhs_ex) return *lhs_ex == *rhs_ex; - else return lhs_ex.ptr() == rhs_ex.ptr(); + if (rhs_ex && lhs_ex) + return *lhs_ex == *rhs_ex; + else + return lhs_ex.ptr() == rhs_ex.ptr(); } - else return false; + else + return false; } - bool Pseudo_Selector::operator== (const Simple_Selector& rhs) const + bool Pseudo_Selector::operator==(const Simple_Selector& rhs) const { if (Pseudo_Selector_Ptr_Const w = Cast(&rhs)) { return *this == *w; } - return is_ns_eq(rhs) && - name() == rhs.name(); + return is_ns_eq(rhs) && name() == rhs.name(); } - bool Pseudo_Selector::operator< (const Pseudo_Selector& rhs) const + bool Pseudo_Selector::operator<(const Pseudo_Selector& rhs) const { if (is_ns_eq(rhs) && name() == rhs.name()) { String_Obj lhs_ex = expression(); String_Obj rhs_ex = rhs.expression(); - if (rhs_ex && lhs_ex) return *lhs_ex < *rhs_ex; - else return lhs_ex.ptr() < rhs_ex.ptr(); + if (rhs_ex && lhs_ex) + return *lhs_ex < *rhs_ex; + else + return lhs_ex.ptr() < rhs_ex.ptr(); } if (is_ns_eq(rhs)) - { return name() < rhs.name(); } + { + return name() < rhs.name(); + } return ns() < rhs.ns(); } - bool Pseudo_Selector::operator< (const Simple_Selector& rhs) const + bool Pseudo_Selector::operator<(const Simple_Selector& rhs) const { if (Pseudo_Selector_Ptr_Const w = Cast(&rhs)) { return *this < *w; } if (is_ns_eq(rhs)) - { return name() < rhs.name(); } + { + return name() < rhs.name(); + } return ns() < rhs.ns(); } - bool Wrapped_Selector::operator== (const Wrapped_Selector& rhs) const + bool Wrapped_Selector::operator==(const Wrapped_Selector& rhs) const { if (is_ns_eq(rhs) && name() == rhs.name()) - { return *(selector()) == *(rhs.selector()); } - else return false; + { + return *(selector()) == *(rhs.selector()); + } + else + return false; } - bool Wrapped_Selector::operator== (const Simple_Selector& rhs) const + bool Wrapped_Selector::operator==(const Simple_Selector& rhs) const { if (Wrapped_Selector_Ptr_Const w = Cast(&rhs)) { return *this == *w; } - return is_ns_eq(rhs) && - name() == rhs.name(); + return is_ns_eq(rhs) && name() == rhs.name(); } - bool Wrapped_Selector::operator< (const Wrapped_Selector& rhs) const + bool Wrapped_Selector::operator<(const Wrapped_Selector& rhs) const { if (is_ns_eq(rhs) && name() == rhs.name()) - { return *(selector()) < *(rhs.selector()); } + { + return *(selector()) < *(rhs.selector()); + } if (is_ns_eq(rhs)) - { return name() < rhs.name(); } + { + return name() < rhs.name(); + } return ns() < rhs.ns(); } - bool Wrapped_Selector::operator< (const Simple_Selector& rhs) const + bool Wrapped_Selector::operator<(const Simple_Selector& rhs) const { if (Wrapped_Selector_Ptr_Const w = Cast(&rhs)) { return *this < *w; } if (is_ns_eq(rhs)) - { return name() < rhs.name(); } + { + return name() < rhs.name(); + } return ns() < rhs.ns(); } @@ -755,8 +875,10 @@ namespace Sass { { if (this->name() != sub->name()) return false; if (this->name() == ":current") return false; - if (Selector_List_Obj rhs_list = Cast(sub->selector())) { - if (Selector_List_Obj lhs_list = Cast(selector())) { + if (Selector_List_Obj rhs_list = Cast(sub->selector())) + { + if (Selector_List_Obj lhs_list = Cast(selector())) + { return lhs_list->is_superselector_of(rhs_list); } } @@ -766,7 +888,8 @@ namespace Sass { bool Compound_Selector::is_superselector_of(Selector_List_Obj rhs, std::string wrapped) { - for (Complex_Selector_Obj item : rhs->elements()) { + for (Complex_Selector_Obj item : rhs->elements()) + { if (is_superselector_of(item, wrapped)) return true; } return false; @@ -789,21 +912,26 @@ namespace Sass { std::set lpsuedoset, rpsuedoset; for (size_t i = 0, L = length(); i < L; ++i) { - if ((*this)[i]->is_pseudo_element()) { + if ((*this)[i]->is_pseudo_element()) + { std::string pseudo((*this)[i]->to_string()); - pseudo = pseudo.substr(pseudo.find_first_not_of(":")); // strip off colons to ensure :after matches ::after since ruby sass is forgiving + pseudo = pseudo.substr(pseudo.find_first_not_of( + ":")); // strip off colons to ensure :after matches ::after since ruby sass is forgiving lpsuedoset.insert(pseudo); } } for (size_t i = 0, L = rhs->length(); i < L; ++i) { - if ((*rhs)[i]->is_pseudo_element()) { + if ((*rhs)[i]->is_pseudo_element()) + { std::string pseudo((*rhs)[i]->to_string()); - pseudo = pseudo.substr(pseudo.find_first_not_of(":")); // strip off colons to ensure :after matches ::after since ruby sass is forgiving + pseudo = pseudo.substr(pseudo.find_first_not_of( + ":")); // strip off colons to ensure :after matches ::after since ruby sass is forgiving rpsuedoset.insert(pseudo); } } - if (lpsuedoset != rpsuedoset) { + if (lpsuedoset != rpsuedoset) + { return false; } @@ -814,11 +942,16 @@ namespace Sass { if (lbase && rbase) { - if (lbase->to_string() == rbase->to_string()) { + if (lbase->to_string() == rbase->to_string()) + { for (size_t i = 1, L = length(); i < L; ++i) - { lset.insert((*this)[i]->to_string()); } + { + lset.insert((*this)[i]->to_string()); + } for (size_t i = 1, L = rhs->length(); i < L; ++i) - { rset.insert((*rhs)[i]->to_string()); } + { + rset.insert((*rhs)[i]->to_string()); + } return includes(rset.begin(), rset.end(), lset.begin(), lset.end()); } return false; @@ -828,20 +961,30 @@ namespace Sass { { Selector_Obj wlhs = (*this)[i]; // very special case for wrapped matches selector - if (Wrapped_Selector_Obj wrapped = Cast(wlhs)) { - if (wrapped->name() == ":not") { - if (Selector_List_Obj not_list = Cast(wrapped->selector())) { + if (Wrapped_Selector_Obj wrapped = Cast(wlhs)) + { + if (wrapped->name() == ":not") + { + if (Selector_List_Obj not_list = Cast(wrapped->selector())) + { if (not_list->is_superselector_of(rhs, wrapped->name())) return false; - } else { + } + else + { throw std::runtime_error("wrapped not selector is not a list"); } } - if (wrapped->name() == ":matches" || wrapped->name() == ":-moz-any") { + if (wrapped->name() == ":matches" || wrapped->name() == ":-moz-any") + { wlhs = wrapped->selector(); - if (Selector_List_Obj list = Cast(wrapped->selector())) { - if (Compound_Selector_Obj comp = Cast(rhs)) { + if (Selector_List_Obj list = Cast(wrapped->selector())) + { + if (Compound_Selector_Obj comp = Cast(rhs)) + { if (!wrapping.empty() && wrapping != wrapped->name()) return false; - if (wrapping.empty() || wrapping != wrapped->name()) {; + if (wrapping.empty() || wrapping != wrapped->name()) + { + ; if (list->is_superselector_of(comp, wrapped->name())) return true; } } @@ -849,11 +992,15 @@ namespace Sass { } Simple_Selector_Ptr rhs_sel = NULL; if (rhs->elements().size() > i) rhs_sel = (*rhs)[i]; - if (Wrapped_Selector_Ptr wrapped_r = Cast(rhs_sel)) { - if (wrapped->name() == wrapped_r->name()) { - if (wrapped->is_superselector_of(wrapped_r)) { - continue; - }} + if (Wrapped_Selector_Ptr wrapped_r = Cast(rhs_sel)) + { + if (wrapped->name() == wrapped_r->name()) + { + if (wrapped->is_superselector_of(wrapped_r)) + { + continue; + } + } } } // match from here on as strings @@ -863,18 +1010,24 @@ namespace Sass { for (size_t n = 0, nL = rhs->length(); n < nL; ++n) { Selector_Obj r = (*rhs)[n]; - if (Wrapped_Selector_Obj wrapped = Cast(r)) { - if (wrapped->name() == ":not") { - if (Selector_List_Obj ls = Cast(wrapped->selector())) { + if (Wrapped_Selector_Obj wrapped = Cast(r)) + { + if (wrapped->name() == ":not") + { + if (Selector_List_Obj ls = Cast(wrapped->selector())) + { ls->remove_parent_selectors(); if (is_superselector_of(ls, wrapped->name())) return false; } } - if (wrapped->name() == ":matches" || wrapped->name() == ":-moz-any") { - if (!wrapping.empty()) { + if (wrapped->name() == ":matches" || wrapped->name() == ":-moz-any") + { + if (!wrapping.empty()) + { if (wrapping != wrapped->name()) return false; } - if (Selector_List_Obj ls = Cast(wrapped->selector())) { + if (Selector_List_Obj ls = Cast(wrapped->selector())) + { ls->remove_parent_selectors(); return (is_superselector_of(ls, wrapped->name())); } @@ -883,24 +1036,19 @@ namespace Sass { rset.insert(r->to_string()); } - //for (auto l : lset) { cerr << "l: " << l << endl; } - //for (auto r : rset) { cerr << "r: " << r << endl; } + // for (auto l : lset) { cerr << "l: " << l << endl; } + // for (auto r : rset) { cerr << "r: " << r << endl; } if (lset.empty()) return true; // return true if rset contains all the elements of lset return includes(rset.begin(), rset.end(), lset.begin(), lset.end()); - } // create complex selector (ancestor of) from compound selector Complex_Selector_Obj Compound_Selector::to_complex() { // create an intermediate complex selector - return SASS_MEMORY_NEW(Complex_Selector, - pstate(), - Complex_Selector::ANCESTOR_OF, - this, - 0); + return SASS_MEMORY_NEW(Complex_Selector, pstate(), Complex_Selector::ANCESTOR_OF, this, 0); } Selector_List_Ptr Complex_Selector::unify_with(Complex_Selector_Ptr other) @@ -918,7 +1066,7 @@ namespace Sass { // was to see if this is a ruby 'SimpleSequence' equivalent. // It seems to do the job correctly as some specs react to this if (l_last->combinator() != Combinator::ANCESTOR_OF) return 0; - if (r_last->combinator() != Combinator::ANCESTOR_OF ) return 0; + if (r_last->combinator() != Combinator::ANCESTOR_OF) return 0; // get the headers for the last tails Compound_Selector_Obj l_last_head = l_last->head(); @@ -935,8 +1083,7 @@ namespace Sass { if (unified == 0) return 0; // check for universal (star: `*`) selector - bool is_universal = l_last_head->is_universal() || - r_last_head->is_universal(); + bool is_universal = l_last_head->is_universal() || r_last_head->is_universal(); if (is_universal) { @@ -964,14 +1111,15 @@ namespace Sass { Selector_List_Obj result = SASS_MEMORY_NEW(Selector_List, pstate()); NodeDequePtr col = node.collection(); // move from collection to list for (NodeDeque::iterator it = col->begin(), end = col->end(); it != end; it++) - { result->append(nodeToComplexSelector(Node::naiveTrim(*it))); } + { + result->append(nodeToComplexSelector(Node::naiveTrim(*it))); + } // only return if list has some entries return result->length() ? result.detach() : 0; - } - bool Compound_Selector::operator== (const Compound_Selector& rhs) const + bool Compound_Selector::operator==(const Compound_Selector& rhs) const { // for array access size_t i = 0, n = 0; @@ -986,8 +1134,10 @@ namespace Sass { while (true) { // first check for valid index - if (i == iL) return iL == nL; - else if (n == nL) return iL == nL; + if (i == iL) + return iL == nL; + else if (n == nL) + return iL == nL; // the access the vector items Simple_Selector_Obj l = l_lst[i]; Simple_Selector_Obj r = r_lst[n]; @@ -996,9 +1146,12 @@ namespace Sass { if (!r) ++n; // do the check now else if (*l != *r) - { return false; } + { + return false; + } // advance now - ++i; ++n; + ++i; + ++n; } // there is no break?! } @@ -1013,52 +1166,73 @@ namespace Sass { Complex_Selector_Ptr lhs = this; // check for selectors with leading or trailing combinators if (!lhs->head() || !rhs->head()) - { return false; } + { + return false; + } Complex_Selector_Obj l_innermost = lhs->innermost(); if (l_innermost->combinator() != Complex_Selector::ANCESTOR_OF) - { return false; } + { + return false; + } Complex_Selector_Obj r_innermost = rhs->innermost(); if (r_innermost->combinator() != Complex_Selector::ANCESTOR_OF) - { return false; } + { + return false; + } // more complex (i.e., longer) selectors are always more specific size_t l_len = lhs->length(), r_len = rhs->length(); if (l_len > r_len) - { return false; } + { + return false; + } if (l_len == 1) - { return lhs->head()->is_superselector_of(rhs->last()->head(), wrapping); } + { + return lhs->head()->is_superselector_of(rhs->last()->head(), wrapping); + } // we have to look one tail deeper, since we cary the // combinator around for it (which is important here) - if (rhs->tail() && lhs->tail() && combinator() != Complex_Selector::ANCESTOR_OF) { + if (rhs->tail() && lhs->tail() && combinator() != Complex_Selector::ANCESTOR_OF) + { Complex_Selector_Obj lhs_tail = lhs->tail(); Complex_Selector_Obj rhs_tail = rhs->tail(); if (lhs_tail->combinator() != rhs_tail->combinator()) return false; if (lhs_tail->head() && !rhs_tail->head()) return false; if (!lhs_tail->head() && rhs_tail->head()) return false; - if (lhs_tail->head() && rhs_tail->head()) { + if (lhs_tail->head() && rhs_tail->head()) + { if (!lhs_tail->head()->is_superselector_of(rhs_tail->head())) return false; } } bool found = false; Complex_Selector_Obj marker = rhs; - for (size_t i = 0, L = rhs->length(); i < L; ++i) { - if (i == L-1) - { return false; } + for (size_t i = 0, L = rhs->length(); i < L; ++i) + { + if (i == L - 1) + { + return false; + } if (lhs->head() && marker->head() && lhs->head()->is_superselector_of(marker->head(), wrapping)) - { found = true; break; } + { + found = true; + break; + } marker = marker->tail(); } if (!found) - { return false; } + { + return false; + } /* Hmm, I hope I have the logic right: if lhs has a combinator: if !(marker has a combinator) return false - if !(lhs.combinator == '~' ? marker.combinator != '>' : lhs.combinator == marker.combinator) return false + if !(lhs.combinator == '~' ? marker.combinator != '>' : lhs.combinator == marker.combinator) + return false return lhs.tail-without-innermost.is_superselector_of(marker.tail-without-innermost) else if marker has a combinator: if !(marker.combinator == ">") return false @@ -1069,15 +1243,22 @@ namespace Sass { if (lhs->combinator() != Complex_Selector::ANCESTOR_OF) { if (marker->combinator() == Complex_Selector::ANCESTOR_OF) - { return false; } - if (!(lhs->combinator() == Complex_Selector::PRECEDES ? marker->combinator() != Complex_Selector::PARENT_OF : lhs->combinator() == marker->combinator())) - { return false; } + { + return false; + } + if (!(lhs->combinator() == Complex_Selector::PRECEDES ? marker->combinator() != Complex_Selector::PARENT_OF : + lhs->combinator() == marker->combinator())) + { + return false; + } return lhs->tail()->is_superselector_of(marker->tail()); } else if (marker->combinator() != Complex_Selector::ANCESTOR_OF) { if (marker->combinator() != Complex_Selector::PARENT_OF) - { return false; } + { + return false; + } return lhs->tail()->is_superselector_of(marker->tail()); } return lhs->tail()->is_superselector_of(marker->tail()); @@ -1106,77 +1287,104 @@ namespace Sass { if (ss->has_line_break()) has_line_break(true); // append old headers - if (h && h->length()) { - if (last()->combinator() != ANCESTOR_OF && c != ANCESTOR_OF) { + if (h && h->length()) + { + if (last()->combinator() != ANCESTOR_OF && c != ANCESTOR_OF) + { error("Invalid parent selector", pstate_); - } else if (last()->head_ && last()->head_->length()) { + } + else if (last()->head_ && last()->head_->length()) + { Compound_Selector_Obj rh = last()->head(); size_t i; size_t L = h->length(); - if (Cast(h->first())) { - if (Class_Selector_Ptr cs = Cast(rh->last())) { + if (Cast(h->first())) + { + if (Class_Selector_Ptr cs = Cast(rh->last())) + { Class_Selector_Ptr sqs = SASS_MEMORY_COPY(cs); sqs->name(sqs->name() + (*h)[0]->name()); sqs->pstate((*h)[0]->pstate()); - (*rh)[rh->length()-1] = sqs; + (*rh)[rh->length() - 1] = sqs; rh->pstate(h->pstate()); - for (i = 1; i < L; ++i) rh->append((*h)[i]); - } else if (Id_Selector_Ptr is = Cast(rh->last())) { + for (i = 1; i < L; ++i) + rh->append((*h)[i]); + } + else if (Id_Selector_Ptr is = Cast(rh->last())) + { Id_Selector_Ptr sqs = SASS_MEMORY_COPY(is); sqs->name(sqs->name() + (*h)[0]->name()); sqs->pstate((*h)[0]->pstate()); - (*rh)[rh->length()-1] = sqs; + (*rh)[rh->length() - 1] = sqs; rh->pstate(h->pstate()); - for (i = 1; i < L; ++i) rh->append((*h)[i]); - } else if (Element_Selector_Ptr ts = Cast(rh->last())) { + for (i = 1; i < L; ++i) + rh->append((*h)[i]); + } + else if (Element_Selector_Ptr ts = Cast(rh->last())) + { Element_Selector_Ptr tss = SASS_MEMORY_COPY(ts); tss->name(tss->name() + (*h)[0]->name()); tss->pstate((*h)[0]->pstate()); - (*rh)[rh->length()-1] = tss; + (*rh)[rh->length() - 1] = tss; rh->pstate(h->pstate()); - for (i = 1; i < L; ++i) rh->append((*h)[i]); - } else if (Placeholder_Selector_Ptr ps = Cast(rh->last())) { + for (i = 1; i < L; ++i) + rh->append((*h)[i]); + } + else if (Placeholder_Selector_Ptr ps = Cast(rh->last())) + { Placeholder_Selector_Ptr pss = SASS_MEMORY_COPY(ps); pss->name(pss->name() + (*h)[0]->name()); pss->pstate((*h)[0]->pstate()); - (*rh)[rh->length()-1] = pss; + (*rh)[rh->length() - 1] = pss; rh->pstate(h->pstate()); - for (i = 1; i < L; ++i) rh->append((*h)[i]); - } else { + for (i = 1; i < L; ++i) + rh->append((*h)[i]); + } + else + { last()->head_->concat(h); } - } else { + } + else + { last()->head_->concat(h); } - } else { + } + else + { last()->head_->concat(h); } - } else { + } + else + { // std::cerr << "has no or empty head\n"; } - if (last()) { - if (last()->combinator() != ANCESTOR_OF && c != ANCESTOR_OF) { + if (last()) + { + if (last()->combinator() != ANCESTOR_OF && c != ANCESTOR_OF) + { Complex_Selector_Ptr inter = SASS_MEMORY_NEW(Complex_Selector, pstate()); inter->reference(r); inter->combinator(c); inter->tail(t); last()->tail(inter); - } else { - if (last()->combinator() == ANCESTOR_OF) { + } + else + { + if (last()->combinator() == ANCESTOR_OF) + { last()->combinator(c); last()->reference(r); } last()->tail(t); } } - } Selector_List_Obj Selector_List::eval(Eval& eval) { - Selector_List_Obj list = schema() ? - eval(schema()) : eval(this); + Selector_List_Obj list = schema() ? eval(schema()) : eval(this); list->schema(schema()); return list; } @@ -1186,8 +1394,10 @@ namespace Sass { if (!this->has_parent_ref()) return this; Selector_List_Ptr ss = SASS_MEMORY_NEW(Selector_List, pstate()); Selector_List_Ptr ps = pstack.back(); - for (size_t pi = 0, pL = ps->length(); pi < pL; ++pi) { - for (size_t si = 0, sL = this->length(); si < sL; ++si) { + for (size_t pi = 0, pL = ps->length(); pi < pL; ++pi) + { + for (size_t si = 0, sL = this->length(); si < sL; ++si) + { Selector_List_Obj rv = at(si)->resolve_parent_refs(pstack, implicit_parent); ss->concat(rv); } @@ -1201,7 +1411,8 @@ namespace Sass { Compound_Selector_Obj head = this->head(); Selector_List_Ptr parents = pstack.back(); - if (!this->has_real_parent_ref() && !implicit_parent) { + if (!this->has_real_parent_ref() && !implicit_parent) + { Selector_List_Ptr retval = SASS_MEMORY_NEW(Selector_List, pstate()); retval->append(this); return retval; @@ -1210,27 +1421,35 @@ namespace Sass { // first resolve_parent_refs the tail (which may return an expanded list) Selector_List_Obj tails = tail ? tail->resolve_parent_refs(pstack, implicit_parent) : 0; - if (head && head->length() > 0) { + if (head && head->length() > 0) + { Selector_List_Obj retval; // we have a parent selector in a simple compound list // mix parent complex selector into the compound list - if (Cast((*head)[0])) { + if (Cast((*head)[0])) + { retval = SASS_MEMORY_NEW(Selector_List, pstate()); // it turns out that real parent references reach // across @at-root rules, which comes unexpected - if (parents == NULL && head->has_real_parent_ref()) { + if (parents == NULL && head->has_real_parent_ref()) + { int i = pstack.size() - 1; - while (!parents && i > -1) { + while (!parents && i > -1) + { parents = pstack.at(i--); } } - if (parents && parents->length()) { - if (tails && tails->length() > 0) { - for (size_t n = 0, nL = tails->length(); n < nL; ++n) { - for (size_t i = 0, iL = parents->length(); i < iL; ++i) { + if (parents && parents->length()) + { + if (tails && tails->length() > 0) + { + for (size_t n = 0, nL = tails->length(); n < nL; ++n) + { + for (size_t i = 0, iL = parents->length(); i < iL; ++i) + { Complex_Selector_Obj t = (*tails)[n]; Complex_Selector_Obj parent = (*parents)[i]; Complex_Selector_Obj s = SASS_MEMORY_CLONE(parent); @@ -1238,14 +1457,18 @@ namespace Sass { ss->tail(t ? SASS_MEMORY_CLONE(t) : NULL); Compound_Selector_Obj h = SASS_MEMORY_COPY(head_); // remove parent selector from sequence - if (h->length()) { + if (h->length()) + { h->erase(h->begin()); ss->head(h); - } else { + } + else + { ss->head(NULL); } // adjust for parent selector (1 char) - if (h->length()) { + if (h->length()) + { ParserState state(h->at(0)->pstate()); state.offset.column += 1; state.column -= 1; @@ -1261,29 +1484,36 @@ namespace Sass { } // have no tails but parents // loop above is inside out - else { - for (size_t i = 0, iL = parents->length(); i < iL; ++i) { + else + { + for (size_t i = 0, iL = parents->length(); i < iL; ++i) + { Complex_Selector_Obj parent = (*parents)[i]; Complex_Selector_Obj s = SASS_MEMORY_CLONE(parent); Complex_Selector_Obj ss = SASS_MEMORY_CLONE(this); // this is only if valid if the parent has no trailing op // otherwise we cannot append more simple selectors to head - if (parent->last()->combinator() != ANCESTOR_OF) { + if (parent->last()->combinator() != ANCESTOR_OF) + { throw Exception::InvalidParent(parent, ss); } ss->tail(tail ? SASS_MEMORY_CLONE(tail) : NULL); Compound_Selector_Obj h = SASS_MEMORY_COPY(head_); // remove parent selector from sequence - if (h->length()) { + if (h->length()) + { h->erase(h->begin()); ss->head(h); - } else { + } + else + { ss->head(NULL); } // \/ IMO ruby sass bug \/ ss->has_line_feed(false); // adjust for parent selector (1 char) - if (h->length()) { + if (h->length()) + { ParserState state(h->at(0)->pstate()); state.offset.column += 1; state.column -= 1; @@ -1298,9 +1528,12 @@ namespace Sass { } } // have no parent but some tails - else { - if (tails && tails->length() > 0) { - for (size_t n = 0, nL = tails->length(); n < nL; ++n) { + else + { + if (tails && tails->length() > 0) + { + for (size_t n = 0, nL = tails->length(); n < nL; ++n) + { Complex_Selector_Obj cpy = SASS_MEMORY_CLONE(this); cpy->tail(SASS_MEMORY_CLONE(tails->at(n))); cpy->head(SASS_MEMORY_NEW(Compound_Selector, head->pstate())); @@ -1311,7 +1544,8 @@ namespace Sass { } } // have no parent nor tails - else { + else + { Complex_Selector_Obj cpy = SASS_MEMORY_CLONE(this); cpy->head(SASS_MEMORY_NEW(Compound_Selector, head->pstate())); for (size_t i = 1, L = this->head()->length(); i < L; ++i) @@ -1322,20 +1556,23 @@ namespace Sass { } } // no parent selector in head - else { + else + { retval = this->tails(tails); } - for (Simple_Selector_Obj ss : head->elements()) { - if (Wrapped_Selector_Ptr ws = Cast(ss)) { - if (Selector_List_Ptr sl = Cast(ws->selector())) { + for (Simple_Selector_Obj ss : head->elements()) + { + if (Wrapped_Selector_Ptr ws = Cast(ss)) + { + if (Selector_List_Ptr sl = Cast(ws->selector())) + { if (parents) ws->selector(sl->resolve_parent_refs(pstack, implicit_parent)); } } } return retval.detach(); - } // has no head return this->tails(tails); @@ -1344,14 +1581,17 @@ namespace Sass { Selector_List_Ptr Complex_Selector::tails(Selector_List_Ptr tails) { Selector_List_Ptr rv = SASS_MEMORY_NEW(Selector_List, pstate_); - if (tails && tails->length()) { - for (size_t i = 0, iL = tails->length(); i < iL; ++i) { + if (tails && tails->length()) + { + for (size_t i = 0, iL = tails->length(); i < iL; ++i) + { Complex_Selector_Obj pr = SASS_MEMORY_CLONE(this); pr->tail(tails->at(i)); rv->append(pr); } } - else { + else + { rv->append(this); } return rv; @@ -1369,7 +1609,8 @@ namespace Sass { // get the head head = cur->head_; // abort (and return) if it is not a parent selector - if (!head || head->length() != 1 || !Cast((*head)[0])) { + if (!head || head->length() != 1 || !Cast((*head)[0])) + { break; } // advance to next @@ -1385,7 +1626,8 @@ namespace Sass { Complex_Selector_Ptr cur = this; Complex_Selector_Ptr nxt = cur; // loop until last - while (nxt) { + while (nxt) + { cur = nxt; nxt = cur->tail(); } @@ -1396,18 +1638,29 @@ namespace Sass { { Combinator c; if (!tail() || tail()->tail() == 0) - { c = combinator(); combinator(ANCESTOR_OF); tail(0); } + { + c = combinator(); + combinator(ANCESTOR_OF); + tail(0); + } else - { c = tail()->clear_innermost(); } + { + c = tail()->clear_innermost(); + } return c; } void Complex_Selector::set_innermost(Complex_Selector_Obj val, Combinator c) { if (!tail()) - { tail(val); combinator(c); } + { + tail(val); + combinator(c); + } else - { tail()->set_innermost(val, c); } + { + tail()->set_innermost(val, c); + } } void Complex_Selector::cloneChildren() @@ -1418,14 +1671,16 @@ namespace Sass { void Compound_Selector::cloneChildren() { - for (size_t i = 0, l = length(); i < l; i++) { + for (size_t i = 0, l = length(); i < l; i++) + { at(i) = SASS_MEMORY_CLONE(at(i)); } } void Selector_List::cloneChildren() { - for (size_t i = 0, l = length(); i < l; i++) { + for (size_t i = 0, l = length(); i < l; i++) + { at(i) = SASS_MEMORY_CLONE(at(i)); } } @@ -1440,20 +1695,26 @@ namespace Sass { void Selector_List::remove_parent_selectors() { // Check every rhs selector against left hand list - for(size_t i = 0, L = length(); i < L; ++i) { + for (size_t i = 0, L = length(); i < L; ++i) + { if (!(*this)[i]->head()) continue; - if ((*this)[i]->head()->is_empty_reference()) { + if ((*this)[i]->head()->is_empty_reference()) + { // simply move to the next tail if we have "no" combinator - if ((*this)[i]->combinator() == Complex_Selector::ANCESTOR_OF) { - if ((*this)[i]->tail()) { - if ((*this)[i]->has_line_feed()) { + if ((*this)[i]->combinator() == Complex_Selector::ANCESTOR_OF) + { + if ((*this)[i]->tail()) + { + if ((*this)[i]->has_line_feed()) + { (*this)[i]->tail()->has_line_feed(true); } (*this)[i] = (*this)[i]->tail(); } } // otherwise remove the first item from head - else { + else + { (*this)[i]->head()->erase((*this)[i]->head()->begin()); } } @@ -1462,18 +1723,21 @@ namespace Sass { size_t Wrapped_Selector::hash() { - if (hash_ == 0) { + if (hash_ == 0) + { hash_combine(hash_, Simple_Selector::hash()); if (selector_) hash_combine(hash_, selector_->hash()); } return hash_; } - bool Wrapped_Selector::has_parent_ref() const { + bool Wrapped_Selector::has_parent_ref() const + { // if (has_reference()) return true; if (!selector()) return false; return selector()->has_parent_ref(); } - bool Wrapped_Selector::has_real_parent_ref() const { + bool Wrapped_Selector::has_real_parent_ref() const + { // if (has_reference()) return true; if (!selector()) return false; return selector()->has_real_parent_ref(); @@ -1486,7 +1750,8 @@ namespace Sass { bool Selector_List::has_parent_ref() const { - for (Complex_Selector_Obj s : elements()) { + for (Complex_Selector_Obj s : elements()) + { if (s && s->has_parent_ref()) return true; } return false; @@ -1494,7 +1759,8 @@ namespace Sass { bool Selector_List::has_real_parent_ref() const { - for (Complex_Selector_Obj s : elements()) { + for (Complex_Selector_Obj s : elements()) + { if (s && s->has_real_parent_ref()) return true; } return false; @@ -1502,7 +1768,8 @@ namespace Sass { bool Selector_Schema::has_parent_ref() const { - if (String_Schema_Obj schema = Cast(contents())) { + if (String_Schema_Obj schema = Cast(contents())) + { return schema->length() > 0 && Cast(schema->at(0)) != NULL; } return false; @@ -1510,7 +1777,8 @@ namespace Sass { bool Selector_Schema::has_real_parent_ref() const { - if (String_Schema_Obj schema = Cast(contents())) { + if (String_Schema_Obj schema = Cast(contents())) + { Parent_Selector_Obj p = Cast(schema->at(0)); return schema->length() > 0 && p && p->is_real_parent_ref(); } @@ -1527,7 +1795,8 @@ namespace Sass { bool Complex_Selector::is_superselector_of(Selector_List_Obj sub, std::string wrapping) { // Check every rhs selector against left hand list - for(size_t i = 0, L = sub->length(); i < L; ++i) { + for (size_t i = 0, L = sub->length(); i < L; ++i) + { if (!is_superselector_of((*sub)[i], wrapping)) return false; } return true; @@ -1538,7 +1807,8 @@ namespace Sass { bool Selector_List::is_superselector_of(Selector_List_Obj sub, std::string wrapping) { // Check every rhs selector against left hand list - for(size_t i = 0, L = sub->length(); i < L; ++i) { + for (size_t i = 0, L = sub->length(); i < L; ++i) + { if (!is_superselector_of((*sub)[i], wrapping)) return false; } return true; @@ -1549,7 +1819,8 @@ namespace Sass { bool Selector_List::is_superselector_of(Compound_Selector_Obj sub, std::string wrapping) { // Check every lhs selector against right hand - for(size_t i = 0, L = length(); i < L; ++i) { + for (size_t i = 0, L = length(); i < L; ++i) + { if ((*this)[i]->is_superselector_of(sub, wrapping)) return true; } return false; @@ -1560,24 +1831,30 @@ namespace Sass { bool Selector_List::is_superselector_of(Complex_Selector_Obj sub, std::string wrapping) { // Check every lhs selector against right hand - for(size_t i = 0, L = length(); i < L; ++i) { + for (size_t i = 0, L = length(); i < L; ++i) + { if ((*this)[i]->is_superselector_of(sub)) return true; } return false; } - Selector_List_Ptr Selector_List::unify_with(Selector_List_Ptr rhs) { + Selector_List_Ptr Selector_List::unify_with(Selector_List_Ptr rhs) + { std::vector unified_complex_selectors; // Unify all of children with RHS's children, storing the results in `unified_complex_selectors` - for (size_t lhs_i = 0, lhs_L = length(); lhs_i < lhs_L; ++lhs_i) { + for (size_t lhs_i = 0, lhs_L = length(); lhs_i < lhs_L; ++lhs_i) + { Complex_Selector_Obj seq1 = (*this)[lhs_i]; - for(size_t rhs_i = 0, rhs_L = rhs->length(); rhs_i < rhs_L; ++rhs_i) { + for (size_t rhs_i = 0, rhs_L = rhs->length(); rhs_i < rhs_L; ++rhs_i) + { Complex_Selector_Ptr seq2 = rhs->at(rhs_i); Selector_List_Obj result = seq1->unify_with(seq2); - if( result ) { - for(size_t i = 0, L = result->length(); i < L; ++i) { - unified_complex_selectors.push_back( (*result)[i] ); + if (result) + { + for (size_t i = 0, L = result->length(); i < L; ++i) + { + unified_complex_selectors.push_back((*result)[i]); } } } @@ -1585,7 +1862,8 @@ namespace Sass { // Creates the final Selector_List by combining all the complex selectors Selector_List_Ptr final_result = SASS_MEMORY_NEW(Selector_List, pstate()); - for (auto itr = unified_complex_selectors.begin(); itr != unified_complex_selectors.end(); ++itr) { + for (auto itr = unified_complex_selectors.begin(); itr != unified_complex_selectors.end(); ++itr) + { final_result->append(*itr); } return final_result; @@ -1595,16 +1873,19 @@ namespace Sass { { Selector_List_Ptr extender = this; - for (auto complex_sel : extendee->elements()) { + for (auto complex_sel : extendee->elements()) + { Complex_Selector_Obj c = complex_sel; // Ignore any parent selectors, until we find the first non Selectorerence head Compound_Selector_Obj compound_sel = c->head(); Complex_Selector_Obj pIter = complex_sel; - while (pIter) { + while (pIter) + { Compound_Selector_Obj pHead = pIter->head(); - if (pHead && Cast(pHead->elements()[0]) == NULL) { + if (pHead && Cast(pHead->elements()[0]) == NULL) + { compound_sel = pHead; break; } @@ -1612,13 +1893,15 @@ namespace Sass { pIter = pIter->tail(); } - if (!pIter->head() || pIter->tail()) { + if (!pIter->head() || pIter->tail()) + { error("nested selectors may not be extended", c->pstate()); } compound_sel->is_optional(extendee->is_optional()); - for (size_t i = 0, L = extender->length(); i < L; ++i) { + for (size_t i = 0, L = extender->length(); i < L; ++i) + { extends.put(compound_sel, std::make_pair((*extender)[i], compound_sel)); } } @@ -1656,16 +1939,21 @@ namespace Sass { void Compound_Selector::mergeSources(ComplexSelectorSet& sources) { - for (ComplexSelectorSet::iterator iterator = sources.begin(), endIterator = sources.end(); iterator != endIterator; ++iterator) { + for (ComplexSelectorSet::iterator iterator = sources.begin(), endIterator = sources.end(); + iterator != endIterator; ++iterator) + { this->sources_.insert(SASS_MEMORY_CLONE(*iterator)); } } Argument_Obj Arguments::get_rest_argument() { - if (this->has_rest_argument()) { - for (Argument_Obj arg : this->elements()) { - if (arg->is_rest_argument()) { + if (this->has_rest_argument()) + { + for (Argument_Obj arg : this->elements()) + { + if (arg->is_rest_argument()) + { return arg; } } @@ -1675,9 +1963,12 @@ namespace Sass { Argument_Obj Arguments::get_keyword_argument() { - if (this->has_keyword_argument()) { - for (Argument_Obj arg : this->elements()) { - if (arg->is_keyword_argument()) { + if (this->has_keyword_argument()) + { + for (Argument_Obj arg : this->elements()) + { + if (arg->is_keyword_argument()) + { return arg; } } @@ -1687,47 +1978,61 @@ namespace Sass { void Arguments::adjust_after_pushing(Argument_Obj a) { - if (!a->name().empty()) { - if (has_keyword_argument()) { + if (!a->name().empty()) + { + if (has_keyword_argument()) + { error("named arguments must precede variable-length argument", a->pstate()); } has_named_arguments(true); } - else if (a->is_rest_argument()) { - if (has_rest_argument()) { + else if (a->is_rest_argument()) + { + if (has_rest_argument()) + { error("functions and mixins may only be called with one variable-length argument", a->pstate()); } - if (has_keyword_argument_) { + if (has_keyword_argument_) + { error("only keyword arguments may follow variable arguments", a->pstate()); } has_rest_argument(true); } - else if (a->is_keyword_argument()) { - if (has_keyword_argument()) { + else if (a->is_keyword_argument()) + { + if (has_keyword_argument()) + { error("functions and mixins may only be called with one keyword argument", a->pstate()); } has_keyword_argument(true); } - else { - if (has_rest_argument()) { + else + { + if (has_rest_argument()) + { error("ordinal arguments must precede variable-length arguments", a->pstate()); } - if (has_named_arguments()) { + if (has_named_arguments()) + { error("ordinal arguments must precede named arguments", a->pstate()); } } } - bool Ruleset::is_invisible() const { - if (Selector_List_Ptr sl = Cast(selector())) { + bool Ruleset::is_invisible() const + { + if (Selector_List_Ptr sl = Cast(selector())) + { for (size_t i = 0, L = sl->length(); i < L; ++i) if (!(*sl)[i]->has_placeholder()) return false; } return true; } - bool Media_Block::is_invisible() const { - for (size_t i = 0, L = block()->length(); i < L; ++i) { + bool Media_Block::is_invisible() const + { + for (size_t i = 0, L = block()->length(); i < L; ++i) + { Statement_Obj stm = block()->at(i); if (!stm->is_invisible()) return false; } @@ -1735,29 +2040,29 @@ namespace Sass { } Number::Number(ParserState pstate, double val, std::string u, bool zero) - : Value(pstate), - value_(val), - zero_(zero), - numerator_units_(std::vector()), - denominator_units_(std::vector()), - hash_(0) + : Value(pstate), value_(val), zero_(zero), numerator_units_(std::vector()), + denominator_units_(std::vector()), hash_(0) { size_t l = 0; size_t r; - if (!u.empty()) { + if (!u.empty()) + { bool nominator = true; - while (true) { + while (true) + { r = u.find_first_of("*/", l); std::string unit(u.substr(l, r == std::string::npos ? r : r - l)); - if (!unit.empty()) { - if (nominator) numerator_units_.push_back(unit); - else denominator_units_.push_back(unit); + if (!unit.empty()) + { + if (nominator) + numerator_units_.push_back(unit); + else + denominator_units_.push_back(unit); } if (r == std::string::npos) break; // ToDo: should error for multiple slashes // if (!nominator && u[r] == '/') error(...) - if (u[r] == '/') - nominator = false; + if (u[r] == '/') nominator = false; l = r + 1; } } @@ -1767,12 +2072,14 @@ namespace Sass { std::string Number::unit() const { std::string u; - for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) { + for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) + { if (i) u += '*'; u += numerator_units_[i]; } if (!denominator_units_.empty()) u += '/'; - for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) { + for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) + { if (i) u += '*'; u += denominator_units_[i]; } @@ -1781,12 +2088,13 @@ namespace Sass { bool Number::is_valid_css_unit() const { - return numerator_units().size() <= 1 && - denominator_units().size() == 0; + return numerator_units().size() <= 1 && denominator_units().size() == 0; } bool Number::is_unitless() const - { return numerator_units_.empty() && denominator_units_.empty(); } + { + return numerator_units_.empty() && denominator_units_.empty(); + } void Number::normalize(const std::string& prefered, bool strict) { @@ -1800,8 +2108,10 @@ namespace Sass { std::map exponents; // initialize by summing up occurences in unit vectors - for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) ++ exponents[numerator_units_[i]]; - for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) -- exponents[denominator_units_[i]]; + for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) + ++exponents[numerator_units_[i]]; + for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) + --exponents[denominator_units_[i]]; // the final conversion factor double factor = 1; @@ -1818,7 +2128,7 @@ namespace Sass { while (denom_it != denom_end) { // get and increment afterwards - const std::string denom = *(denom_it ++); + const std::string denom = *(denom_it++); // skip already canceled out unit if (exponents[denom] >= 0) continue; // skip all units we don't know how to convert @@ -1827,7 +2137,7 @@ namespace Sass { while (nom_it != nom_end) { // get and increment afterwards - const std::string nom = *(nom_it ++); + const std::string nom = *(nom_it++); // skip already canceled out unit if (exponents[nom] <= 0) continue; // skip all units we don't know how to convert @@ -1836,7 +2146,8 @@ namespace Sass { // add factor for current conversion factor *= conversion_factor(nom, denom, strict); // update nominator/denominator exponent - -- exponents[nom]; ++ exponents[denom]; + --exponents[nom]; + ++exponents[denom]; // inner loop done break; } @@ -1851,13 +2162,16 @@ namespace Sass { { // maybe there is more effecient way to push // the same item multiple times to a vector? - for(size_t i = 0, S = abs(exp.second); i < S; ++i) + for (size_t i = 0, S = abs(exp.second); i < S; ++i) { // opted to have these switches in the inner loop // makes it more readable and should not cost much - if (!exp.first.empty()) { - if (exp.second < 0) denominator_units_.push_back(exp.first); - else if (exp.second > 0) numerator_units_.push_back(exp.first); + if (!exp.first.empty()) + { + if (exp.second < 0) + denominator_units_.push_back(exp.first); + else if (exp.second > 0) + numerator_units_.push_back(exp.first); } } } @@ -1868,11 +2182,18 @@ namespace Sass { // maybe convert to other unit // easier implemented on its own - try { convert(prefered, strict); } + try + { + convert(prefered, strict); + } catch (Exception::IncompatibleUnits& err) - { error(err.what(), pstate()); } - catch (...) { throw; } - + { + error(err.what(), pstate()); + } + catch (...) + { + throw; + } } // this does not cover all cases (multiple prefered units) @@ -1884,8 +2205,10 @@ namespace Sass { // we basically construct exponents for each unit class // std::map exponents; // initialize by summing up occurences in unit vectors - // for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) ++ exponents[unit_to_class(numerator_units_[i])]; - // for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) -- exponents[unit_to_class(denominator_units_[i])]; + // for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) ++ + // exponents[unit_to_class(numerator_units_[i])]; + // for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) -- + // exponents[unit_to_class(denominator_units_[i])]; std::vector l_miss_nums(0); std::vector l_miss_dens(0); @@ -1906,7 +2229,7 @@ namespace Sass { while (l_num_it != l_num_end) { // get and increment afterwards - const std::string l_num = *(l_num_it ++); + const std::string l_num = *(l_num_it++); std::vector::iterator r_num_it = r_nums.begin(); std::vector::iterator r_num_end = r_nums.end(); @@ -1920,8 +2243,9 @@ namespace Sass { // get possible converstion factor for units double conversion = conversion_factor(l_num, r_num, false); // skip incompatible numerator - if (conversion == 0) { - ++ r_num_it; + if (conversion == 0) + { + ++r_num_it; continue; } // apply to global factor @@ -1944,7 +2268,7 @@ namespace Sass { while (l_den_it != l_den_end) { // get and increment afterwards - const std::string l_den = *(l_den_it ++); + const std::string l_den = *(l_den_it++); std::vector::iterator r_den_it = r_dens.begin(); std::vector::iterator r_den_end = r_dens.end(); @@ -1958,8 +2282,9 @@ namespace Sass { // get possible converstion factor for units double conversion = conversion_factor(l_den, r_den, false); // skip incompatible denominator - if (conversion == 0) { - ++ r_den_it; + if (conversion == 0) + { + ++r_den_it; continue; } // apply to global factor @@ -1976,16 +2301,20 @@ namespace Sass { } // check left-overs (ToDo: might cancel out) - if (l_miss_nums.size() > 0 && !r_unitless) { + if (l_miss_nums.size() > 0 && !r_unitless) + { throw Exception::IncompatibleUnits(n, *this); } - if (l_miss_dens.size() > 0 && !r_unitless) { + if (l_miss_dens.size() > 0 && !r_unitless) + { throw Exception::IncompatibleUnits(n, *this); } - if (r_nums.size() > 0 && !l_unitless) { + if (r_nums.size() > 0 && !l_unitless) + { throw Exception::IncompatibleUnits(n, *this); } - if (r_dens.size() > 0 && !l_unitless) { + if (r_dens.size() > 0 && !l_unitless) + { throw Exception::IncompatibleUnits(n, *this); } @@ -2005,8 +2334,10 @@ namespace Sass { std::map exponents; // initialize by summing up occurences in unit vectors - for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) ++ exponents[numerator_units_[i]]; - for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) -- exponents[denominator_units_[i]]; + for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) + ++exponents[numerator_units_[i]]; + for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) + --exponents[denominator_units_[i]]; // the final conversion factor double factor = 1; @@ -2019,7 +2350,7 @@ namespace Sass { while (denom_it != denom_end) { // get and increment afterwards - const std::string denom = *(denom_it ++); + const std::string denom = *(denom_it++); // check if conversion is needed if (denom == prefered) continue; // skip already canceled out unit @@ -2030,7 +2361,8 @@ namespace Sass { // add factor for current conversion factor *= conversion_factor(denom, prefered, strict); // update nominator/denominator exponent - ++ exponents[denom]; -- exponents[prefered]; + ++exponents[denom]; + --exponents[prefered]; } std::vector::iterator nom_it = numerator_units_.begin(); @@ -2040,7 +2372,7 @@ namespace Sass { while (nom_it != nom_end) { // get and increment afterwards - const std::string nom = *(nom_it ++); + const std::string nom = *(nom_it++); // check if conversion is needed if (nom == prefered) continue; // skip already canceled out unit @@ -2051,7 +2383,8 @@ namespace Sass { // add factor for current conversion factor *= conversion_factor(nom, prefered, strict); // update nominator/denominator exponent - -- exponents[nom]; ++ exponents[prefered]; + --exponents[nom]; + ++exponents[prefered]; } // now we can build up the new unit arrays @@ -2063,13 +2396,16 @@ namespace Sass { { // maybe there is more effecient way to push // the same item multiple times to a vector? - for(size_t i = 0, S = abs(exp.second); i < S; ++i) + for (size_t i = 0, S = abs(exp.second); i < S; ++i) { // opted to have these switches in the inner loop // makes it more readable and should not cost much - if (!exp.first.empty()) { - if (exp.second < 0) denominator_units_.push_back(exp.first); - else if (exp.second > 0) numerator_units_.push_back(exp.first); + if (!exp.first.empty()) + { + if (exp.second < 0) + denominator_units_.push_back(exp.first); + else if (exp.second > 0) + numerator_units_.push_back(exp.first); } } } @@ -2080,61 +2416,66 @@ namespace Sass { // success? return true; - } // useful for making one number compatible with another std::string Number::find_convertible_unit() const { - for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) { + for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) + { std::string u(numerator_units_[i]); if (string_to_unit(u) != UNKNOWN) return u; } - for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) { + for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) + { std::string u(denominator_units_[i]); if (string_to_unit(u) != UNKNOWN) return u; } return std::string(); } - bool Custom_Warning::operator== (const Expression& rhs) const + bool Custom_Warning::operator==(const Expression& rhs) const { - if (Custom_Warning_Ptr_Const r = Cast(&rhs)) { + if (Custom_Warning_Ptr_Const r = Cast(&rhs)) + { return message() == r->message(); } return false; } - bool Custom_Error::operator== (const Expression& rhs) const + bool Custom_Error::operator==(const Expression& rhs) const { - if (Custom_Error_Ptr_Const r = Cast(&rhs)) { + if (Custom_Error_Ptr_Const r = Cast(&rhs)) + { return message() == r->message(); } return false; } - bool Number::operator== (const Expression& rhs) const + bool Number::operator==(const Expression& rhs) const { - if (Number_Ptr_Const r = Cast(&rhs)) { + if (Number_Ptr_Const r = Cast(&rhs)) + { size_t lhs_units = numerator_units_.size() + denominator_units_.size(); size_t rhs_units = r->numerator_units_.size() + r->denominator_units_.size(); // unitless and only having one unit seems equivalent (will change in future) - if (!lhs_units || !rhs_units) { + if (!lhs_units || !rhs_units) + { return std::fabs(value() - r->value()) < NUMBER_EPSILON; } - return (numerator_units_ == r->numerator_units_) && - (denominator_units_ == r->denominator_units_) && + return (numerator_units_ == r->numerator_units_) && (denominator_units_ == r->denominator_units_) && std::fabs(value() - r->value()) < NUMBER_EPSILON; } return false; } - bool Number::operator< (const Number& rhs) const + bool Number::operator<(const Number& rhs) const { size_t lhs_units = numerator_units_.size() + denominator_units_.size(); size_t rhs_units = rhs.numerator_units_.size() + rhs.denominator_units_.size(); // unitless and only having one unit seems equivalent (will change in future) - if (!lhs_units || !rhs_units) { + if (!lhs_units || !rhs_units) + { return value() < rhs.value(); } @@ -2142,31 +2483,39 @@ namespace Sass { tmp_r.normalize(find_convertible_unit()); std::string l_unit(unit()); std::string r_unit(tmp_r.unit()); - if (unit() != tmp_r.unit()) { + if (unit() != tmp_r.unit()) + { error("cannot compare numbers with incompatible units", pstate()); } return value() < tmp_r.value(); } - bool String_Quoted::operator== (const Expression& rhs) const + bool String_Quoted::operator==(const Expression& rhs) const { - if (String_Quoted_Ptr_Const qstr = Cast(&rhs)) { + if (String_Quoted_Ptr_Const qstr = Cast(&rhs)) + { return (value() == qstr->value()); - } else if (String_Constant_Ptr_Const cstr = Cast(&rhs)) { + } + else if (String_Constant_Ptr_Const cstr = Cast(&rhs)) + { return (value() == cstr->value()); } return false; } - bool String_Constant::is_invisible() const { + bool String_Constant::is_invisible() const + { return value_.empty() && quote_mark_ == 0; } - bool String_Constant::operator== (const Expression& rhs) const + bool String_Constant::operator==(const Expression& rhs) const { - if (String_Quoted_Ptr_Const qstr = Cast(&rhs)) { + if (String_Quoted_Ptr_Const qstr = Cast(&rhs)) + { return (value() == qstr->value()); - } else if (String_Constant_Ptr_Const cstr = Cast(&rhs)) { + } + else if (String_Constant_Ptr_Const cstr = Cast(&rhs)) + { return (value() == cstr->value()); } return false; @@ -2181,11 +2530,13 @@ namespace Sass { return length() && last()->is_right_interpolant(); } - bool String_Schema::operator== (const Expression& rhs) const + bool String_Schema::operator==(const Expression& rhs) const { - if (String_Schema_Ptr_Const r = Cast(&rhs)) { + if (String_Schema_Ptr_Const r = Cast(&rhs)) + { if (length() != r->length()) return false; - for (size_t i = 0, L = length(); i < L; ++i) { + for (size_t i = 0, L = length(); i < L; ++i) + { Expression_Obj rv = (*r)[i]; Expression_Obj lv = (*this)[i]; if (!lv || !rv) return false; @@ -2196,32 +2547,33 @@ namespace Sass { return false; } - bool Boolean::operator== (const Expression& rhs) const + bool Boolean::operator==(const Expression& rhs) const { - if (Boolean_Ptr_Const r = Cast(&rhs)) { + if (Boolean_Ptr_Const r = Cast(&rhs)) + { return (value() == r->value()); } return false; } - bool Color::operator== (const Expression& rhs) const + bool Color::operator==(const Expression& rhs) const { - if (Color_Ptr_Const r = Cast(&rhs)) { - return r_ == r->r() && - g_ == r->g() && - b_ == r->b() && - a_ == r->a(); + if (Color_Ptr_Const r = Cast(&rhs)) + { + return r_ == r->r() && g_ == r->g() && b_ == r->b() && a_ == r->a(); } return false; } - bool List::operator== (const Expression& rhs) const + bool List::operator==(const Expression& rhs) const { - if (List_Ptr_Const r = Cast(&rhs)) { + if (List_Ptr_Const r = Cast(&rhs)) + { if (length() != r->length()) return false; if (separator() != r->separator()) return false; if (is_bracketed() != r->is_bracketed()) return false; - for (size_t i = 0, L = length(); i < L; ++i) { + for (size_t i = 0, L = length(); i < L; ++i) + { Expression_Obj rv = r->at(i); Expression_Obj lv = this->at(i); if (!lv || !rv) return false; @@ -2232,11 +2584,13 @@ namespace Sass { return false; } - bool Map::operator== (const Expression& rhs) const + bool Map::operator==(const Expression& rhs) const { - if (Map_Ptr_Const r = Cast(&rhs)) { + if (Map_Ptr_Const r = Cast(&rhs)) + { if (length() != r->length()) return false; - for (auto key : keys()) { + for (auto key : keys()) + { Expression_Obj lv = at(key); Expression_Obj rv = r->at(key); if (!rv || !lv) return false; @@ -2247,18 +2601,21 @@ namespace Sass { return false; } - bool Null::operator== (const Expression& rhs) const + bool Null::operator==(const Expression& rhs) const { return rhs.concrete_type() == NULL_VAL; } - size_t List::size() const { + size_t List::size() const + { if (!is_arglist_) return length(); // arglist expects a list of arguments // so we need to break before keywords - for (size_t i = 0, L = length(); i < L; ++i) { + for (size_t i = 0, L = length(); i < L; ++i) + { Expression_Obj obj = this->at(i); - if (Argument_Ptr arg = Cast(obj)) { + if (Argument_Ptr arg = Cast(obj)) + { if (!arg->name().empty()) return i; } } @@ -2268,8 +2625,13 @@ namespace Sass { Expression_Obj Hashed::at(Expression_Obj k) const { if (elements_.count(k)) - { return elements_.at(k); } - else { return NULL; } + { + return elements_.at(k); + } + else + { + return NULL; + } } bool Binary_Expression::is_left_interpolant(void) const @@ -2310,15 +2672,22 @@ namespace Sass { ////////////////////////////////////////////////////////////////////////////////////////// // Additional method on Lists to retrieve values directly or from an encompassed Argument. ////////////////////////////////////////////////////////////////////////////////////////// - Expression_Obj List::value_at_index(size_t i) { + Expression_Obj List::value_at_index(size_t i) + { Expression_Obj obj = this->at(i); - if (is_arglist_) { - if (Argument_Ptr arg = Cast(obj)) { + if (is_arglist_) + { + if (Argument_Ptr arg = Cast(obj)) + { return arg->value(); - } else { + } + else + { return obj; } - } else { + } + else + { return obj; } } @@ -2326,10 +2695,12 @@ namespace Sass { ////////////////////////////////////////////////////////////////////////////////////////// // Convert map to (key, value) list. ////////////////////////////////////////////////////////////////////////////////////////// - List_Obj Map::to_list(ParserState& pstate) { + List_Obj Map::to_list(ParserState& pstate) + { List_Obj ret = SASS_MEMORY_NEW(List, pstate, length(), SASS_COMMA); - for (auto key : keys()) { + for (auto key : keys()) + { List_Obj l = SASS_MEMORY_NEW(List, pstate, 2); l->append(key); l->append(at(key)); @@ -2339,37 +2710,41 @@ namespace Sass { return ret; } - ////////////////////////////////////////////////////////////////////////////////////////// - // Copy implementations - ////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////// +// Copy implementations +////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef DEBUG_SHARED_PTR - #ifdef DEBUG_SHARED_PTR - - #define IMPLEMENT_AST_OPERATORS(klass) \ - klass##_Ptr klass::copy(std::string file, size_t line) const { \ - klass##_Ptr cpy = new klass(this); \ - cpy->trace(file, line); \ - return cpy; \ - } \ - klass##_Ptr klass::clone(std::string file, size_t line) const { \ - klass##_Ptr cpy = copy(file, line); \ - cpy->cloneChildren(); \ - return cpy; \ - } \ - - #else - - #define IMPLEMENT_AST_OPERATORS(klass) \ - klass##_Ptr klass::copy() const { \ - return new klass(this); \ - } \ - klass##_Ptr klass::clone() const { \ - klass##_Ptr cpy = copy(); \ - cpy->cloneChildren(); \ - return cpy; \ - } \ - - #endif +#define IMPLEMENT_AST_OPERATORS(klass) \ + klass##_Ptr klass::copy(std::string file, size_t line) const \ + { \ + klass##_Ptr cpy = new klass(this); \ + cpy->trace(file, line); \ + return cpy; \ + } \ + klass##_Ptr klass::clone(std::string file, size_t line) const \ + { \ + klass##_Ptr cpy = copy(file, line); \ + cpy->cloneChildren(); \ + return cpy; \ + } + +#else + +#define IMPLEMENT_AST_OPERATORS(klass) \ + klass##_Ptr klass::copy() const \ + { \ + return new klass(this); \ + } \ + klass##_Ptr klass::clone() const \ + { \ + klass##_Ptr cpy = copy(); \ + cpy->cloneChildren(); \ + return cpy; \ + } + +#endif IMPLEMENT_AST_OPERATORS(Supports_Operator); IMPLEMENT_AST_OPERATORS(Supports_Negation); @@ -2437,5 +2812,4 @@ namespace Sass { IMPLEMENT_AST_OPERATORS(Placeholder_Selector); IMPLEMENT_AST_OPERATORS(Definition); IMPLEMENT_AST_OPERATORS(Declaration); - } diff --git a/src/ast.hpp b/src/ast.hpp index 5c6da5e3f6..d94a8b7cca 100644 --- a/src/ast.hpp +++ b/src/ast.hpp @@ -15,23 +15,23 @@ #ifdef DEBUG_SHARED_PTR -#define ATTACH_VIRTUAL_AST_OPERATIONS(klass) \ +#define ATTACH_VIRTUAL_AST_OPERATIONS(klass) \ virtual klass##_Ptr copy(std::string, size_t) const = 0; \ - virtual klass##_Ptr clone(std::string, size_t) const = 0; \ + virtual klass##_Ptr clone(std::string, size_t) const = 0; -#define ATTACH_AST_OPERATIONS(klass) \ +#define ATTACH_AST_OPERATIONS(klass) \ virtual klass##_Ptr copy(std::string, size_t) const; \ - virtual klass##_Ptr clone(std::string, size_t) const; \ + virtual klass##_Ptr clone(std::string, size_t) const; #else #define ATTACH_VIRTUAL_AST_OPERATIONS(klass) \ - virtual klass##_Ptr copy() const = 0; \ - virtual klass##_Ptr clone() const = 0; \ + virtual klass##_Ptr copy() const = 0; \ + virtual klass##_Ptr clone() const = 0; #define ATTACH_AST_OPERATIONS(klass) \ - virtual klass##_Ptr copy() const; \ - virtual klass##_Ptr clone() const; \ + virtual klass##_Ptr copy() const; \ + virtual klass##_Ptr clone() const; #endif @@ -66,7 +66,8 @@ #include "sass.h" -namespace Sass { +namespace Sass +{ // easier to search with name const bool DELAYED = true; @@ -77,15 +78,18 @@ namespace Sass { // ToDo: where does this fit best? // We don't share this with C-API? - class Operand { + class Operand + { public: - Operand(Sass_OP operand, bool ws_before = false, bool ws_after = false) - : operand(operand), ws_before(ws_before), ws_after(ws_after) - { } + Operand(Sass_OP operand, bool ws_before = false, bool ws_after = false) + : operand(operand), ws_before(ws_before), ws_after(ws_after) + { + } + public: - enum Sass_OP operand; - bool ws_before; - bool ws_after; + enum Sass_OP operand; + bool ws_before; + bool ws_after; }; ////////////////////////////////////////////////////////// @@ -93,60 +97,76 @@ namespace Sass { // http://www.boost.org/doc/libs/1_35_0/doc/html/hash/combine.html // Boost Software License - Version 1.0 // http://www.boost.org/users/license.html - template - void hash_combine (std::size_t& seed, const T& val) + template void hash_combine(std::size_t& seed, const T& val) { - seed ^= std::hash()(val) + 0x9e3779b9 - + (seed<<6) + (seed>>2); + seed ^= std::hash()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2); } ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// // Abstract base class for all abstract syntax tree nodes. ////////////////////////////////////////////////////////// - class AST_Node : public SharedObj { + class AST_Node : public SharedObj + { ADD_PROPERTY(ParserState, pstate) - public: - AST_Node(ParserState pstate) - : pstate_(pstate) - { } - AST_Node(const AST_Node* ptr) - : pstate_(ptr->pstate_) - { } + public: + AST_Node(ParserState pstate) : pstate_(pstate) + { + } + AST_Node(const AST_Node* ptr) : pstate_(ptr->pstate_) + { + } // AST_Node(AST_Node& ptr) = delete; virtual ~AST_Node() = 0; - virtual size_t hash() { return 0; } + virtual size_t hash() + { + return 0; + } ATTACH_VIRTUAL_AST_OPERATIONS(AST_Node); - virtual std::string inspect() const { return to_string({ INSPECT, 5 }); } - virtual std::string to_sass() const { return to_string({ TO_SASS, 5 }); } + virtual std::string inspect() const + { + return to_string({ INSPECT, 5 }); + } + virtual std::string to_sass() const + { + return to_string({ TO_SASS, 5 }); + } virtual const std::string to_string(Sass_Inspect_Options opt) const; virtual const std::string to_string() const; - virtual void cloneChildren() {}; - public: + virtual void cloneChildren(){}; + + public: void update_pstate(const ParserState& pstate); - public: - Offset off() { return pstate(); } - Position pos() { return pstate(); } + + public: + Offset off() + { + return pstate(); + } + Position pos() + { + return pstate(); + } ATTACH_OPERATIONS() }; - inline AST_Node::~AST_Node() { } + inline AST_Node::~AST_Node() + { + } ////////////////////////////////////////////////////////////////////// // define cast template now (need complete type) ////////////////////////////////////////////////////////////////////// - template - T* Cast(AST_Node* ptr) { - return ptr && typeid(T) == typeid(*ptr) ? - static_cast(ptr) : NULL; + template T* Cast(AST_Node* ptr) + { + return ptr && typeid(T) == typeid(*ptr) ? static_cast(ptr) : NULL; }; - template - const T* Cast(const AST_Node* ptr) { - return ptr && typeid(T) == typeid(*ptr) ? - static_cast(ptr) : NULL; + template const T* Cast(const AST_Node* ptr) + { + return ptr && typeid(T) == typeid(*ptr) ? static_cast(ptr) : NULL; }; ////////////////////////////////////////////////////////////////////// @@ -154,9 +174,11 @@ namespace Sass { // represents elements in value contexts, which exist primarily to be // evaluated and returned. ////////////////////////////////////////////////////////////////////// - class Expression : public AST_Node { - public: - enum Concrete_Type { + class Expression : public AST_Node + { + public: + enum Concrete_Type + { NONE, BOOLEAN, NUMBER, @@ -172,83 +194,127 @@ namespace Sass { VARIABLE, NUM_TYPES }; - enum Simple_Type { + enum Simple_Type + { SIMPLE, ATTR_SEL, PSEUDO_SEL, WRAPPED_SEL, }; - private: + + private: // expressions in some contexts shouldn't be evaluated ADD_PROPERTY(bool, is_delayed) ADD_PROPERTY(bool, is_expanded) ADD_PROPERTY(bool, is_interpolant) ADD_PROPERTY(Concrete_Type, concrete_type) - public: - Expression(ParserState pstate, - bool d = false, bool e = false, bool i = false, Concrete_Type ct = NONE) - : AST_Node(pstate), - is_delayed_(d), - is_expanded_(e), - is_interpolant_(i), - concrete_type_(ct) - { } + public: + Expression(ParserState pstate, bool d = false, bool e = false, bool i = false, Concrete_Type ct = NONE) + : AST_Node(pstate), is_delayed_(d), is_expanded_(e), is_interpolant_(i), concrete_type_(ct) + { + } Expression(const Expression* ptr) - : AST_Node(ptr), - is_delayed_(ptr->is_delayed_), - is_expanded_(ptr->is_expanded_), - is_interpolant_(ptr->is_interpolant_), - concrete_type_(ptr->concrete_type_) - { } - virtual operator bool() { return true; } - virtual ~Expression() { } - virtual std::string type() const { return ""; /* TODO: raise an error? */ } - virtual bool is_invisible() const { return false; } - static std::string type_name() { return ""; } - virtual bool is_false() { return false; } + : AST_Node(ptr), is_delayed_(ptr->is_delayed_), is_expanded_(ptr->is_expanded_), + is_interpolant_(ptr->is_interpolant_), concrete_type_(ptr->concrete_type_) + { + } + virtual operator bool() + { + return true; + } + virtual ~Expression() + { + } + virtual std::string type() const + { + return ""; /* TODO: raise an error? */ + } + virtual bool is_invisible() const + { + return false; + } + static std::string type_name() + { + return ""; + } + virtual bool is_false() + { + return false; + } // virtual bool is_true() { return !is_false(); } - virtual bool operator== (const Expression& rhs) const { return false; } - virtual bool eq(const Expression& rhs) const { return *this == rhs; }; - virtual void set_delayed(bool delayed) { is_delayed(delayed); } - virtual bool has_interpolant() const { return is_interpolant(); } - virtual bool is_left_interpolant() const { return is_interpolant(); } - virtual bool is_right_interpolant() const { return is_interpolant(); } - virtual std::string inspect() const { return to_string({ INSPECT, 5 }); } - virtual std::string to_sass() const { return to_string({ TO_SASS, 5 }); } + virtual bool operator==(const Expression& rhs) const + { + return false; + } + virtual bool eq(const Expression& rhs) const + { + return *this == rhs; + }; + virtual void set_delayed(bool delayed) + { + is_delayed(delayed); + } + virtual bool has_interpolant() const + { + return is_interpolant(); + } + virtual bool is_left_interpolant() const + { + return is_interpolant(); + } + virtual bool is_right_interpolant() const + { + return is_interpolant(); + } + virtual std::string inspect() const + { + return to_string({ INSPECT, 5 }); + } + virtual std::string to_sass() const + { + return to_string({ TO_SASS, 5 }); + } ATTACH_VIRTUAL_AST_OPERATIONS(Expression); - virtual size_t hash() { return 0; } + virtual size_t hash() + { + return 0; + } }; ////////////////////////////////////////////////////////////////////// // Still just an expression, but with a to_string method ////////////////////////////////////////////////////////////////////// - class PreValue : public Expression { - public: - PreValue(ParserState pstate, - bool d = false, bool e = false, bool i = false, Concrete_Type ct = NONE) + class PreValue : public Expression + { + public: + PreValue(ParserState pstate, bool d = false, bool e = false, bool i = false, Concrete_Type ct = NONE) : Expression(pstate, d, e, i, ct) - { } - PreValue(const PreValue* ptr) - : Expression(ptr) - { } + { + } + PreValue(const PreValue* ptr) : Expression(ptr) + { + } ATTACH_VIRTUAL_AST_OPERATIONS(PreValue); - virtual ~PreValue() { } + virtual ~PreValue() + { + } }; ////////////////////////////////////////////////////////////////////// // base class for values that support operations ////////////////////////////////////////////////////////////////////// - class Value : public Expression { - public: - Value(ParserState pstate, - bool d = false, bool e = false, bool i = false, Concrete_Type ct = NONE) + class Value : public Expression + { + public: + Value(ParserState pstate, bool d = false, bool e = false, bool i = false, Concrete_Type ct = NONE) : Expression(pstate, d, e, i, ct) - { } - Value(const Value* ptr) - : Expression(ptr) - { } + { + } + Value(const Value* ptr) : Expression(ptr) + { + } ATTACH_VIRTUAL_AST_OPERATIONS(Value); - virtual bool operator== (const Expression& rhs) const = 0; + virtual bool operator==(const Expression& rhs) const = 0; }; } @@ -256,55 +322,92 @@ namespace Sass { // Hash method specializations for std::unordered_map to work with Sass::Expression ///////////////////////////////////////////////////////////////////////////////////// -namespace std { - template<> - struct hash +namespace std +{ + template <> struct hash { size_t operator()(Sass::Expression_Obj s) const { return s->hash(); } }; - template<> - struct equal_to + template <> struct equal_to { - bool operator()( Sass::Expression_Obj lhs, Sass::Expression_Obj rhs) const + bool operator()(Sass::Expression_Obj lhs, Sass::Expression_Obj rhs) const { return lhs->hash() == rhs->hash(); } }; } -namespace Sass { +namespace Sass +{ ///////////////////////////////////////////////////////////////////////////// // Mixin class for AST nodes that should behave like vectors. Uses the // "Template Method" design pattern to allow subclasses to adjust their flags // when certain objects are pushed. ///////////////////////////////////////////////////////////////////////////// - template - class Vectorized { + template class Vectorized + { std::vector elements_; - protected: + + protected: size_t hash_; - void reset_hash() { hash_ = 0; } - virtual void adjust_after_pushing(T element) { } - public: + void reset_hash() + { + hash_ = 0; + } + virtual void adjust_after_pushing(T element) + { + } + + public: Vectorized(size_t s = 0) : elements_(std::vector()), hash_(0) - { elements_.reserve(s); } + { + elements_.reserve(s); + } virtual ~Vectorized() = 0; - size_t length() const { return elements_.size(); } - bool empty() const { return elements_.empty(); } - void clear() { return elements_.clear(); } - T last() const { return elements_.back(); } - T first() const { return elements_.front(); } - T& operator[](size_t i) { return elements_[i]; } - virtual const T& at(size_t i) const { return elements_.at(i); } - virtual T& at(size_t i) { return elements_.at(i); } - const T& operator[](size_t i) const { return elements_[i]; } + size_t length() const + { + return elements_.size(); + } + bool empty() const + { + return elements_.empty(); + } + void clear() + { + return elements_.clear(); + } + T last() const + { + return elements_.back(); + } + T first() const + { + return elements_.front(); + } + T& operator[](size_t i) + { + return elements_[i]; + } + virtual const T& at(size_t i) const + { + return elements_.at(i); + } + virtual T& at(size_t i) + { + return elements_.at(i); + } + const T& operator[](size_t i) const + { + return elements_[i]; + } virtual void append(T element) { - if (element) { + if (element) + { reset_hash(); elements_.push_back(element); adjust_after_pushing(element); @@ -312,72 +415,135 @@ namespace Sass { } virtual void concat(Vectorized* v) { - for (size_t i = 0, L = v->length(); i < L; ++i) this->append((*v)[i]); + for (size_t i = 0, L = v->length(); i < L; ++i) + this->append((*v)[i]); } Vectorized& unshift(T element) { elements_.insert(elements_.begin(), element); return *this; } - std::vector& elements() { return elements_; } - const std::vector& elements() const { return elements_; } - std::vector& elements(std::vector& e) { elements_ = e; return elements_; } + std::vector& elements() + { + return elements_; + } + const std::vector& elements() const + { + return elements_; + } + std::vector& elements(std::vector& e) + { + elements_ = e; + return elements_; + } virtual size_t hash() { - if (hash_ == 0) { - for (T& el : elements_) { + if (hash_ == 0) + { + for (T& el : elements_) + { hash_combine(hash_, el->hash()); } } return hash_; } - typename std::vector::iterator end() { return elements_.end(); } - typename std::vector::iterator begin() { return elements_.begin(); } - typename std::vector::const_iterator end() const { return elements_.end(); } - typename std::vector::const_iterator begin() const { return elements_.begin(); } - typename std::vector::iterator erase(typename std::vector::iterator el) { return elements_.erase(el); } - typename std::vector::const_iterator erase(typename std::vector::const_iterator el) { return elements_.erase(el); } - + typename std::vector::iterator end() + { + return elements_.end(); + } + typename std::vector::iterator begin() + { + return elements_.begin(); + } + typename std::vector::const_iterator end() const + { + return elements_.end(); + } + typename std::vector::const_iterator begin() const + { + return elements_.begin(); + } + typename std::vector::iterator erase(typename std::vector::iterator el) + { + return elements_.erase(el); + } + typename std::vector::const_iterator erase(typename std::vector::const_iterator el) + { + return elements_.erase(el); + } }; - template - inline Vectorized::~Vectorized() { } + template inline Vectorized::~Vectorized() + { + } ///////////////////////////////////////////////////////////////////////////// // Mixin class for AST nodes that should behave like a hash table. Uses an // extra internally to maintain insertion order for interation. ///////////////////////////////////////////////////////////////////////////// - class Hashed { - private: + class Hashed + { + private: ExpressionMap elements_; std::vector list_; - protected: + + protected: size_t hash_; Expression_Obj duplicate_key_; - void reset_hash() { hash_ = 0; } - void reset_duplicate_key() { duplicate_key_ = 0; } - virtual void adjust_after_pushing(std::pair p) { } - public: + void reset_hash() + { + hash_ = 0; + } + void reset_duplicate_key() + { + duplicate_key_ = 0; + } + virtual void adjust_after_pushing(std::pair p) + { + } + + public: Hashed(size_t s = 0) - : elements_(ExpressionMap(s)), - list_(std::vector()), - hash_(0), duplicate_key_(NULL) - { elements_.reserve(s); list_.reserve(s); } + : elements_(ExpressionMap(s)), list_(std::vector()), hash_(0), duplicate_key_(NULL) + { + elements_.reserve(s); + list_.reserve(s); + } virtual ~Hashed(); - size_t length() const { return list_.size(); } - bool empty() const { return list_.empty(); } - bool has(Expression_Obj k) const { return elements_.count(k) == 1; } + size_t length() const + { + return list_.size(); + } + bool empty() const + { + return list_.empty(); + } + bool has(Expression_Obj k) const + { + return elements_.count(k) == 1; + } Expression_Obj at(Expression_Obj k) const; - bool has_duplicate_key() const { return duplicate_key_ != 0; } - Expression_Obj get_duplicate_key() const { return duplicate_key_; } - const ExpressionMap elements() { return elements_; } + bool has_duplicate_key() const + { + return duplicate_key_ != 0; + } + Expression_Obj get_duplicate_key() const + { + return duplicate_key_; + } + const ExpressionMap elements() + { + return elements_; + } Hashed& operator<<(std::pair p) { reset_hash(); - if (!has(p.first)) list_.push_back(p.first); - else if (!duplicate_key_) duplicate_key_ = p.first; + if (!has(p.first)) + list_.push_back(p.first); + else if (!duplicate_key_) + duplicate_key_ = p.first; elements_[p.first] = p.second; @@ -386,29 +552,42 @@ namespace Sass { } Hashed& operator+=(Hashed* h) { - if (length() == 0) { + if (length() == 0) + { this->elements_ = h->elements_; this->list_ = h->list_; return *this; } - for (auto key : h->keys()) { + for (auto key : h->keys()) + { *this << std::make_pair(key, h->at(key)); } reset_duplicate_key(); return *this; } - const ExpressionMap& pairs() const { return elements_; } - const std::vector& keys() const { return list_; } - -// std::unordered_map::iterator end() { return elements_.end(); } -// std::unordered_map::iterator begin() { return elements_.begin(); } -// std::unordered_map::const_iterator end() const { return elements_.end(); } -// std::unordered_map::const_iterator begin() const { return elements_.begin(); } + const ExpressionMap& pairs() const + { + return elements_; + } + const std::vector& keys() const + { + return list_; + } + // std::unordered_map::iterator end() { return + // elements_.end(); } + // std::unordered_map::iterator begin() { return + // elements_.begin(); } + // std::unordered_map::const_iterator end() const { return + // elements_.end(); } + // std::unordered_map::const_iterator begin() const { return + // elements_.begin(); } }; - inline Hashed::~Hashed() { } + inline Hashed::~Hashed() + { + } ///////////////////////////////////////////////////////////////////////// @@ -416,9 +595,11 @@ namespace Sass { // represents elements in expansion contexts, which exist primarily to be // rewritten and macro-expanded. ///////////////////////////////////////////////////////////////////////// - class Statement : public AST_Node { - public: - enum Statement_Type { + class Statement : public AST_Node + { + public: + enum Statement_Type + { NONE, RULESET, MEDIA, @@ -443,55 +624,64 @@ namespace Sass { FOR, IF }; - private: + + private: ADD_PROPERTY(Statement_Type, statement_type) ADD_PROPERTY(size_t, tabs) ADD_PROPERTY(bool, group_end) - public: + public: Statement(ParserState pstate, Statement_Type st = NONE, size_t t = 0) : AST_Node(pstate), statement_type_(st), tabs_(t), group_end_(false) - { } + { + } Statement(const Statement* ptr) - : AST_Node(ptr), - statement_type_(ptr->statement_type_), - tabs_(ptr->tabs_), - group_end_(ptr->group_end_) - { } + : AST_Node(ptr), statement_type_(ptr->statement_type_), tabs_(ptr->tabs_), group_end_(ptr->group_end_) + { + } virtual ~Statement() = 0; // needed for rearranging nested rulesets during CSS emission - virtual bool is_invisible() const { return false; } - virtual bool bubbles() { return false; } + virtual bool is_invisible() const + { + return false; + } + virtual bool bubbles() + { + return false; + } virtual bool has_content() { return statement_type_ == CONTENT; } }; - inline Statement::~Statement() { } + inline Statement::~Statement() + { + } //////////////////////// // Blocks of statements. //////////////////////// - class Block : public Statement, public Vectorized { + class Block : public Statement, public Vectorized + { ADD_PROPERTY(bool, is_root) // needed for properly formatted CSS emission - protected: + protected: void adjust_after_pushing(Statement_Obj s) { } - public: + + public: Block(ParserState pstate, size_t s = 0, bool r = false) - : Statement(pstate), - Vectorized(s), - is_root_(r) - { } + : Statement(pstate), Vectorized(s), is_root_(r) + { + } Block(const Block* ptr) - : Statement(ptr), - Vectorized(*ptr), - is_root_(ptr->is_root_) - { } + : Statement(ptr), Vectorized(*ptr), is_root_(ptr->is_root_) + { + } virtual bool has_content() { - for (size_t i = 0, L = elements().size(); i < L; ++i) { + for (size_t i = 0, L = elements().size(); i < L; ++i) + { if (elements()[i]->has_content()) return true; } return Statement::has_content(); @@ -503,39 +693,45 @@ namespace Sass { //////////////////////////////////////////////////////////////////////// // Abstract base class for statements that contain blocks of statements. //////////////////////////////////////////////////////////////////////// - class Has_Block : public Statement { + class Has_Block : public Statement + { ADD_PROPERTY(Block_Obj, block) - public: - Has_Block(ParserState pstate, Block_Obj b) - : Statement(pstate), block_(b) - { } - Has_Block(const Has_Block* ptr) - : Statement(ptr), block_(ptr->block_) - { } + public: + Has_Block(ParserState pstate, Block_Obj b) : Statement(pstate), block_(b) + { + } + Has_Block(const Has_Block* ptr) : Statement(ptr), block_(ptr->block_) + { + } virtual bool has_content() { return (block_ && block_->has_content()) || Statement::has_content(); } virtual ~Has_Block() = 0; }; - inline Has_Block::~Has_Block() { } + inline Has_Block::~Has_Block() + { + } ///////////////////////////////////////////////////////////////////////////// // Rulesets (i.e., sets of styles headed by a selector and containing a block // of style declarations. ///////////////////////////////////////////////////////////////////////////// - class Ruleset : public Has_Block { + class Ruleset : public Has_Block + { ADD_PROPERTY(Selector_List_Obj, selector) ADD_PROPERTY(bool, is_root); - public: + + public: Ruleset(ParserState pstate, Selector_List_Obj s = 0, Block_Obj b = 0) : Has_Block(pstate, b), selector_(s), is_root_(false) - { statement_type(RULESET); } - Ruleset(const Ruleset* ptr) - : Has_Block(ptr), - selector_(ptr->selector_), - is_root_(ptr->is_root_) - { statement_type(RULESET); } + { + statement_type(RULESET); + } + Ruleset(const Ruleset* ptr) : Has_Block(ptr), selector_(ptr->selector_), is_root_(ptr->is_root_) + { + statement_type(RULESET); + } bool is_invisible() const; ATTACH_AST_OPERATIONS(Ruleset) ATTACH_OPERATIONS() @@ -544,19 +740,22 @@ namespace Sass { ///////////////// // Bubble. ///////////////// - class Bubble : public Statement { + class Bubble : public Statement + { ADD_PROPERTY(Statement_Obj, node) ADD_PROPERTY(bool, group_end) - public: + public: Bubble(ParserState pstate, Statement_Obj n, Statement_Obj g = 0, size_t t = 0) : Statement(pstate, Statement::BUBBLE, t), node_(n), group_end_(g == 0) - { } - Bubble(const Bubble* ptr) - : Statement(ptr), - node_(ptr->node_), - group_end_(ptr->group_end_) - { } - bool bubbles() { return true; } + { + } + Bubble(const Bubble* ptr) : Statement(ptr), node_(ptr->node_), group_end_(ptr->group_end_) + { + } + bool bubbles() + { + return true; + } ATTACH_AST_OPERATIONS(Bubble) ATTACH_OPERATIONS() }; @@ -564,16 +763,16 @@ namespace Sass { ///////////////// // Trace. ///////////////// - class Trace : public Has_Block { + class Trace : public Has_Block + { ADD_CONSTREF(std::string, name) - public: - Trace(ParserState pstate, std::string n, Block_Obj b = 0) - : Has_Block(pstate, b), name_(n) - { } - Trace(const Trace* ptr) - : Has_Block(ptr), - name_(ptr->name_) - { } + public: + Trace(ParserState pstate, std::string n, Block_Obj b = 0) : Has_Block(pstate, b), name_(n) + { + } + Trace(const Trace* ptr) : Has_Block(ptr), name_(ptr->name_) + { + } ATTACH_AST_OPERATIONS(Trace) ATTACH_OPERATIONS() }; @@ -581,16 +780,23 @@ namespace Sass { ///////////////// // Media queries. ///////////////// - class Media_Block : public Has_Block { + class Media_Block : public Has_Block + { ADD_PROPERTY(List_Obj, media_queries) - public: + public: Media_Block(ParserState pstate, List_Obj mqs, Block_Obj b) : Has_Block(pstate, b), media_queries_(mqs) - { statement_type(MEDIA); } - Media_Block(const Media_Block* ptr) - : Has_Block(ptr), media_queries_(ptr->media_queries_) - { statement_type(MEDIA); } - bool bubbles() { return true; } + { + statement_type(MEDIA); + } + Media_Block(const Media_Block* ptr) : Has_Block(ptr), media_queries_(ptr->media_queries_) + { + statement_type(MEDIA); + } + bool bubbles() + { + return true; + } bool is_invisible() const; ATTACH_AST_OPERATIONS(Media_Block) ATTACH_OPERATIONS() @@ -600,32 +806,37 @@ namespace Sass { // At-rules -- arbitrary directives beginning with "@" that may have an // optional statement block. /////////////////////////////////////////////////////////////////////// - class Directive : public Has_Block { + class Directive : public Has_Block + { ADD_CONSTREF(std::string, keyword) ADD_PROPERTY(Selector_List_Obj, selector) ADD_PROPERTY(Expression_Obj, value) - public: + public: Directive(ParserState pstate, std::string kwd, Selector_List_Obj sel = 0, Block_Obj b = 0, Expression_Obj val = 0) - : Has_Block(pstate, b), keyword_(kwd), selector_(sel), value_(val) // set value manually if needed - { statement_type(DIRECTIVE); } + : Has_Block(pstate, b), keyword_(kwd), selector_(sel), + value_(val) // set value manually if needed + { + statement_type(DIRECTIVE); + } Directive(const Directive* ptr) - : Has_Block(ptr), - keyword_(ptr->keyword_), - selector_(ptr->selector_), + : Has_Block(ptr), keyword_(ptr->keyword_), selector_(ptr->selector_), value_(ptr->value_) // set value manually if needed - { statement_type(DIRECTIVE); } - bool bubbles() { return is_keyframes() || is_media(); } - bool is_media() { - return keyword_.compare("@-webkit-media") == 0 || - keyword_.compare("@-moz-media") == 0 || - keyword_.compare("@-o-media") == 0 || - keyword_.compare("@media") == 0; - } - bool is_keyframes() { - return keyword_.compare("@-webkit-keyframes") == 0 || - keyword_.compare("@-moz-keyframes") == 0 || - keyword_.compare("@-o-keyframes") == 0 || - keyword_.compare("@keyframes") == 0; + { + statement_type(DIRECTIVE); + } + bool bubbles() + { + return is_keyframes() || is_media(); + } + bool is_media() + { + return keyword_.compare("@-webkit-media") == 0 || keyword_.compare("@-moz-media") == 0 || + keyword_.compare("@-o-media") == 0 || keyword_.compare("@media") == 0; + } + bool is_keyframes() + { + return keyword_.compare("@-webkit-keyframes") == 0 || keyword_.compare("@-moz-keyframes") == 0 || + keyword_.compare("@-o-keyframes") == 0 || keyword_.compare("@keyframes") == 0; } ATTACH_AST_OPERATIONS(Directive) ATTACH_OPERATIONS() @@ -634,17 +845,20 @@ namespace Sass { /////////////////////////////////////////////////////////////////////// // Keyframe-rules -- the child blocks of "@keyframes" nodes. /////////////////////////////////////////////////////////////////////// - class Keyframe_Rule : public Has_Block { + class Keyframe_Rule : public Has_Block + { // according to css spec, this should be // = | ADD_PROPERTY(Selector_List_Obj, name) - public: - Keyframe_Rule(ParserState pstate, Block_Obj b) - : Has_Block(pstate, b), name_() - { statement_type(KEYFRAMERULE); } - Keyframe_Rule(const Keyframe_Rule* ptr) - : Has_Block(ptr), name_(ptr->name_) - { statement_type(KEYFRAMERULE); } + public: + Keyframe_Rule(ParserState pstate, Block_Obj b) : Has_Block(pstate, b), name_() + { + statement_type(KEYFRAMERULE); + } + Keyframe_Rule(const Keyframe_Rule* ptr) : Has_Block(ptr), name_(ptr->name_) + { + statement_type(KEYFRAMERULE); + } ATTACH_AST_OPERATIONS(Keyframe_Rule) ATTACH_OPERATIONS() }; @@ -652,23 +866,24 @@ namespace Sass { //////////////////////////////////////////////////////////////////////// // Declarations -- style rules consisting of a property name and values. //////////////////////////////////////////////////////////////////////// - class Declaration : public Has_Block { + class Declaration : public Has_Block + { ADD_PROPERTY(String_Obj, property) ADD_PROPERTY(Expression_Obj, value) ADD_PROPERTY(bool, is_important) ADD_PROPERTY(bool, is_indented) - public: - Declaration(ParserState pstate, - String_Obj prop, Expression_Obj val, bool i = false, Block_Obj b = 0) + public: + Declaration(ParserState pstate, String_Obj prop, Expression_Obj val, bool i = false, Block_Obj b = 0) : Has_Block(pstate, b), property_(prop), value_(val), is_important_(i), is_indented_(false) - { statement_type(DECLARATION); } + { + statement_type(DECLARATION); + } Declaration(const Declaration* ptr) - : Has_Block(ptr), - property_(ptr->property_), - value_(ptr->value_), - is_important_(ptr->is_important_), - is_indented_(ptr->is_indented_) - { statement_type(DECLARATION); } + : Has_Block(ptr), property_(ptr->property_), value_(ptr->value_), + is_important_(ptr->is_important_), is_indented_(ptr->is_indented_) + { + statement_type(DECLARATION); + } ATTACH_AST_OPERATIONS(Declaration) ATTACH_OPERATIONS() }; @@ -676,25 +891,24 @@ namespace Sass { ///////////////////////////////////// // Assignments -- variable and value. ///////////////////////////////////// - class Assignment : public Statement { + class Assignment : public Statement + { ADD_CONSTREF(std::string, variable) ADD_PROPERTY(Expression_Obj, value) ADD_PROPERTY(bool, is_default) ADD_PROPERTY(bool, is_global) - public: - Assignment(ParserState pstate, - std::string var, Expression_Obj val, - bool is_default = false, - bool is_global = false) + public: + Assignment(ParserState pstate, std::string var, Expression_Obj val, bool is_default = false, bool is_global = false) : Statement(pstate), variable_(var), value_(val), is_default_(is_default), is_global_(is_global) - { statement_type(ASSIGNMENT); } + { + statement_type(ASSIGNMENT); + } Assignment(const Assignment* ptr) - : Statement(ptr), - variable_(ptr->variable_), - value_(ptr->value_), - is_default_(ptr->is_default_), + : Statement(ptr), variable_(ptr->variable_), value_(ptr->value_), is_default_(ptr->is_default_), is_global_(ptr->is_global_) - { statement_type(ASSIGNMENT); } + { + statement_type(ASSIGNMENT); + } ATTACH_AST_OPERATIONS(Assignment) ATTACH_OPERATIONS() }; @@ -703,44 +917,64 @@ namespace Sass { // Import directives. CSS and Sass import lists can be intermingled, so it's // necessary to store a list of each in an Import node. //////////////////////////////////////////////////////////////////////////// - class Import : public Statement { + class Import : public Statement + { std::vector urls_; - std::vector incs_; - ADD_PROPERTY(List_Obj, import_queries); - public: + std::vector incs_; + ADD_PROPERTY(List_Obj, import_queries); + + public: Import(ParserState pstate) - : Statement(pstate), - urls_(std::vector()), - incs_(std::vector()), + : Statement(pstate), urls_(std::vector()), incs_(std::vector()), import_queries_() - { statement_type(IMPORT); } + { + statement_type(IMPORT); + } Import(const Import* ptr) - : Statement(ptr), - urls_(ptr->urls_), - incs_(ptr->incs_), - import_queries_(ptr->import_queries_) - { statement_type(IMPORT); } - std::vector& urls() { return urls_; } - std::vector& incs() { return incs_; } + : Statement(ptr), urls_(ptr->urls_), incs_(ptr->incs_), import_queries_(ptr->import_queries_) + { + statement_type(IMPORT); + } + std::vector& urls() + { + return urls_; + } + std::vector& incs() + { + return incs_; + } ATTACH_AST_OPERATIONS(Import) ATTACH_OPERATIONS() }; // not yet resolved single import // so far we only know requested name - class Import_Stub : public Statement { + class Import_Stub : public Statement + { Include resource_; - public: - std::string abs_path() { return resource_.abs_path; }; - std::string imp_path() { return resource_.imp_path; }; - Include resource() { return resource_; }; - - Import_Stub(ParserState pstate, Include res) - : Statement(pstate), resource_(res) - { statement_type(IMPORT_STUB); } - Import_Stub(const Import_Stub* ptr) - : Statement(ptr), resource_(ptr->resource_) - { statement_type(IMPORT_STUB); } + + public: + std::string abs_path() + { + return resource_.abs_path; + }; + std::string imp_path() + { + return resource_.imp_path; + }; + Include resource() + { + return resource_; + }; + + Import_Stub(ParserState pstate, Include res) : Statement(pstate), resource_(res) + { + statement_type(IMPORT_STUB); + } + Import_Stub(const Import_Stub* ptr) : Statement(ptr), resource_(ptr->resource_) + { + statement_type(IMPORT_STUB); + } ATTACH_AST_OPERATIONS(Import_Stub) ATTACH_OPERATIONS() }; @@ -748,15 +982,18 @@ namespace Sass { ////////////////////////////// // The Sass `@warn` directive. ////////////////////////////// - class Warning : public Statement { + class Warning : public Statement + { ADD_PROPERTY(Expression_Obj, message) - public: - Warning(ParserState pstate, Expression_Obj msg) - : Statement(pstate), message_(msg) - { statement_type(WARNING); } - Warning(const Warning* ptr) - : Statement(ptr), message_(ptr->message_) - { statement_type(WARNING); } + public: + Warning(ParserState pstate, Expression_Obj msg) : Statement(pstate), message_(msg) + { + statement_type(WARNING); + } + Warning(const Warning* ptr) : Statement(ptr), message_(ptr->message_) + { + statement_type(WARNING); + } ATTACH_AST_OPERATIONS(Warning) ATTACH_OPERATIONS() }; @@ -764,15 +1001,18 @@ namespace Sass { /////////////////////////////// // The Sass `@error` directive. /////////////////////////////// - class Error : public Statement { + class Error : public Statement + { ADD_PROPERTY(Expression_Obj, message) - public: - Error(ParserState pstate, Expression_Obj msg) - : Statement(pstate), message_(msg) - { statement_type(ERROR); } - Error(const Error* ptr) - : Statement(ptr), message_(ptr->message_) - { statement_type(ERROR); } + public: + Error(ParserState pstate, Expression_Obj msg) : Statement(pstate), message_(msg) + { + statement_type(ERROR); + } + Error(const Error* ptr) : Statement(ptr), message_(ptr->message_) + { + statement_type(ERROR); + } ATTACH_AST_OPERATIONS(Error) ATTACH_OPERATIONS() }; @@ -780,15 +1020,18 @@ namespace Sass { /////////////////////////////// // The Sass `@debug` directive. /////////////////////////////// - class Debug : public Statement { + class Debug : public Statement + { ADD_PROPERTY(Expression_Obj, value) - public: - Debug(ParserState pstate, Expression_Obj val) - : Statement(pstate), value_(val) - { statement_type(DEBUGSTMT); } - Debug(const Debug* ptr) - : Statement(ptr), value_(ptr->value_) - { statement_type(DEBUGSTMT); } + public: + Debug(ParserState pstate, Expression_Obj val) : Statement(pstate), value_(val) + { + statement_type(DEBUGSTMT); + } + Debug(const Debug* ptr) : Statement(ptr), value_(ptr->value_) + { + statement_type(DEBUGSTMT); + } ATTACH_AST_OPERATIONS(Debug) ATTACH_OPERATIONS() }; @@ -796,20 +1039,25 @@ namespace Sass { /////////////////////////////////////////// // CSS comments. These may be interpolated. /////////////////////////////////////////// - class Comment : public Statement { + class Comment : public Statement + { ADD_PROPERTY(String_Obj, text) ADD_PROPERTY(bool, is_important) - public: + public: Comment(ParserState pstate, String_Obj txt, bool is_important) : Statement(pstate), text_(txt), is_important_(is_important) - { statement_type(COMMENT); } + { + statement_type(COMMENT); + } Comment(const Comment* ptr) - : Statement(ptr), - text_(ptr->text_), - is_important_(ptr->is_important_) - { statement_type(COMMENT); } + : Statement(ptr), text_(ptr->text_), is_important_(ptr->is_important_) + { + statement_type(COMMENT); + } virtual bool is_invisible() const - { return /* is_important() == */ false; } + { + return /* is_important() == */ false; + } ATTACH_AST_OPERATIONS(Comment) ATTACH_OPERATIONS() }; @@ -817,18 +1065,20 @@ namespace Sass { //////////////////////////////////// // The Sass `@if` control directive. //////////////////////////////////// - class If : public Has_Block { + class If : public Has_Block + { ADD_PROPERTY(Expression_Obj, predicate) ADD_PROPERTY(Block_Obj, alternative) - public: + public: If(ParserState pstate, Expression_Obj pred, Block_Obj con, Block_Obj alt = 0) : Has_Block(pstate, con), predicate_(pred), alternative_(alt) - { statement_type(IF); } - If(const If* ptr) - : Has_Block(ptr), - predicate_(ptr->predicate_), - alternative_(ptr->alternative_) - { statement_type(IF); } + { + statement_type(IF); + } + If(const If* ptr) : Has_Block(ptr), predicate_(ptr->predicate_), alternative_(ptr->alternative_) + { + statement_type(IF); + } virtual bool has_content() { return Has_Block::has_content() || (alternative_ && alternative_->has_content()); @@ -840,24 +1090,24 @@ namespace Sass { ///////////////////////////////////// // The Sass `@for` control directive. ///////////////////////////////////// - class For : public Has_Block { + class For : public Has_Block + { ADD_CONSTREF(std::string, variable) ADD_PROPERTY(Expression_Obj, lower_bound) ADD_PROPERTY(Expression_Obj, upper_bound) ADD_PROPERTY(bool, is_inclusive) - public: - For(ParserState pstate, - std::string var, Expression_Obj lo, Expression_Obj hi, Block_Obj b, bool inc) - : Has_Block(pstate, b), - variable_(var), lower_bound_(lo), upper_bound_(hi), is_inclusive_(inc) - { statement_type(FOR); } + public: + For(ParserState pstate, std::string var, Expression_Obj lo, Expression_Obj hi, Block_Obj b, bool inc) + : Has_Block(pstate, b), variable_(var), lower_bound_(lo), upper_bound_(hi), is_inclusive_(inc) + { + statement_type(FOR); + } For(const For* ptr) - : Has_Block(ptr), - variable_(ptr->variable_), - lower_bound_(ptr->lower_bound_), - upper_bound_(ptr->upper_bound_), - is_inclusive_(ptr->is_inclusive_) - { statement_type(FOR); } + : Has_Block(ptr), variable_(ptr->variable_), lower_bound_(ptr->lower_bound_), + upper_bound_(ptr->upper_bound_), is_inclusive_(ptr->is_inclusive_) + { + statement_type(FOR); + } ATTACH_AST_OPERATIONS(For) ATTACH_OPERATIONS() }; @@ -865,16 +1115,20 @@ namespace Sass { ////////////////////////////////////// // The Sass `@each` control directive. ////////////////////////////////////// - class Each : public Has_Block { + class Each : public Has_Block + { ADD_PROPERTY(std::vector, variables) ADD_PROPERTY(Expression_Obj, list) - public: + public: Each(ParserState pstate, std::vector vars, Expression_Obj lst, Block_Obj b) : Has_Block(pstate, b), variables_(vars), list_(lst) - { statement_type(EACH); } - Each(const Each* ptr) - : Has_Block(ptr), variables_(ptr->variables_), list_(ptr->list_) - { statement_type(EACH); } + { + statement_type(EACH); + } + Each(const Each* ptr) : Has_Block(ptr), variables_(ptr->variables_), list_(ptr->list_) + { + statement_type(EACH); + } ATTACH_AST_OPERATIONS(Each) ATTACH_OPERATIONS() }; @@ -882,15 +1136,19 @@ namespace Sass { /////////////////////////////////////// // The Sass `@while` control directive. /////////////////////////////////////// - class While : public Has_Block { + class While : public Has_Block + { ADD_PROPERTY(Expression_Obj, predicate) - public: + public: While(ParserState pstate, Expression_Obj pred, Block_Obj b) : Has_Block(pstate, b), predicate_(pred) - { statement_type(WHILE); } - While(const While* ptr) - : Has_Block(ptr), predicate_(ptr->predicate_) - { statement_type(WHILE); } + { + statement_type(WHILE); + } + While(const While* ptr) : Has_Block(ptr), predicate_(ptr->predicate_) + { + statement_type(WHILE); + } ATTACH_AST_OPERATIONS(While) ATTACH_OPERATIONS() }; @@ -898,15 +1156,18 @@ namespace Sass { ///////////////////////////////////////////////////////////// // The @return directive for use inside SassScript functions. ///////////////////////////////////////////////////////////// - class Return : public Statement { + class Return : public Statement + { ADD_PROPERTY(Expression_Obj, value) - public: - Return(ParserState pstate, Expression_Obj val) - : Statement(pstate), value_(val) - { statement_type(RETURN); } - Return(const Return* ptr) - : Statement(ptr), value_(ptr->value_) - { statement_type(RETURN); } + public: + Return(ParserState pstate, Expression_Obj val) : Statement(pstate), value_(val) + { + statement_type(RETURN); + } + Return(const Return* ptr) : Statement(ptr), value_(ptr->value_) + { + statement_type(RETURN); + } ATTACH_AST_OPERATIONS(Return) ATTACH_OPERATIONS() }; @@ -914,15 +1175,18 @@ namespace Sass { //////////////////////////////// // The Sass `@extend` directive. //////////////////////////////// - class Extension : public Statement { + class Extension : public Statement + { ADD_PROPERTY(Selector_List_Obj, selector) - public: - Extension(ParserState pstate, Selector_List_Obj s) - : Statement(pstate), selector_(s) - { statement_type(EXTEND); } - Extension(const Extension* ptr) - : Statement(ptr), selector_(ptr->selector_) - { statement_type(EXTEND); } + public: + Extension(ParserState pstate, Selector_List_Obj s) : Statement(pstate), selector_(s) + { + statement_type(EXTEND); + } + Extension(const Extension* ptr) : Statement(ptr), selector_(ptr->selector_) + { + statement_type(EXTEND); + } ATTACH_AST_OPERATIONS(Extension) ATTACH_OPERATIONS() }; @@ -934,9 +1198,14 @@ namespace Sass { struct Backtrace; typedef const char* Signature; typedef Expression_Ptr (*Native_Function)(Env&, Env&, Context&, Signature, ParserState, Backtrace*, std::vector); - class Definition : public Has_Block { - public: - enum Type { MIXIN, FUNCTION }; + class Definition : public Has_Block + { + public: + enum Type + { + MIXIN, + FUNCTION + }; ADD_CONSTREF(std::string, name) ADD_PROPERTY(Parameters_Obj, parameters) ADD_PROPERTY(Env*, environment) @@ -946,71 +1215,31 @@ namespace Sass { ADD_PROPERTY(void*, cookie) ADD_PROPERTY(bool, is_overload_stub) ADD_PROPERTY(Signature, signature) - public: + public: Definition(const Definition* ptr) - : Has_Block(ptr), - name_(ptr->name_), - parameters_(ptr->parameters_), - environment_(ptr->environment_), - type_(ptr->type_), - native_function_(ptr->native_function_), - c_function_(ptr->c_function_), - cookie_(ptr->cookie_), - is_overload_stub_(ptr->is_overload_stub_), - signature_(ptr->signature_) - { } - - Definition(ParserState pstate, - std::string n, - Parameters_Obj params, - Block_Obj b, - Type t) - : Has_Block(pstate, b), - name_(n), - parameters_(params), - environment_(0), - type_(t), - native_function_(0), - c_function_(0), - cookie_(0), - is_overload_stub_(false), - signature_(0) - { } - Definition(ParserState pstate, - Signature sig, - std::string n, - Parameters_Obj params, - Native_Function func_ptr, - bool overload_stub = false) - : Has_Block(pstate, 0), - name_(n), - parameters_(params), - environment_(0), - type_(FUNCTION), - native_function_(func_ptr), - c_function_(0), - cookie_(0), - is_overload_stub_(overload_stub), - signature_(sig) - { } - Definition(ParserState pstate, - Signature sig, - std::string n, - Parameters_Obj params, - Sass_Function_Entry c_func, - bool whatever, - bool whatever2) - : Has_Block(pstate, 0), - name_(n), - parameters_(params), - environment_(0), - type_(FUNCTION), - native_function_(0), - c_function_(c_func), - cookie_(sass_function_get_cookie(c_func)), - is_overload_stub_(false), + : Has_Block(ptr), name_(ptr->name_), parameters_(ptr->parameters_), environment_(ptr->environment_), + type_(ptr->type_), native_function_(ptr->native_function_), c_function_(ptr->c_function_), + cookie_(ptr->cookie_), is_overload_stub_(ptr->is_overload_stub_), signature_(ptr->signature_) + { + } + + Definition(ParserState pstate, std::string n, Parameters_Obj params, Block_Obj b, Type t) + : Has_Block(pstate, b), name_(n), parameters_(params), environment_(0), type_(t), + native_function_(0), c_function_(0), cookie_(0), is_overload_stub_(false), signature_(0) + { + } + Definition(ParserState pstate, Signature sig, std::string n, Parameters_Obj params, Native_Function func_ptr, bool overload_stub = false) + : Has_Block(pstate, 0), name_(n), parameters_(params), environment_(0), type_(FUNCTION), + native_function_(func_ptr), c_function_(0), cookie_(0), is_overload_stub_(overload_stub), signature_(sig) - { } + { + } + Definition(ParserState pstate, Signature sig, std::string n, Parameters_Obj params, Sass_Function_Entry c_func, bool whatever, bool whatever2) + : Has_Block(pstate, 0), name_(n), parameters_(params), environment_(0), type_(FUNCTION), + native_function_(0), c_function_(c_func), cookie_(sass_function_get_cookie(c_func)), + is_overload_stub_(false), signature_(sig) + { + } ATTACH_AST_OPERATIONS(Definition) ATTACH_OPERATIONS() }; @@ -1018,18 +1247,19 @@ namespace Sass { ////////////////////////////////////// // Mixin calls (i.e., `@include ...`). ////////////////////////////////////// - class Mixin_Call : public Has_Block { + class Mixin_Call : public Has_Block + { ADD_CONSTREF(std::string, name) ADD_PROPERTY(Arguments_Obj, arguments) - public: + public: Mixin_Call(ParserState pstate, std::string n, Arguments_Obj args, Block_Obj b = 0) : Has_Block(pstate, b), name_(n), arguments_(args) - { } + { + } Mixin_Call(const Mixin_Call* ptr) - : Has_Block(ptr), - name_(ptr->name_), - arguments_(ptr->arguments_) - { } + : Has_Block(ptr), name_(ptr->name_), arguments_(ptr->arguments_) + { + } ATTACH_AST_OPERATIONS(Mixin_Call) ATTACH_OPERATIONS() }; @@ -1037,17 +1267,18 @@ namespace Sass { /////////////////////////////////////////////////// // The @content directive for mixin content blocks. /////////////////////////////////////////////////// - class Content : public Statement { + class Content : public Statement + { ADD_PROPERTY(Media_Block_Ptr, media_block) - public: - Content(ParserState pstate) - : Statement(pstate), - media_block_(NULL) - { statement_type(CONTENT); } - Content(const Content* ptr) - : Statement(ptr), - media_block_(ptr->media_block_) - { statement_type(CONTENT); } + public: + Content(ParserState pstate) : Statement(pstate), media_block_(NULL) + { + statement_type(CONTENT); + } + Content(const Content* ptr) : Statement(ptr), media_block_(ptr->media_block_) + { + statement_type(CONTENT); + } ATTACH_AST_OPERATIONS(Content) ATTACH_OPERATIONS() }; @@ -1056,45 +1287,55 @@ namespace Sass { // Lists of values, both comma- and space-separated (distinguished by a // type-tag.) Also used to represent variable-length argument lists. /////////////////////////////////////////////////////////////////////// - class List : public Value, public Vectorized { - void adjust_after_pushing(Expression_Obj e) { is_expanded(false); } - private: + class List : public Value, public Vectorized + { + void adjust_after_pushing(Expression_Obj e) + { + is_expanded(false); + } + + private: ADD_PROPERTY(enum Sass_Separator, separator) ADD_PROPERTY(bool, is_arglist) ADD_PROPERTY(bool, is_bracketed) ADD_PROPERTY(bool, from_selector) - public: - List(ParserState pstate, - size_t size = 0, enum Sass_Separator sep = SASS_SPACE, bool argl = false, bool bracket = false) - : Value(pstate), - Vectorized(size), - separator_(sep), - is_arglist_(argl), - is_bracketed_(bracket), - from_selector_(false) - { concrete_type(LIST); } + public: + List(ParserState pstate, size_t size = 0, enum Sass_Separator sep = SASS_SPACE, bool argl = false, bool bracket = false) + : Value(pstate), Vectorized(size), separator_(sep), is_arglist_(argl), + is_bracketed_(bracket), from_selector_(false) + { + concrete_type(LIST); + } List(const List* ptr) - : Value(ptr), - Vectorized(*ptr), - separator_(ptr->separator_), - is_arglist_(ptr->is_arglist_), - is_bracketed_(ptr->is_bracketed_), - from_selector_(ptr->from_selector_) - { concrete_type(LIST); } - std::string type() const { return is_arglist_ ? "arglist" : "list"; } - static std::string type_name() { return "list"; } - const char* sep_string(bool compressed = false) const { - return separator() == SASS_SPACE ? - " " : (compressed ? "," : ", "); - } - bool is_invisible() const { return empty() && !is_bracketed(); } + : Value(ptr), Vectorized(*ptr), separator_(ptr->separator_), + is_arglist_(ptr->is_arglist_), is_bracketed_(ptr->is_bracketed_), from_selector_(ptr->from_selector_) + { + concrete_type(LIST); + } + std::string type() const + { + return is_arglist_ ? "arglist" : "list"; + } + static std::string type_name() + { + return "list"; + } + const char* sep_string(bool compressed = false) const + { + return separator() == SASS_SPACE ? " " : (compressed ? "," : ", "); + } + bool is_invisible() const + { + return empty() && !is_bracketed(); + } Expression_Obj value_at_index(size_t i); virtual size_t size() const; virtual size_t hash() { - if (hash_ == 0) { + if (hash_ == 0) + { hash_ = std::hash()(sep_string()); hash_combine(hash_, std::hash()(is_bracketed())); for (size_t i = 0, L = length(); i < L; ++i) @@ -1109,7 +1350,7 @@ namespace Sass { // don't set children } - virtual bool operator== (const Expression& rhs) const; + virtual bool operator==(const Expression& rhs) const; ATTACH_AST_OPERATIONS(List) ATTACH_OPERATIONS() @@ -1118,27 +1359,42 @@ namespace Sass { /////////////////////////////////////////////////////////////////////// // Key value paris. /////////////////////////////////////////////////////////////////////// - class Map : public Value, public Hashed { - void adjust_after_pushing(std::pair p) { is_expanded(false); } - public: - Map(ParserState pstate, - size_t size = 0) - : Value(pstate), - Hashed(size) - { concrete_type(MAP); } - Map(const Map* ptr) - : Value(ptr), - Hashed(*ptr) - { concrete_type(MAP); } - std::string type() const { return "map"; } - static std::string type_name() { return "map"; } - bool is_invisible() const { return empty(); } + class Map : public Value, public Hashed + { + void adjust_after_pushing(std::pair p) + { + is_expanded(false); + } + + public: + Map(ParserState pstate, size_t size = 0) : Value(pstate), Hashed(size) + { + concrete_type(MAP); + } + Map(const Map* ptr) : Value(ptr), Hashed(*ptr) + { + concrete_type(MAP); + } + std::string type() const + { + return "map"; + } + static std::string type_name() + { + return "map"; + } + bool is_invisible() const + { + return empty(); + } List_Obj to_list(ParserState& pstate); virtual size_t hash() { - if (hash_ == 0) { - for (auto key : keys()) { + if (hash_ == 0) + { + for (auto key : keys()) + { hash_combine(hash_, key->hash()); hash_combine(hash_, at(key)->hash()); } @@ -1147,30 +1403,47 @@ namespace Sass { return hash_; } - virtual bool operator== (const Expression& rhs) const; + virtual bool operator==(const Expression& rhs) const; ATTACH_AST_OPERATIONS(Map) ATTACH_OPERATIONS() }; - inline static const std::string sass_op_to_name(enum Sass_OP op) { - switch (op) { - case AND: return "and"; - case OR: return "or"; - case EQ: return "eq"; - case NEQ: return "neq"; - case GT: return "gt"; - case GTE: return "gte"; - case LT: return "lt"; - case LTE: return "lte"; - case ADD: return "plus"; - case SUB: return "sub"; - case MUL: return "times"; - case DIV: return "div"; - case MOD: return "mod"; - // this is only used internally! - case NUM_OPS: return "[OPS]"; - default: return "invalid"; + inline static const std::string sass_op_to_name(enum Sass_OP op) + { + switch (op) + { + case AND: + return "and"; + case OR: + return "or"; + case EQ: + return "eq"; + case NEQ: + return "neq"; + case GT: + return "gt"; + case GTE: + return "gte"; + case LT: + return "lt"; + case LTE: + return "lte"; + case ADD: + return "plus"; + case SUB: + return "sub"; + case MUL: + return "times"; + case DIV: + return "div"; + case MOD: + return "mod"; + // this is only used internally! + case NUM_OPS: + return "[OPS]"; + default: + return "invalid"; } } @@ -1179,70 +1452,102 @@ namespace Sass { // operations. Templatized to avoid large switch statements and repetitive // subclassing. ////////////////////////////////////////////////////////////////////////// - class Binary_Expression : public PreValue { - private: + class Binary_Expression : public PreValue + { + private: HASH_PROPERTY(Operand, op) HASH_PROPERTY(Expression_Obj, left) HASH_PROPERTY(Expression_Obj, right) size_t hash_; - public: - Binary_Expression(ParserState pstate, - Operand op, Expression_Obj lhs, Expression_Obj rhs) + + public: + Binary_Expression(ParserState pstate, Operand op, Expression_Obj lhs, Expression_Obj rhs) : PreValue(pstate), op_(op), left_(lhs), right_(rhs), hash_(0) - { } + { + } Binary_Expression(const Binary_Expression* ptr) - : PreValue(ptr), - op_(ptr->op_), - left_(ptr->left_), - right_(ptr->right_), - hash_(ptr->hash_) - { } - const std::string type_name() { - switch (optype()) { - case AND: return "and"; - case OR: return "or"; - case EQ: return "eq"; - case NEQ: return "neq"; - case GT: return "gt"; - case GTE: return "gte"; - case LT: return "lt"; - case LTE: return "lte"; - case ADD: return "add"; - case SUB: return "sub"; - case MUL: return "mul"; - case DIV: return "div"; - case MOD: return "mod"; - // this is only used internally! - case NUM_OPS: return "[OPS]"; - default: return "invalid"; - } - } - const std::string separator() { - switch (optype()) { - case AND: return "&&"; - case OR: return "||"; - case EQ: return "=="; - case NEQ: return "!="; - case GT: return ">"; - case GTE: return ">="; - case LT: return "<"; - case LTE: return "<="; - case ADD: return "+"; - case SUB: return "-"; - case MUL: return "*"; - case DIV: return "/"; - case MOD: return "%"; - // this is only used internally! - case NUM_OPS: return "[OPS]"; - default: return "invalid"; + : PreValue(ptr), op_(ptr->op_), left_(ptr->left_), right_(ptr->right_), hash_(ptr->hash_) + { + } + const std::string type_name() + { + switch (optype()) + { + case AND: + return "and"; + case OR: + return "or"; + case EQ: + return "eq"; + case NEQ: + return "neq"; + case GT: + return "gt"; + case GTE: + return "gte"; + case LT: + return "lt"; + case LTE: + return "lte"; + case ADD: + return "add"; + case SUB: + return "sub"; + case MUL: + return "mul"; + case DIV: + return "div"; + case MOD: + return "mod"; + // this is only used internally! + case NUM_OPS: + return "[OPS]"; + default: + return "invalid"; + } + } + const std::string separator() + { + switch (optype()) + { + case AND: + return "&&"; + case OR: + return "||"; + case EQ: + return "=="; + case NEQ: + return "!="; + case GT: + return ">"; + case GTE: + return ">="; + case LT: + return "<"; + case LTE: + return "<="; + case ADD: + return "+"; + case SUB: + return "-"; + case MUL: + return "*"; + case DIV: + return "/"; + case MOD: + return "%"; + // this is only used internally! + case NUM_OPS: + return "[OPS]"; + default: + return "invalid"; } } bool is_left_interpolant(void) const; bool is_right_interpolant(void) const; bool has_interpolant() const { - return is_left_interpolant() || - is_right_interpolant(); + return is_left_interpolant() || is_right_interpolant(); } virtual void set_delayed(bool delayed) { @@ -1256,26 +1561,31 @@ namespace Sass { { Binary_Expression_Ptr_Const m = Cast(&rhs); if (m == 0) return false; - return type() == m->type() && - *left() == *m->left() && - *right() == *m->right(); + return type() == m->type() && *left() == *m->left() && *right() == *m->right(); } catch (std::bad_cast&) { return false; } - catch (...) { throw; } + catch (...) + { + throw; + } } virtual size_t hash() { - if (hash_ == 0) { + if (hash_ == 0) + { hash_ = std::hash()(optype()); hash_combine(hash_, left()->hash()); hash_combine(hash_, right()->hash()); } return hash_; } - enum Sass_OP optype() const { return op_.operand; } + enum Sass_OP optype() const + { + return op_.operand; + } ATTACH_AST_OPERATIONS(Binary_Expression) ATTACH_OPERATIONS() }; @@ -1283,29 +1593,42 @@ namespace Sass { //////////////////////////////////////////////////////////////////////////// // Arithmetic negation (logical negation is just an ordinary function call). //////////////////////////////////////////////////////////////////////////// - class Unary_Expression : public Expression { - public: - enum Type { PLUS, MINUS, NOT }; - private: + class Unary_Expression : public Expression + { + public: + enum Type + { + PLUS, + MINUS, + NOT + }; + + private: HASH_PROPERTY(Type, optype) HASH_PROPERTY(Expression_Obj, operand) size_t hash_; - public: + + public: Unary_Expression(ParserState pstate, Type t, Expression_Obj o) : Expression(pstate), optype_(t), operand_(o), hash_(0) - { } + { + } Unary_Expression(const Unary_Expression* ptr) - : Expression(ptr), - optype_(ptr->optype_), - operand_(ptr->operand_), - hash_(ptr->hash_) - { } - const std::string type_name() { - switch (optype_) { - case PLUS: return "plus"; - case MINUS: return "minus"; - case NOT: return "not"; - default: return "invalid"; + : Expression(ptr), optype_(ptr->optype_), operand_(ptr->operand_), hash_(ptr->hash_) + { + } + const std::string type_name() + { + switch (optype_) + { + case PLUS: + return "plus"; + case MINUS: + return "minus"; + case NOT: + return "not"; + default: + return "invalid"; } } virtual bool operator==(const Expression& rhs) const @@ -1314,18 +1637,21 @@ namespace Sass { { Unary_Expression_Ptr_Const m = Cast(&rhs); if (m == 0) return false; - return type() == m->type() && - *operand() == *m->operand(); + return type() == m->type() && *operand() == *m->operand(); } catch (std::bad_cast&) { return false; } - catch (...) { throw; } + catch (...) + { + throw; + } } virtual size_t hash() { - if (hash_ == 0) { + if (hash_ == 0) + { hash_ = std::hash()(optype_); hash_combine(hash_, operand()->hash()); }; @@ -1338,29 +1664,30 @@ namespace Sass { //////////////////////////////////////////////////////////// // Individual argument objects for mixin and function calls. //////////////////////////////////////////////////////////// - class Argument : public Expression { + class Argument : public Expression + { HASH_PROPERTY(Expression_Obj, value) HASH_CONSTREF(std::string, name) ADD_PROPERTY(bool, is_rest_argument) ADD_PROPERTY(bool, is_keyword_argument) size_t hash_; - public: + + public: Argument(ParserState pstate, Expression_Obj val, std::string n = "", bool rest = false, bool keyword = false) - : Expression(pstate), value_(val), name_(n), is_rest_argument_(rest), is_keyword_argument_(keyword), hash_(0) + : Expression(pstate), value_(val), name_(n), is_rest_argument_(rest), + is_keyword_argument_(keyword), hash_(0) { - if (!name_.empty() && is_rest_argument_) { + if (!name_.empty() && is_rest_argument_) + { error("variable-length argument may not be passed by name", pstate_); } } Argument(const Argument* ptr) - : Expression(ptr), - value_(ptr->value_), - name_(ptr->name_), - is_rest_argument_(ptr->is_rest_argument_), - is_keyword_argument_(ptr->is_keyword_argument_), - hash_(ptr->hash_) + : Expression(ptr), value_(ptr->value_), name_(ptr->name_), is_rest_argument_(ptr->is_rest_argument_), + is_keyword_argument_(ptr->is_keyword_argument_), hash_(ptr->hash_) { - if (!name_.empty() && is_rest_argument_) { + if (!name_.empty() && is_rest_argument_) + { error("variable-length argument may not be passed by name", pstate_); } } @@ -1378,12 +1705,16 @@ namespace Sass { { return false; } - catch (...) { throw; } + catch (...) + { + throw; + } } virtual size_t hash() { - if (hash_ == 0) { + if (hash_ == 0) + { hash_ = std::hash()(name()); hash_combine(hash_, value()->hash()); } @@ -1399,27 +1730,25 @@ namespace Sass { // error checking (e.g., ensuring that all ordinal arguments precede all // named arguments). //////////////////////////////////////////////////////////////////////// - class Arguments : public Expression, public Vectorized { + class Arguments : public Expression, public Vectorized + { ADD_PROPERTY(bool, has_named_arguments) ADD_PROPERTY(bool, has_rest_argument) ADD_PROPERTY(bool, has_keyword_argument) - protected: + protected: void adjust_after_pushing(Argument_Obj a); - public: + + public: Arguments(ParserState pstate) - : Expression(pstate), - Vectorized(), - has_named_arguments_(false), - has_rest_argument_(false), - has_keyword_argument_(false) - { } + : Expression(pstate), Vectorized(), has_named_arguments_(false), + has_rest_argument_(false), has_keyword_argument_(false) + { + } Arguments(const Arguments* ptr) - : Expression(ptr), - Vectorized(*ptr), - has_named_arguments_(ptr->has_named_arguments_), - has_rest_argument_(ptr->has_rest_argument_), - has_keyword_argument_(ptr->has_keyword_argument_) - { } + : Expression(ptr), Vectorized(*ptr), has_named_arguments_(ptr->has_named_arguments_), + has_rest_argument_(ptr->has_rest_argument_), has_keyword_argument_(ptr->has_keyword_argument_) + { + } virtual void set_delayed(bool delayed); @@ -1433,27 +1762,31 @@ namespace Sass { ////////////////// // Function calls. ////////////////// - class Function_Call : public PreValue { + class Function_Call : public PreValue + { HASH_CONSTREF(std::string, name) HASH_PROPERTY(Arguments_Obj, arguments) ADD_PROPERTY(bool, via_call) ADD_PROPERTY(void*, cookie) size_t hash_; - public: + + public: Function_Call(ParserState pstate, std::string n, Arguments_Obj args, void* cookie) : PreValue(pstate), name_(n), arguments_(args), via_call_(false), cookie_(cookie), hash_(0) - { concrete_type(FUNCTION); } + { + concrete_type(FUNCTION); + } Function_Call(ParserState pstate, std::string n, Arguments_Obj args) : PreValue(pstate), name_(n), arguments_(args), via_call_(false), cookie_(0), hash_(0) - { concrete_type(FUNCTION); } + { + concrete_type(FUNCTION); + } Function_Call(const Function_Call* ptr) - : PreValue(ptr), - name_(ptr->name_), - arguments_(ptr->arguments_), - via_call_(ptr->via_call_), - cookie_(ptr->cookie_), - hash_(ptr->hash_) - { concrete_type(FUNCTION); } + : PreValue(ptr), name_(ptr->name_), arguments_(ptr->arguments_), via_call_(ptr->via_call_), + cookie_(ptr->cookie_), hash_(ptr->hash_) + { + concrete_type(FUNCTION); + } virtual bool operator==(const Expression& rhs) const { @@ -1462,7 +1795,7 @@ namespace Sass { Function_Call_Ptr_Const m = Cast(&rhs); if (!(m && name() == m->name())) return false; if (!(m && arguments()->length() == m->arguments()->length())) return false; - for (size_t i =0, L = arguments()->length(); i < L; ++i) + for (size_t i = 0, L = arguments()->length(); i < L; ++i) if (!(*(*arguments())[i] == *(*m->arguments())[i])) return false; return true; } @@ -1470,12 +1803,16 @@ namespace Sass { { return false; } - catch (...) { throw; } + catch (...) + { + throw; + } } virtual size_t hash() { - if (hash_ == 0) { + if (hash_ == 0) + { hash_ = std::hash()(name()); for (auto argument : arguments()->elements()) hash_combine(hash_, argument->hash()); @@ -1489,18 +1826,21 @@ namespace Sass { ///////////////////////// // Function call schemas. ///////////////////////// - class Function_Call_Schema : public Expression { + class Function_Call_Schema : public Expression + { ADD_PROPERTY(String_Obj, name) ADD_PROPERTY(Arguments_Obj, arguments) - public: + public: Function_Call_Schema(ParserState pstate, String_Obj n, Arguments_Obj args) : Expression(pstate), name_(n), arguments_(args) - { concrete_type(STRING); } + { + concrete_type(STRING); + } Function_Call_Schema(const Function_Call_Schema* ptr) - : Expression(ptr), - name_(ptr->name_), - arguments_(ptr->arguments_) - { concrete_type(STRING); } + : Expression(ptr), name_(ptr->name_), arguments_(ptr->arguments_) + { + concrete_type(STRING); + } ATTACH_AST_OPERATIONS(Function_Call_Schema) ATTACH_OPERATIONS() }; @@ -1508,15 +1848,18 @@ namespace Sass { /////////////////////// // Variable references. /////////////////////// - class Variable : public PreValue { + class Variable : public PreValue + { ADD_CONSTREF(std::string, name) - public: - Variable(ParserState pstate, std::string n) - : PreValue(pstate), name_(n) - { concrete_type(VARIABLE); } - Variable(const Variable* ptr) - : PreValue(ptr), name_(ptr->name_) - { concrete_type(VARIABLE); } + public: + Variable(ParserState pstate, std::string n) : PreValue(pstate), name_(n) + { + concrete_type(VARIABLE); + } + Variable(const Variable* ptr) : PreValue(ptr), name_(ptr->name_) + { + concrete_type(VARIABLE); + } virtual bool operator==(const Expression& rhs) const { @@ -1529,7 +1872,10 @@ namespace Sass { { return false; } - catch (...) { throw; } + catch (...) + { + throw; + } } virtual size_t hash() @@ -1544,31 +1890,53 @@ namespace Sass { //////////////////////////////////////////////// // Numbers, percentages, dimensions, and colors. //////////////////////////////////////////////// - class Number : public Value { + class Number : public Value + { HASH_PROPERTY(double, value) ADD_PROPERTY(bool, zero) std::vector numerator_units_; std::vector denominator_units_; size_t hash_; - public: + + public: Number(ParserState pstate, double val, std::string u = "", bool zero = true); Number(const Number* ptr) - : Value(ptr), - value_(ptr->value_), zero_(ptr->zero_), - numerator_units_(ptr->numerator_units_), - denominator_units_(ptr->denominator_units_), - hash_(ptr->hash_) - { concrete_type(NUMBER); } - - bool zero() { return zero_; } + : Value(ptr), value_(ptr->value_), zero_(ptr->zero_), numerator_units_(ptr->numerator_units_), + denominator_units_(ptr->denominator_units_), hash_(ptr->hash_) + { + concrete_type(NUMBER); + } + + bool zero() + { + return zero_; + } bool is_valid_css_unit() const; - std::vector& numerator_units() { return numerator_units_; } - std::vector& denominator_units() { return denominator_units_; } - const std::vector& numerator_units() const { return numerator_units_; } - const std::vector& denominator_units() const { return denominator_units_; } - std::string type() const { return "number"; } - static std::string type_name() { return "number"; } + std::vector& numerator_units() + { + return numerator_units_; + } + std::vector& denominator_units() + { + return denominator_units_; + } + const std::vector& numerator_units() const + { + return numerator_units_; + } + const std::vector& denominator_units() const + { + return denominator_units_; + } + std::string type() const + { + return "number"; + } + static std::string type_name() + { + return "number"; + } std::string unit() const; bool is_unitless() const; @@ -1580,7 +1948,8 @@ namespace Sass { virtual size_t hash() { - if (hash_ == 0) { + if (hash_ == 0) + { hash_ = std::hash()(value_); for (const auto numerator : numerator_units()) hash_combine(hash_, std::hash()(numerator)); @@ -1590,8 +1959,8 @@ namespace Sass { return hash_; } - virtual bool operator< (const Number& rhs) const; - virtual bool operator== (const Expression& rhs) const; + virtual bool operator<(const Number& rhs) const; + virtual bool operator==(const Expression& rhs) const; ATTACH_AST_OPERATIONS(Number) ATTACH_OPERATIONS() }; @@ -1599,33 +1968,39 @@ namespace Sass { ////////// // Colors. ////////// - class Color : public Value { + class Color : public Value + { HASH_PROPERTY(double, r) HASH_PROPERTY(double, g) HASH_PROPERTY(double, b) HASH_PROPERTY(double, a) ADD_CONSTREF(std::string, disp) size_t hash_; - public: + + public: Color(ParserState pstate, double r, double g, double b, double a = 1, const std::string disp = "") - : Value(pstate), r_(r), g_(g), b_(b), a_(a), disp_(disp), - hash_(0) - { concrete_type(COLOR); } + : Value(pstate), r_(r), g_(g), b_(b), a_(a), disp_(disp), hash_(0) + { + concrete_type(COLOR); + } Color(const Color* ptr) - : Value(ptr), - r_(ptr->r_), - g_(ptr->g_), - b_(ptr->b_), - a_(ptr->a_), - disp_(ptr->disp_), - hash_(ptr->hash_) - { concrete_type(COLOR); } - std::string type() const { return "color"; } - static std::string type_name() { return "color"; } + : Value(ptr), r_(ptr->r_), g_(ptr->g_), b_(ptr->b_), a_(ptr->a_), disp_(ptr->disp_), hash_(ptr->hash_) + { + concrete_type(COLOR); + } + std::string type() const + { + return "color"; + } + static std::string type_name() + { + return "color"; + } virtual size_t hash() { - if (hash_ == 0) { + if (hash_ == 0) + { hash_ = std::hash()(a_); hash_combine(hash_, std::hash()(r_)); hash_combine(hash_, std::hash()(g_)); @@ -1634,7 +2009,7 @@ namespace Sass { return hash_; } - virtual bool operator== (const Expression& rhs) const; + virtual bool operator==(const Expression& rhs) const; ATTACH_AST_OPERATIONS(Color) ATTACH_OPERATIONS() @@ -1643,16 +2018,19 @@ namespace Sass { ////////////////////////////// // Errors from Sass_Values. ////////////////////////////// - class Custom_Error : public Value { + class Custom_Error : public Value + { ADD_CONSTREF(std::string, message) - public: - Custom_Error(ParserState pstate, std::string msg) - : Value(pstate), message_(msg) - { concrete_type(C_ERROR); } - Custom_Error(const Custom_Error* ptr) - : Value(ptr), message_(ptr->message_) - { concrete_type(C_ERROR); } - virtual bool operator== (const Expression& rhs) const; + public: + Custom_Error(ParserState pstate, std::string msg) : Value(pstate), message_(msg) + { + concrete_type(C_ERROR); + } + Custom_Error(const Custom_Error* ptr) : Value(ptr), message_(ptr->message_) + { + concrete_type(C_ERROR); + } + virtual bool operator==(const Expression& rhs) const; ATTACH_AST_OPERATIONS(Custom_Error) ATTACH_OPERATIONS() }; @@ -1660,16 +2038,19 @@ namespace Sass { ////////////////////////////// // Warnings from Sass_Values. ////////////////////////////// - class Custom_Warning : public Value { + class Custom_Warning : public Value + { ADD_CONSTREF(std::string, message) - public: - Custom_Warning(ParserState pstate, std::string msg) - : Value(pstate), message_(msg) - { concrete_type(C_WARNING); } - Custom_Warning(const Custom_Warning* ptr) - : Value(ptr), message_(ptr->message_) - { concrete_type(C_WARNING); } - virtual bool operator== (const Expression& rhs) const; + public: + Custom_Warning(ParserState pstate, std::string msg) : Value(pstate), message_(msg) + { + concrete_type(C_WARNING); + } + Custom_Warning(const Custom_Warning* ptr) : Value(ptr), message_(ptr->message_) + { + concrete_type(C_WARNING); + } + virtual bool operator==(const Expression& rhs) const; ATTACH_AST_OPERATIONS(Custom_Warning) ATTACH_OPERATIONS() }; @@ -1677,33 +2058,47 @@ namespace Sass { //////////// // Booleans. //////////// - class Boolean : public Value { + class Boolean : public Value + { HASH_PROPERTY(bool, value) size_t hash_; - public: - Boolean(ParserState pstate, bool val) - : Value(pstate), value_(val), - hash_(0) - { concrete_type(BOOLEAN); } - Boolean(const Boolean* ptr) - : Value(ptr), - value_(ptr->value_), - hash_(ptr->hash_) - { concrete_type(BOOLEAN); } - virtual operator bool() { return value_; } - std::string type() const { return "bool"; } - static std::string type_name() { return "bool"; } - virtual bool is_false() { return !value_; } + + public: + Boolean(ParserState pstate, bool val) : Value(pstate), value_(val), hash_(0) + { + concrete_type(BOOLEAN); + } + Boolean(const Boolean* ptr) : Value(ptr), value_(ptr->value_), hash_(ptr->hash_) + { + concrete_type(BOOLEAN); + } + virtual operator bool() + { + return value_; + } + std::string type() const + { + return "bool"; + } + static std::string type_name() + { + return "bool"; + } + virtual bool is_false() + { + return !value_; + } virtual size_t hash() { - if (hash_ == 0) { + if (hash_ == 0) + { hash_ = std::hash()(value_); } return hash_; } - virtual bool operator== (const Expression& rhs) const; + virtual bool operator==(const Expression& rhs) const; ATTACH_AST_OPERATIONS(Boolean) ATTACH_OPERATIONS() @@ -1713,51 +2108,70 @@ namespace Sass { // Abstract base class for Sass string values. Includes interpolated and // "flat" strings. //////////////////////////////////////////////////////////////////////// - class String : public Value { - public: - String(ParserState pstate, bool delayed = false) - : Value(pstate, delayed) - { concrete_type(STRING); } - String(const String* ptr) - : Value(ptr) - { concrete_type(STRING); } - static std::string type_name() { return "string"; } + class String : public Value + { + public: + String(ParserState pstate, bool delayed = false) : Value(pstate, delayed) + { + concrete_type(STRING); + } + String(const String* ptr) : Value(ptr) + { + concrete_type(STRING); + } + static std::string type_name() + { + return "string"; + } virtual ~String() = 0; virtual void rtrim() = 0; virtual bool operator==(const Expression& rhs) const = 0; - virtual bool operator<(const Expression& rhs) const { + virtual bool operator<(const Expression& rhs) const + { return this->to_string() < rhs.to_string(); }; ATTACH_VIRTUAL_AST_OPERATIONS(String); ATTACH_OPERATIONS() }; - inline String::~String() { }; + inline String::~String(){}; /////////////////////////////////////////////////////////////////////// // Interpolated strings. Meant to be reduced to flat strings during the // evaluation phase. /////////////////////////////////////////////////////////////////////// - class String_Schema : public String, public Vectorized { + class String_Schema : public String, public Vectorized + { // ADD_PROPERTY(bool, has_interpolants) size_t hash_; - public: + + public: String_Schema(ParserState pstate, size_t size = 0, bool has_interpolants = false) : String(pstate), Vectorized(size), hash_(0) - { concrete_type(STRING); } + { + concrete_type(STRING); + } String_Schema(const String_Schema* ptr) - : String(ptr), - Vectorized(*ptr), - hash_(ptr->hash_) - { concrete_type(STRING); } + : String(ptr), Vectorized(*ptr), hash_(ptr->hash_) + { + concrete_type(STRING); + } - std::string type() const { return "string"; } - static std::string type_name() { return "string"; } + std::string type() const + { + return "string"; + } + static std::string type_name() + { + return "string"; + } bool is_left_interpolant(void) const; bool is_right_interpolant(void) const; // void has_interpolants(bool tc) { } - bool has_interpolants() { - for (auto el : elements()) { + bool has_interpolants() + { + for (auto el : elements()) + { if (el->is_interpolant()) return true; } return false; @@ -1766,14 +2180,16 @@ namespace Sass { virtual size_t hash() { - if (hash_ == 0) { + if (hash_ == 0) + { for (auto string : elements()) hash_combine(hash_, string->hash()); } return hash_; } - virtual void set_delayed(bool delayed) { + virtual void set_delayed(bool delayed) + { is_delayed(delayed); } @@ -1785,40 +2201,55 @@ namespace Sass { //////////////////////////////////////////////////////// // Flat strings -- the lowest level of raw textual data. //////////////////////////////////////////////////////// - class String_Constant : public String { + class String_Constant : public String + { ADD_PROPERTY(char, quote_mark) ADD_PROPERTY(bool, can_compress_whitespace) HASH_CONSTREF(std::string, value) - protected: + protected: size_t hash_; - public: + + public: String_Constant(const String_Constant* ptr) - : String(ptr), - quote_mark_(ptr->quote_mark_), - can_compress_whitespace_(ptr->can_compress_whitespace_), - value_(ptr->value_), - hash_(ptr->hash_) - { } + : String(ptr), quote_mark_(ptr->quote_mark_), + can_compress_whitespace_(ptr->can_compress_whitespace_), value_(ptr->value_), hash_(ptr->hash_) + { + } String_Constant(ParserState pstate, std::string val) - : String(pstate), quote_mark_(0), can_compress_whitespace_(false), value_(read_css_string(val)), hash_(0) - { } + : String(pstate), quote_mark_(0), can_compress_whitespace_(false), value_(read_css_string(val)), + hash_(0) + { + } String_Constant(ParserState pstate, const char* beg) - : String(pstate), quote_mark_(0), can_compress_whitespace_(false), value_(read_css_string(std::string(beg))), hash_(0) - { } + : String(pstate), quote_mark_(0), can_compress_whitespace_(false), + value_(read_css_string(std::string(beg))), hash_(0) + { + } String_Constant(ParserState pstate, const char* beg, const char* end) - : String(pstate), quote_mark_(0), can_compress_whitespace_(false), value_(read_css_string(std::string(beg, end-beg))), hash_(0) - { } + : String(pstate), quote_mark_(0), can_compress_whitespace_(false), + value_(read_css_string(std::string(beg, end - beg))), hash_(0) + { + } String_Constant(ParserState pstate, const Token& tok) - : String(pstate), quote_mark_(0), can_compress_whitespace_(false), value_(read_css_string(std::string(tok.begin, tok.end))), hash_(0) - { } - std::string type() const { return "string"; } - static std::string type_name() { return "string"; } + : String(pstate), quote_mark_(0), can_compress_whitespace_(false), + value_(read_css_string(std::string(tok.begin, tok.end))), hash_(0) + { + } + std::string type() const + { + return "string"; + } + static std::string type_name() + { + return "string"; + } virtual bool is_invisible() const; virtual void rtrim(); virtual size_t hash() { - if (hash_ == 0) { + if (hash_ == 0) + { hash_ = std::hash()(value_); } return hash_; @@ -1828,8 +2259,14 @@ namespace Sass { virtual std::string inspect() const; // quotes are forced on inspection // static char auto_quote() { return '*'; } - static char double_quote() { return '"'; } - static char single_quote() { return '\''; } + static char double_quote() + { + return '"'; + } + static char single_quote() + { + return '\''; + } ATTACH_AST_OPERATIONS(String_Constant) ATTACH_OPERATIONS() @@ -1838,21 +2275,26 @@ namespace Sass { //////////////////////////////////////////////////////// // Possibly quoted string (unquote on instantiation) //////////////////////////////////////////////////////// - class String_Quoted : public String_Constant { - public: - String_Quoted(ParserState pstate, std::string val, char q = 0, - bool keep_utf8_escapes = false, bool skip_unquoting = false, - bool strict_unquoting = true) + class String_Quoted : public String_Constant + { + public: + String_Quoted(ParserState pstate, + std::string val, + char q = 0, + bool keep_utf8_escapes = false, + bool skip_unquoting = false, + bool strict_unquoting = true) : String_Constant(pstate, val) { - if (skip_unquoting == false) { + if (skip_unquoting == false) + { value_ = unquote(value_, "e_mark_, keep_utf8_escapes, strict_unquoting); } if (q && quote_mark_) quote_mark_ = q; } - String_Quoted(const String_Quoted* ptr) - : String_Constant(ptr) - { } + String_Quoted(const String_Quoted* ptr) : String_Constant(ptr) + { + } virtual bool operator==(const Expression& rhs) const; virtual std::string inspect() const; // quotes are forced on inspection ATTACH_AST_OPERATIONS(String_Quoted) @@ -1862,24 +2304,22 @@ namespace Sass { ///////////////// // Media queries. ///////////////// - class Media_Query : public Expression, - public Vectorized { + class Media_Query : public Expression, public Vectorized + { ADD_PROPERTY(String_Obj, media_type) ADD_PROPERTY(bool, is_negated) ADD_PROPERTY(bool, is_restricted) - public: - Media_Query(ParserState pstate, - String_Obj t = 0, size_t s = 0, bool n = false, bool r = false) - : Expression(pstate), Vectorized(s), - media_type_(t), is_negated_(n), is_restricted_(r) - { } + public: + Media_Query(ParserState pstate, String_Obj t = 0, size_t s = 0, bool n = false, bool r = false) + : Expression(pstate), Vectorized(s), media_type_(t), is_negated_(n), + is_restricted_(r) + { + } Media_Query(const Media_Query* ptr) - : Expression(ptr), - Vectorized(*ptr), - media_type_(ptr->media_type_), - is_negated_(ptr->is_negated_), - is_restricted_(ptr->is_restricted_) - { } + : Expression(ptr), Vectorized(*ptr), media_type_(ptr->media_type_), + is_negated_(ptr->is_negated_), is_restricted_(ptr->is_restricted_) + { + } ATTACH_AST_OPERATIONS(Media_Query) ATTACH_OPERATIONS() }; @@ -1887,21 +2327,20 @@ namespace Sass { //////////////////////////////////////////////////// // Media expressions (for use inside media queries). //////////////////////////////////////////////////// - class Media_Query_Expression : public Expression { + class Media_Query_Expression : public Expression + { ADD_PROPERTY(Expression_Obj, feature) ADD_PROPERTY(Expression_Obj, value) ADD_PROPERTY(bool, is_interpolated) - public: - Media_Query_Expression(ParserState pstate, - Expression_Obj f, Expression_Obj v, bool i = false) + public: + Media_Query_Expression(ParserState pstate, Expression_Obj f, Expression_Obj v, bool i = false) : Expression(pstate), feature_(f), value_(v), is_interpolated_(i) - { } + { + } Media_Query_Expression(const Media_Query_Expression* ptr) - : Expression(ptr), - feature_(ptr->feature_), - value_(ptr->value_), - is_interpolated_(ptr->is_interpolated_) - { } + : Expression(ptr), feature_(ptr->feature_), value_(ptr->value_), is_interpolated_(ptr->is_interpolated_) + { + } ATTACH_AST_OPERATIONS(Media_Query_Expression) ATTACH_OPERATIONS() }; @@ -1909,16 +2348,23 @@ namespace Sass { //////////////////// // `@supports` rule. //////////////////// - class Supports_Block : public Has_Block { + class Supports_Block : public Has_Block + { ADD_PROPERTY(Supports_Condition_Obj, condition) - public: + public: Supports_Block(ParserState pstate, Supports_Condition_Obj condition, Block_Obj block = 0) : Has_Block(pstate, block), condition_(condition) - { statement_type(SUPPORTS); } - Supports_Block(const Supports_Block* ptr) - : Has_Block(ptr), condition_(ptr->condition_) - { statement_type(SUPPORTS); } - bool bubbles() { return true; } + { + statement_type(SUPPORTS); + } + Supports_Block(const Supports_Block* ptr) : Has_Block(ptr), condition_(ptr->condition_) + { + statement_type(SUPPORTS); + } + bool bubbles() + { + return true; + } ATTACH_AST_OPERATIONS(Supports_Block) ATTACH_OPERATIONS() }; @@ -1926,15 +2372,19 @@ namespace Sass { ////////////////////////////////////////////////////// // The abstract superclass of all Supports conditions. ////////////////////////////////////////////////////// - class Supports_Condition : public Expression { - public: - Supports_Condition(ParserState pstate) - : Expression(pstate) - { } - Supports_Condition(const Supports_Condition* ptr) - : Expression(ptr) - { } - virtual bool needs_parens(Supports_Condition_Obj cond) const { return false; } + class Supports_Condition : public Expression + { + public: + Supports_Condition(ParserState pstate) : Expression(pstate) + { + } + Supports_Condition(const Supports_Condition* ptr) : Expression(ptr) + { + } + virtual bool needs_parens(Supports_Condition_Obj cond) const + { + return false; + } ATTACH_AST_OPERATIONS(Supports_Condition) ATTACH_OPERATIONS() }; @@ -1942,23 +2392,29 @@ namespace Sass { //////////////////////////////////////////////////////////// // An operator condition (e.g. `CONDITION1 and CONDITION2`). //////////////////////////////////////////////////////////// - class Supports_Operator : public Supports_Condition { - public: - enum Operand { AND, OR }; - private: + class Supports_Operator : public Supports_Condition + { + public: + enum Operand + { + AND, + OR + }; + + private: ADD_PROPERTY(Supports_Condition_Obj, left); ADD_PROPERTY(Supports_Condition_Obj, right); ADD_PROPERTY(Operand, operand); - public: + + public: Supports_Operator(ParserState pstate, Supports_Condition_Obj l, Supports_Condition_Obj r, Operand o) : Supports_Condition(pstate), left_(l), right_(r), operand_(o) - { } + { + } Supports_Operator(const Supports_Operator* ptr) - : Supports_Condition(ptr), - left_(ptr->left_), - right_(ptr->right_), - operand_(ptr->operand_) - { } + : Supports_Condition(ptr), left_(ptr->left_), right_(ptr->right_), operand_(ptr->operand_) + { + } virtual bool needs_parens(Supports_Condition_Obj cond) const; ATTACH_AST_OPERATIONS(Supports_Operator) ATTACH_OPERATIONS() @@ -1967,16 +2423,20 @@ namespace Sass { ////////////////////////////////////////// // A negation condition (`not CONDITION`). ////////////////////////////////////////// - class Supports_Negation : public Supports_Condition { - private: + class Supports_Negation : public Supports_Condition + { + private: ADD_PROPERTY(Supports_Condition_Obj, condition); - public: + + public: Supports_Negation(ParserState pstate, Supports_Condition_Obj c) : Supports_Condition(pstate), condition_(c) - { } + { + } Supports_Negation(const Supports_Negation* ptr) : Supports_Condition(ptr), condition_(ptr->condition_) - { } + { + } virtual bool needs_parens(Supports_Condition_Obj cond) const; ATTACH_AST_OPERATIONS(Supports_Negation) ATTACH_OPERATIONS() @@ -1985,20 +2445,25 @@ namespace Sass { ///////////////////////////////////////////////////// // A declaration condition (e.g. `(feature: value)`). ///////////////////////////////////////////////////// - class Supports_Declaration : public Supports_Condition { - private: + class Supports_Declaration : public Supports_Condition + { + private: ADD_PROPERTY(Expression_Obj, feature); ADD_PROPERTY(Expression_Obj, value); - public: + + public: Supports_Declaration(ParserState pstate, Expression_Obj f, Expression_Obj v) : Supports_Condition(pstate), feature_(f), value_(v) - { } + { + } Supports_Declaration(const Supports_Declaration* ptr) - : Supports_Condition(ptr), - feature_(ptr->feature_), - value_(ptr->value_) - { } - virtual bool needs_parens(Supports_Condition_Obj cond) const { return false; } + : Supports_Condition(ptr), feature_(ptr->feature_), value_(ptr->value_) + { + } + virtual bool needs_parens(Supports_Condition_Obj cond) const + { + return false; + } ATTACH_AST_OPERATIONS(Supports_Declaration) ATTACH_OPERATIONS() }; @@ -2006,18 +2471,24 @@ namespace Sass { /////////////////////////////////////////////// // An interpolation condition (e.g. `#{$var}`). /////////////////////////////////////////////// - class Supports_Interpolation : public Supports_Condition { - private: + class Supports_Interpolation : public Supports_Condition + { + private: ADD_PROPERTY(Expression_Obj, value); - public: + + public: Supports_Interpolation(ParserState pstate, Expression_Obj v) : Supports_Condition(pstate), value_(v) - { } + { + } Supports_Interpolation(const Supports_Interpolation* ptr) - : Supports_Condition(ptr), - value_(ptr->value_) - { } - virtual bool needs_parens(Supports_Condition_Obj cond) const { return false; } + : Supports_Condition(ptr), value_(ptr->value_) + { + } + virtual bool needs_parens(Supports_Condition_Obj cond) const + { + return false; + } ATTACH_AST_OPERATIONS(Supports_Interpolation) ATTACH_OPERATIONS() }; @@ -2025,19 +2496,20 @@ namespace Sass { ///////////////////////////////////////////////// // At root expressions (for use inside @at-root). ///////////////////////////////////////////////// - class At_Root_Query : public Expression { - private: + class At_Root_Query : public Expression + { + private: ADD_PROPERTY(Expression_Obj, feature) ADD_PROPERTY(Expression_Obj, value) - public: + public: At_Root_Query(ParserState pstate, Expression_Obj f = 0, Expression_Obj v = 0, bool i = false) : Expression(pstate), feature_(f), value_(v) - { } + { + } At_Root_Query(const At_Root_Query* ptr) - : Expression(ptr), - feature_(ptr->feature_), - value_(ptr->value_) - { } + : Expression(ptr), feature_(ptr->feature_), value_(ptr->value_) + { + } bool exclude(std::string str); ATTACH_AST_OPERATIONS(At_Root_Query) ATTACH_OPERATIONS() @@ -2046,17 +2518,25 @@ namespace Sass { /////////// // At-root. /////////// - class At_Root_Block : public Has_Block { + class At_Root_Block : public Has_Block + { ADD_PROPERTY(At_Root_Query_Obj, expression) - public: + public: At_Root_Block(ParserState pstate, Block_Obj b = 0, At_Root_Query_Obj e = 0) : Has_Block(pstate, b), expression_(e) - { statement_type(ATROOT); } - At_Root_Block(const At_Root_Block* ptr) - : Has_Block(ptr), expression_(ptr->expression_) - { statement_type(ATROOT); } - bool bubbles() { return true; } - bool exclude_node(Statement_Obj s) { + { + statement_type(ATROOT); + } + At_Root_Block(const At_Root_Block* ptr) : Has_Block(ptr), expression_(ptr->expression_) + { + statement_type(ATROOT); + } + bool bubbles() + { + return true; + } + bool exclude_node(Statement_Obj s) + { if (expression() == 0) { return s->statement_type() == Statement::RULESET; @@ -2096,22 +2576,44 @@ namespace Sass { ////////////////// // The null value. ////////////////// - class Null : public Value { - public: - Null(ParserState pstate) : Value(pstate) { concrete_type(NULL_VAL); } - Null(const Null* ptr) : Value(ptr) { concrete_type(NULL_VAL); } - std::string type() const { return "null"; } - static std::string type_name() { return "null"; } - bool is_invisible() const { return true; } - operator bool() { return false; } - bool is_false() { return true; } + class Null : public Value + { + public: + Null(ParserState pstate) : Value(pstate) + { + concrete_type(NULL_VAL); + } + Null(const Null* ptr) : Value(ptr) + { + concrete_type(NULL_VAL); + } + std::string type() const + { + return "null"; + } + static std::string type_name() + { + return "null"; + } + bool is_invisible() const + { + return true; + } + operator bool() + { + return false; + } + bool is_false() + { + return true; + } virtual size_t hash() { return -1; } - virtual bool operator== (const Expression& rhs) const; + virtual bool operator==(const Expression& rhs) const; ATTACH_AST_OPERATIONS(Null) ATTACH_OPERATIONS() @@ -2120,25 +2622,27 @@ namespace Sass { ///////////////////////////////// // Thunks for delayed evaluation. ///////////////////////////////// - class Thunk : public Expression { + class Thunk : public Expression + { ADD_PROPERTY(Expression_Obj, expression) ADD_PROPERTY(Env*, environment) - public: + public: Thunk(ParserState pstate, Expression_Obj exp, Env* env = 0) : Expression(pstate), expression_(exp), environment_(env) - { } + { + } }; ///////////////////////////////////////////////////////// // Individual parameter objects for mixins and functions. ///////////////////////////////////////////////////////// - class Parameter : public AST_Node { + class Parameter : public AST_Node + { ADD_CONSTREF(std::string, name) ADD_PROPERTY(Expression_Obj, default_value) ADD_PROPERTY(bool, is_rest_parameter) - public: - Parameter(ParserState pstate, - std::string n, Expression_Obj def = 0, bool rest = false) + public: + Parameter(ParserState pstate, std::string n, Expression_Obj def = 0, bool rest = false) : AST_Node(pstate), name_(n), default_value_(def), is_rest_parameter_(rest) { // tried to come up with a spec test for this, but it does no longer @@ -2148,9 +2652,7 @@ namespace Sass { // } } Parameter(const Parameter* ptr) - : AST_Node(ptr), - name_(ptr->name_), - default_value_(ptr->default_value_), + : AST_Node(ptr), name_(ptr->name_), default_value_(ptr->default_value_), is_rest_parameter_(ptr->is_rest_parameter_) { // tried to come up with a spec test for this, but it does no longer @@ -2168,46 +2670,53 @@ namespace Sass { // error checking (e.g., ensuring that all optional parameters follow all // required parameters). ///////////////////////////////////////////////////////////////////////// - class Parameters : public AST_Node, public Vectorized { + class Parameters : public AST_Node, public Vectorized + { ADD_PROPERTY(bool, has_optional_parameters) ADD_PROPERTY(bool, has_rest_parameter) - protected: + protected: void adjust_after_pushing(Parameter_Obj p) { - if (p->default_value()) { - if (has_rest_parameter()) { + if (p->default_value()) + { + if (has_rest_parameter()) + { error("optional parameters may not be combined with variable-length parameters", p->pstate()); } has_optional_parameters(true); } - else if (p->is_rest_parameter()) { - if (has_rest_parameter()) { + else if (p->is_rest_parameter()) + { + if (has_rest_parameter()) + { error("functions and mixins cannot have more than one variable-length parameter", p->pstate()); } has_rest_parameter(true); } - else { - if (has_rest_parameter()) { + else + { + if (has_rest_parameter()) + { error("required parameters must precede variable-length parameters", p->pstate()); } - if (has_optional_parameters()) { + if (has_optional_parameters()) + { error("required parameters must precede optional parameters", p->pstate()); } } } - public: + + public: Parameters(ParserState pstate) - : AST_Node(pstate), - Vectorized(), - has_optional_parameters_(false), + : AST_Node(pstate), Vectorized(), has_optional_parameters_(false), has_rest_parameter_(false) - { } + { + } Parameters(const Parameters* ptr) - : AST_Node(ptr), - Vectorized(*ptr), - has_optional_parameters_(ptr->has_optional_parameters_), - has_rest_parameter_(ptr->has_rest_parameter_) - { } + : AST_Node(ptr), Vectorized(*ptr), + has_optional_parameters_(ptr->has_optional_parameters_), has_rest_parameter_(ptr->has_rest_parameter_) + { + } ATTACH_AST_OPERATIONS(Parameters) ATTACH_OPERATIONS() }; @@ -2215,7 +2724,8 @@ namespace Sass { ///////////////////////////////////////// // Abstract base class for CSS selectors. ///////////////////////////////////////// - class Selector : public Expression { + class Selector : public Expression + { // ADD_PROPERTY(bool, has_reference) // line break before list separator ADD_PROPERTY(bool, has_line_feed) @@ -2228,36 +2738,37 @@ namespace Sass { // must not be a reference counted object // otherwise we create circular references ADD_PROPERTY(Media_Block_Ptr, media_block) - protected: + protected: size_t hash_; - public: + + public: Selector(ParserState pstate) - : Expression(pstate), - has_line_feed_(false), - has_line_break_(false), - is_optional_(false), - media_block_(0), - hash_(0) - { concrete_type(SELECTOR); } + : Expression(pstate), has_line_feed_(false), has_line_break_(false), is_optional_(false), + media_block_(0), hash_(0) + { + concrete_type(SELECTOR); + } Selector(const Selector* ptr) : Expression(ptr), // has_reference_(ptr->has_reference_), - has_line_feed_(ptr->has_line_feed_), - has_line_break_(ptr->has_line_break_), - is_optional_(ptr->is_optional_), - media_block_(ptr->media_block_), - hash_(ptr->hash_) - { concrete_type(SELECTOR); } + has_line_feed_(ptr->has_line_feed_), has_line_break_(ptr->has_line_break_), + is_optional_(ptr->is_optional_), media_block_(ptr->media_block_), hash_(ptr->hash_) + { + concrete_type(SELECTOR); + } virtual ~Selector() = 0; virtual size_t hash() = 0; virtual unsigned long specificity() const = 0; - virtual void set_media_block(Media_Block_Ptr mb) { + virtual void set_media_block(Media_Block_Ptr mb) + { media_block(mb); } - virtual bool has_parent_ref() const { + virtual bool has_parent_ref() const + { return false; } - virtual bool has_real_parent_ref() const { + virtual bool has_real_parent_ref() const + { return false; } // dispatch to correct handlers @@ -2265,13 +2776,16 @@ namespace Sass { virtual bool operator==(const Selector& rhs) const = 0; ATTACH_VIRTUAL_AST_OPERATIONS(Selector); }; - inline Selector::~Selector() { } + inline Selector::~Selector() + { + } ///////////////////////////////////////////////////////////////////////// // Interpolated selectors -- the interpolated String will be expanded and // re-parsed into a normal selector class. ///////////////////////////////////////////////////////////////////////// - class Selector_Schema : public AST_Node { + class Selector_Schema : public AST_Node + { ADD_PROPERTY(String_Obj, contents) ADD_PROPERTY(bool, connect_parent); // must not be a reference counted object @@ -2279,30 +2793,31 @@ namespace Sass { ADD_PROPERTY(Media_Block_Ptr, media_block) // store computed hash size_t hash_; - public: + + public: Selector_Schema(ParserState pstate, String_Obj c) - : AST_Node(pstate), - contents_(c), - connect_parent_(true), - media_block_(NULL), - hash_(0) - { } + : AST_Node(pstate), contents_(c), connect_parent_(true), media_block_(NULL), hash_(0) + { + } Selector_Schema(const Selector_Schema* ptr) - : AST_Node(ptr), - contents_(ptr->contents_), - connect_parent_(ptr->connect_parent_), - media_block_(ptr->media_block_), - hash_(ptr->hash_) - { } + : AST_Node(ptr), contents_(ptr->contents_), connect_parent_(ptr->connect_parent_), + media_block_(ptr->media_block_), hash_(ptr->hash_) + { + } virtual bool has_parent_ref() const; virtual bool has_real_parent_ref() const; virtual bool operator<(const Selector& rhs) const; virtual bool operator==(const Selector& rhs) const; // selector schema is not yet a final selector, so we do not // have a specificity for it yet. We need to - virtual unsigned long specificity() const { return 0; } - virtual size_t hash() { - if (hash_ == 0) { + virtual unsigned long specificity() const + { + return 0; + } + virtual size_t hash() + { + if (hash_ == 0) + { hash_combine(hash_, contents_->hash()); } return hash_; @@ -2314,40 +2829,41 @@ namespace Sass { //////////////////////////////////////////// // Abstract base class for simple selectors. //////////////////////////////////////////// - class Simple_Selector : public Selector { + class Simple_Selector : public Selector + { ADD_CONSTREF(std::string, ns) ADD_CONSTREF(std::string, name) ADD_PROPERTY(Simple_Type, simple_type) ADD_PROPERTY(bool, has_ns) - public: + public: Simple_Selector(ParserState pstate, std::string n = "") : Selector(pstate), ns_(""), name_(n), has_ns_(false) { simple_type(SIMPLE); size_t pos = n.find('|'); // found some namespace - if (pos != std::string::npos) { + if (pos != std::string::npos) + { has_ns_ = true; ns_ = n.substr(0, pos); name_ = n.substr(pos + 1); } } Simple_Selector(const Simple_Selector* ptr) - : Selector(ptr), - ns_(ptr->ns_), - name_(ptr->name_), - has_ns_(ptr->has_ns_) - { simple_type(SIMPLE); } + : Selector(ptr), ns_(ptr->ns_), name_(ptr->name_), has_ns_(ptr->has_ns_) + { + simple_type(SIMPLE); + } virtual std::string ns_name() const { std::string name(""); - if (has_ns_) - name += ns_ + "|"; + if (has_ns_) name += ns_ + "|"; return name + name_; } virtual size_t hash() { - if (hash_ == 0) { + if (hash_ == 0) + { hash_combine(hash_, std::hash()(SELECTOR)); hash_combine(hash_, std::hash()(ns())); hash_combine(hash_, std::hash()(name())); @@ -2383,21 +2899,37 @@ namespace Sass { return name_ == "*"; } - virtual bool has_placeholder() { + virtual bool has_placeholder() + { return false; } virtual ~Simple_Selector() = 0; virtual Compound_Selector_Ptr unify_with(Compound_Selector_Ptr); - virtual bool has_parent_ref() const { return false; }; - virtual bool has_real_parent_ref() const { return false; }; - virtual bool is_pseudo_element() const { return false; } + virtual bool has_parent_ref() const + { + return false; + }; + virtual bool has_real_parent_ref() const + { + return false; + }; + virtual bool is_pseudo_element() const + { + return false; + } - virtual bool is_superselector_of(Compound_Selector_Obj sub) { return false; } + virtual bool is_superselector_of(Compound_Selector_Obj sub) + { + return false; + } virtual bool operator==(const Selector& rhs) const; virtual bool operator==(const Simple_Selector& rhs) const; - inline bool operator!=(const Simple_Selector& rhs) const { return !(*this == rhs); } + inline bool operator!=(const Simple_Selector& rhs) const + { + return !(*this == rhs); + } bool operator<(const Selector& rhs) const; bool operator<(const Simple_Selector& rhs) const; @@ -2405,7 +2937,9 @@ namespace Sass { ATTACH_VIRTUAL_AST_OPERATIONS(Simple_Selector); ATTACH_OPERATIONS(); }; - inline Simple_Selector::~Simple_Selector() { } + inline Simple_Selector::~Simple_Selector() + { + } ////////////////////////////////// @@ -2414,24 +2948,40 @@ namespace Sass { // parent selectors can occur in selectors but also // inside strings in declarations (Compound_Selector). // only one simple parent selector means the first case. - class Parent_Selector : public Simple_Selector { + class Parent_Selector : public Simple_Selector + { ADD_PROPERTY(bool, real) - public: - Parent_Selector(ParserState pstate, bool r = true) - : Simple_Selector(pstate, "&"), real_(r) - { /* has_reference(true); */ } - Parent_Selector(const Parent_Selector* ptr) - : Simple_Selector(ptr), real_(ptr->real_) - { /* has_reference(true); */ } - bool is_real_parent_ref() const { return real(); }; - virtual bool has_parent_ref() const { return true; }; - virtual bool has_real_parent_ref() const { return is_real_parent_ref(); }; + public: + Parent_Selector(ParserState pstate, bool r = true) : Simple_Selector(pstate, "&"), real_(r) + { /* has_reference(true); */ + } + Parent_Selector(const Parent_Selector* ptr) : Simple_Selector(ptr), real_(ptr->real_) + { /* has_reference(true); */ + } + bool is_real_parent_ref() const + { + return real(); + }; + virtual bool has_parent_ref() const + { + return true; + }; + virtual bool has_real_parent_ref() const + { + return is_real_parent_ref(); + }; virtual unsigned long specificity() const { return 0; } - std::string type() const { return "selector"; } - static std::string type_name() { return "selector"; } + std::string type() const + { + return "selector"; + } + static std::string type_name() + { + return "selector"; + } ATTACH_AST_OPERATIONS(Parent_Selector) ATTACH_OPERATIONS() }; @@ -2439,22 +2989,24 @@ namespace Sass { ///////////////////////////////////////////////////////////////////////// // Placeholder selectors (e.g., "%foo") for use in extend-only selectors. ///////////////////////////////////////////////////////////////////////// - class Placeholder_Selector : public Simple_Selector { - public: - Placeholder_Selector(ParserState pstate, std::string n) - : Simple_Selector(pstate, n) - { } - Placeholder_Selector(const Placeholder_Selector* ptr) - : Simple_Selector(ptr) - { } + class Placeholder_Selector : public Simple_Selector + { + public: + Placeholder_Selector(ParserState pstate, std::string n) : Simple_Selector(pstate, n) + { + } + Placeholder_Selector(const Placeholder_Selector* ptr) : Simple_Selector(ptr) + { + } virtual unsigned long specificity() const { return Constants::Specificity_Base; } - virtual bool has_placeholder() { + virtual bool has_placeholder() + { return true; } - virtual ~Placeholder_Selector() {}; + virtual ~Placeholder_Selector(){}; ATTACH_AST_OPERATIONS(Placeholder_Selector) ATTACH_OPERATIONS() }; @@ -2462,18 +3014,21 @@ namespace Sass { ///////////////////////////////////////////////////////////////////// // Element selectors (and the universal selector) -- e.g., div, span, *. ///////////////////////////////////////////////////////////////////// - class Element_Selector : public Simple_Selector { - public: - Element_Selector(ParserState pstate, std::string n) - : Simple_Selector(pstate, n) - { } - Element_Selector(const Element_Selector* ptr) - : Simple_Selector(ptr) - { } + class Element_Selector : public Simple_Selector + { + public: + Element_Selector(ParserState pstate, std::string n) : Simple_Selector(pstate, n) + { + } + Element_Selector(const Element_Selector* ptr) : Simple_Selector(ptr) + { + } virtual unsigned long specificity() const { - if (name() == "*") return 0; - else return Constants::Specificity_Element; + if (name() == "*") + return 0; + else + return Constants::Specificity_Element; } virtual Simple_Selector_Ptr unify_with(Simple_Selector_Ptr); virtual Compound_Selector_Ptr unify_with(Compound_Selector_Ptr); @@ -2484,14 +3039,15 @@ namespace Sass { //////////////////////////////////////////////// // Class selectors -- i.e., .foo. //////////////////////////////////////////////// - class Class_Selector : public Simple_Selector { - public: - Class_Selector(ParserState pstate, std::string n) - : Simple_Selector(pstate, n) - { } - Class_Selector(const Class_Selector* ptr) - : Simple_Selector(ptr) - { } + class Class_Selector : public Simple_Selector + { + public: + Class_Selector(ParserState pstate, std::string n) : Simple_Selector(pstate, n) + { + } + Class_Selector(const Class_Selector* ptr) : Simple_Selector(ptr) + { + } virtual unsigned long specificity() const { return Constants::Specificity_Class; @@ -2504,14 +3060,15 @@ namespace Sass { //////////////////////////////////////////////// // ID selectors -- i.e., #foo. //////////////////////////////////////////////// - class Id_Selector : public Simple_Selector { - public: - Id_Selector(ParserState pstate, std::string n) - : Simple_Selector(pstate, n) - { } - Id_Selector(const Id_Selector* ptr) - : Simple_Selector(ptr) - { } + class Id_Selector : public Simple_Selector + { + public: + Id_Selector(ParserState pstate, std::string n) : Simple_Selector(pstate, n) + { + } + Id_Selector(const Id_Selector* ptr) : Simple_Selector(ptr) + { + } virtual unsigned long specificity() const { return Constants::Specificity_ID; @@ -2524,22 +3081,26 @@ namespace Sass { /////////////////////////////////////////////////// // Attribute selectors -- e.g., [src*=".jpg"], etc. /////////////////////////////////////////////////// - class Attribute_Selector : public Simple_Selector { + class Attribute_Selector : public Simple_Selector + { ADD_CONSTREF(std::string, matcher) // this cannot be changed to obj atm!!!!!!????!!!!!!! ADD_PROPERTY(String_Obj, value) // might be interpolated - public: + public: Attribute_Selector(ParserState pstate, std::string n, std::string m, String_Obj v) : Simple_Selector(pstate, n), matcher_(m), value_(v) - { simple_type(ATTR_SEL); } + { + simple_type(ATTR_SEL); + } Attribute_Selector(const Attribute_Selector* ptr) - : Simple_Selector(ptr), - matcher_(ptr->matcher_), - value_(ptr->value_) - { simple_type(ATTR_SEL); } + : Simple_Selector(ptr), matcher_(ptr->matcher_), value_(ptr->value_) + { + simple_type(ATTR_SEL); + } virtual size_t hash() { - if (hash_ == 0) { + if (hash_ == 0) + { hash_combine(hash_, Simple_Selector::hash()); hash_combine(hash_, std::hash()(matcher())); if (value_) hash_combine(hash_, value_->hash()); @@ -2567,22 +3128,25 @@ namespace Sass { /* and occur only in the last simple_selector_sequence. */ inline bool is_pseudo_class_element(const std::string& name) { - return name == ":before" || - name == ":after" || - name == ":first-line" || + return name == ":before" || name == ":after" || name == ":first-line" || name == ":first-letter"; } // Pseudo Selector cannot have any namespace? - class Pseudo_Selector : public Simple_Selector { + class Pseudo_Selector : public Simple_Selector + { ADD_PROPERTY(String_Obj, expression) - public: + public: Pseudo_Selector(ParserState pstate, std::string n, String_Obj expr = 0) : Simple_Selector(pstate, n), expression_(expr) - { simple_type(PSEUDO_SEL); } + { + simple_type(PSEUDO_SEL); + } Pseudo_Selector(const Pseudo_Selector* ptr) : Simple_Selector(ptr), expression_(ptr->expression_) - { simple_type(PSEUDO_SEL); } + { + simple_type(PSEUDO_SEL); + } // A pseudo-element is made of two colons (::) followed by the name. // The `::` notation is introduced by the current document in order to @@ -2594,12 +3158,12 @@ namespace Sass { // introduced in this specification. virtual bool is_pseudo_element() const { - return (name_[0] == ':' && name_[1] == ':') - || is_pseudo_class_element(name_); + return (name_[0] == ':' && name_[1] == ':') || is_pseudo_class_element(name_); } virtual size_t hash() { - if (hash_ == 0) { + if (hash_ == 0) + { hash_combine(hash_, Simple_Selector::hash()); if (expression_) hash_combine(hash_, expression_->hash()); } @@ -2607,8 +3171,7 @@ namespace Sass { } virtual unsigned long specificity() const { - if (is_pseudo_element()) - return Constants::Specificity_Element; + if (is_pseudo_element()) return Constants::Specificity_Element; return Constants::Specificity_Pseudo; } virtual bool operator==(const Simple_Selector& rhs) const; @@ -2621,17 +3184,22 @@ namespace Sass { }; ///////////////////////////////////////////////// - // 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) + // 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) ///////////////////////////////////////////////// - class Wrapped_Selector : public Simple_Selector { + class Wrapped_Selector : public Simple_Selector + { ADD_PROPERTY(Selector_List_Obj, selector) - public: + public: Wrapped_Selector(ParserState pstate, std::string n, Selector_List_Obj sel) : Simple_Selector(pstate, n), selector_(sel) - { simple_type(WRAPPED_SEL); } - Wrapped_Selector(const Wrapped_Selector* ptr) - : Simple_Selector(ptr), selector_(ptr->selector_) - { simple_type(WRAPPED_SEL); } + { + simple_type(WRAPPED_SEL); + } + Wrapped_Selector(const Wrapped_Selector* ptr) : Simple_Selector(ptr), selector_(ptr->selector_) + { + simple_type(WRAPPED_SEL); + } virtual bool is_superselector_of(Wrapped_Selector_Obj sub); // Selectors inside the negation pseudo-class are counted like any // other, but the negation itself does not count as a pseudo-class. @@ -2652,32 +3220,34 @@ namespace Sass { // Simple selector sequences. Maintains flags indicating whether it contains // any parent references or placeholders, to simplify expansion. //////////////////////////////////////////////////////////////////////////// - class Compound_Selector : public Selector, public Vectorized { - private: + class Compound_Selector : public Selector, public Vectorized + { + private: ComplexSelectorSet sources_; ADD_PROPERTY(bool, extended); ADD_PROPERTY(bool, has_parent_reference); - protected: + + protected: void adjust_after_pushing(Simple_Selector_Obj s) { // if (s->has_reference()) has_reference(true); // if (s->has_placeholder()) has_placeholder(true); } - public: + + public: Compound_Selector(ParserState pstate, size_t s = 0) - : Selector(pstate), - Vectorized(s), - extended_(false), - has_parent_reference_(false) - { } + : Selector(pstate), Vectorized(s), extended_(false), has_parent_reference_(false) + { + } Compound_Selector(const Compound_Selector* ptr) - : Selector(ptr), - Vectorized(*ptr), - extended_(ptr->extended_), + : Selector(ptr), Vectorized(*ptr), extended_(ptr->extended_), has_parent_reference_(ptr->has_parent_reference_) - { } - bool contains_placeholder() { - for (size_t i = 0, L = length(); i < L; ++i) { + { + } + bool contains_placeholder() + { + for (size_t i = 0, L = length(); i < L; ++i) + { if ((*this)[i]->has_placeholder()) return true; } return false; @@ -2695,11 +3265,11 @@ namespace Sass { // virtual Placeholder_Selector_Ptr find_placeholder(); virtual bool has_parent_ref() const; virtual bool has_real_parent_ref() const; - Simple_Selector_Ptr base() const { + Simple_Selector_Ptr base() const + { if (length() == 0) return 0; // ToDo: why is this needed? - if (Cast((*this)[0])) - return (*this)[0]; + if (Cast((*this)[0])) return (*this)[0]; return 0; } virtual bool is_superselector_of(Compound_Selector_Obj sub, std::string wrapped = ""); @@ -2707,7 +3277,8 @@ namespace Sass { virtual bool is_superselector_of(Selector_List_Obj sub, std::string wrapped = ""); virtual size_t hash() { - if (Selector::hash_ == 0) { + if (Selector::hash_ == 0) + { hash_combine(Selector::hash_, std::hash()(SELECTOR)); if (length()) hash_combine(Selector::hash_, Vectorized::hash()); } @@ -2717,14 +3288,17 @@ namespace Sass { { int sum = 0; for (size_t i = 0, L = length(); i < L; ++i) - { sum += (*this)[i]->specificity(); } + { + sum += (*this)[i]->specificity(); + } return sum; } virtual bool has_placeholder() { if (length() == 0) return false; - if (Simple_Selector_Obj ss = elements().front()) { + if (Simple_Selector_Obj ss = elements().front()) + { if (ss->has_placeholder()) return true; } return false; @@ -2732,18 +3306,26 @@ namespace Sass { bool is_empty_reference() { - return length() == 1 && - Cast((*this)[0]); + return length() == 1 && Cast((*this)[0]); } virtual bool operator<(const Selector& rhs) const; virtual bool operator==(const Selector& rhs) const; virtual bool operator<(const Compound_Selector& rhs) const; virtual bool operator==(const Compound_Selector& rhs) const; - inline bool operator!=(const Compound_Selector& rhs) const { return !(*this == rhs); } + inline bool operator!=(const Compound_Selector& rhs) const + { + return !(*this == rhs); + } - ComplexSelectorSet& sources() { return sources_; } - void clearSources() { sources_.clear(); } + ComplexSelectorSet& sources() + { + return sources_; + } + void clearSources() + { + sources_.clear(); + } void mergeSources(ComplexSelectorSet& sources); Compound_Selector_Ptr minus(Compound_Selector_Ptr rhs); @@ -2757,16 +3339,27 @@ namespace Sass { // CSS selector combinators (">", "+", "~", and whitespace). Essentially a // linked list. //////////////////////////////////////////////////////////////////////////// - class Complex_Selector : public Selector { - public: - enum Combinator { ANCESTOR_OF, PARENT_OF, PRECEDES, ADJACENT_TO, REFERENCE }; - private: + class Complex_Selector : public Selector + { + public: + enum Combinator + { + ANCESTOR_OF, + PARENT_OF, + PRECEDES, + ADJACENT_TO, + REFERENCE + }; + + private: HASH_CONSTREF(Combinator, combinator) HASH_PROPERTY(Compound_Selector_Obj, head) HASH_PROPERTY(Complex_Selector_Obj, tail) HASH_PROPERTY(String_Obj, reference); - public: - bool contains_placeholder() { + + public: + bool contains_placeholder() + { if (head() && head()->contains_placeholder()) return true; if (tail() && tail()->contains_placeholder()) return true; return false; @@ -2776,24 +3369,18 @@ namespace Sass { Compound_Selector_Obj h = 0, Complex_Selector_Obj t = 0, String_Obj r = 0) - : Selector(pstate), - combinator_(c), - head_(h), tail_(t), - reference_(r) - {} + : Selector(pstate), combinator_(c), head_(h), tail_(t), reference_(r) + { + } Complex_Selector(const Complex_Selector* ptr) - : Selector(ptr), - combinator_(ptr->combinator_), - head_(ptr->head_), tail_(ptr->tail_), - reference_(ptr->reference_) - {}; + : Selector(ptr), combinator_(ptr->combinator_), head_(ptr->head_), tail_(ptr->tail_), + reference_(ptr->reference_){}; virtual bool has_parent_ref() const; virtual bool has_real_parent_ref() const; Complex_Selector_Obj skip_empty_reference() { - if ((!head_ || !head_->length() || head_->is_empty_reference()) && - combinator() == Combinator::ANCESTOR_OF) + if ((!head_ || !head_->length() || head_->is_empty_reference()) && combinator() == Combinator::ANCESTOR_OF) { if (!tail_) return 0; tail_->has_line_feed_ = this->has_line_feed_; @@ -2806,8 +3393,7 @@ namespace Sass { // can still have a tail bool is_empty_ancestor() const { - return (!head() || head()->length() == 0) && - combinator() == Combinator::ANCESTOR_OF; + return (!head() || head()->length() == 0) && combinator() == Combinator::ANCESTOR_OF; } Selector_List_Ptr tails(Selector_List_Ptr tails); @@ -2819,7 +3405,10 @@ namespace Sass { Complex_Selector_Obj last(); // some shortcuts that should be removed - Complex_Selector_Obj innermost() { return last(); }; + Complex_Selector_Obj innermost() + { + return last(); + }; size_t length() const; Selector_List_Ptr resolve_parent_refs(std::vector& pstack, bool implicit_parent = true); @@ -2832,7 +3421,8 @@ namespace Sass { void set_innermost(Complex_Selector_Obj, Combinator); virtual size_t hash() { - if (hash_ == 0) { + if (hash_ == 0) + { hash_combine(hash_, std::hash()(SELECTOR)); hash_combine(hash_, std::hash()(combinator_)); if (head_) hash_combine(hash_, head_->hash()); @@ -2847,12 +3437,14 @@ namespace Sass { if (tail()) sum += tail()->specificity(); return sum; } - virtual void set_media_block(Media_Block_Ptr mb) { + virtual void set_media_block(Media_Block_Ptr mb) + { media_block(mb); if (tail_) tail_->set_media_block(mb); if (head_) head_->set_media_block(mb); } - virtual bool has_placeholder() { + virtual bool has_placeholder() + { if (head_ && head_->has_placeholder()) return true; if (tail_ && tail_->has_placeholder()) return true; return false; @@ -2861,49 +3453,60 @@ namespace Sass { virtual bool operator==(const Selector& rhs) const; virtual bool operator<(const Complex_Selector& rhs) const; virtual bool operator==(const Complex_Selector& rhs) const; - inline bool operator!=(const Complex_Selector& rhs) const { return !(*this == rhs); } + inline bool operator!=(const Complex_Selector& rhs) const + { + return !(*this == rhs); + } const ComplexSelectorSet sources() { - //s = Set.new - //seq.map {|sseq_or_op| s.merge sseq_or_op.sources if sseq_or_op.is_a?(SimpleSequence)} - //s + // s = Set.new + // seq.map {|sseq_or_op| s.merge sseq_or_op.sources if sseq_or_op.is_a?(SimpleSequence)} + // s ComplexSelectorSet srcs; Compound_Selector_Obj pHead = head(); - Complex_Selector_Obj pTail = tail(); + Complex_Selector_Obj pTail = tail(); - if (pHead) { + if (pHead) + { const ComplexSelectorSet& headSources = pHead->sources(); srcs.insert(headSources.begin(), headSources.end()); } - if (pTail) { + if (pTail) + { const ComplexSelectorSet& tailSources = pTail->sources(); srcs.insert(tailSources.begin(), tailSources.end()); } return srcs; } - void addSources(ComplexSelectorSet& sources) { + void addSources(ComplexSelectorSet& sources) + { // members.map! {|m| m.is_a?(SimpleSequence) ? m.with_more_sources(sources) : m} Complex_Selector_Ptr pIter = this; - while (pIter) { + while (pIter) + { Compound_Selector_Ptr pHead = pIter->head(); - if (pHead) { + if (pHead) + { pHead->mergeSources(sources); } pIter = pIter->tail(); } } - void clearSources() { + void clearSources() + { Complex_Selector_Ptr pIter = this; - while (pIter) { + while (pIter) + { Compound_Selector_Ptr pHead = pIter->head(); - if (pHead) { + if (pHead) + { pHead->clearSources(); } @@ -2919,25 +3522,26 @@ namespace Sass { /////////////////////////////////// // Comma-separated selector groups. /////////////////////////////////// - class Selector_List : public Selector, public Vectorized { + class Selector_List : public Selector, public Vectorized + { ADD_PROPERTY(Selector_Schema_Obj, schema) ADD_CONSTREF(std::vector, wspace) - protected: + protected: void adjust_after_pushing(Complex_Selector_Obj c); - public: + + public: Selector_List(ParserState pstate, size_t s = 0) - : Selector(pstate), - Vectorized(s), - schema_(NULL), - wspace_(0) - { } + : Selector(pstate), Vectorized(s), schema_(NULL), wspace_(0) + { + } Selector_List(const Selector_List* ptr) - : Selector(ptr), - Vectorized(*ptr), - schema_(ptr->schema_), - wspace_(ptr->wspace_) - { } - std::string type() const { return "list"; } + : Selector(ptr), Vectorized(*ptr), schema_(ptr->schema_), wspace_(ptr->wspace_) + { + } + std::string type() const + { + return "list"; + } // remove parent selector references // basically unwraps parsed selectors virtual bool has_parent_ref() const; @@ -2952,7 +3556,8 @@ namespace Sass { Selector_List_Obj eval(Eval& eval); virtual size_t hash() { - if (Selector::hash_ == 0) { + if (Selector::hash_ == 0) + { hash_combine(Selector::hash_, std::hash()(SELECTOR)); hash_combine(Selector::hash_, Vectorized::hash()); } @@ -2969,14 +3574,18 @@ namespace Sass { } return sum; } - virtual void set_media_block(Media_Block_Ptr mb) { + virtual void set_media_block(Media_Block_Ptr mb) + { media_block(mb); - for (Complex_Selector_Obj cs : elements()) { + for (Complex_Selector_Obj cs : elements()) + { cs->set_media_block(mb); } } - virtual bool has_placeholder() { - for (Complex_Selector_Obj cs : elements()) { + virtual bool has_placeholder() + { + for (Complex_Selector_Obj cs : elements()) + { if (cs->has_placeholder()) return true; } return false; @@ -2993,10 +3602,27 @@ namespace Sass { }; // compare function for sorting and probably other other uses - struct cmp_complex_selector { inline bool operator() (const Complex_Selector_Obj l, const Complex_Selector_Obj r) { return (*l < *r); } }; - struct cmp_compound_selector { inline bool operator() (const Compound_Selector_Obj l, const Compound_Selector_Obj r) { return (*l < *r); } }; - struct cmp_simple_selector { inline bool operator() (const Simple_Selector_Obj l, const Simple_Selector_Obj r) { return (*l < *r); } }; - + struct cmp_complex_selector + { + inline bool operator()(const Complex_Selector_Obj l, const Complex_Selector_Obj r) + { + return (*l < *r); + } + }; + struct cmp_compound_selector + { + inline bool operator()(const Compound_Selector_Obj l, const Compound_Selector_Obj r) + { + return (*l < *r); + } + }; + struct cmp_simple_selector + { + inline bool operator()(const Simple_Selector_Obj l, const Simple_Selector_Obj r) + { + return (*l < *r); + } + }; } #ifdef __clang__ diff --git a/src/ast_def_macros.hpp b/src/ast_def_macros.hpp index 0ff30d1e3e..b22a19cbcb 100644 --- a/src/ast_def_macros.hpp +++ b/src/ast_def_macros.hpp @@ -2,70 +2,129 @@ #define SASS_AST_DEF_MACROS_H // Helper class to switch a flag and revert once we go out of scope -template -class LocalOption { +template class LocalOption +{ private: - T* var; // pointer to original variable - T orig; // copy of the original option + T* var; // pointer to original variable + T orig; // copy of the original option public: - LocalOption(T& var) - { - this->var = &var; - this->orig = var; - } - LocalOption(T& var, T orig) - { - this->var = &var; - this->orig = var; - *(this->var) = orig; - } - ~LocalOption() { - *(this->var) = this->orig; - } + LocalOption(T& var) + { + this->var = &var; + this->orig = var; + } + LocalOption(T& var, T orig) + { + this->var = &var; + this->orig = var; + *(this->var) = orig; + } + ~LocalOption() + { + *(this->var) = this->orig; + } }; -#define LOCAL_FLAG(name,opt) LocalOption flag_##name(name, opt) +#define LOCAL_FLAG(name, opt) LocalOption flag_##name(name, opt) -#define ATTACH_OPERATIONS()\ -virtual void perform(Operation* op) { (*op)(this); }\ -virtual AST_Node_Ptr perform(Operation* op) { return (*op)(this); }\ -virtual Statement_Ptr perform(Operation* op) { return (*op)(this); }\ -virtual Expression_Ptr perform(Operation* op) { return (*op)(this); }\ -virtual Selector_Ptr perform(Operation* op) { return (*op)(this); }\ -virtual std::string perform(Operation* op) { return (*op)(this); }\ -virtual union Sass_Value* perform(Operation* op) { return (*op)(this); }\ -virtual Value_Ptr perform(Operation* op) { return (*op)(this); } +#define ATTACH_OPERATIONS() \ + virtual void perform(Operation* op) \ + { \ + (*op)(this); \ + } \ + virtual AST_Node_Ptr perform(Operation* op) \ + { \ + return (*op)(this); \ + } \ + virtual Statement_Ptr perform(Operation* op) \ + { \ + return (*op)(this); \ + } \ + virtual Expression_Ptr perform(Operation* op) \ + { \ + return (*op)(this); \ + } \ + virtual Selector_Ptr perform(Operation* op) \ + { \ + return (*op)(this); \ + } \ + virtual std::string perform(Operation* op) \ + { \ + return (*op)(this); \ + } \ + virtual union Sass_Value* perform(Operation* op) \ + { \ + return (*op)(this); \ + } \ + virtual Value_Ptr perform(Operation* op) \ + { \ + return (*op)(this); \ + } -#define ADD_PROPERTY(type, name)\ -protected:\ - type name##_;\ -public:\ - type name() const { return name##_; }\ - type name(type name##__) { return name##_ = name##__; }\ -private: +#define ADD_PROPERTY(type, name) \ + protected: \ + type name##_; \ + \ + public: \ + type name() const \ + { \ + return name##_; \ + } \ + type name(type name##__) \ + { \ + return name##_ = name##__; \ + } \ + \ + private: -#define HASH_PROPERTY(type, name)\ -protected:\ - type name##_;\ -public:\ - type name() const { return name##_; }\ - type name(type name##__) { hash_ = 0; return name##_ = name##__; }\ -private: +#define HASH_PROPERTY(type, name) \ + protected: \ + type name##_; \ + \ + public: \ + type name() const \ + { \ + return name##_; \ + } \ + type name(type name##__) \ + { \ + hash_ = 0; \ + return name##_ = name##__; \ + } \ + \ + private: #define ADD_CONSTREF(type, name) \ -protected: \ - type name##_; \ -public: \ - const type& name() const { return name##_; } \ - void name(type name##__) { name##_ = name##__; } \ -private: + protected: \ + type name##_; \ + \ + public: \ + const type& name() const \ + { \ + return name##_; \ + } \ + void name(type name##__) \ + { \ + name##_ = name##__; \ + } \ + \ + private: #define HASH_CONSTREF(type, name) \ -protected: \ - type name##_; \ -public: \ - const type& name() const { return name##_; } \ - void name(type name##__) { hash_ = 0; name##_ = name##__; } \ -private: + protected: \ + type name##_; \ + \ + public: \ + const type& name() const \ + { \ + return name##_; \ + } \ + void name(type name##__) \ + { \ + hash_ = 0; \ + name##_ = name##__; \ + } \ + \ + private: #endif diff --git a/src/ast_fwd_decl.cpp b/src/ast_fwd_decl.cpp index c9c76727a6..38813e17f7 100644 --- a/src/ast_fwd_decl.cpp +++ b/src/ast_fwd_decl.cpp @@ -1,17 +1,18 @@ #include "ast.hpp" -namespace Sass { +namespace Sass +{ - #define IMPLEMENT_BASE_CAST(T) \ - template<> \ - T* Cast(AST_Node* ptr) { \ - return dynamic_cast(ptr); \ - }; \ - \ - template<> \ - const T* Cast(const AST_Node* ptr) { \ - return dynamic_cast(ptr); \ - }; \ +#define IMPLEMENT_BASE_CAST(T) \ + template <> T* Cast(AST_Node* ptr) \ + { \ + return dynamic_cast(ptr); \ + }; \ + \ + template <> const T* Cast(const AST_Node* ptr) \ + { \ + return dynamic_cast(ptr); \ + }; IMPLEMENT_BASE_CAST(AST_Node) IMPLEMENT_BASE_CAST(Expression) @@ -25,5 +26,4 @@ namespace Sass { IMPLEMENT_BASE_CAST(Supports_Condition) IMPLEMENT_BASE_CAST(Selector) IMPLEMENT_BASE_CAST(Simple_Selector) - } diff --git a/src/ast_fwd_decl.hpp b/src/ast_fwd_decl.hpp index 5ce94b6daa..be551993c4 100644 --- a/src/ast_fwd_decl.hpp +++ b/src/ast_fwd_decl.hpp @@ -15,7 +15,8 @@ ///////////////////////////////////////////// // Forward declarations for the AST visitors. ///////////////////////////////////////////// -namespace Sass { +namespace Sass +{ class AST_Node; typedef AST_Node* AST_Node_Ptr; @@ -252,19 +253,19 @@ namespace Sass { class Pseudo_Selector; typedef Pseudo_Selector* Pseudo_Selector_Ptr; - typedef Pseudo_Selector const * Pseudo_Selector_Ptr_Const; + typedef Pseudo_Selector const* Pseudo_Selector_Ptr_Const; class Wrapped_Selector; typedef Wrapped_Selector* Wrapped_Selector_Ptr; - typedef Wrapped_Selector const * Wrapped_Selector_Ptr_Const; + typedef Wrapped_Selector const* Wrapped_Selector_Ptr_Const; class Compound_Selector; typedef Compound_Selector* Compound_Selector_Ptr; - typedef Compound_Selector const * Compound_Selector_Ptr_Const; + typedef Compound_Selector const* Compound_Selector_Ptr_Const; class Complex_Selector; typedef Complex_Selector* Complex_Selector_Ptr; - typedef Complex_Selector const * Complex_Selector_Ptr_Const; + typedef Complex_Selector const* Complex_Selector_Ptr_Const; class Selector_List; typedef Selector_List* Selector_List_Ptr; - typedef Selector_List const * Selector_List_Ptr_Const; + typedef Selector_List const* Selector_List_Ptr_Const; // common classes @@ -272,9 +273,9 @@ namespace Sass { class Expand; class Eval; - // declare classes that are instances of memory nodes - // #define IMPL_MEM_OBJ(type) using type##_Obj = SharedImpl - #define IMPL_MEM_OBJ(type) typedef SharedImpl type##_Obj +// declare classes that are instances of memory nodes +// #define IMPL_MEM_OBJ(type) using type##_Obj = SharedImpl +#define IMPL_MEM_OBJ(type) typedef SharedImpl type##_Obj IMPL_MEM_OBJ(AST_Node); IMPL_MEM_OBJ(Statement); @@ -357,26 +358,28 @@ namespace Sass { // Implement compare, order and hashing operations for AST Nodes // ########################################################################### - struct HashNodes { - template - size_t operator() (const T& ex) const { + struct HashNodes + { + template size_t operator()(const T& ex) const + { return ex.isNull() ? 0 : ex->hash(); } }; - struct OrderNodes { - template - bool operator() (const T& lhs, const T& rhs) const { + struct OrderNodes + { + template bool operator()(const T& lhs, const T& rhs) const + { return !lhs.isNull() && !rhs.isNull() && *lhs < *rhs; } }; - struct CompareNodes { - template - bool operator() (const T& lhs, const T& rhs) const { + struct CompareNodes + { + template bool operator()(const T& lhs, const T& rhs) const + { // code around sass logic issue. 1px == 1 is true // but both items are still different keys in maps if (dynamic_cast(lhs.ptr())) - if (dynamic_cast(rhs.ptr())) - return lhs->hash() == rhs->hash(); + if (dynamic_cast(rhs.ptr())) return lhs->hash() == rhs->hash(); return !lhs.isNull() && !rhs.isNull() && *lhs == *rhs; } }; @@ -385,17 +388,17 @@ namespace Sass { // some often used typedefs // ########################################################################### - typedef std::unordered_map< - Expression_Obj, // key - Expression_Obj, // value - HashNodes, // hasher - CompareNodes // compare - > ExpressionMap; - typedef std::unordered_set< - Expression_Obj, // value - HashNodes, // hasher - CompareNodes // compare - > ExpressionSet; + typedef std::unordered_map + ExpressionMap; + typedef std::unordered_set + ExpressionSet; typedef std::string SubSetMapKey; typedef std::vector SubSetMapKeys; @@ -414,25 +417,23 @@ namespace Sass { typedef std::set CompoundSelectorSet; typedef std::unordered_set SimpleSelectorDict; - // only to switch implementations for testing - #define environment_map std::map +// only to switch implementations for testing +#define environment_map std::map // ########################################################################### // explicit type conversion functions // ########################################################################### - template - T* Cast(AST_Node* ptr); + template T* Cast(AST_Node* ptr); - template - const T* Cast(const AST_Node* ptr); + template const T* Cast(const AST_Node* ptr); - // sometimes you know the class you want to cast to is final - // in this case a simple typeid check is faster and safe to use +// sometimes you know the class you want to cast to is final +// in this case a simple typeid check is faster and safe to use - #define DECLARE_BASE_CAST(T) \ - template<> T* Cast(AST_Node* ptr); \ - template<> const T* Cast(const AST_Node* ptr); \ +#define DECLARE_BASE_CAST(T) \ + template <> T* Cast(AST_Node* ptr); \ + template <> const T* Cast(const AST_Node* ptr); // ########################################################################### // implement specialization for final classes @@ -450,7 +451,6 @@ namespace Sass { DECLARE_BASE_CAST(Supports_Condition) DECLARE_BASE_CAST(Selector) DECLARE_BASE_CAST(Simple_Selector) - } #endif diff --git a/src/backtrace.hpp b/src/backtrace.hpp index 57ce1786f2..145df4fe24 100644 --- a/src/backtrace.hpp +++ b/src/backtrace.hpp @@ -6,20 +6,21 @@ #include "file.hpp" #include "position.hpp" -namespace Sass { +namespace Sass +{ - struct Backtrace { + struct Backtrace + { - Backtrace* parent; + Backtrace* parent; ParserState pstate; - std::string caller; + std::string caller; Backtrace(Backtrace* prn, ParserState pstate, std::string c) - : parent(prn), - pstate(pstate), - caller(c) - { } + : parent(prn), pstate(pstate), caller(c) + { + } const std::string to_string(bool warning = false) { @@ -30,26 +31,22 @@ namespace Sass { if (!warning) ss << std::endl << "Backtrace:"; // the first tracepoint (which is parent-less) is an empty placeholder - while (this_point->parent) { + while (this_point->parent) + { // make path relative to the current directory std::string rel_path(Sass::File::abs2rel(this_point->pstate.path, cwd, cwd)); - if (warning) { + if (warning) + { ss << std::endl - << "\t" - << (++i == 0 ? "on" : "from") - << " line " - << this_point->pstate.line + 1 - << " of " - << rel_path; - } else { + << "\t" << (++i == 0 ? "on" : "from") << " line " << this_point->pstate.line + 1 + << " of " << rel_path; + } + else + { ss << std::endl - << "\t" - << rel_path - << ":" - << this_point->pstate.line + 1 - << this_point->parent->caller; + << "\t" << rel_path << ":" << this_point->pstate.line + 1 << this_point->parent->caller; } this_point = this_point->parent; @@ -62,15 +59,14 @@ namespace Sass { { size_t d = std::string::npos; Backtrace* p = parent; - while (p) { + while (p) + { ++d; p = p->parent; } return d; } - }; - } #endif diff --git a/src/base64vlq.cpp b/src/base64vlq.cpp index be2fb4926a..76b3c1ba84 100644 --- a/src/base64vlq.cpp +++ b/src/base64vlq.cpp @@ -1,7 +1,8 @@ #include "sass.hpp" #include "base64vlq.hpp" -namespace Sass { +namespace Sass +{ std::string Base64VLQ::encode(const int number) const { @@ -9,10 +10,12 @@ namespace Sass { int vlq = to_vlq_signed(number); - do { + do + { int digit = vlq & VLQ_BASE_MASK; vlq >>= VLQ_BASE_SHIFT; - if (vlq > 0) { + if (vlq > 0) + { digit |= VLQ_CONTINUATION_BIT; } encoded += base64_encode(digit); @@ -34,11 +37,11 @@ namespace Sass { return (number < 0) ? ((-number) << 1) + 1 : (number << 1) + 0; } - const char* Base64VLQ::CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + const char* Base64VLQ::CHARACTERS = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; const int Base64VLQ::VLQ_BASE_SHIFT = 5; const int Base64VLQ::VLQ_BASE = 1 << VLQ_BASE_SHIFT; const int Base64VLQ::VLQ_BASE_MASK = VLQ_BASE - 1; const int Base64VLQ::VLQ_CONTINUATION_BIT = VLQ_BASE; - } diff --git a/src/base64vlq.hpp b/src/base64vlq.hpp index aca315a21e..de2a67c9f4 100644 --- a/src/base64vlq.hpp +++ b/src/base64vlq.hpp @@ -3,16 +3,16 @@ #include -namespace Sass { +namespace Sass +{ - class Base64VLQ { - - public: + class Base64VLQ + { + public: std::string encode(const int number) const; - private: - + private: char base64_encode(const int number) const; int to_vlq_signed(const int number) const; @@ -24,7 +24,6 @@ namespace Sass { static const int VLQ_BASE_MASK; static const int VLQ_CONTINUATION_BIT; }; - } #endif diff --git a/src/bind.cpp b/src/bind.cpp index 84947ab090..681cae77da 100644 --- a/src/bind.cpp +++ b/src/bind.cpp @@ -7,7 +7,8 @@ #include #include -namespace Sass { +namespace Sass +{ void bind(std::string type, std::string name, Parameters_Obj ps, Arguments_Obj as, Context* ctx, Env* env, Eval* eval) { @@ -15,10 +16,13 @@ namespace Sass { std::map param_map; - for (size_t i = 0, L = as->length(); i < L; ++i) { - if (auto str = Cast((*as)[i]->value())) { + for (size_t i = 0, L = as->length(); i < L; ++i) + { + if (auto str = Cast((*as)[i]->value())) + { // force optional quotes (only if needed) - if (str->quote_mark()) { + if (str->quote_mark()) + { str->quote_mark('*'); } } @@ -26,8 +30,9 @@ namespace Sass { // Set up a map to ensure named arguments refer to actual parameters. Also // eval each default value left-to-right, wrt env, populating env as we go. - for (size_t i = 0, L = ps->length(); i < L; ++i) { - Parameter_Obj p = ps->at(i); + for (size_t i = 0, L = ps->length(); i < L; ++i) + { + Parameter_Obj p = ps->at(i); param_map[p->name()] = p; // if (p->default_value()) { // env->local_frame()[p->name()] = p->default_value()->perform(eval->with(env)); @@ -37,14 +42,20 @@ namespace Sass { // plug in all args; if we have leftover params, deal with it later size_t ip = 0, LP = ps->length(); size_t ia = 0, LA = as->length(); - while (ia < LA) { + while (ia < LA) + { Argument_Obj a = as->at(ia); - if (ip >= LP) { + if (ip >= LP) + { // skip empty rest arguments - if (a->is_rest_argument()) { - if (List_Obj l = Cast(a->value())) { - if (l->length() == 0) { - ++ ia; continue; + if (a->is_rest_argument()) + { + if (List_Obj l = Cast(a->value())) + { + if (l->length() == 0) + { + ++ia; + continue; } } } @@ -56,64 +67,59 @@ namespace Sass { Parameter_Obj p = ps->at(ip); // If the current parameter is the rest parameter, process and break the loop - if (p->is_rest_parameter()) { + if (p->is_rest_parameter()) + { // The next argument by coincidence provides a rest argument - if (a->is_rest_argument()) { + if (a->is_rest_argument()) + { // We should always get a list for rest arguments - if (List_Obj rest = Cast(a->value())) { - // create a new list object for wrapped items - List_Ptr arglist = SASS_MEMORY_NEW(List, - p->pstate(), - 0, - rest->separator(), - true); - // wrap each item from list as an argument - for (Expression_Obj item : rest->elements()) { - if (Argument_Obj arg = Cast(item)) { - arglist->append(SASS_MEMORY_COPY(arg)); // copy - } else { - arglist->append(SASS_MEMORY_NEW(Argument, - item->pstate(), - item, - "", - false, - false)); - } + if (List_Obj rest = Cast(a->value())) + { + // create a new list object for wrapped items + List_Ptr arglist = SASS_MEMORY_NEW(List, p->pstate(), 0, rest->separator(), true); + // wrap each item from list as an argument + for (Expression_Obj item : rest->elements()) + { + if (Argument_Obj arg = Cast(item)) + { + arglist->append(SASS_MEMORY_COPY(arg)); // copy + } + else + { + arglist->append(SASS_MEMORY_NEW(Argument, item->pstate(), item, "", false, false)); } - // assign new arglist to environment - env->local_frame()[p->name()] = arglist; } + // assign new arglist to environment + env->local_frame()[p->name()] = arglist; + } // invalid state - else { + else + { throw std::runtime_error("invalid state"); } - } else if (a->is_keyword_argument()) { + } + else if (a->is_keyword_argument()) + { // expand keyword arguments into their parameters List_Ptr arglist = SASS_MEMORY_NEW(List, p->pstate(), 0, SASS_COMMA, true); env->local_frame()[p->name()] = arglist; Map_Obj argmap = Cast(a->value()); - for (auto key : argmap->keys()) { + for (auto key : argmap->keys()) + { std::string param = unquote(Cast(key)->value()); - arglist->append(SASS_MEMORY_NEW(Argument, - key->pstate(), - argmap->at(key), - "$" + param, - false, - false)); + arglist->append(SASS_MEMORY_NEW(Argument, key->pstate(), argmap->at(key), "$" + param, false, false)); } - - } else { + } + else + { // create a new list object for wrapped items - List_Obj arglist = SASS_MEMORY_NEW(List, - p->pstate(), - 0, - SASS_COMMA, - true); + List_Obj arglist = SASS_MEMORY_NEW(List, p->pstate(), 0, SASS_COMMA, true); // consume the next args - while (ia < LA) { + while (ia < LA) + { // get and post inc a = (*as)[ia++]; // maybe we have another list as argument @@ -122,36 +128,31 @@ namespace Sass { if (ls && ls->empty() && a->is_rest_argument()) continue; Expression_Obj value = a->value(); - if (Argument_Obj arg = Cast(value)) { + if (Argument_Obj arg = Cast(value)) + { arglist->append(arg); } // check if we have rest argument - else if (a->is_rest_argument()) { + else if (a->is_rest_argument()) + { // preserve the list separator from rest args - if (List_Obj rest = Cast(a->value())) { + if (List_Obj rest = Cast(a->value())) + { arglist->separator(rest->separator()); - for (size_t i = 0, L = rest->size(); i < L; ++i) { + for (size_t i = 0, L = rest->size(); i < L; ++i) + { Expression_Obj obj = rest->at(i); - arglist->append(SASS_MEMORY_NEW(Argument, - obj->pstate(), - obj, - "", - false, - false)); + arglist->append(SASS_MEMORY_NEW(Argument, obj->pstate(), obj, "", false, false)); } } // no more arguments break; } // wrap all other value types into Argument - else { - arglist->append(SASS_MEMORY_NEW(Argument, - a->pstate(), - a->value(), - a->name(), - false, - false)); + else + { + arglist->append(SASS_MEMORY_NEW(Argument, a->pstate(), a->value(), a->name(), false, false)); } } // assign new arglist to environment @@ -164,21 +165,28 @@ namespace Sass { } // If the current argument is the rest argument, extract a value for processing - else if (a->is_rest_argument()) { + else if (a->is_rest_argument()) + { // normal param and rest arg List_Obj arglist = Cast(a->value()); - if (!arglist) { - if (Expression_Obj arg = Cast(a->value())) { + if (!arglist) + { + if (Expression_Obj arg = Cast(a->value())) + { arglist = SASS_MEMORY_NEW(List, a->pstate(), 1); arglist->append(arg); } } // empty rest arg - treat all args as default values - if (!arglist || !arglist->length()) { + if (!arglist || !arglist->length()) + { break; - } else { - if (arglist->length() > LP - ip && !ps->has_rest_parameter()) { + } + else + { + if (arglist->length() > LP - ip && !ps->has_rest_parameter()) + { size_t arg_count = (arglist->length() + LA - 1); std::stringstream msg; msg << callee << " takes " << LP; @@ -187,34 +195,35 @@ namespace Sass { msg << (arg_count == 1 ? " was passed" : " were passed."); deprecated_bind(msg.str(), as->pstate()); - while (arglist->length() > LP - ip) { + while (arglist->length() > LP - ip) + { arglist->elements().erase(arglist->elements().end() - 1); } } } // otherwise move one of the rest args into the param, converting to argument if necessary Expression_Obj obj = arglist->at(0); - if (!(a = Cast(obj))) { + if (!(a = Cast(obj))) + { Expression_Ptr a_to_convert = obj; - a = SASS_MEMORY_NEW(Argument, - a_to_convert->pstate(), - a_to_convert, - "", - false, - false); + a = SASS_MEMORY_NEW(Argument, a_to_convert->pstate(), a_to_convert, "", false, false); } arglist->elements().erase(arglist->elements().begin()); - if (!arglist->length() || (!arglist->is_arglist() && ip + 1 == LP)) { + if (!arglist->length() || (!arglist->is_arglist() && ip + 1 == LP)) + { ++ia; } - - } else if (a->is_keyword_argument()) { + } + else if (a->is_keyword_argument()) + { Map_Obj argmap = Cast(a->value()); - for (auto key : argmap->keys()) { + for (auto key : argmap->keys()) + { std::string param = "$" + unquote(Cast(key)->value()); - if (!param_map.count(param)) { + if (!param_map.count(param)) + { std::stringstream msg; msg << callee << " has no parameter named " << param; error(msg.str(), a->pstate()); @@ -223,38 +232,43 @@ namespace Sass { } ++ia; continue; - } else { + } + else + { ++ia; } - if (a->name().empty()) { - if (env->has_local(p->name())) { + if (a->name().empty()) + { + if (env->has_local(p->name())) + { std::stringstream msg; - msg << "parameter " << p->name() - << " provided more than once in call to " << callee; + msg << "parameter " << p->name() << " provided more than once in call to " << callee; error(msg.str(), a->pstate()); } // ordinal arg -- bind it to the next param env->local_frame()[p->name()] = a->value(); ++ip; } - else { + else + { // named arg -- bind it to the appropriately named param - if (!param_map.count(a->name())) { + if (!param_map.count(a->name())) + { std::stringstream msg; msg << callee << " has no parameter named " << a->name(); error(msg.str(), a->pstate()); } - if (param_map[a->name()]->is_rest_parameter()) { + if (param_map[a->name()]->is_rest_parameter()) + { std::stringstream msg; - msg << "argument " << a->name() << " of " << callee - << "cannot be used as named argument"; + msg << "argument " << a->name() << " of " << callee << "cannot be used as named argument"; error(msg.str(), a->pstate()); } - if (env->has_local(a->name())) { + if (env->has_local(a->name())) + { std::stringstream msg; - msg << "parameter " << p->name() - << "provided more than once in call to " << callee; + msg << "parameter " << p->name() << "provided more than once in call to " << callee; error(msg.str(), a->pstate()); } env->local_frame()[a->name()] = a->value(); @@ -265,24 +279,26 @@ namespace Sass { // If we make it here, we're out of args but may have leftover params. // That's only okay if they have default values, or were already bound by // named arguments, or if it's a single rest-param. - for (size_t i = ip; i < LP; ++i) { + for (size_t i = ip; i < LP; ++i) + { Parameter_Obj leftover = ps->at(i); // cerr << "env for default params:" << endl; // env->print(); // cerr << "********" << endl; - if (!env->has_local(leftover->name())) { - if (leftover->is_rest_parameter()) { - env->local_frame()[leftover->name()] = SASS_MEMORY_NEW(List, - leftover->pstate(), - 0, - SASS_COMMA, - true); + if (!env->has_local(leftover->name())) + { + if (leftover->is_rest_parameter()) + { + env->local_frame()[leftover->name()] = + SASS_MEMORY_NEW(List, leftover->pstate(), 0, SASS_COMMA, true); } - else if (leftover->default_value()) { + else if (leftover->default_value()) + { Expression_Ptr dv = leftover->default_value()->perform(eval); env->local_frame()[leftover->name()] = dv; } - else { + else + { // param is unbound and has no default value -- error throw Exception::MissingArgument(as->pstate(), name, leftover->name(), type); } @@ -291,6 +307,4 @@ namespace Sass { return; } - - } diff --git a/src/bind.hpp b/src/bind.hpp index 93a503aa67..776981440f 100644 --- a/src/bind.hpp +++ b/src/bind.hpp @@ -5,7 +5,8 @@ #include "environment.hpp" #include "ast_fwd_decl.hpp" -namespace Sass { +namespace Sass +{ void bind(std::string type, std::string name, Parameters_Obj, Arguments_Obj, Context*, Env*, Eval*); } diff --git a/src/check_nesting.cpp b/src/check_nesting.cpp index 5d0a8366eb..54264d3a34 100644 --- a/src/check_nesting.cpp +++ b/src/check_nesting.cpp @@ -3,37 +3,42 @@ #include "check_nesting.hpp" -namespace Sass { +namespace Sass +{ CheckNesting::CheckNesting() - : parents(std::vector()), - parent(0), - current_mixin_definition(0) - { } + : parents(std::vector()), parent(0), current_mixin_definition(0) + { + } Statement_Ptr CheckNesting::visit_children(Statement_Ptr parent) { Statement_Ptr old_parent = this->parent; - if (At_Root_Block_Ptr root = Cast(parent)) { + if (At_Root_Block_Ptr root = Cast(parent)) + { std::vector old_parents = this->parents; std::vector new_parents; - for (size_t i = 0, L = this->parents.size(); i < L; i++) { + for (size_t i = 0, L = this->parents.size(); i < L; i++) + { Statement_Ptr p = this->parents.at(i); - if (!root->exclude_node(p)) { + if (!root->exclude_node(p)) + { new_parents.push_back(p); } } this->parents = new_parents; - for (size_t i = this->parents.size(); i > 0; i--) { + for (size_t i = this->parents.size(); i > 0; i--) + { Statement_Ptr p = 0; Statement_Ptr gp = 0; if (i > 0) p = this->parents.at(i - 1); if (i > 1) gp = this->parents.at(i - 2); - if (!this->is_transparent_parent(p, gp)) { + if (!this->is_transparent_parent(p, gp)) + { this->parent = p; break; } @@ -48,7 +53,8 @@ namespace Sass { return ret; } - if (!this->is_transparent_parent(parent, old_parent)) { + if (!this->is_transparent_parent(parent, old_parent)) + { this->parent = parent; } @@ -56,14 +62,18 @@ namespace Sass { Block_Ptr b = Cast(parent); - if (!b) { - if (Has_Block_Ptr bb = Cast(parent)) { + if (!b) + { + if (Has_Block_Ptr bb = Cast(parent)) + { b = bb->block(); } } - if (b) { - for (auto n : b->elements()) { + if (b) + { + for (auto n : b->elements()) + { n->perform(this); } } @@ -82,7 +92,8 @@ namespace Sass { Statement_Ptr CheckNesting::operator()(Definition_Ptr n) { if (!this->should_visit(n)) return NULL; - if (!is_mixin(n)) { + if (!is_mixin(n)) + { visit_children(n); return n; } @@ -109,71 +120,79 @@ namespace Sass { if (!this->parent) return true; if (Cast(node)) - { this->invalid_content_parent(this->parent); } + { + this->invalid_content_parent(this->parent); + } if (is_charset(node)) - { this->invalid_charset_parent(this->parent); } + { + this->invalid_charset_parent(this->parent); + } if (Cast(node)) - { this->invalid_extend_parent(this->parent); } + { + this->invalid_extend_parent(this->parent); + } // if (Cast(node)) // { this->invalid_import_parent(this->parent); } if (this->is_mixin(node)) - { this->invalid_mixin_definition_parent(this->parent); } + { + this->invalid_mixin_definition_parent(this->parent); + } if (this->is_function(node)) - { this->invalid_function_parent(this->parent); } + { + this->invalid_function_parent(this->parent); + } if (this->is_function(this->parent)) - { this->invalid_function_child(node); } + { + this->invalid_function_child(node); + } if (Cast(node)) - { this->invalid_prop_parent(this->parent); } + { + this->invalid_prop_parent(this->parent); + } if (Cast(this->parent)) - { this->invalid_prop_child(node); } + { + this->invalid_prop_child(node); + } if (Cast(node)) - { this->invalid_return_parent(this->parent); } + { + this->invalid_return_parent(this->parent); + } return true; } void CheckNesting::invalid_content_parent(Statement_Ptr parent) { - if (!this->current_mixin_definition) { - throw Exception::InvalidSass( - parent->pstate(), - "@content may only be used within a mixin." - ); + if (!this->current_mixin_definition) + { + throw Exception::InvalidSass(parent->pstate(), "@content may only be used within a mixin."); } } void CheckNesting::invalid_charset_parent(Statement_Ptr parent) { - if (!( - is_root_node(parent) - )) { - throw Exception::InvalidSass( - parent->pstate(), - "@charset may only be used at the root of a document." - ); + if (!(is_root_node(parent))) + { + throw Exception::InvalidSass(parent->pstate(), + "@charset may only be used at the root of a document."); } } void CheckNesting::invalid_extend_parent(Statement_Ptr parent) { - if (!( - Cast(parent) || - Cast(parent) || - is_mixin(parent) - )) { - throw Exception::InvalidSass( - parent->pstate(), - "Extend directives may only be used within rules." - ); + if (!(Cast(parent) || Cast(parent) || is_mixin(parent))) + { + throw Exception::InvalidSass(parent->pstate(), + "Extend directives may only be used within rules."); } } @@ -210,111 +229,68 @@ namespace Sass { void CheckNesting::invalid_mixin_definition_parent(Statement_Ptr parent) { - for (Statement_Ptr pp : this->parents) { - if ( - Cast(pp) || - Cast(pp) || - Cast(pp) || - Cast(pp) || - Cast(pp) || - Cast(pp) || - is_mixin(pp) - ) { - throw Exception::InvalidSass( - parent->pstate(), - "Mixins may not be defined within control directives or other mixins." - ); + for (Statement_Ptr pp : this->parents) + { + if (Cast(pp) || Cast(pp) || Cast(pp) || Cast(pp) || Cast(pp) || + Cast(pp) || is_mixin(pp)) + { + throw Exception::InvalidSass(parent->pstate(), "Mixins may not be defined within control " + "directives or other mixins."); } } } void CheckNesting::invalid_function_parent(Statement_Ptr parent) { - for (Statement_Ptr pp : this->parents) { - if ( - Cast(pp) || - Cast(pp) || - Cast(pp) || - Cast(pp) || - Cast(pp) || - Cast(pp) || - is_mixin(pp) - ) { - throw Exception::InvalidSass( - parent->pstate(), - "Functions may not be defined within control directives or other mixins." - ); + for (Statement_Ptr pp : this->parents) + { + if (Cast(pp) || Cast(pp) || Cast(pp) || Cast(pp) || Cast(pp) || + Cast(pp) || is_mixin(pp)) + { + throw Exception::InvalidSass(parent->pstate(), "Functions may not be defined within " + "control directives or other mixins."); } } } void CheckNesting::invalid_function_child(Statement_Ptr child) { - if (!( - Cast(child) || - Cast(child) || - Cast(child) || - Cast(child) || - Cast(child) || - Cast(child) || - Cast(child) || - Cast(child) || - Cast(child) || - // Ruby Sass doesn't distinguish variables and assignments - Cast(child) || - Cast(child) || - Cast(child) - )) { - throw Exception::InvalidSass( - child->pstate(), - "Functions can only contain variable declarations and control directives." - ); + if (!(Cast(child) || Cast(child) || Cast(child) || Cast(child) || Cast(child) || + Cast(child) || Cast(child) || Cast(child) || Cast(child) || + // Ruby Sass doesn't distinguish variables and assignments + Cast(child) || Cast(child) || Cast(child))) + { + throw Exception::InvalidSass(child->pstate(), "Functions can only contain variable " + "declarations and control directives."); } } void CheckNesting::invalid_prop_child(Statement_Ptr child) { - if (!( - Cast(child) || - Cast(child) || - Cast(child) || - Cast(child) || - Cast(child) || - Cast(child) || - Cast(child) || - Cast(child) - )) { - throw Exception::InvalidSass( - child->pstate(), - "Illegal nesting: Only properties may be nested beneath properties." - ); + if (!(Cast(child) || Cast(child) || Cast(child) || Cast(child) || + Cast(child) || Cast(child) || Cast(child) || Cast(child))) + { + throw Exception::InvalidSass(child->pstate(), "Illegal nesting: Only properties may be " + "nested beneath properties."); } } void CheckNesting::invalid_prop_parent(Statement_Ptr parent) { - if (!( - is_mixin(parent) || - is_directive_node(parent) || - Cast(parent) || - Cast(parent) || - Cast(parent) || - Cast(parent) - )) { - throw Exception::InvalidSass( - parent->pstate(), - "Properties are only allowed within rules, directives, mixin includes, or other properties." - ); + if (!(is_mixin(parent) || is_directive_node(parent) || Cast(parent) || + Cast(parent) || Cast(parent) || Cast(parent))) + { + throw Exception::InvalidSass(parent->pstate(), "Properties are only allowed within rules, " + "directives, mixin includes, or other " + "properties."); } } void CheckNesting::invalid_return_parent(Statement_Ptr parent) { - if (!this->is_function(parent)) { - throw Exception::InvalidSass( - parent->pstate(), - "@return may only be used within a function." - ); + if (!this->is_function(parent)) + { + throw Exception::InvalidSass(parent->pstate(), "@return may only be used within a function."); } } @@ -322,17 +298,10 @@ namespace Sass { { bool parent_bubbles = parent && parent->bubbles(); - bool valid_bubble_node = parent_bubbles && - !is_root_node(grandparent) && - !is_at_root_node(grandparent); - - return Cast(parent) || - Cast(parent) || - Cast(parent) || - Cast(parent) || - Cast(parent) || - Cast(parent) || - valid_bubble_node; + bool valid_bubble_node = parent_bubbles && !is_root_node(grandparent) && !is_at_root_node(grandparent); + + return Cast(parent) || Cast(parent) || Cast(parent) || Cast(parent) || + Cast(parent) || Cast(parent) || valid_bubble_node; } bool CheckNesting::is_charset(Statement_Ptr n) @@ -368,9 +337,6 @@ namespace Sass { bool CheckNesting::is_directive_node(Statement_Ptr n) { - return Cast(n) || - Cast(n) || - Cast(n) || - Cast(n); + return Cast(n) || Cast(n) || Cast(n) || Cast(n); } } diff --git a/src/check_nesting.hpp b/src/check_nesting.hpp index ec9ee2ae00..a65c804dc1 100644 --- a/src/check_nesting.hpp +++ b/src/check_nesting.hpp @@ -4,35 +4,40 @@ #include "ast.hpp" #include "operation.hpp" -namespace Sass { +namespace Sass +{ - class CheckNesting : public Operation_CRTP { + class CheckNesting : public Operation_CRTP + { - std::vector parents; - Statement_Ptr parent; - Definition_Ptr current_mixin_definition; + std::vector parents; + Statement_Ptr parent; + Definition_Ptr current_mixin_definition; Statement_Ptr fallback_impl(Statement_Ptr); Statement_Ptr before(Statement_Ptr); Statement_Ptr visit_children(Statement_Ptr); - public: + public: CheckNesting(); - ~CheckNesting() { } + ~CheckNesting() + { + } Statement_Ptr operator()(Block_Ptr); Statement_Ptr operator()(Definition_Ptr); - template - Statement_Ptr fallback(U x) { + template Statement_Ptr fallback(U x) + { Statement_Ptr n = Cast(x); - if (this->should_visit(n)) { + if (this->should_visit(n)) + { return fallback_impl(n); } return NULL; } - private: + private: void invalid_content_parent(Statement_Ptr); void invalid_charset_parent(Statement_Ptr); void invalid_extend_parent(Statement_Ptr); @@ -56,7 +61,6 @@ namespace Sass { bool is_at_root_node(Statement_Ptr); bool is_directive_node(Statement_Ptr); }; - } #endif diff --git a/src/color_maps.cpp b/src/color_maps.cpp index f21e9e029d..ba96280a50 100644 --- a/src/color_maps.cpp +++ b/src/color_maps.cpp @@ -2,162 +2,164 @@ #include "ast.hpp" #include "color_maps.hpp" -namespace Sass { +namespace Sass +{ namespace ColorNames { - const char aliceblue [] = "aliceblue"; - const char antiquewhite [] = "antiquewhite"; - const char cyan [] = "cyan"; - const char aqua [] = "aqua"; - const char aquamarine [] = "aquamarine"; - const char azure [] = "azure"; - const char beige [] = "beige"; - const char bisque [] = "bisque"; - const char black [] = "black"; - const char blanchedalmond [] = "blanchedalmond"; - const char blue [] = "blue"; - const char blueviolet [] = "blueviolet"; - const char brown [] = "brown"; - const char burlywood [] = "burlywood"; - const char cadetblue [] = "cadetblue"; - const char chartreuse [] = "chartreuse"; - const char chocolate [] = "chocolate"; - const char coral [] = "coral"; - const char cornflowerblue [] = "cornflowerblue"; - const char cornsilk [] = "cornsilk"; - const char crimson [] = "crimson"; - const char darkblue [] = "darkblue"; - const char darkcyan [] = "darkcyan"; - const char darkgoldenrod [] = "darkgoldenrod"; - const char darkgray [] = "darkgray"; - const char darkgrey [] = "darkgrey"; - const char darkgreen [] = "darkgreen"; - const char darkkhaki [] = "darkkhaki"; - const char darkmagenta [] = "darkmagenta"; - const char darkolivegreen [] = "darkolivegreen"; - const char darkorange [] = "darkorange"; - const char darkorchid [] = "darkorchid"; - const char darkred [] = "darkred"; - const char darksalmon [] = "darksalmon"; - const char darkseagreen [] = "darkseagreen"; - const char darkslateblue [] = "darkslateblue"; - const char darkslategray [] = "darkslategray"; - const char darkslategrey [] = "darkslategrey"; - const char darkturquoise [] = "darkturquoise"; - const char darkviolet [] = "darkviolet"; - const char deeppink [] = "deeppink"; - const char deepskyblue [] = "deepskyblue"; - const char dimgray [] = "dimgray"; - const char dimgrey [] = "dimgrey"; - const char dodgerblue [] = "dodgerblue"; - const char firebrick [] = "firebrick"; - const char floralwhite [] = "floralwhite"; - const char forestgreen [] = "forestgreen"; - const char magenta [] = "magenta"; - const char fuchsia [] = "fuchsia"; - const char gainsboro [] = "gainsboro"; - const char ghostwhite [] = "ghostwhite"; - const char gold [] = "gold"; - const char goldenrod [] = "goldenrod"; - const char gray [] = "gray"; - const char grey [] = "grey"; - const char green [] = "green"; - const char greenyellow [] = "greenyellow"; - const char honeydew [] = "honeydew"; - const char hotpink [] = "hotpink"; - const char indianred [] = "indianred"; - const char indigo [] = "indigo"; - const char ivory [] = "ivory"; - const char khaki [] = "khaki"; - const char lavender [] = "lavender"; - const char lavenderblush [] = "lavenderblush"; - const char lawngreen [] = "lawngreen"; - const char lemonchiffon [] = "lemonchiffon"; - const char lightblue [] = "lightblue"; - const char lightcoral [] = "lightcoral"; - const char lightcyan [] = "lightcyan"; - const char lightgoldenrodyellow [] = "lightgoldenrodyellow"; - const char lightgray [] = "lightgray"; - const char lightgrey [] = "lightgrey"; - const char lightgreen [] = "lightgreen"; - const char lightpink [] = "lightpink"; - const char lightsalmon [] = "lightsalmon"; - const char lightseagreen [] = "lightseagreen"; - const char lightskyblue [] = "lightskyblue"; - const char lightslategray [] = "lightslategray"; - const char lightslategrey [] = "lightslategrey"; - const char lightsteelblue [] = "lightsteelblue"; - const char lightyellow [] = "lightyellow"; - const char lime [] = "lime"; - const char limegreen [] = "limegreen"; - const char linen [] = "linen"; - const char maroon [] = "maroon"; - const char mediumaquamarine [] = "mediumaquamarine"; - const char mediumblue [] = "mediumblue"; - const char mediumorchid [] = "mediumorchid"; - const char mediumpurple [] = "mediumpurple"; - const char mediumseagreen [] = "mediumseagreen"; - const char mediumslateblue [] = "mediumslateblue"; - const char mediumspringgreen [] = "mediumspringgreen"; - const char mediumturquoise [] = "mediumturquoise"; - const char mediumvioletred [] = "mediumvioletred"; - const char midnightblue [] = "midnightblue"; - const char mintcream [] = "mintcream"; - const char mistyrose [] = "mistyrose"; - const char moccasin [] = "moccasin"; - const char navajowhite [] = "navajowhite"; - const char navy [] = "navy"; - const char oldlace [] = "oldlace"; - const char olive [] = "olive"; - const char olivedrab [] = "olivedrab"; - const char orange [] = "orange"; - const char orangered [] = "orangered"; - const char orchid [] = "orchid"; - const char palegoldenrod [] = "palegoldenrod"; - const char palegreen [] = "palegreen"; - const char paleturquoise [] = "paleturquoise"; - const char palevioletred [] = "palevioletred"; - const char papayawhip [] = "papayawhip"; - const char peachpuff [] = "peachpuff"; - const char peru [] = "peru"; - const char pink [] = "pink"; - const char plum [] = "plum"; - const char powderblue [] = "powderblue"; - const char purple [] = "purple"; - const char red [] = "red"; - const char rosybrown [] = "rosybrown"; - const char royalblue [] = "royalblue"; - const char saddlebrown [] = "saddlebrown"; - const char salmon [] = "salmon"; - const char sandybrown [] = "sandybrown"; - const char seagreen [] = "seagreen"; - const char seashell [] = "seashell"; - const char sienna [] = "sienna"; - const char silver [] = "silver"; - const char skyblue [] = "skyblue"; - const char slateblue [] = "slateblue"; - const char slategray [] = "slategray"; - const char slategrey [] = "slategrey"; - const char snow [] = "snow"; - const char springgreen [] = "springgreen"; - const char steelblue [] = "steelblue"; - const char tan [] = "tan"; - const char teal [] = "teal"; - const char thistle [] = "thistle"; - const char tomato [] = "tomato"; - const char turquoise [] = "turquoise"; - const char violet [] = "violet"; - const char wheat [] = "wheat"; - const char white [] = "white"; - const char whitesmoke [] = "whitesmoke"; - const char yellow [] = "yellow"; - const char yellowgreen [] = "yellowgreen"; - const char rebeccapurple [] = "rebeccapurple"; - const char transparent [] = "transparent"; + const char aliceblue[] = "aliceblue"; + const char antiquewhite[] = "antiquewhite"; + const char cyan[] = "cyan"; + const char aqua[] = "aqua"; + const char aquamarine[] = "aquamarine"; + const char azure[] = "azure"; + const char beige[] = "beige"; + const char bisque[] = "bisque"; + const char black[] = "black"; + const char blanchedalmond[] = "blanchedalmond"; + const char blue[] = "blue"; + const char blueviolet[] = "blueviolet"; + const char brown[] = "brown"; + const char burlywood[] = "burlywood"; + const char cadetblue[] = "cadetblue"; + const char chartreuse[] = "chartreuse"; + const char chocolate[] = "chocolate"; + const char coral[] = "coral"; + const char cornflowerblue[] = "cornflowerblue"; + const char cornsilk[] = "cornsilk"; + const char crimson[] = "crimson"; + const char darkblue[] = "darkblue"; + const char darkcyan[] = "darkcyan"; + const char darkgoldenrod[] = "darkgoldenrod"; + const char darkgray[] = "darkgray"; + const char darkgrey[] = "darkgrey"; + const char darkgreen[] = "darkgreen"; + const char darkkhaki[] = "darkkhaki"; + const char darkmagenta[] = "darkmagenta"; + const char darkolivegreen[] = "darkolivegreen"; + const char darkorange[] = "darkorange"; + const char darkorchid[] = "darkorchid"; + const char darkred[] = "darkred"; + const char darksalmon[] = "darksalmon"; + const char darkseagreen[] = "darkseagreen"; + const char darkslateblue[] = "darkslateblue"; + const char darkslategray[] = "darkslategray"; + const char darkslategrey[] = "darkslategrey"; + const char darkturquoise[] = "darkturquoise"; + const char darkviolet[] = "darkviolet"; + const char deeppink[] = "deeppink"; + const char deepskyblue[] = "deepskyblue"; + const char dimgray[] = "dimgray"; + const char dimgrey[] = "dimgrey"; + const char dodgerblue[] = "dodgerblue"; + const char firebrick[] = "firebrick"; + const char floralwhite[] = "floralwhite"; + const char forestgreen[] = "forestgreen"; + const char magenta[] = "magenta"; + const char fuchsia[] = "fuchsia"; + const char gainsboro[] = "gainsboro"; + const char ghostwhite[] = "ghostwhite"; + const char gold[] = "gold"; + const char goldenrod[] = "goldenrod"; + const char gray[] = "gray"; + const char grey[] = "grey"; + const char green[] = "green"; + const char greenyellow[] = "greenyellow"; + const char honeydew[] = "honeydew"; + const char hotpink[] = "hotpink"; + const char indianred[] = "indianred"; + const char indigo[] = "indigo"; + const char ivory[] = "ivory"; + const char khaki[] = "khaki"; + const char lavender[] = "lavender"; + const char lavenderblush[] = "lavenderblush"; + const char lawngreen[] = "lawngreen"; + const char lemonchiffon[] = "lemonchiffon"; + const char lightblue[] = "lightblue"; + const char lightcoral[] = "lightcoral"; + const char lightcyan[] = "lightcyan"; + const char lightgoldenrodyellow[] = "lightgoldenrodyellow"; + const char lightgray[] = "lightgray"; + const char lightgrey[] = "lightgrey"; + const char lightgreen[] = "lightgreen"; + const char lightpink[] = "lightpink"; + const char lightsalmon[] = "lightsalmon"; + const char lightseagreen[] = "lightseagreen"; + const char lightskyblue[] = "lightskyblue"; + const char lightslategray[] = "lightslategray"; + const char lightslategrey[] = "lightslategrey"; + const char lightsteelblue[] = "lightsteelblue"; + const char lightyellow[] = "lightyellow"; + const char lime[] = "lime"; + const char limegreen[] = "limegreen"; + const char linen[] = "linen"; + const char maroon[] = "maroon"; + const char mediumaquamarine[] = "mediumaquamarine"; + const char mediumblue[] = "mediumblue"; + const char mediumorchid[] = "mediumorchid"; + const char mediumpurple[] = "mediumpurple"; + const char mediumseagreen[] = "mediumseagreen"; + const char mediumslateblue[] = "mediumslateblue"; + const char mediumspringgreen[] = "mediumspringgreen"; + const char mediumturquoise[] = "mediumturquoise"; + const char mediumvioletred[] = "mediumvioletred"; + const char midnightblue[] = "midnightblue"; + const char mintcream[] = "mintcream"; + const char mistyrose[] = "mistyrose"; + const char moccasin[] = "moccasin"; + const char navajowhite[] = "navajowhite"; + const char navy[] = "navy"; + const char oldlace[] = "oldlace"; + const char olive[] = "olive"; + const char olivedrab[] = "olivedrab"; + const char orange[] = "orange"; + const char orangered[] = "orangered"; + const char orchid[] = "orchid"; + const char palegoldenrod[] = "palegoldenrod"; + const char palegreen[] = "palegreen"; + const char paleturquoise[] = "paleturquoise"; + const char palevioletred[] = "palevioletred"; + const char papayawhip[] = "papayawhip"; + const char peachpuff[] = "peachpuff"; + const char peru[] = "peru"; + const char pink[] = "pink"; + const char plum[] = "plum"; + const char powderblue[] = "powderblue"; + const char purple[] = "purple"; + const char red[] = "red"; + const char rosybrown[] = "rosybrown"; + const char royalblue[] = "royalblue"; + const char saddlebrown[] = "saddlebrown"; + const char salmon[] = "salmon"; + const char sandybrown[] = "sandybrown"; + const char seagreen[] = "seagreen"; + const char seashell[] = "seashell"; + const char sienna[] = "sienna"; + const char silver[] = "silver"; + const char skyblue[] = "skyblue"; + const char slateblue[] = "slateblue"; + const char slategray[] = "slategray"; + const char slategrey[] = "slategrey"; + const char snow[] = "snow"; + const char springgreen[] = "springgreen"; + const char steelblue[] = "steelblue"; + const char tan[] = "tan"; + const char teal[] = "teal"; + const char thistle[] = "thistle"; + const char tomato[] = "tomato"; + const char turquoise[] = "turquoise"; + const char violet[] = "violet"; + const char wheat[] = "wheat"; + const char white[] = "white"; + const char whitesmoke[] = "whitesmoke"; + const char yellow[] = "yellow"; + const char yellowgreen[] = "yellowgreen"; + const char rebeccapurple[] = "rebeccapurple"; + const char transparent[] = "transparent"; } - namespace Colors { + namespace Colors + { const ParserState color_table("[COLOR TABLE]"); const Color aliceblue(color_table, 240, 248, 255, 1); const Color antiquewhite(color_table, 250, 235, 215, 1); @@ -310,68 +312,68 @@ namespace Sass { const Color transparent(color_table, 0, 0, 0, 0); } - const std::map colors_to_names { + const std::map colors_to_names{ { 240 * 0x10000 + 248 * 0x100 + 255, ColorNames::aliceblue }, { 250 * 0x10000 + 235 * 0x100 + 215, ColorNames::antiquewhite }, - { 0 * 0x10000 + 255 * 0x100 + 255, ColorNames::cyan }, + { 0 * 0x10000 + 255 * 0x100 + 255, ColorNames::cyan }, { 127 * 0x10000 + 255 * 0x100 + 212, ColorNames::aquamarine }, { 240 * 0x10000 + 255 * 0x100 + 255, ColorNames::azure }, { 245 * 0x10000 + 245 * 0x100 + 220, ColorNames::beige }, { 255 * 0x10000 + 228 * 0x100 + 196, ColorNames::bisque }, - { 0 * 0x10000 + 0 * 0x100 + 0, ColorNames::black }, + { 0 * 0x10000 + 0 * 0x100 + 0, ColorNames::black }, { 255 * 0x10000 + 235 * 0x100 + 205, ColorNames::blanchedalmond }, - { 0 * 0x10000 + 0 * 0x100 + 255, ColorNames::blue }, - { 138 * 0x10000 + 43 * 0x100 + 226, ColorNames::blueviolet }, - { 165 * 0x10000 + 42 * 0x100 + 42, ColorNames::brown }, + { 0 * 0x10000 + 0 * 0x100 + 255, ColorNames::blue }, + { 138 * 0x10000 + 43 * 0x100 + 226, ColorNames::blueviolet }, + { 165 * 0x10000 + 42 * 0x100 + 42, ColorNames::brown }, { 222 * 0x10000 + 184 * 0x100 + 135, ColorNames::burlywood }, - { 95 * 0x10000 + 158 * 0x100 + 160, ColorNames::cadetblue }, - { 127 * 0x10000 + 255 * 0x100 + 0, ColorNames::chartreuse }, - { 210 * 0x10000 + 105 * 0x100 + 30, ColorNames::chocolate }, - { 255 * 0x10000 + 127 * 0x100 + 80, ColorNames::coral }, + { 95 * 0x10000 + 158 * 0x100 + 160, ColorNames::cadetblue }, + { 127 * 0x10000 + 255 * 0x100 + 0, ColorNames::chartreuse }, + { 210 * 0x10000 + 105 * 0x100 + 30, ColorNames::chocolate }, + { 255 * 0x10000 + 127 * 0x100 + 80, ColorNames::coral }, { 100 * 0x10000 + 149 * 0x100 + 237, ColorNames::cornflowerblue }, { 255 * 0x10000 + 248 * 0x100 + 220, ColorNames::cornsilk }, - { 220 * 0x10000 + 20 * 0x100 + 60, ColorNames::crimson }, - { 0 * 0x10000 + 0 * 0x100 + 139, ColorNames::darkblue }, - { 0 * 0x10000 + 139 * 0x100 + 139, ColorNames::darkcyan }, - { 184 * 0x10000 + 134 * 0x100 + 11, ColorNames::darkgoldenrod }, + { 220 * 0x10000 + 20 * 0x100 + 60, ColorNames::crimson }, + { 0 * 0x10000 + 0 * 0x100 + 139, ColorNames::darkblue }, + { 0 * 0x10000 + 139 * 0x100 + 139, ColorNames::darkcyan }, + { 184 * 0x10000 + 134 * 0x100 + 11, ColorNames::darkgoldenrod }, { 169 * 0x10000 + 169 * 0x100 + 169, ColorNames::darkgray }, - { 0 * 0x10000 + 100 * 0x100 + 0, ColorNames::darkgreen }, + { 0 * 0x10000 + 100 * 0x100 + 0, ColorNames::darkgreen }, { 189 * 0x10000 + 183 * 0x100 + 107, ColorNames::darkkhaki }, - { 139 * 0x10000 + 0 * 0x100 + 139, ColorNames::darkmagenta }, - { 85 * 0x10000 + 107 * 0x100 + 47, ColorNames::darkolivegreen }, - { 255 * 0x10000 + 140 * 0x100 + 0, ColorNames::darkorange }, - { 153 * 0x10000 + 50 * 0x100 + 204, ColorNames::darkorchid }, - { 139 * 0x10000 + 0 * 0x100 + 0, ColorNames::darkred }, + { 139 * 0x10000 + 0 * 0x100 + 139, ColorNames::darkmagenta }, + { 85 * 0x10000 + 107 * 0x100 + 47, ColorNames::darkolivegreen }, + { 255 * 0x10000 + 140 * 0x100 + 0, ColorNames::darkorange }, + { 153 * 0x10000 + 50 * 0x100 + 204, ColorNames::darkorchid }, + { 139 * 0x10000 + 0 * 0x100 + 0, ColorNames::darkred }, { 233 * 0x10000 + 150 * 0x100 + 122, ColorNames::darksalmon }, { 143 * 0x10000 + 188 * 0x100 + 143, ColorNames::darkseagreen }, - { 72 * 0x10000 + 61 * 0x100 + 139, ColorNames::darkslateblue }, - { 47 * 0x10000 + 79 * 0x100 + 79, ColorNames::darkslategray }, - { 0 * 0x10000 + 206 * 0x100 + 209, ColorNames::darkturquoise }, - { 148 * 0x10000 + 0 * 0x100 + 211, ColorNames::darkviolet }, - { 255 * 0x10000 + 20 * 0x100 + 147, ColorNames::deeppink }, - { 0 * 0x10000 + 191 * 0x100 + 255, ColorNames::deepskyblue }, + { 72 * 0x10000 + 61 * 0x100 + 139, ColorNames::darkslateblue }, + { 47 * 0x10000 + 79 * 0x100 + 79, ColorNames::darkslategray }, + { 0 * 0x10000 + 206 * 0x100 + 209, ColorNames::darkturquoise }, + { 148 * 0x10000 + 0 * 0x100 + 211, ColorNames::darkviolet }, + { 255 * 0x10000 + 20 * 0x100 + 147, ColorNames::deeppink }, + { 0 * 0x10000 + 191 * 0x100 + 255, ColorNames::deepskyblue }, { 105 * 0x10000 + 105 * 0x100 + 105, ColorNames::dimgray }, - { 30 * 0x10000 + 144 * 0x100 + 255, ColorNames::dodgerblue }, - { 178 * 0x10000 + 34 * 0x100 + 34, ColorNames::firebrick }, + { 30 * 0x10000 + 144 * 0x100 + 255, ColorNames::dodgerblue }, + { 178 * 0x10000 + 34 * 0x100 + 34, ColorNames::firebrick }, { 255 * 0x10000 + 250 * 0x100 + 240, ColorNames::floralwhite }, - { 34 * 0x10000 + 139 * 0x100 + 34, ColorNames::forestgreen }, - { 255 * 0x10000 + 0 * 0x100 + 255, ColorNames::magenta }, + { 34 * 0x10000 + 139 * 0x100 + 34, ColorNames::forestgreen }, + { 255 * 0x10000 + 0 * 0x100 + 255, ColorNames::magenta }, { 220 * 0x10000 + 220 * 0x100 + 220, ColorNames::gainsboro }, { 248 * 0x10000 + 248 * 0x100 + 255, ColorNames::ghostwhite }, - { 255 * 0x10000 + 215 * 0x100 + 0, ColorNames::gold }, - { 218 * 0x10000 + 165 * 0x100 + 32, ColorNames::goldenrod }, + { 255 * 0x10000 + 215 * 0x100 + 0, ColorNames::gold }, + { 218 * 0x10000 + 165 * 0x100 + 32, ColorNames::goldenrod }, { 128 * 0x10000 + 128 * 0x100 + 128, ColorNames::gray }, - { 0 * 0x10000 + 128 * 0x100 + 0, ColorNames::green }, - { 173 * 0x10000 + 255 * 0x100 + 47, ColorNames::greenyellow }, + { 0 * 0x10000 + 128 * 0x100 + 0, ColorNames::green }, + { 173 * 0x10000 + 255 * 0x100 + 47, ColorNames::greenyellow }, { 240 * 0x10000 + 255 * 0x100 + 240, ColorNames::honeydew }, { 255 * 0x10000 + 105 * 0x100 + 180, ColorNames::hotpink }, - { 205 * 0x10000 + 92 * 0x100 + 92, ColorNames::indianred }, - { 75 * 0x10000 + 0 * 0x100 + 130, ColorNames::indigo }, + { 205 * 0x10000 + 92 * 0x100 + 92, ColorNames::indianred }, + { 75 * 0x10000 + 0 * 0x100 + 130, ColorNames::indigo }, { 255 * 0x10000 + 255 * 0x100 + 240, ColorNames::ivory }, { 240 * 0x10000 + 230 * 0x100 + 140, ColorNames::khaki }, { 230 * 0x10000 + 230 * 0x100 + 250, ColorNames::lavender }, { 255 * 0x10000 + 240 * 0x100 + 245, ColorNames::lavenderblush }, - { 124 * 0x10000 + 252 * 0x100 + 0, ColorNames::lawngreen }, + { 124 * 0x10000 + 252 * 0x100 + 0, ColorNames::lawngreen }, { 255 * 0x10000 + 250 * 0x100 + 205, ColorNames::lemonchiffon }, { 173 * 0x10000 + 216 * 0x100 + 230, ColorNames::lightblue }, { 240 * 0x10000 + 128 * 0x100 + 128, ColorNames::lightcoral }, @@ -381,35 +383,35 @@ namespace Sass { { 144 * 0x10000 + 238 * 0x100 + 144, ColorNames::lightgreen }, { 255 * 0x10000 + 182 * 0x100 + 193, ColorNames::lightpink }, { 255 * 0x10000 + 160 * 0x100 + 122, ColorNames::lightsalmon }, - { 32 * 0x10000 + 178 * 0x100 + 170, ColorNames::lightseagreen }, + { 32 * 0x10000 + 178 * 0x100 + 170, ColorNames::lightseagreen }, { 135 * 0x10000 + 206 * 0x100 + 250, ColorNames::lightskyblue }, { 119 * 0x10000 + 136 * 0x100 + 153, ColorNames::lightslategray }, { 176 * 0x10000 + 196 * 0x100 + 222, ColorNames::lightsteelblue }, { 255 * 0x10000 + 255 * 0x100 + 224, ColorNames::lightyellow }, - { 0 * 0x10000 + 255 * 0x100 + 0, ColorNames::lime }, - { 50 * 0x10000 + 205 * 0x100 + 50, ColorNames::limegreen }, + { 0 * 0x10000 + 255 * 0x100 + 0, ColorNames::lime }, + { 50 * 0x10000 + 205 * 0x100 + 50, ColorNames::limegreen }, { 250 * 0x10000 + 240 * 0x100 + 230, ColorNames::linen }, - { 128 * 0x10000 + 0 * 0x100 + 0, ColorNames::maroon }, + { 128 * 0x10000 + 0 * 0x100 + 0, ColorNames::maroon }, { 102 * 0x10000 + 205 * 0x100 + 170, ColorNames::mediumaquamarine }, - { 0 * 0x10000 + 0 * 0x100 + 205, ColorNames::mediumblue }, - { 186 * 0x10000 + 85 * 0x100 + 211, ColorNames::mediumorchid }, + { 0 * 0x10000 + 0 * 0x100 + 205, ColorNames::mediumblue }, + { 186 * 0x10000 + 85 * 0x100 + 211, ColorNames::mediumorchid }, { 147 * 0x10000 + 112 * 0x100 + 219, ColorNames::mediumpurple }, - { 60 * 0x10000 + 179 * 0x100 + 113, ColorNames::mediumseagreen }, + { 60 * 0x10000 + 179 * 0x100 + 113, ColorNames::mediumseagreen }, { 123 * 0x10000 + 104 * 0x100 + 238, ColorNames::mediumslateblue }, - { 0 * 0x10000 + 250 * 0x100 + 154, ColorNames::mediumspringgreen }, - { 72 * 0x10000 + 209 * 0x100 + 204, ColorNames::mediumturquoise }, - { 199 * 0x10000 + 21 * 0x100 + 133, ColorNames::mediumvioletred }, - { 25 * 0x10000 + 25 * 0x100 + 112, ColorNames::midnightblue }, + { 0 * 0x10000 + 250 * 0x100 + 154, ColorNames::mediumspringgreen }, + { 72 * 0x10000 + 209 * 0x100 + 204, ColorNames::mediumturquoise }, + { 199 * 0x10000 + 21 * 0x100 + 133, ColorNames::mediumvioletred }, + { 25 * 0x10000 + 25 * 0x100 + 112, ColorNames::midnightblue }, { 245 * 0x10000 + 255 * 0x100 + 250, ColorNames::mintcream }, { 255 * 0x10000 + 228 * 0x100 + 225, ColorNames::mistyrose }, { 255 * 0x10000 + 228 * 0x100 + 181, ColorNames::moccasin }, { 255 * 0x10000 + 222 * 0x100 + 173, ColorNames::navajowhite }, - { 0 * 0x10000 + 0 * 0x100 + 128, ColorNames::navy }, + { 0 * 0x10000 + 0 * 0x100 + 128, ColorNames::navy }, { 253 * 0x10000 + 245 * 0x100 + 230, ColorNames::oldlace }, - { 128 * 0x10000 + 128 * 0x100 + 0, ColorNames::olive }, - { 107 * 0x10000 + 142 * 0x100 + 35, ColorNames::olivedrab }, - { 255 * 0x10000 + 165 * 0x100 + 0, ColorNames::orange }, - { 255 * 0x10000 + 69 * 0x100 + 0, ColorNames::orangered }, + { 128 * 0x10000 + 128 * 0x100 + 0, ColorNames::olive }, + { 107 * 0x10000 + 142 * 0x100 + 35, ColorNames::olivedrab }, + { 255 * 0x10000 + 165 * 0x100 + 0, ColorNames::orange }, + { 255 * 0x10000 + 69 * 0x100 + 0, ColorNames::orangered }, { 218 * 0x10000 + 112 * 0x100 + 214, ColorNames::orchid }, { 238 * 0x10000 + 232 * 0x100 + 170, ColorNames::palegoldenrod }, { 152 * 0x10000 + 251 * 0x100 + 152, ColorNames::palegreen }, @@ -417,43 +419,42 @@ namespace Sass { { 219 * 0x10000 + 112 * 0x100 + 147, ColorNames::palevioletred }, { 255 * 0x10000 + 239 * 0x100 + 213, ColorNames::papayawhip }, { 255 * 0x10000 + 218 * 0x100 + 185, ColorNames::peachpuff }, - { 205 * 0x10000 + 133 * 0x100 + 63, ColorNames::peru }, + { 205 * 0x10000 + 133 * 0x100 + 63, ColorNames::peru }, { 255 * 0x10000 + 192 * 0x100 + 203, ColorNames::pink }, { 221 * 0x10000 + 160 * 0x100 + 221, ColorNames::plum }, { 176 * 0x10000 + 224 * 0x100 + 230, ColorNames::powderblue }, - { 128 * 0x10000 + 0 * 0x100 + 128, ColorNames::purple }, - { 255 * 0x10000 + 0 * 0x100 + 0, ColorNames::red }, + { 128 * 0x10000 + 0 * 0x100 + 128, ColorNames::purple }, + { 255 * 0x10000 + 0 * 0x100 + 0, ColorNames::red }, { 188 * 0x10000 + 143 * 0x100 + 143, ColorNames::rosybrown }, - { 65 * 0x10000 + 105 * 0x100 + 225, ColorNames::royalblue }, - { 139 * 0x10000 + 69 * 0x100 + 19, ColorNames::saddlebrown }, + { 65 * 0x10000 + 105 * 0x100 + 225, ColorNames::royalblue }, + { 139 * 0x10000 + 69 * 0x100 + 19, ColorNames::saddlebrown }, { 250 * 0x10000 + 128 * 0x100 + 114, ColorNames::salmon }, - { 244 * 0x10000 + 164 * 0x100 + 96, ColorNames::sandybrown }, - { 46 * 0x10000 + 139 * 0x100 + 87, ColorNames::seagreen }, + { 244 * 0x10000 + 164 * 0x100 + 96, ColorNames::sandybrown }, + { 46 * 0x10000 + 139 * 0x100 + 87, ColorNames::seagreen }, { 255 * 0x10000 + 245 * 0x100 + 238, ColorNames::seashell }, - { 160 * 0x10000 + 82 * 0x100 + 45, ColorNames::sienna }, + { 160 * 0x10000 + 82 * 0x100 + 45, ColorNames::sienna }, { 192 * 0x10000 + 192 * 0x100 + 192, ColorNames::silver }, { 135 * 0x10000 + 206 * 0x100 + 235, ColorNames::skyblue }, - { 106 * 0x10000 + 90 * 0x100 + 205, ColorNames::slateblue }, + { 106 * 0x10000 + 90 * 0x100 + 205, ColorNames::slateblue }, { 112 * 0x10000 + 128 * 0x100 + 144, ColorNames::slategray }, { 255 * 0x10000 + 250 * 0x100 + 250, ColorNames::snow }, - { 0 * 0x10000 + 255 * 0x100 + 127, ColorNames::springgreen }, - { 70 * 0x10000 + 130 * 0x100 + 180, ColorNames::steelblue }, + { 0 * 0x10000 + 255 * 0x100 + 127, ColorNames::springgreen }, + { 70 * 0x10000 + 130 * 0x100 + 180, ColorNames::steelblue }, { 210 * 0x10000 + 180 * 0x100 + 140, ColorNames::tan }, - { 0 * 0x10000 + 128 * 0x100 + 128, ColorNames::teal }, + { 0 * 0x10000 + 128 * 0x100 + 128, ColorNames::teal }, { 216 * 0x10000 + 191 * 0x100 + 216, ColorNames::thistle }, - { 255 * 0x10000 + 99 * 0x100 + 71, ColorNames::tomato }, - { 64 * 0x10000 + 224 * 0x100 + 208, ColorNames::turquoise }, + { 255 * 0x10000 + 99 * 0x100 + 71, ColorNames::tomato }, + { 64 * 0x10000 + 224 * 0x100 + 208, ColorNames::turquoise }, { 238 * 0x10000 + 130 * 0x100 + 238, ColorNames::violet }, { 245 * 0x10000 + 222 * 0x100 + 179, ColorNames::wheat }, { 255 * 0x10000 + 255 * 0x100 + 255, ColorNames::white }, { 245 * 0x10000 + 245 * 0x100 + 245, ColorNames::whitesmoke }, - { 255 * 0x10000 + 255 * 0x100 + 0, ColorNames::yellow }, - { 154 * 0x10000 + 205 * 0x100 + 50, ColorNames::yellowgreen }, - { 102 * 0x10000 + 51 * 0x100 + 153, ColorNames::rebeccapurple } + { 255 * 0x10000 + 255 * 0x100 + 0, ColorNames::yellow }, + { 154 * 0x10000 + 205 * 0x100 + 50, ColorNames::yellowgreen }, + { 102 * 0x10000 + 51 * 0x100 + 153, ColorNames::rebeccapurple } }; - const std::map names_to_colors - { + const std::map names_to_colors{ { ColorNames::aliceblue, &Colors::aliceblue }, { ColorNames::antiquewhite, &Colors::antiquewhite }, { ColorNames::cyan, &Colors::cyan }, @@ -608,7 +609,8 @@ namespace Sass { Color_Ptr_Const name_to_color(const char* key) { auto p = names_to_colors.find(key); - if (p != names_to_colors.end()) { + if (p != names_to_colors.end()) + { return p->second; } return 0; @@ -622,7 +624,8 @@ namespace Sass { const char* color_to_name(const int key) { auto p = colors_to_names.find(key); - if (p != colors_to_names.end()) { + if (p != colors_to_names.end()) + { return p->second; } return 0; @@ -635,10 +638,7 @@ namespace Sass { const char* color_to_name(const Color& c) { - double key = c.r() * 0x10000 - + c.g() * 0x100 - + c.b(); + double key = c.r() * 0x10000 + c.g() * 0x100 + c.b(); return color_to_name(key); } - } diff --git a/src/color_maps.hpp b/src/color_maps.hpp index d4fd416074..c58110540e 100644 --- a/src/color_maps.hpp +++ b/src/color_maps.hpp @@ -5,11 +5,12 @@ #include #include "ast.hpp" -namespace Sass { +namespace Sass +{ struct map_cmp_str { - bool operator()(char const *a, char const *b) const + bool operator()(char const* a, char const* b) const { return std::strcmp(a, b) < 0; } @@ -168,7 +169,8 @@ namespace Sass { extern const char transparent[]; } - namespace Colors { + namespace Colors + { extern const Color aliceblue; extern const Color antiquewhite; extern const Color cyan; @@ -325,7 +327,6 @@ namespace Sass { const char* color_to_name(const int); const char* color_to_name(const Color&); const char* color_to_name(const double); - } #endif diff --git a/src/constants.cpp b/src/constants.cpp index 4246b3e52f..ca77722f6c 100644 --- a/src/constants.cpp +++ b/src/constants.cpp @@ -1,8 +1,10 @@ #include "sass.hpp" #include "constants.hpp" -namespace Sass { - namespace Constants { +namespace Sass +{ + namespace Constants + { extern const unsigned long MaxCallStack = 1024; @@ -19,76 +21,76 @@ namespace Sass { extern const unsigned long Specificity_ID = 1000000; // sass keywords - extern const char at_root_kwd[] = "@at-root"; - extern const char import_kwd[] = "@import"; - extern const char mixin_kwd[] = "@mixin"; - extern const char function_kwd[] = "@function"; - extern const char return_kwd[] = "@return"; - extern const char include_kwd[] = "@include"; - extern const char content_kwd[] = "@content"; - extern const char extend_kwd[] = "@extend"; - extern const char if_kwd[] = "@if"; - extern const char else_kwd[] = "@else"; + extern const char at_root_kwd[] = "@at-root"; + extern const char import_kwd[] = "@import"; + extern const char mixin_kwd[] = "@mixin"; + extern const char function_kwd[] = "@function"; + extern const char return_kwd[] = "@return"; + extern const char include_kwd[] = "@include"; + extern const char content_kwd[] = "@content"; + extern const char extend_kwd[] = "@extend"; + extern const char if_kwd[] = "@if"; + extern const char else_kwd[] = "@else"; extern const char if_after_else_kwd[] = "if"; - extern const char for_kwd[] = "@for"; - extern const char from_kwd[] = "from"; - extern const char to_kwd[] = "to"; - extern const char through_kwd[] = "through"; - extern const char each_kwd[] = "@each"; - extern const char in_kwd[] = "in"; - extern const char while_kwd[] = "@while"; - extern const char warn_kwd[] = "@warn"; - extern const char error_kwd[] = "@error"; - extern const char debug_kwd[] = "@debug"; - extern const char default_kwd[] = "default"; - extern const char global_kwd[] = "global"; - extern const char null_kwd[] = "null"; - extern const char optional_kwd[] = "optional"; - extern const char with_kwd[] = "with"; - extern const char without_kwd[] = "without"; - extern const char all_kwd[] = "all"; - extern const char rule_kwd[] = "rule"; + extern const char for_kwd[] = "@for"; + extern const char from_kwd[] = "from"; + extern const char to_kwd[] = "to"; + extern const char through_kwd[] = "through"; + extern const char each_kwd[] = "@each"; + extern const char in_kwd[] = "in"; + extern const char while_kwd[] = "@while"; + extern const char warn_kwd[] = "@warn"; + extern const char error_kwd[] = "@error"; + extern const char debug_kwd[] = "@debug"; + extern const char default_kwd[] = "default"; + extern const char global_kwd[] = "global"; + extern const char null_kwd[] = "null"; + extern const char optional_kwd[] = "optional"; + extern const char with_kwd[] = "with"; + extern const char without_kwd[] = "without"; + extern const char all_kwd[] = "all"; + extern const char rule_kwd[] = "rule"; // css standard units - extern const char em_kwd[] = "em"; - extern const char ex_kwd[] = "ex"; - extern const char px_kwd[] = "px"; - extern const char cm_kwd[] = "cm"; - extern const char mm_kwd[] = "mm"; - extern const char pt_kwd[] = "pt"; - extern const char pc_kwd[] = "pc"; - extern const char deg_kwd[] = "deg"; - extern const char rad_kwd[] = "rad"; + extern const char em_kwd[] = "em"; + extern const char ex_kwd[] = "ex"; + extern const char px_kwd[] = "px"; + extern const char cm_kwd[] = "cm"; + extern const char mm_kwd[] = "mm"; + extern const char pt_kwd[] = "pt"; + extern const char pc_kwd[] = "pc"; + extern const char deg_kwd[] = "deg"; + extern const char rad_kwd[] = "rad"; extern const char grad_kwd[] = "grad"; extern const char turn_kwd[] = "turn"; - extern const char ms_kwd[] = "ms"; - extern const char s_kwd[] = "s"; - extern const char Hz_kwd[] = "Hz"; - extern const char kHz_kwd[] = "kHz"; + extern const char ms_kwd[] = "ms"; + extern const char s_kwd[] = "s"; + extern const char Hz_kwd[] = "Hz"; + extern const char kHz_kwd[] = "kHz"; // vendor prefixes - extern const char vendor_opera_kwd[] = "-o-"; - extern const char vendor_webkit_kwd[] = "-webkit-"; - extern const char vendor_mozilla_kwd[] = "-moz-"; - extern const char vendor_ms_kwd[] = "-ms-"; - extern const char vendor_khtml_kwd[] = "-khtml-"; + extern const char vendor_opera_kwd[] = "-o-"; + extern const char vendor_webkit_kwd[] = "-webkit-"; + extern const char vendor_mozilla_kwd[] = "-moz-"; + extern const char vendor_ms_kwd[] = "-ms-"; + extern const char vendor_khtml_kwd[] = "-khtml-"; // css functions and keywords - extern const char charset_kwd[] = "@charset"; - extern const char media_kwd[] = "@media"; - extern const char supports_kwd[] = "@supports"; - extern const char keyframes_kwd[] = "keyframes"; - extern const char only_kwd[] = "only"; - extern const char rgb_kwd[] = "rgb("; - extern const char url_kwd[] = "url"; + extern const char charset_kwd[] = "@charset"; + extern const char media_kwd[] = "@media"; + extern const char supports_kwd[] = "@supports"; + extern const char keyframes_kwd[] = "keyframes"; + extern const char only_kwd[] = "only"; + extern const char rgb_kwd[] = "rgb("; + extern const char url_kwd[] = "url"; // extern const char url_prefix_kwd[] = "url-prefix("; - extern const char important_kwd[] = "important"; - extern const char pseudo_not_kwd[] = ":not("; - extern const char even_kwd[] = "even"; - extern const char odd_kwd[] = "odd"; - extern const char progid_kwd[] = "progid"; - extern const char expression_kwd[] = "expression"; - extern const char calc_fn_kwd[] = "calc"; + extern const char important_kwd[] = "important"; + extern const char pseudo_not_kwd[] = ":not("; + extern const char even_kwd[] = "even"; + extern const char odd_kwd[] = "odd"; + extern const char progid_kwd[] = "progid"; + extern const char expression_kwd[] = "expression"; + extern const char calc_fn_kwd[] = "calc"; extern const char almost_any_value_class[] = "\"'#!;{}"; @@ -96,58 +98,58 @@ namespace Sass { extern const char sel_deep_kwd[] = "/deep/"; // css attribute-matching operators - extern const char tilde_equal[] = "~="; - extern const char pipe_equal[] = "|="; - extern const char caret_equal[] = "^="; + extern const char tilde_equal[] = "~="; + extern const char pipe_equal[] = "|="; + extern const char caret_equal[] = "^="; extern const char dollar_equal[] = "$="; - extern const char star_equal[] = "*="; + extern const char star_equal[] = "*="; // relational & logical operators and constants - extern const char and_kwd[] = "and"; - extern const char or_kwd[] = "or"; - extern const char not_kwd[] = "not"; - extern const char gt[] = ">"; - extern const char gte[] = ">="; - extern const char lt[] = "<"; - extern const char lte[] = "<="; - extern const char eq[] = "=="; - extern const char neq[] = "!="; - extern const char true_kwd[] = "true"; + extern const char and_kwd[] = "and"; + extern const char or_kwd[] = "or"; + extern const char not_kwd[] = "not"; + extern const char gt[] = ">"; + extern const char gte[] = ">="; + extern const char lt[] = "<"; + extern const char lte[] = "<="; + extern const char eq[] = "=="; + extern const char neq[] = "!="; + extern const char true_kwd[] = "true"; extern const char false_kwd[] = "false"; // miscellaneous punctuation and delimiters - extern const char percent_str[] = "%"; - extern const char empty_str[] = ""; - extern const char slash_slash[] = "//"; - extern const char slash_star[] = "/*"; - extern const char star_slash[] = "*/"; - extern const char hash_lbrace[] = "#{"; - extern const char rbrace[] = "}"; - extern const char rparen[] = ")"; - extern const char sign_chars[] = "-+"; - extern const char op_chars[] = "-+"; - extern const char hyphen[] = "-"; - extern const char ellipsis[] = "..."; + extern const char percent_str[] = "%"; + extern const char empty_str[] = ""; + extern const char slash_slash[] = "//"; + extern const char slash_star[] = "/*"; + extern const char star_slash[] = "*/"; + extern const char hash_lbrace[] = "#{"; + extern const char rbrace[] = "}"; + extern const char rparen[] = ")"; + extern const char sign_chars[] = "-+"; + extern const char op_chars[] = "-+"; + extern const char hyphen[] = "-"; + extern const char ellipsis[] = "..."; // extern const char url_space_chars[] = " \t\r\n\f"; // type names - extern const char numeric_name[] = "numeric value"; - extern const char number_name[] = "number"; + extern const char numeric_name[] = "numeric value"; + extern const char number_name[] = "number"; extern const char percentage_name[] = "percentage"; - extern const char dimension_name[] = "numeric dimension"; - extern const char string_name[] = "string"; - extern const char bool_name[] = "bool"; - extern const char color_name[] = "color"; - extern const char list_name[] = "list"; - extern const char map_name[] = "map"; - extern const char arglist_name[] = "arglist"; + extern const char dimension_name[] = "numeric dimension"; + extern const char string_name[] = "string"; + extern const char bool_name[] = "bool"; + extern const char color_name[] = "color"; + extern const char list_name[] = "list"; + extern const char map_name[] = "map"; + extern const char arglist_name[] = "arglist"; // constants for uri parsing (RFC 3986 Appendix A.) - extern const char uri_chars[] = ":;/?!%&#@|[]{}'`^\"*+-.,_=~"; - extern const char real_uri_chars[] = "#%&"; + extern const char uri_chars[] = ":;/?!%&#@|[]{}'`^\"*+-.,_=~"; + extern const char real_uri_chars[] = "#%&"; // some specific constant character classes // they must be static to be useable by lexer - extern const char static_ops[] = "*/%"; + extern const char static_ops[] = "*/%"; // some character classes for the parser extern const char selector_list_delims[] = "){};!"; extern const char complex_selector_delims[] = ",){};!"; @@ -158,21 +160,20 @@ namespace Sass { // byte order marks // (taken from http://en.wikipedia.org/wiki/Byte_order_mark) - extern const unsigned char utf_8_bom[] = { 0xEF, 0xBB, 0xBF }; - extern const unsigned char utf_16_bom_be[] = { 0xFE, 0xFF }; - extern const unsigned char utf_16_bom_le[] = { 0xFF, 0xFE }; - extern const unsigned char utf_32_bom_be[] = { 0x00, 0x00, 0xFE, 0xFF }; - extern const unsigned char utf_32_bom_le[] = { 0xFF, 0xFE, 0x00, 0x00 }; - extern const unsigned char utf_7_bom_1[] = { 0x2B, 0x2F, 0x76, 0x38 }; - extern const unsigned char utf_7_bom_2[] = { 0x2B, 0x2F, 0x76, 0x39 }; - extern const unsigned char utf_7_bom_3[] = { 0x2B, 0x2F, 0x76, 0x2B }; - extern const unsigned char utf_7_bom_4[] = { 0x2B, 0x2F, 0x76, 0x2F }; - extern const unsigned char utf_7_bom_5[] = { 0x2B, 0x2F, 0x76, 0x38, 0x2D }; - extern const unsigned char utf_1_bom[] = { 0xF7, 0x64, 0x4C }; + extern const unsigned char utf_8_bom[] = { 0xEF, 0xBB, 0xBF }; + extern const unsigned char utf_16_bom_be[] = { 0xFE, 0xFF }; + extern const unsigned char utf_16_bom_le[] = { 0xFF, 0xFE }; + extern const unsigned char utf_32_bom_be[] = { 0x00, 0x00, 0xFE, 0xFF }; + extern const unsigned char utf_32_bom_le[] = { 0xFF, 0xFE, 0x00, 0x00 }; + extern const unsigned char utf_7_bom_1[] = { 0x2B, 0x2F, 0x76, 0x38 }; + extern const unsigned char utf_7_bom_2[] = { 0x2B, 0x2F, 0x76, 0x39 }; + extern const unsigned char utf_7_bom_3[] = { 0x2B, 0x2F, 0x76, 0x2B }; + extern const unsigned char utf_7_bom_4[] = { 0x2B, 0x2F, 0x76, 0x2F }; + extern const unsigned char utf_7_bom_5[] = { 0x2B, 0x2F, 0x76, 0x38, 0x2D }; + extern const unsigned char utf_1_bom[] = { 0xF7, 0x64, 0x4C }; extern const unsigned char utf_ebcdic_bom[] = { 0xDD, 0x73, 0x66, 0x73 }; - extern const unsigned char scsu_bom[] = { 0x0E, 0xFE, 0xFF }; - extern const unsigned char bocu_1_bom[] = { 0xFB, 0xEE, 0x28 }; - extern const unsigned char gb_18030_bom[] = { 0x84, 0x31, 0x95, 0x33 }; - + extern const unsigned char scsu_bom[] = { 0x0E, 0xFE, 0xFF }; + extern const unsigned char bocu_1_bom[] = { 0xFB, 0xEE, 0x28 }; + extern const unsigned char gb_18030_bom[] = { 0x84, 0x31, 0x95, 0x33 }; } } diff --git a/src/constants.hpp b/src/constants.hpp index 8470d5d6a5..95bae95eab 100644 --- a/src/constants.hpp +++ b/src/constants.hpp @@ -1,8 +1,10 @@ #ifndef SASS_CONSTANTS_H #define SASS_CONSTANTS_H -namespace Sass { - namespace Constants { +namespace Sass +{ + namespace Constants + { // The maximum call stack that can be created extern const unsigned long MaxCallStack; @@ -173,7 +175,6 @@ namespace Sass { extern const unsigned char scsu_bom[]; extern const unsigned char bocu_1_bom[]; extern const unsigned char gb_18030_bom[]; - } } diff --git a/src/context.cpp b/src/context.cpp index 0f4932a582..4856d4bbcb 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -30,13 +30,16 @@ #include "prelexer.hpp" #include "emitter.hpp" -namespace Sass { +namespace Sass +{ using namespace Constants; using namespace File; using namespace Sass; - inline bool sort_importers (const Sass_Importer_Entry& i, const Sass_Importer_Entry& j) - { return sass_importer_get_priority(i) > sass_importer_get_priority(j); } + inline bool sort_importers(const Sass_Importer_Entry& i, const Sass_Importer_Entry& j) + { + return sass_importer_get_priority(i) > sass_importer_get_priority(j); + } static std::string safe_input(const char* in_path) { @@ -50,7 +53,8 @@ namespace Sass { { std::string safe_path(out_path ? out_path : ""); // maybe we can extract an output path from input path - if (safe_path == "" && input_path != "") { + if (safe_path == "" && input_path != "") + { int lastindex = static_cast(input_path.find_last_of(".")); return (lastindex > -1 ? input_path.substr(0, lastindex) : input_path) + ".css"; } @@ -60,37 +64,26 @@ namespace Sass { } Context::Context(struct Sass_Context& c_ctx) - : CWD(File::get_cwd()), - c_options(c_ctx), - entry_path(""), - head_imports(0), - plugins(), - emitter(c_options), + : CWD(File::get_cwd()), c_options(c_ctx), entry_path(""), head_imports(0), plugins(), emitter(c_options), - strings(), - resources(), - sheets(), - subset_map(), - import_stack(), - callee_stack(), - c_compiler(NULL), + strings(), resources(), sheets(), subset_map(), import_stack(), callee_stack(), c_compiler(NULL), - c_headers (std::vector()), - c_importers (std::vector()), - c_functions (std::vector()), + c_headers(std::vector()), c_importers(std::vector()), + c_functions(std::vector()), - indent (safe_str(c_options.indent, " ")), - linefeed (safe_str(c_options.linefeed, "\n")), + indent(safe_str(c_options.indent, " ")), linefeed(safe_str(c_options.linefeed, "\n")), - input_path (make_canonical_path(safe_input(c_options.input_path))), - output_path (make_canonical_path(safe_output(c_options.output_path, input_path))), - source_map_file (make_canonical_path(safe_str(c_options.source_map_file, ""))), - source_map_root (make_canonical_path(safe_str(c_options.source_map_root, ""))) + input_path(make_canonical_path(safe_input(c_options.input_path))), + output_path(make_canonical_path(safe_output(c_options.output_path, input_path))), + source_map_file(make_canonical_path(safe_str(c_options.source_map_file, ""))), + source_map_root(make_canonical_path(safe_str(c_options.source_map_root, ""))) { - // Sass 3.4: The current working directory will no longer be placed onto the Sass load path by default. - // If you need the current working directory to be available, set SASS_PATH=. in your shell's environment. + // Sass 3.4: The current working directory will no longer be placed onto the Sass load path by + // default. + // If you need the current working directory to be available, set SASS_PATH=. in your shell's + // environment. // include_paths.push_back(CWD); // collect more paths from different options @@ -100,17 +93,20 @@ namespace Sass { collect_plugin_paths(c_options.plugin_paths); // load plugins and register custom behaviors - for(auto plug : plugin_paths) plugins.load_plugins(plug); - for(auto fn : plugins.get_headers()) c_headers.push_back(fn); - for(auto fn : plugins.get_importers()) c_importers.push_back(fn); - for(auto fn : plugins.get_functions()) c_functions.push_back(fn); + for (auto plug : plugin_paths) + plugins.load_plugins(plug); + for (auto fn : plugins.get_headers()) + c_headers.push_back(fn); + for (auto fn : plugins.get_importers()) + c_importers.push_back(fn); + for (auto fn : plugins.get_functions()) + c_functions.push_back(fn); // sort the items by priority (lowest first) - sort (c_headers.begin(), c_headers.end(), sort_importers); - sort (c_importers.begin(), c_importers.end(), sort_importers); + sort(c_headers.begin(), c_headers.end(), sort_importers); + sort(c_importers.begin(), c_importers.end(), sort_importers); emitter.set_filename(abs2rel(output_path, source_map_file, CWD)); - } void Context::add_c_function(Sass_Function_Entry function) @@ -121,33 +117,37 @@ namespace Sass { { c_headers.push_back(header); // need to sort the array afterwards (no big deal) - sort (c_headers.begin(), c_headers.end(), sort_importers); + sort(c_headers.begin(), c_headers.end(), sort_importers); } void Context::add_c_importer(Sass_Importer_Entry importer) { c_importers.push_back(importer); // need to sort the array afterwards (no big deal) - sort (c_importers.begin(), c_importers.end(), sort_importers); + sort(c_importers.begin(), c_importers.end(), sort_importers); } Context::~Context() { // resources were allocated by strdup or malloc - for (size_t i = 0; i < resources.size(); ++i) { + for (size_t i = 0; i < resources.size(); ++i) + { free(resources[i].contents); free(resources[i].srcmap); } // free all strings we kept alive during compiler execution - for (size_t n = 0; n < strings.size(); ++n) free(strings[n]); + for (size_t n = 0; n < strings.size(); ++n) + free(strings[n]); // everything that gets put into sources will be freed by us // this shouldn't have anything in it anyway!? - for (size_t m = 0; m < import_stack.size(); ++m) { + for (size_t m = 0; m < import_stack.size(); ++m) + { sass_import_take_source(import_stack[m]); sass_import_take_srcmap(import_stack[m]); sass_delete_import(import_stack[m]); } // clear inner structures (vectors) and input source - resources.clear(); import_stack.clear(); + resources.clear(); + import_stack.clear(); subset_map.clear(), sheets.clear(); } @@ -166,13 +166,16 @@ namespace Sass { void Context::collect_include_paths(const char* paths_str) { - if (paths_str) { + if (paths_str) + { const char* beg = paths_str; const char* end = Prelexer::find_first(beg); - while (end) { + while (end) + { std::string path(beg, end - beg); - if (!path.empty()) { + if (!path.empty()) + { if (*path.rbegin() != '/') path += '/'; include_paths.push_back(path); } @@ -181,7 +184,8 @@ namespace Sass { } std::string path(beg); - if (!path.empty()) { + if (!path.empty()) + { if (*path.rbegin() != '/') path += '/'; include_paths.push_back(path); } @@ -199,13 +203,16 @@ namespace Sass { void Context::collect_plugin_paths(const char* paths_str) { - if (paths_str) { + if (paths_str) + { const char* beg = paths_str; const char* end = Prelexer::find_first(beg); - while (end) { + while (end) + { std::string path(beg, end - beg); - if (!path.empty()) { + if (!path.empty()) + { if (*path.rbegin() != '/') path += '/'; plugin_paths.push_back(path); } @@ -214,7 +221,8 @@ namespace Sass { } std::string path(beg); - if (!path.empty()) { + if (!path.empty()) + { if (*path.rbegin() != '/') path += '/'; plugin_paths.push_back(path); } @@ -279,12 +287,8 @@ namespace Sass { srcmap_links.push_back(abs2rel(inc.abs_path, source_map_file, CWD)); // get pointer to the loaded content - Sass_Import_Entry import = sass_make_import( - inc.imp_path.c_str(), - inc.abs_path.c_str(), - res.contents, - res.srcmap - ); + Sass_Import_Entry import = + sass_make_import(inc.imp_path.c_str(), inc.abs_path.c_str(), res.contents, res.srcmap); // add the entry to the stack import_stack.push_back(import); @@ -297,13 +301,16 @@ namespace Sass { ParserState pstate(strings.back(), contents, idx); // check existing import stack for possible recursion - for (size_t i = 0; i < import_stack.size() - 2; ++i) { + for (size_t i = 0; i < import_stack.size() - 2; ++i) + { auto parent = import_stack[i]; - if (std::strcmp(parent->abs_path, import->abs_path) == 0) { + if (std::strcmp(parent->abs_path, import->abs_path) == 0) + { std::string stack("An @import loop has been found:"); - for (size_t n = 1; n < i + 2; ++n) { - stack += "\n " + std::string(import_stack[n]->imp_path) + - " imports " + std::string(import_stack[n+1]->imp_path); + for (size_t n = 1; n < i + 2; ++n) + { + stack += "\n " + std::string(import_stack[n]->imp_path) + " imports " + + std::string(import_stack[n + 1]->imp_path); } // implement error throw directly until we // decided how to handle full stack traces @@ -325,11 +332,9 @@ namespace Sass { // remove current stack frame import_stack.pop_back(); // create key/value pair for ast node - std::pair - ast_pair(inc.abs_path, { res, root }); + std::pair ast_pair(inc.abs_path, { res, root }); // register resulting resource sheets.insert(ast_pair); - } // Add a new import to the context (called from `import_url`) @@ -341,25 +346,33 @@ namespace Sass { const std::vector resolved(find_includes(imp)); // error nicely on ambiguous imp_path - if (resolved.size() > 1) { + if (resolved.size() > 1) + { std::stringstream msg_stream; msg_stream << "It's not clear which file to import for "; - msg_stream << "'@import \"" << imp.imp_path << "\"'." << "\n"; - msg_stream << "Candidates:" << "\n"; + msg_stream << "'@import \"" << imp.imp_path << "\"'." + << "\n"; + msg_stream << "Candidates:" + << "\n"; for (size_t i = 0, L = resolved.size(); i < L; ++i) - { msg_stream << " " << resolved[i].imp_path << "\n"; } - msg_stream << "Please delete or rename all but one of these files." << "\n"; + { + msg_stream << " " << resolved[i].imp_path << "\n"; + } + msg_stream << "Please delete or rename all but one of these files." + << "\n"; error(msg_stream.str(), pstate); } // process the resolved entry - else if (resolved.size() == 1) { + else if (resolved.size() == 1) + { bool use_cache = c_importers.size() == 0; // use cache for the resource loading if (use_cache && sheets.count(resolved[0].abs_path)) return resolved[0]; // try to read the content of the resolved file entry // the memory buffer returned must be freed by us! - if (char* contents = read_file(resolved[0].abs_path)) { + if (char* contents = read_file(resolved[0].abs_path)) + { // register the newly resolved file resource register_resource(resolved[0], { contents, 0 }, &pstate); // return resolved entry @@ -369,17 +382,18 @@ namespace Sass { // nothing found return { imp, "" }; - } - void Context::import_url (Import_Ptr imp, std::string load_path, const std::string& ctx_path) { + void Context::import_url(Import_Ptr imp, std::string load_path, const std::string& ctx_path) + { ParserState pstate(imp->pstate()); std::string imp_path(unquote(load_path)); std::string protocol("file"); using namespace Prelexer; - if (const char* proto = sequence< identifier, exactly<':'>, exactly<'/'>, exactly<'/'> >(imp_path.c_str())) { + if (const char* proto = sequence, exactly<'/'>, exactly<'/'>>(imp_path.c_str())) + { protocol = std::string(imp_path.c_str(), proto - 3); // if (protocol.compare("file") && true) { } @@ -387,10 +401,12 @@ namespace Sass { // add urls (protocol other than file) and urls without procotol to `urls` member // ToDo: if ctx_path is already a file resource, we should not add it here? - if (imp->import_queries() || protocol != "file" || imp_path.substr(0, 2) == "//") { + if (imp->import_queries() || protocol != "file" || imp_path.substr(0, 2) == "//") + { imp->urls().push_back(SASS_MEMORY_NEW(String_Quoted, imp->pstate(), load_path)); } - else if (imp_path.length() > 4 && imp_path.substr(imp_path.length() - 4, 4) == ".css") { + else if (imp_path.length() > 4 && imp_path.substr(imp_path.length() - 4, 4) == ".css") + { String_Constant_Ptr loc = SASS_MEMORY_NEW(String_Constant, pstate, unquote(load_path)); Argument_Obj loc_arg = SASS_MEMORY_NEW(Argument, pstate, loc); Arguments_Obj loc_args = SASS_MEMORY_NEW(Arguments, pstate); @@ -398,39 +414,49 @@ namespace Sass { Function_Call_Ptr new_url = SASS_MEMORY_NEW(Function_Call, pstate, "url", loc_args); imp->urls().push_back(new_url); } - else { + else + { const Importer importer(imp_path, ctx_path); Include include(load_import(importer, pstate)); - if (include.abs_path.empty()) { + if (include.abs_path.empty()) + { error("File to import not found or unreadable: " + imp_path + ".\nParent style sheet: " + ctx_path, pstate); } imp->incs().push_back(include); } - } - // call custom importers on the given (unquoted) load_path and eventually parse the resulting style_sheet - bool Context::call_loader(const std::string& load_path, const char* ctx_path, ParserState& pstate, Import_Ptr imp, std::vector importers, bool only_one) + // call custom importers on the given (unquoted) load_path and eventually parse the resulting + // style_sheet + bool Context::call_loader(const std::string& load_path, + const char* ctx_path, + ParserState& pstate, + Import_Ptr imp, + std::vector importers, + bool only_one) { // unique counter size_t count = 0; // need one correct import bool has_import = false; // process all custom importers (or custom headers) - for (Sass_Importer_Entry& importer_ent : importers) { + for (Sass_Importer_Entry& importer_ent : importers) + { // int priority = sass_importer_get_priority(importer); Sass_Importer_Fn fn = sass_importer_get_function(importer_ent); // skip importer if it returns NULL - if (Sass_Import_List includes = - fn(load_path.c_str(), importer_ent, c_compiler) - ) { + if (Sass_Import_List includes = fn(load_path.c_str(), importer_ent, c_compiler)) + { // get c pointer copy to iterate over Sass_Import_List it_includes = includes; - while (*it_includes) { ++count; + while (*it_includes) + { + ++count; // create unique path to use as key std::string uniq_path = load_path; - if (!only_one && count) { + if (!only_one && count) + { std::stringstream path_strm; path_strm << uniq_path << ":" << count; uniq_path = path_strm.str(); @@ -443,16 +469,21 @@ namespace Sass { char* srcmap = sass_import_take_srcmap(include_ent); size_t line = sass_import_get_error_line(include_ent); size_t column = sass_import_get_error_column(include_ent); - const char *abs_path = sass_import_get_abs_path(include_ent); + const char* abs_path = sass_import_get_abs_path(include_ent); // handle error message passed back from custom importer // it may (or may not) override the line and column info - if (const char* err_message = sass_import_get_error_message(include_ent)) { - if (source || srcmap) register_resource({ importer, uniq_path }, { source, srcmap }, &pstate); - if (line == std::string::npos && column == std::string::npos) error(err_message, pstate); - else error(err_message, ParserState(ctx_path, source, Position(line, column))); + if (const char* err_message = sass_import_get_error_message(include_ent)) + { + if (source || srcmap) + register_resource({ importer, uniq_path }, { source, srcmap }, &pstate); + if (line == std::string::npos && column == std::string::npos) + error(err_message, pstate); + else + error(err_message, ParserState(ctx_path, source, Position(line, column))); } // content for import was set - else if (source) { + else if (source) + { // resolved abs_path should be set by custom importer // use the created uniq_path as fallback (maybe enforce) std::string path_key(abs_path ? abs_path : uniq_path); @@ -465,7 +496,8 @@ namespace Sass { } // only a path was retuned // try to load it like normal - else if(abs_path) { + else if (abs_path) + { // checks some urls to preserve // `http://`, `https://` and `//` // or dispatchs to `import_file` @@ -508,14 +540,17 @@ namespace Sass { // get the resulting buffer from stream OutputBuffer emitted = emitter.get_buffer(); // should we append a source map url? - if (!c_options.omit_source_map_url) { + if (!c_options.omit_source_map_url) + { // generate an embeded source map - if (c_options.source_map_embed) { + if (c_options.source_map_embed) + { emitted.buffer += linefeed; emitted.buffer += format_embedded_source_map(); } // or just link the generated one - else if (source_map_file != "") { + else if (source_map_file != "") + { emitted.buffer += linefeed; emitted.buffer += format_source_mapping_url(source_map_file); } @@ -537,7 +572,8 @@ namespace Sass { // add the statement if we have urls if (!imp->urls().empty()) root->append(imp); // process all other resources (add Import_Stub nodes) - for (size_t i = 0, S = imp->incs().size(); i < S; ++i) { + for (size_t i = 0, S = imp->incs().size(); i < S; ++i) + { root->append(SASS_MEMORY_NEW(Import_Stub, pstate, imp->incs()[i])); } } @@ -557,7 +593,8 @@ namespace Sass { // alternatively also look inside each include path folder // I think this differs from ruby sass (IMO too late to remove) - for (size_t i = 0, S = include_paths.size(); contents == 0 && i < S; ++i) { + for (size_t i = 0, S = include_paths.size(); contents == 0 && i < S; ++i) + { // build absolute path for this include path entry abs_path = rel2abs(input_path, include_paths[i]); // try to load the resulting path @@ -571,21 +608,15 @@ namespace Sass { entry_path = abs_path; // create entry only for import stack - Sass_Import_Entry import = sass_make_import( - input_path.c_str(), - entry_path.c_str(), - contents, - 0 - ); + Sass_Import_Entry import = sass_make_import(input_path.c_str(), entry_path.c_str(), contents, 0); // add the entry to the stack import_stack.push_back(import); // create the source entry for file entry - register_resource({{ input_path, "." }, abs_path }, { contents, 0 }); + register_resource({ { input_path, "." }, abs_path }, { contents, 0 }); // create root ast tree node return compile(); - } Block_Obj Data_Context::parse() @@ -595,13 +626,15 @@ namespace Sass { if (!source_c_str) return 0; // convert indented sass syntax - if(c_options.is_indented_syntax_src) { + if (c_options.is_indented_syntax_src) + { // call sass2scss to convert the string - char * converted = sass2scss(source_c_str, - // preserve the structure as much as possible - SASS2SCSS_PRETTIFY_1 | SASS2SCSS_KEEP_COMMENT); + char* converted = sass2scss(source_c_str, + // preserve the structure as much as possible + SASS2SCSS_PRETTIFY_1 | SASS2SCSS_KEEP_COMMENT); // replace old source_c_str with converted - free(source_c_str); source_c_str = converted; + free(source_c_str); + source_c_str = converted; } // remember entry path (defaults to stdin for string) @@ -613,24 +646,18 @@ namespace Sass { strings.push_back(abs_path_c_str); // create entry only for the import stack - Sass_Import_Entry import = sass_make_import( - entry_path.c_str(), - abs_path_c_str, - source_c_str, - srcmap_c_str - ); + Sass_Import_Entry import = sass_make_import(entry_path.c_str(), abs_path_c_str, source_c_str, srcmap_c_str); // add the entry to the stack import_stack.push_back(import); // register a synthetic resource (path does not really exist, skip in includes) - register_resource({{ input_path, "." }, input_path }, { source_c_str, srcmap_c_str }); + register_resource({ { input_path, "." }, input_path }, { source_c_str, srcmap_c_str }); // create root ast tree node return compile(); } - // parse root block from includes Block_Obj Context::compile() { @@ -645,7 +672,9 @@ namespace Sass { register_built_in_functions(*this, &global); // register custom functions (defined via C-API) for (size_t i = 0, S = c_functions.size(); i < S; ++i) - { register_c_function(*this, &global, c_functions[i]); } + { + register_c_function(*this, &global, c_functions[i]); + } // create initial backtrace entry Backtrace backtrace(0, ParserState("", 0), ""); // create crtp visitor objects @@ -661,7 +690,8 @@ namespace Sass { // merge and bubble certain rules root = cssize(root); // should we extend something? - if (!subset_map.empty()) { + if (!subset_map.empty()) + { // create crtp visitor object Extend extend(subset_map); // extend tree nodes @@ -680,7 +710,7 @@ namespace Sass { std::string Context::format_embedded_source_map() { std::string map = emitter.render_srcmap(*this); - std::istringstream is( map ); + std::istringstream is(map); std::ostringstream buffer; base64::encoder E; E.encode(is, buffer); @@ -707,14 +737,20 @@ namespace Sass { // we probably always want to skip the header includes? std::vector Context::get_included_files(bool skip, size_t headers) { - // create a copy of the vector for manipulations - std::vector includes = included_files; - if (includes.size() == 0) return includes; - if (skip) { includes.erase( includes.begin(), includes.begin() + 1 + headers); } - else { includes.erase( includes.begin() + 1, includes.begin() + 1 + headers); } - includes.erase( std::unique( includes.begin(), includes.end() ), includes.end() ); - std::sort( includes.begin() + (skip ? 0 : 1), includes.end() ); - return includes; + // create a copy of the vector for manipulations + std::vector includes = included_files; + if (includes.size() == 0) return includes; + if (skip) + { + includes.erase(includes.begin(), includes.begin() + 1 + headers); + } + else + { + includes.erase(includes.begin() + 1, includes.begin() + 1 + headers); + } + includes.erase(std::unique(includes.begin(), includes.end()), includes.end()); + std::sort(includes.begin() + (skip ? 0 : 1), includes.end()); + return includes; } void register_function(Context& ctx, Signature sig, Native_Function f, Env* env) @@ -735,13 +771,8 @@ namespace Sass { void register_overload_stub(Context& ctx, std::string name, Env* env) { - Definition_Ptr stub = SASS_MEMORY_NEW(Definition, - ParserState("[built-in function]"), - 0, - name, - 0, - 0, - true); + Definition_Ptr stub = + SASS_MEMORY_NEW(Definition, ParserState("[built-in function]"), 0, name, 0, 0, true); (*env)[name + "[f]"] = stub; } @@ -850,7 +881,8 @@ namespace Sass { void register_c_functions(Context& ctx, Env* env, Sass_Function_List descrs) { - while (descrs && *descrs) { + while (descrs && *descrs) + { register_c_function(ctx, env, *descrs); ++descrs; } @@ -861,5 +893,4 @@ namespace Sass { def->environment(env); (*env)[def->name() + "[f]"] = def; } - } diff --git a/src/context.hpp b/src/context.hpp index 44a32ed062..c330645188 100644 --- a/src/context.hpp +++ b/src/context.hpp @@ -22,20 +22,31 @@ struct Sass_Function; -namespace Sass { +namespace Sass +{ - class Context { - public: - void import_url (Import_Ptr imp, std::string load_path, const std::string& ctx_path); + class Context + { + public: + void import_url(Import_Ptr imp, std::string load_path, const std::string& ctx_path); bool call_headers(const std::string& load_path, const char* ctx_path, ParserState& pstate, Import_Ptr imp) - { return call_loader(load_path, ctx_path, pstate, imp, c_headers, false); }; + { + return call_loader(load_path, ctx_path, pstate, imp, c_headers, false); + }; bool call_importers(const std::string& load_path, const char* ctx_path, ParserState& pstate, Import_Ptr imp) - { return call_loader(load_path, ctx_path, pstate, imp, c_importers, true); }; - - private: - bool call_loader(const std::string& load_path, const char* ctx_path, ParserState& pstate, Import_Ptr imp, std::vector importers, bool only_one = true); - - public: + { + return call_loader(load_path, ctx_path, pstate, imp, c_importers, true); + }; + + private: + bool call_loader(const std::string& load_path, + const char* ctx_path, + ParserState& pstate, + Import_Ptr imp, + std::vector importers, + bool only_one = true); + + public: const std::string CWD; struct Sass_Options& c_options; std::string entry_path; @@ -64,9 +75,6 @@ namespace Sass { std::vector include_paths; // lookup paths for includes - - - void apply_custom_headers(Block_Obj root, const char* path, ParserState pstate); std::vector c_headers; @@ -95,10 +103,13 @@ namespace Sass { std::vector find_includes(const Importer& import); Include load_import(const Importer&, ParserState pstate); - Sass_Output_Style output_style() { return c_options.output_style; }; + Sass_Output_Style output_style() + { + return c_options.output_style; + }; std::vector get_included_files(bool skip = false, size_t headers = 0); - private: + private: void collect_plugin_paths(const char* paths_str); void collect_plugin_paths(string_list* paths_array); void collect_include_paths(const char* paths_str); @@ -112,35 +123,38 @@ namespace Sass { // void register_function(Signature sig, Native_Function f, size_t arity, Env* env); // void register_overload_stub(std::string name, Env* env); - public: - const std::string& cwd() { return CWD; }; + public: + const std::string& cwd() + { + return CWD; + }; }; - class File_Context : public Context { - public: - File_Context(struct Sass_File_Context& ctx) - : Context(ctx) - { } + class File_Context : public Context + { + public: + File_Context(struct Sass_File_Context& ctx) : Context(ctx) + { + } virtual ~File_Context(); virtual Block_Obj parse(); }; - class Data_Context : public Context { - public: + class Data_Context : public Context + { + public: char* source_c_str; char* srcmap_c_str; - Data_Context(struct Sass_Data_Context& ctx) - : Context(ctx) + Data_Context(struct Sass_Data_Context& ctx) : Context(ctx) { - source_c_str = ctx.source_string; - srcmap_c_str = ctx.srcmap_string; + source_c_str = ctx.source_string; + srcmap_c_str = ctx.srcmap_string; ctx.source_string = 0; // passed away ctx.srcmap_string = 0; // passed away } virtual ~Data_Context(); virtual Block_Obj parse(); }; - } #endif diff --git a/src/cssize.cpp b/src/cssize.cpp index 22a1ce0655..2d2fd9df31 100644 --- a/src/cssize.cpp +++ b/src/cssize.cpp @@ -7,14 +7,13 @@ #include "context.hpp" #include "backtrace.hpp" -namespace Sass { +namespace Sass +{ Cssize::Cssize(Context& ctx, Backtrace* bt) - : ctx(ctx), - block_stack(std::vector()), - p_stack(std::vector()), - backtrace(bt) - { } + : ctx(ctx), block_stack(std::vector()), p_stack(std::vector()), backtrace(bt) + { + } Statement_Ptr Cssize::parent() { @@ -40,21 +39,18 @@ namespace Sass { { String_Obj property = Cast(d->property()); - if (Declaration_Ptr dd = Cast(parent())) { + if (Declaration_Ptr dd = Cast(parent())) + { String_Obj parent_property = Cast(dd->property()); - property = SASS_MEMORY_NEW(String_Constant, - d->property()->pstate(), + property = SASS_MEMORY_NEW(String_Constant, d->property()->pstate(), parent_property->to_string() + "-" + property->to_string()); - if (!dd->value()) { + if (!dd->value()) + { d->tabs(dd->tabs() + 1); } } - Declaration_Obj dd = SASS_MEMORY_NEW(Declaration, - d->pstate(), - property, - d->value(), - d->is_important()); + Declaration_Obj dd = SASS_MEMORY_NEW(Declaration, d->pstate(), property, d->value(), d->is_important()); dd->is_indented(d->is_indented()); dd->tabs(d->tabs()); @@ -62,13 +58,16 @@ namespace Sass { Block_Obj bb = d->block() ? operator()(d->block()) : NULL; p_stack.pop_back(); - if (bb && bb->length()) { - if (dd->value() && !dd->value()->is_invisible()) { + if (bb && bb->length()) + { + if (dd->value() && !dd->value()->is_invisible()) + { bb->unshift(dd); } return bb.detach(); } - else if (dd->value() && !dd->value()->is_invisible()) { + else if (dd->value() && !dd->value()->is_invisible()) + { return dd.detach(); } @@ -85,26 +84,27 @@ namespace Sass { } p_stack.push_back(r); - Directive_Obj rr = SASS_MEMORY_NEW(Directive, - r->pstate(), - r->keyword(), - r->selector(), - r->block() ? operator()(r->block()) : 0); + Directive_Obj rr = SASS_MEMORY_NEW(Directive, r->pstate(), r->keyword(), r->selector(), + r->block() ? operator()(r->block()) : 0); if (r->value()) rr->value(r->value()); p_stack.pop_back(); bool directive_exists = false; size_t L = rr->block() ? rr->block()->length() : 0; - for (size_t i = 0; i < L && !directive_exists; ++i) { + for (size_t i = 0; i < L && !directive_exists; ++i) + { Statement_Obj s = r->block()->at(i); - if (s->statement_type() != Statement::BUBBLE) directive_exists = true; - else { + if (s->statement_type() != Statement::BUBBLE) + directive_exists = true; + else + { Bubble_Obj s_obj = Cast(s); s = s_obj->node(); - if (s->statement_type() != Statement::DIRECTIVE) directive_exists = false; - else directive_exists = (Cast(s)->keyword() == rr->keyword()); + if (s->statement_type() != Statement::DIRECTIVE) + directive_exists = false; + else + directive_exists = (Cast(s)->keyword() == rr->keyword()); } - } Block_Ptr result = SASS_MEMORY_NEW(Block, rr->pstate()); @@ -118,7 +118,8 @@ namespace Sass { Block_Obj db = rr->block(); if (db.isNull()) db = SASS_MEMORY_NEW(Block, rr->pstate()); Block_Obj ss = debubble(db, rr); - for (size_t i = 0, L = ss->length(); i < L; ++i) { + for (size_t i = 0, L = ss->length(); i < L; ++i) + { result->append(ss->at(i)); } @@ -129,9 +130,7 @@ namespace Sass { { if (!r->block() || !r->block()->length()) return r; - Keyframe_Rule_Obj rr = SASS_MEMORY_NEW(Keyframe_Rule, - r->pstate(), - operator()(r->block())); + Keyframe_Rule_Obj rr = SASS_MEMORY_NEW(Keyframe_Rule, r->pstate(), operator()(r->block())); if (!r->name().isNull()) rr->name(r->name()); return debubble(rr->block(), rr); @@ -147,19 +146,18 @@ namespace Sass { Block_Ptr bb = operator()(r->block()); // this should protect us (at least a bit) from our mess // fixing this properly is harder that it should be ... - if (Cast(bb) == NULL) { + if (Cast(bb) == NULL) + { error("Illegal nesting: Only properties may be nested beneath properties.", r->block()->pstate()); } - Ruleset_Obj rr = SASS_MEMORY_NEW(Ruleset, - r->pstate(), - r->selector(), - bb); + Ruleset_Obj rr = SASS_MEMORY_NEW(Ruleset, r->pstate(), r->selector(), bb); rr->is_root(r->is_root()); // rr->tabs(r->block()->tabs()); p_stack.pop_back(); - if (!rr->block()) { + if (!rr->block()) + { error("Illegal nesting: Only properties may be nested beneath properties.", r->block()->pstate()); } @@ -191,13 +189,12 @@ namespace Sass { rules = debubble(rules); void* lp = ptr; void* rp = rules; - if (lp != rp) { + if (lp != rp) + { Block_Obj obj = ptr; } - if (!(!rules->length() || - !bubblable(rules->last()) || - parent()->statement_type() == Statement::RULESET)) + if (!(!rules->length() || !bubblable(rules->last()) || parent()->statement_type() == Statement::RULESET)) { rules->last()->group_end(true); } @@ -212,17 +209,19 @@ namespace Sass { Statement_Ptr Cssize::operator()(Media_Block_Ptr m) { if (parent()->statement_type() == Statement::RULESET) - { return bubble(m); } + { + return bubble(m); + } if (parent()->statement_type() == Statement::MEDIA) - { return SASS_MEMORY_NEW(Bubble, m->pstate(), m); } + { + return SASS_MEMORY_NEW(Bubble, m->pstate(), m); + } p_stack.push_back(m); - Media_Block_Obj mm = SASS_MEMORY_NEW(Media_Block, - m->pstate(), - m->media_queries(), - operator()(m->block())); + Media_Block_Obj mm = + SASS_MEMORY_NEW(Media_Block, m->pstate(), m->media_queries(), operator()(m->block())); mm->tabs(m->tabs()); p_stack.pop_back(); @@ -233,17 +232,19 @@ namespace Sass { Statement_Ptr Cssize::operator()(Supports_Block_Ptr m) { if (!m->block()->length()) - { return m; } + { + return m; + } if (parent()->statement_type() == Statement::RULESET) - { return bubble(m); } + { + return bubble(m); + } p_stack.push_back(m); - Supports_Block_Obj mm = SASS_MEMORY_NEW(Supports_Block, - m->pstate(), - m->condition(), - operator()(m->block())); + Supports_Block_Obj mm = + SASS_MEMORY_NEW(Supports_Block, m->pstate(), m->condition(), operator()(m->block())); mm->tabs(m->tabs()); p_stack.pop_back(); @@ -254,7 +255,8 @@ namespace Sass { Statement_Ptr Cssize::operator()(At_Root_Block_Ptr m) { bool tmp = false; - for (size_t i = 0, L = p_stack.size(); i < L; ++i) { + for (size_t i = 0, L = p_stack.size(); i < L; ++i) + { Statement_Ptr s = p_stack[i]; tmp |= m->exclude_node(s); } @@ -262,7 +264,8 @@ namespace Sass { if (!tmp) { Block_Ptr bb = operator()(m->block()); - for (size_t i = 0, L = bb->length(); i < L; ++i) { + for (size_t i = 0, L = bb->length(); i < L; ++i) + { // (bb->elements())[i]->tabs(m->tabs()); Statement_Obj stm = bb->at(i); if (bubblable(stm)) stm->tabs(stm->tabs() + m->tabs()); @@ -289,11 +292,7 @@ namespace Sass { Block_Obj wrapper_block = SASS_MEMORY_NEW(Block, m->block() ? m->block()->pstate() : m->pstate()); wrapper_block->append(new_rule); - Directive_Obj mm = SASS_MEMORY_NEW(Directive, - m->pstate(), - m->keyword(), - m->selector(), - wrapper_block); + Directive_Obj mm = SASS_MEMORY_NEW(Directive, m->pstate(), m->keyword(), m->selector(), wrapper_block); if (m->value()) mm->value(m->value()); Bubble_Ptr bubble = SASS_MEMORY_NEW(Bubble, mm->pstate(), mm); @@ -310,10 +309,7 @@ namespace Sass { Block_Ptr wrapper_block = SASS_MEMORY_NEW(Block, m->block()->pstate()); wrapper_block->append(new_rule); - At_Root_Block_Ptr mm = SASS_MEMORY_NEW(At_Root_Block, - m->pstate(), - wrapper_block, - m->expression()); + At_Root_Block_Ptr mm = SASS_MEMORY_NEW(At_Root_Block, m->pstate(), wrapper_block, m->expression()); Bubble_Ptr bubble = SASS_MEMORY_NEW(Bubble, mm->pstate(), mm); return bubble; } @@ -323,19 +319,13 @@ namespace Sass { Ruleset_Obj parent = Cast(SASS_MEMORY_COPY(this->parent())); Block_Ptr bb = SASS_MEMORY_NEW(Block, parent->block()->pstate()); - Ruleset_Ptr new_rule = SASS_MEMORY_NEW(Ruleset, - parent->pstate(), - parent->selector(), - bb); + Ruleset_Ptr new_rule = SASS_MEMORY_NEW(Ruleset, parent->pstate(), parent->selector(), bb); new_rule->tabs(parent->tabs()); new_rule->block()->concat(m->block()); Block_Ptr wrapper_block = SASS_MEMORY_NEW(Block, m->block()->pstate()); wrapper_block->append(new_rule); - Supports_Block_Ptr mm = SASS_MEMORY_NEW(Supports_Block, - m->pstate(), - m->condition(), - wrapper_block); + Supports_Block_Ptr mm = SASS_MEMORY_NEW(Supports_Block, m->pstate(), m->condition(), wrapper_block); mm->tabs(m->tabs()); @@ -348,19 +338,13 @@ namespace Sass { Ruleset_Obj parent = Cast(SASS_MEMORY_COPY(this->parent())); Block_Ptr bb = SASS_MEMORY_NEW(Block, parent->block()->pstate()); - Ruleset_Ptr new_rule = SASS_MEMORY_NEW(Ruleset, - parent->pstate(), - parent->selector(), - bb); + Ruleset_Ptr new_rule = SASS_MEMORY_NEW(Ruleset, parent->pstate(), parent->selector(), bb); new_rule->tabs(parent->tabs()); new_rule->block()->concat(m->block()); Block_Ptr wrapper_block = SASS_MEMORY_NEW(Block, m->block()->pstate()); wrapper_block->append(new_rule); - Media_Block_Obj mm = SASS_MEMORY_NEW(Media_Block, - m->pstate(), - m->media_queries(), - wrapper_block); + Media_Block_Obj mm = SASS_MEMORY_NEW(Media_Block, m->pstate(), m->media_queries(), wrapper_block); mm->tabs(m->tabs()); @@ -375,15 +359,19 @@ namespace Sass { Block_Ptr Cssize::flatten(Block_Ptr b) { Block_Ptr result = SASS_MEMORY_NEW(Block, b->pstate(), 0, b->is_root()); - for (size_t i = 0, L = b->length(); i < L; ++i) { + for (size_t i = 0, L = b->length(); i < L; ++i) + { Statement_Ptr ss = b->at(i); - if (Block_Ptr bb = Cast(ss)) { + if (Block_Ptr bb = Cast(ss)) + { Block_Obj bs = flatten(bb); - for (size_t j = 0, K = bs->length(); j < K; ++j) { + for (size_t j = 0, K = bs->length(); j < K; ++j) + { result->append(bs->at(j)); } } - else { + else + { result->append(ss); } } @@ -394,7 +382,8 @@ namespace Sass { { std::vector> results; - for (size_t i = 0, L = b->length(); i < L; ++i) { + for (size_t i = 0, L = b->length(); i < L; ++i) + { Statement_Obj value = b->at(i); bool key = Cast(value) != NULL; @@ -419,18 +408,23 @@ namespace Sass { std::vector> baz = slice_by_bubble(children); Block_Obj result = SASS_MEMORY_NEW(Block, children->pstate()); - for (size_t i = 0, L = baz.size(); i < L; ++i) { + for (size_t i = 0, L = baz.size(); i < L; ++i) + { bool is_bubble = baz[i].first; Block_Obj slice = baz[i].second; - if (!is_bubble) { - if (!parent) { + if (!is_bubble) + { + if (!parent) + { result->append(slice); } - else if (previous_parent) { + else if (previous_parent) + { previous_parent->block()->concat(slice); } - else { + else + { previous_parent = Cast(SASS_MEMORY_COPY(parent)); previous_parent->block(slice); previous_parent->tabs(parent->tabs()); @@ -450,22 +444,18 @@ namespace Sass { Media_Block_Ptr m2 = NULL; if (parent) m1 = Cast(parent); if (node) m2 = Cast(node->node()); - if (!parent || - parent->statement_type() != Statement::MEDIA || + if (!parent || parent->statement_type() != Statement::MEDIA || node->node()->statement_type() != Statement::MEDIA || - (m1 && m2 && *m1->media_queries() == *m2->media_queries()) - ) + (m1 && m2 && *m1->media_queries() == *m2->media_queries())) { ss = node->node(); } else { - List_Obj mq = merge_media_queries( - Cast(node->node()), - Cast(parent) - ); + List_Obj mq = merge_media_queries(Cast(node->node()), Cast(parent)); if (!mq->length()) continue; - if (Media_Block* b = Cast(node->node())) { + if (Media_Block* b = Cast(node->node())) + { b->media_queries(mq); } ss = node->node(); @@ -476,25 +466,22 @@ namespace Sass { ss->tabs(ss->tabs() + node->tabs()); ss->group_end(node->group_end()); - Block_Obj bb = SASS_MEMORY_NEW(Block, - children->pstate(), - children->length(), - children->is_root()); + Block_Obj bb = SASS_MEMORY_NEW(Block, children->pstate(), children->length(), children->is_root()); bb->append(ss->perform(this)); - Block_Obj wrapper_block = SASS_MEMORY_NEW(Block, - children->pstate(), - children->length(), - children->is_root()); + Block_Obj wrapper_block = + SASS_MEMORY_NEW(Block, children->pstate(), children->length(), children->is_root()); Block_Ptr wrapper = flatten(bb); wrapper_block->append(wrapper); - if (wrapper->length()) { + if (wrapper->length()) + { previous_parent = NULL; } - if (wrapper_block) { + if (wrapper_block) + { result->append(wrapper_block); } } @@ -510,14 +497,18 @@ namespace Sass { void Cssize::append_block(Block_Ptr b, Block_Ptr cur) { - for (size_t i = 0, L = b->length(); i < L; ++i) { + for (size_t i = 0, L = b->length(); i < L; ++i) + { Statement_Obj ith = b->at(i)->perform(this); - if (Block_Ptr bb = Cast(ith)) { - for (size_t j = 0, K = bb->length(); j < K; ++j) { + if (Block_Ptr bb = Cast(ith)) + { + for (size_t j = 0, K = bb->length(); j < K; ++j) + { cur->append(bb->at(j)); } } - else if (ith) { + else if (ith) + { cur->append(ith); } } @@ -525,13 +516,13 @@ namespace Sass { List_Ptr Cssize::merge_media_queries(Media_Block_Ptr m1, Media_Block_Ptr m2) { - List_Ptr qq = SASS_MEMORY_NEW(List, - m1->media_queries()->pstate(), - m1->media_queries()->length(), - SASS_COMMA); + List_Ptr qq = + SASS_MEMORY_NEW(List, m1->media_queries()->pstate(), m1->media_queries()->length(), SASS_COMMA); - for (size_t i = 0, L = m1->media_queries()->length(); i < L; i++) { - for (size_t j = 0, K = m2->media_queries()->length(); j < K; j++) { + for (size_t i = 0, L = m1->media_queries()->length(); i < L; i++) + { + for (size_t j = 0, K = m2->media_queries()->length(); j < K; j++) + { Expression_Obj l1 = m1->media_queries()->at(i); Expression_Obj l2 = m2->media_queries()->at(j); Media_Query_Ptr mq1 = Cast(l1); @@ -560,35 +551,39 @@ namespace Sass { if (t1.empty()) t1 = t2; if (t2.empty()) t2 = t1; - if ((m1 == "not") ^ (m2 == "not")) { - if (t1 == t2) { + if ((m1 == "not") ^ (m2 == "not")) + { + if (t1 == t2) + { return 0; } type = m1 == "not" ? t2 : t1; mod = m1 == "not" ? m2 : m1; } - else if (m1 == "not" && m2 == "not") { - if (t1 != t2) { + else if (m1 == "not" && m2 == "not") + { + if (t1 != t2) + { return 0; } type = t1; mod = "not"; } - else if (t1 != t2) { + else if (t1 != t2) + { return 0; - } else { + } + else + { type = t1; mod = m1.empty() ? m2 : m1; } - Media_Query_Ptr mm = SASS_MEMORY_NEW(Media_Query, - mq1->pstate(), - 0, - mq1->length() + mq2->length(), - mod == "not", - mod == "only"); + Media_Query_Ptr mm = SASS_MEMORY_NEW(Media_Query, mq1->pstate(), 0, mq1->length() + mq2->length(), + mod == "not", mod == "only"); - if (!type.empty()) { + if (!type.empty()) + { mm->media_type(SASS_MEMORY_NEW(String_Quoted, mq1->pstate(), type)); } diff --git a/src/cssize.hpp b/src/cssize.hpp index 506b075f77..cc7a6b183c 100644 --- a/src/cssize.hpp +++ b/src/cssize.hpp @@ -6,22 +6,26 @@ #include "operation.hpp" #include "environment.hpp" -namespace Sass { +namespace Sass +{ struct Backtrace; - class Cssize : public Operation_CRTP { + class Cssize : public Operation_CRTP + { - Context& ctx; - std::vector block_stack; - std::vector p_stack; - Backtrace* backtrace; + Context& ctx; + std::vector block_stack; + std::vector p_stack; + Backtrace* backtrace; Statement_Ptr fallback_impl(AST_Node_Ptr n); - public: + public: Cssize(Context&, Backtrace*); - ~Cssize() { } + ~Cssize() + { + } Selector_List_Ptr selector(); @@ -66,12 +70,13 @@ namespace Sass { List_Ptr merge_media_queries(Media_Block_Ptr, Media_Block_Ptr); Media_Query_Ptr merge_media_query(Media_Query_Ptr, Media_Query_Ptr); - template - Statement_Ptr fallback(U x) { return fallback_impl(x); } + template Statement_Ptr fallback(U x) + { + return fallback_impl(x); + } void append_block(Block_Ptr, Block_Ptr); }; - } #endif diff --git a/src/debug.hpp b/src/debug.hpp index 43fe05e67e..4f9abc15f6 100644 --- a/src/debug.hpp +++ b/src/debug.hpp @@ -4,10 +4,11 @@ #include #ifndef UINT32_MAX - #define UINT32_MAX 0xffffffffU +#define UINT32_MAX 0xffffffffU #endif -enum dbg_lvl_t : uint32_t { +enum dbg_lvl_t : uint32_t +{ NONE = 0, TRIM = 1, CHUNKS = 2, @@ -28,9 +29,21 @@ const uint32_t debug_lvl = UINT32_MAX; const uint32_t debug_lvl = (DEBUG_LVL); #endif // DEBUG_LVL -#define DEBUG_PRINT(lvl, x) if((lvl) & debug_lvl) { std::cerr << x; } -#define DEBUG_PRINTLN(lvl, x) if((lvl) & debug_lvl) { std::cerr << x << std::endl; } -#define DEBUG_EXEC(lvl, x) if((lvl) & debug_lvl) { x; } +#define DEBUG_PRINT(lvl, x) \ + if ((lvl)&debug_lvl) \ + { \ + std::cerr << x; \ + } +#define DEBUG_PRINTLN(lvl, x) \ + if ((lvl)&debug_lvl) \ + { \ + std::cerr << x << std::endl; \ + } +#define DEBUG_EXEC(lvl, x) \ + if ((lvl)&debug_lvl) \ + { \ + x; \ + } #else // DEBUG diff --git a/src/debugger.hpp b/src/debugger.hpp index f90a7a4b74..936313df4e 100644 --- a/src/debugger.hpp +++ b/src/debugger.hpp @@ -10,39 +10,45 @@ using namespace Sass; inline void debug_ast(AST_Node_Ptr node, std::string ind = "", Env* env = 0); -inline void debug_ast(const AST_Node* node, std::string ind = "", Env* env = 0) { +inline void debug_ast(const AST_Node* node, std::string ind = "", Env* env = 0) +{ debug_ast(const_cast(node), ind, env); } inline void debug_sources_set(ComplexSelectorSet& set, std::string ind = "") { - if (ind == "") std::cerr << "#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; - for(auto const &pair : set) { + if (ind == "") + std::cerr << "#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; + for (auto const& pair : set) + { debug_ast(pair, ind + ""); // debug_ast(set[pair], ind + "first: "); } - if (ind == "") std::cerr << "#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; + if (ind == "") + std::cerr << "#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; } inline std::string str_replace(std::string str, const std::string& oldStr, const std::string& newStr) { size_t pos = 0; - while((pos = str.find(oldStr, pos)) != std::string::npos) + while ((pos = str.find(oldStr, pos)) != std::string::npos) { - str.replace(pos, oldStr.length(), newStr); - pos += newStr.length(); + str.replace(pos, oldStr.length(), newStr); + pos += newStr.length(); } return str; } -inline std::string prettyprint(const std::string& str) { +inline std::string prettyprint(const std::string& str) +{ std::string clean = str_replace(str, "\n", "\\n"); clean = str_replace(clean, " ", "\\t"); clean = str_replace(clean, "\r", "\\r"); return clean; } -inline std::string longToHex(long long t) { +inline std::string longToHex(long long t) +{ std::stringstream is; is << std::hex << t; return is.str(); @@ -53,13 +59,12 @@ inline std::string pstate_source_position(AST_Node_Ptr node) std::stringstream str; Position start(node->pstate()); Position end(start + node->pstate().offset); - str << (start.file == std::string::npos ? -1 : start.file) - << "@[" << start.line << ":" << start.column << "]" - << "-[" << end.line << ":" << end.column << "]"; + str << (start.file == std::string::npos ? -1 : start.file) << "@[" << start.line << ":" + << start.column << "]" + << "-[" << end.line << ":" << end.column << "]"; #ifdef DEBUG_SHARED_PTR - str << "x" << node->getRefCount() << "" - << " " << node->getDbgFile() - << "@" << node->getDbgLine(); + str << "x" << node->getRefCount() << "" + << " " << node->getDbgFile() << "@" << node->getDbgLine(); #endif return str.str(); } @@ -67,22 +72,27 @@ inline std::string pstate_source_position(AST_Node_Ptr node) inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) { if (node == 0) return; - if (ind == "") std::cerr << "####################################################################\n"; - if (Cast(node)) { + if (ind == "") + std::cerr << "####################################################################\n"; + if (Cast(node)) + { Bubble_Ptr bubble = Cast(node); std::cerr << ind << "Bubble " << bubble; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << bubble->tabs(); std::cerr << std::endl; debug_ast(bubble->node(), ind + " ", env); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Trace_Ptr trace = Cast(node); std::cerr << ind << "Trace " << trace; std::cerr << " (" << pstate_source_position(node) << ")" - << " [name:" << trace->name() << "]" - << std::endl; + << " [name:" << trace->name() << "]" << std::endl; debug_ast(trace->block(), ind + " ", env); - } else if (Cast(node)) { + } + else if (Cast(node)) + { At_Root_Block_Ptr root_block = Cast(node); std::cerr << ind << "At_Root_Block " << root_block; std::cerr << " (" << pstate_source_position(node) << ")"; @@ -90,283 +100,352 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) std::cerr << std::endl; debug_ast(root_block->expression(), ind + ":", env); debug_ast(root_block->block(), ind + " ", env); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Selector_List_Ptr selector = Cast(node); std::cerr << ind << "Selector_List " << selector; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " <" << selector->hash() << ">"; std::cerr << " [@media:" << selector->media_block() << "]"; - std::cerr << (selector->is_invisible() ? " [INVISIBLE]": " -"); - std::cerr << (selector->has_placeholder() ? " [PLACEHOLDER]": " -"); - std::cerr << (selector->is_optional() ? " [is_optional]": " -"); - std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -"); - std::cerr << (selector->has_line_break() ? " [line-break]": " -"); - std::cerr << (selector->has_line_feed() ? " [line-feed]": " -"); + std::cerr << (selector->is_invisible() ? " [INVISIBLE]" : " -"); + std::cerr << (selector->has_placeholder() ? " [PLACEHOLDER]" : " -"); + std::cerr << (selector->is_optional() ? " [is_optional]" : " -"); + std::cerr << (selector->has_parent_ref() ? " [has-parent]" : " -"); + std::cerr << (selector->has_line_break() ? " [line-break]" : " -"); + std::cerr << (selector->has_line_feed() ? " [line-feed]" : " -"); std::cerr << std::endl; debug_ast(selector->schema(), "#{} "); - for(const Complex_Selector_Obj& i : selector->elements()) { debug_ast(i, ind + " ", env); } - -// } else if (Cast(node)) { -// Expression_Ptr expression = Cast(node); -// std::cerr << ind << "Expression " << expression << " " << expression->concrete_type() << std::endl; + for (const Complex_Selector_Obj& i : selector->elements()) + { + debug_ast(i, ind + " ", env); + } - } else if (Cast(node)) { + // } else if (Cast(node)) { + // Expression_Ptr expression = Cast(node); + // std::cerr << ind << "Expression " << expression << " " << expression->concrete_type() << + // std::endl; + } + else if (Cast(node)) + { Parent_Selector_Ptr selector = Cast(node); std::cerr << ind << "Parent_Selector " << selector; -// if (selector->not_selector()) cerr << " [in_declaration]"; + // if (selector->not_selector()) cerr << " [in_declaration]"; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " <" << selector->hash() << ">"; std::cerr << " [" << (selector->is_real_parent_ref() ? "REAL" : "FAKE") << "]"; std::cerr << " <" << prettyprint(selector->pstate().token.ws_before()) << ">" << std::endl; -// debug_ast(selector->selector(), ind + "->", env); - - } else if (Cast(node)) { + // debug_ast(selector->selector(), ind + "->", env); + } + else if (Cast(node)) + { Complex_Selector_Ptr selector = Cast(node); - std::cerr << ind << "Complex_Selector " << selector - << " (" << pstate_source_position(node) << ")" - << " <" << selector->hash() << ">" - << " [length:" << longToHex(selector->length()) << "]" - << " [weight:" << longToHex(selector->specificity()) << "]" - << " [@media:" << selector->media_block() << "]" - << (selector->is_invisible() ? " [INVISIBLE]": " -") - << (selector->has_placeholder() ? " [PLACEHOLDER]": " -") - << (selector->is_optional() ? " [is_optional]": " -") - << (selector->has_parent_ref() ? " [has parent]": " -") - << (selector->has_line_feed() ? " [line-feed]": " -") - << (selector->has_line_break() ? " [line-break]": " -") - << " -- "; - std::string del; - switch (selector->combinator()) { - case Complex_Selector::PARENT_OF: del = ">"; break; - case Complex_Selector::PRECEDES: del = "~"; break; - case Complex_Selector::ADJACENT_TO: del = "+"; break; - case Complex_Selector::ANCESTOR_OF: del = " "; break; - case Complex_Selector::REFERENCE: del = "//"; break; - } - // if (del = "/") del += selector->reference()->perform(&to_string) + "/"; + std::cerr << ind << "Complex_Selector " << selector << " (" << pstate_source_position(node) << ")" + << " <" << selector->hash() << ">" + << " [length:" << longToHex(selector->length()) << "]" + << " [weight:" << longToHex(selector->specificity()) << "]" + << " [@media:" << selector->media_block() << "]" + << (selector->is_invisible() ? " [INVISIBLE]" : " -") + << (selector->has_placeholder() ? " [PLACEHOLDER]" : " -") + << (selector->is_optional() ? " [is_optional]" : " -") + << (selector->has_parent_ref() ? " [has parent]" : " -") + << (selector->has_line_feed() ? " [line-feed]" : " -") + << (selector->has_line_break() ? " [line-break]" : " -") << " -- "; + std::string del; + switch (selector->combinator()) + { + case Complex_Selector::PARENT_OF: + del = ">"; + break; + case Complex_Selector::PRECEDES: + del = "~"; + break; + case Complex_Selector::ADJACENT_TO: + del = "+"; + break; + case Complex_Selector::ANCESTOR_OF: + del = " "; + break; + case Complex_Selector::REFERENCE: + del = "//"; + break; + } + // if (del = "/") del += selector->reference()->perform(&to_string) + "/"; std::cerr << " <" << prettyprint(selector->pstate().token.ws_before()) << ">" << std::endl; debug_ast(selector->head(), ind + " " /* + "[" + del + "]" */, env); - if (selector->tail()) { + if (selector->tail()) + { debug_ast(selector->tail(), ind + "{" + del + "}", env); - } else if(del != " ") { + } + else if (del != " ") + { std::cerr << ind << " |" << del << "| {trailing op}" << std::endl; } ComplexSelectorSet set = selector->sources(); // debug_sources_set(set, ind + " @--> "); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Compound_Selector_Ptr selector = Cast(node); std::cerr << ind << "Compound_Selector " << selector; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " <" << selector->hash() << ">"; std::cerr << " [weight:" << longToHex(selector->specificity()) << "]"; std::cerr << " [@media:" << selector->media_block() << "]"; - std::cerr << (selector->extended() ? " [extended]": " -"); - std::cerr << (selector->is_optional() ? " [is_optional]": " -"); - std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -"); - std::cerr << (selector->has_line_break() ? " [line-break]": " -"); - std::cerr << (selector->has_line_feed() ? " [line-feed]": " -"); + std::cerr << (selector->extended() ? " [extended]" : " -"); + std::cerr << (selector->is_optional() ? " [is_optional]" : " -"); + std::cerr << (selector->has_parent_ref() ? " [has-parent]" : " -"); + std::cerr << (selector->has_line_break() ? " [line-break]" : " -"); + std::cerr << (selector->has_line_feed() ? " [line-feed]" : " -"); std::cerr << " <" << prettyprint(selector->pstate().token.ws_before()) << ">" << std::endl; - for(const Simple_Selector_Obj& i : selector->elements()) { debug_ast(i, ind + " ", env); } - } else if (Cast(node)) { + for (const Simple_Selector_Obj& i : selector->elements()) + { + debug_ast(i, ind + " ", env); + } + } + else if (Cast(node)) + { Wrapped_Selector_Ptr selector = Cast(node); std::cerr << ind << "Wrapped_Selector " << selector; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " <" << selector->hash() << ">"; std::cerr << " <<" << selector->ns_name() << ">>"; - std::cerr << (selector->is_optional() ? " [is_optional]": " -"); - std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -"); - std::cerr << (selector->has_line_break() ? " [line-break]": " -"); - std::cerr << (selector->has_line_feed() ? " [line-feed]": " -"); + std::cerr << (selector->is_optional() ? " [is_optional]" : " -"); + std::cerr << (selector->has_parent_ref() ? " [has-parent]" : " -"); + std::cerr << (selector->has_line_break() ? " [line-break]" : " -"); + std::cerr << (selector->has_line_feed() ? " [line-feed]" : " -"); std::cerr << std::endl; debug_ast(selector->selector(), ind + " () ", env); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Pseudo_Selector_Ptr selector = Cast(node); std::cerr << ind << "Pseudo_Selector " << selector; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " <" << selector->hash() << ">"; std::cerr << " <<" << selector->ns_name() << ">>"; - std::cerr << (selector->is_optional() ? " [is_optional]": " -"); - std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -"); - std::cerr << (selector->has_line_break() ? " [line-break]": " -"); - std::cerr << (selector->has_line_feed() ? " [line-feed]": " -"); + std::cerr << (selector->is_optional() ? " [is_optional]" : " -"); + std::cerr << (selector->has_parent_ref() ? " [has-parent]" : " -"); + std::cerr << (selector->has_line_break() ? " [line-break]" : " -"); + std::cerr << (selector->has_line_feed() ? " [line-feed]" : " -"); std::cerr << std::endl; debug_ast(selector->expression(), ind + " <= ", env); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Attribute_Selector_Ptr selector = Cast(node); std::cerr << ind << "Attribute_Selector " << selector; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " <" << selector->hash() << ">"; std::cerr << " <<" << selector->ns_name() << ">>"; - std::cerr << (selector->is_optional() ? " [is_optional]": " -"); - std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -"); - std::cerr << (selector->has_line_break() ? " [line-break]": " -"); - std::cerr << (selector->has_line_feed() ? " [line-feed]": " -"); + std::cerr << (selector->is_optional() ? " [is_optional]" : " -"); + std::cerr << (selector->has_parent_ref() ? " [has-parent]" : " -"); + std::cerr << (selector->has_line_break() ? " [line-break]" : " -"); + std::cerr << (selector->has_line_feed() ? " [line-feed]" : " -"); std::cerr << std::endl; debug_ast(selector->value(), ind + "[" + selector->matcher() + "] ", env); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Class_Selector_Ptr selector = Cast(node); std::cerr << ind << "Class_Selector " << selector; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " <" << selector->hash() << ">"; std::cerr << " <<" << selector->ns_name() << ">>"; - std::cerr << (selector->is_optional() ? " [is_optional]": " -"); - std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -"); - std::cerr << (selector->has_line_break() ? " [line-break]": " -"); - std::cerr << (selector->has_line_feed() ? " [line-feed]": " -"); + std::cerr << (selector->is_optional() ? " [is_optional]" : " -"); + std::cerr << (selector->has_parent_ref() ? " [has-parent]" : " -"); + std::cerr << (selector->has_line_break() ? " [line-break]" : " -"); + std::cerr << (selector->has_line_feed() ? " [line-feed]" : " -"); std::cerr << std::endl; - } else if (Cast(node)) { + } + else if (Cast(node)) + { Id_Selector_Ptr selector = Cast(node); std::cerr << ind << "Id_Selector " << selector; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " <" << selector->hash() << ">"; std::cerr << " <<" << selector->ns_name() << ">>"; - std::cerr << (selector->is_optional() ? " [is_optional]": " -"); - std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -"); - std::cerr << (selector->has_line_break() ? " [line-break]": " -"); - std::cerr << (selector->has_line_feed() ? " [line-feed]": " -"); + std::cerr << (selector->is_optional() ? " [is_optional]" : " -"); + std::cerr << (selector->has_parent_ref() ? " [has-parent]" : " -"); + std::cerr << (selector->has_line_break() ? " [line-break]" : " -"); + std::cerr << (selector->has_line_feed() ? " [line-feed]" : " -"); std::cerr << std::endl; - } else if (Cast(node)) { + } + else if (Cast(node)) + { Element_Selector_Ptr selector = Cast(node); std::cerr << ind << "Element_Selector " << selector; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " <" << selector->hash() << ">"; std::cerr << " <<" << selector->ns_name() << ">>"; - std::cerr << (selector->is_optional() ? " [is_optional]": " -"); - std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -"); - std::cerr << (selector->has_line_break() ? " [line-break]": " -"); - std::cerr << (selector->has_line_feed() ? " [line-feed]": " -"); + std::cerr << (selector->is_optional() ? " [is_optional]" : " -"); + std::cerr << (selector->has_parent_ref() ? " [has-parent]" : " -"); + std::cerr << (selector->has_line_break() ? " [line-break]" : " -"); + std::cerr << (selector->has_line_feed() ? " [line-feed]" : " -"); std::cerr << " <" << prettyprint(selector->pstate().token.ws_before()) << ">"; std::cerr << std::endl; - } else if (Cast(node)) { + } + else if (Cast(node)) + { Placeholder_Selector_Ptr selector = Cast(node); std::cerr << ind << "Placeholder_Selector [" << selector->ns_name() << "] " << selector; std::cerr << " (" << pstate_source_position(selector) << ")" - << " <" << selector->hash() << ">" - << " [@media:" << selector->media_block() << "]" - << (selector->is_optional() ? " [is_optional]": " -") - << (selector->has_line_break() ? " [line-break]": " -") - << (selector->has_line_feed() ? " [line-feed]": " -") - << std::endl; - - } else if (Cast(node)) { + << " <" << selector->hash() << ">" + << " [@media:" << selector->media_block() << "]" + << (selector->is_optional() ? " [is_optional]" : " -") + << (selector->has_line_break() ? " [line-break]" : " -") + << (selector->has_line_feed() ? " [line-feed]" : " -") << std::endl; + } + else if (Cast(node)) + { Simple_Selector* selector = Cast(node); std::cerr << ind << "Simple_Selector " << selector; std::cerr << " (" << pstate_source_position(node) << ")"; - std::cerr << (selector->has_line_break() ? " [line-break]": " -") << (selector->has_line_feed() ? " [line-feed]": " -") << std::endl; - - } else if (Cast(node)) { + std::cerr << (selector->has_line_break() ? " [line-break]" : " -") + << (selector->has_line_feed() ? " [line-feed]" : " -") << std::endl; + } + else if (Cast(node)) + { Selector_Schema_Ptr selector = Cast(node); std::cerr << ind << "Selector_Schema " << selector; std::cerr << " (" << pstate_source_position(node) << ")" - << " [@media:" << selector->media_block() << "]" - << (selector->connect_parent() ? " [connect-parent]": " -") - << std::endl; + << " [@media:" << selector->media_block() << "]" + << (selector->connect_parent() ? " [connect-parent]" : " -") << std::endl; debug_ast(selector->contents(), ind + " "); // for(auto i : selector->elements()) { debug_ast(i, ind + " ", env); } - - } else if (Cast(node)) { + } + else if (Cast(node)) + { Selector_Ptr selector = Cast(node); std::cerr << ind << "Selector " << selector; std::cerr << " (" << pstate_source_position(node) << ")"; - std::cerr << (selector->has_line_break() ? " [line-break]": " -") - << (selector->has_line_feed() ? " [line-feed]": " -") - << std::endl; - - } else if (Cast(node)) { + std::cerr << (selector->has_line_break() ? " [line-break]" : " -") + << (selector->has_line_feed() ? " [line-feed]" : " -") << std::endl; + } + else if (Cast(node)) + { Media_Query_Expression_Ptr block = Cast(node); std::cerr << ind << "Media_Query_Expression " << block; std::cerr << " (" << pstate_source_position(node) << ")"; - std::cerr << (block->is_interpolated() ? " [is_interpolated]": " -") - << std::endl; + std::cerr << (block->is_interpolated() ? " [is_interpolated]" : " -") << std::endl; debug_ast(block->feature(), ind + " feature) "); debug_ast(block->value(), ind + " value) "); - - } else if (Cast(node)) { + } + else if (Cast(node)) + { Media_Query_Ptr block = Cast(node); std::cerr << ind << "Media_Query " << block; std::cerr << " (" << pstate_source_position(node) << ")"; - std::cerr << (block->is_negated() ? " [is_negated]": " -") - << (block->is_restricted() ? " [is_restricted]": " -") - << std::endl; + std::cerr << (block->is_negated() ? " [is_negated]" : " -") + << (block->is_restricted() ? " [is_restricted]" : " -") << std::endl; debug_ast(block->media_type(), ind + " "); - for(const auto& i : block->elements()) { debug_ast(i, ind + " ", env); } - - } else if (Cast(node)) { + for (const auto& i : block->elements()) + { + debug_ast(i, ind + " ", env); + } + } + else if (Cast(node)) + { Media_Block_Ptr block = Cast(node); std::cerr << ind << "Media_Block " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; debug_ast(block->media_queries(), ind + " =@ "); - if (block->block()) for(const Statement_Obj& i : block->block()->elements()) { debug_ast(i, ind + " ", env); } - } else if (Cast(node)) { + if (block->block()) + for (const Statement_Obj& i : block->block()->elements()) + { + debug_ast(i, ind + " ", env); + } + } + else if (Cast(node)) + { Supports_Block_Ptr block = Cast(node); std::cerr << ind << "Supports_Block " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; debug_ast(block->condition(), ind + " =@ "); debug_ast(block->block(), ind + " <>"); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Supports_Operator_Ptr block = Cast(node); std::cerr << ind << "Supports_Operator " << block; - std::cerr << " (" << pstate_source_position(node) << ")" - << std::endl; + std::cerr << " (" << pstate_source_position(node) << ")" << std::endl; debug_ast(block->left(), ind + " left) "); debug_ast(block->right(), ind + " right) "); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Supports_Negation_Ptr block = Cast(node); std::cerr << ind << "Supports_Negation " << block; - std::cerr << " (" << pstate_source_position(node) << ")" - << std::endl; + std::cerr << " (" << pstate_source_position(node) << ")" << std::endl; debug_ast(block->condition(), ind + " condition) "); - } else if (Cast(node)) { + } + else if (Cast(node)) + { At_Root_Query_Ptr block = Cast(node); std::cerr << ind << "At_Root_Query " << block; - std::cerr << " (" << pstate_source_position(node) << ")" - << std::endl; + std::cerr << " (" << pstate_source_position(node) << ")" << std::endl; debug_ast(block->feature(), ind + " feature) "); debug_ast(block->value(), ind + " value) "); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Supports_Declaration_Ptr block = Cast(node); std::cerr << ind << "Supports_Declaration " << block; - std::cerr << " (" << pstate_source_position(node) << ")" - << std::endl; + std::cerr << " (" << pstate_source_position(node) << ")" << std::endl; debug_ast(block->feature(), ind + " feature) "); debug_ast(block->value(), ind + " value) "); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Block_Ptr root_block = Cast(node); std::cerr << ind << "Block " << root_block; std::cerr << " (" << pstate_source_position(node) << ")"; if (root_block->is_root()) std::cerr << " [root]"; std::cerr << " " << root_block->tabs() << std::endl; - for(const Statement_Obj& i : root_block->elements()) { debug_ast(i, ind + " ", env); } - } else if (Cast(node)) { + for (const Statement_Obj& i : root_block->elements()) + { + debug_ast(i, ind + " ", env); + } + } + else if (Cast(node)) + { Warning_Ptr block = Cast(node); std::cerr << ind << "Warning " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; debug_ast(block->message(), ind + " : "); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Error_Ptr block = Cast(node); std::cerr << ind << "Error " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; - } else if (Cast(node)) { + } + else if (Cast(node)) + { Debug_Ptr block = Cast(node); std::cerr << ind << "Debug " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; debug_ast(block->value(), ind + " "); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Comment_Ptr block = Cast(node); std::cerr << ind << "Comment " << block; std::cerr << " (" << pstate_source_position(node) << ")"; - std::cerr << " " << block->tabs() << - " <" << prettyprint(block->pstate().token.ws_before()) << ">" << std::endl; + std::cerr << " " << block->tabs() << " <" << prettyprint(block->pstate().token.ws_before()) + << ">" << std::endl; debug_ast(block->text(), ind + "// ", env); - } else if (Cast(node)) { + } + else if (Cast(node)) + { If_Ptr block = Cast(node); std::cerr << ind << "If " << block; std::cerr << " (" << pstate_source_position(node) << ")"; @@ -374,44 +453,59 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) debug_ast(block->predicate(), ind + " = "); debug_ast(block->block(), ind + " <>"); debug_ast(block->alternative(), ind + " ><"); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Return_Ptr block = Cast(node); std::cerr << ind << "Return " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; - } else if (Cast(node)) { + } + else if (Cast(node)) + { Extension_Ptr block = Cast(node); std::cerr << ind << "Extension " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; debug_ast(block->selector(), ind + "-> ", env); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Content_Ptr block = Cast(node); std::cerr << ind << "Content " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [@media:" << block->media_block() << "]"; std::cerr << " " << block->tabs() << std::endl; - } else if (Cast(node)) { + } + else if (Cast(node)) + { Import_Stub_Ptr block = Cast(node); std::cerr << ind << "Import_Stub " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [" << block->imp_path() << "] "; std::cerr << " " << block->tabs() << std::endl; - } else if (Cast(node)) { + } + else if (Cast(node)) + { Import_Ptr block = Cast(node); std::cerr << ind << "Import " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; // std::vector files_; - for (auto imp : block->urls()) debug_ast(imp, ind + "@: ", env); + for (auto imp : block->urls()) + debug_ast(imp, ind + "@: ", env); debug_ast(block->import_queries(), ind + "@@ "); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Assignment_Ptr block = Cast(node); std::cerr << ind << "Assignment " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " <<" << block->variable() << ">> " << block->tabs() << std::endl; debug_ast(block->value(), ind + "=", env); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Declaration_Ptr block = Cast(node); std::cerr << ind << "Declaration " << block; std::cerr << " (" << pstate_source_position(node) << ")"; @@ -419,60 +513,97 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) debug_ast(block->property(), ind + " prop: ", env); debug_ast(block->value(), ind + " value: ", env); debug_ast(block->block(), ind + " ", env); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Keyframe_Rule_Ptr has_block = Cast(node); std::cerr << ind << "Keyframe_Rule " << has_block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << has_block->tabs() << std::endl; if (has_block->name()) debug_ast(has_block->name(), ind + "@"); - if (has_block->block()) for(const Statement_Obj& i : has_block->block()->elements()) { debug_ast(i, ind + " ", env); } - } else if (Cast(node)) { + if (has_block->block()) + for (const Statement_Obj& i : has_block->block()->elements()) + { + debug_ast(i, ind + " ", env); + } + } + else if (Cast(node)) + { Directive_Ptr block = Cast(node); std::cerr << ind << "Directive " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [" << block->keyword() << "] " << block->tabs() << std::endl; debug_ast(block->selector(), ind + "~", env); debug_ast(block->value(), ind + "+", env); - if (block->block()) for(const Statement_Obj& i : block->block()->elements()) { debug_ast(i, ind + " ", env); } - } else if (Cast(node)) { + if (block->block()) + for (const Statement_Obj& i : block->block()->elements()) + { + debug_ast(i, ind + " ", env); + } + } + else if (Cast(node)) + { Each_Ptr block = Cast(node); std::cerr << ind << "Each " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; - if (block->block()) for(const Statement_Obj& i : block->block()->elements()) { debug_ast(i, ind + " ", env); } - } else if (Cast(node)) { + if (block->block()) + for (const Statement_Obj& i : block->block()->elements()) + { + debug_ast(i, ind + " ", env); + } + } + else if (Cast(node)) + { For_Ptr block = Cast(node); std::cerr << ind << "For " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; - if (block->block()) for(const Statement_Obj& i : block->block()->elements()) { debug_ast(i, ind + " ", env); } - } else if (Cast(node)) { + if (block->block()) + for (const Statement_Obj& i : block->block()->elements()) + { + debug_ast(i, ind + " ", env); + } + } + else if (Cast(node)) + { While_Ptr block = Cast(node); std::cerr << ind << "While " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; - if (block->block()) for(const Statement_Obj& i : block->block()->elements()) { debug_ast(i, ind + " ", env); } - } else if (Cast(node)) { + if (block->block()) + for (const Statement_Obj& i : block->block()->elements()) + { + debug_ast(i, ind + " ", env); + } + } + else if (Cast(node)) + { Definition_Ptr block = Cast(node); std::cerr << ind << "Definition " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [name: " << block->name() << "] "; - std::cerr << " [type: " << (block->type() == Sass::Definition::Type::MIXIN ? "Mixin " : "Function ") << "] "; + std::cerr + << " [type: " << (block->type() == Sass::Definition::Type::MIXIN ? "Mixin " : "Function ") << "] "; // this seems to lead to segfaults some times? // std::cerr << " [signature: " << block->signature() << "] "; std::cerr << " [native: " << block->native_function() << "] "; std::cerr << " " << block->tabs() << std::endl; debug_ast(block->parameters(), ind + " params: ", env); if (block->block()) debug_ast(block->block(), ind + " ", env); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Mixin_Call_Ptr block = Cast(node); std::cerr << ind << "Mixin_Call " << block << " " << block->tabs(); std::cerr << " (" << pstate_source_position(block) << ")"; - std::cerr << " [" << block->name() << "]"; + std::cerr << " [" << block->name() << "]"; std::cerr << " [has_content: " << block->has_content() << "] " << std::endl; debug_ast(block->arguments(), ind + " args: "); if (block->block()) debug_ast(block->block(), ind + " ", env); - } else if (Ruleset_Ptr ruleset = Cast(node)) { + } + else if (Ruleset_Ptr ruleset = Cast(node)) + { std::cerr << ind << "Ruleset " << ruleset; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [indent: " << ruleset->tabs() << "]"; @@ -481,14 +612,21 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) std::cerr << std::endl; debug_ast(ruleset->selector(), ind + ">"); debug_ast(ruleset->block(), ind + " "); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Block_Ptr block = Cast(node); std::cerr << ind << "Block " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << (block->is_invisible() ? " [INVISIBLE]" : ""); std::cerr << " [indent: " << block->tabs() << "]" << std::endl; - for(const Statement_Obj& i : block->elements()) { debug_ast(i, ind + " ", env); } - } else if (Cast(node)) { + for (const Statement_Obj& i : block->elements()) + { + debug_ast(i, ind + " ", env); + } + } + else if (Cast(node)) + { Variable_Ptr expression = Cast(node); std::cerr << ind << "Variable " << expression; std::cerr << " [interpolant: " << expression->is_interpolant() << "] "; @@ -496,7 +634,9 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) std::cerr << " [" << expression->name() << "]" << std::endl; std::string name(expression->name()); if (env && env->has(name)) debug_ast(Cast((*env)[name]), ind + " -> ", env); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Function_Call_Schema_Ptr expression = Cast(node); std::cerr << ind << "Function_Call_Schema " << expression; std::cerr << " [interpolant: " << expression->is_interpolant() << "] "; @@ -504,7 +644,9 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) std::cerr << "" << std::endl; debug_ast(expression->name(), ind + "name: ", env); debug_ast(expression->arguments(), ind + " args: ", env); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Function_Call_Ptr expression = Cast(node); std::cerr << ind << "Function_Call " << expression; std::cerr << " [interpolant: " << expression->is_interpolant() << "] "; @@ -514,7 +656,9 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) if (expression->is_interpolant()) std::cerr << " [interpolant]"; std::cerr << std::endl; debug_ast(expression->arguments(), ind + " args: ", env); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Arguments_Ptr expression = Cast(node); std::cerr << ind << "Arguments " << expression; if (expression->is_delayed()) std::cerr << " [delayed]"; @@ -523,8 +667,13 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) if (expression->has_rest_argument()) std::cerr << " [has_rest_argument]"; if (expression->has_keyword_argument()) std::cerr << " [has_keyword_argument]"; std::cerr << std::endl; - for(const Argument_Obj& i : expression->elements()) { debug_ast(i, ind + " ", env); } - } else if (Cast(node)) { + for (const Argument_Obj& i : expression->elements()) + { + debug_ast(i, ind + " ", env); + } + } + else if (Cast(node)) + { Argument_Ptr expression = Cast(node); std::cerr << ind << "Argument " << expression; std::cerr << " (" << pstate_source_position(node) << ")"; @@ -533,22 +682,31 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) std::cerr << " [rest: " << expression->is_rest_argument() << "] "; std::cerr << " [keyword: " << expression->is_keyword_argument() << "] " << std::endl; debug_ast(expression->value(), ind + " value: ", env); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Parameters_Ptr expression = Cast(node); std::cerr << ind << "Parameters " << expression; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [has_optional: " << expression->has_optional_parameters() << "] "; std::cerr << " [has_rest: " << expression->has_rest_parameter() << "] "; std::cerr << std::endl; - for(const Parameter_Obj& i : expression->elements()) { debug_ast(i, ind + " ", env); } - } else if (Cast(node)) { + for (const Parameter_Obj& i : expression->elements()) + { + debug_ast(i, ind + " ", env); + } + } + else if (Cast(node)) + { Parameter_Ptr expression = Cast(node); std::cerr << ind << "Parameter " << expression; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [name: " << expression->name() << "] "; std::cerr << " [default: " << expression->default_value().ptr() << "] "; std::cerr << " [rest: " << expression->is_rest_parameter() << "] " << std::endl; - } else if (Cast(node)) { + } + else if (Cast(node)) + { Unary_Expression_Ptr expression = Cast(node); std::cerr << ind << "Unary_Expression " << expression; std::cerr << " [interpolant: " << expression->is_interpolant() << "] "; @@ -556,7 +714,9 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [" << expression->type() << "]" << std::endl; debug_ast(expression->operand(), ind + " operand: ", env); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Binary_Expression_Ptr expression = Cast(node); std::cerr << ind << "Binary_Expression " << expression; if (expression->is_interpolant()) std::cerr << " [is interpolant] "; @@ -569,66 +729,86 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) std::cerr << " [" << expression->type_name() << "]" << std::endl; debug_ast(expression->left(), ind + " left: ", env); debug_ast(expression->right(), ind + " right: ", env); - } else if (Cast(node)) { + } + else if (Cast(node)) + { Map_Ptr expression = Cast(node); std::cerr << ind << "Map " << expression; std::cerr << " [interpolant: " << expression->is_interpolant() << "] "; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [Hashed]" << std::endl; - for (const auto& i : expression->elements()) { + for (const auto& i : expression->elements()) + { debug_ast(i.first, ind + " key: "); debug_ast(i.second, ind + " val: "); } - } else if (Cast(node)) { + } + else if (Cast(node)) + { List_Ptr expression = Cast(node); std::cerr << ind << "List " << expression; std::cerr << " (" << pstate_source_position(node) << ")"; - std::cerr << " (" << expression->length() << ") " << - (expression->separator() == SASS_COMMA ? "Comma " : expression->separator() == SASS_HASH ? "Map " : "Space ") << - " [delayed: " << expression->is_delayed() << "] " << - " [interpolant: " << expression->is_interpolant() << "] " << - " [listized: " << expression->from_selector() << "] " << - " [arglist: " << expression->is_arglist() << "] " << - " [bracketed: " << expression->is_bracketed() << "] " << - " [expanded: " << expression->is_expanded() << "] " << - " [hash: " << expression->hash() << "] " << - std::endl; - for(const auto& i : expression->elements()) { debug_ast(i, ind + " ", env); } - } else if (Cast(node)) { + std::cerr + << " (" << expression->length() << ") " + << (expression->separator() == SASS_COMMA ? "Comma " : expression->separator() == SASS_HASH ? "Map " : "Space ") + << " [delayed: " << expression->is_delayed() << "] " + << " [interpolant: " << expression->is_interpolant() << "] " + << " [listized: " << expression->from_selector() << "] " + << " [arglist: " << expression->is_arglist() << "] " + << " [bracketed: " << expression->is_bracketed() << "] " + << " [expanded: " << expression->is_expanded() << "] " + << " [hash: " << expression->hash() << "] " << std::endl; + for (const auto& i : expression->elements()) + { + debug_ast(i, ind + " ", env); + } + } + else if (Cast(node)) + { Content_Ptr expression = Cast(node); std::cerr << ind << "Content " << expression; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [@media:" << expression->media_block() << "]"; std::cerr << " [Statement]" << std::endl; - } else if (Cast(node)) { + } + else if (Cast(node)) + { Boolean_Ptr expression = Cast(node); std::cerr << ind << "Boolean " << expression; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [interpolant: " << expression->is_interpolant() << "] "; std::cerr << " [" << expression->value() << "]" << std::endl; - } else if (Cast(node)) { + } + else if (Cast(node)) + { Color_Ptr expression = Cast(node); std::cerr << ind << "Color " << expression; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [delayed: " << expression->is_delayed() << "] "; std::cerr << " [interpolant: " << expression->is_interpolant() << "] "; - std::cerr << " [" << expression->r() << ":" << expression->g() << ":" << expression->b() << "@" << expression->a() << "]" << std::endl; - } else if (Cast(node)) { + std::cerr << " [" << expression->r() << ":" << expression->g() << ":" << expression->b() << "@" + << expression->a() << "]" << std::endl; + } + else if (Cast(node)) + { Number_Ptr expression = Cast(node); std::cerr << ind << "Number " << expression; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [interpolant: " << expression->is_interpolant() << "] "; - std::cerr << " [" << expression->value() << expression->unit() << "]" << - " [hash: " << expression->hash() << "] " << - std::endl; - } else if (Cast(node)) { + std::cerr << " [" << expression->value() << expression->unit() << "]" + << " [hash: " << expression->hash() << "] " << std::endl; + } + else if (Cast(node)) + { Null_Ptr expression = Cast(node); std::cerr << ind << "Null " << expression; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [interpolant: " << expression->is_interpolant() << "] " - // " [hash: " << expression->hash() << "] " - << std::endl; - } else if (Cast(node)) { + // " [hash: " << expression->hash() << "] " + << std::endl; + } + else if (Cast(node)) + { String_Quoted_Ptr expression = Cast(node); std::cerr << ind << "String_Quoted " << expression; std::cerr << " (" << pstate_source_position(node) << ")"; @@ -637,10 +817,13 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) if (expression->is_interpolant()) std::cerr << " [interpolant]"; if (expression->quote_mark()) std::cerr << " [quote_mark: " << expression->quote_mark() << "]"; std::cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << std::endl; - } else if (Cast(node)) { + } + else if (Cast(node)) + { String_Constant_Ptr expression = Cast(node); std::cerr << ind << "String_Constant " << expression; - if (expression->concrete_type()) { + if (expression->concrete_type()) + { std::cerr << " " << expression->concrete_type(); } std::cerr << " (" << pstate_source_position(node) << ")"; @@ -648,7 +831,9 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) if (expression->is_delayed()) std::cerr << " [delayed]"; if (expression->is_interpolant()) std::cerr << " [interpolant]"; std::cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << std::endl; - } else if (Cast(node)) { + } + else if (Cast(node)) + { String_Schema_Ptr expression = Cast(node); std::cerr << ind << "String_Schema " << expression; std::cerr << " (" << pstate_source_position(expression) << ")"; @@ -660,97 +845,163 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) if (expression->is_left_interpolant()) std::cerr << " [left interpolant] "; if (expression->is_right_interpolant()) std::cerr << " [right interpolant] "; std::cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << std::endl; - for(const auto& i : expression->elements()) { debug_ast(i, ind + " ", env); } - } else if (Cast(node)) { + for (const auto& i : expression->elements()) + { + debug_ast(i, ind + " ", env); + } + } + else if (Cast(node)) + { String_Ptr expression = Cast(node); std::cerr << ind << "String " << expression; std::cerr << " " << expression->concrete_type(); std::cerr << " (" << pstate_source_position(node) << ")"; if (expression->is_interpolant()) std::cerr << " [interpolant]"; std::cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << std::endl; - } else if (Cast(node)) { + } + else if (Cast(node)) + { Expression_Ptr expression = Cast(node); std::cerr << ind << "Expression " << expression; std::cerr << " (" << pstate_source_position(node) << ")"; - switch (expression->concrete_type()) { - case Expression::Concrete_Type::NONE: std::cerr << " [NONE]"; break; - case Expression::Concrete_Type::BOOLEAN: std::cerr << " [BOOLEAN]"; break; - case Expression::Concrete_Type::NUMBER: std::cerr << " [NUMBER]"; break; - case Expression::Concrete_Type::COLOR: std::cerr << " [COLOR]"; break; - case Expression::Concrete_Type::STRING: std::cerr << " [STRING]"; break; - case Expression::Concrete_Type::LIST: std::cerr << " [LIST]"; break; - case Expression::Concrete_Type::MAP: std::cerr << " [MAP]"; break; - case Expression::Concrete_Type::SELECTOR: std::cerr << " [SELECTOR]"; break; - case Expression::Concrete_Type::NULL_VAL: std::cerr << " [NULL_VAL]"; break; - case Expression::Concrete_Type::C_WARNING: std::cerr << " [C_WARNING]"; break; - case Expression::Concrete_Type::C_ERROR: std::cerr << " [C_ERROR]"; break; - case Expression::Concrete_Type::FUNCTION: std::cerr << " [FUNCTION]"; break; - case Expression::Concrete_Type::NUM_TYPES: std::cerr << " [NUM_TYPES]"; break; + switch (expression->concrete_type()) + { + case Expression::Concrete_Type::NONE: + std::cerr << " [NONE]"; + break; + case Expression::Concrete_Type::BOOLEAN: + std::cerr << " [BOOLEAN]"; + break; + case Expression::Concrete_Type::NUMBER: + std::cerr << " [NUMBER]"; + break; + case Expression::Concrete_Type::COLOR: + std::cerr << " [COLOR]"; + break; + case Expression::Concrete_Type::STRING: + std::cerr << " [STRING]"; + break; + case Expression::Concrete_Type::LIST: + std::cerr << " [LIST]"; + break; + case Expression::Concrete_Type::MAP: + std::cerr << " [MAP]"; + break; + case Expression::Concrete_Type::SELECTOR: + std::cerr << " [SELECTOR]"; + break; + case Expression::Concrete_Type::NULL_VAL: + std::cerr << " [NULL_VAL]"; + break; + case Expression::Concrete_Type::C_WARNING: + std::cerr << " [C_WARNING]"; + break; + case Expression::Concrete_Type::C_ERROR: + std::cerr << " [C_ERROR]"; + break; + case Expression::Concrete_Type::FUNCTION: + std::cerr << " [FUNCTION]"; + break; + case Expression::Concrete_Type::NUM_TYPES: + std::cerr << " [NUM_TYPES]"; + break; } std::cerr << std::endl; - } else if (Cast(node)) { + } + else if (Cast(node)) + { Has_Block_Ptr has_block = Cast(node); std::cerr << ind << "Has_Block " << has_block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << has_block->tabs() << std::endl; - if (has_block->block()) for(const Statement_Obj& i : has_block->block()->elements()) { debug_ast(i, ind + " ", env); } - } else if (Cast(node)) { + if (has_block->block()) + for (const Statement_Obj& i : has_block->block()->elements()) + { + debug_ast(i, ind + " ", env); + } + } + else if (Cast(node)) + { Statement_Ptr statement = Cast(node); std::cerr << ind << "Statement " << statement; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << statement->tabs() << std::endl; } - if (ind == "") std::cerr << "####################################################################\n"; + if (ind == "") + std::cerr << "####################################################################\n"; } inline void debug_node(Node* node, std::string ind = "") { - if (ind == "") std::cerr << "#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - if (node->isCombinator()) { + if (ind == "") + std::cerr << "#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; + if (node->isCombinator()) + { std::cerr << ind; std::cerr << "Combinator "; std::cerr << node << " "; if (node->got_line_feed) std::cerr << "[LF] "; - switch (node->combinator()) { - case Complex_Selector::ADJACENT_TO: std::cerr << "{+} "; break; - case Complex_Selector::PARENT_OF: std::cerr << "{>} "; break; - case Complex_Selector::PRECEDES: std::cerr << "{~} "; break; - case Complex_Selector::REFERENCE: std::cerr << "{@} "; break; - case Complex_Selector::ANCESTOR_OF: std::cerr << "{ } "; break; + switch (node->combinator()) + { + case Complex_Selector::ADJACENT_TO: + std::cerr << "{+} "; + break; + case Complex_Selector::PARENT_OF: + std::cerr << "{>} "; + break; + case Complex_Selector::PRECEDES: + std::cerr << "{~} "; + break; + case Complex_Selector::REFERENCE: + std::cerr << "{@} "; + break; + case Complex_Selector::ANCESTOR_OF: + std::cerr << "{ } "; + break; } std::cerr << std::endl; // debug_ast(node->combinator(), ind + " "); - } else if (node->isSelector()) { + } + else if (node->isSelector()) + { std::cerr << ind; std::cerr << "Selector "; std::cerr << node << " "; if (node->got_line_feed) std::cerr << "[LF] "; std::cerr << std::endl; debug_ast(node->selector(), ind + " "); - } else if (node->isCollection()) { + } + else if (node->isCollection()) + { std::cerr << ind; std::cerr << "Collection "; std::cerr << node << " "; if (node->got_line_feed) std::cerr << "[LF] "; std::cerr << std::endl; - for(auto n : (*node->collection())) { + for (auto n : (*node->collection())) + { debug_node(&n, ind + " "); } - } else if (node->isNil()) { + } + else if (node->isNil()) + { std::cerr << ind; std::cerr << "Nil "; std::cerr << node << " "; if (node->got_line_feed) std::cerr << "[LF] "; std::cerr << std::endl; - } else { + } + else + { std::cerr << ind; std::cerr << "OTHER "; std::cerr << node << " "; if (node->got_line_feed) std::cerr << "[LF] "; std::cerr << std::endl; } - if (ind == "") std::cerr << "#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; + if (ind == "") + std::cerr << "#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; } /* @@ -766,22 +1017,28 @@ inline void debug_node(const Node* node, std::string ind = "") inline void debug_subset_map(Sass::Subset_Map& map, std::string ind = "") { - if (ind == "") std::cerr << "#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; - for(auto const &it : map.values()) { + if (ind == "") + std::cerr << "#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; + for (auto const& it : map.values()) + { debug_ast(it.first, ind + "first: "); debug_ast(it.second, ind + "second: "); } - if (ind == "") std::cerr << "#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; + if (ind == "") + std::cerr << "#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; } inline void debug_subset_entries(SubSetMapPairs* entries, std::string ind = "") { - if (ind == "") std::cerr << "#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; - for(auto const &pair : *entries) { + if (ind == "") + std::cerr << "#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; + for (auto const& pair : *entries) + { debug_ast(pair.first, ind + "first: "); debug_ast(pair.second, ind + "second: "); } - if (ind == "") std::cerr << "#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; + if (ind == "") + std::cerr << "#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; } #endif // SASS_DEBUGGER diff --git a/src/emitter.cpp b/src/emitter.cpp index f315b840b2..35947f0094 100644 --- a/src/emitter.cpp +++ b/src/emitter.cpp @@ -5,23 +5,15 @@ #include "emitter.hpp" #include "utf8_string.hpp" -namespace Sass { +namespace Sass +{ Emitter::Emitter(struct Sass_Output_Options& opt) - : wbuf(), - opt(opt), - indentation(0), - scheduled_space(0), - scheduled_linefeed(0), - scheduled_delimiter(false), - scheduled_mapping(0), - in_comment(false), - in_wrapped(false), - in_media_block(false), - in_declaration(false), - in_space_array(false), - in_comma_array(false) - { } + : wbuf(), opt(opt), indentation(0), scheduled_space(0), scheduled_linefeed(0), + scheduled_delimiter(false), scheduled_mapping(0), in_comment(false), in_wrapped(false), + in_media_block(false), in_declaration(false), in_space_array(false), in_comma_array(false) + { + } // return buffer as string std::string Emitter::get_buffer(void) @@ -37,22 +29,36 @@ namespace Sass { // PROXY METHODS FOR SOURCE MAPS void Emitter::add_source_index(size_t idx) - { wbuf.smap.source_index.push_back(idx); } + { + wbuf.smap.source_index.push_back(idx); + } - std::string Emitter::render_srcmap(Context &ctx) - { return wbuf.smap.render_srcmap(ctx); } + std::string Emitter::render_srcmap(Context& ctx) + { + return wbuf.smap.render_srcmap(ctx); + } void Emitter::set_filename(const std::string& str) - { wbuf.smap.file = str; } + { + wbuf.smap.file = str; + } void Emitter::schedule_mapping(const AST_Node_Ptr node) - { scheduled_mapping = node; } + { + scheduled_mapping = node; + } void Emitter::add_open_mapping(const AST_Node_Ptr node) - { wbuf.smap.add_open_mapping(node); } + { + wbuf.smap.add_open_mapping(node); + } void Emitter::add_close_mapping(const AST_Node_Ptr node) - { wbuf.smap.add_close_mapping(node); } + { + wbuf.smap.add_close_mapping(node); + } ParserState Emitter::remap(const ParserState& pstate) - { return wbuf.smap.remap(pstate); } + { + return wbuf.smap.remap(pstate); + } // MAIN BUFFER MANIPULATION @@ -62,8 +68,7 @@ namespace Sass { scheduled_space = 0; if (output_style() == SASS_STYLE_COMPRESSED) if (final) scheduled_delimiter = false; - if (scheduled_linefeed) - scheduled_linefeed = 1; + if (scheduled_linefeed) scheduled_linefeed = 1; flush_schedules(); } @@ -71,7 +76,8 @@ namespace Sass { void Emitter::flush_schedules(void) { // check the schedule - if (scheduled_linefeed) { + if (scheduled_linefeed) + { std::string linefeeds = ""; for (size_t i = 0; i < scheduled_linefeed; i++) @@ -79,13 +85,15 @@ namespace Sass { scheduled_space = 0; scheduled_linefeed = 0; append_string(linefeeds); - - } else if (scheduled_space) { + } + else if (scheduled_space) + { std::string spaces(scheduled_space, ' '); scheduled_space = 0; append_string(spaces); } - if (scheduled_delimiter) { + if (scheduled_delimiter) + { scheduled_delimiter = false; append_string(";"); } @@ -112,14 +120,17 @@ namespace Sass { // write space/lf flush_schedules(); - if (in_comment && output_style() == COMPACT) { + if (in_comment && output_style() == COMPACT) + { // unescape comment nodes std::string out = comment_to_string(text); // add to buffer wbuf.buffer += out; // account for data in source-maps wbuf.smap.append(Offset(out)); - } else { + } + else + { // add to buffer wbuf.buffer += text; // account for data in source-maps @@ -131,7 +142,8 @@ namespace Sass { void Emitter::append_wspace(const std::string& text) { if (text.empty()) return; - if (peek_linefeed(text.c_str())) { + if (peek_linefeed(text.c_str())) + { scheduled_space = 0; append_mandatory_linefeed(); } @@ -145,7 +157,8 @@ namespace Sass { add_open_mapping(node); // hotfix for browser issues // this is pretty ugly indeed - if (scheduled_mapping) { + if (scheduled_mapping) + { add_open_mapping(scheduled_mapping); scheduled_mapping = 0; } @@ -160,8 +173,7 @@ namespace Sass { if (output_style() == COMPRESSED) return; if (output_style() == COMPACT) return; if (in_declaration && in_comma_array) return; - if (scheduled_linefeed && indentation) - scheduled_linefeed = 1; + if (scheduled_linefeed && indentation) scheduled_linefeed = 1; std::string indent = ""; for (size_t i = 0; i < indentation; i++) indent += opt.indent; @@ -171,13 +183,19 @@ namespace Sass { void Emitter::append_delimiter() { scheduled_delimiter = true; - if (output_style() == COMPACT) { - if (indentation == 0) { + if (output_style() == COMPACT) + { + if (indentation == 0) + { append_mandatory_linefeed(); - } else { + } + else + { append_mandatory_space(); } - } else if (output_style() != COMPRESSED) { + } + else if (output_style() != COMPRESSED) + { append_optional_linefeed(); } } @@ -203,9 +221,11 @@ namespace Sass { void Emitter::append_optional_space() { - if ((output_style() != COMPRESSED) && buffer().size()) { + if ((output_style() != COMPRESSED) && buffer().size()) + { unsigned char lst = buffer().at(buffer().length() - 1); - if (!isspace(lst) || scheduled_delimiter) { + if (!isspace(lst) || scheduled_delimiter) + { append_mandatory_space(); } } @@ -213,7 +233,8 @@ namespace Sass { void Emitter::append_special_linefeed() { - if (output_style() == COMPACT) { + if (output_style() == COMPACT) + { append_mandatory_linefeed(); for (size_t p = 0; p < indentation; p++) append_string(opt.indent); @@ -223,16 +244,20 @@ namespace Sass { void Emitter::append_optional_linefeed() { if (in_declaration && in_comma_array) return; - if (output_style() == COMPACT) { + if (output_style() == COMPACT) + { append_mandatory_space(); - } else { + } + else + { append_mandatory_linefeed(); } } void Emitter::append_mandatory_linefeed() { - if (output_style() != COMPRESSED) { + if (output_style() != COMPRESSED) + { scheduled_linefeed = 1; scheduled_space = 0; // flush_schedules(); @@ -248,26 +273,26 @@ namespace Sass { append_string("{"); append_optional_linefeed(); // append_optional_space(); - ++ indentation; + ++indentation; } void Emitter::append_scope_closer(AST_Node_Ptr node) { - -- indentation; + --indentation; scheduled_linefeed = 0; - if (output_style() == COMPRESSED) - scheduled_delimiter = false; - if (output_style() == EXPANDED) { + if (output_style() == COMPRESSED) scheduled_delimiter = false; + if (output_style() == EXPANDED) + { append_optional_linefeed(); append_indentation(); - } else { + } + else + { append_optional_space(); } append_string("}"); if (node) add_close_mapping(node); append_optional_linefeed(); if (indentation != 0) return; - if (output_style() != COMPRESSED) - scheduled_linefeed = 2; + if (output_style() != COMPRESSED) scheduled_linefeed = 2; } - } diff --git a/src/emitter.hpp b/src/emitter.hpp index 94b2a08bd2..019f786976 100644 --- a/src/emitter.hpp +++ b/src/emitter.hpp @@ -7,86 +7,98 @@ #include "source_map.hpp" #include "ast_fwd_decl.hpp" -namespace Sass { +namespace Sass +{ class Context; - class Emitter { + class Emitter + { public: - Emitter(struct Sass_Output_Options& opt); - virtual ~Emitter() { } + Emitter(struct Sass_Output_Options& opt); + virtual ~Emitter() + { + } protected: - OutputBuffer wbuf; + OutputBuffer wbuf; + public: - const std::string& buffer(void) { return wbuf.buffer; } - const SourceMap smap(void) { return wbuf.smap; } - const OutputBuffer output(void) { return wbuf; } - // proxy methods for source maps - void add_source_index(size_t idx); - void set_filename(const std::string& str); - void add_open_mapping(const AST_Node_Ptr node); - void add_close_mapping(const AST_Node_Ptr node); - void schedule_mapping(const AST_Node_Ptr node); - std::string render_srcmap(Context &ctx); - ParserState remap(const ParserState& pstate); + const std::string& buffer(void) + { + return wbuf.buffer; + } + const SourceMap smap(void) + { + return wbuf.smap; + } + const OutputBuffer output(void) + { + return wbuf; + } + // proxy methods for source maps + void add_source_index(size_t idx); + void set_filename(const std::string& str); + void add_open_mapping(const AST_Node_Ptr node); + void add_close_mapping(const AST_Node_Ptr node); + void schedule_mapping(const AST_Node_Ptr node); + std::string render_srcmap(Context& ctx); + ParserState remap(const ParserState& pstate); public: - struct Sass_Output_Options& opt; - size_t indentation; - size_t scheduled_space; - size_t scheduled_linefeed; - bool scheduled_delimiter; - AST_Node_Ptr scheduled_mapping; + struct Sass_Output_Options& opt; + size_t indentation; + size_t scheduled_space; + size_t scheduled_linefeed; + bool scheduled_delimiter; + AST_Node_Ptr scheduled_mapping; public: - // output strings different in comments - bool in_comment; - // selector list does not get linefeeds - bool in_wrapped; - // lists always get a space after delimiter - bool in_media_block; - // nested list must not have parentheses - bool in_declaration; - // nested lists need parentheses - bool in_space_array; - bool in_comma_array; + // output strings different in comments + bool in_comment; + // selector list does not get linefeeds + bool in_wrapped; + // lists always get a space after delimiter + bool in_media_block; + // nested list must not have parentheses + bool in_declaration; + // nested lists need parentheses + bool in_space_array; + bool in_comma_array; public: - // return buffer as std::string - std::string get_buffer(void); - // flush scheduled space/linefeed - Sass_Output_Style output_style(void) const; - // add outstanding linefeed - void finalize(bool final = true); - // flush scheduled space/linefeed - void flush_schedules(void); - // prepend some text or token to the buffer - void prepend_string(const std::string& text); - void prepend_output(const OutputBuffer& out); - // append some text or token to the buffer - void append_string(const std::string& text); - // append some white-space only text - void append_wspace(const std::string& text); - // append some text or token to the buffer - // this adds source-mappings for node start and end - void append_token(const std::string& text, const AST_Node_Ptr node); + // return buffer as std::string + std::string get_buffer(void); + // flush scheduled space/linefeed + Sass_Output_Style output_style(void) const; + // add outstanding linefeed + void finalize(bool final = true); + // flush scheduled space/linefeed + void flush_schedules(void); + // prepend some text or token to the buffer + void prepend_string(const std::string& text); + void prepend_output(const OutputBuffer& out); + // append some text or token to the buffer + void append_string(const std::string& text); + // append some white-space only text + void append_wspace(const std::string& text); + // append some text or token to the buffer + // this adds source-mappings for node start and end + void append_token(const std::string& text, const AST_Node_Ptr node); public: // syntax sugar - void append_indentation(); - void append_optional_space(void); - void append_mandatory_space(void); - void append_special_linefeed(void); - void append_optional_linefeed(void); - void append_mandatory_linefeed(void); - void append_scope_opener(AST_Node_Ptr node = 0); - void append_scope_closer(AST_Node_Ptr node = 0); - void append_comma_separator(void); - void append_colon_separator(void); - void append_delimiter(void); - + void append_indentation(); + void append_optional_space(void); + void append_mandatory_space(void); + void append_special_linefeed(void); + void append_optional_linefeed(void); + void append_mandatory_linefeed(void); + void append_scope_opener(AST_Node_Ptr node = 0); + void append_scope_closer(AST_Node_Ptr node = 0); + void append_comma_separator(void); + void append_colon_separator(void); + void append_delimiter(void); }; - } #endif diff --git a/src/environment.cpp b/src/environment.cpp index 46420cd5ae..efb9bc456d 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -2,123 +2,128 @@ #include "ast.hpp" #include "environment.hpp" -namespace Sass { +namespace Sass +{ template Environment::Environment(bool is_shadow) - : local_frame_(environment_map()), - parent_(0), is_shadow_(false) - { } + : local_frame_(environment_map()), parent_(0), is_shadow_(false) + { + } template Environment::Environment(Environment* env, bool is_shadow) - : local_frame_(environment_map()), - parent_(env), is_shadow_(is_shadow) - { } + : local_frame_(environment_map()), parent_(env), is_shadow_(is_shadow) + { + } template Environment::Environment(Environment& env, bool is_shadow) - : local_frame_(environment_map()), - parent_(&env), is_shadow_(is_shadow) - { } + : local_frame_(environment_map()), parent_(&env), is_shadow_(is_shadow) + { + } // link parent to create a stack - template - void Environment::link(Environment& env) { parent_ = &env; } - template - void Environment::link(Environment* env) { parent_ = env; } + template void Environment::link(Environment& env) + { + parent_ = &env; + } + template void Environment::link(Environment* env) + { + parent_ = env; + } // this is used to find the global frame // which is the second last on the stack - template - bool Environment::is_lexical() const + template bool Environment::is_lexical() const { - return !! parent_ && parent_->parent_; + return !!parent_ && parent_->parent_; } // only match the real root scope // there is still a parent around // not sure what it is actually use for // I guess we store functions etc. there - template - bool Environment::is_global() const + template bool Environment::is_global() const { - return parent_ && ! parent_->parent_; + return parent_ && !parent_->parent_; } - template - environment_map& Environment::local_frame() { + template environment_map& Environment::local_frame() + { return local_frame_; } - template - bool Environment::has_local(const std::string& key) const - { return local_frame_.find(key) != local_frame_.end(); } + template bool Environment::has_local(const std::string& key) const + { + return local_frame_.find(key) != local_frame_.end(); + } - template EnvResult - Environment::find_local(const std::string& key) + template EnvResult Environment::find_local(const std::string& key) { auto end = local_frame_.end(); auto it = local_frame_.find(key); return EnvResult(it, it != end); } - template - T& Environment::get_local(const std::string& key) - { return local_frame_[key]; } + template T& Environment::get_local(const std::string& key) + { + return local_frame_[key]; + } - template - void Environment::set_local(const std::string& key, const T& val) + template void Environment::set_local(const std::string& key, const T& val) { local_frame_[key] = val; } - template - void Environment::set_local(const std::string& key, T&& val) + template void Environment::set_local(const std::string& key, T&& val) { local_frame_[key] = val; } - template - void Environment::del_local(const std::string& key) - { local_frame_.erase(key); } + template void Environment::del_local(const std::string& key) + { + local_frame_.erase(key); + } - template - Environment* Environment::global_env() + template Environment* Environment::global_env() { Environment* cur = this; - while (cur->is_lexical()) { + while (cur->is_lexical()) + { cur = cur->parent_; } return cur; } - template - bool Environment::has_global(const std::string& key) - { return global_env()->has(key); } + template bool Environment::has_global(const std::string& key) + { + return global_env()->has(key); + } - template - T& Environment::get_global(const std::string& key) - { return (*global_env())[key]; } + template T& Environment::get_global(const std::string& key) + { + return (*global_env())[key]; + } - template - void Environment::set_global(const std::string& key, const T& val) + template void Environment::set_global(const std::string& key, const T& val) { global_env()->local_frame_[key] = val; } - template - void Environment::set_global(const std::string& key, T&& val) + template void Environment::set_global(const std::string& key, T&& val) { global_env()->local_frame_[key] = val; } - template - void Environment::del_global(const std::string& key) - { global_env()->local_frame_.erase(key); } + template void Environment::del_global(const std::string& key) + { + global_env()->local_frame_.erase(key); + } - template - Environment* Environment::lexical_env(const std::string& key) + template Environment* Environment::lexical_env(const std::string& key) { Environment* cur = this; - while (cur) { - if (cur->has_local(key)) { + while (cur) + { + if (cur->has_local(key)) + { return cur; } cur = cur->parent_; @@ -129,11 +134,11 @@ namespace Sass { // see if we have a lexical variable // move down the stack but stop before we // reach the global frame (is not included) - template - bool Environment::has_lexical(const std::string& key) const + template bool Environment::has_lexical(const std::string& key) const { auto cur = this; - while (cur->is_lexical()) { + while (cur->is_lexical()) + { if (cur->has_local(key)) return true; cur = cur->parent_; } @@ -143,14 +148,15 @@ namespace Sass { // see if we have a lexical we could update // either update already existing lexical value // or if flag is set, we create one if no lexical found - template - void Environment::set_lexical(const std::string& key, const T& val) + template void Environment::set_lexical(const std::string& key, const T& val) { Environment* cur = this; bool shadow = false; - while ((cur && cur->is_lexical()) || shadow) { + while ((cur && cur->is_lexical()) || shadow) + { EnvResult rv(cur->find_local(key)); - if (rv.found) { + if (rv.found) + { rv.it->second = val; return; } @@ -160,14 +166,15 @@ namespace Sass { set_local(key, val); } // this one moves the value - template - void Environment::set_lexical(const std::string& key, T&& val) + template void Environment::set_lexical(const std::string& key, T&& val) { Environment* cur = this; bool shadow = false; - while ((cur && cur->is_lexical()) || shadow) { + while ((cur && cur->is_lexical()) || shadow) + { EnvResult rv(cur->find_local(key)); - if (rv.found) { + if (rv.found) + { rv.it->second = val; return; } @@ -179,12 +186,13 @@ namespace Sass { // look on the full stack for key // include all scopes available - template - bool Environment::has(const std::string& key) const + template bool Environment::has(const std::string& key) const { auto cur = this; - while (cur) { - if (cur->has_local(key)) { + while (cur) + { + if (cur->has_local(key)) + { return true; } cur = cur->parent_; @@ -194,11 +202,11 @@ namespace Sass { // look on the full stack for key // include all scopes available - template EnvResult - Environment::find(const std::string& key) + template EnvResult Environment::find(const std::string& key) { auto cur = this; - while (true) { + while (true) + { EnvResult rv(cur->find_local(key)); if (rv.found) return rv; cur = cur->parent_; @@ -207,12 +215,13 @@ namespace Sass { }; // use array access for getter and setter functions - template - T& Environment::operator[](const std::string& key) + template T& Environment::operator[](const std::string& key) { auto cur = this; - while (cur) { - if (cur->has_local(key)) { + while (cur) + { + if (cur->has_local(key)) + { return cur->get_local(key); } cur = cur->parent_; @@ -220,27 +229,30 @@ namespace Sass { return get_local(key); } - #ifdef DEBUG - template - size_t Environment::print(std::string prefix) +#ifdef DEBUG + template size_t Environment::print(std::string prefix) { size_t indent = 0; if (parent_) indent = parent_->print(prefix) + 1; std::cerr << prefix << std::string(indent, ' ') << "== " << this << std::endl; - for (typename environment_map::iterator i = local_frame_.begin(); i != local_frame_.end(); ++i) { - if (!ends_with(i->first, "[f]") && !ends_with(i->first, "[f]4") && !ends_with(i->first, "[f]2")) { + for (typename environment_map::iterator i = local_frame_.begin(); + i != local_frame_.end(); ++i) + { + if (!ends_with(i->first, "[f]") && !ends_with(i->first, "[f]4") && + !ends_with(i->first, "[f]2")) + { std::cerr << prefix << std::string(indent, ' ') << i->first << " " << i->second; if (Value_Ptr val = Cast(i->second)) - { std::cerr << " : " << val->to_string(); } + { + std::cerr << " : " << val->to_string(); + } std::cerr << std::endl; } } - return indent ; + return indent; } - #endif +#endif // compile implementation for AST_Node template class Environment; - } - diff --git a/src/environment.hpp b/src/environment.hpp index a6939be238..0e6fbe739e 100644 --- a/src/environment.hpp +++ b/src/environment.hpp @@ -5,27 +5,31 @@ #include "ast_fwd_decl.hpp" #include "ast_def_macros.hpp" -namespace Sass { +namespace Sass +{ typedef environment_map::iterator EnvIter; - class EnvResult { + class EnvResult + { public: - EnvIter it; - bool found; + EnvIter it; + bool found; + public: - EnvResult(EnvIter it, bool found) - : it(it), found(found) {} + EnvResult(EnvIter it, bool found) : it(it), found(found) + { + } }; - template - class Environment { + template class Environment + { // TODO: test with map environment_map local_frame_; ADD_PROPERTY(Environment*, parent) ADD_PROPERTY(bool, is_shadow) - public: + public: Environment(bool is_shadow = false); Environment(Environment* env, bool is_shadow = false); Environment(Environment& env, bool is_shadow = false); @@ -99,15 +103,13 @@ namespace Sass { // use array access for getter and setter functions T& operator[](const std::string& key); - #ifdef DEBUG +#ifdef DEBUG size_t print(std::string prefix = ""); - #endif - +#endif }; // define typedef for our use case typedef Environment Env; - } #endif diff --git a/src/error_handling.cpp b/src/error_handling.cpp index a27f64b0d1..c49dae574b 100644 --- a/src/error_handling.cpp +++ b/src/error_handling.cpp @@ -6,19 +6,20 @@ #include -namespace Sass { +namespace Sass +{ - namespace Exception { + namespace Exception + { Base::Base(ParserState pstate, std::string msg, std::vector* import_stack) - : std::runtime_error(msg), msg(msg), - prefix("Error"), pstate(pstate), - import_stack(import_stack) - { } + : std::runtime_error(msg), msg(msg), prefix("Error"), pstate(pstate), import_stack(import_stack) + { + } - InvalidSass::InvalidSass(ParserState pstate, std::string msg) - : Base(pstate, msg) - { } + InvalidSass::InvalidSass(ParserState pstate, std::string msg) : Base(pstate, msg) + { + } InvalidParent::InvalidParent(Selector_Ptr parent, Selector_Ptr selector) @@ -34,7 +35,7 @@ namespace Sass { InvalidArgumentType::InvalidArgumentType(ParserState pstate, std::string fn, std::string arg, std::string type, const Value_Ptr value) : Base(pstate), fn(fn), arg(arg), type(type), value(value) { - msg = arg + ": \""; + msg = arg + ": \""; if (value) msg += value->to_string(Sass_Inspect_Options()); msg += "\" is not a " + type; msg += " for `" + fn + "'"; @@ -43,19 +44,20 @@ namespace Sass { MissingArgument::MissingArgument(ParserState pstate, std::string fn, std::string arg, std::string fntype) : Base(pstate), fn(fn), arg(arg), fntype(fntype) { - msg = fntype + " " + fn; + msg = fntype + " " + fn; msg += " is missing argument "; msg += arg + "."; } InvalidSyntax::InvalidSyntax(ParserState pstate, std::string msg, std::vector* import_stack) : Base(pstate, msg, import_stack) - { } + { + } UndefinedOperation::UndefinedOperation(Expression_Ptr_Const lhs, Expression_Ptr_Const rhs, const std::string& op) : lhs(lhs), rhs(rhs), op(op) { - msg = def_op_msg + ": \""; + msg = def_op_msg + ": \""; msg += lhs->to_string({ NESTED, 5 }); msg += " " + op + " "; msg += rhs->to_string({ TO_SASS, 5 }); @@ -65,7 +67,7 @@ namespace Sass { InvalidNullOperation::InvalidNullOperation(Expression_Ptr_Const lhs, Expression_Ptr_Const rhs, const std::string& op) : UndefinedOperation(lhs, rhs, op) { - msg = def_op_null_msg + ": \""; + msg = def_op_null_msg + ": \""; msg += lhs->inspect(); msg += " " + op + " "; msg += rhs->inspect(); @@ -75,13 +77,13 @@ namespace Sass { ZeroDivisionError::ZeroDivisionError(const Expression& lhs, const Expression& rhs) : lhs(lhs), rhs(rhs) { - msg = "divided by 0"; + msg = "divided by 0"; } DuplicateKeyError::DuplicateKeyError(const Map& dup, const Expression& org) : Base(org.pstate()), dup(dup), org(org) { - msg = "Duplicate key "; + msg = "Duplicate key "; msg += dup.get_duplicate_key()->inspect(); msg += " in map ("; msg += org.inspect(); @@ -91,28 +93,26 @@ namespace Sass { TypeMismatch::TypeMismatch(const Expression& var, const std::string type) : Base(var.pstate()), var(var), type(type) { - msg = var.to_string(); + msg = var.to_string(); msg += " is not an "; msg += type; msg += "."; } - InvalidValue::InvalidValue(const Expression& val) - : Base(val.pstate()), val(val) + InvalidValue::InvalidValue(const Expression& val) : Base(val.pstate()), val(val) { - msg = val.to_string(); + msg = val.to_string(); msg += " isn't a valid CSS value."; } - StackError::StackError(const AST_Node& node) - : Base(node.pstate()), node(node) + StackError::StackError(const AST_Node& node) : Base(node.pstate()), node(node) { - msg = "stack level too deep"; + msg = "stack level too deep"; } IncompatibleUnits::IncompatibleUnits(const Number& lhs, const Number& rhs) { - msg = "Incompatible units: '"; + msg = "Incompatible units: '"; msg += rhs.unit(); msg += "' and '"; msg += lhs.unit(); @@ -121,17 +121,19 @@ namespace Sass { IncompatibleUnits::IncompatibleUnits(const UnitType lhs, const UnitType rhs) { - msg = "Incompatible units: '"; + msg = "Incompatible units: '"; msg += unit_to_string(rhs); msg += "' and '"; msg += unit_to_string(lhs); msg += "'."; } - AlphaChannelsNotEqual::AlphaChannelsNotEqual(Expression_Ptr_Const lhs, Expression_Ptr_Const rhs, const std::string& op) + AlphaChannelsNotEqual::AlphaChannelsNotEqual(Expression_Ptr_Const lhs, + Expression_Ptr_Const rhs, + const std::string& op) : lhs(lhs), rhs(rhs), op(op) { - msg = "Alpha channels must be equal: "; + msg = "Alpha channels must be equal: "; msg += lhs->to_string({ NESTED, 5 }); msg += " " + op + " "; msg += rhs->to_string({ NESTED, 5 }); @@ -145,13 +147,12 @@ namespace Sass { msg = err.what(); prefix = err.errtype(); } - } void warn(std::string msg, ParserState pstate) { - std::cerr << "Warning: " << msg<< std::endl; + std::cerr << "Warning: " << msg << std::endl; } void warn(std::string msg, ParserState pstate, Backtrace* bt) @@ -170,7 +171,7 @@ namespace Sass { std::cerr << "DEPRECATION WARNING: " << msg << std::endl; std::cerr << "will be an error in future versions of Sass." << std::endl; - std::cerr << " on line " << pstate.line+1 << " of " << output_path << std::endl; + std::cerr << " on line " << pstate.line + 1 << " of " << output_path << std::endl; } void deprecated(std::string msg, std::string msg2, ParserState pstate) @@ -196,7 +197,7 @@ namespace Sass { std::string output_path(Sass::File::path_for_console(rel_path, abs_path, pstate.path)); std::cerr << "WARNING: " << msg << std::endl; - std::cerr << " on line " << pstate.line+1 << " of " << output_path << std::endl; + std::cerr << " on line " << pstate.line + 1 << " of " << output_path << std::endl; std::cerr << "This will be an error in future versions of Sass." << std::endl; } @@ -211,5 +212,4 @@ namespace Sass { msg += "\n" + top.to_string(); error(msg, pstate); } - } diff --git a/src/error_handling.hpp b/src/error_handling.hpp index e6d4e5ce6d..0c1d356af7 100644 --- a/src/error_handling.hpp +++ b/src/error_handling.hpp @@ -8,178 +8,235 @@ #include "ast_fwd_decl.hpp" #include "sass/functions.h" -namespace Sass { +namespace Sass +{ struct Backtrace; - namespace Exception { + namespace Exception + { const std::string def_msg = "Invalid sass detected"; const std::string def_op_msg = "Undefined operation"; const std::string def_op_null_msg = "Invalid null operation"; - class Base : public std::runtime_error { + class Base : public std::runtime_error + { protected: - std::string msg; - std::string prefix; + std::string msg; + std::string prefix; + public: - ParserState pstate; - std::vector* import_stack; + ParserState pstate; + std::vector* import_stack; + public: - Base(ParserState pstate, std::string msg = def_msg, std::vector* import_stack = 0); - virtual const char* errtype() const { return prefix.c_str(); } - virtual const char* what() const throw() { return msg.c_str(); } - virtual ~Base() throw() {}; + Base(ParserState pstate, std::string msg = def_msg, std::vector* import_stack = 0); + virtual const char* errtype() const + { + return prefix.c_str(); + } + virtual const char* what() const throw() + { + return msg.c_str(); + } + virtual ~Base() throw(){}; }; - class InvalidSass : public Base { + class InvalidSass : public Base + { public: - InvalidSass(ParserState pstate, std::string msg); - virtual ~InvalidSass() throw() {}; + InvalidSass(ParserState pstate, std::string msg); + virtual ~InvalidSass() throw(){}; }; - class InvalidParent : public Base { + class InvalidParent : public Base + { protected: - Selector_Ptr parent; - Selector_Ptr selector; + Selector_Ptr parent; + Selector_Ptr selector; + public: - InvalidParent(Selector_Ptr parent, Selector_Ptr selector); - virtual ~InvalidParent() throw() {}; + InvalidParent(Selector_Ptr parent, Selector_Ptr selector); + virtual ~InvalidParent() throw(){}; }; - class MissingArgument : public Base { + class MissingArgument : public Base + { protected: - std::string fn; - std::string arg; - std::string fntype; + std::string fn; + std::string arg; + std::string fntype; + public: - MissingArgument(ParserState pstate, std::string fn, std::string arg, std::string fntype); - virtual ~MissingArgument() throw() {}; + MissingArgument(ParserState pstate, std::string fn, std::string arg, std::string fntype); + virtual ~MissingArgument() throw(){}; }; - class InvalidArgumentType : public Base { + class InvalidArgumentType : public Base + { protected: - std::string fn; - std::string arg; - std::string type; - const Value_Ptr value; + std::string fn; + std::string arg; + std::string type; + const Value_Ptr value; + public: - InvalidArgumentType(ParserState pstate, std::string fn, std::string arg, std::string type, const Value_Ptr value = 0); - virtual ~InvalidArgumentType() throw() {}; + InvalidArgumentType(ParserState pstate, std::string fn, std::string arg, std::string type, const Value_Ptr value = 0); + virtual ~InvalidArgumentType() throw(){}; }; - class InvalidSyntax : public Base { + class InvalidSyntax : public Base + { public: - InvalidSyntax(ParserState pstate, std::string msg, std::vector* import_stack = 0); - virtual ~InvalidSyntax() throw() {}; + InvalidSyntax(ParserState pstate, std::string msg, std::vector* import_stack = 0); + virtual ~InvalidSyntax() throw(){}; }; /* common virtual base class (has no pstate) */ - class OperationError : public std::runtime_error { + class OperationError : public std::runtime_error + { protected: - std::string msg; + std::string msg; + public: - OperationError(std::string msg = def_op_msg) - : std::runtime_error(msg), msg(msg) - {}; + OperationError(std::string msg = def_op_msg) : std::runtime_error(msg), msg(msg){}; + public: - virtual const char* errtype() const { return "Error"; } - virtual const char* what() const throw() { return msg.c_str(); } - virtual ~OperationError() throw() {}; + virtual const char* errtype() const + { + return "Error"; + } + virtual const char* what() const throw() + { + return msg.c_str(); + } + virtual ~OperationError() throw(){}; }; - class ZeroDivisionError : public OperationError { + class ZeroDivisionError : public OperationError + { protected: - const Expression& lhs; - const Expression& rhs; + const Expression& lhs; + const Expression& rhs; + public: - ZeroDivisionError(const Expression& lhs, const Expression& rhs); - virtual const char* errtype() const { return "ZeroDivisionError"; } - virtual ~ZeroDivisionError() throw() {}; + ZeroDivisionError(const Expression& lhs, const Expression& rhs); + virtual const char* errtype() const + { + return "ZeroDivisionError"; + } + virtual ~ZeroDivisionError() throw(){}; }; - class DuplicateKeyError : public Base { + class DuplicateKeyError : public Base + { protected: - const Map& dup; - const Expression& org; + const Map& dup; + const Expression& org; + public: - DuplicateKeyError(const Map& dup, const Expression& org); - virtual const char* errtype() const { return "Error"; } - virtual ~DuplicateKeyError() throw() {}; + DuplicateKeyError(const Map& dup, const Expression& org); + virtual const char* errtype() const + { + return "Error"; + } + virtual ~DuplicateKeyError() throw(){}; }; - class TypeMismatch : public Base { + class TypeMismatch : public Base + { protected: - const Expression& var; - const std::string type; + const Expression& var; + const std::string type; + public: - TypeMismatch(const Expression& var, const std::string type); - virtual const char* errtype() const { return "Error"; } - virtual ~TypeMismatch() throw() {}; + TypeMismatch(const Expression& var, const std::string type); + virtual const char* errtype() const + { + return "Error"; + } + virtual ~TypeMismatch() throw(){}; }; - class InvalidValue : public Base { + class InvalidValue : public Base + { protected: - const Expression& val; + const Expression& val; + public: - InvalidValue(const Expression& val); - virtual const char* errtype() const { return "Error"; } - virtual ~InvalidValue() throw() {}; + InvalidValue(const Expression& val); + virtual const char* errtype() const + { + return "Error"; + } + virtual ~InvalidValue() throw(){}; }; - class StackError : public Base { + class StackError : public Base + { protected: - const AST_Node& node; + const AST_Node& node; + public: - StackError(const AST_Node& node); - virtual const char* errtype() const { return "SystemStackError"; } - virtual ~StackError() throw() {}; + StackError(const AST_Node& node); + virtual const char* errtype() const + { + return "SystemStackError"; + } + virtual ~StackError() throw(){}; }; - class IncompatibleUnits : public OperationError { + class IncompatibleUnits : public OperationError + { protected: - // const Sass::UnitType lhs; - // const Sass::UnitType rhs; + // const Sass::UnitType lhs; + // const Sass::UnitType rhs; public: - IncompatibleUnits(const Number& lhs, const Number& rhs); - IncompatibleUnits(const UnitType lhs, const UnitType rhs); - virtual ~IncompatibleUnits() throw() {}; + IncompatibleUnits(const Number& lhs, const Number& rhs); + IncompatibleUnits(const UnitType lhs, const UnitType rhs); + virtual ~IncompatibleUnits() throw(){}; }; - class UndefinedOperation : public OperationError { + class UndefinedOperation : public OperationError + { protected: - Expression_Ptr_Const lhs; - Expression_Ptr_Const rhs; - const std::string op; + Expression_Ptr_Const lhs; + Expression_Ptr_Const rhs; + const std::string op; + public: - UndefinedOperation(Expression_Ptr_Const lhs, Expression_Ptr_Const rhs, const std::string& op); - // virtual const char* errtype() const { return "Error"; } - virtual ~UndefinedOperation() throw() {}; + UndefinedOperation(Expression_Ptr_Const lhs, Expression_Ptr_Const rhs, const std::string& op); + // virtual const char* errtype() const { return "Error"; } + virtual ~UndefinedOperation() throw(){}; }; - class InvalidNullOperation : public UndefinedOperation { + class InvalidNullOperation : public UndefinedOperation + { public: - InvalidNullOperation(Expression_Ptr_Const lhs, Expression_Ptr_Const rhs, const std::string& op); - virtual ~InvalidNullOperation() throw() {}; + InvalidNullOperation(Expression_Ptr_Const lhs, Expression_Ptr_Const rhs, const std::string& op); + virtual ~InvalidNullOperation() throw(){}; }; - class AlphaChannelsNotEqual : public OperationError { + class AlphaChannelsNotEqual : public OperationError + { protected: - Expression_Ptr_Const lhs; - Expression_Ptr_Const rhs; - const std::string op; + Expression_Ptr_Const lhs; + Expression_Ptr_Const rhs; + const std::string op; + public: - AlphaChannelsNotEqual(Expression_Ptr_Const lhs, Expression_Ptr_Const rhs, const std::string& op); - // virtual const char* errtype() const { return "Error"; } - virtual ~AlphaChannelsNotEqual() throw() {}; + AlphaChannelsNotEqual(Expression_Ptr_Const lhs, Expression_Ptr_Const rhs, const std::string& op); + // virtual const char* errtype() const { return "Error"; } + virtual ~AlphaChannelsNotEqual() throw(){}; }; - class SassValueError : public Base { + class SassValueError : public Base + { public: - SassValueError(ParserState pstate, OperationError& err); - virtual ~SassValueError() throw() {}; + SassValueError(ParserState pstate, OperationError& err); + virtual ~SassValueError() throw(){}; }; - } void warn(std::string msg, ParserState pstate); @@ -192,7 +249,6 @@ namespace Sass { void error(std::string msg, ParserState pstate); void error(std::string msg, ParserState pstate, Backtrace* bt); - } #endif diff --git a/src/eval.cpp b/src/eval.cpp index f5f547736c..fa9bb7fa6e 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -26,37 +26,50 @@ #include "color_maps.hpp" #include "sass_functions.hpp" -namespace Sass { - - inline double add(double x, double y) { return x + y; } - inline double sub(double x, double y) { return x - y; } - inline double mul(double x, double y) { return x * y; } - inline double div(double x, double y) { return x / y; } // x/0 checked by caller - inline double mod(double x, double y) { // x/0 checked by caller - if ((x > 0 && y < 0) || (x < 0 && y > 0)) { +namespace Sass +{ + + inline double add(double x, double y) + { + return x + y; + } + inline double sub(double x, double y) + { + return x - y; + } + inline double mul(double x, double y) + { + return x * y; + } + inline double div(double x, double y) + { + return x / y; + } // x/0 checked by caller + inline double mod(double x, double y) + { // x/0 checked by caller + if ((x > 0 && y < 0) || (x < 0 && y > 0)) + { double ret = std::fmod(x, y); return ret ? ret + y : ret; - } else { + } + else + { return std::fmod(x, y); } } typedef double (*bop)(double, double); - bop ops[Sass_OP::NUM_OPS] = { - 0, 0, // and, or - 0, 0, 0, 0, 0, 0, // eq, neq, gt, gte, lt, lte - add, sub, mul, div, mod - }; - - Eval::Eval(Expand& exp) - : exp(exp), - ctx(exp.ctx), - force(false), - is_in_comment(false) + bop ops[Sass_OP::NUM_OPS] = { 0, 0, // and, or + 0, 0, 0, 0, 0, 0, // eq, neq, gt, gte, lt, lte + add, sub, mul, div, mod }; + + Eval::Eval(Expand& exp) : exp(exp), ctx(exp.ctx), force(false), is_in_comment(false) { bool_true = SASS_MEMORY_NEW(Boolean, "[NA]", true); bool_false = SASS_MEMORY_NEW(Boolean, "[NA]", false); } - Eval::~Eval() { } + Eval::~Eval() + { + } Env* Eval::environment() { @@ -76,7 +89,8 @@ namespace Sass { Expression_Ptr Eval::operator()(Block_Ptr b) { Expression_Ptr val = 0; - for (size_t i = 0, L = b->length(); i < L; ++i) { + for (size_t i = 0, L = b->length(); i < L; ++i) + { val = b->at(i)->perform(this); if (val) return val; } @@ -87,34 +101,47 @@ namespace Sass { { Env* env = exp.environment(); std::string var(a->variable()); - if (a->is_global()) { - if (a->is_default()) { - if (env->has_global(var)) { + if (a->is_global()) + { + if (a->is_default()) + { + if (env->has_global(var)) + { Expression_Ptr e = Cast(env->get_global(var)); - if (!e || e->concrete_type() == Expression::NULL_VAL) { + if (!e || e->concrete_type() == Expression::NULL_VAL) + { env->set_global(var, a->value()->perform(this)); } } - else { + else + { env->set_global(var, a->value()->perform(this)); } } - else { + else + { env->set_global(var, a->value()->perform(this)); } } - else if (a->is_default()) { - if (env->has_lexical(var)) { + else if (a->is_default()) + { + if (env->has_lexical(var)) + { auto cur = env; - while (cur && cur->is_lexical()) { - if (cur->has_local(var)) { - if (AST_Node_Obj node = cur->get_local(var)) { + while (cur && cur->is_lexical()) + { + if (cur->has_local(var)) + { + if (AST_Node_Obj node = cur->get_local(var)) + { Expression_Ptr e = Cast(node); - if (!e || e->concrete_type() == Expression::NULL_VAL) { + if (!e || e->concrete_type() == Expression::NULL_VAL) + { cur->set_local(var, a->value()->perform(this)); } } - else { + else + { throw std::runtime_error("Env not in sync"); } return 0; @@ -123,22 +150,28 @@ namespace Sass { } throw std::runtime_error("Env not in sync"); } - else if (env->has_global(var)) { - if (AST_Node_Obj node = env->get_global(var)) { + else if (env->has_global(var)) + { + if (AST_Node_Obj node = env->get_global(var)) + { Expression_Ptr e = Cast(node); - if (!e || e->concrete_type() == Expression::NULL_VAL) { + if (!e || e->concrete_type() == Expression::NULL_VAL) + { env->set_global(var, a->value()->perform(this)); } } } - else if (env->is_lexical()) { + else if (env->is_lexical()) + { env->set_local(var, a->value()->perform(this)); } - else { + else + { env->set_local(var, a->value()->perform(this)); } } - else { + else + { env->set_lexical(var, a->value()->perform(this)); } return 0; @@ -150,10 +183,12 @@ namespace Sass { Env env(exp.environment()); exp.env_stack.push_back(&env); Expression_Obj cond = i->predicate()->perform(this); - if (!cond->is_false()) { + if (!cond->is_false()) + { rv = i->block()->perform(this); } - else { + else + { Block_Obj alt = i->alternative(); if (alt) rv = alt->perform(this); } @@ -167,20 +202,22 @@ namespace Sass { { std::string variable(f->variable()); Expression_Obj low = f->lower_bound()->perform(this); - if (low->concrete_type() != Expression::NUMBER) { + if (low->concrete_type() != Expression::NUMBER) + { throw Exception::TypeMismatch(*low, "integer"); } Expression_Obj high = f->upper_bound()->perform(this); - if (high->concrete_type() != Expression::NUMBER) { + if (high->concrete_type() != Expression::NUMBER) + { throw Exception::TypeMismatch(*high, "integer"); } Number_Obj sass_start = Cast(low); Number_Obj sass_end = Cast(high); // check if units are valid for sequence - if (sass_start->unit() != sass_end->unit()) { - std::stringstream msg; msg << "Incompatible units: '" - << sass_end->unit() << "' and '" - << sass_start->unit() << "'."; + if (sass_start->unit() != sass_end->unit()) + { + std::stringstream msg; + msg << "Incompatible units: '" << sass_end->unit() << "' and '" << sass_start->unit() << "'."; error(msg.str(), low->pstate(), backtrace()); } double start = sass_start->value(); @@ -190,21 +227,22 @@ namespace Sass { exp.env_stack.push_back(&env); Block_Obj body = f->block(); Expression_Ptr val = 0; - if (start < end) { + if (start < end) + { if (f->is_inclusive()) ++end; - for (double i = start; - i < end; - ++i) { + for (double i = start; i < end; ++i) + { Number_Obj it = SASS_MEMORY_NEW(Number, low->pstate(), i, sass_end->unit()); env.set_local(variable, it); val = body->perform(this); if (val) break; } - } else { + } + else + { if (f->is_inclusive()) --end; - for (double i = start; - i > end; - --i) { + for (double i = start; i > end; --i) + { Number_Obj it = SASS_MEMORY_NEW(Number, low->pstate(), i, sass_end->unit()); env.set_local(variable, it); val = body->perform(this); @@ -225,35 +263,44 @@ namespace Sass { exp.env_stack.push_back(&env); List_Obj list = 0; Map_Ptr map = 0; - if (expr->concrete_type() == Expression::MAP) { + if (expr->concrete_type() == Expression::MAP) + { map = Cast(expr); } - else if (Selector_List_Ptr ls = Cast(expr)) { + else if (Selector_List_Ptr ls = Cast(expr)) + { Listize listize; Expression_Obj rv = ls->perform(&listize); list = Cast(rv); } - else if (expr->concrete_type() != Expression::LIST) { + else if (expr->concrete_type() != Expression::LIST) + { list = SASS_MEMORY_NEW(List, expr->pstate(), 1, SASS_COMMA); list->append(expr); } - else { + else + { list = Cast(expr); } Block_Obj body = e->block(); Expression_Obj val = 0; - if (map) { - for (Expression_Obj key : map->keys()) { + if (map) + { + for (Expression_Obj key : map->keys()) + { Expression_Obj value = map->at(key); - if (variables.size() == 1) { + if (variables.size() == 1) + { List_Ptr variable = SASS_MEMORY_NEW(List, map->pstate(), 2, SASS_SPACE); variable->append(key); variable->append(value); env.set_local(variables[0], variable); - } else { + } + else + { env.set_local(variables[0], key); env.set_local(variables[1], value); } @@ -262,32 +309,43 @@ namespace Sass { if (val) break; } } - else { - if (list->length() == 1 && Cast(list)) { + else + { + if (list->length() == 1 && Cast(list)) + { list = Cast(list); } - for (size_t i = 0, L = list->length(); i < L; ++i) { + for (size_t i = 0, L = list->length(); i < L; ++i) + { Expression_Ptr item = list->at(i); // unwrap value if the expression is an argument if (Argument_Ptr arg = Cast(item)) item = arg->value(); // check if we got passed a list of args (investigate) - if (List_Ptr scalars = Cast(item)) { - if (variables.size() == 1) { + if (List_Ptr scalars = Cast(item)) + { + if (variables.size() == 1) + { Expression_Ptr var = scalars; env.set_local(variables[0], var); - } else { + } + else + { // XXX: this is never hit via spec tests - for (size_t j = 0, K = variables.size(); j < K; ++j) { - Expression_Ptr res = j >= scalars->length() - ? SASS_MEMORY_NEW(Null, expr->pstate()) - : scalars->at(j); + for (size_t j = 0, K = variables.size(); j < K; ++j) + { + Expression_Ptr res = + j >= scalars->length() ? SASS_MEMORY_NEW(Null, expr->pstate()) : scalars->at(j); env.set_local(variables[j], res); } } - } else { - if (variables.size() > 0) { + } + else + { + if (variables.size() > 0) + { env.set_local(variables.at(0), item); - for (size_t j = 1, K = variables.size(); j < K; ++j) { + for (size_t j = 1, K = variables.size(); j < K; ++j) + { // XXX: this is never hit via spec tests Expression_Ptr res = SASS_MEMORY_NEW(Null, expr->pstate()); env.set_local(variables[j], res); @@ -309,9 +367,11 @@ namespace Sass { Env env(environment(), true); exp.env_stack.push_back(&env); Expression_Obj cond = pred->perform(this); - while (!cond->is_false()) { + while (!cond->is_false()) + { Expression_Obj val = body->perform(this); - if (val) { + if (val) + { exp.env_stack.pop_back(); return val.detach(); } @@ -334,17 +394,12 @@ namespace Sass { Env* env = exp.environment(); // try to use generic function - if (env->has("@warn[f]")) { + if (env->has("@warn[f]")) + { // add call stack entry - ctx.callee_stack.push_back({ - "@warn", - w->pstate().path, - w->pstate().line + 1, - w->pstate().column + 1, - SASS_CALLEE_FUNCTION, - { env } - }); + ctx.callee_stack.push_back( + { "@warn", w->pstate().path, w->pstate().line + 1, w->pstate().column + 1, SASS_CALLEE_FUNCTION, { env } }); Definition_Ptr def = Cast((*env)["@warn[f]"]); // Block_Obj body = def->block(); @@ -361,7 +416,6 @@ namespace Sass { sass_delete_value(c_args); sass_delete_value(c_val); return 0; - } std::string result(unquote(message->to_sass())); @@ -381,17 +435,12 @@ namespace Sass { Env* env = exp.environment(); // try to use generic function - if (env->has("@error[f]")) { + if (env->has("@error[f]")) + { // add call stack entry - ctx.callee_stack.push_back({ - "@error", - e->pstate().path, - e->pstate().line + 1, - e->pstate().column + 1, - SASS_CALLEE_FUNCTION, - { env } - }); + ctx.callee_stack.push_back( + { "@error", e->pstate().path, e->pstate().line + 1, e->pstate().column + 1, SASS_CALLEE_FUNCTION, { env } }); Definition_Ptr def = Cast((*env)["@error[f]"]); // Block_Obj body = def->block(); @@ -408,7 +457,6 @@ namespace Sass { sass_delete_value(c_args); sass_delete_value(c_val); return 0; - } std::string result(unquote(message->to_sass())); @@ -425,17 +473,12 @@ namespace Sass { Env* env = exp.environment(); // try to use generic function - if (env->has("@debug[f]")) { + if (env->has("@debug[f]")) + { // add call stack entry - ctx.callee_stack.push_back({ - "@debug", - d->pstate().path, - d->pstate().line + 1, - d->pstate().column + 1, - SASS_CALLEE_FUNCTION, - { env } - }); + ctx.callee_stack.push_back( + { "@debug", d->pstate().path, d->pstate().line + 1, d->pstate().column + 1, SASS_CALLEE_FUNCTION, { env } }); Definition_Ptr def = Cast((*env)["@debug[f]"]); // Block_Obj body = def->block(); @@ -452,7 +495,6 @@ namespace Sass { sass_delete_value(c_args); sass_delete_value(c_val); return 0; - } std::string cwd(ctx.cwd()); @@ -462,7 +504,7 @@ namespace Sass { std::string output_path(Sass::File::path_for_console(rel_path, abs_path, d->pstate().path)); ctx.c_options.output_style = outstyle; - std::cerr << output_path << ":" << d->pstate().line+1 << " DEBUG: " << result; + std::cerr << output_path << ":" << d->pstate().line + 1 << " DEBUG: " << result; std::cerr << std::endl; return 0; } @@ -470,19 +512,19 @@ namespace Sass { Expression_Ptr Eval::operator()(List_Ptr l) { // special case for unevaluated map - if (l->separator() == SASS_HASH) { - Map_Obj lm = SASS_MEMORY_NEW(Map, - l->pstate(), - l->length() / 2); + if (l->separator() == SASS_HASH) + { + Map_Obj lm = SASS_MEMORY_NEW(Map, l->pstate(), l->length() / 2); for (size_t i = 0, L = l->length(); i < L; i += 2) { - Expression_Obj key = (*l)[i+0]->perform(this); - Expression_Obj val = (*l)[i+1]->perform(this); + Expression_Obj key = (*l)[i + 0]->perform(this); + Expression_Obj val = (*l)[i + 1]->perform(this); // make sure the color key never displays its real name key->is_delayed(true); // verified *lm << std::make_pair(key, val); } - if (lm->has_duplicate_key()) { + if (lm->has_duplicate_key()) + { throw Exception::DuplicateKeyError(*lm, *l); } @@ -492,13 +534,10 @@ namespace Sass { // check if we should expand it if (l->is_expanded()) return l; // regular case for unevaluated lists - List_Obj ll = SASS_MEMORY_NEW(List, - l->pstate(), - l->length(), - l->separator(), - l->is_arglist(), - l->is_bracketed()); - for (size_t i = 0, L = l->length(); i < L; ++i) { + List_Obj ll = + SASS_MEMORY_NEW(List, l->pstate(), l->length(), l->separator(), l->is_arglist(), l->is_bracketed()); + for (size_t i = 0, L = l->length(); i < L; ++i) + { ll->append((*l)[i]->perform(this)); } ll->is_interpolant(l->is_interpolant()); @@ -513,21 +552,22 @@ namespace Sass { // make sure we're not starting with duplicate keys. // the duplicate key state will have been set in the parser phase. - if (m->has_duplicate_key()) { + if (m->has_duplicate_key()) + { throw Exception::DuplicateKeyError(*m, *m); } - Map_Obj mm = SASS_MEMORY_NEW(Map, - m->pstate(), - m->length()); - for (auto key : m->keys()) { + Map_Obj mm = SASS_MEMORY_NEW(Map, m->pstate(), m->length()); + for (auto key : m->keys()) + { Expression_Ptr ex_key = key->perform(this); Expression_Ptr ex_val = m->at(key)->perform(this); *mm << std::make_pair(ex_key, ex_val); } // check the evaluated keys aren't duplicates. - if (mm->has_duplicate_key()) { + if (mm->has_duplicate_key()) + { throw Exception::DuplicateKeyError(*mm, *m); } @@ -542,13 +582,15 @@ namespace Sass { Expression_Obj rhs = b_in->right(); enum Sass_OP op_type = b_in->optype(); - if (op_type == Sass_OP::AND) { + if (op_type == Sass_OP::AND) + { // LOCAL_FLAG(force, true); lhs = lhs->perform(this); if (!*lhs) return lhs.detach(); return rhs->perform(this); } - else if (op_type == Sass_OP::OR) { + else if (op_type == Sass_OP::OR) + { // LOCAL_FLAG(force, true); lhs = lhs->perform(this); if (*lhs) return lhs.detach(); @@ -556,27 +598,32 @@ namespace Sass { } // Evaluate variables as early o - while (Variable_Ptr l_v = Cast(lhs)) { + while (Variable_Ptr l_v = Cast(lhs)) + { lhs = operator()(l_v); } - while (Variable_Ptr r_v = Cast(rhs)) { + while (Variable_Ptr r_v = Cast(rhs)) + { rhs = operator()(r_v); } Binary_Expression_Obj b = b_in; // Evaluate sub-expressions early on - while (Binary_Expression_Ptr l_b = Cast(lhs)) { + while (Binary_Expression_Ptr l_b = Cast(lhs)) + { if (!force && l_b->is_delayed()) break; lhs = operator()(l_b); } - while (Binary_Expression_Ptr r_b = Cast(rhs)) { + while (Binary_Expression_Ptr r_b = Cast(rhs)) + { if (!force && r_b->is_delayed()) break; rhs = operator()(r_b); } // don't eval delayed expressions (the '/' when used as a separator) - if (!force && op_type == Sass_OP::DIV && b->is_delayed()) { + if (!force && op_type == Sass_OP::DIV && b->is_delayed()) + { b->right(b->right()->perform(this)); b->left(b->left()->perform(this)); return b.detach(); @@ -584,20 +631,35 @@ namespace Sass { // specific types we know are final // handle them early to avoid overhead - if (Number_Ptr l_n = Cast(lhs)) { + if (Number_Ptr l_n = Cast(lhs)) + { // lhs is number and rhs is number - if (Number_Ptr r_n = Cast(rhs)) { - try { - switch (op_type) { - case Sass_OP::EQ: return *l_n == *r_n ? bool_true : bool_false; - case Sass_OP::NEQ: return *l_n == *r_n ? bool_false : bool_true; - case Sass_OP::LT: return *l_n < *r_n ? bool_true : bool_false; - case Sass_OP::GTE: return *l_n < *r_n ? bool_false : bool_true; - case Sass_OP::LTE: return *l_n < *r_n || *l_n == *r_n ? bool_true : bool_false; - case Sass_OP::GT: return *l_n < *r_n || *l_n == *r_n ? bool_false : bool_true; - case Sass_OP::ADD: case Sass_OP::SUB: case Sass_OP::MUL: case Sass_OP::DIV: case Sass_OP::MOD: - return op_numbers(op_type, *l_n, *r_n, ctx.c_options, b_in->pstate()); - default: break; + if (Number_Ptr r_n = Cast(rhs)) + { + try + { + switch (op_type) + { + case Sass_OP::EQ: + return *l_n == *r_n ? bool_true : bool_false; + case Sass_OP::NEQ: + return *l_n == *r_n ? bool_false : bool_true; + case Sass_OP::LT: + return *l_n < *r_n ? bool_true : bool_false; + case Sass_OP::GTE: + return *l_n < *r_n ? bool_false : bool_true; + case Sass_OP::LTE: + return *l_n < *r_n || *l_n == *r_n ? bool_true : bool_false; + case Sass_OP::GT: + return *l_n < *r_n || *l_n == *r_n ? bool_false : bool_true; + case Sass_OP::ADD: + case Sass_OP::SUB: + case Sass_OP::MUL: + case Sass_OP::DIV: + case Sass_OP::MOD: + return op_numbers(op_type, *l_n, *r_n, ctx.c_options, b_in->pstate()); + default: + break; } } catch (Exception::OperationError& err) @@ -606,18 +668,32 @@ namespace Sass { } } // lhs is number and rhs is color - else if (Color_Ptr r_c = Cast(rhs)) { - try { - switch (op_type) { - case Sass_OP::EQ: return *l_n == *r_c ? bool_true : bool_false; - case Sass_OP::NEQ: return *l_n == *r_c ? bool_false : bool_true; - case Sass_OP::LT: return *l_n < *r_c ? bool_true : bool_false; - case Sass_OP::GTE: return *l_n < *r_c ? bool_false : bool_true; - case Sass_OP::LTE: return *l_n < *r_c || *l_n == *r_c ? bool_true : bool_false; - case Sass_OP::GT: return *l_n < *r_c || *l_n == *r_c ? bool_false : bool_true; - case Sass_OP::ADD: case Sass_OP::SUB: case Sass_OP::MUL: case Sass_OP::DIV: case Sass_OP::MOD: - return op_number_color(op_type, *l_n, *r_c, ctx.c_options, b_in->pstate()); - default: break; + else if (Color_Ptr r_c = Cast(rhs)) + { + try + { + switch (op_type) + { + case Sass_OP::EQ: + return *l_n == *r_c ? bool_true : bool_false; + case Sass_OP::NEQ: + return *l_n == *r_c ? bool_false : bool_true; + case Sass_OP::LT: + return *l_n < *r_c ? bool_true : bool_false; + case Sass_OP::GTE: + return *l_n < *r_c ? bool_false : bool_true; + case Sass_OP::LTE: + return *l_n < *r_c || *l_n == *r_c ? bool_true : bool_false; + case Sass_OP::GT: + return *l_n < *r_c || *l_n == *r_c ? bool_false : bool_true; + case Sass_OP::ADD: + case Sass_OP::SUB: + case Sass_OP::MUL: + case Sass_OP::DIV: + case Sass_OP::MOD: + return op_number_color(op_type, *l_n, *r_c, ctx.c_options, b_in->pstate()); + default: + break; } } catch (Exception::OperationError& err) @@ -626,20 +702,35 @@ namespace Sass { } } } - else if (Color_Ptr l_c = Cast(lhs)) { + else if (Color_Ptr l_c = Cast(lhs)) + { // lhs is color and rhs is color - if (Color_Ptr r_c = Cast(rhs)) { - try { - switch (op_type) { - case Sass_OP::EQ: return *l_c == *r_c ? bool_true : bool_false; - case Sass_OP::NEQ: return *l_c == *r_c ? bool_false : bool_true; - case Sass_OP::LT: return *l_c < *r_c ? bool_true : bool_false; - case Sass_OP::GTE: return *l_c < *r_c ? bool_false : bool_true; - case Sass_OP::LTE: return *l_c < *r_c || *l_c == *r_c ? bool_true : bool_false; - case Sass_OP::GT: return *l_c < *r_c || *l_c == *r_c ? bool_false : bool_true; - case Sass_OP::ADD: case Sass_OP::SUB: case Sass_OP::MUL: case Sass_OP::DIV: case Sass_OP::MOD: - return op_colors(op_type, *l_c, *r_c, ctx.c_options, b_in->pstate()); - default: break; + if (Color_Ptr r_c = Cast(rhs)) + { + try + { + switch (op_type) + { + case Sass_OP::EQ: + return *l_c == *r_c ? bool_true : bool_false; + case Sass_OP::NEQ: + return *l_c == *r_c ? bool_false : bool_true; + case Sass_OP::LT: + return *l_c < *r_c ? bool_true : bool_false; + case Sass_OP::GTE: + return *l_c < *r_c ? bool_false : bool_true; + case Sass_OP::LTE: + return *l_c < *r_c || *l_c == *r_c ? bool_true : bool_false; + case Sass_OP::GT: + return *l_c < *r_c || *l_c == *r_c ? bool_false : bool_true; + case Sass_OP::ADD: + case Sass_OP::SUB: + case Sass_OP::MUL: + case Sass_OP::DIV: + case Sass_OP::MOD: + return op_colors(op_type, *l_c, *r_c, ctx.c_options, b_in->pstate()); + default: + break; } } catch (Exception::OperationError& err) @@ -648,18 +739,32 @@ namespace Sass { } } // lhs is color and rhs is number - else if (Number_Ptr r_n = Cast(rhs)) { - try { - switch (op_type) { - case Sass_OP::EQ: return *l_c == *r_n ? bool_true : bool_false; - case Sass_OP::NEQ: return *l_c == *r_n ? bool_false : bool_true; - case Sass_OP::LT: return *l_c < *r_n ? bool_true : bool_false; - case Sass_OP::GTE: return *l_c < *r_n ? bool_false : bool_true; - case Sass_OP::LTE: return *l_c < *r_n || *l_c == *r_n ? bool_true : bool_false; - case Sass_OP::GT: return *l_c < *r_n || *l_c == *r_n ? bool_false : bool_true; - case Sass_OP::ADD: case Sass_OP::SUB: case Sass_OP::MUL: case Sass_OP::DIV: case Sass_OP::MOD: - return op_color_number(op_type, *l_c, *r_n, ctx.c_options, b_in->pstate()); - default: break; + else if (Number_Ptr r_n = Cast(rhs)) + { + try + { + switch (op_type) + { + case Sass_OP::EQ: + return *l_c == *r_n ? bool_true : bool_false; + case Sass_OP::NEQ: + return *l_c == *r_n ? bool_false : bool_true; + case Sass_OP::LT: + return *l_c < *r_n ? bool_true : bool_false; + case Sass_OP::GTE: + return *l_c < *r_n ? bool_false : bool_true; + case Sass_OP::LTE: + return *l_c < *r_n || *l_c == *r_n ? bool_true : bool_false; + case Sass_OP::GT: + return *l_c < *r_n || *l_c == *r_n ? bool_false : bool_true; + case Sass_OP::ADD: + case Sass_OP::SUB: + case Sass_OP::MUL: + case Sass_OP::DIV: + case Sass_OP::MOD: + return op_color_number(op_type, *l_c, *r_n, ctx.c_options, b_in->pstate()); + default: + break; } } catch (Exception::OperationError& err) @@ -672,28 +777,34 @@ namespace Sass { String_Schema_Obj ret_schema; // only the last item will be used to eval the binary expression - if (String_Schema_Ptr s_l = Cast(b->left())) { - if (!s_l->has_interpolant() && (!s_l->is_right_interpolant())) { + if (String_Schema_Ptr s_l = Cast(b->left())) + { + if (!s_l->has_interpolant() && (!s_l->is_right_interpolant())) + { ret_schema = SASS_MEMORY_NEW(String_Schema, b->pstate()); - Binary_Expression_Obj bin_ex = SASS_MEMORY_NEW(Binary_Expression, b->pstate(), - b->op(), s_l->last(), b->right()); + Binary_Expression_Obj bin_ex = + SASS_MEMORY_NEW(Binary_Expression, b->pstate(), b->op(), s_l->last(), b->right()); bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed()); // unverified - for (size_t i = 0; i < s_l->length() - 1; ++i) { + for (size_t i = 0; i < s_l->length() - 1; ++i) + { ret_schema->append(s_l->at(i)->perform(this)); } ret_schema->append(bin_ex->perform(this)); return ret_schema->perform(this); } } - if (String_Schema_Ptr s_r = Cast(b->right())) { + if (String_Schema_Ptr s_r = Cast(b->right())) + { - if (!s_r->has_interpolant() && (!s_r->is_left_interpolant() || op_type == Sass_OP::DIV)) { + if (!s_r->has_interpolant() && (!s_r->is_left_interpolant() || op_type == Sass_OP::DIV)) + { ret_schema = SASS_MEMORY_NEW(String_Schema, b->pstate()); - Binary_Expression_Obj bin_ex = SASS_MEMORY_NEW(Binary_Expression, b->pstate(), - b->op(), b->left(), s_r->first()); + Binary_Expression_Obj bin_ex = + SASS_MEMORY_NEW(Binary_Expression, b->pstate(), b->op(), b->left(), s_r->first()); bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed()); // verified ret_schema->append(bin_ex->perform(this)); - for (size_t i = 1; i < s_r->length(); ++i) { + for (size_t i = 1; i < s_r->length(); ++i) + { ret_schema->append(s_r->at(i)->perform(this)); } return ret_schema->perform(this); @@ -701,12 +812,8 @@ namespace Sass { } // fully evaluate their values - if (op_type == Sass_OP::EQ || - op_type == Sass_OP::NEQ || - op_type == Sass_OP::GT || - op_type == Sass_OP::GTE || - op_type == Sass_OP::LT || - op_type == Sass_OP::LTE) + if (op_type == Sass_OP::EQ || op_type == Sass_OP::NEQ || op_type == Sass_OP::GT || + op_type == Sass_OP::GTE || op_type == Sass_OP::LT || op_type == Sass_OP::LTE) { LOCAL_FLAG(force, true); lhs->is_expanded(false); @@ -716,7 +823,8 @@ namespace Sass { rhs->set_delayed(false); rhs = rhs->perform(this); } - else { + else + { lhs = lhs->perform(this); } @@ -736,28 +844,31 @@ namespace Sass { bool schema_op = false; - bool force_delay = (s2 && s2->is_left_interpolant()) || - (s1 && s1->is_right_interpolant()) || - (b1 && b1->is_right_interpolant()) || - (b2 && b2->is_left_interpolant()); + bool force_delay = (s2 && s2->is_left_interpolant()) || (s1 && s1->is_right_interpolant()) || + (b1 && b1->is_right_interpolant()) || (b2 && b2->is_left_interpolant()); if ((s1 && s1->has_interpolants()) || (s2 && s2->has_interpolants()) || force_delay) { - if (op_type == Sass_OP::DIV || op_type == Sass_OP::MUL || op_type == Sass_OP::MOD || op_type == Sass_OP::ADD || op_type == Sass_OP::SUB || - op_type == Sass_OP::EQ) { + if (op_type == Sass_OP::DIV || op_type == Sass_OP::MUL || op_type == Sass_OP::MOD || + op_type == Sass_OP::ADD || op_type == Sass_OP::SUB || op_type == Sass_OP::EQ) + { // If possible upgrade LHS to a number (for number to string compare) - if (String_Constant_Ptr str = Cast(lhs)) { + if (String_Constant_Ptr str = Cast(lhs)) + { std::string value(str->value()); const char* start = value.c_str(); - if (Prelexer::sequence < Prelexer::dimension, Prelexer::end_of_file >(start) != 0) { + if (Prelexer::sequence(start) != 0) + { lhs = Parser::lexed_dimension(b->pstate(), str->value()); } } // If possible upgrade RHS to a number (for string to number compare) - if (String_Constant_Ptr str = Cast(rhs)) { + if (String_Constant_Ptr str = Cast(rhs)) + { std::string value(str->value()); const char* start = value.c_str(); - if (Prelexer::sequence < Prelexer::dimension, Prelexer::number >(start) != 0) { + if (Prelexer::sequence(start) != 0) + { rhs = Parser::lexed_dimension(b->pstate(), str->value()); } } @@ -767,7 +878,8 @@ namespace Sass { Value_Obj v_l = Cast(lhs->perform(&to_value)); Value_Obj v_r = Cast(rhs->perform(&to_value)); - if (force_delay) { + if (force_delay) + { std::string str(""); str += v_l->to_string(ctx.c_options); if (b->op().ws_before) str += " "; @@ -781,15 +893,24 @@ namespace Sass { } // see if it's a relational expression - try { - switch(op_type) { - case Sass_OP::EQ: return SASS_MEMORY_NEW(Boolean, b->pstate(), eq(lhs, rhs)); - case Sass_OP::NEQ: return SASS_MEMORY_NEW(Boolean, b->pstate(), !eq(lhs, rhs)); - case Sass_OP::GT: return SASS_MEMORY_NEW(Boolean, b->pstate(), !lt(lhs, rhs, "gt") && !eq(lhs, rhs)); - case Sass_OP::GTE: return SASS_MEMORY_NEW(Boolean, b->pstate(), !lt(lhs, rhs, "gte")); - case Sass_OP::LT: return SASS_MEMORY_NEW(Boolean, b->pstate(), lt(lhs, rhs, "lt")); - case Sass_OP::LTE: return SASS_MEMORY_NEW(Boolean, b->pstate(), lt(lhs, rhs, "lte") || eq(lhs, rhs)); - default: break; + try + { + switch (op_type) + { + case Sass_OP::EQ: + return SASS_MEMORY_NEW(Boolean, b->pstate(), eq(lhs, rhs)); + case Sass_OP::NEQ: + return SASS_MEMORY_NEW(Boolean, b->pstate(), !eq(lhs, rhs)); + case Sass_OP::GT: + return SASS_MEMORY_NEW(Boolean, b->pstate(), !lt(lhs, rhs, "gt") && !eq(lhs, rhs)); + case Sass_OP::GTE: + return SASS_MEMORY_NEW(Boolean, b->pstate(), !lt(lhs, rhs, "gte")); + case Sass_OP::LT: + return SASS_MEMORY_NEW(Boolean, b->pstate(), lt(lhs, rhs, "lt")); + case Sass_OP::LTE: + return SASS_MEMORY_NEW(Boolean, b->pstate(), lt(lhs, rhs, "lte") || eq(lhs, rhs)); + default: + break; } } catch (Exception::OperationError& err) @@ -804,55 +925,65 @@ namespace Sass { // ToDo: throw error in op functions // ToDo: then catch and re-throw them Expression_Obj rv; - try { + try + { ParserState pstate(b->pstate()); - if (l_type == Expression::NUMBER && r_type == Expression::NUMBER) { + if (l_type == Expression::NUMBER && r_type == Expression::NUMBER) + { Number_Ptr l_n = Cast(lhs); Number_Ptr r_n = Cast(rhs); rv = op_numbers(op_type, *l_n, *r_n, ctx.c_options, pstate); } - else if (l_type == Expression::NUMBER && r_type == Expression::COLOR) { + else if (l_type == Expression::NUMBER && r_type == Expression::COLOR) + { Number_Ptr l_n = Cast(lhs); Color_Ptr r_c = Cast(rhs); rv = op_number_color(op_type, *l_n, *r_c, ctx.c_options, pstate); } - else if (l_type == Expression::COLOR && r_type == Expression::NUMBER) { + else if (l_type == Expression::COLOR && r_type == Expression::NUMBER) + { Color_Ptr l_c = Cast(lhs); Number_Ptr r_n = Cast(rhs); rv = op_color_number(op_type, *l_c, *r_n, ctx.c_options, pstate); } - else if (l_type == Expression::COLOR && r_type == Expression::COLOR) { + else if (l_type == Expression::COLOR && r_type == Expression::COLOR) + { Color_Ptr l_c = Cast(lhs); Color_Ptr r_c = Cast(rhs); rv = op_colors(op_type, *l_c, *r_c, ctx.c_options, pstate); } - else { + else + { To_Value to_value(ctx); // this will leak if perform does not return a value! Value_Obj v_l = Cast(lhs->perform(&to_value)); Value_Obj v_r = Cast(rhs->perform(&to_value)); - bool interpolant = b->is_right_interpolant() || - b->is_left_interpolant() || - b->is_interpolant(); + bool interpolant = b->is_right_interpolant() || b->is_left_interpolant() || b->is_interpolant(); if (op_type == Sass_OP::SUB) interpolant = false; // if (op_type == Sass_OP::DIV) interpolant = true; // check for type violations - if (l_type == Expression::MAP) { + if (l_type == Expression::MAP) + { throw Exception::InvalidValue(*v_l); } - if (r_type == Expression::MAP) { + if (r_type == Expression::MAP) + { throw Exception::InvalidValue(*v_r); } - Value_Ptr ex = op_strings(b->op(), *v_l, *v_r, ctx.c_options, pstate, !interpolant); // pass true to compress + Value_Ptr ex = op_strings(b->op(), *v_l, *v_r, ctx.c_options, pstate, + !interpolant); // pass true to compress if (String_Constant_Ptr str = Cast(ex)) { if (str->concrete_type() == Expression::STRING) { String_Constant_Ptr lstr = Cast(lhs); String_Constant_Ptr rstr = Cast(rhs); - if (op_type != Sass_OP::SUB) { + if (op_type != Sass_OP::SUB) + { if (String_Constant_Ptr org = lstr ? lstr : rstr) - { str->quote_mark(org->quote_mark()); } + { + str->quote_mark(org->quote_mark()); + } } } } @@ -866,8 +997,10 @@ namespace Sass { throw Exception::SassValueError(b->pstate(), err); } - if (rv) { - if (schema_op) { + if (rv) + { + if (schema_op) + { // XXX: this is never hit via spec tests (*s2)[0] = rv; rv = s2->perform(this); @@ -875,48 +1008,53 @@ namespace Sass { } return rv.detach(); - } Expression_Ptr Eval::operator()(Unary_Expression_Ptr u) { Expression_Obj operand = u->operand()->perform(this); - if (u->optype() == Unary_Expression::NOT) { + if (u->optype() == Unary_Expression::NOT) + { Boolean_Ptr result = SASS_MEMORY_NEW(Boolean, u->pstate(), (bool)*operand); result->value(!result->value()); return result; } - else if (Number_Obj nr = Cast(operand)) { + else if (Number_Obj nr = Cast(operand)) + { // negate value for minus unary expression - if (u->optype() == Unary_Expression::MINUS) { + if (u->optype() == Unary_Expression::MINUS) + { Number_Obj cpy = SASS_MEMORY_COPY(nr); - cpy->value( - cpy->value() ); // negate value + cpy->value(-cpy->value()); // negate value return cpy.detach(); // return the copy } // nothing for positive return nr.detach(); } - else { + else + { // Special cases: +/- variables which evaluate to null ouput just +/-, // but +/- null itself outputs the string - if (operand->concrete_type() == Expression::NULL_VAL && Cast(u->operand())) { + if (operand->concrete_type() == Expression::NULL_VAL && Cast(u->operand())) + { u->operand(SASS_MEMORY_NEW(String_Quoted, u->pstate(), "")); } // Never apply unary opertions on colors @see #2140 - else if (Color_Ptr color = Cast(operand)) { + else if (Color_Ptr color = Cast(operand)) + { // Use the color name if this was eval with one - if (color->disp().length() > 0) { + if (color->disp().length() > 0) + { operand = SASS_MEMORY_NEW(String_Constant, operand->pstate(), color->disp()); u->operand(operand); } } - else { + else + { u->operand(operand); } - return SASS_MEMORY_NEW(String_Quoted, - u->pstate(), - u->inspect()); + return SASS_MEMORY_NEW(String_Quoted, u->pstate(), u->inspect()); } // unreachable return u; @@ -924,11 +1062,12 @@ namespace Sass { Expression_Ptr Eval::operator()(Function_Call_Ptr c) { - if (backtrace()->parent != NULL && backtrace()->depth() > Constants::MaxCallStack) { - // XXX: this is never hit via spec tests - std::ostringstream stm; - stm << "Stack depth exceeded max of " << Constants::MaxCallStack; - error(stm.str(), c->pstate(), backtrace()); + if (backtrace()->parent != NULL && backtrace()->depth() > Constants::MaxCallStack) + { + // XXX: this is never hit via spec tests + std::ostringstream stm; + stm << "Stack depth exceeded max of " << Constants::MaxCallStack; + error(stm.str(), c->pstate(), backtrace()); } std::string name(Util::normalize_underscores(c->name())); std::string full_name(name + "[f]"); @@ -936,46 +1075,52 @@ namespace Sass { Arguments_Obj args = c->arguments(); Env* env = environment(); - if (!env->has(full_name) || (!c->via_call() && Prelexer::re_special_fun(name.c_str()))) { - if (!env->has("*[f]")) { - for (Argument_Obj arg : args->elements()) { - if (List_Obj ls = Cast(arg->value())) { + if (!env->has(full_name) || (!c->via_call() && Prelexer::re_special_fun(name.c_str()))) + { + if (!env->has("*[f]")) + { + for (Argument_Obj arg : args->elements()) + { + if (List_Obj ls = Cast(arg->value())) + { if (ls->size() == 0) error("() isn't a valid CSS value.", c->pstate()); } } args = Cast(args->perform(this)); - Function_Call_Obj lit = SASS_MEMORY_NEW(Function_Call, - c->pstate(), - c->name(), - args); - if (args->has_named_arguments()) { + Function_Call_Obj lit = SASS_MEMORY_NEW(Function_Call, c->pstate(), c->name(), args); + if (args->has_named_arguments()) + { error("Function " + c->name() + " doesn't support keyword arguments", c->pstate()); } - String_Quoted_Ptr str = SASS_MEMORY_NEW(String_Quoted, - c->pstate(), - lit->to_string(ctx.c_options)); + String_Quoted_Ptr str = SASS_MEMORY_NEW(String_Quoted, c->pstate(), lit->to_string(ctx.c_options)); str->is_interpolant(c->is_interpolant()); return str; - } else { + } + else + { // call generic function full_name = "*[f]"; } } // further delay for calls - if (full_name != "call[f]") { + if (full_name != "call[f]") + { args->set_delayed(false); // verified } - if (full_name != "if[f]") { + if (full_name != "if[f]") + { args = Cast(args->perform(this)); } Definition_Ptr def = Cast((*env)[full_name]); - if (def->is_overload_stub()) { + if (def->is_overload_stub()) + { std::stringstream ss; size_t L = args->length(); // account for rest arguments - if (args->has_rest_argument() && args->length() > 0) { + if (args->has_rest_argument() && args->length() > 0) + { // get the rest arguments list List_Ptr rest = Cast(args->last()->value()); // arguments before rest argument plus rest @@ -984,40 +1129,41 @@ namespace Sass { ss << full_name << L; full_name = ss.str(); std::string resolved_name(full_name); - if (!env->has(resolved_name)) error("overloaded function `" + std::string(c->name()) + "` given wrong number of arguments", c->pstate()); + if (!env->has(resolved_name)) + error("overloaded function `" + std::string(c->name()) + + "` given wrong number of arguments", + c->pstate()); def = Cast((*env)[resolved_name]); } - Expression_Obj result = c; - Block_Obj body = def->block(); - Native_Function func = def->native_function(); + Expression_Obj result = c; + Block_Obj body = def->block(); + Native_Function func = def->native_function(); Sass_Function_Entry c_function = def->c_function(); Parameters_Obj params = def->parameters(); Env fn_env(def->environment()); exp.env_stack.push_back(&fn_env); - if (func || body) { + if (func || body) + { bind(std::string("Function"), c->name(), params, args, &ctx, &fn_env, this); Backtrace here(backtrace(), c->pstate(), ", in function `" + c->name() + "`"); exp.backtrace_stack.push_back(&here); - ctx.callee_stack.push_back({ - c->name().c_str(), - c->pstate().path, - c->pstate().line + 1, - c->pstate().column + 1, - SASS_CALLEE_FUNCTION, - { env } - }); + ctx.callee_stack.push_back( + { c->name().c_str(), c->pstate().path, c->pstate().line + 1, c->pstate().column + 1, SASS_CALLEE_FUNCTION, { env } }); // eval the body if user-defined or special, invoke underlying CPP function if native - if (body /* && !Prelexer::re_special_fun(name.c_str()) */) { + if (body /* && !Prelexer::re_special_fun(name.c_str()) */) + { result = body->perform(this); } - else if (func) { + else if (func) + { result = func(fn_env, *env, ctx, def->signature(), c->pstate(), backtrace(), exp.selector_stack); } - if (!result) { + if (!result) + { error(std::string("Function ") + c->name() + " did not return a value", c->pstate()); } exp.backtrace_stack.pop_back(); @@ -1026,9 +1172,11 @@ namespace Sass { // else if it's a user-defined c function // convert call into C-API compatible form - else if (c_function) { + else if (c_function) + { Sass_Function_Fn c_func = sass_function_get_function(c_function); - if (full_name == "*[f]") { + if (full_name == "*[f]") + { String_Quoted_Obj str = SASS_MEMORY_NEW(String_Quoted, c->pstate(), c->name()); Arguments_Obj new_args = SASS_MEMORY_NEW(Arguments, c->pstate()); new_args->append(SASS_MEMORY_NEW(Argument, c->pstate(), str)); @@ -1042,18 +1190,13 @@ namespace Sass { Backtrace here(backtrace(), c->pstate(), ", in function `" + c->name() + "`"); exp.backtrace_stack.push_back(&here); - ctx.callee_stack.push_back({ - c->name().c_str(), - c->pstate().path, - c->pstate().line + 1, - c->pstate().column + 1, - SASS_CALLEE_C_FUNCTION, - { env } - }); + ctx.callee_stack.push_back( + { c->name().c_str(), c->pstate().path, c->pstate().line + 1, c->pstate().column + 1, SASS_CALLEE_C_FUNCTION, { env } }); To_C to_c; union Sass_Value* c_args = sass_make_list(params->length(), SASS_COMMA, false); - for(size_t i = 0; i < params->length(); i++) { + for (size_t i = 0; i < params->length(); i++) + { Parameter_Obj param = params->at(i); std::string key = param->name(); AST_Node_Obj node = fn_env.get_local(key); @@ -1061,24 +1204,27 @@ namespace Sass { sass_list_set_value(c_args, i, arg->perform(&to_c)); } union Sass_Value* c_val = c_func(c_args, c_function, ctx.c_compiler); - if (sass_value_get_tag(c_val) == SASS_ERROR) { - error("error in C function " + c->name() + ": " + sass_error_get_message(c_val), c->pstate(), backtrace()); - } else if (sass_value_get_tag(c_val) == SASS_WARNING) { - error("warning in C function " + c->name() + ": " + sass_warning_get_message(c_val), c->pstate(), backtrace()); + if (sass_value_get_tag(c_val) == SASS_ERROR) + { + error("error in C function " + c->name() + ": " + sass_error_get_message(c_val), + c->pstate(), backtrace()); + } + else if (sass_value_get_tag(c_val) == SASS_WARNING) + { + error("warning in C function " + c->name() + ": " + sass_warning_get_message(c_val), + c->pstate(), backtrace()); } result = cval_to_astnode(c_val, backtrace(), c->pstate()); exp.backtrace_stack.pop_back(); ctx.callee_stack.pop_back(); sass_delete_value(c_args); - if (c_val != c_args) - sass_delete_value(c_val); + if (c_val != c_args) sass_delete_value(c_val); } // link back to function definition // only do this for custom functions - if (result->pstate().file == std::string::npos) - result->pstate(c->pstate()); + if (result->pstate().file == std::string::npos) result->pstate(c->pstate()); result = result->perform(this); result->is_interpolant(c->is_interpolant()); @@ -1102,15 +1248,17 @@ namespace Sass { Env* env = environment(); const std::string& name(v->name()); EnvResult rv(env->find(name)); - if (rv.found) value = static_cast(rv.it->second.ptr()); - else error("Undefined variable: \"" + v->name() + "\".", v->pstate()); + if (rv.found) + value = static_cast(rv.it->second.ptr()); + else + error("Undefined variable: \"" + v->name() + "\".", v->pstate()); if (Argument_Ptr arg = Cast(value)) value = arg->value(); if (Number_Ptr nr = Cast(value)) nr->zero(true); // force flag value->is_interpolant(v->is_interpolant()); if (force) value->is_expanded(false); value->set_delayed(false); // verified value = value->perform(this); - if(!force) rv.it->second = value; + if (!force) rv.it->second = value; return value.detach(); } @@ -1129,13 +1277,16 @@ namespace Sass { return b; } - void Eval::interpolation(Context& ctx, std::string& res, Expression_Obj ex, bool into_quotes, bool was_itpl) { + void Eval::interpolation(Context& ctx, std::string& res, Expression_Obj ex, bool into_quotes, bool was_itpl) + { bool needs_closing_brace = false; - if (Arguments_Ptr args = Cast(ex)) { + if (Arguments_Ptr args = Cast(ex)) + { List_Ptr ll = SASS_MEMORY_NEW(List, args->pstate(), 0, SASS_COMMA); - for(auto arg : args->elements()) { + for (auto arg : args->elements()) + { ll->append(arg->value()); } ll->is_interpolant(args->is_interpolant()); @@ -1143,48 +1294,63 @@ namespace Sass { res += "("; ex = ll; } - if (Number_Ptr nr = Cast(ex)) { - if (!nr->is_valid_css_unit()) { + if (Number_Ptr nr = Cast(ex)) + { + if (!nr->is_valid_css_unit()) + { throw Exception::InvalidValue(*nr); } } - if (Argument_Ptr arg = Cast(ex)) { + if (Argument_Ptr arg = Cast(ex)) + { ex = arg->value(); } - if (String_Quoted_Ptr sq = Cast(ex)) { - if (was_itpl) { + if (String_Quoted_Ptr sq = Cast(ex)) + { + if (was_itpl) + { bool was_interpolant = ex->is_interpolant(); ex = SASS_MEMORY_NEW(String_Constant, sq->pstate(), sq->value()); ex->is_interpolant(was_interpolant); } } - if (Cast(ex)) { return; } + if (Cast(ex)) + { + return; + } // parent selector needs another go - if (Cast(ex)) { + if (Cast(ex)) + { // XXX: this is never hit via spec tests ex = ex->perform(this); } - if (List_Ptr l = Cast(ex)) { + if (List_Ptr l = Cast(ex)) + { List_Obj ll = SASS_MEMORY_NEW(List, l->pstate(), 0, l->separator()); // this fixes an issue with bourbon sample, not really sure why // if (l->size() && Cast((*l)[0])) { res += ""; } - for(Expression_Obj item : *l) { + for (Expression_Obj item : *l) + { item->is_interpolant(l->is_interpolant()); - std::string rl(""); interpolation(ctx, rl, item, into_quotes, l->is_interpolant()); + std::string rl(""); + interpolation(ctx, rl, item, into_quotes, l->is_interpolant()); bool is_null = Cast(item) != 0; // rl != "" if (!is_null) ll->append(SASS_MEMORY_NEW(String_Quoted, item->pstate(), rl)); } // Check indicates that we probably should not get a list // here. Normally single list items are already unwrapped. - if (l->size() > 1) { + if (l->size() > 1) + { // string_to_output would fail "#{'_\a' '_\a'}"; std::string str(ll->to_string(ctx.c_options)); newline_to_space(str); // replace directly res += str; // append to result string - } else { + } + else + { res += (ll->to_string(ctx.c_options)); } ll->is_interpolant(l->is_interpolant()); @@ -1197,49 +1363,66 @@ namespace Sass { // String_Constant // Parent_Selector // Binary_Expression - else { + else + { // ex = ex->perform(this); - if (into_quotes && ex->is_interpolant()) { + if (into_quotes && ex->is_interpolant()) + { res += evacuate_escapes(ex ? ex->to_string(ctx.c_options) : ""); - } else { + } + else + { res += ex ? ex->to_string(ctx.c_options) : ""; } } if (needs_closing_brace) res += ")"; - } Expression_Ptr Eval::operator()(String_Schema_Ptr s) { size_t L = s->length(); bool into_quotes = false; - if (L > 1) { - if (!Cast((*s)[0]) && !Cast((*s)[L - 1])) { - if (String_Constant_Ptr l = Cast((*s)[0])) { - if (String_Constant_Ptr r = Cast((*s)[L - 1])) { - if (r->value().size() > 0) { - if (l->value()[0] == '"' && r->value()[r->value().size() - 1] == '"') into_quotes = true; - if (l->value()[0] == '\'' && r->value()[r->value().size() - 1] == '\'') into_quotes = true; + if (L > 1) + { + if (!Cast((*s)[0]) && !Cast((*s)[L - 1])) + { + if (String_Constant_Ptr l = Cast((*s)[0])) + { + if (String_Constant_Ptr r = Cast((*s)[L - 1])) + { + if (r->value().size() > 0) + { + if (l->value()[0] == '"' && r->value()[r->value().size() - 1] == '"') + into_quotes = true; + if (l->value()[0] == '\'' && r->value()[r->value().size() - 1] == '\'') + into_quotes = true; + } } } } - } } bool was_quoted = false; bool was_interpolant = false; std::string res(""); - for (size_t i = 0; i < L; ++i) { + for (size_t i = 0; i < L; ++i) + { bool is_quoted = Cast((*s)[i]) != NULL; - if (was_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) { res += " "; } - else if (i > 0 && is_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) { res += " "; } + if (was_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) + { + res += " "; + } + else if (i > 0 && is_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) + { + res += " "; + } Expression_Obj ex = (*s)[i]->perform(this); interpolation(ctx, res, ex, into_quotes, ex->is_interpolant()); was_quoted = Cast((*s)[i]) != NULL; was_interpolant = (*s)[i]->is_interpolant(); - } - if (!s->is_interpolant()) { + if (!s->is_interpolant()) + { if (s->length() > 1 && res == "") return SASS_MEMORY_NEW(Null, s->pstate()); return SASS_MEMORY_NEW(String_Constant, s->pstate(), res); } @@ -1247,8 +1430,10 @@ namespace Sass { String_Quoted_Obj str = SASS_MEMORY_NEW(String_Quoted, s->pstate(), res, 0, false, false, false); // if (s->is_interpolant()) str->quote_mark(0); // String_Constant_Ptr str = SASS_MEMORY_NEW(String_Constant, s->pstate(), res); - if (str->quote_mark()) str->quote_mark('*'); - else if (!is_in_comment) str->value(string_to_output(str->value())); + if (str->quote_mark()) + str->quote_mark('*'); + else if (!is_in_comment) + str->value(string_to_output(str->value())); str->is_interpolant(s->is_interpolant()); return str.detach(); } @@ -1256,7 +1441,8 @@ namespace Sass { Expression_Ptr Eval::operator()(String_Constant_Ptr s) { - if (!s->is_delayed() && name_to_color(s->value())) { + if (!s->is_delayed() && name_to_color(s->value())) + { Color_Ptr c = SASS_MEMORY_COPY(name_to_color(s->value())); // copy c->pstate(s->pstate()); c->disp(s->value()); @@ -1279,20 +1465,16 @@ namespace Sass { { Expression_Ptr left = c->left()->perform(this); Expression_Ptr right = c->right()->perform(this); - Supports_Operator_Ptr cc = SASS_MEMORY_NEW(Supports_Operator, - c->pstate(), - Cast(left), - Cast(right), - c->operand()); + Supports_Operator_Ptr cc = SASS_MEMORY_NEW(Supports_Operator, c->pstate(), Cast(left), + Cast(right), c->operand()); return cc; } Expression_Ptr Eval::operator()(Supports_Negation_Ptr c) { Expression_Ptr condition = c->condition()->perform(this); - Supports_Negation_Ptr cc = SASS_MEMORY_NEW(Supports_Negation, - c->pstate(), - Cast(condition)); + Supports_Negation_Ptr cc = + SASS_MEMORY_NEW(Supports_Negation, c->pstate(), Cast(condition)); return cc; } @@ -1300,19 +1482,14 @@ namespace Sass { { Expression_Ptr feature = c->feature()->perform(this); Expression_Ptr value = c->value()->perform(this); - Supports_Declaration_Ptr cc = SASS_MEMORY_NEW(Supports_Declaration, - c->pstate(), - feature, - value); + Supports_Declaration_Ptr cc = SASS_MEMORY_NEW(Supports_Declaration, c->pstate(), feature, value); return cc; } Expression_Ptr Eval::operator()(Supports_Interpolation_Ptr c) { Expression_Ptr value = c->value()->perform(this); - Supports_Interpolation_Ptr cc = SASS_MEMORY_NEW(Supports_Interpolation, - c->pstate(), - value); + Supports_Interpolation_Ptr cc = SASS_MEMORY_NEW(Supports_Interpolation, c->pstate(), value); return cc; } @@ -1322,10 +1499,7 @@ namespace Sass { feature = (feature ? feature->perform(this) : 0); Expression_Obj value = e->value(); value = (value ? value->perform(this) : 0); - Expression_Ptr ee = SASS_MEMORY_NEW(At_Root_Query, - e->pstate(), - Cast(feature), - value); + Expression_Ptr ee = SASS_MEMORY_NEW(At_Root_Query, e->pstate(), Cast(feature), value); return ee; } @@ -1333,13 +1507,10 @@ namespace Sass { { String_Obj t = q->media_type(); t = static_cast(t.isNull() ? 0 : t->perform(this)); - Media_Query_Obj qq = SASS_MEMORY_NEW(Media_Query, - q->pstate(), - t, - q->length(), - q->is_negated(), - q->is_restricted()); - for (size_t i = 0, L = q->length(); i < L; ++i) { + Media_Query_Obj qq = + SASS_MEMORY_NEW(Media_Query, q->pstate(), t, q->length(), q->is_negated(), q->is_restricted()); + for (size_t i = 0, L = q->length(); i < L; ++i) + { qq->append(static_cast((*q)[i]->perform(this))); } return qq.detach(); @@ -1349,24 +1520,18 @@ namespace Sass { { Expression_Obj feature = e->feature(); feature = (feature ? feature->perform(this) : 0); - if (feature && Cast(feature)) { - feature = SASS_MEMORY_NEW(String_Quoted, - feature->pstate(), - Cast(feature)->value()); + if (feature && Cast(feature)) + { + feature = SASS_MEMORY_NEW(String_Quoted, feature->pstate(), Cast(feature)->value()); } Expression_Obj value = e->value(); value = (value ? value->perform(this) : 0); - if (value && Cast(value)) { + if (value && Cast(value)) + { // XXX: this is never hit via spec tests - value = SASS_MEMORY_NEW(String_Quoted, - value->pstate(), - Cast(value)->value()); - } - return SASS_MEMORY_NEW(Media_Query_Expression, - e->pstate(), - feature, - value, - e->is_interpolated()); + value = SASS_MEMORY_NEW(String_Quoted, value->pstate(), Cast(value)->value()); + } + return SASS_MEMORY_NEW(Media_Query_Expression, e->pstate(), feature, value, e->is_interpolated()); } Expression_Ptr Eval::operator()(Null_Ptr n) @@ -1380,42 +1545,39 @@ namespace Sass { bool is_rest_argument = a->is_rest_argument(); bool is_keyword_argument = a->is_keyword_argument(); - if (a->is_rest_argument()) { - if (val->concrete_type() == Expression::MAP) { + if (a->is_rest_argument()) + { + if (val->concrete_type() == Expression::MAP) + { is_rest_argument = false; is_keyword_argument = true; } - else if(val->concrete_type() != Expression::LIST) { - List_Obj wrapper = SASS_MEMORY_NEW(List, - val->pstate(), - 0, - SASS_COMMA, - true); + else if (val->concrete_type() != Expression::LIST) + { + List_Obj wrapper = SASS_MEMORY_NEW(List, val->pstate(), 0, SASS_COMMA, true); wrapper->append(val); val = wrapper; } } - return SASS_MEMORY_NEW(Argument, - a->pstate(), - val, - a->name(), - is_rest_argument, - is_keyword_argument); + return SASS_MEMORY_NEW(Argument, a->pstate(), val, a->name(), is_rest_argument, is_keyword_argument); } Expression_Ptr Eval::operator()(Arguments_Ptr a) { Arguments_Obj aa = SASS_MEMORY_NEW(Arguments, a->pstate()); if (a->length() == 0) return aa.detach(); - for (size_t i = 0, L = a->length(); i < L; ++i) { + for (size_t i = 0, L = a->length(); i < L; ++i) + { Expression_Obj rv = (*a)[i]->perform(this); Argument_Ptr arg = Cast(rv); - if (!(arg->is_rest_argument() || arg->is_keyword_argument())) { + if (!(arg->is_rest_argument() || arg->is_keyword_argument())) + { aa->append(arg); } } - if (a->has_rest_argument()) { + if (a->has_rest_argument()) + { Expression_Obj rest = a->get_rest_argument()->perform(this); Expression_Obj splat = Cast(rest)->value()->perform(this); @@ -1423,27 +1585,32 @@ namespace Sass { List_Ptr ls = Cast(splat); Map_Ptr ms = Cast(splat); - List_Obj arglist = SASS_MEMORY_NEW(List, - splat->pstate(), - 0, - ls ? ls->separator() : separator, - true); + List_Obj arglist = SASS_MEMORY_NEW(List, splat->pstate(), 0, ls ? ls->separator() : separator, true); - if (ls && ls->is_arglist()) { + if (ls && ls->is_arglist()) + { arglist->concat(ls); - } else if (ms) { + } + else if (ms) + { aa->append(SASS_MEMORY_NEW(Argument, splat->pstate(), ms, "", false, true)); - } else if (ls) { + } + else if (ls) + { arglist->concat(ls); - } else { + } + else + { arglist->append(splat); } - if (arglist->length()) { + if (arglist->length()) + { aa->append(SASS_MEMORY_NEW(Argument, splat->pstate(), arglist, "", true)); } } - if (a->has_keyword_argument()) { + if (a->has_keyword_argument()) + { Expression_Obj rv = a->get_keyword_argument()->perform(this); Argument_Ptr rvarg = Cast(rv); Expression_Obj kwarg = rvarg->value()->perform(this); @@ -1481,15 +1648,18 @@ namespace Sass { return *l < *r; } - Value_Ptr Eval::op_numbers(enum Sass_OP op, const Number& l, const Number& r, struct Sass_Inspect_Options opt, const ParserState& pstate) + Value_Ptr + Eval::op_numbers(enum Sass_OP op, const Number& l, const Number& r, struct Sass_Inspect_Options opt, const ParserState& pstate) { double lv = l.value(); double rv = r.value(); - if (op == Sass_OP::DIV && rv == 0) { + if (op == Sass_OP::DIV && rv == 0) + { // XXX: this is never hit via spec tests return SASS_MEMORY_NEW(String_Quoted, pstate, lv ? "Infinity" : "NaN"); } - if (op == Sass_OP::MOD && !rv) { + if (op == Sass_OP::MOD && !rv) + { // XXX: this is never hit via spec tests throw Exception::ZeroDivisionError(l, r); } @@ -1499,10 +1669,14 @@ namespace Sass { size_t r_n_units = r.denominator_units().size(); size_t r_d_units = r.denominator_units().size(); // optimize out the most common and simplest case - if (l_n_units == r_n_units && l_d_units == r_d_units) { - if (l_n_units + l_d_units <= 1 && r_n_units + r_d_units <= 1) { - if (l.numerator_units() == r.numerator_units()) { - if (l.denominator_units() == r.denominator_units()) { + if (l_n_units == r_n_units && l_d_units == r_d_units) + { + if (l_n_units + l_d_units <= 1 && r_n_units + r_d_units <= 1) + { + if (l.numerator_units() == r.numerator_units()) + { + if (l.denominator_units() == r.denominator_units()) + { Number_Ptr v = SASS_MEMORY_COPY(&l); v->value(ops[op](lv, rv)); return v; @@ -1518,29 +1692,38 @@ namespace Sass { std::string r_unit(tmp.unit()); Number_Obj v = SASS_MEMORY_COPY(&l); // copy v->pstate(pstate); - if (l_unit.empty() && (op == Sass_OP::ADD || op == Sass_OP::SUB || op == Sass_OP::MOD)) { + if (l_unit.empty() && (op == Sass_OP::ADD || op == Sass_OP::SUB || op == Sass_OP::MOD)) + { v->numerator_units() = r.numerator_units(); v->denominator_units() = r.denominator_units(); } - if (op == Sass_OP::MUL) { + if (op == Sass_OP::MUL) + { v->value(ops[op](lv, rv)); - for (size_t i = 0, S = r.numerator_units().size(); i < S; ++i) { + for (size_t i = 0, S = r.numerator_units().size(); i < S; ++i) + { v->numerator_units().push_back(r.numerator_units()[i]); } - for (size_t i = 0, S = r.denominator_units().size(); i < S; ++i) { + for (size_t i = 0, S = r.denominator_units().size(); i < S; ++i) + { v->denominator_units().push_back(r.denominator_units()[i]); } } - else if (op == Sass_OP::DIV) { + else if (op == Sass_OP::DIV) + { v->value(ops[op](lv, rv)); - for (size_t i = 0, S = r.numerator_units().size(); i < S; ++i) { + for (size_t i = 0, S = r.numerator_units().size(); i < S; ++i) + { v->denominator_units().push_back(r.numerator_units()[i]); } - for (size_t i = 0, S = r.denominator_units().size(); i < S; ++i) { + for (size_t i = 0, S = r.denominator_units().size(); i < S; ++i) + { v->numerator_units().push_back(r.denominator_units()[i]); } - } else { + } + else + { v->value(ops[op](lv, r.value() * r.convert_factor(l))); // v->normalize(); return v.detach(); @@ -1549,71 +1732,77 @@ namespace Sass { return v.detach(); } - Value_Ptr Eval::op_number_color(enum Sass_OP op, const Number& l, const Color& r, struct Sass_Inspect_Options opt, const ParserState& pstate) + Value_Ptr Eval::op_number_color(enum Sass_OP op, + const Number& l, + const Color& r, + struct Sass_Inspect_Options opt, + const ParserState& pstate) { double lv = l.value(); - switch (op) { - case Sass_OP::ADD: - case Sass_OP::MUL: { - return SASS_MEMORY_NEW(Color, - pstate, - ops[op](lv, r.r()), - ops[op](lv, r.g()), - ops[op](lv, r.b()), - r.a()); - } - case Sass_OP::SUB: - case Sass_OP::DIV: { - std::string sep(op == Sass_OP::SUB ? "-" : "/"); - std::string color(r.to_string(opt)); - return SASS_MEMORY_NEW(String_Quoted, - pstate, - l.to_string(opt) - + sep - + color); - } - case Sass_OP::MOD: { - throw Exception::UndefinedOperation(&l, &r, sass_op_to_name(op)); - } - default: break; // caller should ensure that we don't get here + switch (op) + { + case Sass_OP::ADD: + case Sass_OP::MUL: + { + return SASS_MEMORY_NEW(Color, pstate, ops[op](lv, r.r()), ops[op](lv, r.g()), + ops[op](lv, r.b()), r.a()); + } + case Sass_OP::SUB: + case Sass_OP::DIV: + { + std::string sep(op == Sass_OP::SUB ? "-" : "/"); + std::string color(r.to_string(opt)); + return SASS_MEMORY_NEW(String_Quoted, pstate, l.to_string(opt) + sep + color); + } + case Sass_OP::MOD: + { + throw Exception::UndefinedOperation(&l, &r, sass_op_to_name(op)); + } + default: + break; // caller should ensure that we don't get here } // unreachable return NULL; } - Value_Ptr Eval::op_color_number(enum Sass_OP op, const Color& l, const Number& r, struct Sass_Inspect_Options opt, const ParserState& pstate) + Value_Ptr Eval::op_color_number(enum Sass_OP op, + const Color& l, + const Number& r, + struct Sass_Inspect_Options opt, + const ParserState& pstate) { double rv = r.value(); - if (op == Sass_OP::DIV && !rv) { + if (op == Sass_OP::DIV && !rv) + { // comparison of Fixnum with Float failed? throw Exception::ZeroDivisionError(l, r); } - return SASS_MEMORY_NEW(Color, - pstate, - ops[op](l.r(), rv), - ops[op](l.g(), rv), - ops[op](l.b(), rv), - l.a()); + return SASS_MEMORY_NEW(Color, pstate, ops[op](l.r(), rv), ops[op](l.g(), rv), + ops[op](l.b(), rv), l.a()); } - Value_Ptr Eval::op_colors(enum Sass_OP op, const Color& l, const Color& r, struct Sass_Inspect_Options opt, const ParserState& pstate) + Value_Ptr + Eval::op_colors(enum Sass_OP op, const Color& l, const Color& r, struct Sass_Inspect_Options opt, const ParserState& pstate) { - if (l.a() != r.a()) { + if (l.a() != r.a()) + { throw Exception::AlphaChannelsNotEqual(&l, &r, "+"); } - if (op == Sass_OP::DIV && (!r.r() || !r.g() ||!r.b())) { + if (op == Sass_OP::DIV && (!r.r() || !r.g() || !r.b())) + { // comparison of Fixnum with Float failed? throw Exception::ZeroDivisionError(l, r); } - return SASS_MEMORY_NEW(Color, - pstate, - ops[op](l.r(), r.r()), - ops[op](l.g(), r.g()), - ops[op](l.b(), r.b()), - l.a()); + return SASS_MEMORY_NEW(Color, pstate, ops[op](l.r(), r.r()), ops[op](l.g(), r.g()), + ops[op](l.b(), r.b()), l.a()); } - Value_Ptr Eval::op_strings(Sass::Operand operand, Value& lhs, Value& rhs, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed) + Value_Ptr Eval::op_strings(Sass::Operand operand, + Value& lhs, + Value& rhs, + struct Sass_Inspect_Options opt, + const ParserState& pstate, + bool delayed) { Expression::Concrete_Type ltype = lhs.concrete_type(); Expression::Concrete_Type rtype = rhs.concrete_type(); @@ -1625,37 +1814,62 @@ namespace Sass { std::string lstr(lqstr ? lqstr->value() : lhs.to_string(opt)); std::string rstr(rqstr ? rqstr->value() : rhs.to_string(opt)); - if (ltype == Expression::NULL_VAL) throw Exception::InvalidNullOperation(&lhs, &rhs, sass_op_to_name(op)); - if (rtype == Expression::NULL_VAL) throw Exception::InvalidNullOperation(&lhs, &rhs, sass_op_to_name(op)); + if (ltype == Expression::NULL_VAL) + throw Exception::InvalidNullOperation(&lhs, &rhs, sass_op_to_name(op)); + if (rtype == Expression::NULL_VAL) + throw Exception::InvalidNullOperation(&lhs, &rhs, sass_op_to_name(op)); std::string sep; - switch (op) { - case Sass_OP::SUB: sep = "-"; break; - case Sass_OP::DIV: sep = "/"; break; - // cases are already handled above - case Sass_OP::EQ: sep = "=="; break; - case Sass_OP::NEQ: sep = "!="; break; - case Sass_OP::LT: sep = "<"; break; - case Sass_OP::GT: sep = ">"; break; - case Sass_OP::LTE: sep = "<="; break; - case Sass_OP::GTE: sep = ">="; break; - case Sass_OP::MUL: throw Exception::UndefinedOperation(&lhs, &rhs, sass_op_to_name(op)); - case Sass_OP::MOD: throw Exception::UndefinedOperation(&lhs, &rhs, sass_op_to_name(op)); - default: break; - } - - if ( (sep == "") /* && - (sep != "/" || !rqstr || !rqstr->quote_mark()) */ - ) { + switch (op) + { + case Sass_OP::SUB: + sep = "-"; + break; + case Sass_OP::DIV: + sep = "/"; + break; + // cases are already handled above + case Sass_OP::EQ: + sep = "=="; + break; + case Sass_OP::NEQ: + sep = "!="; + break; + case Sass_OP::LT: + sep = "<"; + break; + case Sass_OP::GT: + sep = ">"; + break; + case Sass_OP::LTE: + sep = "<="; + break; + case Sass_OP::GTE: + sep = ">="; + break; + case Sass_OP::MUL: + throw Exception::UndefinedOperation(&lhs, &rhs, sass_op_to_name(op)); + case Sass_OP::MOD: + throw Exception::UndefinedOperation(&lhs, &rhs, sass_op_to_name(op)); + default: + break; + } + + if ((sep == "") /* && + (sep != "/" || !rqstr || !rqstr->quote_mark()) */ + ) + { // create a new string that might be quoted on output (but do not unquote what we pass) return SASS_MEMORY_NEW(String_Quoted, pstate, lstr + rstr, 0, false, true); } - if (sep != "" && !delayed) { + if (sep != "" && !delayed) + { if (operand.ws_before) sep = " " + sep; if (operand.ws_after) sep = sep + " "; } - if (op == Sass_OP::SUB || op == Sass_OP::DIV) { + if (op == Sass_OP::SUB || op == Sass_OP::DIV) + { if (lqstr && lqstr->quote_mark()) lstr = quote(lstr); if (rqstr && rqstr->quote_mark()) rstr = quote(rstr); } @@ -1668,50 +1882,73 @@ namespace Sass { using std::strlen; using std::strcpy; Expression_Ptr e = NULL; - switch (sass_value_get_tag(v)) { - case SASS_BOOLEAN: { - e = SASS_MEMORY_NEW(Boolean, pstate, !!sass_boolean_get_value(v)); - } break; - case SASS_NUMBER: { - e = SASS_MEMORY_NEW(Number, pstate, sass_number_get_value(v), sass_number_get_unit(v)); - } break; - case SASS_COLOR: { - e = SASS_MEMORY_NEW(Color, pstate, sass_color_get_r(v), sass_color_get_g(v), sass_color_get_b(v), sass_color_get_a(v)); - } break; - case SASS_STRING: { - if (sass_string_is_quoted(v)) - e = SASS_MEMORY_NEW(String_Quoted, pstate, sass_string_get_value(v)); - else { - e = SASS_MEMORY_NEW(String_Constant, pstate, sass_string_get_value(v)); - } - } break; - case SASS_LIST: { - List_Ptr l = SASS_MEMORY_NEW(List, pstate, sass_list_get_length(v), sass_list_get_separator(v)); - for (size_t i = 0, L = sass_list_get_length(v); i < L; ++i) { - l->append(cval_to_astnode(sass_list_get_value(v, i), backtrace, pstate)); - } - l->is_bracketed(sass_list_get_is_bracketed(v)); - e = l; - } break; - case SASS_MAP: { - Map_Ptr m = SASS_MEMORY_NEW(Map, pstate); - for (size_t i = 0, L = sass_map_get_length(v); i < L; ++i) { - *m << std::make_pair( - cval_to_astnode(sass_map_get_key(v, i), backtrace, pstate), - cval_to_astnode(sass_map_get_value(v, i), backtrace, pstate)); - } - e = m; - } break; - case SASS_NULL: { - e = SASS_MEMORY_NEW(Null, pstate); - } break; - case SASS_ERROR: { - error("Error in C function: " + std::string(sass_error_get_message(v)), pstate, backtrace); - } break; - case SASS_WARNING: { - error("Warning in C function: " + std::string(sass_warning_get_message(v)), pstate, backtrace); - } break; - default: break; + switch (sass_value_get_tag(v)) + { + case SASS_BOOLEAN: + { + e = SASS_MEMORY_NEW(Boolean, pstate, !!sass_boolean_get_value(v)); + } + break; + case SASS_NUMBER: + { + e = SASS_MEMORY_NEW(Number, pstate, sass_number_get_value(v), sass_number_get_unit(v)); + } + break; + case SASS_COLOR: + { + e = SASS_MEMORY_NEW(Color, pstate, sass_color_get_r(v), sass_color_get_g(v), + sass_color_get_b(v), sass_color_get_a(v)); + } + break; + case SASS_STRING: + { + if (sass_string_is_quoted(v)) + e = SASS_MEMORY_NEW(String_Quoted, pstate, sass_string_get_value(v)); + else + { + e = SASS_MEMORY_NEW(String_Constant, pstate, sass_string_get_value(v)); + } + } + break; + case SASS_LIST: + { + List_Ptr l = SASS_MEMORY_NEW(List, pstate, sass_list_get_length(v), sass_list_get_separator(v)); + for (size_t i = 0, L = sass_list_get_length(v); i < L; ++i) + { + l->append(cval_to_astnode(sass_list_get_value(v, i), backtrace, pstate)); + } + l->is_bracketed(sass_list_get_is_bracketed(v)); + e = l; + } + break; + case SASS_MAP: + { + Map_Ptr m = SASS_MEMORY_NEW(Map, pstate); + for (size_t i = 0, L = sass_map_get_length(v); i < L; ++i) + { + *m << std::make_pair(cval_to_astnode(sass_map_get_key(v, i), backtrace, pstate), + cval_to_astnode(sass_map_get_value(v, i), backtrace, pstate)); + } + e = m; + } + break; + case SASS_NULL: + { + e = SASS_MEMORY_NEW(Null, pstate); + } + break; + case SASS_ERROR: + { + error("Error in C function: " + std::string(sass_error_get_message(v)), pstate, backtrace); + } + break; + case SASS_WARNING: + { + error("Warning in C function: " + std::string(sass_warning_get_message(v)), pstate, backtrace); + } + break; + default: + break; } return e; } @@ -1723,27 +1960,33 @@ namespace Sass { sl->is_optional(s->is_optional()); sl->media_block(s->media_block()); sl->is_optional(s->is_optional()); - for (size_t i = 0, iL = s->length(); i < iL; ++i) { + for (size_t i = 0, iL = s->length(); i < iL; ++i) + { rv.push_back(operator()((*s)[i])); } // we should actually permutate parent first // but here we have permutated the selector first size_t round = 0; - while (round != std::string::npos) { + while (round != std::string::npos) + { bool abort = true; - for (size_t i = 0, iL = rv.size(); i < iL; ++i) { - if (rv[i]->length() > round) { + for (size_t i = 0, iL = rv.size(); i < iL; ++i) + { + if (rv[i]->length() > round) + { sl->append((*rv[i])[round]); abort = false; } } - if (abort) { + if (abort) + { round = std::string::npos; - } else { - ++ round; } - + else + { + ++round; + } } return sl.detach(); } @@ -1759,7 +2002,10 @@ namespace Sass { Attribute_Selector_Ptr Eval::operator()(Attribute_Selector_Ptr s) { String_Obj attr = s->value(); - if (attr) { attr = static_cast(attr->perform(this)); } + if (attr) + { + attr = static_cast(attr->perform(this)); + } Attribute_Selector_Ptr ss = SASS_MEMORY_COPY(s); ss->value(attr); return ss; @@ -1781,14 +2027,16 @@ namespace Sass { Expression_Ptr Eval::operator()(Parent_Selector_Ptr p) { - if (Selector_List_Obj pr = selector()) { + if (Selector_List_Obj pr = selector()) + { exp.selector_stack.pop_back(); Selector_List_Obj rv = operator()(pr); exp.selector_stack.push_back(rv); return rv.detach(); - } else { + } + else + { return SASS_MEMORY_NEW(Null, p->pstate()); } } - } diff --git a/src/eval.hpp b/src/eval.hpp index 4fe0bcb1eb..fdff13c063 100644 --- a/src/eval.hpp +++ b/src/eval.hpp @@ -7,18 +7,20 @@ #include "operation.hpp" #include "environment.hpp" -namespace Sass { +namespace Sass +{ class Expand; class Context; - class Eval : public Operation_CRTP { + class Eval : public Operation_CRTP + { - private: + private: Expression_Ptr fallback_impl(AST_Node_Ptr n); - public: - Expand& exp; + public: + Expand& exp; Context& ctx; Eval(Expand& exp); ~Eval(); @@ -76,36 +78,59 @@ namespace Sass { Selector_List_Ptr operator()(Complex_Selector_Ptr); Attribute_Selector_Ptr operator()(Attribute_Selector_Ptr); // they don't have any specific implementatio (yet) - Element_Selector_Ptr operator()(Element_Selector_Ptr s) { return s; }; - Pseudo_Selector_Ptr operator()(Pseudo_Selector_Ptr s) { return s; }; - Wrapped_Selector_Ptr operator()(Wrapped_Selector_Ptr s) { return s; }; - Class_Selector_Ptr operator()(Class_Selector_Ptr s) { return s; }; - Id_Selector_Ptr operator()(Id_Selector_Ptr s) { return s; }; - Placeholder_Selector_Ptr operator()(Placeholder_Selector_Ptr s) { return s; }; + Element_Selector_Ptr operator()(Element_Selector_Ptr s) + { + return s; + }; + Pseudo_Selector_Ptr operator()(Pseudo_Selector_Ptr s) + { + return s; + }; + Wrapped_Selector_Ptr operator()(Wrapped_Selector_Ptr s) + { + return s; + }; + Class_Selector_Ptr operator()(Class_Selector_Ptr s) + { + return s; + }; + Id_Selector_Ptr operator()(Id_Selector_Ptr s) + { + return s; + }; + Placeholder_Selector_Ptr operator()(Placeholder_Selector_Ptr s) + { + return s; + }; // actual evaluated selectors Selector_List_Ptr operator()(Selector_Schema_Ptr); Expression_Ptr operator()(Parent_Selector_Ptr); - template - Expression_Ptr fallback(U x) { return fallback_impl(x); } + template Expression_Ptr fallback(U x) + { + return fallback_impl(x); + } // -- only need to define two comparisons, and the rest can be implemented in terms of them static bool eq(Expression_Obj, Expression_Obj); static bool lt(Expression_Obj, Expression_Obj, std::string op); // -- arithmetic on the combinations that matter - static Value_Ptr op_numbers(enum Sass_OP, const Number&, const Number&, struct Sass_Inspect_Options opt, const ParserState& pstate); - static Value_Ptr op_number_color(enum Sass_OP, const Number&, const Color&, struct Sass_Inspect_Options opt, const ParserState& pstate); - static Value_Ptr op_color_number(enum Sass_OP, const Color&, const Number&, struct Sass_Inspect_Options opt, const ParserState& pstate); - static Value_Ptr op_colors(enum Sass_OP, const Color&, const Color&, struct Sass_Inspect_Options opt, const ParserState& pstate); - static Value_Ptr op_strings(Sass::Operand, Value&, Value&, struct Sass_Inspect_Options opt, const ParserState& pstate, bool interpolant = false); - - private: + static Value_Ptr + op_numbers(enum Sass_OP, const Number&, const Number&, struct Sass_Inspect_Options opt, const ParserState& pstate); + static Value_Ptr + op_number_color(enum Sass_OP, const Number&, const Color&, struct Sass_Inspect_Options opt, const ParserState& pstate); + static Value_Ptr + op_color_number(enum Sass_OP, const Color&, const Number&, struct Sass_Inspect_Options opt, const ParserState& pstate); + static Value_Ptr + op_colors(enum Sass_OP, const Color&, const Color&, struct Sass_Inspect_Options opt, const ParserState& pstate); + static Value_Ptr + op_strings(Sass::Operand, Value&, Value&, struct Sass_Inspect_Options opt, const ParserState& pstate, bool interpolant = false); + + private: void interpolation(Context& ctx, std::string& res, Expression_Obj ex, bool into_quotes, bool was_itpl = false); - }; Expression_Ptr cval_to_astnode(union Sass_Value* v, Backtrace* backtrace, ParserState pstate = ParserState("[AST]")); - } #endif diff --git a/src/expand.cpp b/src/expand.cpp index 78f2ab0e17..44ea6f6503 100644 --- a/src/expand.cpp +++ b/src/expand.cpp @@ -11,31 +11,31 @@ #include "parser.hpp" #include "sass_functions.hpp" -namespace Sass { +namespace Sass +{ // simple endless recursion protection const size_t maxRecursion = 500; Expand::Expand(Context& ctx, Env* env, Backtrace* bt, std::vector* stack) - : ctx(ctx), - eval(Eval(*this)), - recursions(0), - in_keyframes(false), - at_root_without_rule(false), - old_at_root_without_rule(false), - env_stack(std::vector()), - block_stack(std::vector()), - call_stack(std::vector()), + : ctx(ctx), eval(Eval(*this)), recursions(0), in_keyframes(false), at_root_without_rule(false), + old_at_root_without_rule(false), env_stack(std::vector()), + block_stack(std::vector()), call_stack(std::vector()), selector_stack(std::vector()), - media_block_stack(std::vector()), - backtrace_stack(std::vector()) + media_block_stack(std::vector()), backtrace_stack(std::vector()) { env_stack.push_back(0); env_stack.push_back(env); block_stack.push_back(0); call_stack.push_back(0); - if (stack == NULL) { selector_stack.push_back(0); } - else { selector_stack.insert(selector_stack.end(), stack->begin(), stack->end()); } + if (stack == NULL) + { + selector_stack.push_back(0); + } + else + { + selector_stack.insert(selector_stack.end(), stack->begin(), stack->end()); + } media_block_stack.push_back(0); backtrace_stack.push_back(0); backtrace_stack.push_back(bt); @@ -43,22 +43,19 @@ namespace Sass { Env* Expand::environment() { - if (env_stack.size() > 0) - return env_stack.back(); + if (env_stack.size() > 0) return env_stack.back(); return 0; } Selector_List_Obj Expand::selector() { - if (selector_stack.size() > 0) - return selector_stack.back(); + if (selector_stack.size() > 0) return selector_stack.back(); return 0; } Backtrace* Expand::backtrace() { - if (backtrace_stack.size() > 0) - return backtrace_stack.back(); + if (backtrace_stack.size() > 0) return backtrace_stack.back(); return 0; } @@ -69,10 +66,7 @@ namespace Sass { // set the current env as parent Env env(environment()); // copy the block object (add items later) - Block_Obj bb = SASS_MEMORY_NEW(Block, - b->pstate(), - b->length(), - b->is_root()); + Block_Obj bb = SASS_MEMORY_NEW(Block, b->pstate(), b->length(), b->is_root()); // setup block and env stack this->block_stack.push_back(bb); this->env_stack.push_back(&env); @@ -90,11 +84,14 @@ namespace Sass { { LOCAL_FLAG(old_at_root_without_rule, at_root_without_rule); - if (in_keyframes) { + if (in_keyframes) + { Block_Ptr bb = operator()(r->block()); Keyframe_Rule_Obj k = SASS_MEMORY_NEW(Keyframe_Rule, r->pstate(), bb); - if (r->selector()) { - if (Selector_List_Ptr s = r->selector()) { + if (r->selector()) + { + if (Selector_List_Ptr s = r->selector()) + { selector_stack.push_back(0); k->name(s->eval(eval)); selector_stack.pop_back(); @@ -108,7 +105,8 @@ namespace Sass { // `&` is allowed in `@at-root`! bool has_parent_selector = false; - for (size_t i = 0, L = selector_stack.size(); i < L && !has_parent_selector; i++) { + for (size_t i = 0, L = selector_stack.size(); i < L && !has_parent_selector; i++) + { Selector_List_Obj ll = selector_stack.at(i); has_parent_selector = ll != 0 && ll->length() > 0; } @@ -117,44 +115,55 @@ namespace Sass { if (sel) sel = sel->eval(eval); // check for parent selectors in base level rules - if (r->is_root()) { - if (Selector_List_Ptr selector_list = Cast(r->selector())) { - for (Complex_Selector_Obj complex_selector : selector_list->elements()) { + if (r->is_root()) + { + if (Selector_List_Ptr selector_list = Cast(r->selector())) + { + for (Complex_Selector_Obj complex_selector : selector_list->elements()) + { Complex_Selector_Ptr tail = complex_selector; - while (tail) { - if (tail->head()) for (Simple_Selector_Obj header : tail->head()->elements()) { - Parent_Selector_Ptr ptr = Cast(header); - if (ptr == NULL || (!ptr->real() || has_parent_selector)) continue; - std::string sel_str(complex_selector->to_string(ctx.c_options)); - error("Base-level rules cannot contain the parent-selector-referencing character '&'.", header->pstate(), backtrace()); - } + while (tail) + { + if (tail->head()) + for (Simple_Selector_Obj header : tail->head()->elements()) + { + Parent_Selector_Ptr ptr = Cast(header); + if (ptr == NULL || (!ptr->real() || has_parent_selector)) continue; + std::string sel_str(complex_selector->to_string(ctx.c_options)); + error( + "Base-level rules cannot contain the parent-selector-referencing character '&'.", + header->pstate(), backtrace()); + } tail = tail->tail(); } } } } - else { - if (sel->length() == 0 || sel->has_parent_ref()) { - if (sel->has_real_parent_ref() && !has_parent_selector) { - error("Base-level rules cannot contain the parent-selector-referencing character '&'.", sel->pstate(), backtrace()); + else + { + if (sel->length() == 0 || sel->has_parent_ref()) + { + if (sel->has_real_parent_ref() && !has_parent_selector) + { + error("Base-level rules cannot contain the parent-selector-referencing character '&'.", + sel->pstate(), backtrace()); } } } selector_stack.push_back(sel); Env env(environment()); - if (block_stack.back()->is_root()) { + if (block_stack.back()->is_root()) + { env_stack.push_back(&env); } sel->set_media_block(media_block_stack.back()); Block_Obj blk = 0; if (r->block()) blk = operator()(r->block()); - Ruleset_Ptr rr = SASS_MEMORY_NEW(Ruleset, - r->pstate(), - sel, - blk); + Ruleset_Ptr rr = SASS_MEMORY_NEW(Ruleset, r->pstate(), sel, blk); selector_stack.pop_back(); - if (block_stack.back()->is_root()) { + if (block_stack.back()->is_root()) + { env_stack.pop_back(); } @@ -167,10 +176,8 @@ namespace Sass { Statement_Ptr Expand::operator()(Supports_Block_Ptr f) { Expression_Obj condition = f->condition()->perform(&eval); - Supports_Block_Obj ff = SASS_MEMORY_NEW(Supports_Block, - f->pstate(), - Cast(condition), - operator()(f->block())); + Supports_Block_Obj ff = SASS_MEMORY_NEW(Supports_Block, f->pstate(), + Cast(condition), operator()(f->block())); return ff.detach(); } @@ -186,10 +193,7 @@ namespace Sass { cpy->media_queries(mq); media_block_stack.push_back(cpy); Block_Obj blk = operator()(m->block()); - Media_Block_Ptr mm = SASS_MEMORY_NEW(Media_Block, - m->pstate(), - mq, - blk); + Media_Block_Ptr mm = SASS_MEMORY_NEW(Media_Block, m->pstate(), mq, blk); media_block_stack.pop_back(); mm->tabs(m->tabs()); return mm; @@ -200,19 +204,18 @@ namespace Sass { Block_Obj ab = a->block(); Expression_Obj ae = a->expression(); - if (ae) ae = ae->perform(&eval); - else ae = SASS_MEMORY_NEW(At_Root_Query, a->pstate()); + if (ae) + ae = ae->perform(&eval); + else + ae = SASS_MEMORY_NEW(At_Root_Query, a->pstate()); LOCAL_FLAG(at_root_without_rule, true); LOCAL_FLAG(in_keyframes, false); - ; + ; Block_Obj bb = ab ? operator()(ab) : NULL; - At_Root_Block_Obj aa = SASS_MEMORY_NEW(At_Root_Block, - a->pstate(), - bb, - Cast(ae)); + At_Root_Block_Obj aa = SASS_MEMORY_NEW(At_Root_Block, a->pstate(), bb, Cast(ae)); return aa.detach(); } @@ -227,12 +230,7 @@ namespace Sass { if (as) as = eval(as); selector_stack.pop_back(); Block_Ptr bb = ab ? operator()(ab) : NULL; - Directive_Ptr aa = SASS_MEMORY_NEW(Directive, - a->pstate(), - a->keyword(), - as, - bb, - av); + Directive_Ptr aa = SASS_MEMORY_NEW(Directive, a->pstate(), a->keyword(), as, bb, av); return aa; } @@ -243,21 +241,18 @@ namespace Sass { Expression_Obj prop = old_p->perform(&eval); String_Obj new_p = Cast(prop); // we might get a color back - if (!new_p) { + if (!new_p) + { std::string str(prop->to_string(ctx.c_options)); new_p = SASS_MEMORY_NEW(String_Constant, old_p->pstate(), str); } Expression_Obj value = d->value()->perform(&eval); Block_Obj bb = ab ? operator()(ab) : NULL; - if (!bb) { + if (!bb) + { if (!value || (value->is_invisible() && !d->is_important())) return 0; } - Declaration_Ptr decl = SASS_MEMORY_NEW(Declaration, - d->pstate(), - new_p, - value, - d->is_important(), - bb); + Declaration_Ptr decl = SASS_MEMORY_NEW(Declaration, d->pstate(), new_p, value, d->is_important(), bb); decl->tabs(d->tabs()); return decl; } @@ -266,34 +261,47 @@ namespace Sass { { Env* env = environment(); const std::string& var(a->variable()); - if (a->is_global()) { - if (a->is_default()) { - if (env->has_global(var)) { + if (a->is_global()) + { + if (a->is_default()) + { + if (env->has_global(var)) + { Expression_Obj e = Cast(env->get_global(var)); - if (!e || e->concrete_type() == Expression::NULL_VAL) { + if (!e || e->concrete_type() == Expression::NULL_VAL) + { env->set_global(var, a->value()->perform(&eval)); } } - else { + else + { env->set_global(var, a->value()->perform(&eval)); } } - else { + else + { env->set_global(var, a->value()->perform(&eval)); } } - else if (a->is_default()) { - if (env->has_lexical(var)) { + else if (a->is_default()) + { + if (env->has_lexical(var)) + { auto cur = env; - while (cur && cur->is_lexical()) { - if (cur->has_local(var)) { - if (AST_Node_Obj node = cur->get_local(var)) { + while (cur && cur->is_lexical()) + { + if (cur->has_local(var)) + { + if (AST_Node_Obj node = cur->get_local(var)) + { Expression_Obj e = Cast(node); - if (!e || e->concrete_type() == Expression::NULL_VAL) { + if (!e || e->concrete_type() == Expression::NULL_VAL) + { cur->set_local(var, a->value()->perform(&eval)); } } - else { + else + { throw std::runtime_error("Env not in sync"); } return 0; @@ -302,22 +310,28 @@ namespace Sass { } throw std::runtime_error("Env not in sync"); } - else if (env->has_global(var)) { - if (AST_Node_Obj node = env->get_global(var)) { + else if (env->has_global(var)) + { + if (AST_Node_Obj node = env->get_global(var)) + { Expression_Obj e = Cast(node); - if (!e || e->concrete_type() == Expression::NULL_VAL) { + if (!e || e->concrete_type() == Expression::NULL_VAL) + { env->set_global(var, a->value()->perform(&eval)); } } } - else if (env->is_lexical()) { + else if (env->is_lexical()) + { env->set_local(var, a->value()->perform(&eval)); } - else { + else + { env->set_local(var, a->value()->perform(&eval)); } } - else { + else + { env->set_lexical(var, a->value()->perform(&eval)); } return 0; @@ -326,11 +340,13 @@ namespace Sass { Statement_Ptr Expand::operator()(Import_Ptr imp) { Import_Obj result = SASS_MEMORY_NEW(Import, imp->pstate()); - if (imp->import_queries() && imp->import_queries()->size()) { + if (imp->import_queries() && imp->import_queries()->size()) + { Expression_Obj ex = imp->import_queries()->perform(&eval); result->import_queries(Cast(ex)); } - for ( size_t i = 0, S = imp->urls().size(); i < S; ++i) { + for (size_t i = 0, S = imp->urls().size(); i < S; ++i) + { result->urls().push_back(imp->urls()[i]->perform(&eval)); } // all resources have been dropped for Input_Stubs @@ -342,15 +358,12 @@ namespace Sass { { // get parent node from call stack AST_Node_Obj parent = call_stack.back(); - if (Cast(parent) == NULL) { + if (Cast(parent) == NULL) + { error("Import directives may not be used within control directives or mixins.", i->pstate()); } // we don't seem to need that actually afterall - Sass_Import_Entry import = sass_make_import( - i->imp_path().c_str(), - i->abs_path().c_str(), - 0, 0 - ); + Sass_Import_Entry import = sass_make_import(i->imp_path().c_str(), i->abs_path().c_str(), 0, 0); ctx.import_stack.push_back(import); const std::string& abs_path(i->resource().abs_path); append_block(ctx.sheets.at(abs_path).root); @@ -383,7 +396,8 @@ namespace Sass { Statement_Ptr Expand::operator()(Comment_Ptr c) { eval.is_in_comment = true; - Comment_Ptr rv = SASS_MEMORY_NEW(Comment, c->pstate(), Cast(c->text()->perform(&eval)), c->is_important()); + Comment_Ptr rv = + SASS_MEMORY_NEW(Comment, c->pstate(), Cast(c->text()->perform(&eval)), c->is_important()); eval.is_in_comment = false; // TODO: eval the text, once we're parsing/storing it as a String_Schema return rv; @@ -395,10 +409,12 @@ namespace Sass { env_stack.push_back(&env); call_stack.push_back(i); Expression_Obj rv = i->predicate()->perform(&eval); - if (*rv) { + if (*rv) + { append_block(i->block()); } - else { + else + { Block_Ptr alt = i->alternative(); if (alt) append_block(alt); } @@ -413,20 +429,22 @@ namespace Sass { { std::string variable(f->variable()); Expression_Obj low = f->lower_bound()->perform(&eval); - if (low->concrete_type() != Expression::NUMBER) { + if (low->concrete_type() != Expression::NUMBER) + { throw Exception::TypeMismatch(*low, "integer"); } Expression_Obj high = f->upper_bound()->perform(&eval); - if (high->concrete_type() != Expression::NUMBER) { + if (high->concrete_type() != Expression::NUMBER) + { throw Exception::TypeMismatch(*high, "integer"); } Number_Obj sass_start = Cast(low); Number_Obj sass_end = Cast(high); // check if units are valid for sequence - if (sass_start->unit() != sass_end->unit()) { - std::stringstream msg; msg << "Incompatible units: '" - << sass_start->unit() << "' and '" - << sass_end->unit() << "'."; + if (sass_start->unit() != sass_end->unit()) + { + std::stringstream msg; + msg << "Incompatible units: '" << sass_start->unit() << "' and '" << sass_end->unit() << "'."; error(msg.str(), low->pstate(), backtrace()); } double start = sass_start->value(); @@ -436,20 +454,21 @@ namespace Sass { env_stack.push_back(&env); call_stack.push_back(f); Block_Ptr body = f->block(); - if (start < end) { + if (start < end) + { if (f->is_inclusive()) ++end; - for (double i = start; - i < end; - ++i) { + for (double i = start; i < end; ++i) + { Number_Obj it = SASS_MEMORY_NEW(Number, low->pstate(), i, sass_end->unit()); env.set_local(variable, it); append_block(body); } - } else { + } + else + { if (f->is_inclusive()) --end; - for (double i = start; - i > end; - --i) { + for (double i = start; i > end; --i) + { Number_Obj it = SASS_MEMORY_NEW(Number, low->pstate(), i, sass_end->unit()); env.set_local(variable, it); append_block(body); @@ -468,19 +487,23 @@ namespace Sass { Expression_Obj expr = e->list()->perform(&eval); List_Obj list = 0; Map_Obj map; - if (expr->concrete_type() == Expression::MAP) { + if (expr->concrete_type() == Expression::MAP) + { map = Cast(expr); } - else if (Selector_List_Ptr ls = Cast(expr)) { + else if (Selector_List_Ptr ls = Cast(expr)) + { Listize listize; Expression_Obj rv = ls->perform(&listize); list = Cast(rv); } - else if (expr->concrete_type() != Expression::LIST) { + else if (expr->concrete_type() != Expression::LIST) + { list = SASS_MEMORY_NEW(List, expr->pstate(), 1, SASS_COMMA); list->append(expr); } - else { + else + { list = Cast(expr); } // remember variables and then reset them @@ -489,50 +512,66 @@ namespace Sass { call_stack.push_back(e); Block_Ptr body = e->block(); - if (map) { - for (auto key : map->keys()) { + if (map) + { + for (auto key : map->keys()) + { Expression_Obj k = key->perform(&eval); Expression_Obj v = map->at(key)->perform(&eval); - if (variables.size() == 1) { + if (variables.size() == 1) + { List_Obj variable = SASS_MEMORY_NEW(List, map->pstate(), 2, SASS_SPACE); variable->append(k); variable->append(v); env.set_local(variables[0], variable); - } else { + } + else + { env.set_local(variables[0], k); env.set_local(variables[1], v); } append_block(body); } } - else { + else + { // bool arglist = list->is_arglist(); - if (list->length() == 1 && Cast(list)) { + if (list->length() == 1 && Cast(list)) + { list = Cast(list); } - for (size_t i = 0, L = list->length(); i < L; ++i) { + for (size_t i = 0, L = list->length(); i < L; ++i) + { Expression_Obj item = list->at(i); // unwrap value if the expression is an argument if (Argument_Obj arg = Cast(item)) item = arg->value(); // check if we got passed a list of args (investigate) - if (List_Obj scalars = Cast(item)) { - if (variables.size() == 1) { + if (List_Obj scalars = Cast(item)) + { + if (variables.size() == 1) + { List_Obj var = scalars; // if (arglist) var = (*scalars)[0]; env.set_local(variables[0], var); - } else { - for (size_t j = 0, K = variables.size(); j < K; ++j) { - Expression_Obj res = j >= scalars->length() - ? SASS_MEMORY_NEW(Null, expr->pstate()) - : (*scalars)[j]->perform(&eval); + } + else + { + for (size_t j = 0, K = variables.size(); j < K; ++j) + { + Expression_Obj res = j >= scalars->length() ? SASS_MEMORY_NEW(Null, expr->pstate()) : + (*scalars)[j]->perform(&eval); env.set_local(variables[j], res); } } - } else { - if (variables.size() > 0) { + } + else + { + if (variables.size() > 0) + { env.set_local(variables.at(0), item); - for (size_t j = 1, K = variables.size(); j < K; ++j) { + for (size_t j = 1, K = variables.size(); j < K; ++j) + { Expression_Obj res = SASS_MEMORY_NEW(Null, expr->pstate()); env.set_local(variables[j], res); } @@ -554,7 +593,8 @@ namespace Sass { env_stack.push_back(&env); call_stack.push_back(w); Expression_Obj cond = pred->perform(&eval); - while (!cond->is_false()) { + while (!cond->is_false()) + { append_block(body); cond = pred->perform(&eval); } @@ -570,17 +610,24 @@ namespace Sass { } - void Expand::expand_selector_list(Selector_Obj s, Selector_List_Obj extender) { + void Expand::expand_selector_list(Selector_Obj s, Selector_List_Obj extender) + { - if (Selector_List_Obj sl = Cast(s)) { - for (Complex_Selector_Obj complex_selector : sl->elements()) { + if (Selector_List_Obj sl = Cast(s)) + { + for (Complex_Selector_Obj complex_selector : sl->elements()) + { Complex_Selector_Obj tail = complex_selector; - while (tail) { - if (tail->head()) for (Simple_Selector_Obj header : tail->head()->elements()) { - if (Cast(header) == NULL) continue; // skip all others - std::string sel_str(complex_selector->to_string(ctx.c_options)); - error("Can't extend " + sel_str + ": can't extend parent selectors", header->pstate(), backtrace()); - } + while (tail) + { + if (tail->head()) + for (Simple_Selector_Obj header : tail->head()->elements()) + { + if (Cast(header) == NULL) continue; // skip all others + std::string sel_str(complex_selector->to_string(ctx.c_options)); + error("Can't extend " + sel_str + ": can't extend parent selectors", header->pstate(), + backtrace()); + } tail = tail->tail(); } } @@ -589,18 +636,20 @@ namespace Sass { Selector_List_Obj contextualized = Cast(s->perform(&eval)); if (contextualized == false) return; - for (auto complex_sel : contextualized->elements()) { + for (auto complex_sel : contextualized->elements()) + { Complex_Selector_Obj c = complex_sel; - if (!c->head() || c->tail()) { + if (!c->head() || c->tail()) + { std::string sel_str(contextualized->to_string(ctx.c_options)); error("Can't extend " + sel_str + ": can't extend nested selectors", c->pstate(), backtrace()); } Compound_Selector_Obj target = c->head(); if (contextualized->is_optional()) target->is_optional(true); - for (size_t i = 0, L = extender->length(); i < L; ++i) { + for (size_t i = 0, L = extender->length(); i < L; ++i) + { Complex_Selector_Obj sel = (*extender)[i]; - if (!(sel->head() && sel->head()->length() > 0 && - Cast((*sel->head())[0]))) + if (!(sel->head() && sel->head()->length() > 0 && Cast((*sel->head())[0]))) { Compound_Selector_Obj hh = SASS_MEMORY_NEW(Compound_Selector, (*extender)[i]->pstate()); hh->media_block((*extender)[i]->media_block()); @@ -618,30 +667,36 @@ namespace Sass { ctx.subset_map.put(target, std::make_pair(sel, target)); } } - } Statement* Expand::operator()(Extension_Ptr e) { - if (Selector_List_Ptr extender = selector()) { + if (Selector_List_Ptr extender = selector()) + { Selector_List_Ptr sl = e->selector(); // abort on invalid selector if (sl == NULL) return NULL; - if (Selector_Schema_Ptr schema = sl->schema()) { - if (schema->has_real_parent_ref()) { + if (Selector_Schema_Ptr schema = sl->schema()) + { + if (schema->has_real_parent_ref()) + { // put root block on stack again (ignore parents) // selector schema must not connect in eval! block_stack.push_back(block_stack.at(1)); sl = eval(sl->schema()); block_stack.pop_back(); - } else { + } + else + { selector_stack.push_back(0); sl = eval(sl->schema()); selector_stack.pop_back(); } } - for (Complex_Selector_Obj cs : sl->elements()) { - if (!cs.isNull() && !cs->head().isNull()) { + for (Complex_Selector_Obj cs : sl->elements()) + { + if (!cs.isNull() && !cs->head().isNull()) + { cs->head()->media_block(media_block_stack.back()); } } @@ -656,20 +711,13 @@ namespace Sass { { Env* env = environment(); Definition_Obj dd = SASS_MEMORY_COPY(d); - env->local_frame()[d->name() + - (d->type() == Definition::MIXIN ? "[m]" : "[f]")] = dd; - - if (d->type() == Definition::FUNCTION && ( - Prelexer::calc_fn_call(d->name().c_str()) || - d->name() == "element" || - d->name() == "expression" || - d->name() == "url" - )) { - deprecated( - "Naming a function \"" + d->name() + "\" is disallowed", - "This name conflicts with an existing CSS function with special parse rules.", - d->pstate() - ); + env->local_frame()[d->name() + (d->type() == Definition::MIXIN ? "[m]" : "[f]")] = dd; + + if (d->type() == Definition::FUNCTION && (Prelexer::calc_fn_call(d->name().c_str()) || d->name() == "element" || + d->name() == "expression" || d->name() == "url")) + { + deprecated("Naming a function \"" + d->name() + "\" is disallowed", + "This name conflicts with an existing CSS function with special parse rules.", d->pstate()); } // set the static link so we can have lexical scoping @@ -680,47 +728,42 @@ namespace Sass { Statement_Ptr Expand::operator()(Mixin_Call_Ptr c) { - if (recursions > maxRecursion) { + if (recursions > maxRecursion) + { throw Exception::StackError(*c); } - recursions ++; + recursions++; Env* env = environment(); std::string full_name(c->name() + "[m]"); - if (!env->has(full_name)) { + if (!env->has(full_name)) + { error("no mixin named " + c->name(), c->pstate(), backtrace()); } Definition_Obj def = Cast((*env)[full_name]); Block_Obj body = def->block(); Parameters_Obj params = def->parameters(); - if (c->block() && c->name() != "@content" && !body->has_content()) { + if (c->block() && c->name() != "@content" && !body->has_content()) + { error("Mixin \"" + c->name() + "\" does not accept a content block.", c->pstate(), backtrace()); } Expression_Obj rv = c->arguments()->perform(&eval); Arguments_Obj args = Cast(rv); Backtrace new_bt(backtrace(), c->pstate(), ", in mixin `" + c->name() + "`"); backtrace_stack.push_back(&new_bt); - ctx.callee_stack.push_back({ - c->name().c_str(), - c->pstate().path, - c->pstate().line + 1, - c->pstate().column + 1, - SASS_CALLEE_MIXIN, - { env } - }); + ctx.callee_stack.push_back( + { c->name().c_str(), c->pstate().path, c->pstate().line + 1, c->pstate().column + 1, SASS_CALLEE_MIXIN, { env } }); Env new_env(def->environment()); env_stack.push_back(&new_env); - if (c->block()) { + if (c->block()) + { // represent mixin content blocks as thunks/closures - Definition_Obj thunk = SASS_MEMORY_NEW(Definition, - c->pstate(), - "@content", - SASS_MEMORY_NEW(Parameters, c->pstate()), - c->block(), - Definition::MIXIN); + Definition_Obj thunk = + SASS_MEMORY_NEW(Definition, c->pstate(), "@content", SASS_MEMORY_NEW(Parameters, c->pstate()), + c->block(), Definition::MIXIN); thunk->environment(env); new_env.local_frame()["@content[m]"] = thunk; } @@ -732,7 +775,8 @@ namespace Sass { block_stack.push_back(trace_block); - for (auto bb : body->elements()) { + for (auto bb : body->elements()) + { Statement_Obj ith = bb->perform(this); if (ith) trace->block()->append(ith); } @@ -742,7 +786,7 @@ namespace Sass { backtrace_stack.pop_back(); ctx.callee_stack.pop_back(); - recursions --; + recursions--; return trace.detach(); } @@ -752,18 +796,18 @@ namespace Sass { // convert @content directives into mixin calls to the underlying thunk if (!env->has("@content[m]")) return 0; - if (block_stack.back()->is_root()) { + if (block_stack.back()->is_root()) + { selector_stack.push_back(0); } - Mixin_Call_Obj call = SASS_MEMORY_NEW(Mixin_Call, - c->pstate(), - "@content", - SASS_MEMORY_NEW(Arguments, c->pstate())); + Mixin_Call_Obj call = + SASS_MEMORY_NEW(Mixin_Call, c->pstate(), "@content", SASS_MEMORY_NEW(Arguments, c->pstate())); Trace_Obj trace = Cast(call->perform(this)); - if (block_stack.back()->is_root()) { + if (block_stack.back()->is_root()) + { selector_stack.pop_back(); } @@ -773,7 +817,7 @@ namespace Sass { // produce an error if something is not implemented inline Statement_Ptr Expand::fallback_impl(AST_Node_Ptr n) { - std::string err =std:: string("`Expand` doesn't handle ") + typeid(*n).name(); + std::string err = std::string("`Expand` doesn't handle ") + typeid(*n).name(); String_Quoted_Obj msg = SASS_MEMORY_NEW(String_Quoted, ParserState("[WARN]"), err); error("unknown internal error; please contact the LibSass maintainers", n->pstate(), backtrace()); return SASS_MEMORY_NEW(Warning, ParserState("[WARN]"), msg); @@ -783,12 +827,12 @@ namespace Sass { inline void Expand::append_block(Block_Ptr b) { if (b->is_root()) call_stack.push_back(b); - for (size_t i = 0, L = b->length(); i < L; ++i) { + for (size_t i = 0, L = b->length(); i < L; ++i) + { Statement_Ptr stm = b->at(i); Statement_Obj ith = stm->perform(this); if (ith) block_stack.back()->append(ith); } if (b->is_root()) call_stack.pop_back(); } - } diff --git a/src/expand.hpp b/src/expand.hpp index 2d0d5ecea2..0d5a478faa 100644 --- a/src/expand.hpp +++ b/src/expand.hpp @@ -8,43 +8,46 @@ #include "operation.hpp" #include "environment.hpp" -namespace Sass { +namespace Sass +{ class Listize; class Context; class Eval; struct Backtrace; - class Expand : public Operation_CRTP { - public: - + class Expand : public Operation_CRTP + { + public: Env* environment(); Selector_List_Obj selector(); Backtrace* backtrace(); - Context& ctx; - Eval eval; - size_t recursions; - bool in_keyframes; - bool at_root_without_rule; - bool old_at_root_without_rule; + Context& ctx; + Eval eval; + size_t recursions; + bool in_keyframes; + bool at_root_without_rule; + bool old_at_root_without_rule; // it's easier to work with vectors - std::vector env_stack; - std::vector block_stack; - std::vector call_stack; + std::vector env_stack; + std::vector block_stack; + std::vector call_stack; std::vector selector_stack; - std::vector media_block_stack; - std::vector backtrace_stack; + std::vector media_block_stack; + std::vector backtrace_stack; Statement_Ptr fallback_impl(AST_Node_Ptr n); - private: + private: void expand_selector_list(Selector_Obj, Selector_List_Obj extender); - public: + public: Expand(Context&, Env*, Backtrace*, std::vector* stack = NULL); - ~Expand() { } + ~Expand() + { + } Block_Ptr operator()(Block_Ptr); Statement_Ptr operator()(Ruleset_Ptr); @@ -70,12 +73,13 @@ namespace Sass { Statement_Ptr operator()(Mixin_Call_Ptr); Statement_Ptr operator()(Content_Ptr); - template - Statement_Ptr fallback(U x) { return fallback_impl(x); } + template Statement_Ptr fallback(U x) + { + return fallback_impl(x); + } void append_block(Block_Ptr); }; - } #endif diff --git a/src/extend.cpp b/src/extend.cpp index 9341d8d59f..a9d55b80f1 100644 --- a/src/extend.cpp +++ b/src/extend.cpp @@ -15,19 +15,28 @@ /* NOTES: - - The print* functions print to cerr. This allows our testing frameworks (like sass-spec) to ignore the output, which - is very helpful when debugging. The format of the output is mainly to wrap things in square brackets to match what + - The print* functions print to cerr. This allows our testing frameworks (like sass-spec) to ignore + the output, which + is very helpful when debugging. The format of the output is mainly to wrap things in square + brackets to match what ruby already outputs (to make comparisons easier). - - For the direct porting effort, we're trying to port method-for-method until we get all the tests passing. - Where applicable, I've tried to include the ruby code above the function for reference until all our tests pass. - The ruby code isn't always directly portable, so I've tried to include any modified ruby code that was actually + - For the direct porting effort, we're trying to port method-for-method until we get all the tests + passing. + Where applicable, I've tried to include the ruby code above the function for reference until all + our tests pass. + The ruby code isn't always directly portable, so I've tried to include any modified ruby code + that was actually used for the porting. - - DO NOT try to optimize yet. We get a tremendous benefit out of comparing the output of each stage of the extend to the ruby - output at the same stage. This makes it much easier to determine where problems are. Try to keep as close to - the ruby code as you can until we have all the sass-spec tests passing. Then, we should optimize. However, if you see - something that could probably be optimized, let's not forget it. Add a // TODO: or // IMPROVEMENT: comment. + - DO NOT try to optimize yet. We get a tremendous benefit out of comparing the output of each stage + of the extend to the ruby + output at the same stage. This makes it much easier to determine where problems are. Try to keep + as close to + the ruby code as you can until we have all the sass-spec tests passing. Then, we should optimize. + However, if you see + something that could probably be optimized, let's not forget it. Add a // TODO: or // + IMPROVEMENT: comment. - Coding conventions in this file (these may need to be changed before merging back into master) - Very basic hungarian notation: @@ -37,119 +46,161 @@ - prefer verbose naming over terse naming - use typedefs for STL container types for make maintenance easier - - You may see a lot of comments that say "// TODO: is this the correct combinator?". See the comment referring to combinators - in extendCompoundSelector for a more extensive explanation of my confusion. I think our divergence in data model from ruby + - You may see a lot of comments that say "// TODO: is this the correct combinator?". See the + comment referring to combinators + in extendCompoundSelector for a more extensive explanation of my confusion. I think our + divergence in data model from ruby sass causes this to be necessary. GLOBAL TODOS: - - wrap the contents of the print functions in DEBUG preprocesser conditionals so they will be optimized away in non-debug mode. + - wrap the contents of the print functions in DEBUG preprocesser conditionals so they will be + optimized away in non-debug mode. - - consider making the extend* functions member functions to avoid passing around ctx and subset_map map around. This has the - drawback that the implementation details of the operator are then exposed to the outside world, which is not ideal and + - consider making the extend* functions member functions to avoid passing around ctx and subset_map + map around. This has the + drawback that the implementation details of the operator are then exposed to the outside world, + which is not ideal and can cause additional compile time dependencies. - mark the helper methods in this file static to given them compilation unit linkage. - implement parent directive matching - - fix compilation warnings for unused Extend members if we really don't need those references anymore. + - fix compilation warnings for unused Extend members if we really don't need those references + anymore. */ -namespace Sass { - +namespace Sass +{ #ifdef DEBUG // TODO: move the ast specific ostream operators into ast.hpp/ast.cpp - std::ostream& operator<<(std::ostream& os, const Complex_Selector::Combinator combinator) { - switch (combinator) { - case Complex_Selector::ANCESTOR_OF: os << "\" \""; break; - case Complex_Selector::PARENT_OF: os << "\">\""; break; - case Complex_Selector::PRECEDES: os << "\"~\""; break; - case Complex_Selector::ADJACENT_TO: os << "\"+\""; break; - case Complex_Selector::REFERENCE: os << "\"/\""; break; + std::ostream& operator<<(std::ostream& os, const Complex_Selector::Combinator combinator) + { + switch (combinator) + { + case Complex_Selector::ANCESTOR_OF: + os << "\" \""; + break; + case Complex_Selector::PARENT_OF: + os << "\">\""; + break; + case Complex_Selector::PRECEDES: + os << "\"~\""; + break; + case Complex_Selector::ADJACENT_TO: + os << "\"+\""; + break; + case Complex_Selector::REFERENCE: + os << "\"/\""; + break; } return os; } - std::ostream& operator<<(std::ostream& os, Compound_Selector& compoundSelector) { - for (size_t i = 0, L = compoundSelector.length(); i < L; ++i) { + std::ostream& operator<<(std::ostream& os, Compound_Selector& compoundSelector) + { + for (size_t i = 0, L = compoundSelector.length(); i < L; ++i) + { if (i > 0) os << ", "; os << compoundSelector[i]->to_string(); } return os; } - std::ostream& operator<<(std::ostream& os, Simple_Selector& simpleSelector) { + std::ostream& operator<<(std::ostream& os, Simple_Selector& simpleSelector) + { os << simpleSelector.to_string(); return os; } // Print a string representation of a Compound_Selector - static void printSimpleSelector(Simple_Selector* pSimpleSelector, const char* message=NULL, bool newline=true) { + static void printSimpleSelector(Simple_Selector* pSimpleSelector, const char* message = NULL, bool newline = true) + { - if (message) { + if (message) + { std::cerr << message; } - if (pSimpleSelector) { + if (pSimpleSelector) + { std::cerr << "[" << *pSimpleSelector << "]"; - } else { + } + else + { std::cerr << "NULL"; } - if (newline) { + if (newline) + { std::cerr << std::endl; } } // Print a string representation of a Compound_Selector - static void printCompoundSelector(Compound_Selector_Ptr pCompoundSelector, const char* message=NULL, bool newline=true) { + static void + printCompoundSelector(Compound_Selector_Ptr pCompoundSelector, const char* message = NULL, bool newline = true) + { - if (message) { + if (message) + { std::cerr << message; } - if (pCompoundSelector) { + if (pCompoundSelector) + { std::cerr << "[" << *pCompoundSelector << "]"; - } else { + } + else + { std::cerr << "NULL"; } - if (newline) { + if (newline) + { std::cerr << std::endl; } } - std::ostream& operator<<(std::ostream& os, Complex_Selector& complexSelector) { + std::ostream& operator<<(std::ostream& os, Complex_Selector& complexSelector) + { os << "["; Complex_Selector_Ptr pIter = &complexSelector; bool first = true; - while (pIter) { - if (pIter->combinator() != Complex_Selector::ANCESTOR_OF) { - if (!first) { + while (pIter) + { + if (pIter->combinator() != Complex_Selector::ANCESTOR_OF) + { + if (!first) + { os << ", "; } first = false; os << pIter->combinator(); } - if (!first) { + if (!first) + { os << ", "; } first = false; - if (pIter->head()) { + if (pIter->head()) + { os << pIter->head()->to_string(); - } else { + } + else + { os << "NULL_HEAD"; } @@ -162,34 +213,46 @@ namespace Sass { // Print a string representation of a Complex_Selector - static void printComplexSelector(Complex_Selector_Ptr pComplexSelector, const char* message=NULL, bool newline=true) { + static void printComplexSelector(Complex_Selector_Ptr pComplexSelector, const char* message = NULL, bool newline = true) + { - if (message) { + if (message) + { std::cerr << message; } - if (pComplexSelector) { + if (pComplexSelector) + { std::cerr << *pComplexSelector; - } else { + } + else + { std::cerr << "NULL"; } - if (newline) { + if (newline) + { std::cerr << std::endl; } } - static void printSelsNewSeqPairCollection(SubSetMapLookups& collection, const char* message=NULL, bool newline=true) { + static void printSelsNewSeqPairCollection(SubSetMapLookups& collection, const char* message = NULL, bool newline = true) + { - if (message) { + if (message) + { std::cerr << message; } bool first = true; std::cerr << "["; - for(SubSetMapLookup& pair : collection) { - if (first) { + for (SubSetMapLookup& pair : collection) + { + if (first) + { first = false; - } else { + } + else + { std::cerr << ", "; } std::cerr << "["; @@ -200,23 +263,29 @@ namespace Sass { } std::cerr << "]"; - if (newline) { + if (newline) + { std::cerr << std::endl; } } // Print a string representation of a ComplexSelectorSet - static void printSourcesSet(ComplexSelectorSet& sources, const char* message=NULL, bool newline=true) { + static void printSourcesSet(ComplexSelectorSet& sources, const char* message = NULL, bool newline = true) + { - if (message) { + if (message) + { std::cerr << message; } - // Convert to a deque of strings so we can sort since order doesn't matter in a set. This should cut down on + // Convert to a deque of strings so we can sort since order doesn't matter in a set. This should + // cut down on // the differences we see when debug printing. typedef std::deque SourceStrings; SourceStrings sourceStrings; - for (ComplexSelectorSet::iterator iterator = sources.begin(), iteratorEnd = sources.end(); iterator != iteratorEnd; ++iterator) { + for (ComplexSelectorSet::iterator iterator = sources.begin(), iteratorEnd = sources.end(); + iterator != iteratorEnd; ++iterator) + { Complex_Selector_Ptr pSource = *iterator; std::stringstream sstream; sstream << complexSelectorToNode(pSource); @@ -227,50 +296,64 @@ namespace Sass { std::sort(sourceStrings.begin(), sourceStrings.end()); std::cerr << "ComplexSelectorSet["; - for (SourceStrings::iterator iterator = sourceStrings.begin(), iteratorEnd = sourceStrings.end(); iterator != iteratorEnd; ++iterator) { + for (SourceStrings::iterator iterator = sourceStrings.begin(), iteratorEnd = sourceStrings.end(); + iterator != iteratorEnd; ++iterator) + { std::string source = *iterator; - if (iterator != sourceStrings.begin()) { + if (iterator != sourceStrings.begin()) + { std::cerr << ", "; } std::cerr << source; } std::cerr << "]"; - if (newline) { + if (newline) + { std::cerr << std::endl; } } - std::ostream& operator<<(std::ostream& os, SubSetMapPairs& entries) { + std::ostream& operator<<(std::ostream& os, SubSetMapPairs& entries) + { os << "SUBSET_MAP_ENTRIES["; - for (SubSetMapPairs::iterator iterator = entries.begin(), endIterator = entries.end(); iterator != endIterator; ++iterator) { - Complex_Selector_Obj pExtComplexSelector = iterator->first; // The selector up to where the @extend is (ie, the thing to merge) + for (SubSetMapPairs::iterator iterator = entries.begin(), endIterator = entries.end(); + iterator != endIterator; ++iterator) + { + Complex_Selector_Obj pExtComplexSelector = + iterator->first; // The selector up to where the @extend is (ie, the thing to merge) Compound_Selector_Obj pExtCompoundSelector = iterator->second; // The stuff after the @extend - if (iterator != entries.begin()) { + if (iterator != entries.begin()) + { os << ", "; } os << "("; - if (pExtComplexSelector) { + if (pExtComplexSelector) + { std::cerr << *pExtComplexSelector; - } else { + } + else + { std::cerr << "NULL"; } os << " -> "; - if (pExtCompoundSelector) { + if (pExtCompoundSelector) + { std::cerr << *pExtCompoundSelector; - } else { + } + else + { std::cerr << "NULL"; } os << ")"; - } os << "]"; @@ -279,13 +362,17 @@ namespace Sass { } #endif - static bool parentSuperselector(Complex_Selector_Ptr pOne, Complex_Selector_Ptr pTwo) { + static bool parentSuperselector(Complex_Selector_Ptr pOne, Complex_Selector_Ptr pTwo) + { // TODO: figure out a better way to create a Complex_Selector from scratch // TODO: There's got to be a better way. This got ugly quick... - Element_Selector_Obj fakeParent = SASS_MEMORY_NEW(Element_Selector, ParserState("[FAKE]"), "temp"); + Element_Selector_Obj fakeParent = + SASS_MEMORY_NEW(Element_Selector, ParserState("[FAKE]"), "temp"); Compound_Selector_Obj fakeHead = SASS_MEMORY_NEW(Compound_Selector, ParserState("[FAKE]"), 1 /*size*/); fakeHead->elements().push_back(fakeParent); - Complex_Selector_Obj fakeParentContainer = SASS_MEMORY_NEW(Complex_Selector, ParserState("[FAKE]"), Complex_Selector::ANCESTOR_OF, fakeHead /*head*/, NULL /*tail*/); + Complex_Selector_Obj fakeParentContainer = + SASS_MEMORY_NEW(Complex_Selector, ParserState("[FAKE]"), Complex_Selector::ANCESTOR_OF, + fakeHead /*head*/, NULL /*tail*/); pOne->set_innermost(fakeParentContainer, Complex_Selector::ANCESTOR_OF); pTwo->set_innermost(fakeParentContainer, Complex_Selector::ANCESTOR_OF); @@ -298,17 +385,22 @@ namespace Sass { return isSuperselector; } - void nodeToComplexSelectorDeque(const Node& node, ComplexSelectorDeque& out) { - for (NodeDeque::iterator iter = node.collection()->begin(), iterEnd = node.collection()->end(); iter != iterEnd; iter++) { + void nodeToComplexSelectorDeque(const Node& node, ComplexSelectorDeque& out) + { + for (NodeDeque::iterator iter = node.collection()->begin(), iterEnd = node.collection()->end(); + iter != iterEnd; iter++) + { Node& child = *iter; out.push_back(nodeToComplexSelector(child)); } } - Node complexSelectorDequeToNode(const ComplexSelectorDeque& deque) { + Node complexSelectorDequeToNode(const ComplexSelectorDeque& deque) + { Node result = Node::createCollection(); - for (ComplexSelectorDeque::const_iterator iter = deque.begin(), iterEnd = deque.end(); iter != iterEnd; iter++) { + for (ComplexSelectorDeque::const_iterator iter = deque.begin(), iterEnd = deque.end(); iter != iterEnd; iter++) + { Complex_Selector_Obj pChild = *iter; result.collection()->push_back(complexSelectorToNode(pChild)); } @@ -316,11 +408,15 @@ namespace Sass { return result; } - class LcsCollectionComparator { - public: - LcsCollectionComparator() {} + class LcsCollectionComparator + { + public: + LcsCollectionComparator() + { + } - bool operator()(Complex_Selector_Obj pOne, Complex_Selector_Obj pTwo, Complex_Selector_Obj& pOut) const { + bool operator()(Complex_Selector_Obj pOne, Complex_Selector_Obj pTwo, Complex_Selector_Obj& pOut) const + { /* This code is based on the following block from ruby sass' subweave do |s1, s2| @@ -331,21 +427,25 @@ namespace Sass { end */ - if (*pOne == *pTwo) { + if (*pOne == *pTwo) + { pOut = pOne; return true; } - if (pOne->combinator() != Complex_Selector::ANCESTOR_OF || pTwo->combinator() != Complex_Selector::ANCESTOR_OF) { + if (pOne->combinator() != Complex_Selector::ANCESTOR_OF || pTwo->combinator() != Complex_Selector::ANCESTOR_OF) + { return false; } - if (parentSuperselector(pOne, pTwo)) { + if (parentSuperselector(pOne, pTwo)) + { pOut = pTwo; return true; } - if (parentSuperselector(pTwo, pOne)) { + if (parentSuperselector(pTwo, pOne)) + { pOut = pOne; return true; } @@ -359,27 +459,39 @@ namespace Sass { This is the equivalent of ruby's Sass::Util.lcs_backtrace. # Computes a single longest common subsequence for arrays x and y. - # Algorithm from http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Reading_out_an_LCS + # Algorithm from + http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Reading_out_an_LCS */ - void lcs_backtrace(const LCSTable& c, ComplexSelectorDeque& x, ComplexSelectorDeque& y, int i, int j, const LcsCollectionComparator& comparator, ComplexSelectorDeque& out) { - //DEBUG_PRINTLN(LCS, "LCSBACK: X=" << x << " Y=" << y << " I=" << i << " J=" << j) - // TODO: make printComplexSelectorDeque and use DEBUG_EXEC AND DEBUG_PRINTLN HERE to get equivalent output + void lcs_backtrace(const LCSTable& c, + ComplexSelectorDeque& x, + ComplexSelectorDeque& y, + int i, + int j, + const LcsCollectionComparator& comparator, + ComplexSelectorDeque& out) + { + // DEBUG_PRINTLN(LCS, "LCSBACK: X=" << x << " Y=" << y << " I=" << i << " J=" << j) + // TODO: make printComplexSelectorDeque and use DEBUG_EXEC AND DEBUG_PRINTLN HERE to get + // equivalent output - if (i == 0 || j == 0) { + if (i == 0 || j == 0) + { DEBUG_PRINTLN(LCS, "RETURNING EMPTY") return; } Complex_Selector_Obj pCompareOut; - if (comparator(x[i], y[j], pCompareOut)) { + if (comparator(x[i], y[j], pCompareOut)) + { DEBUG_PRINTLN(LCS, "RETURNING AFTER ELEM COMPARE") lcs_backtrace(c, x, y, i - 1, j - 1, comparator, out); out.push_back(pCompareOut); return; } - if (c[i][j - 1] > c[i - 1][j]) { + if (c[i][j - 1] > c[i - 1][j]) + { DEBUG_PRINTLN(LCS, "RETURNING AFTER TABLE COMPARE") lcs_backtrace(c, x, y, i, j - 1, comparator, out); return; @@ -394,11 +506,17 @@ namespace Sass { This is the equivalent of ruby's Sass::Util.lcs_table. # Calculates the memoization table for the Least Common Subsequence algorithm. - # Algorithm from http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Computing_the_length_of_the_LCS + # Algorithm from + http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Computing_the_length_of_the_LCS */ - void lcs_table(const ComplexSelectorDeque& x, const ComplexSelectorDeque& y, const LcsCollectionComparator& comparator, LCSTable& out) { - //DEBUG_PRINTLN(LCS, "LCSTABLE: X=" << x << " Y=" << y) - // TODO: make printComplexSelectorDeque and use DEBUG_EXEC AND DEBUG_PRINTLN HERE to get equivalent output + void lcs_table(const ComplexSelectorDeque& x, + const ComplexSelectorDeque& y, + const LcsCollectionComparator& comparator, + LCSTable& out) + { + // DEBUG_PRINTLN(LCS, "LCSTABLE: X=" << x << " Y=" << y) + // TODO: make printComplexSelectorDeque and use DEBUG_EXEC AND DEBUG_PRINTLN HERE to get + // equivalent output LCSTable c(x.size(), std::vector(y.size())); @@ -406,13 +524,18 @@ namespace Sass { // x.size.times {|i| c[i][0] = 0} // y.size.times {|j| c[0][j] = 0} - for (size_t i = 1; i < x.size(); i++) { - for (size_t j = 1; j < y.size(); j++) { + for (size_t i = 1; i < x.size(); i++) + { + for (size_t j = 1; j < y.size(); j++) + { Complex_Selector_Obj pCompareOut; - if (comparator(x[i], y[j], pCompareOut)) { + if (comparator(x[i], y[j], pCompareOut)) + { c[i][j] = c[i - 1][j - 1] + 1; - } else { + } + else + { c[i][j] = std::max(c[i][j - 1], c[i - 1][j]); } } @@ -435,9 +558,11 @@ namespace Sass { http://en.wikipedia.org/wiki/Longest_common_subsequence_problem */ - void lcs(ComplexSelectorDeque& x, ComplexSelectorDeque& y, const LcsCollectionComparator& comparator, ComplexSelectorDeque& out) { - //DEBUG_PRINTLN(LCS, "LCS: X=" << x << " Y=" << y) - // TODO: make printComplexSelectorDeque and use DEBUG_EXEC AND DEBUG_PRINTLN HERE to get equivalent output + void lcs(ComplexSelectorDeque& x, ComplexSelectorDeque& y, const LcsCollectionComparator& comparator, ComplexSelectorDeque& out) + { + // DEBUG_PRINTLN(LCS, "LCS: X=" << x << " Y=" << y) + // TODO: make printComplexSelectorDeque and use DEBUG_EXEC AND DEBUG_PRINTLN HERE to get + // equivalent output x.push_front(NULL); y.push_front(NULL); @@ -445,7 +570,8 @@ namespace Sass { LCSTable table; lcs_table(x, y, comparator, table); - return lcs_backtrace(table, x, y, static_cast(x.size()) - 1, static_cast(y.size()) - 1, comparator, out); + return lcs_backtrace(table, x, y, static_cast(x.size()) - 1, + static_cast(y.size()) - 1, comparator, out); } @@ -515,11 +641,13 @@ namespace Sass { /* - IMPROVEMENT: We could probably work directly in the output trimmed deque. */ - Node Extend::trim(Node& seqses, bool isReplace) { + Node Extend::trim(Node& seqses, bool isReplace) + { // See the comments in the above ruby code before embarking on understanding this function. // Avoid poor performance in extreme cases. - if (seqses.collection()->size() > 100) { + if (seqses.collection()->size() > 100) + { return seqses; } @@ -532,12 +660,17 @@ namespace Sass { DEBUG_PRINTLN(TRIM, "RESULT INITIAL: " << result) - // Normally we use the standard STL iterators, but in this case, we need to access the result collection by index since we're - // iterating the input collection, computing a value, and then setting the result in the output collection. We have to keep track + // Normally we use the standard STL iterators, but in this case, we need to access the result + // collection by index since we're + // iterating the input collection, computing a value, and then setting the result in the output + // collection. We have to keep track // of the index manually. int toTrimIndex = 0; - for (NodeDeque::iterator seqsesIter = seqses.collection()->begin(), seqsesIterEnd = seqses.collection()->end(); seqsesIter != seqsesIterEnd; ++seqsesIter) { + for (NodeDeque::iterator seqsesIter = seqses.collection()->begin(), + seqsesIterEnd = seqses.collection()->end(); + seqsesIter != seqsesIterEnd; ++seqsesIter) + { Node& seqs1 = *seqsesIter; DEBUG_PRINTLN(TRIM, "SEQS1: " << seqs1 << " " << toTrimIndex) @@ -545,18 +678,26 @@ namespace Sass { Node tempResult = Node::createCollection(); tempResult.got_line_feed = seqs1.got_line_feed; - for (NodeDeque::iterator seqs1Iter = seqs1.collection()->begin(), seqs1EndIter = seqs1.collection()->end(); seqs1Iter != seqs1EndIter; ++seqs1Iter) { + for (NodeDeque::iterator seqs1Iter = seqs1.collection()->begin(), + seqs1EndIter = seqs1.collection()->end(); + seqs1Iter != seqs1EndIter; ++seqs1Iter) + { Node& seq1 = *seqs1Iter; Complex_Selector_Obj pSeq1 = nodeToComplexSelector(seq1); - // Compute the maximum specificity. This requires looking at the "sources" of the sequence. See SimpleSequence.sources in the ruby code + // Compute the maximum specificity. This requires looking at the "sources" of the sequence. + // See SimpleSequence.sources in the ruby code // for a good description of sources. // - // TODO: I'm pretty sure there's a bug in the sources code. It was implemented for sass-spec's 182_test_nested_extend_loop test. - // While the test passes, I compared the state of each trim call to verify correctness. The last trim call had incorrect sources. We - // had an extra source that the ruby version did not have. Without a failing test case, this is going to be extra hard to find. My - // best guess at this point is that we're cloning an object somewhere and maintaining the sources when we shouldn't be. This is purely + // TODO: I'm pretty sure there's a bug in the sources code. It was implemented for + // sass-spec's 182_test_nested_extend_loop test. + // While the test passes, I compared the state of each trim call to verify correctness. The + // last trim call had incorrect sources. We + // had an extra source that the ruby version did not have. Without a failing test case, this + // is going to be extra hard to find. My + // best guess at this point is that we're cloning an object somewhere and maintaining the + // sources when we shouldn't be. This is purely // a guess though. unsigned long maxSpecificity = isReplace ? pSeq1->specificity() : 0; ComplexSelectorSet sources = pSeq1->sources(); @@ -564,7 +705,10 @@ namespace Sass { DEBUG_PRINTLN(TRIM, "TRIM SEQ1: " << seq1) DEBUG_EXEC(TRIM, printSourcesSet(sources, "TRIM SOURCES: ")) - for (ComplexSelectorSet::iterator sourcesSetIterator = sources.begin(), sourcesSetIteratorEnd = sources.end(); sourcesSetIterator != sourcesSetIteratorEnd; ++sourcesSetIterator) { + for (ComplexSelectorSet::iterator sourcesSetIterator = sources.begin(), + sourcesSetIteratorEnd = sources.end(); + sourcesSetIterator != sourcesSetIteratorEnd; ++sourcesSetIterator) + { const Complex_Selector_Obj& pCurrentSelector = *sourcesSetIterator; maxSpecificity = std::max(maxSpecificity, pCurrentSelector->specificity()); } @@ -575,42 +719,57 @@ namespace Sass { int resultIndex = 0; - for (NodeDeque::iterator resultIter = result.collection()->begin(), resultIterEnd = result.collection()->end(); resultIter != resultIterEnd; ++resultIter) { + for (NodeDeque::iterator resultIter = result.collection()->begin(), + resultIterEnd = result.collection()->end(); + resultIter != resultIterEnd; ++resultIter) + { Node& seqs2 = *resultIter; DEBUG_PRINTLN(TRIM, "SEQS1: " << seqs1) DEBUG_PRINTLN(TRIM, "SEQS2: " << seqs2) // Do not compare the same sequence to itself. The ruby call we're trying to - // emulate is: seqs1.equal?(seqs2). equal? is an object comparison, not an equivalency comparision. - // Since we have the same pointers in seqes and results, we can do a pointer comparision. seqs1 is + // emulate is: seqs1.equal?(seqs2). equal? is an object comparison, not an equivalency + // comparision. + // Since we have the same pointers in seqes and results, we can do a pointer comparision. + // seqs1 is // derived from seqses and seqs2 is derived from result. - if (seqs1.collection() == seqs2.collection()) { + if (seqs1.collection() == seqs2.collection()) + { DEBUG_PRINTLN(TRIM, "CONTINUE") continue; } bool isMoreSpecificInner = false; - for (NodeDeque::iterator seqs2Iter = seqs2.collection()->begin(), seqs2IterEnd = seqs2.collection()->end(); seqs2Iter != seqs2IterEnd; ++seqs2Iter) { + for (NodeDeque::iterator seqs2Iter = seqs2.collection()->begin(), + seqs2IterEnd = seqs2.collection()->end(); + seqs2Iter != seqs2IterEnd; ++seqs2Iter) + { Node& seq2 = *seqs2Iter; Complex_Selector_Obj pSeq2 = nodeToComplexSelector(seq2); DEBUG_PRINTLN(TRIM, "SEQ2 SPEC: " << pSeq2->specificity()) - DEBUG_PRINTLN(TRIM, "IS SPEC: " << pSeq2->specificity() << " >= " << maxSpecificity << " " << (pSeq2->specificity() >= maxSpecificity ? "true" : "false")) - DEBUG_PRINTLN(TRIM, "IS SUPER: " << (pSeq2->is_superselector_of(pSeq1) ? "true" : "false")) + DEBUG_PRINTLN(TRIM, + "IS SPEC: " << pSeq2->specificity() << " >= " << maxSpecificity + << " " << (pSeq2->specificity() >= maxSpecificity ? "true" : "false")) + DEBUG_PRINTLN(TRIM, + "IS SUPER: " << (pSeq2->is_superselector_of(pSeq1) ? "true" : "false")) isMoreSpecificInner = pSeq2->specificity() >= maxSpecificity && pSeq2->is_superselector_of(pSeq1); - if (isMoreSpecificInner) { + if (isMoreSpecificInner) + { DEBUG_PRINTLN(TRIM, "FOUND MORE SPECIFIC") break; } } - // If we found something more specific, we're done. Let the outer loop know and stop iterating. - if (isMoreSpecificInner) { + // If we found something more specific, we're done. Let the outer loop know and stop + // iterating. + if (isMoreSpecificInner) + { isMoreSpecificOuter = true; break; } @@ -618,11 +777,11 @@ namespace Sass { resultIndex++; } - if (!isMoreSpecificOuter) { + if (!isMoreSpecificOuter) + { DEBUG_PRINTLN(TRIM, "PUSHING: " << seq1) tempResult.collection()->push_back(seq1); } - } DEBUG_PRINTLN(TRIM, "RESULT BEFORE ASSIGN: " << result) @@ -638,14 +797,17 @@ namespace Sass { } - - static bool parentSuperselector(const Node& one, const Node& two) { + static bool parentSuperselector(const Node& one, const Node& two) + { // TODO: figure out a better way to create a Complex_Selector from scratch // TODO: There's got to be a better way. This got ugly quick... - Element_Selector_Obj fakeParent = SASS_MEMORY_NEW(Element_Selector, ParserState("[FAKE]"), "temp"); + Element_Selector_Obj fakeParent = + SASS_MEMORY_NEW(Element_Selector, ParserState("[FAKE]"), "temp"); Compound_Selector_Obj fakeHead = SASS_MEMORY_NEW(Compound_Selector, ParserState("[FAKE]"), 1 /*size*/); fakeHead->elements().push_back(fakeParent); - Complex_Selector_Obj fakeParentContainer = SASS_MEMORY_NEW(Complex_Selector, ParserState("[FAKE]"), Complex_Selector::ANCESTOR_OF, fakeHead /*head*/, NULL /*tail*/); + Complex_Selector_Obj fakeParentContainer = + SASS_MEMORY_NEW(Complex_Selector, ParserState("[FAKE]"), Complex_Selector::ANCESTOR_OF, + fakeHead /*head*/, NULL /*tail*/); Complex_Selector_Obj pOneWithFakeParent = nodeToComplexSelector(one); pOneWithFakeParent->set_innermost(fakeParentContainer, Complex_Selector::ANCESTOR_OF); @@ -656,21 +818,27 @@ namespace Sass { } - class ParentSuperselectorChunker { - public: - ParentSuperselectorChunker(Node& lcs) : mLcs(lcs) {} + class ParentSuperselectorChunker + { + public: + ParentSuperselectorChunker(Node& lcs) : mLcs(lcs) + { + } Node& mLcs; - bool operator()(const Node& seq) const { + bool operator()(const Node& seq) const + { // {|s| parent_superselector?(s.first, lcs.first)} if (seq.collection()->size() == 0) return false; return parentSuperselector(seq.collection()->front(), mLcs.collection()->front()); } }; - class SubweaveEmptyChunker { - public: - bool operator()(const Node& seq) const { + class SubweaveEmptyChunker + { + public: + bool operator()(const Node& seq) const + { // {|s| s.empty?} return seq.collection()->empty(); @@ -709,33 +877,39 @@ namespace Sass { [chunk1 + chunk2, chunk2 + chunk1] end */ - template - static Node chunks(Node& seq1, Node& seq2, const ChunkerType& chunker) { + template + static Node chunks(Node& seq1, Node& seq2, const ChunkerType& chunker) + { Node chunk1 = Node::createCollection(); - while (seq1.collection()->size() && !chunker(seq1)) { + while (seq1.collection()->size() && !chunker(seq1)) + { chunk1.collection()->push_back(seq1.collection()->front()); seq1.collection()->pop_front(); } Node chunk2 = Node::createCollection(); - while (!chunker(seq2)) { + while (!chunker(seq2)) + { chunk2.collection()->push_back(seq2.collection()->front()); seq2.collection()->pop_front(); } - if (chunk1.collection()->empty() && chunk2.collection()->empty()) { + if (chunk1.collection()->empty() && chunk2.collection()->empty()) + { DEBUG_PRINTLN(CHUNKS, "RETURNING BOTH EMPTY") return Node::createCollection(); } - if (chunk1.collection()->empty()) { + if (chunk1.collection()->empty()) + { Node chunk2Wrapper = Node::createCollection(); chunk2Wrapper.collection()->push_back(chunk2); DEBUG_PRINTLN(CHUNKS, "RETURNING ONE EMPTY") return chunk2Wrapper; } - if (chunk2.collection()->empty()) { + if (chunk2.collection()->empty()) + { Node chunk1Wrapper = Node::createCollection(); chunk1Wrapper.collection()->push_back(chunk1); DEBUG_PRINTLN(CHUNKS, "RETURNING TWO EMPTY") @@ -745,13 +919,17 @@ namespace Sass { Node perms = Node::createCollection(); Node firstPermutation = Node::createCollection(); - firstPermutation.collection()->insert(firstPermutation.collection()->end(), chunk1.collection()->begin(), chunk1.collection()->end()); - firstPermutation.collection()->insert(firstPermutation.collection()->end(), chunk2.collection()->begin(), chunk2.collection()->end()); + firstPermutation.collection()->insert(firstPermutation.collection()->end(), + chunk1.collection()->begin(), chunk1.collection()->end()); + firstPermutation.collection()->insert(firstPermutation.collection()->end(), + chunk2.collection()->begin(), chunk2.collection()->end()); perms.collection()->push_back(firstPermutation); Node secondPermutation = Node::createCollection(); - secondPermutation.collection()->insert(secondPermutation.collection()->end(), chunk2.collection()->begin(), chunk2.collection()->end()); - secondPermutation.collection()->insert(secondPermutation.collection()->end(), chunk1.collection()->begin(), chunk1.collection()->end()); + secondPermutation.collection()->insert(secondPermutation.collection()->end(), + chunk2.collection()->begin(), chunk2.collection()->end()); + secondPermutation.collection()->insert(secondPermutation.collection()->end(), + chunk1.collection()->begin(), chunk1.collection()->end()); perms.collection()->push_back(secondPermutation); DEBUG_PRINTLN(CHUNKS, "RETURNING PERM") @@ -760,19 +938,23 @@ namespace Sass { } - static Node groupSelectors(Node& seq) { + static Node groupSelectors(Node& seq) + { Node newSeq = Node::createCollection(); Node tail = Node::createCollection(); tail.plus(seq); - while (!tail.collection()->empty()) { + while (!tail.collection()->empty()) + { Node head = Node::createCollection(); - do { + do + { head.collection()->push_back(tail.collection()->front()); tail.collection()->pop_front(); - } while (!tail.collection()->empty() && (head.collection()->back().isCombinator() || tail.collection()->front().isCombinator())); + } while (!tail.collection()->empty() && + (head.collection()->back().isCombinator() || tail.collection()->front().isCombinator())); newSeq.collection()->push_back(head); } @@ -781,22 +963,26 @@ namespace Sass { } - static void getAndRemoveInitialOps(Node& seq, Node& ops) { + static void getAndRemoveInitialOps(Node& seq, Node& ops) + { NodeDeque& seqCollection = *(seq.collection()); NodeDeque& opsCollection = *(ops.collection()); - while (seqCollection.size() > 0 && seqCollection.front().isCombinator()) { + while (seqCollection.size() > 0 && seqCollection.front().isCombinator()) + { opsCollection.push_back(seqCollection.front()); seqCollection.pop_front(); } } - static void getAndRemoveFinalOps(Node& seq, Node& ops) { + static void getAndRemoveFinalOps(Node& seq, Node& ops) + { NodeDeque& seqCollection = *(seq.collection()); NodeDeque& opsCollection = *(ops.collection()); - while (seqCollection.size() > 0 && seqCollection.back().isCombinator()) { + while (seqCollection.size() > 0 && seqCollection.back().isCombinator()) + { opsCollection.push_back(seqCollection.back()); // Purposefully reversed to match ruby code seqCollection.pop_back(); } @@ -820,7 +1006,8 @@ namespace Sass { return (newline ? ["\n"] : []) + (ops1.size > ops2.size ? ops1 : ops2) end */ - static Node mergeInitialOps(Node& seq1, Node& seq2) { + static Node mergeInitialOps(Node& seq1, Node& seq2) + { Node ops1 = Node::createCollection(); Node ops2 = Node::createCollection(); @@ -836,7 +1023,8 @@ namespace Sass { DefaultLcsComparator lcsDefaultComparator; Node opsLcs = lcs(ops1, ops2, lcsDefaultComparator); - if (!(opsLcs == ops1 || opsLcs == ops2)) { + if (!(opsLcs == ops1 || opsLcs == ops2)) + { return Node::createNil(); } @@ -911,7 +1099,8 @@ namespace Sass { end end */ - static Node mergeFinalOps(Node& seq1, Node& seq2, Node& res) { + static Node mergeFinalOps(Node& seq1, Node& seq2, Node& res) + { Node ops1 = Node::createCollection(); Node ops2 = Node::createCollection(); @@ -923,30 +1112,40 @@ namespace Sass { // ops1.reject! {|o| o == "\n"} // ops2.reject! {|o| o == "\n"} - if (ops1.collection()->empty() && ops2.collection()->empty()) { + if (ops1.collection()->empty() && ops2.collection()->empty()) + { return res; } - if (ops1.collection()->size() > 1 || ops2.collection()->size() > 1) { + if (ops1.collection()->size() > 1 || ops2.collection()->size() > 1) + { DefaultLcsComparator lcsDefaultComparator; Node opsLcs = lcs(ops1, ops2, lcsDefaultComparator); - // If there are multiple operators, something hacky's going on. If one is a supersequence of the other, use that, otherwise give up. + // If there are multiple operators, something hacky's going on. If one is a supersequence of + // the other, use that, otherwise give up. - if (!(opsLcs == ops1 || opsLcs == ops2)) { + if (!(opsLcs == ops1 || opsLcs == ops2)) + { return Node::createNil(); } - if (ops1.collection()->size() > ops2.collection()->size()) { - res.collection()->insert(res.collection()->begin(), ops1.collection()->rbegin(), ops1.collection()->rend()); - } else { - res.collection()->insert(res.collection()->begin(), ops2.collection()->rbegin(), ops2.collection()->rend()); + if (ops1.collection()->size() > ops2.collection()->size()) + { + res.collection()->insert(res.collection()->begin(), ops1.collection()->rbegin(), + ops1.collection()->rend()); + } + else + { + res.collection()->insert(res.collection()->begin(), ops2.collection()->rbegin(), + ops2.collection()->rend()); } return res; } - if (!ops1.collection()->empty() && !ops2.collection()->empty()) { + if (!ops1.collection()->empty() && !ops2.collection()->empty()) + { Node op1 = ops1.collection()->front(); Node op2 = ops2.collection()->front(); @@ -957,25 +1156,33 @@ namespace Sass { Node sel2 = seq2.collection()->back(); seq2.collection()->pop_back(); - if (op1.combinator() == Complex_Selector::PRECEDES && op2.combinator() == Complex_Selector::PRECEDES) { + if (op1.combinator() == Complex_Selector::PRECEDES && op2.combinator() == Complex_Selector::PRECEDES) + { - if (sel1.selector()->is_superselector_of(sel2.selector())) { + if (sel1.selector()->is_superselector_of(sel2.selector())) + { res.collection()->push_front(op1 /*PRECEDES - could have been op2 as well*/); res.collection()->push_front(sel2); - - } else if (sel2.selector()->is_superselector_of(sel1.selector())) { + } + else if (sel2.selector()->is_superselector_of(sel1.selector())) + { res.collection()->push_front(op1 /*PRECEDES - could have been op2 as well*/); res.collection()->push_front(sel1); - - } else { + } + else + { DEBUG_PRINTLN(ALL, "sel1: " << sel1) DEBUG_PRINTLN(ALL, "sel2: " << sel2) - Complex_Selector_Obj pMergedWrapper = SASS_MEMORY_CLONE(sel1.selector()); // Clone the Complex_Selector to get back to something we can transform to a node once we replace the head with the unification result - // TODO: does subject matter? Ruby: return unless merged = sel1.unify(sel2.members, sel2.subject?) + Complex_Selector_Obj pMergedWrapper = + SASS_MEMORY_CLONE(sel1.selector()); // Clone the Complex_Selector to get back to something + // we can transform to a node once we replace the head + // with the unification result + // TODO: does subject matter? Ruby: return unless merged = sel1.unify(sel2.members, + // sel2.subject?) Compound_Selector_Ptr pMerged = sel1.selector()->head()->unify_with(sel2.selector()->head()); pMergedWrapper->head(pMerged); @@ -997,7 +1204,8 @@ namespace Sass { secondPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES)); newRes.collection()->push_back(secondPerm); - if (pMerged) { + if (pMerged) + { Node mergedPerm = Node::createCollection(); mergedPerm.collection()->push_back(Node::createSelector(pMergedWrapper)); mergedPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES)); @@ -1007,87 +1215,107 @@ namespace Sass { res.collection()->push_front(newRes); DEBUG_PRINTLN(ALL, "RESULT: " << res) - + } + } + else if (((op1.combinator() == Complex_Selector::PRECEDES && op2.combinator() == Complex_Selector::ADJACENT_TO)) || + ((op1.combinator() == Complex_Selector::ADJACENT_TO && op2.combinator() == Complex_Selector::PRECEDES))) + { + + Node tildeSel = sel1; + Node plusSel = sel2; + Node plusOp = op2; + if (op1.combinator() != Complex_Selector::PRECEDES) + { + tildeSel = sel2; + plusSel = sel1; + plusOp = op1; } - } else if (((op1.combinator() == Complex_Selector::PRECEDES && op2.combinator() == Complex_Selector::ADJACENT_TO)) || ((op1.combinator() == Complex_Selector::ADJACENT_TO && op2.combinator() == Complex_Selector::PRECEDES))) { - - Node tildeSel = sel1; - Node plusSel = sel2; - Node plusOp = op2; - if (op1.combinator() != Complex_Selector::PRECEDES) { - tildeSel = sel2; - plusSel = sel1; - plusOp = op1; - } - - if (tildeSel.selector()->is_superselector_of(plusSel.selector())) { - - res.collection()->push_front(plusOp); - res.collection()->push_front(plusSel); - - } else { - - DEBUG_PRINTLN(ALL, "PLUS SEL: " << plusSel) - DEBUG_PRINTLN(ALL, "TILDE SEL: " << tildeSel) - - Complex_Selector_Obj pMergedWrapper = SASS_MEMORY_CLONE(plusSel.selector()); // Clone the Complex_Selector to get back to something we can transform to a node once we replace the head with the unification result - // TODO: does subject matter? Ruby: merged = plus_sel.unify(tilde_sel.members, tilde_sel.subject?) - Compound_Selector_Ptr pMerged = plusSel.selector()->head()->unify_with(tildeSel.selector()->head()); - pMergedWrapper->head(pMerged); + if (tildeSel.selector()->is_superselector_of(plusSel.selector())) + { - DEBUG_EXEC(ALL, printCompoundSelector(pMerged, "MERGED: ")) + res.collection()->push_front(plusOp); + res.collection()->push_front(plusSel); + } + else + { + + DEBUG_PRINTLN(ALL, "PLUS SEL: " << plusSel) + DEBUG_PRINTLN(ALL, "TILDE SEL: " << tildeSel) + + Complex_Selector_Obj pMergedWrapper = + SASS_MEMORY_CLONE(plusSel.selector()); // Clone the Complex_Selector to get back to + // something we can transform to a node once we + // replace the head with the unification result + // TODO: does subject matter? Ruby: merged = plus_sel.unify(tilde_sel.members, + // tilde_sel.subject?) + Compound_Selector_Ptr pMerged = + plusSel.selector()->head()->unify_with(tildeSel.selector()->head()); + pMergedWrapper->head(pMerged); - Node newRes = Node::createCollection(); + DEBUG_EXEC(ALL, printCompoundSelector(pMerged, "MERGED: ")) - Node firstPerm = Node::createCollection(); - firstPerm.collection()->push_back(tildeSel); - firstPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES)); - firstPerm.collection()->push_back(plusSel); - firstPerm.collection()->push_back(Node::createCombinator(Complex_Selector::ADJACENT_TO)); - newRes.collection()->push_back(firstPerm); + Node newRes = Node::createCollection(); - if (pMerged) { - Node mergedPerm = Node::createCollection(); - mergedPerm.collection()->push_back(Node::createSelector(pMergedWrapper)); - mergedPerm.collection()->push_back(Node::createCombinator(Complex_Selector::ADJACENT_TO)); - newRes.collection()->push_back(mergedPerm); - } + Node firstPerm = Node::createCollection(); + firstPerm.collection()->push_back(tildeSel); + firstPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES)); + firstPerm.collection()->push_back(plusSel); + firstPerm.collection()->push_back(Node::createCombinator(Complex_Selector::ADJACENT_TO)); + newRes.collection()->push_back(firstPerm); - res.collection()->push_front(newRes); + if (pMerged) + { + Node mergedPerm = Node::createCollection(); + mergedPerm.collection()->push_back(Node::createSelector(pMergedWrapper)); + mergedPerm.collection()->push_back(Node::createCombinator(Complex_Selector::ADJACENT_TO)); + newRes.collection()->push_back(mergedPerm); + } - DEBUG_PRINTLN(ALL, "RESULT: " << res) + res.collection()->push_front(newRes); - } - } else if (op1.combinator() == Complex_Selector::PARENT_OF && (op2.combinator() == Complex_Selector::PRECEDES || op2.combinator() == Complex_Selector::ADJACENT_TO)) { + DEBUG_PRINTLN(ALL, "RESULT: " << res) + } + } + else if (op1.combinator() == Complex_Selector::PARENT_OF && + (op2.combinator() == Complex_Selector::PRECEDES || op2.combinator() == Complex_Selector::ADJACENT_TO)) + { res.collection()->push_front(op2); res.collection()->push_front(sel2); seq1.collection()->push_back(sel1); seq1.collection()->push_back(op1); - - } else if (op2.combinator() == Complex_Selector::PARENT_OF && (op1.combinator() == Complex_Selector::PRECEDES || op1.combinator() == Complex_Selector::ADJACENT_TO)) { + } + else if (op2.combinator() == Complex_Selector::PARENT_OF && + (op1.combinator() == Complex_Selector::PRECEDES || op1.combinator() == Complex_Selector::ADJACENT_TO)) + { res.collection()->push_front(op1); res.collection()->push_front(sel1); seq2.collection()->push_back(sel2); seq2.collection()->push_back(op2); - - } else if (op1.combinator() == op2.combinator()) { + } + else if (op1.combinator() == op2.combinator()) + { DEBUG_PRINTLN(ALL, "sel1: " << sel1) DEBUG_PRINTLN(ALL, "sel2: " << sel2) - Complex_Selector_Obj pMergedWrapper = SASS_MEMORY_CLONE(sel1.selector()); // Clone the Complex_Selector to get back to something we can transform to a node once we replace the head with the unification result - // TODO: does subject matter? Ruby: return unless merged = sel1.unify(sel2.members, sel2.subject?) + Complex_Selector_Obj pMergedWrapper = + SASS_MEMORY_CLONE(sel1.selector()); // Clone the Complex_Selector to get back to something + // we can transform to a node once we replace the head + // with the unification result + // TODO: does subject matter? Ruby: return unless merged = sel1.unify(sel2.members, + // sel2.subject?) Compound_Selector_Ptr pMerged = sel1.selector()->head()->unify_with(sel2.selector()->head()); pMergedWrapper->head(pMerged); DEBUG_EXEC(ALL, printCompoundSelector(pMerged, "MERGED: ")) - if (!pMerged) { + if (!pMerged) + { return Node::createNil(); } @@ -1095,18 +1323,22 @@ namespace Sass { res.collection()->push_front(Node::createSelector(pMergedWrapper)); DEBUG_PRINTLN(ALL, "RESULT: " << res) - - } else { + } + else + { return Node::createNil(); } return mergeFinalOps(seq1, seq2, res); - - } else if (!ops1.collection()->empty()) { + } + else if (!ops1.collection()->empty()) + { Node op1 = ops1.collection()->front(); - if (op1.combinator() == Complex_Selector::PARENT_OF && !seq2.collection()->empty() && seq2.collection()->back().selector()->is_superselector_of(seq1.collection()->back().selector())) { + if (op1.combinator() == Complex_Selector::PARENT_OF && !seq2.collection()->empty() && + seq2.collection()->back().selector()->is_superselector_of(seq1.collection()->back().selector())) + { seq2.collection()->pop_back(); } @@ -1116,12 +1348,15 @@ namespace Sass { seq1.collection()->pop_back(); return mergeFinalOps(seq1, seq2, res); - - } else { // !ops2.collection()->empty() + } + else + { // !ops2.collection()->empty() Node op2 = ops2.collection()->front(); - if (op2.combinator() == Complex_Selector::PARENT_OF && !seq1.collection()->empty() && seq1.collection()->back().selector()->is_superselector_of(seq2.collection()->back().selector())) { + if (op2.combinator() == Complex_Selector::PARENT_OF && !seq1.collection()->empty() && + seq1.collection()->back().selector()->is_superselector_of(seq2.collection()->back().selector())) + { seq1.collection()->pop_back(); } @@ -1130,9 +1365,7 @@ namespace Sass { seq2.collection()->pop_back(); return mergeFinalOps(seq1, seq2, res); - } - } @@ -1172,14 +1405,17 @@ namespace Sass { result end */ - Node subweave(Node& one, Node& two) { + Node subweave(Node& one, Node& two) + { // Check for the simple cases - if (one.collection()->size() == 0) { + if (one.collection()->size() == 0) + { Node out = Node::createCollection(); out.collection()->push_back(two); return out; } - if (two.collection()->size() == 0) { + if (two.collection()->size() == 0) + { Node out = Node::createCollection(); out.collection()->push_back(one); return out; @@ -1194,7 +1430,8 @@ namespace Sass { DEBUG_PRINTLN(SUBWEAVE, "SUBWEAVE TWO: " << seq2) Node init = mergeInitialOps(seq1, seq2); - if (init.isNil()) { + if (init.isNil()) + { return Node::createNil(); } @@ -1202,7 +1439,8 @@ namespace Sass { Node res = Node::createCollection(); Node fin = mergeFinalOps(seq1, seq2, res); - if (fin.isNil()) { + if (fin.isNil()) + { return Node::createNil(); } @@ -1213,22 +1451,22 @@ namespace Sass { // fin.map {|sel| sel.is_a?(Array) ? sel : [sel]} for (NodeDeque::iterator finIter = fin.collection()->begin(), finEndIter = fin.collection()->end(); - finIter != finEndIter; ++finIter) { + finIter != finEndIter; ++finIter) + { Node& childNode = *finIter; - if (!childNode.isCollection()) { + if (!childNode.isCollection()) + { Node wrapper = Node::createCollection(); wrapper.collection()->push_back(childNode); childNode = wrapper; } - } DEBUG_PRINTLN(SUBWEAVE, "FIN MAPPED: " << fin) - Node groupSeq1 = groupSelectors(seq1); DEBUG_PRINTLN(SUBWEAVE, "SEQ1: " << groupSeq1) @@ -1258,7 +1496,8 @@ namespace Sass { DEBUG_PRINTLN(SUBWEAVE, "DIFF INIT: " << diff) - while (!seqLcs.collection()->empty()) { + while (!seqLcs.collection()->empty()) + { ParentSuperselectorChunker superselectorChunker(seqLcs); Node chunksResult = chunks(groupSeq1, groupSeq2, superselectorChunker); diff.collection()->push_back(chunksResult); @@ -1290,12 +1529,15 @@ namespace Sass { DEBUG_PRINTLN(SUBWEAVE, "DIFF POST FIN MAPPED: " << diff) - // JMA - filter out the empty nodes (use a new collection, since iterator erase() invalidates the old collection) + // JMA - filter out the empty nodes (use a new collection, since iterator erase() invalidates + // the old collection) Node diffFiltered = Node::createCollection(); for (NodeDeque::iterator diffIter = diff.collection()->begin(), diffEndIter = diff.collection()->end(); - diffIter != diffEndIter; ++diffIter) { + diffIter != diffEndIter; ++diffIter) + { Node& node = *diffIter; - if (node.collection() && !node.collection()->empty()) { + if (node.collection() && !node.collection()->empty()) + { diffFiltered.collection()->push_back(node); } } @@ -1310,8 +1552,10 @@ namespace Sass { // We're flattening in place - for (NodeDeque::iterator pathsIter = pathsResult.collection()->begin(), pathsEndIter = pathsResult.collection()->end(); - pathsIter != pathsEndIter; ++pathsIter) { + for (NodeDeque::iterator pathsIter = pathsResult.collection()->begin(), + pathsEndIter = pathsResult.collection()->end(); + pathsIter != pathsEndIter; ++pathsIter) + { Node& child = *pathsIter; child = flatten(child); @@ -1328,7 +1572,6 @@ namespace Sass { return pathsResult; - } /* // disabled to avoid clang warning [-Wunused-function] @@ -1433,7 +1676,8 @@ namespace Sass { return befores end */ - Node Extend::weave(Node& path) { + Node Extend::weave(Node& path) + { DEBUG_PRINTLN(WEAVE, "WEAVE: " << path) @@ -1443,7 +1687,8 @@ namespace Sass { Node afters = Node::createCollection(); afters.plus(path); - while (!afters.collection()->empty()) { + while (!afters.collection()->empty()) + { Node current = afters.collection()->front().klone(); afters.collection()->pop_front(); DEBUG_PRINTLN(WEAVE, "CURRENT: " << current) @@ -1457,18 +1702,24 @@ namespace Sass { Node tempResult = Node::createCollection(); - for (NodeDeque::iterator beforesIter = befores.collection()->begin(), beforesEndIter = befores.collection()->end(); beforesIter != beforesEndIter; beforesIter++) { + for (NodeDeque::iterator beforesIter = befores.collection()->begin(), + beforesEndIter = befores.collection()->end(); + beforesIter != beforesEndIter; beforesIter++) + { Node& before = *beforesIter; Node sub = subweave(before, current); DEBUG_PRINTLN(WEAVE, "SUB: " << sub) - if (sub.isNil()) { + if (sub.isNil()) + { return Node::createCollection(); } - for (NodeDeque::iterator subIter = sub.collection()->begin(), subEndIter = sub.collection()->end(); subIter != subEndIter; subIter++) { + for (NodeDeque::iterator subIter = sub.collection()->begin(), subEndIter = sub.collection()->end(); + subIter != subEndIter; subIter++) + { Node& seqs = *subIter; Node toPush = Node::createCollection(); @@ -1476,19 +1727,16 @@ namespace Sass { toPush.plus(last_current); tempResult.collection()->push_back(toPush); - } } befores = tempResult; - } return befores; } - /* This is the equivalent of ruby's SimpleSequence.do_extend. @@ -1497,19 +1745,24 @@ namespace Sass { /* ISSUES: - Previous TODO: Do we need to group the results by extender? - - What does subject do in?: next unless unified = seq.members.last.unify(self_without_sel, subject?) - - IMPROVEMENT: The search for uniqueness at the end is not ideal since it's has to loop over everything... - - IMPROVEMENT: Check if the final search for uniqueness is doing anything that extendComplexSelector isn't already doing... + - What does subject do in?: next unless unified = seq.members.last.unify(self_without_sel, + subject?) + - IMPROVEMENT: The search for uniqueness at the end is not ideal since it's has to loop over + everything... + - IMPROVEMENT: Check if the final search for uniqueness is doing anything that + extendComplexSelector isn't already doing... */ - template - class GroupByToAFunctor { - public: - KeyType operator()(SubSetMapPair& extPair) const { + template class GroupByToAFunctor + { + public: + KeyType operator()(SubSetMapPair& extPair) const + { Complex_Selector_Obj pSelector = extPair.first; return pSelector; } }; - Node Extend::extendCompoundSelector(Compound_Selector_Ptr pSelector, CompoundSelectorSet& seen, bool isReplace) { + Node Extend::extendCompoundSelector(Compound_Selector_Ptr pSelector, CompoundSelectorSet& seen, bool isReplace) + { /* this turned out to be too much overhead probably due to holding a "Node" object @@ -1537,7 +1790,8 @@ namespace Sass { SubSetMapLookups holder; // for each (EXTENDER, TARGET) in MAP.get(COMPOUND): - for (SubSetMapResult& groupedPair : arr) { + for (SubSetMapResult& groupedPair : arr) + { Complex_Selector_Obj seq = groupedPair.first; SubSetMapPairs& group = groupedPair.second; @@ -1545,7 +1799,8 @@ namespace Sass { DEBUG_EXEC(EXTEND_COMPOUND, printComplexSelector(seq, "SEQ: ")) Compound_Selector_Obj pSels = SASS_MEMORY_NEW(Compound_Selector, pSelector->pstate()); - for (SubSetMapPair& pair : group) { + for (SubSetMapPair& pair : group) + { pair.second->extended(true); pSels->concat(pair.second); } @@ -1555,39 +1810,49 @@ namespace Sass { // The selector up to where the @extend is (ie, the thing to merge) Complex_Selector_Ptr pExtComplexSelector = seq; - // TODO: This can return a Compound_Selector with no elements. Should that just be returning NULL? + // TODO: This can return a Compound_Selector with no elements. Should that just be returning + // NULL? // RUBY: self_without_sel = Sass::Util.array_minus(members, sels) Compound_Selector_Obj pSelectorWithoutExtendSelectors = pSelector->minus(pSels); DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelector, "MEMBERS: ")) - DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelectorWithoutExtendSelectors, "SELF_WO_SEL: ")) + DEBUG_EXEC(EXTEND_COMPOUND, + printCompoundSelector(pSelectorWithoutExtendSelectors, "SELF_WO_SEL: ")) Compound_Selector_Obj pInnermostCompoundSelector = pExtComplexSelector->last()->head(); - if (!pInnermostCompoundSelector) { + if (!pInnermostCompoundSelector) + { pInnermostCompoundSelector = SASS_MEMORY_NEW(Compound_Selector, pSelector->pstate()); } - Compound_Selector_Obj pUnifiedSelector = pInnermostCompoundSelector->unify_with(pSelectorWithoutExtendSelectors); + Compound_Selector_Obj pUnifiedSelector = + pInnermostCompoundSelector->unify_with(pSelectorWithoutExtendSelectors); DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pInnermostCompoundSelector, "LHS: ")) DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelectorWithoutExtendSelectors, "RHS: ")) DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pUnifiedSelector, "UNIFIED: ")) // RUBY: next unless unified - if (!pUnifiedSelector || pUnifiedSelector->length() == 0) { + if (!pUnifiedSelector || pUnifiedSelector->length() == 0) + { continue; } // TODO: implement the parent directive match (if necessary based on test failures) // next if group.map {|e, _| check_directives_match!(e, parent_directives)}.none? - // TODO: This seems a little fishy to me. See if it causes any problems. From the ruby, we should be able to just - // get rid of the last Compound_Selector and replace it with this one. I think the reason this code is more - // complex is that Complex_Selector contains a combinator, but in ruby combinators have already been filtered + // TODO: This seems a little fishy to me. See if it causes any problems. From the ruby, we + // should be able to just + // get rid of the last Compound_Selector and replace it with this one. I think the reason this + // code is more + // complex is that Complex_Selector contains a combinator, but in ruby combinators have + // already been filtered // out and aren't operated on. Complex_Selector_Obj pNewSelector = SASS_MEMORY_CLONE(pExtComplexSelector); // ->first(); - Complex_Selector_Obj pNewInnerMost = SASS_MEMORY_NEW(Complex_Selector, pSelector->pstate(), Complex_Selector::ANCESTOR_OF, pUnifiedSelector, NULL); + Complex_Selector_Obj pNewInnerMost = + SASS_MEMORY_NEW(Complex_Selector, pSelector->pstate(), Complex_Selector::ANCESTOR_OF, + pUnifiedSelector, NULL); Complex_Selector::Combinator combinator = pNewSelector->clear_innermost(); pNewSelector->set_innermost(pNewInnerMost, combinator); @@ -1595,21 +1860,28 @@ namespace Sass { #ifdef DEBUG ComplexSelectorSet debugSet; debugSet = pNewSelector->sources(); - if (debugSet.size() > 0) { - throw std::runtime_error("The new selector should start with no sources. Something needs to be cloned to fix this."); + if (debugSet.size() > 0) + { + throw std::runtime_error( + "The new selector should start with no sources. Something needs to be cloned to fix this."); } debugSet = pExtComplexSelector->sources(); - if (debugSet.size() > 0) { - throw std::runtime_error("The extension selector from our subset map should not have sources. These will bleed to the new selector. Something needs to be cloned to fix this."); + if (debugSet.size() > 0) + { + throw std::runtime_error("The extension selector from our subset map should not have " + "sources. These will bleed to the new selector. Something needs " + "to be cloned to fix this."); } #endif // if (pSelector && pSelector->has_line_feed()) pNewInnerMost->has_line_feed(true); - // Set the sources on our new Complex_Selector to the sources of this simple sequence plus the thing we're extending. + // Set the sources on our new Complex_Selector to the sources of this simple sequence plus the + // thing we're extending. DEBUG_PRINTLN(EXTEND_COMPOUND, "SOURCES SETTING ON NEW SEQ: " << complexSelectorToNode(pNewSelector)) - DEBUG_EXEC(EXTEND_COMPOUND, ComplexSelectorSet oldSet = pNewSelector->sources(); printSourcesSet(oldSet, "SOURCES NEW SEQ BEGIN: ")) + DEBUG_EXEC(EXTEND_COMPOUND, ComplexSelectorSet oldSet = pNewSelector->sources(); + printSourcesSet(oldSet, "SOURCES NEW SEQ BEGIN: ")) // I actually want to create a copy here (performance!) ComplexSelectorSet newSourcesSet = pSelector->sources(); // XXX @@ -1621,8 +1893,11 @@ namespace Sass { // RUBY: new_seq.add_sources!(sources + [seq]) pNewSelector->addSources(newSourcesSet); - DEBUG_EXEC(EXTEND_COMPOUND, ComplexSelectorSet newSet = pNewSelector->sources(); printSourcesSet(newSet, "SOURCES ON NEW SELECTOR AFTER ADD: ")) - DEBUG_EXEC(EXTEND_COMPOUND, printSourcesSet(pSelector->sources(), "SOURCES THIS EXTEND WHICH SHOULD BE SAME STILL: ")) + DEBUG_EXEC(EXTEND_COMPOUND, ComplexSelectorSet newSet = pNewSelector->sources(); + printSourcesSet(newSet, "SOURCES ON NEW SELECTOR AFTER ADD: ")) + DEBUG_EXEC(EXTEND_COMPOUND, + printSourcesSet(pSelector->sources(), + "SOURCES THIS EXTEND WHICH SHOULD BE SAME STILL: ")) if (pSels->has_line_feed()) pNewSelector->has_line_feed(true); @@ -1631,14 +1906,16 @@ namespace Sass { } - for (SubSetMapLookup& pair : holder) { + for (SubSetMapLookup& pair : holder) + { Compound_Selector_Obj pSels = pair.first; Complex_Selector_Obj pNewSelector = pair.second; // RUBY??: next [] if seen.include?(sels) - if (seen.find(pSels) != seen.end()) { + if (seen.find(pSels) != seen.end()) + { continue; } @@ -1652,15 +1929,19 @@ namespace Sass { DEBUG_PRINTLN(EXTEND_COMPOUND, "RECURSING DO EXTEND RETURN: " << recurseExtendedSelectors) - for (NodeDeque::iterator iterator = recurseExtendedSelectors.collection()->begin(), endIterator = recurseExtendedSelectors.collection()->end(); - iterator != endIterator; ++iterator) { + for (NodeDeque::iterator iterator = recurseExtendedSelectors.collection()->begin(), + endIterator = recurseExtendedSelectors.collection()->end(); + iterator != endIterator; ++iterator) + { Node newSelector = *iterator; -// DEBUG_PRINTLN(EXTEND_COMPOUND, "EXTENDED AT THIS POINT: " << results) -// DEBUG_PRINTLN(EXTEND_COMPOUND, "SELECTOR EXISTS ALREADY: " << newSelector << " " << results.contains(newSelector, false /*simpleSelectorOrderDependent*/)); + // DEBUG_PRINTLN(EXTEND_COMPOUND, "EXTENDED AT THIS POINT: " << results) + // DEBUG_PRINTLN(EXTEND_COMPOUND, "SELECTOR EXISTS ALREADY: " << newSelector << " " + // << results.contains(newSelector, false /*simpleSelectorOrderDependent*/)); - if (!results.contains(newSelector)) { -// DEBUG_PRINTLN(EXTEND_COMPOUND, "ADDING NEW SELECTOR") + if (!results.contains(newSelector)) + { + // DEBUG_PRINTLN(EXTEND_COMPOUND, "ADDING NEW SELECTOR") results.collection()->push_back(newSelector); } } @@ -1677,25 +1958,28 @@ namespace Sass { // check if selector has something to be extended by subset_map - bool Extend::complexSelectorHasExtension(Complex_Selector_Ptr selector, CompoundSelectorSet& seen) { + bool Extend::complexSelectorHasExtension(Complex_Selector_Ptr selector, CompoundSelectorSet& seen) + { bool hasExtension = false; Complex_Selector_Obj pIter = selector; - while (!hasExtension && pIter) { + while (!hasExtension && pIter) + { Compound_Selector_Obj pHead = pIter->head(); - if (pHead) { + if (pHead) + { SubSetMapPairs entries = subset_map.get_v(pHead); - for (SubSetMapPair ext : entries) { + for (SubSetMapPair ext : entries) + { // check if both selectors have the same media block parent // if (ext.first->media_block() == pComplexSelector->media_block()) continue; if (ext.second->media_block() == 0) continue; - if (pHead->media_block() && - ext.second->media_block()->media_queries() && - pHead->media_block()->media_queries() - ) { + if (pHead->media_block() && ext.second->media_block()->media_queries() && + pHead->media_block()->media_queries()) + { std::string query_left(ext.second->media_block()->media_queries()->to_string()); std::string query_right(pHead->media_block()->media_queries()->to_string()); if (query_left == query_right) continue; @@ -1709,7 +1993,7 @@ namespace Sass { err << "You may not @extend an outer selector from within @media.\n"; err << "You may only @extend selectors within the same directive.\n"; err << "From \"@extend " << ext.second->to_string() << "\""; - err << " on line " << pstate.line+1 << " of " << rel_path << "\n"; + err << " on line " << pstate.line + 1 << " of " << rel_path << "\n"; error(err.str(), selector->pstate()); } if (entries.size() > 0) hasExtension = true; @@ -1733,12 +2017,14 @@ namespace Sass { the combinator and compound selector are one unit next [[sseq_or_op]] unless sseq_or_op.is_a?(SimpleSequence) */ - Node Extend::extendComplexSelector(Complex_Selector_Ptr selector, CompoundSelectorSet& seen, bool isReplace, bool isOriginal) { + Node Extend::extendComplexSelector(Complex_Selector_Ptr selector, CompoundSelectorSet& seen, bool isReplace, bool isOriginal) + { // check if we already extended this selector // we can do this since subset_map is "static" auto memoized = memoizeComplex.find(selector); - if (memoized != memoizeComplex.end()) { + if (memoized != memoizeComplex.end()) + { return memoized->second; } @@ -1751,15 +2037,19 @@ namespace Sass { Node choices = Node::createCollection(); // for each compound selector COMPOUND in COMPLEX: - for (Node& sseqOrOp : *complexSelector.collection()) { + for (Node& sseqOrOp : *complexSelector.collection()) + { DEBUG_PRINTLN(EXTEND_COMPLEX, "LOOP: " << sseqOrOp) // If it's not a selector (meaning it's a combinator), just include it automatically // RUBY: next [[sseq_or_op]] unless sseq_or_op.is_a?(SimpleSequence) - if (!sseqOrOp.isSelector()) { - // Wrap our Combinator in two collections to match ruby. This is essentially making a collection Node - // with one collection child. The collection child represents a Complex_Selector that is only a combinator. + if (!sseqOrOp.isSelector()) + { + // Wrap our Combinator in two collections to match ruby. This is essentially making a + // collection Node + // with one collection child. The collection child represents a Complex_Selector that is + // only a combinator. Node outer = Node::createCollection(); Node inner = Node::createCollection(); outer.collection()->push_back(inner); @@ -1779,10 +2069,13 @@ namespace Sass { if (sseqOrOp.got_line_feed) extended.got_line_feed = true; DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTENDED: " << extended) - // Prepend the Compound_Selector based on the choices logic; choices seems to be extend but with a ruby - // Array instead of a Sequence due to the member mapping: choices = extended.map {|seq| seq.members} + // Prepend the Compound_Selector based on the choices logic; choices seems to be extend but + // with a ruby + // Array instead of a Sequence due to the member mapping: choices = extended.map {|seq| + // seq.members} // RUBY: extended.first.add_sources!([self]) if original && !has_placeholder? - if (isOriginal && !selector->has_placeholder()) { + if (isOriginal && !selector->has_placeholder()) + { ComplexSelectorSet srcset; srcset.insert(selector); sseqSel->addSources(srcset); @@ -1791,15 +2084,18 @@ namespace Sass { bool isSuperselector = false; // if no complex selector in EXTENDED is a superselector of COMPOUND: - for (Node& childNode : *extended.collection()) { + for (Node& childNode : *extended.collection()) + { Complex_Selector_Obj pExtensionSelector = nodeToComplexSelector(childNode); - if (pExtensionSelector->is_superselector_of(sseqSel)) { + if (pExtensionSelector->is_superselector_of(sseqSel)) + { isSuperselector = true; break; } } - if (!isSuperselector) { + if (!isSuperselector) + { // add a complex selector composed only of COMPOUND to EXTENDED if (sseqOrOp.got_line_feed) sseqSel->has_line_feed(sseqOrOp.got_line_feed); extended.collection()->push_front(complexSelectorToNode(sseqSel)); @@ -1816,7 +2112,6 @@ namespace Sass { DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTENDED NOT EXPANDED: " << choices) - // Ruby Equivalent: paths Node paths = Sass::paths(choices); @@ -1826,7 +2121,8 @@ namespace Sass { Node weaves = Node::createCollection(); // for each list of complex selectors PATH in paths(CHOICES): - for (Node& path : *paths.collection()) { + for (Node& path : *paths.collection()) + { // add weave(PATH) to WEAVES Node weaved = weave(path); // slow(12%)! weaved.got_line_feed = path.got_line_feed; @@ -1854,20 +2150,25 @@ namespace Sass { } - /* This is the equivalent of ruby's CommaSequence.do_extend. */ // We get a selector list with has something to extend and a subset_map with // all extenders. Pick the ones that match our selectors in the list. - Selector_List_Ptr Extend::extendSelectorList(Selector_List_Obj pSelectorList, bool isReplace, bool& extendedSomething, CompoundSelectorSet& seen) { + Selector_List_Ptr Extend::extendSelectorList(Selector_List_Obj pSelectorList, + bool isReplace, + bool& extendedSomething, + CompoundSelectorSet& seen) + { - Selector_List_Obj pNewSelectors = SASS_MEMORY_NEW(Selector_List, pSelectorList->pstate(), pSelectorList->length()); + Selector_List_Obj pNewSelectors = + SASS_MEMORY_NEW(Selector_List, pSelectorList->pstate(), pSelectorList->length()); // check if we already extended this selector // we can do this since subset_map is "static" auto memoized = memoizeList.find(pSelectorList); - if (memoized != memoizeList.end()) { + if (memoized != memoizeList.end()) + { extendedSomething = true; return memoized->second; } @@ -1875,15 +2176,21 @@ namespace Sass { extendedSomething = false; // process each comlplex selector in the selector list. // Find the ones that can be extended by given subset_map. - for (size_t index = 0, length = pSelectorList->length(); index < length; index++) { + for (size_t index = 0, length = pSelectorList->length(); index < length; index++) + { Complex_Selector_Obj pSelector = (*pSelectorList)[index]; - // ruby sass seems to keep a list of things that have extensions and then only extend those. We don't currently do that. - // Since it's not that expensive to check if an extension exists in the subset map and since it can be relatively expensive to - // run through the extend code (which does a data model transformation), check if there is anything to extend before doing - // the extend. We might be able to optimize extendComplexSelector, but this approach keeps us closer to ruby sass (which helps + // ruby sass seems to keep a list of things that have extensions and then only extend those. + // We don't currently do that. + // Since it's not that expensive to check if an extension exists in the subset map and since + // it can be relatively expensive to + // run through the extend code (which does a data model transformation), check if there is + // anything to extend before doing + // the extend. We might be able to optimize extendComplexSelector, but this approach keeps us + // closer to ruby sass (which helps // when debugging). - if (!complexSelectorHasExtension(pSelector, seen)) { + if (!complexSelectorHasExtension(pSelector, seen)) + { pNewSelectors->append(pSelector); continue; } @@ -1894,18 +2201,22 @@ namespace Sass { // now do the actual extension of the complex selector Node extendedSelectors = extendComplexSelector(pSelector, seen, isReplace, true); - if (!pSelector->has_placeholder()) { + if (!pSelector->has_placeholder()) + { Node nSelector(complexSelectorToNode(pSelector)); - if (!extendedSelectors.contains(nSelector)) { + if (!extendedSelectors.contains(nSelector)) + { pNewSelectors->append(pSelector); continue; } } bool doReplace = isReplace; - for (Node& childNode : *extendedSelectors.collection()) { + for (Node& childNode : *extendedSelectors.collection()) + { // When it is a replace, skip the first one, unless there is only one - if(doReplace && extendedSelectors.collection()->size() > 1 ) { + if (doReplace && extendedSelectors.collection()->size() > 1) + { doReplace = false; continue; } @@ -1919,44 +2230,56 @@ namespace Sass { pNewSelectors = remove_placeholders.remove_placeholders(pNewSelectors); // unwrap all wrapped selectors with inner lists - for (Complex_Selector_Obj cur : pNewSelectors->elements()) { + for (Complex_Selector_Obj cur : pNewSelectors->elements()) + { // process tails - while (cur) { + while (cur) + { // process header - if (cur->head() && seen.find(cur->head()) == seen.end()) { + if (cur->head() && seen.find(cur->head()) == seen.end()) + { CompoundSelectorSet recseen(seen); recseen.insert(cur->head()); // create a copy since we add multiple items if stuff get unwrapped Compound_Selector_Obj cpy_head = SASS_MEMORY_NEW(Compound_Selector, cur->pstate()); - for (Simple_Selector_Obj hs : *cur->head()) { - if (Wrapped_Selector_Obj ws = Cast(hs)) { + for (Simple_Selector_Obj hs : *cur->head()) + { + if (Wrapped_Selector_Obj ws = Cast(hs)) + { ws->selector(SASS_MEMORY_CLONE(ws->selector())); - if (Selector_List_Obj sl = Cast(ws->selector())) { + if (Selector_List_Obj sl = Cast(ws->selector())) + { // special case for ruby ass - if (sl->empty()) { + if (sl->empty()) + { // this seems inconsistent but it is how ruby sass seems to remove parentheses cpy_head->append(SASS_MEMORY_NEW(Element_Selector, hs->pstate(), ws->name())); } // has wrapped selectors - else { + else + { // extend the inner list of wrapped selector Selector_List_Obj ext_sl = extendSelectorList(sl, recseen); - for (size_t i = 0; i < ext_sl->length(); i += 1) { - if (Complex_Selector_Obj ext_cs = ext_sl->at(i)) { + for (size_t i = 0; i < ext_sl->length(); i += 1) + { + if (Complex_Selector_Obj ext_cs = ext_sl->at(i)) + { // create clones for wrapped selector and the inner list Wrapped_Selector_Obj cpy_ws = SASS_MEMORY_COPY(ws); Selector_List_Obj cpy_ws_sl = SASS_MEMORY_NEW(Selector_List, sl->pstate()); // remove parent selectors from inner selector - if (ext_cs->first() && ext_cs->first()->head()->length() > 0) { - Wrapped_Selector_Ptr ext_ws = Cast(ext_cs->first()->head()->first()); - if (ext_ws/* && ext_cs->length() == 1*/) { + if (ext_cs->first() && ext_cs->first()->head()->length() > 0) + { + Wrapped_Selector_Ptr ext_ws = + Cast(ext_cs->first()->head()->first()); + if (ext_ws /* && ext_cs->length() == 1*/) + { Selector_List_Obj ws_cs = Cast(ext_ws->selector()); Compound_Selector_Obj ws_ss = ws_cs->first()->head(); - if (!( - Cast(ws_ss->first()) || - Cast(ws_ss->first()) || - Cast(ws_ss->first()) - )) continue; + if (!(Cast(ws_ss->first()) || + Cast(ws_ss->first()) || + Cast(ws_ss->first()))) + continue; } cpy_ws_sl->append(ext_cs->first()); } @@ -1967,10 +2290,14 @@ namespace Sass { } } } - } else { + } + else + { cpy_head->append(hs); } - } else { + } + else + { cpy_head->append(hs); } } @@ -1986,11 +2313,11 @@ namespace Sass { memoizeList.insert(std::pair(pSelectorList, pNewSelectors)); return pNewSelectors.detach(); - } - bool shouldExtendBlock(Block_Obj b) { + bool shouldExtendBlock(Block_Obj b) + { // If a block is empty, there's no reason to extend it since any rules placed on this block // won't have any output. The main benefit of this is for structures like: @@ -2001,40 +2328,47 @@ namespace Sass { // } // } // - // We end up visiting two rulesets (one with the selector .a and the other with the selector .a .b). - // In this case, we don't want to try to pull rules onto .a since they won't get output anyway since + // We end up visiting two rulesets (one with the selector .a and the other with the selector .a + // .b). + // In this case, we don't want to try to pull rules onto .a since they won't get output anyway + // since // there are no child statements. However .a .b should have extensions applied. - for (size_t i = 0, L = b->length(); i < L; ++i) { + for (size_t i = 0, L = b->length(); i < L; ++i) + { Statement_Obj stm = b->at(i); - if (Cast(stm)) { + if (Cast(stm)) + { // Do nothing. This doesn't count as a statement that causes extension since we'll // iterate over this rule set in a future visit and try to extend it. } - else { + else + { return true; } } return false; - } - // Extend a ruleset by extending the selectors and updating them on the ruleset. The block's rules don't need to change. + // Extend a ruleset by extending the selectors and updating them on the ruleset. The block's rules + // don't need to change. // Every Ruleset in the whole tree is calling this function. We decide if there // was is @extend that matches our selector. If we find one, we will go further // and call the extend magic for our selector. The subset_map contains all blocks // where @extend was found. Pick the ones that match our selector! - void Extend::extendObjectWithSelectorAndBlock(Ruleset_Ptr pObject) { + void Extend::extendObjectWithSelectorAndBlock(Ruleset_Ptr pObject) + { DEBUG_PRINTLN(EXTEND_OBJECT, "FOUND SELECTOR: " << Cast(pObject->selector())->to_string()) // Ruby sass seems to filter nodes that don't have any content well before we get here. // I'm not sure the repercussions of doing so, so for now, let's just not extend things // that won't be output later. Profiling shows this may us 0.2% or so. - if (!shouldExtendBlock(pObject->block())) { + if (!shouldExtendBlock(pObject->block())) + { DEBUG_PRINTLN(EXTEND_OBJECT, "RETURNING WITHOUT EXTEND ATTEMPT") return; } @@ -2042,33 +2376,40 @@ namespace Sass { bool extendedSomething = false; CompoundSelectorSet seen; - Selector_List_Obj pNewSelectorList = extendSelectorList(pObject->selector(), false, extendedSomething, seen); + Selector_List_Obj pNewSelectorList = + extendSelectorList(pObject->selector(), false, extendedSomething, seen); - if (extendedSomething && pNewSelectorList) { + if (extendedSomething && pNewSelectorList) + { DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND ORIGINAL SELECTORS: " << pObject->selector()->to_string()) DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND SETTING NEW SELECTORS: " << pNewSelectorList->to_string()) pNewSelectorList->remove_parent_selectors(); pObject->selector(pNewSelectorList); - } else { + } + else + { DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND DID NOT TRY TO EXTEND ANYTHING") } } - Extend::Extend(Subset_Map& ssm) - : subset_map(ssm) - { } + Extend::Extend(Subset_Map& ssm) : subset_map(ssm) + { + } void Extend::operator()(Block_Ptr b) { - for (size_t i = 0, L = b->length(); i < L; ++i) { + for (size_t i = 0, L = b->length(); i < L; ++i) + { Statement_Obj stm = b->at(i); stm->perform(this); } // do final check if everything was extended // we set `extended` flag on extended selectors - if (b->is_root()) { + if (b->is_root()) + { // debug_subset_map(subset_map); - for(auto const &it : subset_map.values()) { + for (auto const& it : subset_map.values()) + { Complex_Selector_Ptr sel = NULL; Compound_Selector_Ptr ext = NULL; if (it.first) sel = it.first->first(); @@ -2079,17 +2420,19 @@ namespace Sass { // debug_ast(sel, "sel: "); // debug_ast(ext, "ext: "); error("\"" + str_sel + "\" failed to @extend \"" + str_ext + "\".\n" - "The selector \"" + str_ext + "\" was not found.\n" - "Use \"@extend " + str_ext + " !optional\" if the" - " extend should be able to fail.", (ext ? ext->pstate() : NULL)); + "The selector \"" + + str_ext + "\" was not found.\n" + "Use \"@extend " + + str_ext + " !optional\" if the" + " extend should be able to fail.", + (ext ? ext->pstate() : NULL)); } } - } void Extend::operator()(Ruleset_Ptr pRuleset) { - extendObjectWithSelectorAndBlock( pRuleset ); + extendObjectWithSelectorAndBlock(pRuleset); pRuleset->block()->perform(this); } diff --git a/src/extend.hpp b/src/extend.hpp index 3928cad0f9..e8579344e1 100644 --- a/src/extend.hpp +++ b/src/extend.hpp @@ -10,31 +10,34 @@ #include "subset_map.hpp" #include "ast_fwd_decl.hpp" -namespace Sass { +namespace Sass +{ Node subweave(Node& one, Node& two); - class Extend : public Operation_CRTP { + class Extend : public Operation_CRTP + { Subset_Map& subset_map; - void fallback_impl(AST_Node_Ptr n) { } + void fallback_impl(AST_Node_Ptr n) + { + } - private: - - std::unordered_map< - Selector_List_Obj, // key - Selector_List_Obj, // value - HashNodes, // hasher - CompareNodes // compare - > memoizeList; - - std::unordered_map< - Complex_Selector_Obj, // key - Node, // value - HashNodes, // hasher - CompareNodes // compare - > memoizeComplex; + private: + std::unordered_map + memoizeList; + + std::unordered_map + memoizeComplex; /* this turned out to be too much overhead re-evaluate once we store an ast selector @@ -53,20 +56,27 @@ namespace Sass { Node trim(Node& seqses, bool isReplace); Node weave(Node& path); - public: - Selector_List_Ptr extendSelectorList(Selector_List_Obj pSelectorList, bool isReplace, bool& extendedSomething, CompoundSelectorSet& seen); - Selector_List_Ptr extendSelectorList(Selector_List_Obj pSelectorList, bool isReplace = false) { + public: + Selector_List_Ptr extendSelectorList(Selector_List_Obj pSelectorList, + bool isReplace, + bool& extendedSomething, + CompoundSelectorSet& seen); + Selector_List_Ptr extendSelectorList(Selector_List_Obj pSelectorList, bool isReplace = false) + { bool extendedSomething = false; CompoundSelectorSet seen; return extendSelectorList(pSelectorList, isReplace, extendedSomething, seen); } - Selector_List_Ptr extendSelectorList(Selector_List_Obj pSelectorList, CompoundSelectorSet& seen) { + Selector_List_Ptr extendSelectorList(Selector_List_Obj pSelectorList, CompoundSelectorSet& seen) + { bool isReplace = false; bool extendedSomething = false; return extendSelectorList(pSelectorList, isReplace, extendedSomething, seen); } Extend(Subset_Map&); - ~Extend() { } + ~Extend() + { + } void operator()(Block_Ptr); void operator()(Ruleset_Ptr); @@ -74,10 +84,11 @@ namespace Sass { void operator()(Media_Block_Ptr); void operator()(Directive_Ptr); - template - void fallback(U x) { return fallback_impl(x); } + template void fallback(U x) + { + return fallback_impl(x); + } }; - } #endif diff --git a/src/file.cpp b/src/file.cpp index a6cabda10a..66f1e6f768 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -1,13 +1,13 @@ #ifdef _WIN32 -# ifdef __MINGW32__ -# ifndef off64_t -# define off64_t _off64_t /* Workaround for http://sourceforge.net/p/mingw/bugs/2024/ */ -# endif -# endif -# include -# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#ifdef __MINGW32__ +#ifndef off64_t +#define off64_t _off64_t /* Workaround for http://sourceforge.net/p/mingw/bugs/2024/ */ +#endif +#endif +#include +#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR) #else -# include +#include #endif #include "sass.hpp" #include @@ -24,43 +24,45 @@ #include "sass2scss.h" #ifdef _WIN32 -# include +#include -# ifdef _MSC_VER -# include +#ifdef _MSC_VER +#include inline static std::string wstring_to_string(const std::wstring& wstr) { - std::wstring_convert, wchar_t> wchar_converter; - return wchar_converter.to_bytes(wstr); + std::wstring_convert, wchar_t> wchar_converter; + return wchar_converter.to_bytes(wstr); } -# else // mingw(/gcc) does not support C++11's codecvt yet. -inline static std::string wstring_to_string(const std::wstring &wstr) +#else // mingw(/gcc) does not support C++11's codecvt yet. +inline static std::string wstring_to_string(const std::wstring& wstr) { - int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL); - std::string strTo(size_needed, 0); - WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL); - return strTo; + int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL); + std::string strTo(size_needed, 0); + WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL); + return strTo; } -# endif +#endif #endif -namespace Sass { - namespace File { +namespace Sass +{ + namespace File + { // return the current directory // always with forward slashes std::string get_cwd() { const size_t wd_len = 1024; - #ifndef _WIN32 - char wd[wd_len]; - std::string cwd = getcwd(wd, wd_len); - #else - wchar_t wd[wd_len]; - std::string cwd = wstring_to_string(_wgetcwd(wd, wd_len)); - //convert backslashes to forward slashes - replace(cwd.begin(), cwd.end(), '\\', '/'); - #endif +#ifndef _WIN32 + char wd[wd_len]; + std::string cwd = getcwd(wd, wd_len); +#else + wchar_t wd[wd_len]; + std::string cwd = wstring_to_string(_wgetcwd(wd, wd_len)); + // convert backslashes to forward slashes + replace(cwd.begin(), cwd.end(), '\\', '/'); +#endif if (cwd[cwd.length() - 1] != '/') cwd += '/'; return cwd; } @@ -68,30 +70,30 @@ namespace Sass { // test if path exists and is a file bool file_exists(const std::string& path) { - #ifdef _WIN32 - std::wstring wpath = UTF_8::convert_to_utf16(path); - DWORD dwAttrib = GetFileAttributesW(wpath.c_str()); - return (dwAttrib != INVALID_FILE_ATTRIBUTES && - (!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY))); - #else - struct stat st_buf; - return (stat (path.c_str(), &st_buf) == 0) && - (!S_ISDIR (st_buf.st_mode)); - #endif +#ifdef _WIN32 + std::wstring wpath = UTF_8::convert_to_utf16(path); + DWORD dwAttrib = GetFileAttributesW(wpath.c_str()); + return (dwAttrib != INVALID_FILE_ATTRIBUTES && (!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY))); +#else + struct stat st_buf; + return (stat(path.c_str(), &st_buf) == 0) && (!S_ISDIR(st_buf.st_mode)); +#endif } // return if given path is absolute // works with *nix and windows paths bool is_absolute_path(const std::string& path) { - #ifdef _WIN32 - if (path.length() >= 2 && isalpha(path[0]) && path[1] == ':') return true; - #endif +#ifdef _WIN32 + if (path.length() >= 2 && isalpha(path[0]) && path[1] == ':') return true; +#endif size_t i = 0; // check if we have a protocol - if (path[i] && Prelexer::is_alpha(path[i])) { + if (path[i] && Prelexer::is_alpha(path[i])) + { // skip over all alphanumeric characters - while (path[i] && Prelexer::is_alnum(path[i])) ++i; + while (path[i] && Prelexer::is_alnum(path[i])) + ++i; i = i && path[i] == ':' ? i + 1 : 0; } return path[i] == '/'; @@ -102,18 +104,21 @@ namespace Sass { { size_t pos; size_t pos_p = path.find_last_of('/', limit); - #ifdef _WIN32 - size_t pos_w = path.find_last_of('\\', limit); - #else - size_t pos_w = std::string::npos; - #endif - if (pos_p != std::string::npos && pos_w != std::string::npos) { +#ifdef _WIN32 + size_t pos_w = path.find_last_of('\\', limit); +#else + size_t pos_w = std::string::npos; +#endif + if (pos_p != std::string::npos && pos_w != std::string::npos) + { pos = std::max(pos_p, pos_w); } - else if (pos_p != std::string::npos) { + else if (pos_p != std::string::npos) + { pos = pos_p; } - else { + else + { pos = pos_w; } return pos; @@ -123,56 +128,68 @@ namespace Sass { std::string dir_name(const std::string& path) { size_t pos = find_last_folder_separator(path); - if (pos == std::string::npos) return ""; - else return path.substr(0, pos+1); + if (pos == std::string::npos) + return ""; + else + return path.substr(0, pos + 1); } // return only the filename part of path std::string base_name(const std::string& path) { size_t pos = find_last_folder_separator(path); - if (pos == std::string::npos) return path; - else return path.substr(pos+1); + if (pos == std::string::npos) + return path; + else + return path.substr(pos + 1); } // do a logical clean up of the path // no physical check on the filesystem - std::string make_canonical_path (std::string path) + std::string make_canonical_path(std::string path) { // declarations size_t pos; - #ifdef _WIN32 - //convert backslashes to forward slashes - replace(path.begin(), path.end(), '\\', '/'); - #endif +#ifdef _WIN32 + // convert backslashes to forward slashes + replace(path.begin(), path.end(), '\\', '/'); +#endif pos = 0; // remove all self references inside the path string - while((pos = path.find("/./", pos)) != std::string::npos) path.erase(pos, 2); + while ((pos = path.find("/./", pos)) != std::string::npos) + path.erase(pos, 2); // remove all leading and trailing self references - while(path.length() > 1 && path.substr(0, 2) == "./") path.erase(0, 2); - while((pos = path.length()) > 1 && path.substr(pos - 2) == "/.") path.erase(pos - 2); + while (path.length() > 1 && path.substr(0, 2) == "./") + path.erase(0, 2); + while ((pos = path.length()) > 1 && path.substr(pos - 2) == "/.") + path.erase(pos - 2); size_t proto = 0; // check if we have a protocol - if (path[proto] && Prelexer::is_alpha(path[proto])) { + if (path[proto] && Prelexer::is_alpha(path[proto])) + { // skip over all alphanumeric characters - while (path[proto] && Prelexer::is_alnum(path[proto++])) {} + while (path[proto] && Prelexer::is_alnum(path[proto++])) + { + } // then skip over the mandatory colon - if (proto && path[proto] == ':') ++ proto; + if (proto && path[proto] == ':') ++proto; } // then skip over start slashes - while (path[proto++] == '/') {} + while (path[proto++] == '/') + { + } pos = proto; // collapse multiple delimiters into a single one - while((pos = path.find("//", pos)) != std::string::npos) path.erase(pos, 1); + while ((pos = path.find("//", pos)) != std::string::npos) + path.erase(pos, 1); return path; - } // join two path segments cleanly together @@ -180,24 +197,27 @@ namespace Sass { std::string join_paths(std::string l, std::string r) { - #ifdef _WIN32 - // convert Windows backslashes to URL forward slashes - replace(l.begin(), l.end(), '\\', '/'); - replace(r.begin(), r.end(), '\\', '/'); - #endif +#ifdef _WIN32 + // convert Windows backslashes to URL forward slashes + replace(l.begin(), l.end(), '\\', '/'); + replace(r.begin(), r.end(), '\\', '/'); +#endif if (l.empty()) return r; if (r.empty()) return l; if (is_absolute_path(r)) return r; - if (l[l.length()-1] != '/') l += '/'; + if (l[l.length() - 1] != '/') l += '/'; - while ((r.length() > 3) && ((r.substr(0, 3) == "../") || (r.substr(0, 3)) == "..\\")) { + while ((r.length() > 3) && ((r.substr(0, 3) == "../") || (r.substr(0, 3)) == "..\\")) + { size_t L = l.length(), pos = find_last_folder_separator(l, L - 2); - bool is_slash = pos + 2 == L && (l[pos+1] == '/' || l[pos+1] == '\\'); - bool is_self = pos + 3 == L && (l[pos+1] == '.'); - if (!is_self && !is_slash) r = r.substr(3); - else if (pos == std::string::npos) break; + bool is_slash = pos + 2 == L && (l[pos + 1] == '/' || l[pos + 1] == '\\'); + bool is_self = pos + 3 == L && (l[pos + 1] == '.'); + if (!is_self && !is_slash) + r = r.substr(3); + else if (pos == std::string::npos) + break; l = l.substr(0, pos == std::string::npos ? pos : pos + 1); } @@ -209,7 +229,8 @@ namespace Sass { // magic algorith goes here!! // if the file is outside this directory show the absolute path - if (rel_path.substr(0, 3) == "../") { + if (rel_path.substr(0, 3) == "../") + { return orig_path; } // this seems to work most of the time @@ -232,56 +253,67 @@ namespace Sass { size_t proto = 0; // check if we have a protocol - if (path[proto] && Prelexer::is_alpha(path[proto])) { + if (path[proto] && Prelexer::is_alpha(path[proto])) + { // skip over all alphanumeric characters - while (path[proto] && Prelexer::is_alnum(path[proto++])) {} + while (path[proto] && Prelexer::is_alnum(path[proto++])) + { + } // then skip over the mandatory colon - if (proto && path[proto] == ':') ++ proto; + if (proto && path[proto] == ':') ++proto; } // distinguish between windows absolute paths and valid protocols // we assume that protocols must at least have two chars to be valid if (proto && path[proto++] == '/' && proto > 3) return path; - #ifdef _WIN32 - // absolute link must have a drive letter, and we know that we - // can only create relative links if both are on the same drive - if (abs_base[0] != abs_path[0]) return abs_path; - #endif +#ifdef _WIN32 + // absolute link must have a drive letter, and we know that we + // can only create relative links if both are on the same drive + if (abs_base[0] != abs_path[0]) return abs_path; +#endif std::string stripped_uri = ""; std::string stripped_base = ""; size_t index = 0; size_t minSize = std::min(abs_path.size(), abs_base.size()); - for (size_t i = 0; i < minSize; ++i) { - #ifdef FS_CASE_SENSITIVE - if (abs_path[i] != abs_base[i]) break; - #else - // compare the charactes in a case insensitive manner - // windows fs is only case insensitive in ascii ranges - if (tolower(abs_path[i]) != tolower(abs_base[i])) break; - #endif + for (size_t i = 0; i < minSize; ++i) + { +#ifdef FS_CASE_SENSITIVE + if (abs_path[i] != abs_base[i]) break; +#else + // compare the charactes in a case insensitive manner + // windows fs is only case insensitive in ascii ranges + if (tolower(abs_path[i]) != tolower(abs_base[i])) break; +#endif if (abs_path[i] == '/') index = i + 1; } - for (size_t i = index; i < abs_path.size(); ++i) { + for (size_t i = index; i < abs_path.size(); ++i) + { stripped_uri += abs_path[i]; } - for (size_t i = index; i < abs_base.size(); ++i) { + for (size_t i = index; i < abs_base.size(); ++i) + { stripped_base += abs_base[i]; } size_t left = 0; size_t directories = 0; - for (size_t right = 0; right < stripped_base.size(); ++right) { - if (stripped_base[right] == '/') { - if (stripped_base.substr(left, 2) != "..") { + for (size_t right = 0; right < stripped_base.size(); ++right) + { + if (stripped_base[right] == '/') + { + if (stripped_base.substr(left, 2) != "..") + { ++directories; } - else if (directories > 1) { + else if (directories > 1) + { --directories; } - else { + else + { directories = 0; } left = right + 1; @@ -289,7 +321,8 @@ namespace Sass { } std::string result = ""; - for (size_t i = 0; i < directories; ++i) { + for (size_t i = 0; i < directories; ++i) + { result += "../"; } result += stripped_uri; @@ -302,7 +335,8 @@ namespace Sass { // (2) underscore + given // (3) underscore + given + extension // (4) given + extension - std::vector resolve_includes(const std::string& root, const std::string& file, const std::vector& exts) + std::vector + resolve_includes(const std::string& root, const std::string& file, const std::vector& exts) { std::string filename = join_paths(root, file); // split the filename @@ -312,22 +346,24 @@ namespace Sass { // create full path (maybe relative) std::string rel_path(join_paths(base, name)); std::string abs_path(join_paths(root, rel_path)); - if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path }); + if (file_exists(abs_path)) includes.push_back({ { rel_path, root }, abs_path }); // next test variation with underscore rel_path = join_paths(base, "_" + name); abs_path = join_paths(root, rel_path); - if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path }); + if (file_exists(abs_path)) includes.push_back({ { rel_path, root }, abs_path }); // next test exts plus underscore - for(auto ext : exts) { + for (auto ext : exts) + { rel_path = join_paths(base, "_" + name + ext); abs_path = join_paths(root, rel_path); - if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path }); + if (file_exists(abs_path)) includes.push_back({ { rel_path, root }, abs_path }); } // next test plain name with exts - for(auto ext : exts) { + for (auto ext : exts) + { rel_path = join_paths(base, name + ext); abs_path = join_paths(root, rel_path); - if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path }); + if (file_exists(abs_path)) includes.push_back({ { rel_path, root }, abs_path }); } // nothing found return includes; @@ -336,7 +372,8 @@ namespace Sass { std::vector find_files(const std::string& file, const std::vector paths) { std::vector includes; - for (std::string path : paths) { + for (std::string path : paths) + { std::string abs_path(join_paths(path, file)); if (file_exists(abs_path)) includes.push_back(abs_path); } @@ -384,48 +421,53 @@ namespace Sass { // will auto convert .sass files char* read_file(const std::string& path) { - #ifdef _WIN32 - BYTE* pBuffer; - DWORD dwBytes; - // windows unicode filepaths are encoded in utf16 - std::wstring wpath = UTF_8::convert_to_utf16(path); - HANDLE hFile = CreateFileW(wpath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - if (hFile == INVALID_HANDLE_VALUE) return 0; - DWORD dwFileLength = GetFileSize(hFile, NULL); - if (dwFileLength == INVALID_FILE_SIZE) return 0; +#ifdef _WIN32 + BYTE* pBuffer; + DWORD dwBytes; + // windows unicode filepaths are encoded in utf16 + std::wstring wpath = UTF_8::convert_to_utf16(path); + HANDLE hFile = CreateFileW(wpath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) return 0; + DWORD dwFileLength = GetFileSize(hFile, NULL); + if (dwFileLength == INVALID_FILE_SIZE) return 0; + // allocate an extra byte for the null char + pBuffer = (BYTE*)malloc((dwFileLength + 1) * sizeof(BYTE)); + ReadFile(hFile, pBuffer, dwFileLength, &dwBytes, NULL); + pBuffer[dwFileLength] = '\0'; + CloseHandle(hFile); + // just convert from unsigned char* + char* contents = (char*)pBuffer; +#else + struct stat st; + if (stat(path.c_str(), &st) == -1 || S_ISDIR(st.st_mode)) return 0; + std::ifstream file(path.c_str(), std::ios::in | std::ios::binary | std::ios::ate); + char* contents = 0; + if (file.is_open()) + { + size_t size = file.tellg(); // allocate an extra byte for the null char - pBuffer = (BYTE*)malloc((dwFileLength+1)*sizeof(BYTE)); - ReadFile(hFile, pBuffer, dwFileLength, &dwBytes, NULL); - pBuffer[dwFileLength] = '\0'; - CloseHandle(hFile); - // just convert from unsigned char* - char* contents = (char*) pBuffer; - #else - struct stat st; - if (stat(path.c_str(), &st) == -1 || S_ISDIR(st.st_mode)) return 0; - std::ifstream file(path.c_str(), std::ios::in | std::ios::binary | std::ios::ate); - char* contents = 0; - if (file.is_open()) { - size_t size = file.tellg(); - // allocate an extra byte for the null char - contents = (char*) malloc((size+1)*sizeof(char)); - file.seekg(0, std::ios::beg); - file.read(contents, size); - contents[size] = '\0'; - file.close(); - } - #endif + contents = (char*)malloc((size + 1) * sizeof(char)); + file.seekg(0, std::ios::beg); + file.read(contents, size); + contents[size] = '\0'; + file.close(); + } +#endif std::string extension; - if (path.length() > 5) { + if (path.length() > 5) + { extension = path.substr(path.length() - 5, 5); } - for(size_t i=0; i(str); // search until null delimiter - while (end) { + while (end) + { // add path from current position to delimiter paths.push_back(std::string(str, end - str)); str = end + 1; // skip delimiter @@ -449,6 +492,5 @@ namespace Sass { // return back return paths; } - } } diff --git a/src/file.hpp b/src/file.hpp index 279b9e9f62..6ad01ef68b 100644 --- a/src/file.hpp +++ b/src/file.hpp @@ -7,9 +7,11 @@ #include "sass/context.h" #include "ast_fwd_decl.hpp" -namespace Sass { +namespace Sass +{ - namespace File { + namespace File + { // return the current directory // always with forward slashes @@ -30,7 +32,7 @@ namespace Sass { // do a locigal clean up of the path // no physical check on the filesystem - std::string make_canonical_path (std::string path); + std::string make_canonical_path(std::string path); // join two path segments cleanly together // but only if right side is not absolute yet @@ -41,11 +43,13 @@ namespace Sass { std::string path_for_console(const std::string& rel_path, const std::string& abs_path, const std::string& orig_path); // create an absolute path by resolving relative paths with cwd - std::string rel2abs(const std::string& path, const std::string& base = ".", const std::string& cwd = get_cwd()); + std::string + rel2abs(const std::string& path, const std::string& base = ".", const std::string& cwd = get_cwd()); // create a path that is relative to the given base directory // path and base will first be resolved against cwd to make them absolute - std::string abs2rel(const std::string& path, const std::string& base = ".", const std::string& cwd = get_cwd()); + std::string + abs2rel(const std::string& path, const std::string& base = ".", const std::string& cwd = get_cwd()); // helper function to resolve a filename // searching without variations in all paths @@ -63,71 +67,78 @@ namespace Sass { // returned memory must be freed // will auto convert .sass files char* read_file(const std::string& file); - } // requested import - class Importer { + class Importer + { public: - // requested import path - std::string imp_path; - // parent context path - std::string ctx_path; - // base derived from context path - // this really just acts as a cache - std::string base_path; + // requested import path + std::string imp_path; + // parent context path + std::string ctx_path; + // base derived from context path + // this really just acts as a cache + std::string base_path; + public: - Importer(std::string imp_path, std::string ctx_path) - : imp_path(File::make_canonical_path(imp_path)), - ctx_path(File::make_canonical_path(ctx_path)), - base_path(File::dir_name(ctx_path)) - { } + Importer(std::string imp_path, std::string ctx_path) + : imp_path(File::make_canonical_path(imp_path)), ctx_path(File::make_canonical_path(ctx_path)), + base_path(File::dir_name(ctx_path)) + { + } }; // a resolved include (final import) - class Include : public Importer { + class Include : public Importer + { public: - // resolved absolute path - std::string abs_path; + // resolved absolute path + std::string abs_path; + public: - Include(const Importer& imp, std::string abs_path) - : Importer(imp), abs_path(abs_path) - { } + Include(const Importer& imp, std::string abs_path) : Importer(imp), abs_path(abs_path) + { + } }; // a loaded resource - class Resource { + class Resource + { public: - // the file contents - char* contents; - // conected sourcemap - char* srcmap; + // the file contents + char* contents; + // conected sourcemap + char* srcmap; + public: - Resource(char* contents, char* srcmap) - : contents(contents), srcmap(srcmap) - { } + Resource(char* contents, char* srcmap) : contents(contents), srcmap(srcmap) + { + } }; // parsed stylesheet from loaded resource - class StyleSheet : public Resource { + class StyleSheet : public Resource + { public: - // parsed root block - Block_Obj root; + // parsed root block + Block_Obj root; + public: - StyleSheet(const Resource& res, Block_Obj root) - : Resource(res), root(root) - { } + StyleSheet(const Resource& res, Block_Obj root) : Resource(res), root(root) + { + } }; - namespace File { + namespace File + { static std::vector defaultExtensions = { ".scss", ".sass", ".css" }; - std::vector resolve_includes(const std::string& root, const std::string& file, - const std::vector& exts = defaultExtensions); - + std::vector resolve_includes(const std::string& root, + const std::string& file, + const std::vector& exts = defaultExtensions); } - } #endif diff --git a/src/functions.cpp b/src/functions.cpp index 71078f8981..e2daa8f1d9 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -34,7 +34,8 @@ #define ARGR(argname, argtype, lo, hi) get_arg_r(argname, env, sig, pstate, lo, hi, backtrace) #define ARGM(argname, argtype, ctx) get_arg_m(argname, env, sig, pstate, backtrace, ctx) -namespace Sass { +namespace Sass +{ using std::stringstream; using std::endl; @@ -44,13 +45,7 @@ namespace Sass { sig_parser.lex(); std::string name(Util::normalize_underscores(sig_parser.lexed)); Parameters_Obj params = sig_parser.parse_parameters(); - return SASS_MEMORY_NEW(Definition, - ParserState("[built-in function]"), - sig, - name, - params, - func, - false); + return SASS_MEMORY_NEW(Definition, ParserState("[built-in function]"), sig, name, params, func, false); } Definition_Ptr make_c_function(Sass_Function_Entry c_func, Context& ctx) @@ -60,20 +55,11 @@ namespace Sass { const char* sig = sass_function_get_signature(c_func); Parser sig_parser = Parser::from_c_str(sig, ctx, ParserState("[c function]")); // allow to overload generic callback plus @warn, @error and @debug with custom functions - sig_parser.lex < alternatives < identifier, exactly <'*'>, - exactly < Constants::warn_kwd >, - exactly < Constants::error_kwd >, - exactly < Constants::debug_kwd > - > >(); + sig_parser.lex, exactly, + exactly, exactly>>(); std::string name(Util::normalize_underscores(sig_parser.lexed)); Parameters_Obj params = sig_parser.parse_parameters(); - return SASS_MEMORY_NEW(Definition, - ParserState("[c function]"), - sig, - name, - params, - c_func, - false, true); + return SASS_MEMORY_NEW(Definition, ParserState("[c function]"), sig, name, params, c_func, false, true); } std::string function_name(Signature sig) @@ -82,26 +68,34 @@ namespace Sass { return str.substr(0, str.find('(')); } - namespace Functions { + namespace Functions + { - inline void handle_utf8_error (const ParserState& pstate, Backtrace* backtrace) + inline void handle_utf8_error(const ParserState& pstate, Backtrace* backtrace) { - try { - throw; + try + { + throw; } - catch (utf8::invalid_code_point) { + catch (utf8::invalid_code_point) + { std::string msg("utf8::invalid_code_point"); error(msg, pstate, backtrace); } - catch (utf8::not_enough_room) { + catch (utf8::not_enough_room) + { std::string msg("utf8::not_enough_room"); error(msg, pstate, backtrace); } - catch (utf8::invalid_utf8) { + catch (utf8::invalid_utf8) + { std::string msg("utf8::invalid_utf8"); error(msg, pstate, backtrace); } - catch (...) { throw; } + catch (...) + { + throw; + } } template @@ -109,7 +103,8 @@ namespace Sass { { // Minimal error handling -- the expectation is that built-ins will be written correctly! T* val = Cast(env[argname]); - if (!val) { + if (!val) + { std::string msg("argument `"); msg += argname; msg += "` of `"; @@ -121,7 +116,8 @@ namespace Sass { return val; } - Map_Ptr get_arg_m(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtrace* backtrace, Context& ctx) + Map_Ptr + get_arg_m(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtrace* backtrace, Context& ctx) { // Minimal error handling -- the expectation is that built-ins will be written correctly! Map_Ptr val = Cast(env[argname]); @@ -135,12 +131,14 @@ namespace Sass { return val; } - Number_Ptr get_arg_r(const std::string& argname, Env& env, Signature sig, ParserState pstate, double lo, double hi, Backtrace* backtrace) + Number_Ptr + get_arg_r(const std::string& argname, Env& env, Signature sig, ParserState pstate, double lo, double hi, Backtrace* backtrace) { // Minimal error handling -- the expectation is that built-ins will be written correctly! Number_Ptr val = get_arg(argname, env, sig, pstate, backtrace); double v = val->value(); - if (!(lo <= v && v <= hi)) { + if (!(lo <= v && v <= hi)) + { std::stringstream msg; msg << "argument `" << argname << "` of `" << sig << "` must be between "; msg << lo << " and " << hi; @@ -149,21 +147,26 @@ namespace Sass { return val; } - #define ARGSEL(argname, seltype, contextualize) get_arg_sel(argname, env, sig, pstate, backtrace, ctx) +#define ARGSEL(argname, seltype, contextualize) \ + get_arg_sel(argname, env, sig, pstate, backtrace, ctx) template T get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtrace* backtrace, Context& ctx); template <> - Selector_List_Obj get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtrace* backtrace, Context& ctx) { + Selector_List_Obj + get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtrace* backtrace, Context& ctx) + { Expression_Obj exp = ARG(argname, Expression); - if (exp->concrete_type() == Expression::NULL_VAL) { + if (exp->concrete_type() == Expression::NULL_VAL) + { std::stringstream msg; msg << argname << ": null is not a valid selector: it must be a string,\n"; msg << "a list of strings, or a list of lists of strings for `" << function_name(sig) << "'"; error(msg.str(), pstate); } - if (String_Constant_Ptr str = Cast(exp)) { + if (String_Constant_Ptr str = Cast(exp)) + { str->quote_mark(0); } std::string exp_src = exp->to_string(ctx.c_options); @@ -171,14 +174,18 @@ namespace Sass { } template <> - Compound_Selector_Obj get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtrace* backtrace, Context& ctx) { + Compound_Selector_Obj + get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtrace* backtrace, Context& ctx) + { Expression_Obj exp = ARG(argname, Expression); - if (exp->concrete_type() == Expression::NULL_VAL) { + if (exp->concrete_type() == Expression::NULL_VAL) + { std::stringstream msg; msg << argname << ": null is not a string for `" << function_name(sig) << "'"; error(msg.str(), pstate); } - if (String_Constant_Ptr str = Cast(exp)) { + if (String_Constant_Ptr str = Cast(exp)) + { str->quote_mark(0); } std::string exp_src = exp->to_string(ctx.c_options); @@ -189,7 +196,7 @@ namespace Sass { return first->tail()->head(); } - #ifdef __MINGW32__ +#ifdef __MINGW32__ uint64_t GetSeed() { HCRYPTPROV hp = 0; @@ -203,13 +210,13 @@ namespace Sass { return seed; } - #else +#else uint64_t GetSeed() { std::random_device rd; return rd(); } - #endif +#endif // note: the performance of many implementations of // random_device degrades sharply once the entropy pool @@ -218,29 +225,34 @@ namespace Sass { static std::mt19937 rand(static_cast(GetSeed())); // features - static std::set features { - "global-variable-shadowing", - "extend-selector-pseudoclass", - "at-error", - "units-level-3" - }; + static std::set features{ "global-variable-shadowing", + "extend-selector-pseudoclass", "at-error", + "units-level-3" }; //////////////// // RGB FUNCTIONS //////////////// - inline double color_num(Number_Ptr n) { - if (n->unit() == "%") { + inline double color_num(Number_Ptr n) + { + if (n->unit() == "%") + { return std::min(std::max(n->value() * 255 / 100.0, 0.0), 255.0); - } else { + } + else + { return std::min(std::max(n->value(), 0.0), 255.0); } } - inline double alpha_num(Number_Ptr n) { - if (n->unit() == "%") { + inline double alpha_num(Number_Ptr n) + { + if (n->unit() == "%") + { return std::min(std::max(n->value(), 0.0), 100.0); - } else { + } + else + { return std::min(std::max(n->value(), 0.0), 1.0); } } @@ -248,22 +260,15 @@ namespace Sass { Signature rgb_sig = "rgb($red, $green, $blue)"; BUILT_IN(rgb) { - return SASS_MEMORY_NEW(Color, - pstate, - color_num(ARG("$red", Number)), - color_num(ARG("$green", Number)), - color_num(ARG("$blue", Number))); + return SASS_MEMORY_NEW(Color, pstate, color_num(ARG("$red", Number)), + color_num(ARG("$green", Number)), color_num(ARG("$blue", Number))); } Signature rgba_4_sig = "rgba($red, $green, $blue, $alpha)"; BUILT_IN(rgba_4) { - return SASS_MEMORY_NEW(Color, - pstate, - color_num(ARG("$red", Number)), - color_num(ARG("$green", Number)), - color_num(ARG("$blue", Number)), - alpha_num(ARG("$alpha", Number))); + return SASS_MEMORY_NEW(Color, pstate, color_num(ARG("$red", Number)), color_num(ARG("$green", Number)), + color_num(ARG("$blue", Number)), alpha_num(ARG("$alpha", Number))); } Signature rgba_2_sig = "rgba($color, $alpha)"; @@ -278,40 +283,45 @@ namespace Sass { Signature red_sig = "red($color)"; BUILT_IN(red) - { return SASS_MEMORY_NEW(Number, pstate, ARG("$color", Color)->r()); } + { + return SASS_MEMORY_NEW(Number, pstate, ARG("$color", Color)->r()); + } Signature green_sig = "green($color)"; BUILT_IN(green) - { return SASS_MEMORY_NEW(Number, pstate, ARG("$color", Color)->g()); } + { + return SASS_MEMORY_NEW(Number, pstate, ARG("$color", Color)->g()); + } Signature blue_sig = "blue($color)"; BUILT_IN(blue) - { return SASS_MEMORY_NEW(Number, pstate, ARG("$color", Color)->b()); } + { + return SASS_MEMORY_NEW(Number, pstate, ARG("$color", Color)->b()); + } - Color* colormix(Context& ctx, ParserState& pstate, Color* color1, Color* color2, Number* weight) { - double p = weight->value()/100; - double w = 2*p - 1; + Color* colormix(Context& ctx, ParserState& pstate, Color* color1, Color* color2, Number* weight) + { + double p = weight->value() / 100; + double w = 2 * p - 1; double a = color1->a() - color2->a(); - double w1 = (((w * a == -1) ? w : (w + a)/(1 + w*a)) + 1)/2.0; + double w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; double w2 = 1 - w1; - return SASS_MEMORY_NEW(Color, - pstate, - Sass::round(w1*color1->r() + w2*color2->r(), ctx.c_options.precision), - Sass::round(w1*color1->g() + w2*color2->g(), ctx.c_options.precision), - Sass::round(w1*color1->b() + w2*color2->b(), ctx.c_options.precision), - color1->a()*p + color2->a()*(1-p)); + return SASS_MEMORY_NEW(Color, pstate, + Sass::round(w1 * color1->r() + w2 * color2->r(), ctx.c_options.precision), + Sass::round(w1 * color1->g() + w2 * color2->g(), ctx.c_options.precision), + Sass::round(w1 * color1->b() + w2 * color2->b(), ctx.c_options.precision), + color1->a() * p + color2->a() * (1 - p)); } Signature mix_sig = "mix($color-1, $color-2, $weight: 50%)"; BUILT_IN(mix) { - Color_Obj color1 = ARG("$color-1", Color); - Color_Obj color2 = ARG("$color-2", Color); + Color_Obj color1 = ARG("$color-1", Color); + Color_Obj color2 = ARG("$color-2", Color); Number_Obj weight = ARGR("$weight", Number, 0, 100); return colormix(ctx, pstate, color1, color2, weight); - } //////////////// @@ -319,12 +329,19 @@ namespace Sass { //////////////// // RGB to HSL helper function - struct HSL { double h; double s; double l; }; + struct HSL + { + double h; + double s; + double l; + }; HSL rgb_to_hsl(double r, double g, double b) { // Algorithm from http://en.wikipedia.org/wiki/wHSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV - r /= 255.0; g /= 255.0; b /= 255.0; + r /= 255.0; + g /= 255.0; + b /= 255.0; double max = std::max(r, std::max(g, b)); double min = std::min(r, std::min(g, b)); @@ -334,16 +351,23 @@ namespace Sass { double s; double l = (max + min) / 2.0; - if (max == min) { + if (max == min) + { h = s = 0; // achromatic } - else { - if (l < 0.5) s = delta / (max + min); - else s = delta / (2.0 - max - min); + else + { + if (l < 0.5) + s = delta / (max + min); + else + s = delta / (2.0 - max - min); - if (r == max) h = (g - b) / delta + (g < b ? 6 : 0); - else if (g == max) h = (b - r) / delta + 2; - else if (b == max) h = (r - g) / delta + 4; + if (r == max) + h = (g - b) / delta + (g < b ? 6 : 0); + else if (g == max) + h = (b - r) / delta + 2; + else if (b == max) + h = (r - g) / delta + 4; } HSL hsl_struct; @@ -355,12 +379,15 @@ namespace Sass { } // hue to RGB helper function - double h_to_rgb(double m1, double m2, double h) { - while (h < 0) h += 1; - while (h > 1) h -= 1; - if (h*6.0 < 1) return m1 + (m2 - m1)*h*6; - if (h*2.0 < 1) return m2; - if (h*3.0 < 2) return m1 + (m2 - m1) * (2.0/3.0 - h)*6; + double h_to_rgb(double m1, double m2, double h) + { + while (h < 0) + h += 1; + while (h > 1) + h -= 1; + if (h * 6.0 < 1) return m1 + (m2 - m1) * h * 6; + if (h * 2.0 < 1) return m2; + if (h * 3.0 < 2) return m1 + (m2 - m1) * (2.0 / 3.0 - h) * 6; return m1; } @@ -374,8 +401,10 @@ namespace Sass { if (s < 0) s = 0; if (l > 1) l = 1; if (s > 1) s = 1; - while (h < 0) h += 1; - while (h > 1) h -= 1; + while (h < 0) + h += 1; + while (h > 1) + h -= 1; // if saturation is exacly zero, we loose // information for hue, since it will evaluate @@ -385,13 +414,15 @@ namespace Sass { // Algorithm from the CSS3 spec: http://www.w3.org/TR/css3-color/#hsl-color. double m2; - if (l <= 0.5) m2 = l*(s+1.0); - else m2 = (l+s)-(l*s); - double m1 = (l*2.0)-m2; + if (l <= 0.5) + m2 = l * (s + 1.0); + else + m2 = (l + s) - (l * s); + double m1 = (l * 2.0) - m2; // round the results -- consider moving this into the Color constructor - double r = (h_to_rgb(m1, m2, h + 1.0/3.0) * 255.0); + double r = (h_to_rgb(m1, m2, h + 1.0 / 3.0) * 255.0); double g = (h_to_rgb(m1, m2, h) * 255.0); - double b = (h_to_rgb(m1, m2, h - 1.0/3.0) * 255.0); + double b = (h_to_rgb(m1, m2, h - 1.0 / 3.0) * 255.0); return SASS_MEMORY_NEW(Color, pstate, r, g, b, a); } @@ -399,32 +430,22 @@ namespace Sass { Signature hsl_sig = "hsl($hue, $saturation, $lightness)"; BUILT_IN(hsl) { - return hsla_impl(ARG("$hue", Number)->value(), - ARG("$saturation", Number)->value(), - ARG("$lightness", Number)->value(), - 1.0, - ctx, - pstate); + return hsla_impl(ARG("$hue", Number)->value(), ARG("$saturation", Number)->value(), + ARG("$lightness", Number)->value(), 1.0, ctx, pstate); } Signature hsla_sig = "hsla($hue, $saturation, $lightness, $alpha)"; BUILT_IN(hsla) { - return hsla_impl(ARG("$hue", Number)->value(), - ARG("$saturation", Number)->value(), - ARG("$lightness", Number)->value(), - ARG("$alpha", Number)->value(), - ctx, - pstate); + return hsla_impl(ARG("$hue", Number)->value(), ARG("$saturation", Number)->value(), + ARG("$lightness", Number)->value(), ARG("$alpha", Number)->value(), ctx, pstate); } Signature hue_sig = "hue($color)"; BUILT_IN(hue) { Color_Ptr rgb_color = ARG("$color", Color); - HSL hsl_color = rgb_to_hsl(rgb_color->r(), - rgb_color->g(), - rgb_color->b()); + HSL hsl_color = rgb_to_hsl(rgb_color->r(), rgb_color->g(), rgb_color->b()); return SASS_MEMORY_NEW(Number, pstate, hsl_color.h, "deg"); } @@ -432,9 +453,7 @@ namespace Sass { BUILT_IN(saturation) { Color_Ptr rgb_color = ARG("$color", Color); - HSL hsl_color = rgb_to_hsl(rgb_color->r(), - rgb_color->g(), - rgb_color->b()); + HSL hsl_color = rgb_to_hsl(rgb_color->r(), rgb_color->g(), rgb_color->b()); return SASS_MEMORY_NEW(Number, pstate, hsl_color.s, "%"); } @@ -442,9 +461,7 @@ namespace Sass { BUILT_IN(lightness) { Color_Ptr rgb_color = ARG("$color", Color); - HSL hsl_color = rgb_to_hsl(rgb_color->r(), - rgb_color->g(), - rgb_color->b()); + HSL hsl_color = rgb_to_hsl(rgb_color->r(), rgb_color->g(), rgb_color->b()); return SASS_MEMORY_NEW(Number, pstate, hsl_color.l, "%"); } @@ -453,15 +470,8 @@ namespace Sass { { Color_Ptr rgb_color = ARG("$color", Color); Number_Ptr degrees = ARG("$degrees", Number); - HSL hsl_color = rgb_to_hsl(rgb_color->r(), - rgb_color->g(), - rgb_color->b()); - return hsla_impl(hsl_color.h + degrees->value(), - hsl_color.s, - hsl_color.l, - rgb_color->a(), - ctx, - pstate); + HSL hsl_color = rgb_to_hsl(rgb_color->r(), rgb_color->g(), rgb_color->b()); + return hsla_impl(hsl_color.h + degrees->value(), hsl_color.s, hsl_color.l, rgb_color->a(), ctx, pstate); } Signature lighten_sig = "lighten($color, $amount)"; @@ -469,21 +479,15 @@ namespace Sass { { Color_Ptr rgb_color = ARG("$color", Color); Number_Ptr amount = ARGR("$amount", Number, 0, 100); - HSL hsl_color = rgb_to_hsl(rgb_color->r(), - rgb_color->g(), - rgb_color->b()); - //Check lightness is not negative before lighten it + HSL hsl_color = rgb_to_hsl(rgb_color->r(), rgb_color->g(), rgb_color->b()); + // Check lightness is not negative before lighten it double hslcolorL = hsl_color.l; - if (hslcolorL < 0) { + if (hslcolorL < 0) + { hslcolorL = 0; } - return hsla_impl(hsl_color.h, - hsl_color.s, - hslcolorL + amount->value(), - rgb_color->a(), - ctx, - pstate); + return hsla_impl(hsl_color.h, hsl_color.s, hslcolorL + amount->value(), rgb_color->a(), ctx, pstate); } Signature darken_sig = "darken($color, $amount)"; @@ -491,22 +495,16 @@ namespace Sass { { Color_Ptr rgb_color = ARG("$color", Color); Number_Ptr amount = ARGR("$amount", Number, 0, 100); - HSL hsl_color = rgb_to_hsl(rgb_color->r(), - rgb_color->g(), - rgb_color->b()); + HSL hsl_color = rgb_to_hsl(rgb_color->r(), rgb_color->g(), rgb_color->b()); - //Check lightness if not over 100, before darken it + // Check lightness if not over 100, before darken it double hslcolorL = hsl_color.l; - if (hslcolorL > 100) { + if (hslcolorL > 100) + { hslcolorL = 100; } - return hsla_impl(hsl_color.h, - hsl_color.s, - hslcolorL - amount->value(), - rgb_color->a(), - ctx, - pstate); + return hsla_impl(hsl_color.h, hsl_color.s, hslcolorL - amount->value(), rgb_color->a(), ctx, pstate); } Signature saturate_sig = "saturate($color, $amount: false)"; @@ -514,32 +512,29 @@ namespace Sass { { // CSS3 filter function overload: pass literal through directly Number_Ptr amount = Cast(env["$amount"]); - if (!amount) { - return SASS_MEMORY_NEW(String_Quoted, pstate, "saturate(" + env["$color"]->to_string(ctx.c_options) + ")"); + if (!amount) + { + return SASS_MEMORY_NEW(String_Quoted, pstate, + "saturate(" + env["$color"]->to_string(ctx.c_options) + ")"); } ARGR("$amount", Number, 0, 100); Color_Ptr rgb_color = ARG("$color", Color); - HSL hsl_color = rgb_to_hsl(rgb_color->r(), - rgb_color->g(), - rgb_color->b()); + HSL hsl_color = rgb_to_hsl(rgb_color->r(), rgb_color->g(), rgb_color->b()); double hslcolorS = hsl_color.s + amount->value(); // Saturation cannot be below 0 or above 100 - if (hslcolorS < 0) { + if (hslcolorS < 0) + { hslcolorS = 0; } - if (hslcolorS > 100) { + if (hslcolorS > 100) + { hslcolorS = 100; } - return hsla_impl(hsl_color.h, - hslcolorS, - hsl_color.l, - rgb_color->a(), - ctx, - pstate); + return hsla_impl(hsl_color.h, hslcolorS, hsl_color.l, rgb_color->a(), ctx, pstate); } Signature desaturate_sig = "desaturate($color, $amount)"; @@ -547,26 +542,21 @@ namespace Sass { { Color_Ptr rgb_color = ARG("$color", Color); Number_Ptr amount = ARGR("$amount", Number, 0, 100); - HSL hsl_color = rgb_to_hsl(rgb_color->r(), - rgb_color->g(), - rgb_color->b()); + HSL hsl_color = rgb_to_hsl(rgb_color->r(), rgb_color->g(), rgb_color->b()); double hslcolorS = hsl_color.s - amount->value(); // Saturation cannot be below 0 or above 100 - if (hslcolorS <= 0) { + if (hslcolorS <= 0) + { hslcolorS = 0; } - if (hslcolorS > 100) { + if (hslcolorS > 100) + { hslcolorS = 100; } - return hsla_impl(hsl_color.h, - hslcolorS, - hsl_color.l, - rgb_color->a(), - ctx, - pstate); + return hsla_impl(hsl_color.h, hslcolorS, hsl_color.l, rgb_color->a(), ctx, pstate); } Signature grayscale_sig = "grayscale($color)"; @@ -574,35 +564,22 @@ namespace Sass { { // CSS3 filter function overload: pass literal through directly Number_Ptr amount = Cast(env["$color"]); - if (amount) { + if (amount) + { return SASS_MEMORY_NEW(String_Quoted, pstate, "grayscale(" + amount->to_string(ctx.c_options) + ")"); } Color_Ptr rgb_color = ARG("$color", Color); - HSL hsl_color = rgb_to_hsl(rgb_color->r(), - rgb_color->g(), - rgb_color->b()); - return hsla_impl(hsl_color.h, - 0.0, - hsl_color.l, - rgb_color->a(), - ctx, - pstate); + HSL hsl_color = rgb_to_hsl(rgb_color->r(), rgb_color->g(), rgb_color->b()); + return hsla_impl(hsl_color.h, 0.0, hsl_color.l, rgb_color->a(), ctx, pstate); } Signature complement_sig = "complement($color)"; BUILT_IN(complement) { Color_Ptr rgb_color = ARG("$color", Color); - HSL hsl_color = rgb_to_hsl(rgb_color->r(), - rgb_color->g(), - rgb_color->b()); - return hsla_impl(hsl_color.h - 180.0, - hsl_color.s, - hsl_color.l, - rgb_color->a(), - ctx, - pstate); + HSL hsl_color = rgb_to_hsl(rgb_color->r(), rgb_color->g(), rgb_color->b()); + return hsla_impl(hsl_color.h - 180.0, hsl_color.s, hsl_color.l, rgb_color->a(), ctx, pstate); } Signature invert_sig = "invert($color, $weight: 100%)"; @@ -610,18 +587,15 @@ namespace Sass { { // CSS3 filter function overload: pass literal through directly Number_Ptr amount = Cast(env["$color"]); - if (amount) { + if (amount) + { return SASS_MEMORY_NEW(String_Quoted, pstate, "invert(" + amount->to_string(ctx.c_options) + ")"); } Number_Obj weight = ARGR("$weight", Number, 0, 100); Color_Ptr rgb_color = ARG("$color", Color); - Color_Obj inv = SASS_MEMORY_NEW(Color, - pstate, - 255 - rgb_color->r(), - 255 - rgb_color->g(), - 255 - rgb_color->b(), - rgb_color->a()); + Color_Obj inv = SASS_MEMORY_NEW(Color, pstate, 255 - rgb_color->r(), 255 - rgb_color->g(), + 255 - rgb_color->b(), rgb_color->a()); return colormix(ctx, pstate, inv, rgb_color, weight); } @@ -633,13 +607,15 @@ namespace Sass { BUILT_IN(alpha) { String_Constant_Ptr ie_kwd = Cast(env["$color"]); - if (ie_kwd) { + if (ie_kwd) + { return SASS_MEMORY_NEW(String_Quoted, pstate, "alpha(" + ie_kwd->value() + ")"); } // CSS3 filter function overload: pass literal through directly Number_Ptr amount = Cast(env["$color"]); - if (amount) { + if (amount) + { return SASS_MEMORY_NEW(String_Quoted, pstate, "opacity(" + amount->to_string(ctx.c_options) + ")"); } @@ -653,12 +629,7 @@ namespace Sass { Color_Ptr color = ARG("$color", Color); double amount = ARGR("$amount", Number, 0, 1)->value(); double alpha = std::min(color->a() + amount, 1.0); - return SASS_MEMORY_NEW(Color, - pstate, - color->r(), - color->g(), - color->b(), - alpha); + return SASS_MEMORY_NEW(Color, pstate, color->r(), color->g(), color->b(), alpha); } Signature transparentize_sig = "transparentize($color, $amount)"; @@ -668,19 +639,16 @@ namespace Sass { Color_Ptr color = ARG("$color", Color); double amount = ARGR("$amount", Number, 0, 1)->value(); double alpha = std::max(color->a() - amount, 0.0); - return SASS_MEMORY_NEW(Color, - pstate, - color->r(), - color->g(), - color->b(), - alpha); + return SASS_MEMORY_NEW(Color, pstate, color->r(), color->g(), color->b(), alpha); } //////////////////////// // OTHER COLOR FUNCTIONS //////////////////////// - Signature adjust_color_sig = "adjust-color($color, $red: false, $green: false, $blue: false, $hue: false, $saturation: false, $lightness: false, $alpha: false)"; + Signature adjust_color_sig = "adjust-color($color, $red: false, $green: false, $blue: false, " + "$hue: false, $saturation: false, $lightness: false, $alpha: " + "false)"; BUILT_IN(adjust_color) { Color_Ptr color = ARG("$color", Color); @@ -695,39 +663,31 @@ namespace Sass { bool rgb = r || g || b; bool hsl = h || s || l; - if (rgb && hsl) { + if (rgb && hsl) + { error("Cannot specify HSL and RGB values for a color at the same time for `adjust-color'", pstate); } - if (rgb) { - double rr = r ? ARGR("$red", Number, -255, 255)->value() : 0; + if (rgb) + { + double rr = r ? ARGR("$red", Number, -255, 255)->value() : 0; double gg = g ? ARGR("$green", Number, -255, 255)->value() : 0; - double bb = b ? ARGR("$blue", Number, -255, 255)->value() : 0; + double bb = b ? ARGR("$blue", Number, -255, 255)->value() : 0; double aa = a ? ARGR("$alpha", Number, -1, 1)->value() : 0; - return SASS_MEMORY_NEW(Color, - pstate, - color->r() + rr, - color->g() + gg, - color->b() + bb, + return SASS_MEMORY_NEW(Color, pstate, color->r() + rr, color->g() + gg, color->b() + bb, color->a() + aa); } - if (hsl) { + if (hsl) + { HSL hsl_struct = rgb_to_hsl(color->r(), color->g(), color->b()); double ss = s ? ARGR("$saturation", Number, -100, 100)->value() : 0; - double ll = l ? ARGR("$lightness", Number, -100, 100)->value() : 0; - double aa = a ? ARGR("$alpha", Number, -1, 1)->value() : 0; - return hsla_impl(hsl_struct.h + (h ? h->value() : 0), - hsl_struct.s + ss, - hsl_struct.l + ll, - color->a() + aa, - ctx, - pstate); - } - if (a) { - return SASS_MEMORY_NEW(Color, - pstate, - color->r(), - color->g(), - color->b(), + double ll = l ? ARGR("$lightness", Number, -100, 100)->value() : 0; + double aa = a ? ARGR("$alpha", Number, -1, 1)->value() : 0; + return hsla_impl(hsl_struct.h + (h ? h->value() : 0), hsl_struct.s + ss, hsl_struct.l + ll, + color->a() + aa, ctx, pstate); + } + if (a) + { + return SASS_MEMORY_NEW(Color, pstate, color->r(), color->g(), color->b(), color->a() + (a ? a->value() : 0)); } error("not enough arguments for `adjust-color'", pstate); @@ -735,7 +695,9 @@ namespace Sass { return color; } - Signature scale_color_sig = "scale-color($color, $red: false, $green: false, $blue: false, $hue: false, $saturation: false, $lightness: false, $alpha: false)"; + Signature scale_color_sig = "scale-color($color, $red: false, $green: false, $blue: false, " + "$hue: false, $saturation: false, $lightness: false, $alpha: " + "false)"; BUILT_IN(scale_color) { Color_Ptr color = ARG("$color", Color); @@ -750,26 +712,28 @@ namespace Sass { bool rgb = r || g || b; bool hsl = h || s || l; - if (rgb && hsl) { + if (rgb && hsl) + { error("Cannot specify HSL and RGB values for a color at the same time for `scale-color'", pstate); } - if (rgb) { - double rscale = (r ? ARGR("$red", Number, -100.0, 100.0)->value() : 0.0) / 100.0; + if (rgb) + { + double rscale = (r ? ARGR("$red", Number, -100.0, 100.0)->value() : 0.0) / 100.0; double gscale = (g ? ARGR("$green", Number, -100.0, 100.0)->value() : 0.0) / 100.0; - double bscale = (b ? ARGR("$blue", Number, -100.0, 100.0)->value() : 0.0) / 100.0; + double bscale = (b ? ARGR("$blue", Number, -100.0, 100.0)->value() : 0.0) / 100.0; double ascale = (a ? ARGR("$alpha", Number, -100.0, 100.0)->value() : 0.0) / 100.0; - return SASS_MEMORY_NEW(Color, - pstate, + return SASS_MEMORY_NEW(Color, pstate, color->r() + rscale * (rscale > 0.0 ? 255 - color->r() : color->r()), color->g() + gscale * (gscale > 0.0 ? 255 - color->g() : color->g()), color->b() + bscale * (bscale > 0.0 ? 255 - color->b() : color->b()), color->a() + ascale * (ascale > 0.0 ? 1.0 - color->a() : color->a())); } - if (hsl) { - double hscale = (h ? ARGR("$hue", Number, -100.0, 100.0)->value() : 0.0) / 100.0; + if (hsl) + { + double hscale = (h ? ARGR("$hue", Number, -100.0, 100.0)->value() : 0.0) / 100.0; double sscale = (s ? ARGR("$saturation", Number, -100.0, 100.0)->value() : 0.0) / 100.0; - double lscale = (l ? ARGR("$lightness", Number, -100.0, 100.0)->value() : 0.0) / 100.0; - double ascale = (a ? ARGR("$alpha", Number, -100.0, 100.0)->value() : 0.0) / 100.0; + double lscale = (l ? ARGR("$lightness", Number, -100.0, 100.0)->value() : 0.0) / 100.0; + double ascale = (a ? ARGR("$alpha", Number, -100.0, 100.0)->value() : 0.0) / 100.0; HSL hsl_struct = rgb_to_hsl(color->r(), color->g(), color->b()); hsl_struct.h += hscale * (hscale > 0.0 ? 360.0 - hsl_struct.h : hsl_struct.h); hsl_struct.s += sscale * (sscale > 0.0 ? 100.0 - hsl_struct.s : hsl_struct.s); @@ -777,13 +741,10 @@ namespace Sass { double alpha = color->a() + ascale * (ascale > 0.0 ? 1.0 - color->a() : color->a()); return hsla_impl(hsl_struct.h, hsl_struct.s, hsl_struct.l, alpha, ctx, pstate); } - if (a) { + if (a) + { double ascale = (ARGR("$alpha", Number, -100.0, 100.0)->value()) / 100.0; - return SASS_MEMORY_NEW(Color, - pstate, - color->r(), - color->g(), - color->b(), + return SASS_MEMORY_NEW(Color, pstate, color->r(), color->g(), color->b(), color->a() + ascale * (ascale > 0.0 ? 1.0 - color->a() : color->a())); } error("not enough arguments for `scale-color'", pstate); @@ -791,7 +752,9 @@ namespace Sass { return color; } - Signature change_color_sig = "change-color($color, $red: false, $green: false, $blue: false, $hue: false, $saturation: false, $lightness: false, $alpha: false)"; + Signature change_color_sig = "change-color($color, $red: false, $green: false, $blue: false, " + "$hue: false, $saturation: false, $lightness: false, $alpha: " + "false)"; BUILT_IN(change_color) { Color_Ptr color = ARG("$color", Color); @@ -806,44 +769,44 @@ namespace Sass { bool rgb = r || g || b; bool hsl = h || s || l; - if (rgb && hsl) { + if (rgb && hsl) + { error("Cannot specify HSL and RGB values for a color at the same time for `change-color'", pstate); } - if (rgb) { - return SASS_MEMORY_NEW(Color, - pstate, - r ? ARGR("$red", Number, 0, 255)->value() : color->r(), + if (rgb) + { + return SASS_MEMORY_NEW(Color, pstate, r ? ARGR("$red", Number, 0, 255)->value() : color->r(), g ? ARGR("$green", Number, 0, 255)->value() : color->g(), - b ? ARGR("$blue", Number, 0, 255)->value() : color->b(), + b ? ARGR("$blue", Number, 0, 255)->value() : color->b(), a ? ARGR("$alpha", Number, 0, 255)->value() : color->a()); } - if (hsl) { + if (hsl) + { HSL hsl_struct = rgb_to_hsl(color->r(), color->g(), color->b()); if (h) hsl_struct.h = std::fmod(h->value(), 360.0); if (s) hsl_struct.s = ARGR("$saturation", Number, 0, 100)->value(); - if (l) hsl_struct.l = ARGR("$lightness", Number, 0, 100)->value(); + if (l) hsl_struct.l = ARGR("$lightness", Number, 0, 100)->value(); double alpha = a ? ARGR("$alpha", Number, 0, 1.0)->value() : color->a(); return hsla_impl(hsl_struct.h, hsl_struct.s, hsl_struct.l, alpha, ctx, pstate); } - if (a) { + if (a) + { double alpha = ARGR("$alpha", Number, 0, 1.0)->value(); - return SASS_MEMORY_NEW(Color, - pstate, - color->r(), - color->g(), - color->b(), - alpha); + return SASS_MEMORY_NEW(Color, pstate, color->r(), color->g(), color->b(), alpha); } error("not enough arguments for `change-color'", pstate); // unreachable return color; } - template - static double cap_channel(double c) { - if (c > range) return range; - else if (c < 0) return 0; - else return c; + template static double cap_channel(double c) + { + if (c > range) + return range; + else if (c < 0) + return 0; + else + return c; } Signature ie_hex_str_sig = "ie-hex-str($color)"; @@ -853,7 +816,7 @@ namespace Sass { double r = cap_channel<0xff>(c->r()); double g = cap_channel<0xff>(c->g()); double b = cap_channel<0xff>(c->b()); - double a = cap_channel<1> (c->a()) * 255; + double a = cap_channel<1>(c->a()) * 255; std::stringstream ss; ss << '#' << std::setw(2) << std::setfill('0'); @@ -863,7 +826,8 @@ namespace Sass { ss << std::hex << std::setw(2) << static_cast(Sass::round(b, ctx.c_options.precision)); std::string result(ss.str()); - for (size_t i = 0, L = result.length(); i < L; ++i) { + for (size_t i = 0, L = result.length(); i < L; ++i) + { result[i] = std::toupper(result[i]); } return SASS_MEMORY_NEW(String_Quoted, pstate, result); @@ -877,16 +841,19 @@ namespace Sass { BUILT_IN(sass_unquote) { AST_Node_Obj arg = env["$string"]; - if (String_Quoted_Ptr string_quoted = Cast(arg)) { + if (String_Quoted_Ptr string_quoted = Cast(arg)) + { String_Constant_Ptr result = SASS_MEMORY_NEW(String_Constant, pstate, string_quoted->value()); // remember if the string was quoted (color tokens) result->is_delayed(true); // delay colors return result; } - else if (String_Constant_Ptr str = Cast(arg)) { + else if (String_Constant_Ptr str = Cast(arg)) + { return str; } - else if (Expression_Ptr ex = Cast(arg)) { + else if (Expression_Ptr ex = Cast(arg)) + { Sass_Output_Style oldstyle = ctx.c_options.output_style; ctx.c_options.output_style = SASS_STYLE_NESTED; std::string val(arg->to_string(ctx.c_options)); @@ -904,7 +871,8 @@ namespace Sass { { AST_Node_Obj arg = env["$string"]; // only set quote mark to true if already a string - if (String_Quoted_Ptr qstr = Cast(arg)) { + if (String_Quoted_Ptr qstr = Cast(arg)) + { qstr->quote_mark('*'); return qstr; } @@ -920,14 +888,17 @@ namespace Sass { BUILT_IN(str_length) { size_t len = std::string::npos; - try { + try + { String_Constant_Ptr s = ARG("$string", String_Constant); len = UTF_8::code_point_count(s->value(), 0, s->value().size()); - } // handle any invalid utf8 errors // other errors will be re-thrown - catch (...) { handle_utf8_error(pstate, backtrace); } + catch (...) + { + handle_utf8_error(pstate, backtrace); + } // return something even if we had an error (-1) return SASS_MEMORY_NEW(Number, pstate, (double)len); } @@ -936,7 +907,8 @@ namespace Sass { BUILT_IN(str_insert) { std::string str; - try { + try + { String_Constant_Ptr s = ARG("$string", String_Constant); str = s->value(); str = unquote(str); @@ -947,34 +919,43 @@ namespace Sass { double index = ind->value(); size_t len = UTF_8::code_point_count(str, 0, str.size()); - if (index > 0 && index <= len) { + if (index > 0 && index <= len) + { // positive and within string length str.insert(UTF_8::offset_at_position(str, static_cast(index) - 1), ins); } - else if (index > len) { + else if (index > len) + { // positive and past string length str += ins; } - else if (index == 0) { + else if (index == 0) + { str = ins + str; } - else if (std::abs(index) <= len) { + else if (std::abs(index) <= len) + { // negative and within string length index += len + 1; str.insert(UTF_8::offset_at_position(str, static_cast(index)), ins); } - else { + else + { // negative and past string length str = ins + str; } - if (String_Quoted_Ptr ss = Cast(s)) { + if (String_Quoted_Ptr ss = Cast(s)) + { if (ss->quote_mark()) str = quote(str); } } // handle any invalid utf8 errors // other errors will be re-thrown - catch (...) { handle_utf8_error(pstate, backtrace); } + catch (...) + { + handle_utf8_error(pstate, backtrace); + } return SASS_MEMORY_NEW(String_Quoted, pstate, str); } @@ -982,7 +963,8 @@ namespace Sass { BUILT_IN(str_index) { size_t index = std::string::npos; - try { + try + { String_Constant_Ptr s = ARG("$string", String_Constant); String_Constant_Ptr t = ARG("$substring", String_Constant); std::string str = s->value(); @@ -991,14 +973,18 @@ namespace Sass { substr = unquote(substr); size_t c_index = str.find(substr); - if(c_index == std::string::npos) { + if (c_index == std::string::npos) + { return SASS_MEMORY_NEW(Null, pstate); } index = UTF_8::code_point_count(str, 0, c_index) + 1; } // handle any invalid utf8 errors // other errors will be re-thrown - catch (...) { handle_utf8_error(pstate, backtrace); } + catch (...) + { + handle_utf8_error(pstate, backtrace); + } // return something even if we had an error (-1) return SASS_MEMORY_NEW(Number, pstate, (double)index); } @@ -1007,7 +993,8 @@ namespace Sass { BUILT_IN(str_slice) { std::string newstr; - try { + try + { String_Constant_Ptr s = ARG("$string", String_Constant); double start_at = ARG("$start-at", Number)->value(); double end_at = ARG("$end-at", Number)->value(); @@ -1017,25 +1004,35 @@ namespace Sass { size_t size = utf8::distance(str.begin(), str.end()); - if (!Cast(env["$end-at"])) { + if (!Cast(env["$end-at"])) + { end_at = -1; } - if (end_at == 0 || (end_at + size) < 0) { + if (end_at == 0 || (end_at + size) < 0) + { if (ss && ss->quote_mark()) newstr = quote(""); return SASS_MEMORY_NEW(String_Quoted, pstate, newstr); } - if (end_at < 0) { + if (end_at < 0) + { end_at += size + 1; if (end_at == 0) end_at = 1; } - if (end_at > size) { end_at = (double)size; } - if (start_at < 0) { + if (end_at > size) + { + end_at = (double)size; + } + if (start_at < 0) + { start_at += size + 1; - if (start_at < 0) start_at = 0; + if (start_at < 0) start_at = 0; + } + else if (start_at == 0) + { + ++start_at; } - else if (start_at == 0) { ++ start_at; } if (start_at <= end_at) { @@ -1045,13 +1042,17 @@ namespace Sass { utf8::advance(end, end_at - start_at + 1, str.end()); newstr = std::string(start, end); } - if (ss) { - if(ss->quote_mark()) newstr = quote(newstr); + if (ss) + { + if (ss->quote_mark()) newstr = quote(newstr); } } // handle any invalid utf8 errors // other errors will be re-thrown - catch (...) { handle_utf8_error(pstate, backtrace); } + catch (...) + { + handle_utf8_error(pstate, backtrace); + } return SASS_MEMORY_NEW(String_Quoted, pstate, newstr); } @@ -1061,17 +1062,22 @@ namespace Sass { String_Constant_Ptr s = ARG("$string", String_Constant); std::string str = s->value(); - for (size_t i = 0, L = str.length(); i < L; ++i) { - if (Sass::Util::isAscii(str[i])) { + for (size_t i = 0, L = str.length(); i < L; ++i) + { + if (Sass::Util::isAscii(str[i])) + { str[i] = std::toupper(str[i]); } } - if (String_Quoted_Ptr ss = Cast(s)) { + if (String_Quoted_Ptr ss = Cast(s)) + { String_Quoted_Ptr cpy = SASS_MEMORY_COPY(ss); cpy->value(str); return cpy; - } else { + } + else + { return SASS_MEMORY_NEW(String_Quoted, pstate, str); } } @@ -1082,17 +1088,22 @@ namespace Sass { String_Constant_Ptr s = ARG("$string", String_Constant); std::string str = s->value(); - for (size_t i = 0, L = str.length(); i < L; ++i) { - if (Sass::Util::isAscii(str[i])) { + for (size_t i = 0, L = str.length(); i < L; ++i) + { + if (Sass::Util::isAscii(str[i])) + { str[i] = std::tolower(str[i]); } } - if (String_Quoted_Ptr ss = Cast(s)) { + if (String_Quoted_Ptr ss = Cast(s)) + { String_Quoted_Ptr cpy = SASS_MEMORY_COPY(ss); cpy->value(str); return cpy; - } else { + } + else + { return SASS_MEMORY_NEW(String_Quoted, pstate, str); } } @@ -1105,7 +1116,8 @@ namespace Sass { BUILT_IN(percentage) { Number_Ptr n = ARG("$number", Number); - if (!n->is_unitless()) error("argument $number of `" + std::string(sig) + "` must be unitless", pstate); + if (!n->is_unitless()) + error("argument $number of `" + std::string(sig) + "` must be unitless", pstate); return SASS_MEMORY_NEW(Number, pstate, n->value() * 100, "%"); } @@ -1154,15 +1166,20 @@ namespace Sass { { List_Ptr arglist = ARG("$numbers", List); Number_Obj least = NULL; - for (size_t i = 0, L = arglist->length(); i < L; ++i) { + for (size_t i = 0, L = arglist->length(); i < L; ++i) + { Expression_Obj val = arglist->value_at_index(i); Number_Obj xi = Cast(val); - if (!xi) { + if (!xi) + { error("\"" + val->to_string(ctx.c_options) + "\" is not a number for `min'", pstate); } - if (least) { + if (least) + { if (*xi < *least) least = xi; - } else least = xi; + } + else + least = xi; } return least.detach(); } @@ -1172,15 +1189,20 @@ namespace Sass { { List_Ptr arglist = ARG("$numbers", List); Number_Obj greatest = NULL; - for (size_t i = 0, L = arglist->length(); i < L; ++i) { + for (size_t i = 0, L = arglist->length(); i < L; ++i) + { Expression_Obj val = arglist->value_at_index(i); Number_Obj xi = Cast(val); - if (!xi) { + if (!xi) + { error("\"" + val->to_string(ctx.c_options) + "\" is not a number for `max'", pstate); } - if (greatest) { + if (greatest) + { if (*greatest < *xi) greatest = xi; - } else greatest = xi; + } + else + greatest = xi; } return greatest.detach(); } @@ -1192,15 +1214,18 @@ namespace Sass { Value_Ptr v = Cast(arg); Number_Ptr l = Cast(arg); Boolean_Ptr b = Cast(arg); - if (l) { + if (l) + { double lv = l->value(); - if (lv < 1) { + if (lv < 1) + { stringstream err; err << "$limit " << lv << " must be greater than or equal to 1 for `random'"; error(err.str(), pstate); } bool eq_int = std::fabs(trunc(lv) - lv) < NUMBER_EPSILON; - if (!eq_int) { + if (!eq_int) + { stringstream err; err << "Expected $limit to be an integer but got " << lv << " for `random'"; error(err.str(), pstate); @@ -1209,13 +1234,18 @@ namespace Sass { uint_fast32_t distributed = static_cast(distributor(rand)); return SASS_MEMORY_NEW(Number, pstate, (double)distributed); } - else if (b) { + else if (b) + { std::uniform_real_distribution<> distributor(0, 1); double distributed = static_cast(distributor(rand)); return SASS_MEMORY_NEW(Number, pstate, distributed); - } else if (v) { + } + else if (v) + { throw Exception::InvalidArgumentType(pstate, "random", "$limit", "number", v); - } else { + } + else + { throw Exception::InvalidArgumentType(pstate, "random", "$limit", "number"); } } @@ -1227,28 +1257,34 @@ namespace Sass { Signature length_sig = "length($list)"; BUILT_IN(length) { - if (Selector_List_Ptr sl = Cast(env["$list"])) { + if (Selector_List_Ptr sl = Cast(env["$list"])) + { return SASS_MEMORY_NEW(Number, pstate, (double)sl->length()); } Expression_Ptr v = ARG("$list", Expression); - if (v->concrete_type() == Expression::MAP) { + if (v->concrete_type() == Expression::MAP) + { Map_Ptr map = Cast(env["$list"]); return SASS_MEMORY_NEW(Number, pstate, (double)(map ? map->length() : 1)); } - if (v->concrete_type() == Expression::SELECTOR) { - if (Compound_Selector_Ptr h = Cast(v)) { + if (v->concrete_type() == Expression::SELECTOR) + { + if (Compound_Selector_Ptr h = Cast(v)) + { return SASS_MEMORY_NEW(Number, pstate, (double)h->length()); - } else if (Selector_List_Ptr ls = Cast(v)) { + } + else if (Selector_List_Ptr ls = Cast(v)) + { return SASS_MEMORY_NEW(Number, pstate, (double)ls->length()); - } else { + } + else + { return SASS_MEMORY_NEW(Number, pstate, 1); } } List_Ptr list = Cast(env["$list"]); - return SASS_MEMORY_NEW(Number, - pstate, - (double)(list ? list->size() : 1)); + return SASS_MEMORY_NEW(Number, pstate, (double)(list ? list->size() : 1)); } Signature nth_sig = "nth($list, $n)"; @@ -1256,20 +1292,25 @@ namespace Sass { { Number_Ptr n = ARG("$n", Number); Map_Ptr m = Cast(env["$list"]); - if (Selector_List_Ptr sl = Cast(env["$list"])) { + if (Selector_List_Ptr sl = Cast(env["$list"])) + { size_t len = m ? m->length() : sl->length(); bool empty = m ? m->empty() : sl->empty(); - if (empty) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate); + if (empty) + error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate); double index = std::floor(n->value() < 0 ? len + n->value() : n->value() - 1); - if (index < 0 || index > len - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate); + if (index < 0 || index > len - 1) + error("index out of bounds for `" + std::string(sig) + "`", pstate); // return (*sl)[static_cast(index)]; Listize listize; return (*sl)[static_cast(index)]->perform(&listize); } List_Obj l = Cast(env["$list"]); - if (n->value() == 0) error("argument `$n` of `" + std::string(sig) + "` must be non-zero", pstate); + if (n->value() == 0) + error("argument `$n` of `" + std::string(sig) + "` must be non-zero", pstate); // if the argument isn't a list, then wrap it in a singleton list - if (!m && !l) { + if (!m && !l) + { l = SASS_MEMORY_NEW(List, pstate, 1); l->append(ARG("$list", Expression)); } @@ -1277,15 +1318,18 @@ namespace Sass { bool empty = m ? m->empty() : l->empty(); if (empty) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate); double index = std::floor(n->value() < 0 ? len + n->value() : n->value() - 1); - if (index < 0 || index > len - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate); + if (index < 0 || index > len - 1) + error("index out of bounds for `" + std::string(sig) + "`", pstate); - if (m) { + if (m) + { l = SASS_MEMORY_NEW(List, pstate, 1); l->append(m->keys()[static_cast(index)]); l->append(m->at(m->keys()[static_cast(index)])); return l.detach(); } - else { + else + { Expression_Obj rv = l->value_at_index(static_cast(index)); rv->set_delayed(false); return rv.detach(); @@ -1299,18 +1343,23 @@ namespace Sass { List_Obj l = Cast(env["$list"]); Number_Obj n = ARG("$n", Number); Expression_Obj v = ARG("$value", Expression); - if (!l) { + if (!l) + { l = SASS_MEMORY_NEW(List, pstate, 1); l->append(ARG("$list", Expression)); } - if (m) { + if (m) + { l = m->to_list(pstate); } - if (l->empty()) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate); + if (l->empty()) + error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate); double index = std::floor(n->value() < 0 ? l->length() + n->value() : n->value() - 1); - if (index < 0 || index > l->length() - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate); + if (index < 0 || index > l->length() - 1) + error("index out of bounds for `" + std::string(sig) + "`", pstate); List_Ptr result = SASS_MEMORY_NEW(List, pstate, l->length(), l->separator(), false, l->is_bracketed()); - for (size_t i = 0, L = l->length(); i < L; ++i) { + for (size_t i = 0, L = l->length(); i < L; ++i) + { result->append(((i == index) ? v : (*l)[i])); } return result; @@ -1322,15 +1371,19 @@ namespace Sass { Map_Obj m = Cast(env["$list"]); List_Obj l = Cast(env["$list"]); Expression_Obj v = ARG("$value", Expression); - if (!l) { + if (!l) + { l = SASS_MEMORY_NEW(List, pstate, 1); l->append(ARG("$list", Expression)); } - if (m) { + if (m) + { l = m->to_list(pstate); } - for (size_t i = 0, L = l->length(); i < L; ++i) { - if (Eval::eq(l->value_at_index(i), v)) return SASS_MEMORY_NEW(Number, pstate, (double)(i+1)); + for (size_t i = 0, L = l->length(); i < L; ++i) + { + if (Eval::eq(l->value_at_index(i), v)) + return SASS_MEMORY_NEW(Number, pstate, (double)(i + 1)); } return SASS_MEMORY_NEW(Null, pstate); } @@ -1346,31 +1399,41 @@ namespace Sass { enum Sass_Separator sep_val = (l1 ? l1->separator() : SASS_SPACE); Value* bracketed = ARG("$bracketed", Value); bool is_bracketed = (l1 ? l1->is_bracketed() : false); - if (!l1) { + if (!l1) + { l1 = SASS_MEMORY_NEW(List, pstate, 1); l1->append(ARG("$list1", Expression)); sep_val = (l2 ? l2->separator() : SASS_SPACE); is_bracketed = (l2 ? l2->is_bracketed() : false); } - if (!l2) { + if (!l2) + { l2 = SASS_MEMORY_NEW(List, pstate, 1); l2->append(ARG("$list2", Expression)); } - if (m1) { + if (m1) + { l1 = m1->to_list(pstate); sep_val = SASS_COMMA; } - if (m2) { + if (m2) + { l2 = m2->to_list(pstate); } size_t len = l1->length() + l2->length(); std::string sep_str = unquote(sep->value()); - if (sep_str == "space") sep_val = SASS_SPACE; - else if (sep_str == "comma") sep_val = SASS_COMMA; - else if (sep_str != "auto") error("argument `$separator` of `" + std::string(sig) + "` must be `space`, `comma`, or `auto`", pstate); + if (sep_str == "space") + sep_val = SASS_SPACE; + else if (sep_str == "comma") + sep_val = SASS_COMMA; + else if (sep_str != "auto") + error("argument `$separator` of `" + std::string(sig) + + "` must be `space`, `comma`, or `auto`", + pstate); String_Constant_Obj bracketed_as_str = Cast(bracketed); bool bracketed_is_auto = bracketed_as_str && unquote(bracketed_as_str->value()) == "auto"; - if (!bracketed_is_auto) { + if (!bracketed_is_auto) + { is_bracketed = !bracketed->is_false(); } List_Obj result = SASS_MEMORY_NEW(List, pstate, len, sep_val, false, is_bracketed); @@ -1385,34 +1448,40 @@ namespace Sass { Map_Obj m = Cast(env["$list"]); List_Obj l = Cast(env["$list"]); Expression_Obj v = ARG("$val", Expression); - if (Selector_List_Ptr sl = Cast(env["$list"])) { + if (Selector_List_Ptr sl = Cast(env["$list"])) + { Listize listize; l = Cast(sl->perform(&listize)); } String_Constant_Obj sep = ARG("$separator", String_Constant); - if (!l) { + if (!l) + { l = SASS_MEMORY_NEW(List, pstate, 1); l->append(ARG("$list", Expression)); } - if (m) { + if (m) + { l = m->to_list(pstate); } List_Ptr result = SASS_MEMORY_COPY(l); std::string sep_str(unquote(sep->value())); - if (sep_str != "auto") { // check default first - if (sep_str == "space") result->separator(SASS_SPACE); - else if (sep_str == "comma") result->separator(SASS_COMMA); - else error("argument `$separator` of `" + std::string(sig) + "` must be `space`, `comma`, or `auto`", pstate); - } - if (l->is_arglist()) { - result->append(SASS_MEMORY_NEW(Argument, - v->pstate(), - v, - "", - false, - false)); - - } else { + if (sep_str != "auto") + { // check default first + if (sep_str == "space") + result->separator(SASS_SPACE); + else if (sep_str == "comma") + result->separator(SASS_COMMA); + else + error("argument `$separator` of `" + std::string(sig) + + "` must be `space`, `comma`, or `auto`", + pstate); + } + if (l->is_arglist()) + { + result->append(SASS_MEMORY_NEW(Argument, v->pstate(), v, "", false, false)); + } + else + { result->append(v); } return result; @@ -1423,20 +1492,28 @@ namespace Sass { { List_Obj arglist = SASS_MEMORY_COPY(ARG("$lists", List)); size_t shortest = 0; - for (size_t i = 0, L = arglist->length(); i < L; ++i) { + for (size_t i = 0, L = arglist->length(); i < L; ++i) + { List_Obj ith = Cast(arglist->value_at_index(i)); Map_Obj mith = Cast(arglist->value_at_index(i)); - if (!ith) { - if (mith) { + if (!ith) + { + if (mith) + { ith = mith->to_list(pstate); - } else { + } + else + { ith = SASS_MEMORY_NEW(List, pstate, 1); ith->append(arglist->value_at_index(i)); } - if (arglist->is_arglist()) { + if (arglist->is_arglist()) + { Argument_Obj arg = (Argument_Ptr)(arglist->at(i).ptr()); // XXX arg->value(ith); - } else { + } + else + { (*arglist)[i] = ith; } } @@ -1444,9 +1521,11 @@ namespace Sass { } List_Ptr zippers = SASS_MEMORY_NEW(List, pstate, shortest, SASS_COMMA); size_t L = arglist->length(); - for (size_t i = 0; i < shortest; ++i) { + for (size_t i = 0; i < shortest; ++i) + { List_Ptr zipper = SASS_MEMORY_NEW(List, pstate, L); - for (size_t j = 0; j < L; ++j) { + for (size_t j = 0; j < L; ++j) + { zipper->append(Cast(arglist->value_at_index(j))->at(i)); } zippers->append(zipper); @@ -1458,13 +1537,13 @@ namespace Sass { BUILT_IN(list_separator) { List_Obj l = Cast(env["$list"]); - if (!l) { + if (!l) + { l = SASS_MEMORY_NEW(List, pstate, 1); l->append(ARG("$list", Expression)); } - return SASS_MEMORY_NEW(String_Quoted, - pstate, - l->separator() == SASS_COMMA ? "comma" : "space"); + return SASS_MEMORY_NEW(String_Quoted, pstate, + l->separator() == SASS_COMMA ? "comma" : "space"); } ///////////////// @@ -1478,15 +1557,21 @@ namespace Sass { // investigate why this is (unexpected) Map_Obj m = ARGM("$map", Map, ctx); Expression_Obj v = ARG("$key", Expression); - try { + try + { Expression_Obj val = m->at(v); if (!val) return SASS_MEMORY_NEW(Null, pstate); val->set_delayed(false); return val.detach(); - } catch (const std::out_of_range&) { + } + catch (const std::out_of_range&) + { return SASS_MEMORY_NEW(Null, pstate); } - catch (...) { throw; } + catch (...) + { + throw; + } } Signature map_has_key_sig = "map-has-key($map, $key)"; @@ -1502,7 +1587,8 @@ namespace Sass { { Map_Obj m = ARGM("$map", Map, ctx); List_Ptr result = SASS_MEMORY_NEW(List, pstate, m->length(), SASS_COMMA); - for ( auto key : m->keys()) { + for (auto key : m->keys()) + { result->append(key); } return result; @@ -1513,7 +1599,8 @@ namespace Sass { { Map_Obj m = ARGM("$map", Map, ctx); List_Ptr result = SASS_MEMORY_NEW(List, pstate, m->length(), SASS_COMMA); - for ( auto key : m->keys()) { + for (auto key : m->keys()) + { result->append(m->at(key)); } return result; @@ -1540,9 +1627,11 @@ namespace Sass { Map_Obj m = ARGM("$map", Map, ctx); List_Obj arglist = ARG("$keys", List); Map_Ptr result = SASS_MEMORY_NEW(Map, pstate, 1); - for (auto key : m->keys()) { + for (auto key : m->keys()) + { remove = false; - for (size_t j = 0, K = arglist->length(); j < K && !remove; ++j) { + for (size_t j = 0, K = arglist->length(); j < K && !remove; ++j) + { remove = Eval::eq(key, arglist->value_at_index(j)); } if (!remove) *result << std::make_pair(key, m->at(key)); @@ -1555,14 +1644,13 @@ namespace Sass { { List_Obj arglist = SASS_MEMORY_COPY(ARG("$args", List)); // copy Map_Obj result = SASS_MEMORY_NEW(Map, pstate, 1); - for (size_t i = arglist->size(), L = arglist->length(); i < L; ++i) { + for (size_t i = arglist->size(), L = arglist->length(); i < L; ++i) + { Expression_Obj obj = arglist->at(i); - Argument_Obj arg = (Argument_Ptr) obj.ptr(); // XXX + Argument_Obj arg = (Argument_Ptr)obj.ptr(); // XXX std::string name = std::string(arg->name()); name = name.erase(0, 1); // sanitize name (remove dollar sign) - *result << std::make_pair(SASS_MEMORY_NEW(String_Quoted, - pstate, name), - arg->value()); + *result << std::make_pair(SASS_MEMORY_NEW(String_Quoted, pstate, name), arg->value()); } return result.detach(); } @@ -1580,18 +1668,23 @@ namespace Sass { Signature unit_sig = "unit($number)"; BUILT_IN(unit) - { return SASS_MEMORY_NEW(String_Quoted, pstate, quote(ARG("$number", Number)->unit(), '"')); } + { + return SASS_MEMORY_NEW(String_Quoted, pstate, quote(ARG("$number", Number)->unit(), '"')); + } Signature unitless_sig = "unitless($number)"; BUILT_IN(unitless) - { return SASS_MEMORY_NEW(Boolean, pstate, ARG("$number", Number)->is_unitless()); } + { + return SASS_MEMORY_NEW(Boolean, pstate, ARG("$number", Number)->is_unitless()); + } Signature comparable_sig = "comparable($number-1, $number-2)"; BUILT_IN(comparable) { Number_Ptr n1 = ARG("$number-1", Number); Number_Ptr n2 = ARG("$number-2", Number); - if (n1->is_unitless() || n2->is_unitless()) { + if (n1->is_unitless() || n2->is_unitless()) + { return SASS_MEMORY_NEW(Boolean, pstate, true); } Number tmp_n2(n2); // copy @@ -1604,10 +1697,12 @@ namespace Sass { { std::string s = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value())); - if(d_env.has("$"+s)) { + if (d_env.has("$" + s)) + { return SASS_MEMORY_NEW(Boolean, pstate, true); } - else { + else + { return SASS_MEMORY_NEW(Boolean, pstate, false); } } @@ -1617,10 +1712,12 @@ namespace Sass { { std::string s = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value())); - if(d_env.has_global("$"+s)) { + if (d_env.has_global("$" + s)) + { return SASS_MEMORY_NEW(Boolean, pstate, true); } - else { + else + { return SASS_MEMORY_NEW(Boolean, pstate, false); } } @@ -1630,10 +1727,12 @@ namespace Sass { { std::string s = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value())); - if(d_env.has_global(s+"[f]")) { + if (d_env.has_global(s + "[f]")) + { return SASS_MEMORY_NEW(Boolean, pstate, true); } - else { + else + { return SASS_MEMORY_NEW(Boolean, pstate, false); } } @@ -1643,10 +1742,12 @@ namespace Sass { { std::string s = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value())); - if(d_env.has_global(s+"[m]")) { + if (d_env.has_global(s + "[m]")) + { return SASS_MEMORY_NEW(Boolean, pstate, true); } - else { + else + { return SASS_MEMORY_NEW(Boolean, pstate, false); } } @@ -1656,10 +1757,12 @@ namespace Sass { { std::string s = unquote(ARG("$name", String_Constant)->value()); - if(features.find(s) == features.end()) { + if (features.find(s) == features.end()) + { return SASS_MEMORY_NEW(Boolean, pstate, false); } - else { + else + { return SASS_MEMORY_NEW(Boolean, pstate, true); } } @@ -1675,23 +1778,24 @@ namespace Sass { // Definition_Ptr def = d_env.has(full_name) ? Cast((d_env)[full_name]) : 0; // Parameters_Ptr params = def ? def->parameters() : 0; // size_t param_size = params ? params->length() : 0; - for (size_t i = 0, L = arglist->length(); i < L; ++i) { + for (size_t i = 0, L = arglist->length(); i < L; ++i) + { Expression_Obj expr = arglist->value_at_index(i); // if (params && params->has_rest_parameter()) { // Parameter_Obj p = param_size > i ? (*params)[i] : 0; // List_Ptr list = Cast(expr); // if (list && p && !p->is_rest_parameter()) expr = (*list)[0]; // } - if (arglist->is_arglist()) { + if (arglist->is_arglist()) + { Expression_Obj obj = arglist->at(i); - Argument_Obj arg = (Argument_Ptr) obj.ptr(); // XXX - args->append(SASS_MEMORY_NEW(Argument, - pstate, - expr, - arg ? arg->name() : "", + Argument_Obj arg = (Argument_Ptr)obj.ptr(); // XXX + args->append(SASS_MEMORY_NEW(Argument, pstate, expr, arg ? arg->name() : "", arg ? arg->is_rest_argument() : false, arg ? arg->is_keyword_argument() : false)); - } else { + } + else + { args->append(SASS_MEMORY_NEW(Argument, pstate, expr)); } } @@ -1699,7 +1803,6 @@ namespace Sass { Expand expand(ctx, &d_env, backtrace, &selector_stack); func->via_call(true); // calc invoke is allowed return func->perform(&expand.eval); - } //////////////////// @@ -1714,7 +1817,8 @@ namespace Sass { Signature if_sig = "if($condition, $if-true, $if-false)"; // BUILT_IN(sass_if) - // { return ARG("$condition", Expression)->is_false() ? ARG("$if-false", Expression) : ARG("$if-true", Expression); } + // { return ARG("$condition", Expression)->is_false() ? ARG("$if-false", Expression) : + // ARG("$if-true", Expression); } BUILT_IN(sass_if) { Expand expand(ctx, &d_env, backtrace, &selector_stack); @@ -1737,13 +1841,20 @@ namespace Sass { BUILT_IN(inspect) { Expression_Ptr v = ARG("$value", Expression); - if (v->concrete_type() == Expression::NULL_VAL) { + if (v->concrete_type() == Expression::NULL_VAL) + { return SASS_MEMORY_NEW(String_Quoted, pstate, "null"); - } else if (v->concrete_type() == Expression::BOOLEAN && v->is_false()) { + } + else if (v->concrete_type() == Expression::BOOLEAN && v->is_false()) + { return SASS_MEMORY_NEW(String_Quoted, pstate, "false"); - } else if (v->concrete_type() == Expression::STRING) { + } + else if (v->concrete_type() == Expression::STRING) + { return v; - } else { + } + else + { // ToDo: fix to_sass for nested parentheses Sass_Output_Style old_style; old_style = ctx.c_options.output_style; @@ -1763,20 +1874,23 @@ namespace Sass { List_Ptr arglist = ARG("$selectors", List); // Not enough parameters - if( arglist->length() == 0 ) + if (arglist->length() == 0) error("$selectors: At least one selector must be passed for `selector-nest'", pstate); // Parse args into vector of selectors std::vector parsedSelectors; - for (size_t i = 0, L = arglist->length(); i < L; ++i) { + for (size_t i = 0, L = arglist->length(); i < L; ++i) + { Expression_Obj exp = Cast(arglist->value_at_index(i)); - if (exp->concrete_type() == Expression::NULL_VAL) { + if (exp->concrete_type() == Expression::NULL_VAL) + { std::stringstream msg; msg << "$selectors: null is not a valid selector: it must be a string,\n"; msg << "a list of strings, or a list of lists of strings for 'selector-nest'"; error(msg.str(), pstate); } - if (String_Constant_Obj str = Cast(exp)) { + if (String_Constant_Obj str = Cast(exp)) + { str->quote_mark(0); } std::string exp_src = exp->to_string(ctx.c_options); @@ -1785,22 +1899,26 @@ namespace Sass { } // Nothing to do - if( parsedSelectors.empty() ) { + if (parsedSelectors.empty()) + { return SASS_MEMORY_NEW(Null, pstate); } - // Set the first element as the `result`, keep appending to as we go down the parsedSelector vector. + // Set the first element as the `result`, keep appending to as we go down the parsedSelector + // vector. std::vector::iterator itr = parsedSelectors.begin(); Selector_List_Obj result = *itr; ++itr; - for(;itr != parsedSelectors.end(); ++itr) { + for (; itr != parsedSelectors.end(); ++itr) + { Selector_List_Obj child = *itr; std::vector exploded; selector_stack.push_back(result); Selector_List_Obj rv = child->resolve_parent_refs(selector_stack); selector_stack.pop_back(); - for (size_t m = 0, mLen = rv->length(); m < mLen; ++m) { + for (size_t m = 0, mLen = rv->length(); m < mLen; ++m) + { exploded.push_back((*rv)[m]); } result->elements(exploded); @@ -1816,20 +1934,23 @@ namespace Sass { List_Ptr arglist = ARG("$selectors", List); // Not enough parameters - if( arglist->length() == 0 ) + if (arglist->length() == 0) error("$selectors: At least one selector must be passed for `selector-append'", pstate); // Parse args into vector of selectors std::vector parsedSelectors; - for (size_t i = 0, L = arglist->length(); i < L; ++i) { + for (size_t i = 0, L = arglist->length(); i < L; ++i) + { Expression_Obj exp = Cast(arglist->value_at_index(i)); - if (exp->concrete_type() == Expression::NULL_VAL) { + if (exp->concrete_type() == Expression::NULL_VAL) + { std::stringstream msg; msg << "$selectors: null is not a valid selector: it must be a string,\n"; msg << "a list of strings, or a list of lists of strings for 'selector-append'"; error(msg.str(), pstate); } - if (String_Constant_Ptr str = Cast(exp)) { + if (String_Constant_Ptr str = Cast(exp)) + { str->quote_mark(0); } std::string exp_src = exp->to_string(); @@ -1838,34 +1959,40 @@ namespace Sass { } // Nothing to do - if( parsedSelectors.empty() ) { + if (parsedSelectors.empty()) + { return SASS_MEMORY_NEW(Null, pstate); } - // Set the first element as the `result`, keep appending to as we go down the parsedSelector vector. + // Set the first element as the `result`, keep appending to as we go down the parsedSelector + // vector. std::vector::iterator itr = parsedSelectors.begin(); Selector_List_Obj result = *itr; ++itr; - for(;itr != parsedSelectors.end(); ++itr) { + for (; itr != parsedSelectors.end(); ++itr) + { Selector_List_Obj child = *itr; std::vector newElements; // For every COMPLEX_SELECTOR in `result` // For every COMPLEX_SELECTOR in `child` - // let parentSeqClone equal a copy of result->elements[i] - // let childSeq equal child->elements[j] - // Append all of childSeq head elements into parentSeqClone - // Set the innermost tail of parentSeqClone, to childSeq's tail + // let parentSeqClone equal a copy of result->elements[i] + // let childSeq equal child->elements[j] + // Append all of childSeq head elements into parentSeqClone + // Set the innermost tail of parentSeqClone, to childSeq's tail // Replace result->elements with newElements - for (size_t i = 0, resultLen = result->length(); i < resultLen; ++i) { - for (size_t j = 0, childLen = child->length(); j < childLen; ++j) { + for (size_t i = 0, resultLen = result->length(); i < resultLen; ++i) + { + for (size_t j = 0, childLen = child->length(); j < childLen; ++j) + { Complex_Selector_Obj parentSeqClone = SASS_MEMORY_CLONE((*result)[i]); Complex_Selector_Obj childSeq = (*child)[j]; Complex_Selector_Obj base = childSeq->tail(); // Must be a simple sequence - if( childSeq->combinator() != Complex_Selector::Combinator::ANCESTOR_OF ) { + if (childSeq->combinator() != Complex_Selector::Combinator::ANCESTOR_OF) + { std::string msg("Can't append \""); msg += childSeq->to_string(); msg += "\" to \""; @@ -1876,7 +2003,8 @@ namespace Sass { // Cannot be a Universal selector Element_Selector_Obj pType = Cast(childSeq->head()->first()); - if(pType && pType->name() == "*") { + if (pType && pType->name() == "*") + { std::string msg("Can't append \""); msg += childSeq->to_string(); msg += "\" to \""; @@ -1891,7 +2019,7 @@ namespace Sass { parentSeqClone->innermost()->head()->concat(base->head()); // Set parentSeqClone new tail - parentSeqClone->innermost()->tail( base->tail() ); + parentSeqClone->innermost()->tail(base->tail()); newElements.push_back(parentSeqClone); } @@ -1922,9 +2050,10 @@ namespace Sass { List_Ptr l = SASS_MEMORY_NEW(List, sel->pstate(), sel->length(), SASS_COMMA); - for (size_t i = 0, L = sel->length(); i < L; ++i) { + for (size_t i = 0, L = sel->length(); i < L; ++i) + { Simple_Selector_Obj ss = (*sel)[i]; - std::string ss_string = ss->to_string() ; + std::string ss_string = ss->to_string(); l->append(SASS_MEMORY_NEW(String_Quoted, ss->pstate(), ss_string)); } @@ -1935,9 +2064,9 @@ namespace Sass { Signature selector_extend_sig = "selector-extend($selector, $extendee, $extender)"; BUILT_IN(selector_extend) { - Selector_List_Obj selector = ARGSEL("$selector", Selector_List_Obj, p_contextualize); - Selector_List_Obj extendee = ARGSEL("$extendee", Selector_List_Obj, p_contextualize); - Selector_List_Obj extender = ARGSEL("$extender", Selector_List_Obj, p_contextualize); + Selector_List_Obj selector = ARGSEL("$selector", Selector_List_Obj, p_contextualize); + Selector_List_Obj extendee = ARGSEL("$extendee", Selector_List_Obj, p_contextualize); + Selector_List_Obj extender = ARGSEL("$extender", Selector_List_Obj, p_contextualize); Subset_Map subset_map; extender->populate_extends(extendee, subset_map); @@ -1977,8 +2106,8 @@ namespace Sass { Signature is_superselector_sig = "is-superselector($super, $sub)"; BUILT_IN(is_superselector) { - Selector_List_Obj sel_sup = ARGSEL("$super", Selector_List_Obj, p_contextualize); - Selector_List_Obj sel_sub = ARGSEL("$sub", Selector_List_Obj, p_contextualize); + Selector_List_Obj sel_sup = ARGSEL("$super", Selector_List_Obj, p_contextualize); + Selector_List_Obj sel_sub = ARGSEL("$sub", Selector_List_Obj, p_contextualize); bool result = sel_sup->is_superselector_of(sel_sub); return SASS_MEMORY_NEW(Boolean, pstate, result); } diff --git a/src/functions.hpp b/src/functions.hpp index f2cc0af506..2a8799557a 100644 --- a/src/functions.hpp +++ b/src/functions.hpp @@ -7,10 +7,12 @@ #include "ast_fwd_decl.hpp" #include "sass/functions.h" -#define BUILT_IN(name) Expression_Ptr \ -name(Env& env, Env& d_env, Context& ctx, Signature sig, ParserState pstate, Backtrace* backtrace, std::vector selector_stack) +#define BUILT_IN(name) \ + Expression_Ptr name(Env& env, Env& d_env, Context& ctx, Signature sig, ParserState pstate, \ + Backtrace* backtrace, std::vector selector_stack) -namespace Sass { +namespace Sass +{ struct Backtrace; typedef const char* Signature; typedef Expression_Ptr (*Native_Function)(Env&, Env&, Context&, Signature, ParserState, Backtrace*, std::vector); @@ -20,7 +22,8 @@ namespace Sass { std::string function_name(Signature); - namespace Functions { + namespace Functions + { extern Signature rgb_sig; extern Signature rgba_4_sig; diff --git a/src/inspect.cpp b/src/inspect.cpp index ca91f7fe68..05c344da42 100644 --- a/src/inspect.cpp +++ b/src/inspect.cpp @@ -13,38 +13,45 @@ #include "color_maps.hpp" #include "utf8/checked.h" -namespace Sass { +namespace Sass +{ - Inspect::Inspect(const Emitter& emi) - : Emitter(emi) - { } - Inspect::~Inspect() { } + Inspect::Inspect(const Emitter& emi) : Emitter(emi) + { + } + Inspect::~Inspect() + { + } // statements void Inspect::operator()(Block_Ptr block) { - if (!block->is_root()) { + if (!block->is_root()) + { add_open_mapping(block); append_scope_opener(); } if (output_style() == NESTED) indentation += block->tabs(); - for (size_t i = 0, L = block->length(); i < L; ++i) { + for (size_t i = 0, L = block->length(); i < L; ++i) + { (*block)[i]->perform(this); } if (output_style() == NESTED) indentation -= block->tabs(); - if (!block->is_root()) { + if (!block->is_root()) + { append_scope_closer(); add_close_mapping(block); } - } void Inspect::operator()(Ruleset_Ptr ruleset) { - if (ruleset->selector()) { + if (ruleset->selector()) + { ruleset->selector()->perform(this); } - if (ruleset->block()) { + if (ruleset->block()) + { ruleset->block()->perform(this); } } @@ -89,7 +96,7 @@ namespace Sass { append_indentation(); append_token("@at-root ", at_root_block); append_mandatory_space(); - if(at_root_block->expression()) at_root_block->expression()->perform(this); + if (at_root_block->expression()) at_root_block->expression()->perform(this); at_root_block->block()->perform(this); } @@ -97,21 +104,25 @@ namespace Sass { { append_indentation(); append_token(at_rule->keyword(), at_rule); - if (at_rule->selector()) { + if (at_rule->selector()) + { append_mandatory_space(); bool was_wrapped = in_wrapped; in_wrapped = true; at_rule->selector()->perform(this); in_wrapped = was_wrapped; } - if (at_rule->value()) { + if (at_rule->value()) + { append_mandatory_space(); at_rule->value()->perform(this); } - if (at_rule->block()) { + if (at_rule->block()) + { at_rule->block()->perform(this); } - else { + else + { append_delimiter(); } } @@ -121,28 +132,29 @@ namespace Sass { if (dec->value()->concrete_type() == Expression::NULL_VAL) return; bool was_decl = in_declaration; in_declaration = true; - if (output_style() == NESTED) - indentation += dec->tabs(); + if (output_style() == NESTED) indentation += dec->tabs(); append_indentation(); - if (dec->property()) - dec->property()->perform(this); + if (dec->property()) dec->property()->perform(this); append_colon_separator(); - if (dec->value()->concrete_type() == Expression::SELECTOR) { + if (dec->value()->concrete_type() == Expression::SELECTOR) + { Listize listize; Expression_Obj ls = dec->value()->perform(&listize); ls->perform(this); - } else { + } + else + { dec->value()->perform(this); } - if (dec->is_important()) { + if (dec->is_important()) + { append_optional_space(); append_string("!important"); } append_delimiter(); - if (output_style() == NESTED) - indentation -= dec->tabs(); + if (output_style() == NESTED) indentation -= dec->tabs(); in_declaration = was_decl; } @@ -151,7 +163,8 @@ namespace Sass { append_token(assn->variable(), assn); append_colon_separator(); assn->value()->perform(this); - if (assn->is_default()) { + if (assn->is_default()) + { append_optional_space(); append_string("!default"); } @@ -160,26 +173,32 @@ namespace Sass { void Inspect::operator()(Import_Ptr import) { - if (!import->urls().empty()) { + if (!import->urls().empty()) + { append_token("@import", import); append_mandatory_space(); import->urls().front()->perform(this); - if (import->urls().size() == 1) { - if (import->import_queries()) { + if (import->urls().size() == 1) + { + if (import->import_queries()) + { append_mandatory_space(); import->import_queries()->perform(this); } } append_delimiter(); - for (size_t i = 1, S = import->urls().size(); i < S; ++i) { + for (size_t i = 1, S = import->urls().size(); i < S; ++i) + { append_mandatory_linefeed(); append_token("@import", import); append_mandatory_space(); import->urls()[i]->perform(this); - if (import->urls().size() - 1 == i) { - if (import->import_queries()) { + if (import->urls().size() - 1 == i) + { + if (import->import_queries()) + { append_mandatory_space(); import->import_queries()->perform(this); } @@ -239,7 +258,8 @@ namespace Sass { append_mandatory_space(); cond->predicate()->perform(this); cond->block()->perform(this); - if (cond->alternative()) { + if (cond->alternative()) + { append_optional_linefeed(); append_indentation(); append_string("else"); @@ -266,7 +286,8 @@ namespace Sass { append_token("@each", loop); append_mandatory_space(); append_string(loop->variables()[0]); - for (size_t i = 1, L = loop->variables().size(); i < L; ++i) { + for (size_t i = 1, L = loop->variables().size(); i < L; ++i) + { append_comma_separator(); append_string(loop->variables()[i]); } @@ -305,10 +326,13 @@ namespace Sass { void Inspect::operator()(Definition_Ptr def) { append_indentation(); - if (def->type() == Definition::MIXIN) { + if (def->type() == Definition::MIXIN) + { append_token("@mixin", def); append_mandatory_space(); - } else { + } + else + { append_token("@function", def); append_mandatory_space(); } @@ -323,10 +347,12 @@ namespace Sass { append_token("@include", call); append_mandatory_space(); append_string(call->name()); - if (call->arguments()) { + if (call->arguments()) + { call->arguments()->perform(this); } - if (call->block()) { + if (call->block()) + { append_optional_space(); call->block()->perform(this); } @@ -342,7 +368,8 @@ namespace Sass { void Inspect::operator()(Map_Ptr map) { - if (output_style() == TO_SASS && map->empty()) { + if (output_style() == TO_SASS && map->empty()) + { append_string("()"); return; } @@ -350,7 +377,8 @@ namespace Sass { if (map->is_invisible()) return; bool items_output = false; append_string("("); - for (auto key : map->keys()) { + for (auto key : map->keys()) + { if (items_output) append_comma_separator(); key->perform(this); append_colon_separator(); @@ -362,69 +390,79 @@ namespace Sass { append_string(")"); } - std::string Inspect::lbracket(List_Ptr list) { + std::string Inspect::lbracket(List_Ptr list) + { return list->is_bracketed() ? "[" : "("; } - std::string Inspect::rbracket(List_Ptr list) { + std::string Inspect::rbracket(List_Ptr list) + { return list->is_bracketed() ? "]" : ")"; } void Inspect::operator()(List_Ptr list) { - if (list->empty() && (output_style() == TO_SASS || list->is_bracketed())) { + if (list->empty() && (output_style() == TO_SASS || list->is_bracketed())) + { append_string(lbracket(list)); append_string(rbracket(list)); return; } std::string sep(list->separator() == SASS_SPACE ? " " : ","); - if ((output_style() != COMPRESSED) && sep == ",") sep += " "; - else if (in_media_block && sep != " ") sep += " "; // verified + if ((output_style() != COMPRESSED) && sep == ",") + sep += " "; + else if (in_media_block && sep != " ") + sep += " "; // verified if (list->empty()) return; bool items_output = false; bool was_space_array = in_space_array; bool was_comma_array = in_comma_array; // if the list is bracketed, always include the left bracket - if (list->is_bracketed()) { + if (list->is_bracketed()) + { append_string(lbracket(list)); } // probably ruby sass eqivalent of element_needs_parens - else if (output_style() == TO_SASS && - list->length() == 1 && - !list->from_selector() && - !Cast(list->at(0)) && - !Cast(list->at(0)) - ) { + else if (output_style() == TO_SASS && list->length() == 1 && !list->from_selector() && + !Cast(list->at(0)) && !Cast(list->at(0))) + { append_string(lbracket(list)); } - else if (!in_declaration && (list->separator() == SASS_HASH || - (list->separator() == SASS_SPACE && in_space_array) || - (list->separator() == SASS_COMMA && in_comma_array) - )) { + else if (!in_declaration && (list->separator() == SASS_HASH || (list->separator() == SASS_SPACE && in_space_array) || + (list->separator() == SASS_COMMA && in_comma_array))) + { append_string(lbracket(list)); } - if (list->separator() == SASS_SPACE) in_space_array = true; - else if (list->separator() == SASS_COMMA) in_comma_array = true; + if (list->separator() == SASS_SPACE) + in_space_array = true; + else if (list->separator() == SASS_COMMA) + in_comma_array = true; - for (size_t i = 0, L = list->size(); i < L; ++i) { + for (size_t i = 0, L = list->size(); i < L; ++i) + { if (list->separator() == SASS_HASH) - { sep[0] = i % 2 ? ':' : ','; } + { + sep[0] = i % 2 ? ':' : ','; + } Expression_Obj list_item = list->at(i); - if (output_style() != TO_SASS) { - if (list_item->is_invisible()) { + if (output_style() != TO_SASS) + { + if (list_item->is_invisible()) + { // this fixes an issue with "" in a list - if (!Cast(list_item)) { + if (!Cast(list_item)) + { continue; } } } - if (items_output) { + if (items_output) + { append_string(sep); } - if (items_output && sep != " ") - append_optional_space(); + if (items_output && sep != " ") append_optional_space(); list_item->perform(this); items_output = true; } @@ -433,72 +471,94 @@ namespace Sass { in_space_array = was_space_array; // if the list is bracketed, always include the right bracket - if (list->is_bracketed()) { - if (list->separator() == SASS_COMMA && list->size() == 1) { + if (list->is_bracketed()) + { + if (list->separator() == SASS_COMMA && list->size() == 1) + { append_string(","); } append_string(rbracket(list)); } // probably ruby sass eqivalent of element_needs_parens - else if (output_style() == TO_SASS && - list->length() == 1 && - !list->from_selector() && - !Cast(list->at(0)) && - !Cast(list->at(0)) - ) { + else if (output_style() == TO_SASS && list->length() == 1 && !list->from_selector() && + !Cast(list->at(0)) && !Cast(list->at(0))) + { append_string(","); append_string(rbracket(list)); } - else if (!in_declaration && (list->separator() == SASS_HASH || - (list->separator() == SASS_SPACE && in_space_array) || - (list->separator() == SASS_COMMA && in_comma_array) - )) { + else if (!in_declaration && (list->separator() == SASS_HASH || (list->separator() == SASS_SPACE && in_space_array) || + (list->separator() == SASS_COMMA && in_comma_array))) + { append_string(rbracket(list)); } - } void Inspect::operator()(Binary_Expression_Ptr expr) { expr->left()->perform(this); - if ( in_media_block || - (output_style() == INSPECT) || ( - expr->op().ws_before - && (!expr->is_interpolant()) - && (expr->is_left_interpolant() || - expr->is_right_interpolant()) - - )) append_string(" "); - switch (expr->optype()) { - case Sass_OP::AND: append_string("&&"); break; - case Sass_OP::OR: append_string("||"); break; - case Sass_OP::EQ: append_string("=="); break; - case Sass_OP::NEQ: append_string("!="); break; - case Sass_OP::GT: append_string(">"); break; - case Sass_OP::GTE: append_string(">="); break; - case Sass_OP::LT: append_string("<"); break; - case Sass_OP::LTE: append_string("<="); break; - case Sass_OP::ADD: append_string("+"); break; - case Sass_OP::SUB: append_string("-"); break; - case Sass_OP::MUL: append_string("*"); break; - case Sass_OP::DIV: append_string("/"); break; - case Sass_OP::MOD: append_string("%"); break; - default: break; // shouldn't get here - } - if ( in_media_block || - (output_style() == INSPECT) || ( - expr->op().ws_after - && (!expr->is_interpolant()) - && (expr->is_left_interpolant() || - expr->is_right_interpolant()) - )) append_string(" "); + if (in_media_block || (output_style() == INSPECT) || + (expr->op().ws_before && (!expr->is_interpolant()) && + (expr->is_left_interpolant() || expr->is_right_interpolant()) + + )) + append_string(" "); + switch (expr->optype()) + { + case Sass_OP::AND: + append_string("&&"); + break; + case Sass_OP::OR: + append_string("||"); + break; + case Sass_OP::EQ: + append_string("=="); + break; + case Sass_OP::NEQ: + append_string("!="); + break; + case Sass_OP::GT: + append_string(">"); + break; + case Sass_OP::GTE: + append_string(">="); + break; + case Sass_OP::LT: + append_string("<"); + break; + case Sass_OP::LTE: + append_string("<="); + break; + case Sass_OP::ADD: + append_string("+"); + break; + case Sass_OP::SUB: + append_string("-"); + break; + case Sass_OP::MUL: + append_string("*"); + break; + case Sass_OP::DIV: + append_string("/"); + break; + case Sass_OP::MOD: + append_string("%"); + break; + default: + break; // shouldn't get here + } + if (in_media_block || (output_style() == INSPECT) || + (expr->op().ws_after && (!expr->is_interpolant()) && + (expr->is_left_interpolant() || expr->is_right_interpolant()))) + append_string(" "); expr->right()->perform(this); } void Inspect::operator()(Unary_Expression_Ptr expr) { - if (expr->optype() == Unary_Expression::PLUS) append_string("+"); - else append_string("-"); + if (expr->optype() == Unary_Expression::PLUS) + append_string("+"); + else + append_string("-"); expr->operand()->perform(this); } @@ -538,8 +598,10 @@ namespace Sass { ss << n->value(); // check if we got scientific notation in result - if (ss.str().find_first_of("e") != std::string::npos) { - ss.clear(); ss.str(std::string()); + if (ss.str().find_first_of("e") != std::string::npos) + { + ss.clear(); + ss.str(std::string()); ss.precision(std::max(12, opt.precision)); ss << std::fixed << n->value(); } @@ -547,11 +609,11 @@ namespace Sass { std::string tmp = ss.str(); size_t pos_point = tmp.find_first_of(".,"); size_t pos_fract = tmp.find_last_not_of("0"); - bool is_int = pos_point == pos_fract || - pos_point == std::string::npos; + bool is_int = pos_point == pos_fract || pos_point == std::string::npos; // reset stream for another run - ss.clear(); ss.str(std::string()); + ss.clear(); + ss.str(std::string()); // take a shortcut for integers if (is_int) @@ -565,36 +627,47 @@ namespace Sass { { // do we have have too much precision? if (pos_fract < opt.precision + pos_point) - { ss.precision((int)(pos_fract - pos_point)); } - else { ss.precision(opt.precision); } + { + ss.precision((int)(pos_fract - pos_point)); + } + else + { + ss.precision(opt.precision); + } // round value again ss << std::fixed << n->value(); res = std::string(ss.str()); // maybe we truncated up to decimal point size_t pos = res.find_last_not_of("0"); // handle case where we have a "0" - if (pos == std::string::npos) { + if (pos == std::string::npos) + { res = "0.0"; - } else { - bool at_dec_point = res[pos] == '.' || - res[pos] == ','; + } + else + { + bool at_dec_point = res[pos] == '.' || res[pos] == ','; // don't leave a blank point - if (at_dec_point) ++ pos; - res.resize (pos + 1); + if (at_dec_point) ++pos; + res.resize(pos + 1); } } // some final cosmetics - if (res == "0.0") res = "0"; - else if (res == "") res = "0"; - else if (res == "-0") res = "0"; - else if (res == "-0.0") res = "0"; + if (res == "0.0") + res = "0"; + else if (res == "") + res = "0"; + else if (res == "-0") + res = "0"; + else if (res == "-0.0") + res = "0"; else if (opt.output_style == COMPRESSED) { // check if handling negative nr size_t off = res[0] == '-' ? 1 : 0; // remove leading zero from floating point in compressed mode - if (n->zero() && res[off] == '0' && res[off+1] == '.') res.erase(off, 1); + if (n->zero() && res[off] == '0' && res[off + 1] == '.') res.erase(off, 1); } // add unit now @@ -605,11 +678,14 @@ namespace Sass { } // helper function for serializing colors - template - static double cap_channel(double c) { - if (c > range) return range; - else if (c < 0) return 0; - else return c; + template static double cap_channel(double c) + { + if (c > range) + return range; + else if (c < 0) + return 0; + else + return c; } void Inspect::operator()(Color_Ptr c) @@ -627,63 +703,77 @@ namespace Sass { double r = Sass::round(cap_channel<0xff>(c->r()), opt.precision); double g = Sass::round(cap_channel<0xff>(c->g()), opt.precision); double b = Sass::round(cap_channel<0xff>(c->b()), opt.precision); - double a = cap_channel<1> (c->a()); + double a = cap_channel<1>(c->a()); // get color from given name (if one was given at all) - if (name != "" && name_to_color(name)) { + if (name != "" && name_to_color(name)) + { Color_Ptr_Const n = name_to_color(name); r = Sass::round(cap_channel<0xff>(n->r()), opt.precision); g = Sass::round(cap_channel<0xff>(n->g()), opt.precision); b = Sass::round(cap_channel<0xff>(n->b()), opt.precision); - a = cap_channel<1> (n->a()); + a = cap_channel<1>(n->a()); } // otherwise get the possible resolved color name - else { + else + { double numval = r * 0x10000 + g * 0x100 + b; - if (color_to_name(numval)) - res_name = color_to_name(numval); + if (color_to_name(numval)) res_name = color_to_name(numval); } std::stringstream hexlet; bool compressed = opt.output_style == COMPRESSED; hexlet << '#' << std::setw(1) << std::setfill('0'); // create a short color hexlet if there is any need for it - if (compressed && is_color_doublet(r, g, b) && a == 1) { + if (compressed && is_color_doublet(r, g, b) && a == 1) + { hexlet << std::hex << std::setw(1) << (static_cast(r) >> 4); hexlet << std::hex << std::setw(1) << (static_cast(g) >> 4); hexlet << std::hex << std::setw(1) << (static_cast(b) >> 4); - } else { + } + else + { hexlet << std::hex << std::setw(2) << static_cast(r); hexlet << std::hex << std::setw(2) << static_cast(g); hexlet << std::hex << std::setw(2) << static_cast(b); } if (compressed && !c->is_delayed()) name = ""; - if (opt.output_style == INSPECT && a >= 1) { + if (opt.output_style == INSPECT && a >= 1) + { append_token(hexlet.str(), c); return; } // retain the originally specified color definition if unchanged - if (name != "") { + if (name != "") + { ss << name; } - else if (r == 0 && g == 0 && b == 0 && a == 0) { - ss << "transparent"; + else if (r == 0 && g == 0 && b == 0 && a == 0) + { + ss << "transparent"; } - else if (a >= 1) { - if (res_name != "") { - if (compressed && hexlet.str().size() < res_name.size()) { + else if (a >= 1) + { + if (res_name != "") + { + if (compressed && hexlet.str().size() < res_name.size()) + { ss << hexlet.str(); - } else { + } + else + { ss << res_name; } } - else { + else + { ss << hexlet.str(); } } - else { + else + { ss << "rgba("; ss << static_cast(r) << ","; if (!compressed) ss << " "; @@ -695,7 +785,6 @@ namespace Sass { } append_token(ss.str(), c); - } void Inspect::operator()(Boolean_Ptr b) @@ -708,7 +797,8 @@ namespace Sass { { // Evaluation should turn these into String_Constants, // so this method is only for inspection purposes. - for (size_t i = 0, L = ss->length(); i < L; ++i) { + for (size_t i = 0, L = ss->length(); i < L; ++i) + { if ((*ss)[i]->is_interpolant()) append_string("#{"); (*ss)[i]->perform(this); if ((*ss)[i]->is_interpolant()) append_string("}"); @@ -722,9 +812,12 @@ namespace Sass { void Inspect::operator()(String_Quoted_Ptr s) { - if (const char q = s->quote_mark()) { + if (const char q = s->quote_mark()) + { append_token(quote(s->value(), q), s); - } else { + } + else + { append_token(s->value(), s); } } @@ -746,11 +839,14 @@ namespace Sass { so->left()->perform(this); if (so->needs_parens(so->left())) append_string(")"); - if (so->operand() == Supports_Operator::AND) { + if (so->operand() == Supports_Operator::AND) + { append_mandatory_space(); append_token("and", so); append_mandatory_space(); - } else if (so->operand() == Supports_Operator::OR) { + } + else if (so->operand() == Supports_Operator::OR) + { append_mandatory_space(); append_token("or", so); append_mandatory_space(); @@ -787,15 +883,20 @@ namespace Sass { void Inspect::operator()(Media_Query_Ptr mq) { size_t i = 0; - if (mq->media_type()) { - if (mq->is_negated()) append_string("not "); - else if (mq->is_restricted()) append_string("only "); + if (mq->media_type()) + { + if (mq->is_negated()) + append_string("not "); + else if (mq->is_restricted()) + append_string("only "); mq->media_type()->perform(this); } - else { + else + { (*mq)[i++]->perform(this); } - for (size_t L = mq->length(); i < L; ++i) { + for (size_t L = mq->length(); i < L; ++i) + { append_string(" and "); (*mq)[i]->perform(this); } @@ -803,13 +904,16 @@ namespace Sass { void Inspect::operator()(Media_Query_Expression_Ptr mqe) { - if (mqe->is_interpolated()) { + if (mqe->is_interpolated()) + { mqe->feature()->perform(this); } - else { + else + { append_string("("); mqe->feature()->perform(this); - if (mqe->value()) { + if (mqe->value()) + { append_string(": "); // verified mqe->value()->perform(this); } @@ -821,7 +925,8 @@ namespace Sass { { append_string("("); ae->feature()->perform(this); - if (ae->value()) { + if (ae->value()) + { append_colon_separator(); ae->value()->perform(this); } @@ -838,11 +943,13 @@ namespace Sass { void Inspect::operator()(Parameter_Ptr p) { append_token(p->name(), p); - if (p->default_value()) { + if (p->default_value()) + { append_colon_separator(); p->default_value()->perform(this); } - else if (p->is_rest_parameter()) { + else if (p->is_rest_parameter()) + { append_string("..."); } } @@ -850,9 +957,11 @@ namespace Sass { void Inspect::operator()(Parameters_Ptr p) { append_string("("); - if (!p->empty()) { + if (!p->empty()) + { (*p)[0]->perform(this); - for (size_t i = 1, L = p->length(); i < L; ++i) { + for (size_t i = 1, L = p->length(); i < L; ++i) + { append_comma_separator(); (*p)[i]->perform(this); } @@ -862,22 +971,28 @@ namespace Sass { void Inspect::operator()(Argument_Ptr a) { - if (!a->name().empty()) { + if (!a->name().empty()) + { append_token(a->name(), a); append_colon_separator(); } if (!a->value()) return; // Special case: argument nulls can be ignored - if (a->value()->concrete_type() == Expression::NULL_VAL) { + if (a->value()->concrete_type() == Expression::NULL_VAL) + { return; } - if (a->value()->concrete_type() == Expression::STRING) { + if (a->value()->concrete_type() == Expression::STRING) + { String_Constant_Ptr s = Cast(a->value()); if (s) s->perform(this); - } else { + } + else + { a->value()->perform(this); } - if (a->is_rest_argument()) { + if (a->is_rest_argument()) + { append_string("..."); } } @@ -885,9 +1000,11 @@ namespace Sass { void Inspect::operator()(Arguments_Ptr a) { append_string("("); - if (!a->empty()) { + if (!a->empty()) + { (*a)[0]->perform(this); - for (size_t i = 1, L = a->length(); i < L; ++i) { + for (size_t i = 1, L = a->length(); i < L; ++i) + { append_string(", "); // verified // Sass Bug? append_comma_separator(); (*a)[i]->perform(this); @@ -911,7 +1028,6 @@ namespace Sass { append_token(s->name(), s); if (s->has_line_break()) append_optional_linefeed(); if (s->has_line_break()) append_indentation(); - } void Inspect::operator()(Element_Selector_Ptr s) @@ -938,9 +1054,11 @@ namespace Sass { append_string("["); add_open_mapping(s); append_token(s->ns_name(), s); - if (!s->matcher().empty()) { + if (!s->matcher().empty()) + { append_string(s->matcher()); - if (s->value() && *s->value()) { + if (s->value() && *s->value()) + { s->value()->perform(this); } } @@ -951,7 +1069,8 @@ namespace Sass { void Inspect::operator()(Pseudo_Selector_Ptr s) { append_token(s->ns_name(), s); - if (s->expression()) { + if (s->expression()) + { append_string("("); s->expression()->perform(this); append_string(")"); @@ -974,11 +1093,14 @@ namespace Sass { void Inspect::operator()(Compound_Selector_Ptr s) { - for (size_t i = 0, L = s->length(); i < L; ++i) { + for (size_t i = 0, L = s->length(); i < L; ++i) + { (*s)[i]->perform(this); } - if (s->has_line_break()) { - if (output_style() != COMPACT) { + if (s->has_line_break()) + { + if (output_style() != COMPACT) + { append_optional_linefeed(); } } @@ -986,17 +1108,20 @@ namespace Sass { void Inspect::operator()(Complex_Selector_Ptr c) { - Compound_Selector_Obj head = c->head(); - Complex_Selector_Obj tail = c->tail(); + Compound_Selector_Obj head = c->head(); + Complex_Selector_Obj tail = c->tail(); Complex_Selector::Combinator comb = c->combinator(); - if (comb == Complex_Selector::ANCESTOR_OF && (!head || head->empty())) { + if (comb == Complex_Selector::ANCESTOR_OF && (!head || head->empty())) + { if (tail) tail->perform(this); return; } - if (c->has_line_feed()) { - if (!(c->has_parent_ref())) { + if (c->has_line_feed()) + { + if (!(c->has_parent_ref())) + { append_optional_linefeed(); append_indentation(); } @@ -1007,42 +1132,51 @@ namespace Sass { bool is_tail = head && !head->is_empty_reference() && tail; if (output_style() == COMPRESSED && comb != Complex_Selector::ANCESTOR_OF) scheduled_space = 0; - switch (comb) { - case Complex_Selector::ANCESTOR_OF: - if (is_tail) append_mandatory_space(); + switch (comb) + { + case Complex_Selector::ANCESTOR_OF: + if (is_tail) append_mandatory_space(); break; - case Complex_Selector::PARENT_OF: - append_optional_space(); - append_string(">"); - append_optional_space(); + case Complex_Selector::PARENT_OF: + append_optional_space(); + append_string(">"); + append_optional_space(); break; - case Complex_Selector::ADJACENT_TO: - append_optional_space(); - append_string("+"); - append_optional_space(); + case Complex_Selector::ADJACENT_TO: + append_optional_space(); + append_string("+"); + append_optional_space(); + break; + case Complex_Selector::REFERENCE: + append_mandatory_space(); + append_string("/"); + c->reference()->perform(this); + append_string("/"); + append_mandatory_space(); break; - case Complex_Selector::REFERENCE: + case Complex_Selector::PRECEDES: + if (is_empty) + append_optional_space(); + else append_mandatory_space(); - append_string("/"); - c->reference()->perform(this); - append_string("/"); + append_string("~"); + if (tail) append_mandatory_space(); + else + append_optional_space(); break; - case Complex_Selector::PRECEDES: - if (is_empty) append_optional_space(); - else append_mandatory_space(); - append_string("~"); - if (tail) append_mandatory_space(); - else append_optional_space(); + default: break; - default: break; } - if (tail && comb != Complex_Selector::ANCESTOR_OF) { + if (tail && comb != Complex_Selector::ANCESTOR_OF) + { if (c->has_line_break()) append_optional_linefeed(); } if (tail) tail->perform(this); - if (!tail && c->has_line_break()) { - if (output_style() == COMPACT) { + if (!tail && c->has_line_break()) + { + if (output_style() == COMPACT) + { append_mandatory_space(); } } @@ -1051,8 +1185,10 @@ namespace Sass { void Inspect::operator()(Selector_List_Ptr g) { - if (g->empty()) { - if (output_style() == TO_SASS) { + if (g->empty()) + { + if (output_style() == TO_SASS) + { append_token("()", g); } return; @@ -1062,24 +1198,27 @@ namespace Sass { bool was_comma_array = in_comma_array; // probably ruby sass eqivalent of element_needs_parens if (output_style() == TO_SASS && g->length() == 1 && - (!Cast((*g)[0]) && - !Cast((*g)[0]))) { + (!Cast((*g)[0]) && !Cast((*g)[0]))) + { append_string("("); } - else if (!in_declaration && in_comma_array) { + else if (!in_declaration && in_comma_array) + { append_string("("); } if (in_declaration) in_comma_array = true; - for (size_t i = 0, L = g->length(); i < L; ++i) { + for (size_t i = 0, L = g->length(); i < L; ++i) + { if (!in_wrapped && i == 0) append_indentation(); if ((*g)[i] == 0) continue; schedule_mapping(g->at(i)->last()); // add_open_mapping((*g)[i]->last()); (*g)[i]->perform(this); // add_close_mapping((*g)[i]->last()); - if (i < L - 1) { + if (i < L - 1) + { scheduled_space = 0; append_comma_separator(); } @@ -1088,18 +1227,17 @@ namespace Sass { in_comma_array = was_comma_array; // probably ruby sass eqivalent of element_needs_parens if (output_style() == TO_SASS && g->length() == 1 && - (!Cast((*g)[0]) && - !Cast((*g)[0]))) { + (!Cast((*g)[0]) && !Cast((*g)[0]))) + { append_string(",)"); } - else if (!in_declaration && in_comma_array) { + else if (!in_declaration && in_comma_array) + { append_string(")"); } - } void Inspect::fallback_impl(AST_Node_Ptr n) { } - } diff --git a/src/inspect.hpp b/src/inspect.hpp index dbff82069b..41dda175c6 100644 --- a/src/inspect.hpp +++ b/src/inspect.hpp @@ -5,18 +5,19 @@ #include "operation.hpp" #include "emitter.hpp" -namespace Sass { +namespace Sass +{ class Context; - class Inspect : public Operation_CRTP, public Emitter { - protected: + class Inspect : public Operation_CRTP, public Emitter + { + protected: // import all the class-specific methods and override as desired using Operation_CRTP::operator(); void fallback_impl(AST_Node_Ptr n); - public: - + public: Inspect(const Emitter& emi); virtual ~Inspect(); @@ -97,6 +98,5 @@ namespace Sass { // template // void fallback(U x) { fallback_impl(reinterpret_cast(x)); } }; - } #endif diff --git a/src/json.cpp b/src/json.cpp index 8f433f5d0b..d6f604bf7a 100644 --- a/src/json.cpp +++ b/src/json.cpp @@ -43,20 +43,21 @@ #ifdef snprintf #undef snprintf #endif -extern "C" int snprintf(char *, size_t, const char *, ...); +extern "C" int snprintf(char*, size_t, const char*, ...); #endif -#define out_of_memory() do { \ - fprintf(stderr, "Out of memory.\n"); \ - exit(EXIT_FAILURE); \ +#define out_of_memory() \ + do \ + { \ + fprintf(stderr, "Out of memory.\n"); \ + exit(EXIT_FAILURE); \ } while (0) /* Sadly, strdup is not portable. */ -static char *json_strdup(const char *str) +static char* json_strdup(const char* str) { - char *ret = (char*) malloc(strlen(str) + 1); - if (ret == NULL) - out_of_memory(); + char* ret = (char*)malloc(strlen(str) + 1); + if (ret == NULL) out_of_memory(); strcpy(ret, str); return ret; } @@ -65,68 +66,69 @@ static char *json_strdup(const char *str) typedef struct { - char *cur; - char *end; - char *start; + char* cur; + char* end; + char* start; } SB; -static void sb_init(SB *sb) +static void sb_init(SB* sb) { - sb->start = (char*) malloc(17); - if (sb->start == NULL) - out_of_memory(); + sb->start = (char*)malloc(17); + if (sb->start == NULL) out_of_memory(); sb->cur = sb->start; sb->end = sb->start + 16; } /* sb and need may be evaluated multiple times. */ -#define sb_need(sb, need) do { \ - if ((sb)->end - (sb)->cur < (need)) \ - sb_grow(sb, need); \ +#define sb_need(sb, need) \ + do \ + { \ + if ((sb)->end - (sb)->cur < (need)) sb_grow(sb, need); \ } while (0) -static void sb_grow(SB *sb, int need) +static void sb_grow(SB* sb, int need) { size_t length = sb->cur - sb->start; size_t alloc = sb->end - sb->start; - do { + do + { alloc *= 2; } while (alloc < length + need); - sb->start = (char*) realloc(sb->start, alloc + 1); - if (sb->start == NULL) - out_of_memory(); + sb->start = (char*)realloc(sb->start, alloc + 1); + if (sb->start == NULL) out_of_memory(); sb->cur = sb->start + length; sb->end = sb->start + alloc; } -static void sb_put(SB *sb, const char *bytes, int count) +static void sb_put(SB* sb, const char* bytes, int count) { sb_need(sb, count); memcpy(sb->cur, bytes, count); sb->cur += count; } -#define sb_putc(sb, c) do { \ - if ((sb)->cur >= (sb)->end) \ - sb_grow(sb, 1); \ - *(sb)->cur++ = (c); \ +#define sb_putc(sb, c) \ + do \ + { \ + if ((sb)->cur >= (sb)->end) sb_grow(sb, 1); \ + *(sb)->cur++ = (c); \ } while (0) -static void sb_puts(SB *sb, const char *str) +static void sb_puts(SB* sb, const char* str) { sb_put(sb, str, (int)strlen(str)); } -static char *sb_finish(SB *sb) +static char* sb_finish(SB* sb) { *sb->cur = 0; assert(sb->start <= sb->cur && strlen(sb->start) == (size_t)(sb->cur - sb->start)); return sb->start; } -static void sb_free(SB *sb) +static void sb_free(SB* sb) { free(sb->start); } @@ -162,69 +164,70 @@ static void sb_free(SB *sb) * * The sixty-six Unicode "non-characters" are permitted * (namely, U+FDD0..U+FDEF, U+xxFFFE, and U+xxFFFF). */ -static int utf8_validate_cz(const char *s) +static int utf8_validate_cz(const char* s) { unsigned char c = *s++; - if (c <= 0x7F) { /* 00..7F */ + if (c <= 0x7F) + { /* 00..7F */ return 1; - } else if (c <= 0xC1) { /* 80..C1 */ + } + else if (c <= 0xC1) + { /* 80..C1 */ /* Disallow overlong 2-byte sequence. */ return 0; - } else if (c <= 0xDF) { /* C2..DF */ + } + else if (c <= 0xDF) + { /* C2..DF */ /* Make sure subsequent byte is in the range 0x80..0xBF. */ - if (((unsigned char)*s++ & 0xC0) != 0x80) - return 0; + if (((unsigned char)*s++ & 0xC0) != 0x80) return 0; return 2; - } else if (c <= 0xEF) { /* E0..EF */ + } + else if (c <= 0xEF) + { /* E0..EF */ /* Disallow overlong 3-byte sequence. */ - if (c == 0xE0 && (unsigned char)*s < 0xA0) - return 0; + if (c == 0xE0 && (unsigned char)*s < 0xA0) return 0; /* Disallow U+D800..U+DFFF. */ - if (c == 0xED && (unsigned char)*s > 0x9F) - return 0; + if (c == 0xED && (unsigned char)*s > 0x9F) return 0; /* Make sure subsequent bytes are in the range 0x80..0xBF. */ - if (((unsigned char)*s++ & 0xC0) != 0x80) - return 0; - if (((unsigned char)*s++ & 0xC0) != 0x80) - return 0; + if (((unsigned char)*s++ & 0xC0) != 0x80) return 0; + if (((unsigned char)*s++ & 0xC0) != 0x80) return 0; return 3; - } else if (c <= 0xF4) { /* F0..F4 */ + } + else if (c <= 0xF4) + { /* F0..F4 */ /* Disallow overlong 4-byte sequence. */ - if (c == 0xF0 && (unsigned char)*s < 0x90) - return 0; + if (c == 0xF0 && (unsigned char)*s < 0x90) return 0; /* Disallow codepoints beyond U+10FFFF. */ - if (c == 0xF4 && (unsigned char)*s > 0x8F) - return 0; + if (c == 0xF4 && (unsigned char)*s > 0x8F) return 0; /* Make sure subsequent bytes are in the range 0x80..0xBF. */ - if (((unsigned char)*s++ & 0xC0) != 0x80) - return 0; - if (((unsigned char)*s++ & 0xC0) != 0x80) - return 0; - if (((unsigned char)*s++ & 0xC0) != 0x80) - return 0; + if (((unsigned char)*s++ & 0xC0) != 0x80) return 0; + if (((unsigned char)*s++ & 0xC0) != 0x80) return 0; + if (((unsigned char)*s++ & 0xC0) != 0x80) return 0; return 4; - } else { /* F5..FF */ + } + else + { /* F5..FF */ return 0; } } /* Validate a null-terminated UTF-8 string. */ -static bool utf8_validate(const char *s) +static bool utf8_validate(const char* s) { int len; - for (; *s != 0; s += len) { + for (; *s != 0; s += len) + { len = utf8_validate_cz(s); - if (len == 0) - return false; + if (len == 0) return false; } return true; @@ -237,33 +240,35 @@ static bool utf8_validate(const char *s) * This function assumes input is valid UTF-8, * and that there are enough characters in front of @s. */ -static int utf8_read_char(const char *s, uint32_t *out) +static int utf8_read_char(const char* s, uint32_t* out) { - const unsigned char *c = (const unsigned char*) s; + const unsigned char* c = (const unsigned char*)s; assert(utf8_validate_cz(s)); - if (c[0] <= 0x7F) { + if (c[0] <= 0x7F) + { /* 00..7F */ *out = c[0]; return 1; - } else if (c[0] <= 0xDF) { + } + else if (c[0] <= 0xDF) + { /* C2..DF (unless input is invalid) */ - *out = ((uint32_t)c[0] & 0x1F) << 6 | - ((uint32_t)c[1] & 0x3F); + *out = ((uint32_t)c[0] & 0x1F) << 6 | ((uint32_t)c[1] & 0x3F); return 2; - } else if (c[0] <= 0xEF) { + } + else if (c[0] <= 0xEF) + { /* E0..EF */ - *out = ((uint32_t)c[0] & 0xF) << 12 | - ((uint32_t)c[1] & 0x3F) << 6 | - ((uint32_t)c[2] & 0x3F); + *out = ((uint32_t)c[0] & 0xF) << 12 | ((uint32_t)c[1] & 0x3F) << 6 | ((uint32_t)c[2] & 0x3F); return 3; - } else { + } + else + { /* F0..F4 (unless input is invalid) */ - *out = ((uint32_t)c[0] & 0x7) << 18 | - ((uint32_t)c[1] & 0x3F) << 12 | - ((uint32_t)c[2] & 0x3F) << 6 | - ((uint32_t)c[3] & 0x3F); + *out = ((uint32_t)c[0] & 0x7) << 18 | ((uint32_t)c[1] & 0x3F) << 12 | + ((uint32_t)c[2] & 0x3F) << 6 | ((uint32_t)c[3] & 0x3F); return 4; } } @@ -276,28 +281,35 @@ static int utf8_read_char(const char *s, uint32_t *out) * * This function will write up to 4 bytes to @out. */ -static int utf8_write_char(uint32_t unicode, char *out) +static int utf8_write_char(uint32_t unicode, char* out) { - unsigned char *o = (unsigned char*) out; + unsigned char* o = (unsigned char*)out; assert(unicode <= 0x10FFFF && !(unicode >= 0xD800 && unicode <= 0xDFFF)); - if (unicode <= 0x7F) { + if (unicode <= 0x7F) + { /* U+0000..U+007F */ *o++ = unicode; return 1; - } else if (unicode <= 0x7FF) { + } + else if (unicode <= 0x7FF) + { /* U+0080..U+07FF */ *o++ = 0xC0 | unicode >> 6; *o++ = 0x80 | (unicode & 0x3F); return 2; - } else if (unicode <= 0xFFFF) { + } + else if (unicode <= 0xFFFF) + { /* U+0800..U+FFFF */ *o++ = 0xE0 | unicode >> 12; *o++ = 0x80 | (unicode >> 6 & 0x3F); *o++ = 0x80 | (unicode & 0x3F); return 3; - } else { + } + else + { /* U+10000..U+10FFFF */ *o++ = 0xF0 | unicode >> 18; *o++ = 0x80 | (unicode >> 12 & 0x3F); @@ -313,12 +325,15 @@ static int utf8_write_char(uint32_t unicode, char *out) * @uc should be 0xD800..0xDBFF, and @lc should be 0xDC00..0xDFFF. * If they aren't, this function returns false. */ -static bool from_surrogate_pair(uint16_t uc, uint16_t lc, uint32_t *unicode) +static bool from_surrogate_pair(uint16_t uc, uint16_t lc, uint32_t* unicode) { - if (uc >= 0xD800 && uc <= 0xDBFF && lc >= 0xDC00 && lc <= 0xDFFF) { + if (uc >= 0xD800 && uc <= 0xDBFF && lc >= 0xDC00 && lc <= 0xDFFF) + { *unicode = 0x10000 + ((((uint32_t)uc & 0x3FF) << 10) | (lc & 0x3FF)); return true; - } else { + } + else + { return false; } } @@ -328,7 +343,7 @@ static bool from_surrogate_pair(uint16_t uc, uint16_t lc, uint32_t *unicode) * * @unicode must be U+10000..U+10FFFF. */ -static void to_surrogate_pair(uint32_t unicode, uint16_t *uc, uint16_t *lc) +static void to_surrogate_pair(uint32_t unicode, uint16_t* uc, uint16_t* lc) { uint32_t n; @@ -339,49 +354,49 @@ static void to_surrogate_pair(uint32_t unicode, uint16_t *uc, uint16_t *lc) *lc = (n & 0x3FF) | 0xDC00; } -static bool is_space (const char *c); -static bool is_digit (const char *c); -static bool parse_value (const char **sp, JsonNode **out); -static bool parse_string (const char **sp, char **out); -static bool parse_number (const char **sp, double *out); -static bool parse_array (const char **sp, JsonNode **out); -static bool parse_object (const char **sp, JsonNode **out); -static bool parse_hex16 (const char **sp, uint16_t *out); - -static bool expect_literal (const char **sp, const char *str); -static void skip_space (const char **sp); - -static void emit_value (SB *out, const JsonNode *node); -static void emit_value_indented (SB *out, const JsonNode *node, const char *space, int indent_level); -static void emit_string (SB *out, const char *str); -static void emit_number (SB *out, double num); -static void emit_array (SB *out, const JsonNode *array); -static void emit_array_indented (SB *out, const JsonNode *array, const char *space, int indent_level); -static void emit_object (SB *out, const JsonNode *object); -static void emit_object_indented (SB *out, const JsonNode *object, const char *space, int indent_level); - -static int write_hex16(char *out, uint16_t val); - -static JsonNode *mknode(JsonTag tag); -static void append_node(JsonNode *parent, JsonNode *child); -static void prepend_node(JsonNode *parent, JsonNode *child); -static void append_member(JsonNode *object, char *key, JsonNode *value); +static bool is_space(const char* c); +static bool is_digit(const char* c); +static bool parse_value(const char** sp, JsonNode** out); +static bool parse_string(const char** sp, char** out); +static bool parse_number(const char** sp, double* out); +static bool parse_array(const char** sp, JsonNode** out); +static bool parse_object(const char** sp, JsonNode** out); +static bool parse_hex16(const char** sp, uint16_t* out); + +static bool expect_literal(const char** sp, const char* str); +static void skip_space(const char** sp); + +static void emit_value(SB* out, const JsonNode* node); +static void emit_value_indented(SB* out, const JsonNode* node, const char* space, int indent_level); +static void emit_string(SB* out, const char* str); +static void emit_number(SB* out, double num); +static void emit_array(SB* out, const JsonNode* array); +static void emit_array_indented(SB* out, const JsonNode* array, const char* space, int indent_level); +static void emit_object(SB* out, const JsonNode* object); +static void emit_object_indented(SB* out, const JsonNode* object, const char* space, int indent_level); + +static int write_hex16(char* out, uint16_t val); + +static JsonNode* mknode(JsonTag tag); +static void append_node(JsonNode* parent, JsonNode* child); +static void prepend_node(JsonNode* parent, JsonNode* child); +static void append_member(JsonNode* object, char* key, JsonNode* value); /* Assertion-friendly validity checks */ static bool tag_is_valid(unsigned int tag); -static bool number_is_valid(const char *num); +static bool number_is_valid(const char* num); -JsonNode *json_decode(const char *json) +JsonNode* json_decode(const char* json) { - const char *s = json; - JsonNode *ret; + const char* s = json; + JsonNode* ret; skip_space(&s); - if (!parse_value(&s, &ret)) - return NULL; + if (!parse_value(&s, &ret)) return NULL; skip_space(&s); - if (*s != 0) { + if (*s != 0) + { json_delete(ret); return NULL; } @@ -389,20 +404,22 @@ JsonNode *json_decode(const char *json) return ret; } -char *json_encode(const JsonNode *node) +char* json_encode(const JsonNode* node) { return json_stringify(node, NULL); } -char *json_encode_string(const char *str) +char* json_encode_string(const char* str) { SB sb; sb_init(&sb); - try { + try + { emit_string(&sb, str); } - catch (std::exception) { + catch (std::exception) + { sb_free(&sb); throw; } @@ -410,18 +427,20 @@ char *json_encode_string(const char *str) return sb_finish(&sb); } -char *json_stringify(const JsonNode *node, const char *space) +char* json_stringify(const JsonNode* node, const char* space) { SB sb; sb_init(&sb); - try { + try + { if (space != NULL) emit_value_indented(&sb, node, space, 0); else emit_value(&sb, node); } - catch (std::exception) { + catch (std::exception) + { sb_free(&sb); throw; } @@ -429,184 +448,184 @@ char *json_stringify(const JsonNode *node, const char *space) return sb_finish(&sb); } -void json_delete(JsonNode *node) +void json_delete(JsonNode* node) { - if (node != NULL) { + if (node != NULL) + { json_remove_from_parent(node); - switch (node->tag) { - case JSON_STRING: - free(node->string_); - break; - case JSON_ARRAY: - case JSON_OBJECT: + switch (node->tag) + { + case JSON_STRING: + free(node->string_); + break; + case JSON_ARRAY: + case JSON_OBJECT: + { + JsonNode *child, *next; + for (child = node->children.head; child != NULL; child = next) { - JsonNode *child, *next; - for (child = node->children.head; child != NULL; child = next) { - next = child->next; - json_delete(child); - } - break; + next = child->next; + json_delete(child); } - default:; + break; + } + default:; } free(node); } } -bool json_validate(const char *json) +bool json_validate(const char* json) { - const char *s = json; + const char* s = json; skip_space(&s); - if (!parse_value(&s, NULL)) - return false; + if (!parse_value(&s, NULL)) return false; skip_space(&s); - if (*s != 0) - return false; + if (*s != 0) return false; return true; } -JsonNode *json_find_element(JsonNode *array, int index) +JsonNode* json_find_element(JsonNode* array, int index) { - JsonNode *element; + JsonNode* element; int i = 0; - if (array == NULL || array->tag != JSON_ARRAY) - return NULL; + if (array == NULL || array->tag != JSON_ARRAY) return NULL; - json_foreach(element, array) { - if (i == index) - return element; + json_foreach(element, array) + { + if (i == index) return element; i++; } return NULL; } -JsonNode *json_find_member(JsonNode *object, const char *name) +JsonNode* json_find_member(JsonNode* object, const char* name) { - JsonNode *member; + JsonNode* member; - if (object == NULL || object->tag != JSON_OBJECT) - return NULL; + if (object == NULL || object->tag != JSON_OBJECT) return NULL; - json_foreach(member, object) - if (strcmp(member->key, name) == 0) - return member; + json_foreach(member, object) if (strcmp(member->key, name) == 0) return member; return NULL; } -JsonNode *json_first_child(const JsonNode *node) +JsonNode* json_first_child(const JsonNode* node) { if (node != NULL && (node->tag == JSON_ARRAY || node->tag == JSON_OBJECT)) return node->children.head; return NULL; } -static JsonNode *mknode(JsonTag tag) +static JsonNode* mknode(JsonTag tag) { - JsonNode *ret = (JsonNode*) calloc(1, sizeof(JsonNode)); - if (ret == NULL) - out_of_memory(); + JsonNode* ret = (JsonNode*)calloc(1, sizeof(JsonNode)); + if (ret == NULL) out_of_memory(); ret->tag = tag; return ret; } -JsonNode *json_mknull(void) +JsonNode* json_mknull(void) { return mknode(JSON_NULL); } -JsonNode *json_mkbool(bool b) +JsonNode* json_mkbool(bool b) { - JsonNode *ret = mknode(JSON_BOOL); + JsonNode* ret = mknode(JSON_BOOL); ret->bool_ = b; return ret; } -static JsonNode *mkstring(char *s) +static JsonNode* mkstring(char* s) { - JsonNode *ret = mknode(JSON_STRING); + JsonNode* ret = mknode(JSON_STRING); ret->string_ = s; return ret; } -JsonNode *json_mkstring(const char *s) +JsonNode* json_mkstring(const char* s) { return mkstring(json_strdup(s)); } -JsonNode *json_mknumber(double n) +JsonNode* json_mknumber(double n) { - JsonNode *node = mknode(JSON_NUMBER); + JsonNode* node = mknode(JSON_NUMBER); node->number_ = n; return node; } -JsonNode *json_mkarray(void) +JsonNode* json_mkarray(void) { return mknode(JSON_ARRAY); } -JsonNode *json_mkobject(void) +JsonNode* json_mkobject(void) { return mknode(JSON_OBJECT); } -static void append_node(JsonNode *parent, JsonNode *child) +static void append_node(JsonNode* parent, JsonNode* child) { - if (child != NULL && parent != NULL) { - child->parent = parent; - child->prev = parent->children.tail; - child->next = NULL; - - if (parent->children.tail != NULL) - parent->children.tail->next = child; - else - parent->children.head = child; - parent->children.tail = child; + if (child != NULL && parent != NULL) + { + child->parent = parent; + child->prev = parent->children.tail; + child->next = NULL; + + if (parent->children.tail != NULL) + parent->children.tail->next = child; + else + parent->children.head = child; + parent->children.tail = child; } } -static void prepend_node(JsonNode *parent, JsonNode *child) +static void prepend_node(JsonNode* parent, JsonNode* child) { - if (child != NULL && parent != NULL) { - child->parent = parent; - child->prev = NULL; - child->next = parent->children.head; - - if (parent->children.head != NULL) - parent->children.head->prev = child; - else - parent->children.tail = child; - parent->children.head = child; + if (child != NULL && parent != NULL) + { + child->parent = parent; + child->prev = NULL; + child->next = parent->children.head; + + if (parent->children.head != NULL) + parent->children.head->prev = child; + else + parent->children.tail = child; + parent->children.head = child; } } -static void append_member(JsonNode *object, char *key, JsonNode *value) +static void append_member(JsonNode* object, char* key, JsonNode* value) { - if (value != NULL && object != NULL) { - value->key = key; - append_node(object, value); + if (value != NULL && object != NULL) + { + value->key = key; + append_node(object, value); } } -void json_append_element(JsonNode *array, JsonNode *element) +void json_append_element(JsonNode* array, JsonNode* element) { - if (array != NULL && element !=NULL) { - assert(array->tag == JSON_ARRAY); - assert(element->parent == NULL); + if (array != NULL && element != NULL) + { + assert(array->tag == JSON_ARRAY); + assert(element->parent == NULL); - append_node(array, element); + append_node(array, element); } } -void json_prepend_element(JsonNode *array, JsonNode *element) +void json_prepend_element(JsonNode* array, JsonNode* element) { assert(array->tag == JSON_ARRAY); assert(element->parent == NULL); @@ -614,159 +633,166 @@ void json_prepend_element(JsonNode *array, JsonNode *element) prepend_node(array, element); } -void json_append_member(JsonNode *object, const char *key, JsonNode *value) +void json_append_member(JsonNode* object, const char* key, JsonNode* value) { - if (object != NULL && key != NULL && value != NULL) { - assert(object->tag == JSON_OBJECT); - assert(value->parent == NULL); + if (object != NULL && key != NULL && value != NULL) + { + assert(object->tag == JSON_OBJECT); + assert(value->parent == NULL); - append_member(object, json_strdup(key), value); + append_member(object, json_strdup(key), value); } } -void json_prepend_member(JsonNode *object, const char *key, JsonNode *value) +void json_prepend_member(JsonNode* object, const char* key, JsonNode* value) { - if (object != NULL && key != NULL && value != NULL) { - assert(object->tag == JSON_OBJECT); - assert(value->parent == NULL); + if (object != NULL && key != NULL && value != NULL) + { + assert(object->tag == JSON_OBJECT); + assert(value->parent == NULL); - value->key = json_strdup(key); - prepend_node(object, value); + value->key = json_strdup(key); + prepend_node(object, value); } } -void json_remove_from_parent(JsonNode *node) +void json_remove_from_parent(JsonNode* node) { - if (node != NULL) { - JsonNode *parent = node->parent; - - if (parent != NULL) { - if (node->prev != NULL) - node->prev->next = node->next; - else - parent->children.head = node->next; + if (node != NULL) + { + JsonNode* parent = node->parent; + + if (parent != NULL) + { + if (node->prev != NULL) + node->prev->next = node->next; + else + parent->children.head = node->next; - if (node->next != NULL) - node->next->prev = node->prev; - else - parent->children.tail = node->prev; + if (node->next != NULL) + node->next->prev = node->prev; + else + parent->children.tail = node->prev; - free(node->key); + free(node->key); - node->parent = NULL; - node->prev = node->next = NULL; - node->key = NULL; - } + node->parent = NULL; + node->prev = node->next = NULL; + node->key = NULL; + } } } -static bool parse_value(const char **sp, JsonNode **out) +static bool parse_value(const char** sp, JsonNode** out) { - const char *s = *sp; - - switch (*s) { - case 'n': - if (expect_literal(&s, "null")) { - if (out) - *out = json_mknull(); - *sp = s; - return true; - } - return false; + const char* s = *sp; + + switch (*s) + { + case 'n': + if (expect_literal(&s, "null")) + { + if (out) *out = json_mknull(); + *sp = s; + return true; + } + return false; - case 'f': - if (expect_literal(&s, "false")) { - if (out) - *out = json_mkbool(false); - *sp = s; - return true; - } - return false; + case 'f': + if (expect_literal(&s, "false")) + { + if (out) *out = json_mkbool(false); + *sp = s; + return true; + } + return false; - case 't': - if (expect_literal(&s, "true")) { - if (out) - *out = json_mkbool(true); - *sp = s; - return true; - } - return false; + case 't': + if (expect_literal(&s, "true")) + { + if (out) *out = json_mkbool(true); + *sp = s; + return true; + } + return false; - case '"': { - char *str = NULL; - if (parse_string(&s, out ? &str : NULL)) { - if (out) - *out = mkstring(str); - *sp = s; - return true; - } - return false; + case '"': + { + char* str = NULL; + if (parse_string(&s, out ? &str : NULL)) + { + if (out) *out = mkstring(str); + *sp = s; + return true; } + return false; + } - case '[': - if (parse_array(&s, out)) { - *sp = s; - return true; - } - return false; + case '[': + if (parse_array(&s, out)) + { + *sp = s; + return true; + } + return false; - case '{': - if (parse_object(&s, out)) { - *sp = s; - return true; - } - return false; + case '{': + if (parse_object(&s, out)) + { + *sp = s; + return true; + } + return false; - default: { - double num; - if (parse_number(&s, out ? &num : NULL)) { - if (out) - *out = json_mknumber(num); - *sp = s; - return true; - } - return false; + default: + { + double num; + if (parse_number(&s, out ? &num : NULL)) + { + if (out) *out = json_mknumber(num); + *sp = s; + return true; } + return false; + } } } -static bool parse_array(const char **sp, JsonNode **out) +static bool parse_array(const char** sp, JsonNode** out) { - const char *s = *sp; - JsonNode *ret = out ? json_mkarray() : NULL; - JsonNode *element = NULL; + const char* s = *sp; + JsonNode* ret = out ? json_mkarray() : NULL; + JsonNode* element = NULL; - if (*s++ != '[') - goto failure; + if (*s++ != '[') goto failure; skip_space(&s); - if (*s == ']') { + if (*s == ']') + { s++; goto success; } - for (;;) { - if (!parse_value(&s, out ? &element : NULL)) - goto failure; + for (;;) + { + if (!parse_value(&s, out ? &element : NULL)) goto failure; skip_space(&s); - if (out) - json_append_element(ret, element); + if (out) json_append_element(ret, element); - if (*s == ']') { + if (*s == ']') + { s++; goto success; } - if (*s++ != ',') - goto failure; + if (*s++ != ',') goto failure; skip_space(&s); } success: *sp = s; - if (out) - *out = ret; + if (out) *out = ret; return true; failure: @@ -774,147 +800,153 @@ static bool parse_array(const char **sp, JsonNode **out) return false; } -static bool parse_object(const char **sp, JsonNode **out) +static bool parse_object(const char** sp, JsonNode** out) { - const char *s = *sp; - JsonNode *ret = out ? json_mkobject() : NULL; - char *key = NULL; - JsonNode *value = NULL; + const char* s = *sp; + JsonNode* ret = out ? json_mkobject() : NULL; + char* key = NULL; + JsonNode* value = NULL; - if (*s++ != '{') - goto failure; + if (*s++ != '{') goto failure; skip_space(&s); - if (*s == '}') { + if (*s == '}') + { s++; goto success; } - for (;;) { - if (!parse_string(&s, out ? &key : NULL)) - goto failure; + for (;;) + { + if (!parse_string(&s, out ? &key : NULL)) goto failure; skip_space(&s); - if (*s++ != ':') - goto failure_free_key; + if (*s++ != ':') goto failure_free_key; skip_space(&s); - if (!parse_value(&s, out ? &value : NULL)) - goto failure_free_key; + if (!parse_value(&s, out ? &value : NULL)) goto failure_free_key; skip_space(&s); - if (out) - append_member(ret, key, value); + if (out) append_member(ret, key, value); - if (*s == '}') { + if (*s == '}') + { s++; goto success; } - if (*s++ != ',') - goto failure; + if (*s++ != ',') goto failure; skip_space(&s); } success: *sp = s; - if (out) - *out = ret; + if (out) *out = ret; return true; failure_free_key: - if (out) - free(key); + if (out) free(key); failure: json_delete(ret); return false; } -bool parse_string(const char **sp, char **out) +bool parse_string(const char** sp, char** out) { - const char *s = *sp; + const char* s = *sp; SB sb = { 0, 0, 0 }; char throwaway_buffer[4]; - /* enough space for a UTF-8 character */ - char *b; + /* enough space for a UTF-8 character */ + char* b; - if (*s++ != '"') - return false; + if (*s++ != '"') return false; - if (out) { + if (out) + { sb_init(&sb); sb_need(&sb, 4); b = sb.cur; - } else { + } + else + { b = throwaway_buffer; } - while (*s != '"') { + while (*s != '"') + { unsigned char c = *s++; /* Parse next character, and write it to b. */ - if (c == '\\') { + if (c == '\\') + { c = *s++; - switch (c) { - case '"': - case '\\': - case '/': - *b++ = c; - break; - case 'b': - *b++ = '\b'; - break; - case 'f': - *b++ = '\f'; - break; - case 'n': - *b++ = '\n'; - break; - case 'r': - *b++ = '\r'; - break; - case 't': - *b++ = '\t'; - break; - case 'u': + switch (c) + { + case '"': + case '\\': + case '/': + *b++ = c; + break; + case 'b': + *b++ = '\b'; + break; + case 'f': + *b++ = '\f'; + break; + case 'n': + *b++ = '\n'; + break; + case 'r': + *b++ = '\r'; + break; + case 't': + *b++ = '\t'; + break; + case 'u': + { + uint16_t uc, lc; + uint32_t unicode; + + if (!parse_hex16(&s, &uc)) goto failed; + + if (uc >= 0xD800 && uc <= 0xDFFF) { - uint16_t uc, lc; - uint32_t unicode; - - if (!parse_hex16(&s, &uc)) - goto failed; - - if (uc >= 0xD800 && uc <= 0xDFFF) { - /* Handle UTF-16 surrogate pair. */ - if (*s++ != '\\' || *s++ != 'u' || !parse_hex16(&s, &lc)) - goto failed; /* Incomplete surrogate pair. */ - if (!from_surrogate_pair(uc, lc, &unicode)) - goto failed; /* Invalid surrogate pair. */ - } else if (uc == 0) { - /* Disallow "\u0000". */ - goto failed; - } else { - unicode = uc; - } - - b += utf8_write_char(unicode, b); - break; + /* Handle UTF-16 surrogate pair. */ + if (*s++ != '\\' || *s++ != 'u' || !parse_hex16(&s, &lc)) + goto failed; /* Incomplete surrogate pair. */ + if (!from_surrogate_pair(uc, lc, &unicode)) goto failed; /* Invalid surrogate pair. */ } - default: - /* Invalid escape */ + else if (uc == 0) + { + /* Disallow "\u0000". */ goto failed; + } + else + { + unicode = uc; + } + + b += utf8_write_char(unicode, b); + break; } - } else if (c <= 0x1F) { + default: + /* Invalid escape */ + goto failed; + } + } + else if (c <= 0x1F) + { /* Control characters are not allowed in string literals. */ goto failed; - } else { + } + else + { /* Validate and echo a UTF-8 character. */ int len; s--; len = utf8_validate_cz(s); - if (len == 0) - goto failed; /* Invalid UTF-8 character. */ + if (len == 0) goto failed; /* Invalid UTF-8 character. */ while (len--) *b++ = *s++; @@ -924,32 +956,35 @@ bool parse_string(const char **sp, char **out) * Update sb to know about the new bytes, * and set up b to write another character. */ - if (out) { + if (out) + { sb.cur = b; sb_need(&sb, 4); b = sb.cur; - } else { + } + else + { b = throwaway_buffer; } } s++; - if (out) - *out = sb_finish(&sb); + if (out) *out = sb_finish(&sb); *sp = s; return true; failed: - if (out) - sb_free(&sb); + if (out) sb_free(&sb); return false; } -bool is_space(const char *c) { +bool is_space(const char* c) +{ return ((*c) == '\t' || (*c) == '\n' || (*c) == '\r' || (*c) == ' '); } -bool is_digit(const char *c){ +bool is_digit(const char* c) +{ return ((*c) >= '0' && (*c) <= '9'); } @@ -963,141 +998,147 @@ bool is_digit(const char *c){ * * This function takes the strict approach. */ -bool parse_number(const char **sp, double *out) +bool parse_number(const char** sp, double* out) { - const char *s = *sp; + const char* s = *sp; /* '-'? */ - if (*s == '-') - s++; + if (*s == '-') s++; /* (0 | [1-9][0-9]*) */ - if (*s == '0') { + if (*s == '0') + { s++; - } else { - if (!is_digit(s)) - return false; - do { + } + else + { + if (!is_digit(s)) return false; + do + { s++; } while (is_digit(s)); } /* ('.' [0-9]+)? */ - if (*s == '.') { + if (*s == '.') + { s++; - if (!is_digit(s)) - return false; - do { + if (!is_digit(s)) return false; + do + { s++; } while (is_digit(s)); } /* ([Ee] [+-]? [0-9]+)? */ - if (*s == 'E' || *s == 'e') { + if (*s == 'E' || *s == 'e') + { s++; - if (*s == '+' || *s == '-') - s++; - if (!is_digit(s)) - return false; - do { + if (*s == '+' || *s == '-') s++; + if (!is_digit(s)) return false; + do + { s++; } while (is_digit(s)); } - if (out) - *out = strtod(*sp, NULL); + if (out) *out = strtod(*sp, NULL); *sp = s; return true; } -static void skip_space(const char **sp) +static void skip_space(const char** sp) { - const char *s = *sp; + const char* s = *sp; while (is_space(s)) s++; *sp = s; } -static void emit_value(SB *out, const JsonNode *node) +static void emit_value(SB* out, const JsonNode* node) { assert(tag_is_valid(node->tag)); - switch (node->tag) { - case JSON_NULL: - sb_puts(out, "null"); - break; - case JSON_BOOL: - sb_puts(out, node->bool_ ? "true" : "false"); - break; - case JSON_STRING: - emit_string(out, node->string_); - break; - case JSON_NUMBER: - emit_number(out, node->number_); - break; - case JSON_ARRAY: - emit_array(out, node); - break; - case JSON_OBJECT: - emit_object(out, node); - break; - default: - assert(false); + switch (node->tag) + { + case JSON_NULL: + sb_puts(out, "null"); + break; + case JSON_BOOL: + sb_puts(out, node->bool_ ? "true" : "false"); + break; + case JSON_STRING: + emit_string(out, node->string_); + break; + case JSON_NUMBER: + emit_number(out, node->number_); + break; + case JSON_ARRAY: + emit_array(out, node); + break; + case JSON_OBJECT: + emit_object(out, node); + break; + default: + assert(false); } } -void emit_value_indented(SB *out, const JsonNode *node, const char *space, int indent_level) +void emit_value_indented(SB* out, const JsonNode* node, const char* space, int indent_level) { assert(tag_is_valid(node->tag)); - switch (node->tag) { - case JSON_NULL: - sb_puts(out, "null"); - break; - case JSON_BOOL: - sb_puts(out, node->bool_ ? "true" : "false"); - break; - case JSON_STRING: - emit_string(out, node->string_); - break; - case JSON_NUMBER: - emit_number(out, node->number_); - break; - case JSON_ARRAY: - emit_array_indented(out, node, space, indent_level); - break; - case JSON_OBJECT: - emit_object_indented(out, node, space, indent_level); - break; - default: - assert(false); + switch (node->tag) + { + case JSON_NULL: + sb_puts(out, "null"); + break; + case JSON_BOOL: + sb_puts(out, node->bool_ ? "true" : "false"); + break; + case JSON_STRING: + emit_string(out, node->string_); + break; + case JSON_NUMBER: + emit_number(out, node->number_); + break; + case JSON_ARRAY: + emit_array_indented(out, node, space, indent_level); + break; + case JSON_OBJECT: + emit_object_indented(out, node, space, indent_level); + break; + default: + assert(false); } } -static void emit_array(SB *out, const JsonNode *array) +static void emit_array(SB* out, const JsonNode* array) { - const JsonNode *element; + const JsonNode* element; sb_putc(out, '['); - json_foreach(element, array) { + json_foreach(element, array) + { emit_value(out, element); - if (element->next != NULL) - sb_putc(out, ','); + if (element->next != NULL) sb_putc(out, ','); } sb_putc(out, ']'); } -static void emit_array_indented(SB *out, const JsonNode *array, const char *space, int indent_level) +static void emit_array_indented(SB* out, const JsonNode* array, const char* space, int indent_level) { - const JsonNode *element = array->children.head; + const JsonNode* element = array->children.head; int i; - if (element == NULL) { + if (element == NULL) + { sb_puts(out, "[]"); return; } sb_puts(out, "[\n"); - while (element != NULL) { + while (element != NULL) + { for (i = 0; i < indent_level + 1; i++) sb_puts(out, space); emit_value_indented(out, element, space, indent_level + 1); @@ -1110,33 +1151,35 @@ static void emit_array_indented(SB *out, const JsonNode *array, const char *spac sb_putc(out, ']'); } -static void emit_object(SB *out, const JsonNode *object) +static void emit_object(SB* out, const JsonNode* object) { - const JsonNode *member; + const JsonNode* member; sb_putc(out, '{'); - json_foreach(member, object) { + json_foreach(member, object) + { emit_string(out, member->key); sb_putc(out, ':'); emit_value(out, member); - if (member->next != NULL) - sb_putc(out, ','); + if (member->next != NULL) sb_putc(out, ','); } sb_putc(out, '}'); } -static void emit_object_indented(SB *out, const JsonNode *object, const char *space, int indent_level) +static void emit_object_indented(SB* out, const JsonNode* object, const char* space, int indent_level) { - const JsonNode *member = object->children.head; + const JsonNode* member = object->children.head; int i; - if (member == NULL) { + if (member == NULL) + { sb_puts(out, "{}"); return; } sb_puts(out, "{\n"); - while (member != NULL) { + while (member != NULL) + { for (i = 0; i < indent_level + 1; i++) sb_puts(out, space); emit_string(out, member->key); @@ -1151,15 +1194,16 @@ static void emit_object_indented(SB *out, const JsonNode *object, const char *sp sb_putc(out, '}'); } -void emit_string(SB *out, const char *str) +void emit_string(SB* out, const char* str) { bool escape_unicode = false; - const char *s = str; - char *b; + const char* s = str; + char* b; // make assertion catchable #ifndef NDEBUG - if (!utf8_validate(str)) { + if (!utf8_validate(str)) + { throw utf8::invalid_utf8(0); } #endif @@ -1174,94 +1218,108 @@ void emit_string(SB *out, const char *str) b = out->cur; *b++ = '"'; - while (*s != 0) { + while (*s != 0) + { unsigned char c = *s++; /* Encode the next character, and write it to b. */ - switch (c) { - case '"': - *b++ = '\\'; - *b++ = '"'; - break; - case '\\': - *b++ = '\\'; - *b++ = '\\'; - break; - case '\b': - *b++ = '\\'; - *b++ = 'b'; - break; - case '\f': - *b++ = '\\'; - *b++ = 'f'; - break; - case '\n': - *b++ = '\\'; - *b++ = 'n'; - break; - case '\r': - *b++ = '\\'; - *b++ = 'r'; - break; - case '\t': - *b++ = '\\'; - *b++ = 't'; - break; - default: { - int len; - - s--; - len = utf8_validate_cz(s); - - if (len == 0) { - /* - * Handle invalid UTF-8 character gracefully in production - * by writing a replacement character (U+FFFD) - * and skipping a single byte. - * - * This should never happen when assertions are enabled - * due to the assertion at the beginning of this function. - */ - assert(false); - if (escape_unicode) { - strcpy(b, "\\uFFFD"); - b += 6; - } else { - *b++ = 0xEFu; - *b++ = 0xBFu; - *b++ = 0xBDu; - } - s++; - } else if (c < 0x1F || (c >= 0x80 && escape_unicode)) { - /* Encode using \u.... */ - uint32_t unicode; - - s += utf8_read_char(s, &unicode); - - if (unicode <= 0xFFFF) { - *b++ = '\\'; - *b++ = 'u'; - b += write_hex16(b, unicode); - } else { - /* Produce a surrogate pair. */ - uint16_t uc, lc; - assert(unicode <= 0x10FFFF); - to_surrogate_pair(unicode, &uc, &lc); - *b++ = '\\'; - *b++ = 'u'; - b += write_hex16(b, uc); - *b++ = '\\'; - *b++ = 'u'; - b += write_hex16(b, lc); - } - } else { - /* Write the character directly. */ - while (len--) - *b++ = *s++; + switch (c) + { + case '"': + *b++ = '\\'; + *b++ = '"'; + break; + case '\\': + *b++ = '\\'; + *b++ = '\\'; + break; + case '\b': + *b++ = '\\'; + *b++ = 'b'; + break; + case '\f': + *b++ = '\\'; + *b++ = 'f'; + break; + case '\n': + *b++ = '\\'; + *b++ = 'n'; + break; + case '\r': + *b++ = '\\'; + *b++ = 'r'; + break; + case '\t': + *b++ = '\\'; + *b++ = 't'; + break; + default: + { + int len; + + s--; + len = utf8_validate_cz(s); + + if (len == 0) + { + /* + * Handle invalid UTF-8 character gracefully in production + * by writing a replacement character (U+FFFD) + * and skipping a single byte. + * + * This should never happen when assertions are enabled + * due to the assertion at the beginning of this function. + */ + assert(false); + if (escape_unicode) + { + strcpy(b, "\\uFFFD"); + b += 6; } + else + { + *b++ = 0xEFu; + *b++ = 0xBFu; + *b++ = 0xBDu; + } + s++; + } + else if (c < 0x1F || (c >= 0x80 && escape_unicode)) + { + /* Encode using \u.... */ + uint32_t unicode; - break; + s += utf8_read_char(s, &unicode); + + if (unicode <= 0xFFFF) + { + *b++ = '\\'; + *b++ = 'u'; + b += write_hex16(b, unicode); + } + else + { + /* Produce a surrogate pair. */ + uint16_t uc, lc; + assert(unicode <= 0x10FFFF); + to_surrogate_pair(unicode, &uc, &lc); + *b++ = '\\'; + *b++ = 'u'; + b += write_hex16(b, uc); + *b++ = '\\'; + *b++ = 'u'; + b += write_hex16(b, lc); + } + } + else + { + /* Write the character directly. */ + while (len--) + *b++ = *s++; } + + break; + } } /* @@ -1277,7 +1335,7 @@ void emit_string(SB *out, const char *str) out->cur = b; } -static void emit_number(SB *out, double num) +static void emit_number(SB* out, double num) { /* * This isn't exactly how JavaScript renders numbers, @@ -1299,18 +1357,17 @@ static bool tag_is_valid(unsigned int tag) return (/* tag >= JSON_NULL && */ tag <= JSON_OBJECT); } -static bool number_is_valid(const char *num) +static bool number_is_valid(const char* num) { return (parse_number(&num, NULL) && *num == '\0'); } -static bool expect_literal(const char **sp, const char *str) +static bool expect_literal(const char** sp, const char* str) { - const char *s = *sp; + const char* s = *sp; while (*str != '\0') - if (*s++ != *str++) - return false; + if (*s++ != *str++) return false; *sp = s; return true; @@ -1320,15 +1377,16 @@ static bool expect_literal(const char **sp, const char *str) * Parses exactly 4 hex characters (capital or lowercase). * Fails if any input chars are not [0-9A-Fa-f]. */ -static bool parse_hex16(const char **sp, uint16_t *out) +static bool parse_hex16(const char** sp, uint16_t* out) { - const char *s = *sp; + const char* s = *sp; uint16_t ret = 0; uint16_t i; uint16_t tmp; char c; - for (i = 0; i < 4; i++) { + for (i = 0; i < 4; i++) + { c = *s++; if (c >= '0' && c <= '9') tmp = c - '0'; @@ -1343,8 +1401,7 @@ static bool parse_hex16(const char **sp, uint16_t *out) ret += tmp; } - if (out) - *out = ret; + if (out) *out = ret; *sp = s; return true; } @@ -1353,76 +1410,73 @@ static bool parse_hex16(const char **sp, uint16_t *out) * Encodes a 16-bit number into hexadecimal, * writing exactly 4 hex chars. */ -static int write_hex16(char *out, uint16_t val) +static int write_hex16(char* out, uint16_t val) { - const char *hex = "0123456789ABCDEF"; + const char* hex = "0123456789ABCDEF"; *out++ = hex[(val >> 12) & 0xF]; - *out++ = hex[(val >> 8) & 0xF]; - *out++ = hex[(val >> 4) & 0xF]; - *out++ = hex[ val & 0xF]; + *out++ = hex[(val >> 8) & 0xF]; + *out++ = hex[(val >> 4) & 0xF]; + *out++ = hex[val & 0xF]; return 4; } -bool json_check(const JsonNode *node, char errmsg[256]) +bool json_check(const JsonNode* node, char errmsg[256]) { - #define problem(...) do { \ - if (errmsg != NULL) \ - snprintf(errmsg, 256, __VA_ARGS__); \ - return false; \ - } while (0) +#define problem(...) \ + do \ + { \ + if (errmsg != NULL) snprintf(errmsg, 256, __VA_ARGS__); \ + return false; \ + } while (0) - if (node->key != NULL && !utf8_validate(node->key)) - problem("key contains invalid UTF-8"); + if (node->key != NULL && !utf8_validate(node->key)) problem("key contains invalid UTF-8"); - if (!tag_is_valid(node->tag)) - problem("tag is invalid (%u)", node->tag); + if (!tag_is_valid(node->tag)) problem("tag is invalid (%u)", node->tag); - if (node->tag == JSON_BOOL) { + if (node->tag == JSON_BOOL) + { if (node->bool_ != false && node->bool_ != true) problem("bool_ is neither false (%d) nor true (%d)", (int)false, (int)true); - } else if (node->tag == JSON_STRING) { - if (node->string_ == NULL) - problem("string_ is NULL"); - if (!utf8_validate(node->string_)) - problem("string_ contains invalid UTF-8"); - } else if (node->tag == JSON_ARRAY || node->tag == JSON_OBJECT) { - JsonNode *head = node->children.head; - JsonNode *tail = node->children.tail; - - if (head == NULL || tail == NULL) { - if (head != NULL) - problem("tail is NULL, but head is not"); - if (tail != NULL) - problem("head is NULL, but tail is not"); - } else { - JsonNode *child; - JsonNode *last = NULL; - - if (head->prev != NULL) - problem("First child's prev pointer is not NULL"); - - for (child = head; child != NULL; last = child, child = child->next) { - if (child == node) - problem("node is its own child"); - if (child->next == child) - problem("child->next == child (cycle)"); - if (child->next == head) - problem("child->next == head (cycle)"); - - if (child->parent != node) - problem("child does not point back to parent"); + } + else if (node->tag == JSON_STRING) + { + if (node->string_ == NULL) problem("string_ is NULL"); + if (!utf8_validate(node->string_)) problem("string_ contains invalid UTF-8"); + } + else if (node->tag == JSON_ARRAY || node->tag == JSON_OBJECT) + { + JsonNode* head = node->children.head; + JsonNode* tail = node->children.tail; + + if (head == NULL || tail == NULL) + { + if (head != NULL) problem("tail is NULL, but head is not"); + if (tail != NULL) problem("head is NULL, but tail is not"); + } + else + { + JsonNode* child; + JsonNode* last = NULL; + + if (head->prev != NULL) problem("First child's prev pointer is not NULL"); + + for (child = head; child != NULL; last = child, child = child->next) + { + if (child == node) problem("node is its own child"); + if (child->next == child) problem("child->next == child (cycle)"); + if (child->next == head) problem("child->next == head (cycle)"); + + if (child->parent != node) problem("child does not point back to parent"); if (child->next != NULL && child->next->prev != child) problem("child->next does not point back to child"); if (node->tag == JSON_ARRAY && child->key != NULL) problem("Array element's key is not NULL"); - if (node->tag == JSON_OBJECT && child->key == NULL) - problem("Object member's key is NULL"); + if (node->tag == JSON_OBJECT && child->key == NULL) problem("Object member's key is NULL"); - if (!json_check(child, errmsg)) - return false; + if (!json_check(child, errmsg)) return false; } if (last != tail) @@ -1432,5 +1486,5 @@ bool json_check(const JsonNode *node, char errmsg[256]) return true; - #undef problem +#undef problem } diff --git a/src/json.hpp b/src/json.hpp index 05b35cd940..78936d12a9 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -41,11 +41,11 @@ typedef struct JsonNode JsonNode; struct JsonNode { /* only if parent is an object or array (NULL otherwise) */ - JsonNode *parent; + JsonNode* parent; JsonNode *prev, *next; /* only if parent is an object (NULL otherwise) */ - char *key; /* Must be valid UTF-8. */ + char* key; /* Must be valid UTF-8. */ JsonTag tag; union { @@ -53,14 +53,15 @@ struct JsonNode bool bool_; /* JSON_STRING */ - char *string_; /* Must be valid UTF-8. */ + char* string_; /* Must be valid UTF-8. */ /* JSON_NUMBER */ double number_; /* JSON_ARRAY */ /* JSON_OBJECT */ - struct { + struct + { JsonNode *head, *tail; } children; }; @@ -68,41 +69,39 @@ struct JsonNode /*** Encoding, decoding, and validation ***/ -JsonNode *json_decode (const char *json); -char *json_encode (const JsonNode *node); -char *json_encode_string (const char *str); -char *json_stringify (const JsonNode *node, const char *space); -void json_delete (JsonNode *node); +JsonNode* json_decode(const char* json); +char* json_encode(const JsonNode* node); +char* json_encode_string(const char* str); +char* json_stringify(const JsonNode* node, const char* space); +void json_delete(JsonNode* node); -bool json_validate (const char *json); +bool json_validate(const char* json); /*** Lookup and traversal ***/ -JsonNode *json_find_element (JsonNode *array, int index); -JsonNode *json_find_member (JsonNode *object, const char *key); +JsonNode* json_find_element(JsonNode* array, int index); +JsonNode* json_find_member(JsonNode* object, const char* key); -JsonNode *json_first_child (const JsonNode *node); +JsonNode* json_first_child(const JsonNode* node); -#define json_foreach(i, object_or_array) \ - for ((i) = json_first_child(object_or_array); \ - (i) != NULL; \ - (i) = (i)->next) +#define json_foreach(i, object_or_array) \ + for ((i) = json_first_child(object_or_array); (i) != NULL; (i) = (i)->next) /*** Construction and manipulation ***/ -JsonNode *json_mknull(void); -JsonNode *json_mkbool(bool b); -JsonNode *json_mkstring(const char *s); -JsonNode *json_mknumber(double n); -JsonNode *json_mkarray(void); -JsonNode *json_mkobject(void); +JsonNode* json_mknull(void); +JsonNode* json_mkbool(bool b); +JsonNode* json_mkstring(const char* s); +JsonNode* json_mknumber(double n); +JsonNode* json_mkarray(void); +JsonNode* json_mkobject(void); -void json_append_element(JsonNode *array, JsonNode *element); -void json_prepend_element(JsonNode *array, JsonNode *element); -void json_append_member(JsonNode *object, const char *key, JsonNode *value); -void json_prepend_member(JsonNode *object, const char *key, JsonNode *value); +void json_append_element(JsonNode* array, JsonNode* element); +void json_prepend_element(JsonNode* array, JsonNode* element); +void json_append_member(JsonNode* object, const char* key, JsonNode* value); +void json_prepend_member(JsonNode* object, const char* key, JsonNode* value); -void json_remove_from_parent(JsonNode *node); +void json_remove_from_parent(JsonNode* node); /*** Debugging ***/ @@ -112,6 +111,6 @@ void json_remove_from_parent(JsonNode *node); * If a problem is detected, return false, writing a description of the problem * to errmsg (unless errmsg is NULL). */ -bool json_check(const JsonNode *node, char errmsg[256]); +bool json_check(const JsonNode* node, char errmsg[256]); #endif diff --git a/src/kwd_arg_macros.hpp b/src/kwd_arg_macros.hpp index e135da7dea..07e7fd6bf4 100644 --- a/src/kwd_arg_macros.hpp +++ b/src/kwd_arg_macros.hpp @@ -15,14 +15,20 @@ #define KWD_ARG_SET(set_name) class set_name #define KWD_ARG(set_name, type, name) \ -private: \ - type name##_; \ -public: \ - set_name& name(type name##__) { \ - name##_ = name##__; \ - return *this; \ - } \ - type name() { return name##_; } \ -private: + private: \ + type name##_; \ + \ + public: \ + set_name& name(type name##__) \ + { \ + name##_ = name##__; \ + return *this; \ + } \ + type name() \ + { \ + return name##_; \ + } \ + \ + private: #endif diff --git a/src/lexer.cpp b/src/lexer.cpp index 781257e2e2..a47301ca85 100644 --- a/src/lexer.cpp +++ b/src/lexer.cpp @@ -6,24 +6,50 @@ #include "constants.hpp" -namespace Sass { +namespace Sass +{ using namespace Constants; - namespace Prelexer { + namespace Prelexer + { //#################################### // BASIC CHARACTER MATCHERS //#################################### // Match standard control chars - const char* kwd_at(const char* src) { return exactly<'@'>(src); } - const char* kwd_dot(const char* src) { return exactly<'.'>(src); } - const char* kwd_comma(const char* src) { return exactly<','>(src); }; - const char* kwd_colon(const char* src) { return exactly<':'>(src); }; - const char* kwd_star(const char* src) { return exactly<'*'>(src); }; - const char* kwd_plus(const char* src) { return exactly<'+'>(src); }; - const char* kwd_minus(const char* src) { return exactly<'-'>(src); }; - const char* kwd_slash(const char* src) { return exactly<'/'>(src); }; + const char* kwd_at(const char* src) + { + return exactly<'@'>(src); + } + const char* kwd_dot(const char* src) + { + return exactly<'.'>(src); + } + const char* kwd_comma(const char* src) + { + return exactly<','>(src); + }; + const char* kwd_colon(const char* src) + { + return exactly<':'>(src); + }; + const char* kwd_star(const char* src) + { + return exactly<'*'>(src); + }; + const char* kwd_plus(const char* src) + { + return exactly<'+'>(src); + }; + const char* kwd_minus(const char* src) + { + return exactly<'-'>(src); + }; + const char* kwd_slash(const char* src) + { + return exactly<'/'>(src); + }; //#################################### // implement some function that do exist in the standard @@ -33,8 +59,7 @@ namespace Sass { bool is_alpha(const char& chr) { - return unsigned(chr - 'A') <= 'Z' - 'A' || - unsigned(chr - 'a') <= 'z' - 'a'; + return unsigned(chr - 'A') <= 'Z' - 'A' || unsigned(chr - 'a') <= 'z' - 'a'; } bool is_space(const char& chr) @@ -52,8 +77,7 @@ namespace Sass { bool is_xdigit(const char& chr) { // adapted the technique from is_alpha - return unsigned(chr - '0') <= '9' - '0' || - unsigned(chr - 'a') <= 'f' - 'a' || + return unsigned(chr - '0') <= '9' - '0' || unsigned(chr - 'a') <= 'f' - 'a' || unsigned(chr - 'A') <= 'F' - 'A'; } @@ -79,19 +103,15 @@ namespace Sass { // but with specific ranges (copied from Ruby Sass) bool is_nonascii(const char& chr) { - return ( - (unsigned(chr) >= 128 && unsigned(chr) <= 15572911) || - (unsigned(chr) >= 15630464 && unsigned(chr) <= 15712189) || - (unsigned(chr) >= 4036001920) - ); + return ((unsigned(chr) >= 128 && unsigned(chr) <= 15572911) || + (unsigned(chr) >= 15630464 && unsigned(chr) <= 15712189) || (unsigned(chr) >= 4036001920)); } // check if char is within a reduced ascii range // valid in a uri (copied from Ruby Sass) bool is_uri_character(const char& chr) { - return (unsigned(chr) > 41 && unsigned(chr) < 127) || - unsigned(chr) == ':' || unsigned(chr) == '/'; + return (unsigned(chr) > 41 && unsigned(chr) < 127) || unsigned(chr) == ':' || unsigned(chr) == '/'; } // check if char is within a reduced ascii range @@ -113,33 +133,90 @@ namespace Sass { //#################################### // create matchers that advance the position - const char* space(const char* src) { return is_space(*src) ? src + 1 : 0; } - const char* alpha(const char* src) { return is_alpha(*src) ? src + 1 : 0; } - const char* unicode(const char* src) { return is_unicode(*src) ? src + 1 : 0; } - const char* nonascii(const char* src) { return is_nonascii(*src) ? src + 1 : 0; } - const char* digit(const char* src) { return is_digit(*src) ? src + 1 : 0; } - const char* xdigit(const char* src) { return is_xdigit(*src) ? src + 1 : 0; } - const char* alnum(const char* src) { return is_alnum(*src) ? src + 1 : 0; } - const char* punct(const char* src) { return is_punct(*src) ? src + 1 : 0; } - const char* hyphen(const char* src) { return *src && *src == '-' ? src + 1 : 0; } - const char* character(const char* src) { return is_character(*src) ? src + 1 : 0; } - const char* uri_character(const char* src) { return is_uri_character(*src) ? src + 1 : 0; } - const char* escapable_character(const char* src) { return is_escapable_character(*src) ? src + 1 : 0; } + const char* space(const char* src) + { + return is_space(*src) ? src + 1 : 0; + } + const char* alpha(const char* src) + { + return is_alpha(*src) ? src + 1 : 0; + } + const char* unicode(const char* src) + { + return is_unicode(*src) ? src + 1 : 0; + } + const char* nonascii(const char* src) + { + return is_nonascii(*src) ? src + 1 : 0; + } + const char* digit(const char* src) + { + return is_digit(*src) ? src + 1 : 0; + } + const char* xdigit(const char* src) + { + return is_xdigit(*src) ? src + 1 : 0; + } + const char* alnum(const char* src) + { + return is_alnum(*src) ? src + 1 : 0; + } + const char* punct(const char* src) + { + return is_punct(*src) ? src + 1 : 0; + } + const char* hyphen(const char* src) + { + return *src && *src == '-' ? src + 1 : 0; + } + const char* character(const char* src) + { + return is_character(*src) ? src + 1 : 0; + } + const char* uri_character(const char* src) + { + return is_uri_character(*src) ? src + 1 : 0; + } + const char* escapable_character(const char* src) + { + return is_escapable_character(*src) ? src + 1 : 0; + } // Match multiple ctype characters. - const char* spaces(const char* src) { return one_plus(src); } - const char* digits(const char* src) { return one_plus(src); } - const char* hyphens(const char* src) { return one_plus(src); } + const char* spaces(const char* src) + { + return one_plus(src); + } + const char* digits(const char* src) + { + return one_plus(src); + } + const char* hyphens(const char* src) + { + return one_plus(src); + } // Whitespace handling. - const char* no_spaces(const char* src) { return negate< space >(src); } - const char* optional_spaces(const char* src) { return zero_plus< space >(src); } + const char* no_spaces(const char* src) + { + return negate(src); + } + const char* optional_spaces(const char* src) + { + return zero_plus(src); + } // Match any single character. - const char* any_char(const char* src) { return *src ? src + 1 : src; } + const char* any_char(const char* src) + { + return *src ? src + 1 : src; + } // Match word boundary (zero-width lookahead). - const char* word_boundary(const char* src) { return is_character(*src) || *src == '#' ? 0 : src; } + const char* word_boundary(const char* src) + { + return is_character(*src) || *src == '#' ? 0 : src; + } // Match linefeed /(?:\n|\r\n?)/ const char* re_linebreak(const char* src) @@ -167,6 +244,5 @@ namespace Sass { // end of file or unix linefeed return here return *src == 0 ? src : 0; } - } } diff --git a/src/lexer.hpp b/src/lexer.hpp index a419a6d112..e36a3a2666 100644 --- a/src/lexer.hpp +++ b/src/lexer.hpp @@ -3,8 +3,10 @@ #include -namespace Sass { - namespace Prelexer { +namespace Sass +{ + namespace Prelexer + { //#################################### // BASIC CHARACTER MATCHERS @@ -87,21 +89,22 @@ namespace Sass { // Match a single character literal. // Regex equivalent: /(?:x)/ - template - const char* exactly(const char* src) { + template const char* exactly(const char* src) + { return *src == chr ? src + 1 : 0; } // Match the full string literal. // Regex equivalent: /(?:literal)/ - template - const char* exactly(const char* src) { + template const char* exactly(const char* src) + { if (str == NULL) return 0; const char* pre = str; if (src == NULL) return 0; // there is a small chance that the search string // is longer than the rest of the string to look at - while (*pre && *src == *pre) { + while (*pre && *src == *pre) + { ++src, ++pre; } // did the matcher finish? @@ -112,14 +115,15 @@ namespace Sass { // Match the full string literal. // Regex equivalent: /(?:literal)/i // only define lower case alpha chars - template - const char* insensitive(const char* src) { + template const char* insensitive(const char* src) + { if (str == NULL) return 0; const char* pre = str; if (src == NULL) return 0; // there is a small chance that the search string // is longer than the rest of the string to look at - while (*pre && (*src == *pre || *src+32 == *pre)) { + while (*pre && (*src == *pre || *src + 32 == *pre)) + { ++src, ++pre; } // did the matcher finish? @@ -128,53 +132,57 @@ namespace Sass { // Match for members of char class. // Regex equivalent: /[axy]/ - template - const char* class_char(const char* src) { + template const char* class_char(const char* src) + { const char* cc = char_class; - while (*cc && *src != *cc) ++cc; + while (*cc && *src != *cc) + ++cc; return *cc ? src + 1 : 0; } // Match for members of char class. // Regex equivalent: /[axy]+/ - template - const char* class_chars(const char* src) { + template const char* class_chars(const char* src) + { const char* p = src; - while (class_char(p)) ++p; + while (class_char(p)) + ++p; return p == src ? 0 : p; } // Match for members of char class. // Regex equivalent: /[^axy]/ - template - const char* neg_class_char(const char* src) { + template const char* neg_class_char(const char* src) + { if (*src == 0) return 0; const char* cc = neg_char_class; - while (*cc && *src != *cc) ++cc; + while (*cc && *src != *cc) + ++cc; return *cc ? 0 : src + 1; } // Match for members of char class. // Regex equivalent: /[^axy]+/ - template - const char* neg_class_chars(const char* src) { + template const char* neg_class_chars(const char* src) + { const char* p = src; - while (neg_class_char(p)) ++p; + while (neg_class_char(p)) + ++p; return p == src ? 0 : p; } // Match all except the supplied one. // Regex equivalent: /[^x]/ - template - const char* any_char_but(const char* src) { + template const char* any_char_but(const char* src) + { return (*src && *src != chr) ? src + 1 : 0; } // Succeeds if the matcher fails. // Aka. zero-width negative lookahead. // Regex equivalent: /(?!literal)/ - template - const char* negate(const char* src) { + template const char* negate(const char* src) + { return mx(src) ? 0 : src; } @@ -182,22 +190,23 @@ namespace Sass { // Aka. zero-width positive lookahead. // Regex equivalent: /(?=literal)/ // just hangs around until we need it - template - const char* lookahead(const char* src) { + template const char* lookahead(const char* src) + { return mx(src) ? src : 0; } // Tries supplied matchers in order. // Succeeds if one of them succeeds. // Regex equivalent: /(?:FOO|BAR)/ - template - const char* alternatives(const char* src) { + template const char* alternatives(const char* src) + { const char* rslt; if ((rslt = mx(src))) return rslt; return 0; } template - const char* alternatives(const char* src) { + const char* alternatives(const char* src) + { const char* rslt; if ((rslt = mx1(src))) return rslt; return alternatives(src); @@ -206,14 +215,15 @@ namespace Sass { // Tries supplied matchers in order. // Succeeds if all of them succeeds. // Regex equivalent: /(?:FOO)(?:BAR)/ - template - const char* sequence(const char* src) { + template const char* sequence(const char* src) + { const char* rslt = src; if (!(rslt = mx1(rslt))) return 0; return rslt; } template - const char* sequence(const char* src) { + const char* sequence(const char* src) + { const char* rslt = src; if (!(rslt = mx1(rslt))) return 0; return sequence(rslt); @@ -222,37 +232,40 @@ namespace Sass { // Match a pattern or not. Always succeeds. // Regex equivalent: /(?:literal)?/ - template - const char* optional(const char* src) { + template const char* optional(const char* src) + { const char* p = mx(src); return p ? p : src; } // Match zero or more of the patterns. // Regex equivalent: /(?:literal)*/ - template - const char* zero_plus(const char* src) { + template const char* zero_plus(const char* src) + { const char* p = mx(src); - while (p) src = p, p = mx(src); + while (p) + src = p, p = mx(src); return src; } // Match one or more of the patterns. // Regex equivalent: /(?:literal)+/ - template - const char* one_plus(const char* src) { + template const char* one_plus(const char* src) + { const char* p = mx(src); if (!p) return 0; - while (p) src = p, p = mx(src); + while (p) + src = p, p = mx(src); return src; } // Match mx non-greedy until delimiter. // Other prelexers are greedy by default. // Regex equivalent: /(?:$mx)*?(?=$delim)\b/ - template - const char* non_greedy(const char* src) { - while (!delim(src)) { + template const char* non_greedy(const char* src) + { + while (!delim(src)) + { const char* p = mx(src); if (p == src) return 0; if (p == 0) return 0; @@ -267,39 +280,26 @@ namespace Sass { // Match with word boundary rule. // Regex equivalent: /(?:$mx)\b/i - template - const char* keyword(const char* src) { - return sequence < - insensitive < str >, - word_boundary - >(src); + template const char* keyword(const char* src) + { + return sequence, word_boundary>(src); } // Match with word boundary rule. // Regex equivalent: /(?:$mx)\b/ - template - const char* word(const char* src) { - return sequence < - exactly < str >, - word_boundary - >(src); + template const char* word(const char* src) + { + return sequence, word_boundary>(src); } - template - const char* loosely(const char* src) { - return sequence < - optional_spaces, - exactly < chr > - >(src); + template const char* loosely(const char* src) + { + return sequence>(src); } - template - const char* loosely(const char* src) { - return sequence < - optional_spaces, - exactly < str > - >(src); + template const char* loosely(const char* src) + { + return sequence>(src); } - } } diff --git a/src/listize.cpp b/src/listize.cpp index cb921ae679..65eb7a9743 100644 --- a/src/listize.cpp +++ b/src/listize.cpp @@ -8,16 +8,19 @@ #include "backtrace.hpp" #include "error_handling.hpp" -namespace Sass { +namespace Sass +{ Listize::Listize() - { } + { + } Expression_Ptr Listize::operator()(Selector_List_Ptr sel) { List_Obj l = SASS_MEMORY_NEW(List, sel->pstate(), sel->length(), SASS_COMMA); l->from_selector(true); - for (size_t i = 0, L = sel->length(); i < L; ++i) { + for (size_t i = 0, L = sel->length(); i < L; ++i) + { if (!sel->at(i)) continue; l->append(sel->at(i)->perform(this)); } @@ -28,7 +31,8 @@ namespace Sass { Expression_Ptr Listize::operator()(Compound_Selector_Ptr sel) { std::string str; - for (size_t i = 0, L = sel->length(); i < L; ++i) { + for (size_t i = 0, L = sel->length(); i < L; ++i) + { Expression_Ptr e = (*sel)[i]->perform(this); if (e) str += e->to_string(); } @@ -46,25 +50,25 @@ namespace Sass { if (hh) l->append(hh); } - std::string reference = ! sel->reference() ? "" - : sel->reference()->to_string(); - switch(sel->combinator()) + std::string reference = !sel->reference() ? "" : sel->reference()->to_string(); + switch (sel->combinator()) { - case Complex_Selector::PARENT_OF: - l->append(SASS_MEMORY_NEW(String_Quoted, sel->pstate(), ">")); + case Complex_Selector::PARENT_OF: + l->append(SASS_MEMORY_NEW(String_Quoted, sel->pstate(), ">")); + break; + case Complex_Selector::ADJACENT_TO: + l->append(SASS_MEMORY_NEW(String_Quoted, sel->pstate(), "+")); break; - case Complex_Selector::ADJACENT_TO: - l->append(SASS_MEMORY_NEW(String_Quoted, sel->pstate(), "+")); + case Complex_Selector::REFERENCE: + l->append(SASS_MEMORY_NEW(String_Quoted, sel->pstate(), "/" + reference + "/")); break; - case Complex_Selector::REFERENCE: - l->append(SASS_MEMORY_NEW(String_Quoted, sel->pstate(), "/" + reference + "/")); + case Complex_Selector::PRECEDES: + l->append(SASS_MEMORY_NEW(String_Quoted, sel->pstate(), "~")); break; - case Complex_Selector::PRECEDES: - l->append(SASS_MEMORY_NEW(String_Quoted, sel->pstate(), "~")); + case Complex_Selector::ANCESTOR_OF: break; - case Complex_Selector::ANCESTOR_OF: + default: break; - default: break; } Complex_Selector_Obj tail = sel->tail(); @@ -72,7 +76,9 @@ namespace Sass { { Expression_Obj tt = tail->perform(this); if (List_Ptr ls = Cast(tt)) - { l->concat(ls); } + { + l->concat(ls); + } } if (l->length() == 0) return 0; return l.detach(); @@ -82,5 +88,4 @@ namespace Sass { { return Cast(n); } - } diff --git a/src/listize.hpp b/src/listize.hpp index 9716ebefc6..7e854f8f12 100644 --- a/src/listize.hpp +++ b/src/listize.hpp @@ -9,26 +9,31 @@ #include "operation.hpp" #include "environment.hpp" -namespace Sass { +namespace Sass +{ struct Backtrace; - class Listize : public Operation_CRTP { + class Listize : public Operation_CRTP + { Expression_Ptr fallback_impl(AST_Node_Ptr n); - public: + public: Listize(); - ~Listize() { } + ~Listize() + { + } Expression_Ptr operator()(Selector_List_Ptr); Expression_Ptr operator()(Complex_Selector_Ptr); Expression_Ptr operator()(Compound_Selector_Ptr); - template - Expression_Ptr fallback(U x) { return fallback_impl(x); } + template Expression_Ptr fallback(U x) + { + return fallback_impl(x); + } }; - } #endif diff --git a/src/mapping.hpp b/src/mapping.hpp index 54fb4a0f75..751d9bd330 100644 --- a/src/mapping.hpp +++ b/src/mapping.hpp @@ -3,16 +3,19 @@ #include "position.hpp" -namespace Sass { +namespace Sass +{ - struct Mapping { + struct Mapping + { Position original_position; Position generated_position; Mapping(const Position& original_position, const Position& generated_position) - : original_position(original_position), generated_position(generated_position) { } + : original_position(original_position), generated_position(generated_position) + { + } }; - } #endif diff --git a/src/node.cpp b/src/node.cpp index fed87b8294..526ac32e44 100644 --- a/src/node.cpp +++ b/src/node.cpp @@ -5,16 +5,19 @@ #include "context.hpp" #include "parser.hpp" -namespace Sass { +namespace Sass +{ - Node Node::createCombinator(const Complex_Selector::Combinator& combinator) { + Node Node::createCombinator(const Complex_Selector::Combinator& combinator) + { NodeDequePtr null; return Node(COMBINATOR, combinator, NULL /*pSelector*/, null /*pCollection*/); } - Node Node::createSelector(const Complex_Selector& pSelector) { + Node Node::createSelector(const Complex_Selector& pSelector) + { NodeDequePtr null; Complex_Selector_Ptr pStripped = SASS_MEMORY_COPY(&pSelector); @@ -27,33 +30,43 @@ namespace Sass { } - Node Node::createCollection() { + Node Node::createCollection() + { NodeDequePtr pEmptyCollection = std::make_shared(); return Node(COLLECTION, Complex_Selector::ANCESTOR_OF, NULL /*pSelector*/, pEmptyCollection); } - Node Node::createCollection(const NodeDeque& values) { + Node Node::createCollection(const NodeDeque& values) + { NodeDequePtr pShallowCopiedCollection = std::make_shared(values); return Node(COLLECTION, Complex_Selector::ANCESTOR_OF, NULL /*pSelector*/, pShallowCopiedCollection); } - Node Node::createNil() { + Node Node::createNil() + { NodeDequePtr null; return Node(NIL, Complex_Selector::ANCESTOR_OF, NULL /*pSelector*/, null /*pCollection*/); } Node::Node(const TYPE& type, Complex_Selector::Combinator combinator, Complex_Selector_Ptr pSelector, NodeDequePtr& pCollection) - : got_line_feed(false), mType(type), mCombinator(combinator), mpSelector(pSelector), mpCollection(pCollection) - { if (pSelector) got_line_feed = pSelector->has_line_feed(); } + : got_line_feed(false), mType(type), mCombinator(combinator), mpSelector(pSelector), + mpCollection(pCollection) + { + if (pSelector) got_line_feed = pSelector->has_line_feed(); + } - Node Node::klone() const { + Node Node::klone() const + { NodeDequePtr pNewCollection = std::make_shared(); - if (mpCollection) { - for (NodeDeque::iterator iter = mpCollection->begin(), iterEnd = mpCollection->end(); iter != iterEnd; iter++) { + if (mpCollection) + { + for (NodeDeque::iterator iter = mpCollection->begin(), iterEnd = mpCollection->end(); + iter != iterEnd; iter++) + { Node& toClone = *iter; pNewCollection->push_back(toClone.klone()); } @@ -65,13 +78,16 @@ namespace Sass { } - bool Node::contains(const Node& potentialChild) const { + bool Node::contains(const Node& potentialChild) const + { bool found = false; - for (NodeDeque::iterator iter = mpCollection->begin(), iterEnd = mpCollection->end(); iter != iterEnd; iter++) { + for (NodeDeque::iterator iter = mpCollection->begin(), iterEnd = mpCollection->end(); iter != iterEnd; iter++) + { Node& toTest = *iter; - if (toTest == potentialChild) { + if (toTest == potentialChild) + { found = true; break; } @@ -81,81 +97,113 @@ namespace Sass { } - bool Node::operator==(const Node& rhs) const { - if (this->type() != rhs.type()) { + bool Node::operator==(const Node& rhs) const + { + if (this->type() != rhs.type()) + { return false; } - if (this->isCombinator()) { + if (this->isCombinator()) + { return this->combinator() == rhs.combinator(); - - } else if (this->isNil()) { + } + else if (this->isNil()) + { return true; // no state to check - - } else if (this->isSelector()){ + } + else if (this->isSelector()) + { return *this->selector() == *rhs.selector(); + } + else if (this->isCollection()) + { - } else if (this->isCollection()) { - - if (this->collection()->size() != rhs.collection()->size()) { + if (this->collection()->size() != rhs.collection()->size()) + { return false; } - for (NodeDeque::iterator lhsIter = this->collection()->begin(), lhsIterEnd = this->collection()->end(), - rhsIter = rhs.collection()->begin(); lhsIter != lhsIterEnd; lhsIter++, rhsIter++) { + for (NodeDeque::iterator lhsIter = this->collection()->begin(), + lhsIterEnd = this->collection()->end(), rhsIter = rhs.collection()->begin(); + lhsIter != lhsIterEnd; lhsIter++, rhsIter++) + { - if (*lhsIter != *rhsIter) { + if (*lhsIter != *rhsIter) + { return false; } - } return true; - } // We shouldn't get here. - throw "Comparing unknown node types. A new type was probably added and this method wasn't implemented for it."; + throw "Comparing unknown node types. A new type was probably added and this method wasn't " + "implemented for it."; } - void Node::plus(Node& rhs) { - if (!this->isCollection() || !rhs.isCollection()) { + void Node::plus(Node& rhs) + { + if (!this->isCollection() || !rhs.isCollection()) + { throw "Both the current node and rhs must be collections."; } - this->collection()->insert(this->collection()->end(), rhs.collection()->begin(), rhs.collection()->end()); + this->collection()->insert(this->collection()->end(), rhs.collection()->begin(), + rhs.collection()->end()); } #ifdef DEBUG - std::ostream& operator<<(std::ostream& os, const Node& node) { + std::ostream& operator<<(std::ostream& os, const Node& node) + { - if (node.isCombinator()) { + if (node.isCombinator()) + { - switch (node.combinator()) { - case Complex_Selector::ANCESTOR_OF: os << "\" \""; break; - case Complex_Selector::PARENT_OF: os << "\">\""; break; - case Complex_Selector::PRECEDES: os << "\"~\""; break; - case Complex_Selector::ADJACENT_TO: os << "\"+\""; break; - case Complex_Selector::REFERENCE: os << "\"/\""; break; + switch (node.combinator()) + { + case Complex_Selector::ANCESTOR_OF: + os << "\" \""; + break; + case Complex_Selector::PARENT_OF: + os << "\">\""; + break; + case Complex_Selector::PRECEDES: + os << "\"~\""; + break; + case Complex_Selector::ADJACENT_TO: + os << "\"+\""; + break; + case Complex_Selector::REFERENCE: + os << "\"/\""; + break; } - - } else if (node.isNil()) { + } + else if (node.isNil()) + { os << "nil"; - - } else if (node.isSelector()){ + } + else if (node.isSelector()) + { os << node.selector()->head()->to_string(); - - } else if (node.isCollection()) { + } + else if (node.isCollection()) + { os << "["; - for (NodeDeque::iterator iter = node.collection()->begin(), iterBegin = node.collection()->begin(), iterEnd = node.collection()->end(); iter != iterEnd; iter++) { - if (iter != iterBegin) { + for (NodeDeque::iterator iter = node.collection()->begin(), iterBegin = node.collection()->begin(), + iterEnd = node.collection()->end(); + iter != iterEnd; iter++) + { + if (iter != iterBegin) + { os << ", "; } @@ -163,17 +211,17 @@ namespace Sass { } os << "]"; - } return os; - } #endif - Node complexSelectorToNode(Complex_Selector_Ptr pToConvert) { - if (pToConvert == NULL) { + Node complexSelectorToNode(Complex_Selector_Ptr pToConvert) + { + if (pToConvert == NULL) + { return Node::createNil(); } Node node = Node::createCollection(); @@ -181,33 +229,39 @@ namespace Sass { bool has_lf = pToConvert->has_line_feed(); // unwrap the selector from parent ref - if (pToConvert->head() && pToConvert->head()->has_parent_ref()) { + if (pToConvert->head() && pToConvert->head()->has_parent_ref()) + { Complex_Selector_Obj tail = pToConvert->tail(); if (tail) tail->has_line_feed(pToConvert->has_line_feed()); pToConvert = tail; } - while (pToConvert) { + while (pToConvert) + { bool empty_parent_ref = pToConvert->head() && pToConvert->head()->is_empty_reference(); - if (pToConvert->head() || empty_parent_ref) { + if (pToConvert->head() || empty_parent_ref) + { } // the first Complex_Selector may contain a dummy head pointer, skip it. - if (pToConvert->head() && !empty_parent_ref) { + if (pToConvert->head() && !empty_parent_ref) + { node.collection()->push_back(Node::createSelector(*pToConvert)); if (has_lf) node.collection()->back().got_line_feed = has_lf; has_lf = false; } - if (pToConvert->combinator() != Complex_Selector::ANCESTOR_OF) { + if (pToConvert->combinator() != Complex_Selector::ANCESTOR_OF) + { node.collection()->push_back(Node::createCombinator(pToConvert->combinator())); if (has_lf) node.collection()->back().got_line_feed = has_lf; has_lf = false; } - if (pToConvert && empty_parent_ref && pToConvert->tail()) { + if (pToConvert && empty_parent_ref && pToConvert->tail()) + { // pToConvert->tail()->has_line_feed(pToConvert->has_line_feed()); } @@ -218,13 +272,16 @@ namespace Sass { } - Complex_Selector_Ptr nodeToComplexSelector(const Node& toConvert) { - if (toConvert.isNil()) { + Complex_Selector_Ptr nodeToComplexSelector(const Node& toConvert) + { + if (toConvert.isNil()) + { return NULL; } - if (!toConvert.isCollection()) { + if (!toConvert.isCollection()) + { throw "The node to convert to a Complex_Selector_Ptr must be a collection type or nil."; } @@ -232,54 +289,70 @@ namespace Sass { NodeDeque& childNodes = *toConvert.collection(); std::string noPath(""); - Complex_Selector_Obj pFirst = SASS_MEMORY_NEW(Complex_Selector, ParserState("[NODE]"), Complex_Selector::ANCESTOR_OF, NULL, NULL); + Complex_Selector_Obj pFirst = + SASS_MEMORY_NEW(Complex_Selector, ParserState("[NODE]"), Complex_Selector::ANCESTOR_OF, NULL, NULL); Complex_Selector_Obj pCurrent = pFirst; if (toConvert.isSelector()) pFirst->has_line_feed(toConvert.got_line_feed); if (toConvert.isCombinator()) pFirst->has_line_feed(toConvert.got_line_feed); - for (NodeDeque::iterator childIter = childNodes.begin(), childIterEnd = childNodes.end(); childIter != childIterEnd; childIter++) { + for (NodeDeque::iterator childIter = childNodes.begin(), childIterEnd = childNodes.end(); + childIter != childIterEnd; childIter++) + { Node& child = *childIter; - if (child.isSelector()) { + if (child.isSelector()) + { // JMA - need to clone the selector, because they can end up getting shared across Node // collections, and can result in an infinite loop during the call to parentSuperselector() pCurrent->tail(SASS_MEMORY_COPY(child.selector())); // if (child.got_line_feed) pCurrent->has_line_feed(child.got_line_feed); pCurrent = pCurrent->tail(); - } else if (child.isCombinator()) { + } + else if (child.isCombinator()) + { pCurrent->combinator(child.combinator()); if (child.got_line_feed) pCurrent->has_line_feed(child.got_line_feed); - // if the next node is also a combinator, create another Complex_Selector to hold it so it doesn't replace the current combinator - if (childIter+1 != childIterEnd) { - Node& nextNode = *(childIter+1); - if (nextNode.isCombinator()) { - pCurrent->tail(SASS_MEMORY_NEW(Complex_Selector, ParserState("[NODE]"), Complex_Selector::ANCESTOR_OF, NULL, NULL)); + // if the next node is also a combinator, create another Complex_Selector to hold it so it + // doesn't replace the current combinator + if (childIter + 1 != childIterEnd) + { + Node& nextNode = *(childIter + 1); + if (nextNode.isCombinator()) + { + pCurrent->tail(SASS_MEMORY_NEW(Complex_Selector, ParserState("[NODE]"), + Complex_Selector::ANCESTOR_OF, NULL, NULL)); if (nextNode.got_line_feed) pCurrent->tail()->has_line_feed(nextNode.got_line_feed); pCurrent = pCurrent->tail(); } } - } else { + } + else + { throw "The node to convert's children must be only combinators or selectors."; } } - // Put the dummy Compound_Selector in the first position, for consistency with the rest of libsass + // Put the dummy Compound_Selector in the first position, for consistency with the rest of + // libsass Compound_Selector_Ptr fakeHead = SASS_MEMORY_NEW(Compound_Selector, ParserState("[NODE]"), 1); Parent_Selector_Ptr selectorRef = SASS_MEMORY_NEW(Parent_Selector, ParserState("[NODE]")); fakeHead->elements().push_back(selectorRef); if (toConvert.got_line_feed) pFirst->has_line_feed(toConvert.got_line_feed); - // pFirst->has_line_feed(pFirst->has_line_feed() || pFirst->tail()->has_line_feed() || toConvert.got_line_feed); + // pFirst->has_line_feed(pFirst->has_line_feed() || pFirst->tail()->has_line_feed() || + // toConvert.got_line_feed); pFirst->head(fakeHead); return SASS_MEMORY_COPY(pFirst); } // A very naive trim function, which removes duplicates in a node - // This is only used in Complex_Selector::unify_with for now, may need modifications to fit other needs - Node Node::naiveTrim(Node& seqses) { + // This is only used in Complex_Selector::unify_with for now, may need modifications to fit other + // needs + Node Node::naiveTrim(Node& seqses) + { std::vector res; std::vector known; @@ -290,25 +363,35 @@ namespace Sass { for (; seqsesIter != seqsesIterEnd; ++seqsesIter) { Node& seqs1 = *seqsesIter; - if( seqs1.isSelector() ) { + if (seqs1.isSelector()) + { Complex_Selector_Obj sel = seqs1.selector(); std::vector::iterator it; bool found = false; - for (it = known.begin(); it != known.end(); ++it) { - if (**it == *sel) { found = true; break; } + for (it = known.begin(); it != known.end(); ++it) + { + if (**it == *sel) + { + found = true; + break; + } } - if( !found ) { + if (!found) + { known.push_back(seqs1.selector()); res.push_back(&seqs1); } - } else { + } + else + { res.push_back(&seqs1); } } Node result = Node::createCollection(); - for (size_t i = res.size() - 1; i != std::string::npos; --i) { + for (size_t i = res.size() - 1; i != std::string::npos; --i) + { result.collection()->push_back(*res[i]); } diff --git a/src/node.hpp b/src/node.hpp index 23ba360c32..8bd8f9a493 100644 --- a/src/node.hpp +++ b/src/node.hpp @@ -7,56 +7,98 @@ #include "ast.hpp" -namespace Sass { - - +namespace Sass +{ class Context; /* - There are a lot of stumbling blocks when trying to port the ruby extend code to C++. The biggest is the choice of - data type. The ruby code will pretty seamlessly switch types between an Array (libsass' - equivalent is the Complex_Selector) to a Sequence, which contains more metadata about the sequence than just the - selector info. They also have the ability to have arbitrary nestings of arrays like [1, [2]], which is hard to - implement using Array equivalents in C++ (like the deque or vector). They also have the ability to include nil - in the arrays, like [1, nil, 3], which has potential semantic differences than an empty array [1, [], 3]. To be - able to represent all of these as unique cases, we need to create a tree of variant objects. The tree nature allows - the inconsistent nesting levels. The variant nature (while making some of the C++ code uglier) allows the code to - more closely match the ruby code, which is a huge benefit when attempting to implement an complex algorithm like + There are a lot of stumbling blocks when trying to port the ruby extend code to C++. The biggest + is the choice of + data type. The ruby code will pretty seamlessly switch types between an Array (libsass' + equivalent is the Complex_Selector) to a Sequence, which contains more metadata about the + sequence than just the + selector info. They also have the ability to have arbitrary nestings of arrays like [1, [2]], + which is hard to + implement using Array equivalents in C++ (like the deque or vector). They also have the ability + to include nil + in the arrays, like [1, nil, 3], which has potential semantic differences than an empty array [1, + [], 3]. To be + able to represent all of these as unique cases, we need to create a tree of variant objects. The + tree nature allows + the inconsistent nesting levels. The variant nature (while making some of the C++ code uglier) + allows the code to + more closely match the ruby code, which is a huge benefit when attempting to implement an complex + algorithm like the Extend operator. - Note that the current libsass data model also pairs the combinator with the Complex_Selector that follows it, but - ruby sass has no such restriction, so we attempt to create a data structure that can handle them split apart. + Note that the current libsass data model also pairs the combinator with the Complex_Selector that + follows it, but + ruby sass has no such restriction, so we attempt to create a data structure that can handle them + split apart. */ class Node; typedef std::deque NodeDeque; typedef std::shared_ptr NodeDequePtr; - class Node { - public: - enum TYPE { + class Node + { + public: + enum TYPE + { SELECTOR, COMBINATOR, COLLECTION, NIL }; - TYPE type() const { return mType; } - bool isCombinator() const { return mType == COMBINATOR; } - bool isSelector() const { return mType == SELECTOR; } - bool isCollection() const { return mType == COLLECTION; } - bool isNil() const { return mType == NIL; } + TYPE type() const + { + return mType; + } + bool isCombinator() const + { + return mType == COMBINATOR; + } + bool isSelector() const + { + return mType == SELECTOR; + } + bool isCollection() const + { + return mType == COLLECTION; + } + bool isNil() const + { + return mType == NIL; + } bool got_line_feed; - Complex_Selector::Combinator combinator() const { return mCombinator; } - - Complex_Selector_Obj selector() { return mpSelector; } - Complex_Selector_Obj selector() const { return mpSelector; } - - NodeDequePtr collection() { return mpCollection; } - const NodeDequePtr collection() const { return mpCollection; } + Complex_Selector::Combinator combinator() const + { + return mCombinator; + } + + Complex_Selector_Obj selector() + { + return mpSelector; + } + Complex_Selector_Obj selector() const + { + return mpSelector; + } + + NodeDequePtr collection() + { + return mpCollection; + } + const NodeDequePtr collection() const + { + return mpCollection; + } static Node createCombinator(const Complex_Selector::Combinator& combinator); @@ -72,7 +114,10 @@ namespace Sass { Node klone() const; bool operator==(const Node& rhs) const; - inline bool operator!=(const Node& rhs) const { return !(*this == rhs); } + inline bool operator!=(const Node& rhs) const + { + return !(*this == rhs); + } /* @@ -93,7 +138,7 @@ namespace Sass { // Node. bool contains(const Node& potentialChild) const; - private: + private: // Private constructor; Use the static methods (like createCombinator and createSelector) // to instantiate this object. This is more expressive, and it allows us to break apart each // case into separate functions. @@ -112,7 +157,6 @@ namespace Sass { #endif Node complexSelectorToNode(Complex_Selector_Ptr pToConvert); Complex_Selector_Ptr nodeToComplexSelector(const Node& toConvert); - } #endif diff --git a/src/operation.hpp b/src/operation.hpp index 3ba4938e00..4f50c5ff9e 100644 --- a/src/operation.hpp +++ b/src/operation.hpp @@ -3,169 +3,380 @@ #include "ast_fwd_decl.hpp" -namespace Sass { +namespace Sass +{ - template - class Operation { - public: - virtual T operator()(AST_Node_Ptr x) = 0; - virtual ~Operation() { } + template class Operation + { + public: + virtual T operator()(AST_Node_Ptr x) = 0; + virtual ~Operation() + { + } // statements - virtual T operator()(Block_Ptr x) = 0; - virtual T operator()(Ruleset_Ptr x) = 0; - virtual T operator()(Bubble_Ptr x) = 0; - virtual T operator()(Trace_Ptr x) = 0; - virtual T operator()(Supports_Block_Ptr x) = 0; - virtual T operator()(Media_Block_Ptr x) = 0; - virtual T operator()(At_Root_Block_Ptr x) = 0; - virtual T operator()(Directive_Ptr x) = 0; - virtual T operator()(Keyframe_Rule_Ptr x) = 0; - virtual T operator()(Declaration_Ptr x) = 0; - virtual T operator()(Assignment_Ptr x) = 0; - virtual T operator()(Import_Ptr x) = 0; - virtual T operator()(Import_Stub_Ptr x) = 0; - virtual T operator()(Warning_Ptr x) = 0; - virtual T operator()(Error_Ptr x) = 0; - virtual T operator()(Debug_Ptr x) = 0; - virtual T operator()(Comment_Ptr x) = 0; - virtual T operator()(If_Ptr x) = 0; - virtual T operator()(For_Ptr x) = 0; - virtual T operator()(Each_Ptr x) = 0; - virtual T operator()(While_Ptr x) = 0; - virtual T operator()(Return_Ptr x) = 0; - virtual T operator()(Content_Ptr x) = 0; - virtual T operator()(Extension_Ptr x) = 0; - virtual T operator()(Definition_Ptr x) = 0; - virtual T operator()(Mixin_Call_Ptr x) = 0; + virtual T operator()(Block_Ptr x) = 0; + virtual T operator()(Ruleset_Ptr x) = 0; + virtual T operator()(Bubble_Ptr x) = 0; + virtual T operator()(Trace_Ptr x) = 0; + virtual T operator()(Supports_Block_Ptr x) = 0; + virtual T operator()(Media_Block_Ptr x) = 0; + virtual T operator()(At_Root_Block_Ptr x) = 0; + virtual T operator()(Directive_Ptr x) = 0; + virtual T operator()(Keyframe_Rule_Ptr x) = 0; + virtual T operator()(Declaration_Ptr x) = 0; + virtual T operator()(Assignment_Ptr x) = 0; + virtual T operator()(Import_Ptr x) = 0; + virtual T operator()(Import_Stub_Ptr x) = 0; + virtual T operator()(Warning_Ptr x) = 0; + virtual T operator()(Error_Ptr x) = 0; + virtual T operator()(Debug_Ptr x) = 0; + virtual T operator()(Comment_Ptr x) = 0; + virtual T operator()(If_Ptr x) = 0; + virtual T operator()(For_Ptr x) = 0; + virtual T operator()(Each_Ptr x) = 0; + virtual T operator()(While_Ptr x) = 0; + virtual T operator()(Return_Ptr x) = 0; + virtual T operator()(Content_Ptr x) = 0; + virtual T operator()(Extension_Ptr x) = 0; + virtual T operator()(Definition_Ptr x) = 0; + virtual T operator()(Mixin_Call_Ptr x) = 0; // expressions - virtual T operator()(List_Ptr x) = 0; - virtual T operator()(Map_Ptr x) = 0; - virtual T operator()(Binary_Expression_Ptr x) = 0; - virtual T operator()(Unary_Expression_Ptr x) = 0; - virtual T operator()(Function_Call_Ptr x) = 0; - virtual T operator()(Function_Call_Schema_Ptr x) = 0; - virtual T operator()(Custom_Warning_Ptr x) = 0; - virtual T operator()(Custom_Error_Ptr x) = 0; - virtual T operator()(Variable_Ptr x) = 0; - virtual T operator()(Number_Ptr x) = 0; - virtual T operator()(Color_Ptr x) = 0; - virtual T operator()(Boolean_Ptr x) = 0; - virtual T operator()(String_Schema_Ptr x) = 0; - virtual T operator()(String_Quoted_Ptr x) = 0; - virtual T operator()(String_Constant_Ptr x) = 0; - virtual T operator()(Supports_Condition_Ptr x) = 0; - virtual T operator()(Supports_Operator_Ptr x) = 0; - virtual T operator()(Supports_Negation_Ptr x) = 0; - virtual T operator()(Supports_Declaration_Ptr x) = 0; + virtual T operator()(List_Ptr x) = 0; + virtual T operator()(Map_Ptr x) = 0; + virtual T operator()(Binary_Expression_Ptr x) = 0; + virtual T operator()(Unary_Expression_Ptr x) = 0; + virtual T operator()(Function_Call_Ptr x) = 0; + virtual T operator()(Function_Call_Schema_Ptr x) = 0; + virtual T operator()(Custom_Warning_Ptr x) = 0; + virtual T operator()(Custom_Error_Ptr x) = 0; + virtual T operator()(Variable_Ptr x) = 0; + virtual T operator()(Number_Ptr x) = 0; + virtual T operator()(Color_Ptr x) = 0; + virtual T operator()(Boolean_Ptr x) = 0; + virtual T operator()(String_Schema_Ptr x) = 0; + virtual T operator()(String_Quoted_Ptr x) = 0; + virtual T operator()(String_Constant_Ptr x) = 0; + virtual T operator()(Supports_Condition_Ptr x) = 0; + virtual T operator()(Supports_Operator_Ptr x) = 0; + virtual T operator()(Supports_Negation_Ptr x) = 0; + virtual T operator()(Supports_Declaration_Ptr x) = 0; virtual T operator()(Supports_Interpolation_Ptr x) = 0; - virtual T operator()(Media_Query_Ptr x) = 0; + virtual T operator()(Media_Query_Ptr x) = 0; virtual T operator()(Media_Query_Expression_Ptr x) = 0; - virtual T operator()(At_Root_Query_Ptr x) = 0; - virtual T operator()(Null_Ptr x) = 0; - virtual T operator()(Parent_Selector_Ptr x) = 0; + virtual T operator()(At_Root_Query_Ptr x) = 0; + virtual T operator()(Null_Ptr x) = 0; + virtual T operator()(Parent_Selector_Ptr x) = 0; // parameters and arguments - virtual T operator()(Parameter_Ptr x) = 0; - virtual T operator()(Parameters_Ptr x) = 0; - virtual T operator()(Argument_Ptr x) = 0; - virtual T operator()(Arguments_Ptr x) = 0; + virtual T operator()(Parameter_Ptr x) = 0; + virtual T operator()(Parameters_Ptr x) = 0; + virtual T operator()(Argument_Ptr x) = 0; + virtual T operator()(Arguments_Ptr x) = 0; // selectors - virtual T operator()(Selector_Schema_Ptr x) = 0; - virtual T operator()(Placeholder_Selector_Ptr x) = 0; - virtual T operator()(Element_Selector_Ptr x) = 0; - virtual T operator()(Class_Selector_Ptr x) = 0; - virtual T operator()(Id_Selector_Ptr x) = 0; - virtual T operator()(Attribute_Selector_Ptr x) = 0; - virtual T operator()(Pseudo_Selector_Ptr x) = 0; - virtual T operator()(Wrapped_Selector_Ptr x) = 0; - virtual T operator()(Compound_Selector_Ptr x)= 0; - virtual T operator()(Complex_Selector_Ptr x) = 0; + virtual T operator()(Selector_Schema_Ptr x) = 0; + virtual T operator()(Placeholder_Selector_Ptr x) = 0; + virtual T operator()(Element_Selector_Ptr x) = 0; + virtual T operator()(Class_Selector_Ptr x) = 0; + virtual T operator()(Id_Selector_Ptr x) = 0; + virtual T operator()(Attribute_Selector_Ptr x) = 0; + virtual T operator()(Pseudo_Selector_Ptr x) = 0; + virtual T operator()(Wrapped_Selector_Ptr x) = 0; + virtual T operator()(Compound_Selector_Ptr x) = 0; + virtual T operator()(Complex_Selector_Ptr x) = 0; virtual T operator()(Selector_List_Ptr x) = 0; - template - T fallback(U x) { return T(); } + template T fallback(U x) + { + return T(); + } }; - template - class Operation_CRTP : public Operation { - public: - D& impl() { return static_cast(*this); } - public: - T operator()(AST_Node_Ptr x) { return static_cast(this)->fallback(x); } + template class Operation_CRTP : public Operation + { + public: + D& impl() + { + return static_cast(*this); + } + + public: + T operator()(AST_Node_Ptr x) + { + return static_cast(this)->fallback(x); + } // statements - T operator()(Block_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Ruleset_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Bubble_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Trace_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Supports_Block_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Media_Block_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(At_Root_Block_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Directive_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Keyframe_Rule_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Declaration_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Assignment_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Import_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Import_Stub_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Warning_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Error_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Debug_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Comment_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(If_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(For_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Each_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(While_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Return_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Content_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Extension_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Definition_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Mixin_Call_Ptr x) { return static_cast(this)->fallback(x); } + T operator()(Block_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Ruleset_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Bubble_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Trace_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Supports_Block_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Media_Block_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(At_Root_Block_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Directive_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Keyframe_Rule_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Declaration_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Assignment_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Import_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Import_Stub_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Warning_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Error_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Debug_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Comment_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(If_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(For_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Each_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(While_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Return_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Content_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Extension_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Definition_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Mixin_Call_Ptr x) + { + return static_cast(this)->fallback(x); + } // expressions - T operator()(List_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Map_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Binary_Expression_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Unary_Expression_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Function_Call_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Function_Call_Schema_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Custom_Warning_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Custom_Error_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Variable_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Number_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Color_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Boolean_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(String_Schema_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(String_Constant_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(String_Quoted_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Supports_Condition_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Supports_Operator_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Supports_Negation_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Supports_Declaration_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Supports_Interpolation_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Media_Query_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Media_Query_Expression_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(At_Root_Query_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Null_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Parent_Selector_Ptr x) { return static_cast(this)->fallback(x); } + T operator()(List_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Map_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Binary_Expression_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Unary_Expression_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Function_Call_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Function_Call_Schema_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Custom_Warning_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Custom_Error_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Variable_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Number_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Color_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Boolean_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(String_Schema_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(String_Constant_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(String_Quoted_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Supports_Condition_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Supports_Operator_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Supports_Negation_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Supports_Declaration_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Supports_Interpolation_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Media_Query_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Media_Query_Expression_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(At_Root_Query_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Null_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Parent_Selector_Ptr x) + { + return static_cast(this)->fallback(x); + } // parameters and arguments - T operator()(Parameter_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Parameters_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Argument_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Arguments_Ptr x) { return static_cast(this)->fallback(x); } + T operator()(Parameter_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Parameters_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Argument_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Arguments_Ptr x) + { + return static_cast(this)->fallback(x); + } // selectors - T operator()(Selector_Schema_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Placeholder_Selector_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Element_Selector_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Class_Selector_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Id_Selector_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Attribute_Selector_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Pseudo_Selector_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Wrapped_Selector_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Compound_Selector_Ptr x){ return static_cast(this)->fallback(x); } - T operator()(Complex_Selector_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Selector_List_Ptr x) { return static_cast(this)->fallback(x); } + T operator()(Selector_Schema_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Placeholder_Selector_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Element_Selector_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Class_Selector_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Id_Selector_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Attribute_Selector_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Pseudo_Selector_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Wrapped_Selector_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Compound_Selector_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Complex_Selector_Ptr x) + { + return static_cast(this)->fallback(x); + } + T operator()(Selector_List_Ptr x) + { + return static_cast(this)->fallback(x); + } - template - T fallback(U x) { return T(); } + template T fallback(U x) + { + return T(); + } }; - } #endif diff --git a/src/output.cpp b/src/output.cpp index 0ba43332ef..f4bc2eb707 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -2,15 +2,16 @@ #include "ast.hpp" #include "output.hpp" -namespace Sass { +namespace Sass +{ - Output::Output(Sass_Output_Options& opt) - : Inspect(Emitter(opt)), - charset(""), - top_nodes(0) - {} + Output::Output(Sass_Output_Options& opt) : Inspect(Emitter(opt)), charset(""), top_nodes(0) + { + } - Output::~Output() { } + Output::~Output() + { + } void Output::fallback_impl(AST_Node_Ptr n) { @@ -23,7 +24,8 @@ namespace Sass { std::string res = n->to_string(opt); // check for a valid unit here // includes result for reporting - if (!n->is_valid_css_unit()) { + if (!n->is_valid_css_unit()) + { throw Exception::InvalidValue(*n); } // output the final token @@ -48,7 +50,8 @@ namespace Sass { Inspect inspect(emitter); size_t size_nodes = top_nodes.size(); - for (size_t i = 0; i < size_nodes; i++) { + for (size_t i = 0; i < size_nodes; i++) + { top_nodes[i]->perform(&inspect); inspect.append_mandatory_linefeed(); } @@ -59,21 +62,23 @@ namespace Sass { // prepend buffer on top prepend_output(inspect.output()); // make sure we end with a linefeed - if (!ends_with(wbuf.buffer, opt.linefeed)) { + if (!ends_with(wbuf.buffer, opt.linefeed)) + { // if the output is not completely empty if (!wbuf.buffer.empty()) append_string(opt.linefeed); } // search for unicode char - for(const char& chr : wbuf.buffer) { + for (const char& chr : wbuf.buffer) + { // skip all ascii chars // static cast to unsigned to handle `char` being signed / unsigned if (static_cast(chr) < 128) continue; // declare the charset if (output_style() != COMPRESSED) - charset = "@charset \"UTF-8\";" - + std::string(opt.linefeed); - else charset = "\xEF\xBB\xBF"; + charset = "@charset \"UTF-8\";" + std::string(opt.linefeed); + else + charset = "\xEF\xBB\xBF"; // abort search break; } @@ -82,7 +87,6 @@ namespace Sass { if (!charset.empty()) prepend_string(charset); return wbuf; - } void Output::operator()(Comment_Ptr c) @@ -90,17 +94,24 @@ namespace Sass { std::string txt = c->text()->to_string(opt); // if (indentation && txt == "/**/") return; bool important = c->is_important(); - if (output_style() != COMPRESSED || important) { - if (buffer().size() == 0) { + if (output_style() != COMPRESSED || important) + { + if (buffer().size() == 0) + { top_nodes.push_back(c); - } else { + } + else + { in_comment = true; append_indentation(); c->text()->perform(this); in_comment = false; - if (indentation == 0) { + if (indentation == 0) + { append_mandatory_linefeed(); - } else { + } + else + { append_optional_linefeed(); } } @@ -109,15 +120,19 @@ namespace Sass { void Output::operator()(Ruleset_Ptr r) { - Selector_Obj s = r->selector(); - Block_Obj b = r->block(); + Selector_Obj s = r->selector(); + Block_Obj b = r->block(); // Filter out rulesets that aren't printable (process its children though) - if (!Util::isPrintable(r, output_style())) { - for (size_t i = 0, L = b->length(); i < L; ++i) { + if (!Util::isPrintable(r, output_style())) + { + for (size_t i = 0, L = b->length(); i < L; ++i) + { const Statement_Obj& stm = b->at(i); - if (Cast(stm)) { - if (!Cast(stm)) { + if (Cast(stm)) + { + if (!Cast(stm)) + { stm->perform(this); } } @@ -126,7 +141,8 @@ namespace Sass { } if (output_style() == NESTED) indentation += r->tabs(); - if (opt.source_comments) { + if (opt.source_comments) + { std::stringstream ss; append_indentation(); std::string path(File::abs2rel(r->pstate().path)); @@ -136,22 +152,29 @@ namespace Sass { } if (s) s->perform(this); append_scope_opener(b); - for (size_t i = 0, L = b->length(); i < L; ++i) { + for (size_t i = 0, L = b->length(); i < L; ++i) + { Statement_Obj stm = b->at(i); bool bPrintExpression = true; // Check print conditions - if (Declaration_Ptr dec = Cast(stm)) { - if (String_Constant_Ptr valConst = Cast(dec->value())) { + if (Declaration_Ptr dec = Cast(stm)) + { + if (String_Constant_Ptr valConst = Cast(dec->value())) + { std::string val(valConst->value()); - if (String_Quoted_Ptr qstr = Cast(valConst)) { - if (!qstr->quote_mark() && val.empty()) { + if (String_Quoted_Ptr qstr = Cast(valConst)) + { + if (!qstr->quote_mark() && val.empty()) + { bPrintExpression = false; } } } - else if (List_Ptr list = Cast(dec->value())) { + else if (List_Ptr list = Cast(dec->value())) + { bool all_invisible = true; - for (size_t list_i = 0, list_L = list->length(); list_i < list_L; ++list_i) { + for (size_t list_i = 0, list_L = list->length(); list_i < list_L; ++list_i) + { Expression_Ptr item = list->at(list_i); if (!item->is_invisible()) all_invisible = false; } @@ -159,30 +182,33 @@ namespace Sass { } } // Print if OK - if (bPrintExpression) { + if (bPrintExpression) + { stm->perform(this); } } if (output_style() == NESTED) indentation -= r->tabs(); append_scope_closer(b); - } void Output::operator()(Keyframe_Rule_Ptr r) { Block_Obj b = r->block(); Selector_Obj v = r->name(); - if (!v.isNull()) { + if (!v.isNull()) + { v->perform(this); } - if (!b) { + if (!b) + { append_colon_separator(); return; } append_scope_opener(); - for (size_t i = 0, L = b->length(); i < L; ++i) { + for (size_t i = 0, L = b->length(); i < L; ++i) + { Statement_Obj stm = b->at(i); stm->perform(this); if (i < L - 1) append_special_linefeed(); @@ -195,13 +221,16 @@ namespace Sass { if (f->is_invisible()) return; Supports_Condition_Obj c = f->condition(); - Block_Obj b = f->block(); + Block_Obj b = f->block(); // Filter out feature blocks that aren't printable (process its children though) - if (!Util::isPrintable(f, output_style())) { - for (size_t i = 0, L = b->length(); i < L; ++i) { + if (!Util::isPrintable(f, output_style())) + { + for (size_t i = 0, L = b->length(); i < L; ++i) + { Statement_Obj stm = b->at(i); - if (Cast(stm)) { + if (Cast(stm)) + { stm->perform(this); } } @@ -215,7 +244,8 @@ namespace Sass { c->perform(this); append_scope_opener(); - for (size_t i = 0, L = b->length(); i < L; ++i) { + for (size_t i = 0, L = b->length(); i < L; ++i) + { Statement_Obj stm = b->at(i); stm->perform(this); if (i < L - 1) append_special_linefeed(); @@ -224,20 +254,22 @@ namespace Sass { if (output_style() == NESTED) indentation -= f->tabs(); append_scope_closer(); - } void Output::operator()(Media_Block_Ptr m) { if (m->is_invisible()) return; - Block_Obj b = m->block(); + Block_Obj b = m->block(); // Filter out media blocks that aren't printable (process its children though) - if (!Util::isPrintable(m, output_style())) { - for (size_t i = 0, L = b->length(); i < L; ++i) { + if (!Util::isPrintable(m, output_style())) + { + for (size_t i = 0, L = b->length(); i < L; ++i) + { Statement_Obj stm = b->at(i); - if (Cast(stm)) { + if (Cast(stm)) + { stm->perform(this); } } @@ -252,9 +284,11 @@ namespace Sass { in_media_block = false; append_scope_opener(); - for (size_t i = 0, L = b->length(); i < L; ++i) { - if (b->at(i)) { - Statement_Obj stm = b->at(i); + for (size_t i = 0, L = b->length(); i < L; ++i) + { + if (b->at(i)) + { + Statement_Obj stm = b->at(i); stm->perform(this); } if (i < L - 1) append_special_linefeed(); @@ -266,39 +300,45 @@ namespace Sass { void Output::operator()(Directive_Ptr a) { - std::string kwd = a->keyword(); - Selector_Obj s = a->selector(); - Expression_Obj v = a->value(); - Block_Obj b = a->block(); + std::string kwd = a->keyword(); + Selector_Obj s = a->selector(); + Expression_Obj v = a->value(); + Block_Obj b = a->block(); append_indentation(); append_token(kwd, a); - if (s) { + if (s) + { append_mandatory_space(); in_wrapped = true; s->perform(this); in_wrapped = false; } - if (v) { + if (v) + { append_mandatory_space(); // ruby sass bug? should use options? append_token(v->to_string(/* opt */), v); } - if (!b) { + if (!b) + { append_delimiter(); return; } - if (b->is_invisible() || b->length() == 0) { + if (b->is_invisible() || b->length() == 0) + { append_optional_space(); return append_string("{}"); } append_scope_opener(); - bool format = kwd != "@font-face";; + bool format = kwd != "@font-face"; + ; - for (size_t i = 0, L = b->length(); i < L; ++i) { + for (size_t i = 0, L = b->length(); i < L; ++i) + { Statement_Obj stm = b->at(i); stm->perform(this); if (i < L - 1 && format) append_special_linefeed(); @@ -309,11 +349,16 @@ namespace Sass { void Output::operator()(String_Quoted_Ptr s) { - if (s->quote_mark()) { + if (s->quote_mark()) + { append_token(quote(s->value(), s->quote_mark()), s); - } else if (!in_comment) { + } + else if (!in_comment) + { append_token(string_to_output(s->value()), s); - } else { + } + else + { append_token(s->value(), s); } } @@ -321,14 +366,17 @@ namespace Sass { void Output::operator()(String_Constant_Ptr s) { std::string value(s->value()); - if (s->can_compress_whitespace() && output_style() == COMPRESSED) { + if (s->can_compress_whitespace() && output_style() == COMPRESSED) + { value.erase(std::remove_if(value.begin(), value.end(), ::isspace), value.end()); } - if (!in_comment) { + if (!in_comment) + { append_token(string_to_output(value), s); - } else { + } + else + { append_token(value, s); } } - } diff --git a/src/output.hpp b/src/output.hpp index c460b13fef..2afa37b9b9 100644 --- a/src/output.hpp +++ b/src/output.hpp @@ -8,29 +8,31 @@ #include "inspect.hpp" #include "operation.hpp" -namespace Sass { +namespace Sass +{ class Context; // Refactor to make it generic to find linefeed (look behind) - inline bool ends_with(std::string const & value, std::string const & ending) + inline bool ends_with(std::string const& value, std::string const& ending) { if (ending.size() > value.size()) return false; return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); } - class Output : public Inspect { - protected: + class Output : public Inspect + { + protected: using Inspect::operator(); - public: + public: Output(Sass_Output_Options& opt); virtual ~Output(); - protected: + protected: std::string charset; std::vector top_nodes; - public: + public: OutputBuffer get_buffer(void); virtual void operator()(Map_Ptr); @@ -46,9 +48,7 @@ namespace Sass { virtual void operator()(String_Constant_Ptr); void fallback_impl(AST_Node_Ptr n); - }; - } #endif diff --git a/src/parser.cpp b/src/parser.cpp index d464813959..b0e6b0bd81 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -26,7 +26,8 @@ #include #include -namespace Sass { +namespace Sass +{ using namespace Constants; using namespace Prelexer; @@ -35,9 +36,9 @@ namespace Sass { pstate.offset.column = 0; pstate.offset.line = 0; Parser p(ctx, pstate); - p.source = source ? source : beg; + p.source = source ? source : beg; p.position = beg ? beg : p.source; - p.end = p.position + strlen(p.position); + p.end = p.position + strlen(p.position); Block_Obj root = SASS_MEMORY_NEW(Block, pstate); p.block_stack.push_back(root); root->is_root(true); @@ -49,22 +50,23 @@ namespace Sass { pstate.offset.column = 0; pstate.offset.line = 0; Parser p(ctx, pstate); - p.source = source ? source : beg; + p.source = source ? source : beg; p.position = beg ? beg : p.source; - p.end = end ? end : p.position + strlen(p.position); + p.end = end ? end : p.position + strlen(p.position); Block_Obj root = SASS_MEMORY_NEW(Block, pstate); p.block_stack.push_back(root); root->is_root(true); return p; } - void Parser::advanceToNextToken() { - lex < css_comments >(false); - // advance to position - pstate += pstate.offset; - pstate.offset.column = 0; - pstate.offset.line = 0; - } + void Parser::advanceToNextToken() + { + lex(false); + // advance to position + pstate += pstate.offset; + pstate.offset.column = 0; + pstate.offset.line = 0; + } Selector_List_Obj Parser::parse_selector(const char* beg, Context& ctx, ParserState pstate, const char* source) { @@ -76,16 +78,15 @@ namespace Sass { bool Parser::peek_newline(const char* start) { - return peek_linefeed(start ? start : position) - && ! peek_css>(start); + return peek_linefeed(start ? start : position) && !peek_css>(start); } Parser Parser::from_token(Token t, Context& ctx, ParserState pstate, const char* source) { Parser p(ctx, pstate); - p.source = source ? source : t.begin; + p.source = source ? source : t.begin; p.position = t.begin ? t.begin : p.source; - p.end = t.end ? t.end : p.position + strlen(p.position); + p.end = t.end ? t.end : p.position + strlen(p.position); Block_Obj root = SASS_MEMORY_NEW(Block, pstate); p.block_stack.push_back(root); root->is_root(true); @@ -103,7 +104,8 @@ namespace Sass { Block_Obj root = SASS_MEMORY_NEW(Block, pstate, 0, true); // check seems a bit esoteric but works - if (ctx.resources.size() == 1) { + if (ctx.resources.size() == 1) + { // apply headers only on very first include ctx.apply_custom_headers(root, path, pstate); } @@ -116,7 +118,8 @@ namespace Sass { // update final position root->update_pstate(pstate); - if (position != end) { + if (position != end) + { css_error("Invalid CSS", " after ", ": expected selector or at-rule, was "); } @@ -134,7 +137,8 @@ namespace Sass { // lex < optional_css_comments >(); // lex mandatory opener or error out - if (!lex_css < exactly<'{'> >()) { + if (!lex_css>()) + { css_error("Invalid CSS", " after ", ": expected \"{\", was "); } // create new block and push to the selector stack @@ -143,7 +147,8 @@ namespace Sass { if (!parse_block_nodes(is_root)) css_error("Invalid CSS", " after ", ": expected \"}\", was "); - if (!lex_css < exactly<'}'> >()) { + if (!lex_css>()) + { css_error("Invalid CSS", " after ", ": expected \"}\", was "); } @@ -174,23 +179,24 @@ namespace Sass { { // loop until end of string - while (position < end) { + while (position < end) + { // we should be able to refactor this parse_block_comments(); - lex < css_whitespace >(); + lex(); - if (lex < exactly<';'> >()) continue; - if (peek < end_of_file >()) return true; - if (peek < exactly<'}'> >()) return true; + if (lex>()) continue; + if (peek()) return true; + if (peek>()) return true; if (parse_block_node(is_root)) continue; parse_block_comments(); - if (lex_css < exactly<';'> >()) continue; - if (peek_css < end_of_file >()) return true; - if (peek_css < exactly<'}'> >()) return true; + if (lex_css>()) continue; + if (peek_css()) return true; + if (peek_css>()) return true; // illegal sass return false; @@ -201,7 +207,8 @@ namespace Sass { // parser for a single node in a block // semicolons must be lexed beforehand - bool Parser::parse_block_node(bool is_root) { + bool Parser::parse_block_node(bool is_root) + { Block_Obj block = block_stack.back(); @@ -209,28 +216,58 @@ namespace Sass { // throw away white-space // includes line comments - lex < css_whitespace >(); + lex(); Lookahead lookahead_result; // also parse block comments // first parse everything that is allowed in functions - if (lex < variable >(true)) { block->append(parse_assignment()); } - else if (lex < kwd_err >(true)) { block->append(parse_error()); } - else if (lex < kwd_dbg >(true)) { block->append(parse_debug()); } - else if (lex < kwd_warn >(true)) { block->append(parse_warning()); } - else if (lex < kwd_if_directive >(true)) { block->append(parse_if_directive()); } - else if (lex < kwd_for_directive >(true)) { block->append(parse_for_directive()); } - else if (lex < kwd_each_directive >(true)) { block->append(parse_each_directive()); } - else if (lex < kwd_while_directive >(true)) { block->append(parse_while_directive()); } - else if (lex < kwd_return_directive >(true)) { block->append(parse_return_directive()); } + if (lex(true)) + { + block->append(parse_assignment()); + } + else if (lex(true)) + { + block->append(parse_error()); + } + else if (lex(true)) + { + block->append(parse_debug()); + } + else if (lex(true)) + { + block->append(parse_warning()); + } + else if (lex(true)) + { + block->append(parse_if_directive()); + } + else if (lex(true)) + { + block->append(parse_for_directive()); + } + else if (lex(true)) + { + block->append(parse_each_directive()); + } + else if (lex(true)) + { + block->append(parse_while_directive()); + } + else if (lex(true)) + { + block->append(parse_return_directive()); + } // parse imports to process later - else if (lex < kwd_import >(true)) { + else if (lex(true)) + { Scope parent = stack.empty() ? Scope::Rules : stack.back(); - if (parent != Scope::Function && parent != Scope::Root && parent != Scope::Rules && parent != Scope::Media) { - if (! peek_css< uri_prefix >(position)) { // this seems to go in ruby sass 3.4.20 + if (parent != Scope::Function && parent != Scope::Root && parent != Scope::Rules && parent != Scope::Media) + { + if (!peek_css(position)) + { // this seems to go in ruby sass 3.4.20 error("Import directives may not be used within control directives or mixins.", pstate); } } @@ -240,19 +277,23 @@ namespace Sass { // if it is a url, we only add the statement if (!imp->urls().empty()) block->append(imp); // process all resources now (add Import_Stub nodes) - for (size_t i = 0, S = imp->incs().size(); i < S; ++i) { + for (size_t i = 0, S = imp->incs().size(); i < S; ++i) + { block->append(SASS_MEMORY_NEW(Import_Stub, pstate, imp->incs()[i])); } } - else if (lex < kwd_extend >(true)) { + else if (lex(true)) + { Lookahead lookahead = lookahead_for_include(position); if (!lookahead.found) css_error("Invalid CSS", " after ", ": expected selector, was "); Selector_List_Obj target; - if (!lookahead.has_interpolants) { + if (!lookahead.has_interpolants) + { target = parse_selector_list(true); } - else { + else + { target = SASS_MEMORY_NEW(Selector_List, pstate); target->schema(parse_selector_schema(lookahead.found, true)); } @@ -262,27 +303,63 @@ namespace Sass { // selector may contain interpolations which need delayed evaluation else if (!(lookahead_result = lookahead_for_selector(position)).error) - { block->append(parse_ruleset(lookahead_result)); } + { + block->append(parse_ruleset(lookahead_result)); + } // parse multiple specific keyword directives - else if (lex < kwd_media >(true)) { block->append(parse_media_block()); } - else if (lex < kwd_at_root >(true)) { block->append(parse_at_root_block()); } - else if (lex < kwd_include_directive >(true)) { block->append(parse_include_directive()); } - else if (lex < kwd_content_directive >(true)) { block->append(parse_content_directive()); } - else if (lex < kwd_supports_directive >(true)) { block->append(parse_supports_directive()); } - else if (lex < kwd_mixin >(true)) { block->append(parse_definition(Definition::MIXIN)); } - else if (lex < kwd_function >(true)) { block->append(parse_definition(Definition::FUNCTION)); } + else if (lex(true)) + { + block->append(parse_media_block()); + } + else if (lex(true)) + { + block->append(parse_at_root_block()); + } + else if (lex(true)) + { + block->append(parse_include_directive()); + } + else if (lex(true)) + { + block->append(parse_content_directive()); + } + else if (lex(true)) + { + block->append(parse_supports_directive()); + } + else if (lex(true)) + { + block->append(parse_definition(Definition::MIXIN)); + } + else if (lex(true)) + { + block->append(parse_definition(Definition::FUNCTION)); + } // ignore the @charset directive for now - else if (lex< kwd_charset_directive >(true)) { parse_charset_directive(); } + else if (lex(true)) + { + parse_charset_directive(); + } // generic at keyword (keep last) - else if (lex< re_special_directive >(true)) { block->append(parse_special_directive()); } - else if (lex< re_prefixed_directive >(true)) { block->append(parse_prefixed_directive()); } - else if (lex< at_keyword >(true)) { block->append(parse_directive()); } + else if (lex(true)) + { + block->append(parse_special_directive()); + } + else if (lex(true)) + { + block->append(parse_prefixed_directive()); + } + else if (lex(true)) + { + block->append(parse_directive()); + } - else if (is_root /* && block->is_root() */) { - lex< css_whitespace >(); + else if (is_root /* && block->is_root() */) + { + lex(); if (position >= end) return true; css_error("Invalid CSS", " after ", ": expected 1 selector or at-rule, was "); } @@ -295,13 +372,14 @@ namespace Sass { decl->tabs(indentation); block->append(decl); // maybe we have a "sub-block" - if (peek< exactly<'{'> >()) { - if (decl->is_indented()) ++ indentation; + if (peek>()) + { + if (decl->is_indented()) ++indentation; // parse a propset that rides on the declaration's property stack.push_back(Scope::Properties); decl->block(parse_block()); stack.pop_back(); - if (decl->is_indented()) -- indentation; + if (decl->is_indented()) --indentation; } } // something matched @@ -313,52 +391,67 @@ namespace Sass { Import_Obj Parser::parse_import() { Import_Obj imp = SASS_MEMORY_NEW(Import, pstate); - std::vector> to_import; + std::vector> to_import; bool first = true; - do { - while (lex< block_comment >()); - if (lex< quoted_string >()) { - to_import.push_back(std::pair(std::string(lexed), 0)); + do + { + while (lex()) + ; + if (lex()) + { + to_import.push_back(std::pair(std::string(lexed), 0)); } - else if (lex< uri_prefix >()) { + else if (lex()) + { Arguments_Obj args = SASS_MEMORY_NEW(Arguments, pstate); Function_Call_Obj result = SASS_MEMORY_NEW(Function_Call, pstate, "url", args); - if (lex< quoted_string >()) { + if (lex()) + { Expression_Obj quoted_url = parse_string(); args->append(SASS_MEMORY_NEW(Argument, quoted_url->pstate(), quoted_url)); } - else if (String_Obj string_url = parse_url_function_argument()) { + else if (String_Obj string_url = parse_url_function_argument()) + { args->append(SASS_MEMORY_NEW(Argument, string_url->pstate(), string_url)); } - else if (peek < skip_over_scopes < exactly < '(' >, exactly < ')' > > >(position)) { + else if (peek, exactly<')'>>>(position)) + { Expression_Obj braced_url = parse_list(); // parse_interpolated_chunk(lexed); args->append(SASS_MEMORY_NEW(Argument, braced_url->pstate(), braced_url)); } - else { + else + { error("malformed URL", pstate); } - if (!lex< exactly<')'> >()) error("URI is missing ')'", pstate); + if (!lex>()) error("URI is missing ')'", pstate); to_import.push_back(std::pair("", result)); } - else { - if (first) error("@import directive requires a url or quoted path", pstate); - else error("expecting another url or quoted path in @import list", pstate); + else + { + if (first) + error("@import directive requires a url or quoted path", pstate); + else + error("expecting another url or quoted path in @import list", pstate); } first = false; - } while (lex_css< exactly<','> >()); + } while (lex_css>()); - if (!peek_css< alternatives< exactly<';'>, exactly<'}'>, end_of_file > >()) { + if (!peek_css, exactly<'}'>, end_of_file>>()) + { List_Obj import_queries = parse_media_queries(); imp->import_queries(import_queries); } - for(auto location : to_import) { - if (location.second) { + for (auto location : to_import) + { + if (location.second) + { imp->urls().push_back(location.second); } // check if custom importers want to take over the handling - else if (!ctx.call_importers(unquote(location.first), path, pstate, imp)) { + else if (!ctx.call_importers(unquote(location.first), path, pstate, imp)) + { // nobody wants it, so we do our import ctx.import_url(imp, location.first, path); } @@ -370,14 +463,18 @@ namespace Sass { Definition_Obj Parser::parse_definition(Definition::Type which_type) { std::string which_str(lexed); - if (!lex< identifier >()) error("invalid name in " + which_str + " definition", pstate); + if (!lex()) error("invalid name in " + which_str + " definition", pstate); std::string name(Util::normalize_underscores(lexed)); if (which_type == Definition::FUNCTION && (name == "and" || name == "or" || name == "not")) - { error("Invalid function name \"" + name + "\".", pstate); } + { + error("Invalid function name \"" + name + "\".", pstate); + } ParserState source_position_of_def = pstate; Parameters_Obj params = parse_parameters(); - if (which_type == Definition::MIXIN) stack.push_back(Scope::Mixin); - else stack.push_back(Scope::Function); + if (which_type == Definition::MIXIN) + stack.push_back(Scope::Mixin); + else + stack.push_back(Scope::Function); Block_Obj body = parse_block(); stack.pop_back(); return SASS_MEMORY_NEW(Definition, source_position_of_def, name, params, body, which_type); @@ -386,15 +483,19 @@ namespace Sass { Parameters_Obj Parser::parse_parameters() { Parameters_Obj params = SASS_MEMORY_NEW(Parameters, pstate); - if (lex_css< exactly<'('> >()) { + if (lex_css>()) + { // if there's anything there at all - if (!peek_css< exactly<')'> >()) { - do { - if (peek< exactly<')'> >()) break; + if (!peek_css>()) + { + do + { + if (peek>()) break; params->append(parse_parameter()); - } while (lex_css< exactly<','> >()); + } while (lex_css>()); } - if (!lex_css< exactly<')'> >()) { + if (!lex_css>()) + { css_error("Invalid CSS", " after ", ": expected \")\", was "); } } @@ -403,21 +504,27 @@ namespace Sass { Parameter_Obj Parser::parse_parameter() { - if (peek< alternatives< exactly<','>, exactly< '{' >, exactly<';'> > >()) { + if (peek, exactly<'{'>, exactly<';'>>>()) + { css_error("Invalid CSS", " after ", ": expected variable (e.g. $foo), was "); } - while (lex< alternatives < spaces, block_comment > >()); - lex < variable >(); + while (lex>()) + ; + lex(); std::string name(Util::normalize_underscores(lexed)); ParserState pos = pstate; Expression_Obj val; bool is_rest = false; - while (lex< alternatives < spaces, block_comment > >()); - if (lex< exactly<':'> >()) { // there's a default value - while (lex< block_comment >()); + while (lex>()) + ; + if (lex>()) + { // there's a default value + while (lex()) + ; val = parse_space_list(); } - else if (lex< exactly< ellipsis > >()) { + else if (lex>()) + { is_rest = true; } return SASS_MEMORY_NEW(Parameter, pos, name, val, is_rest); @@ -426,15 +533,19 @@ namespace Sass { Arguments_Obj Parser::parse_arguments() { Arguments_Obj args = SASS_MEMORY_NEW(Arguments, pstate); - if (lex_css< exactly<'('> >()) { + if (lex_css>()) + { // if there's anything there at all - if (!peek_css< exactly<')'> >()) { - do { - if (peek< exactly<')'> >()) break; + if (!peek_css>()) + { + do + { + if (peek>()) break; args->append(parse_argument()); - } while (lex_css< exactly<','> >()); + } while (lex_css>()); } - if (!lex_css< exactly<')'> >()) { + if (!lex_css>()) + { css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was "); } } @@ -443,33 +554,38 @@ namespace Sass { Argument_Obj Parser::parse_argument() { - if (peek< alternatives< exactly<','>, exactly< '{' >, exactly<';'> > >()) { + if (peek, exactly<'{'>, exactly<';'>>>()) + { css_error("Invalid CSS", " after ", ": expected \")\", was "); } - if (peek_css< sequence < exactly< hash_lbrace >, exactly< rbrace > > >()) { + if (peek_css, exactly>>()) + { position += 2; css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was "); } Argument_Obj arg; - if (peek_css< sequence < variable, optional_css_comments, exactly<':'> > >()) { - lex_css< variable >(); + if (peek_css>>()) + { + lex_css(); std::string name(Util::normalize_underscores(lexed)); ParserState p = pstate; - lex_css< exactly<':'> >(); + lex_css>(); Expression_Obj val = parse_space_list(); arg = SASS_MEMORY_NEW(Argument, p, val, name); } - else { + else + { bool is_arglist = false; bool is_keyword = false; Expression_Obj val = parse_space_list(); List_Ptr l = Cast(val); - if (lex_css< exactly< ellipsis > >()) { - if (val->concrete_type() == Expression::MAP || ( - (l != NULL && l->separator() == SASS_HASH) - )) is_keyword = true; - else is_arglist = true; + if (lex_css>()) + { + if (val->concrete_type() == Expression::MAP || ((l != NULL && l->separator() == SASS_HASH))) + is_keyword = true; + else + is_arglist = true; } arg = SASS_MEMORY_NEW(Argument, pstate, val, "", is_arglist, is_keyword); } @@ -480,22 +596,30 @@ namespace Sass { { std::string name(Util::normalize_underscores(lexed)); ParserState var_source_position = pstate; - if (!lex< exactly<':'> >()) error("expected ':' after " + name + " in assignment statement", pstate); - if (peek_css< alternatives < exactly<';'>, end_of_file > >()) { + if (!lex>()) + error("expected ':' after " + name + " in assignment statement", pstate); + if (peek_css, end_of_file>>()) + { css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was "); } Expression_Obj val; Lookahead lookahead = lookahead_for_value(position); - if (lookahead.has_interpolants && lookahead.found) { + if (lookahead.has_interpolants && lookahead.found) + { val = parse_value_schema(lookahead.found); - } else { + } + else + { val = parse_list(); } bool is_default = false; bool is_global = false; - while (peek< alternatives < default_flag, global_flag > >()) { - if (lex< default_flag >()) is_default = true; - else if (lex< global_flag >()) is_global = true; + while (peek>()) + { + if (lex()) + is_default = true; + else if (lex()) + is_global = true; } return SASS_MEMORY_NEW(Assignment, var_source_position, name, val, is_default, is_global); } @@ -507,12 +631,14 @@ namespace Sass { Block_Obj parent = block_stack.back(); bool is_root = parent && parent->is_root(); // make sure to move up the the last position - lex < optional_css_whitespace >(false, true); + lex(false, true); // create the connector object (add parts later) Ruleset_Obj ruleset = SASS_MEMORY_NEW(Ruleset, pstate); // parse selector static or as schema to be evaluated later - if (lookahead.parsable) ruleset->selector(parse_selector_list(false)); - else { + if (lookahead.parsable) + ruleset->selector(parse_selector_list(false)); + else + { Selector_List_Obj list = SASS_MEMORY_NEW(Selector_List, pstate); list->schema(parse_selector_schema(lookahead.found, false)); ruleset->selector(list); @@ -536,7 +662,7 @@ namespace Sass { Selector_Schema_Obj Parser::parse_selector_schema(const char* end_of_selector, bool chroot) { // move up to the start - lex< optional_spaces >(); + lex(); const char* i = position; // selector schema re-uses string schema implementation String_Schema_Ptr schema = SASS_MEMORY_NEW(String_Schema, pstate); @@ -546,11 +672,14 @@ namespace Sass { selector_schema->media_block(last_media_block); // process until end - while (i < end_of_selector) { + while (i < end_of_selector) + { // try to parse mutliple interpolants - if (const char* p = find_first_in_interval< exactly, block_comment >(i, end_of_selector)) { + if (const char* p = find_first_in_interval, block_comment>(i, end_of_selector)) + { // accumulate the preceding segment if the position has advanced - if (i < p) { + if (i < p) + { std::string parsed(i, p); String_Constant_Obj str = SASS_MEMORY_NEW(String_Constant, pstate, parsed); pstate += Offset(parsed); @@ -559,29 +688,33 @@ namespace Sass { } // check if the interpolation only contains white-space (error out) - if (peek < sequence < optional_spaces, exactly > >(p+2)) { position = p+2; + if (peek>>(p + 2)) + { + position = p + 2; css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was "); } // skip over all nested inner interpolations up to our own delimiter - const char* j = skip_over_scopes< exactly, exactly >(p + 2, end_of_selector); + const char* j = skip_over_scopes, exactly>(p + 2, end_of_selector); // pass inner expression to the parser to resolve nested interpolations - pstate.add(p, p+2); - Expression_Obj interpolant = Parser::from_c_str(p+2, j, ctx, pstate).parse_list(); + pstate.add(p, p + 2); + Expression_Obj interpolant = Parser::from_c_str(p + 2, j, ctx, pstate).parse_list(); // set status on the list expression interpolant->is_interpolant(true); // schema->has_interpolants(true); // add to the string schema schema->append(interpolant); // advance parser state - pstate.add(p+2, j); + pstate.add(p + 2, j); // advance position i = j; } // no more interpolants have been found // add the last segment if there is one - else { + else + { // make sure to add the last bits of the string up to the end (if any) - if (i < end_of_selector) { + if (i < end_of_selector) + { std::string parsed(i, end_of_selector); String_Constant_Obj str = SASS_MEMORY_NEW(String_Constant, pstate, parsed); pstate += Offset(parsed); @@ -610,13 +743,7 @@ namespace Sass { void Parser::parse_charset_directive() { - lex < - sequence < - quoted_string, - optional_spaces, - exactly <';'> - > - >(); + lex>>(); } // called after parsing `kwd_include_directive` @@ -631,7 +758,8 @@ namespace Sass { // parse mandatory arguments call->arguments(parse_arguments()); // parse optional block - if (peek < exactly <'{'> >()) { + if (peek>()) + { call->block(parse_block()); } // return ast node @@ -649,16 +777,18 @@ namespace Sass { Selector_List_Obj group = SASS_MEMORY_NEW(Selector_List, pstate); group->media_block(last_media_block); - if (peek_css< alternatives < end_of_file, exactly <'{'> > >()) { + if (peek_css>>()) + { css_error("Invalid CSS", " after ", ": expected selector, was "); } - do { + do + { reloop = false; had_linefeed = had_linefeed || peek_newline(); - if (peek_css< alternatives < class_char < selector_list_delims > > >()) + if (peek_css>>()) break; // in case there are superfluous commas at the end // now parse the complex selector @@ -670,19 +800,19 @@ namespace Sass { had_linefeed = false; - while (peek_css< exactly<','> >()) + while (peek_css>()) { - lex< css_comments >(false); + lex(false); // consume everything up and including the comma separator - reloop = lex< exactly<','> >() != 0; + reloop = lex>() != 0; // remember line break (also between some commas) had_linefeed = had_linefeed || peek_newline(); // remember line break (also between some commas) } group->append(sel); - } - while (reloop); - while (lex_css< kwd_optional >()) { + } while (reloop); + while (lex_css()) + { group->is_optional(true); } // update for end position @@ -700,16 +830,17 @@ namespace Sass { { String_Obj reference = 0; - lex < block_comment >(); + lex(); advanceToNextToken(); Complex_Selector_Obj sel = SASS_MEMORY_NEW(Complex_Selector, pstate); - if (peek < end_of_file >()) return 0; + if (peek()) return 0; // parse the left hand side Compound_Selector_Obj lhs; // special case if it starts with combinator ([+~>]) - if (!peek_css< class_char < selector_combinator_ops > >()) { + if (!peek_css>()) + { // parse the left hand side lhs = parse_compound_selector(); } @@ -717,15 +848,19 @@ namespace Sass { // parse combinator between lhs and rhs Complex_Selector::Combinator combinator = Complex_Selector::ANCESTOR_OF; - if (lex< exactly<'+'> >()) combinator = Complex_Selector::ADJACENT_TO; - else if (lex< exactly<'~'> >()) combinator = Complex_Selector::PRECEDES; - else if (lex< exactly<'>'> >()) combinator = Complex_Selector::PARENT_OF; - else if (lex< sequence < exactly<'/'>, negate < exactly < '*' > > > >()) { + if (lex>()) + combinator = Complex_Selector::ADJACENT_TO; + else if (lex>()) + combinator = Complex_Selector::PRECEDES; + else if (lex'>>()) + combinator = Complex_Selector::PARENT_OF; + else if (lex, negate>>>()) + { // comments are allowed, but not spaces? combinator = Complex_Selector::REFERENCE; - if (!lex < re_reference_combinator >()) return 0; + if (!lex()) return 0; reference = SASS_MEMORY_NEW(String_Constant, pstate, lexed); - if (!lex < exactly < '/' > >()) return 0; // ToDo: error msg? + if (!lex>()) return 0; // ToDo: error msg? } if (!lhs && combinator == Complex_Selector::ANCESTOR_OF) return 0; @@ -741,14 +876,16 @@ namespace Sass { // sel->has_line_feed(has_line_feed); // check if we got the abort condition (ToDo: optimize) - if (!peek_css< class_char < complex_selector_delims > >()) { + if (!peek_css>()) + { // parse next selector in sequence sel->tail(parse_complex_selector(true)); } // add a parent selector if we are not in a root // also skip adding parent ref if we only have refs - if (!sel->has_parent_ref() && !chroot) { + if (!sel->has_parent_ref() && !chroot) + { // create the objects to wrap parent selector reference Compound_Selector_Obj head = SASS_MEMORY_NEW(Compound_Selector, pstate); Parent_Selector_Ptr parent = SASS_MEMORY_NEW(Parent_Selector, pstate, false); @@ -757,9 +894,13 @@ namespace Sass { // add simple selector head->append(parent); // selector may not have any head yet - if (!sel->head()) { sel->head(head); } + if (!sel->head()) + { + sel->head(head); + } // otherwise we need to create a new complex selector and set the old one as its tail - else { + else + { sel = SASS_MEMORY_NEW(Complex_Selector, pstate, Complex_Selector::ANCESTOR_OF, head, sel); sel->media_block(last_media_block); } @@ -783,93 +924,115 @@ namespace Sass { seq->media_block(last_media_block); // skip initial white-space - lex< css_whitespace >(); + lex(); // parse list while (true) { // remove all block comments (don't skip white-space) - lex< delimited_by< slash_star, star_slash, false > >(false); + lex>(false); // parse functional - if (match < re_pseudo_selector >()) + if (match()) { seq->append(parse_simple_selector()); } // parse parent selector - else if (lex< exactly<'&'> >(false)) + else if (lex>(false)) { // this produces a linefeed!? seq->has_parent_reference(true); seq->append(SASS_MEMORY_NEW(Parent_Selector, pstate)); // parent selector only allowed at start // upcoming Sass may allow also trailing - if (seq->length() > 1) { + if (seq->length() > 1) + { ParserState state(pstate); - Simple_Selector_Obj cur = (*seq)[seq->length()-1]; - Simple_Selector_Obj prev = (*seq)[seq->length()-2]; + Simple_Selector_Obj cur = (*seq)[seq->length() - 1]; + Simple_Selector_Obj prev = (*seq)[seq->length() - 2]; std::string sel(prev->to_string({ NESTED, 5 })); std::string found(cur->to_string({ NESTED, 5 })); - if (lex < identifier >()) { found += std::string(lexed); } + if (lex()) + { + found += std::string(lexed); + } error("Invalid CSS after \"" + sel + "\": expected \"{\", was \"" + found + "\"\n\n" - "\"" + found + "\" may only be used at the beginning of a compound selector.", state); + "\"" + + found + "\" may only be used at the beginning of a compound selector.", + state); } } // parse type selector - else if (lex< re_type_selector >(false)) + else if (lex(false)) { seq->append(SASS_MEMORY_NEW(Element_Selector, pstate, lexed)); } // peek for abort conditions - else if (peek< spaces >()) break; - else if (peek< end_of_file >()) { break; } - else if (peek_css < class_char < selector_combinator_ops > >()) break; - else if (peek_css < class_char < complex_selector_delims > >()) break; + else if (peek()) + break; + else if (peek()) + { + break; + } + else if (peek_css>()) + break; + else if (peek_css>()) + break; // otherwise parse another simple selector - else { + else + { Simple_Selector_Obj sel = parse_simple_selector(); if (!sel) return 0; seq->append(sel); } } - if (seq && !peek_css>>()) { + if (seq && !peek_css>>()) + { seq->has_line_break(peek_newline()); } // EO while true return seq; - } // EO parse_compound_selector Simple_Selector_Obj Parser::parse_simple_selector() { - lex < css_comments >(false); - if (lex< class_name >()) { + lex(false); + if (lex()) + { return SASS_MEMORY_NEW(Class_Selector, pstate, lexed); } - else if (lex< id_name >()) { + else if (lex()) + { return SASS_MEMORY_NEW(Id_Selector, pstate, lexed); } - else if (lex< quoted_string >()) { + else if (lex()) + { return SASS_MEMORY_NEW(Element_Selector, pstate, unquote(lexed)); } - else if (lex< alternatives < variable, number, static_reference_combinator > >()) { + else if (lex>()) + { return SASS_MEMORY_NEW(Element_Selector, pstate, lexed); } - else if (peek< pseudo_not >()) { + else if (peek()) + { return parse_negated_selector(); } - else if (peek< re_pseudo_selector >()) { + else if (peek()) + { return parse_pseudo_selector(); } - else if (peek< exactly<':'> >()) { + else if (peek>()) + { return parse_pseudo_selector(); } - else if (lex < exactly<'['> >()) { + else if (lex>()) + { return parse_attribute_selector(); } - else if (lex< placeholder >()) { + else if (lex()) + { Placeholder_Selector_Ptr sel = SASS_MEMORY_NEW(Placeholder_Selector, pstate, lexed); sel->media_block(last_media_block); return sel; @@ -880,11 +1043,12 @@ namespace Sass { Wrapped_Selector_Obj Parser::parse_negated_selector() { - lex< pseudo_not >(); + lex(); std::string name(lexed); ParserState nsource_position = pstate; Selector_List_Obj negated = parse_selector_list(true); - if (!lex< exactly<')'> >()) { + if (!lex>()) + { error("negated selector is missing ')'", pstate); } name.erase(name.size() - 1); @@ -893,14 +1057,13 @@ namespace Sass { // a pseudo selector often starts with one or two colons // it can contain more selectors inside parentheses - Simple_Selector_Obj Parser::parse_pseudo_selector() { - if (lex< sequence< - optional < pseudo_prefix >, - // we keep the space within the name, strange enough - // ToDo: refactor output to schedule the space for it - // or do we really want to keep the real white-space? - sequence< identifier, optional < block_comment >, exactly<'('> > - > >()) + Simple_Selector_Obj Parser::parse_pseudo_selector() + { + if (lex, + // we keep the space within the name, strange enough + // ToDo: refactor output to schedule the space for it + // or do we really want to keep the real white-space? + sequence, exactly<'('>>>>()) { std::string name(lexed); @@ -909,37 +1072,32 @@ namespace Sass { // specially parse static stuff // ToDo: really everything static? - if (peek_css < - sequence < - alternatives < - static_value, - binomial - >, - optional_css_whitespace, - exactly<')'> - > - >() - ) { - lex_css< alternatives < static_value, binomial > >(); + if (peek_css, optional_css_whitespace, exactly<')'>>>()) + { + lex_css>(); String_Constant_Obj expr = SASS_MEMORY_NEW(String_Constant, pstate, lexed); - if (lex_css< exactly<')'> >()) { + if (lex_css>()) + { expr->can_compress_whitespace(true); return SASS_MEMORY_NEW(Pseudo_Selector, p, name, expr); } } - else if (Selector_List_Obj wrapped = parse_selector_list(true)) { - if (wrapped && lex_css< exactly<')'> >()) { + else if (Selector_List_Obj wrapped = parse_selector_list(true)) + { + if (wrapped && lex_css>()) + { return SASS_MEMORY_NEW(Wrapped_Selector, p, name, wrapped); } } - } // EO if pseudo selector - else if (lex < sequence< optional < pseudo_prefix >, identifier > >()) { + else if (lex, identifier>>()) + { return SASS_MEMORY_NEW(Pseudo_Selector, pstate, lexed); } - else if(lex < pseudo_prefix >()) { + else if (lex()) + { css_error("Invalid CSS", " after ", ": expected pseudoclass or pseudoelement, was "); } @@ -952,27 +1110,32 @@ namespace Sass { Attribute_Selector_Obj Parser::parse_attribute_selector() { ParserState p = pstate; - if (!lex_css< attribute_name >()) error("invalid attribute name in attribute selector", pstate); + if (!lex_css()) error("invalid attribute name in attribute selector", pstate); std::string name(lexed); - if (lex_css< alternatives < exactly<']'>, exactly<'/'> > >()) return SASS_MEMORY_NEW(Attribute_Selector, p, name, "", 0); - if (!lex_css< alternatives< exact_match, class_match, dash_match, - prefix_match, suffix_match, substring_match > >()) { + if (lex_css, exactly<'/'>>>()) + return SASS_MEMORY_NEW(Attribute_Selector, p, name, "", 0); + if (!lex_css>()) + { error("invalid operator in attribute selector for " + name, pstate); } std::string matcher(lexed); String_Obj value = 0; - if (lex_css< identifier >()) { + if (lex_css()) + { value = SASS_MEMORY_NEW(String_Constant, p, lexed); } - else if (lex_css< quoted_string >()) { + else if (lex_css()) + { value = parse_interpolated_chunk(lexed, true); // needed! } - else { + else + { error("expected a string constant or identifier in attribute selector for " + name, pstate); } - if (!lex_css< alternatives < exactly<']'>, exactly<'/'> > >()) error("unterminated attribute selector for " + name, pstate); + if (!lex_css, exactly<'/'>>>()) + error("unterminated attribute selector for " + name, pstate); return SASS_MEMORY_NEW(Attribute_Selector, p, name, matcher, value); } @@ -981,7 +1144,8 @@ namespace Sass { { Block_Obj block = block_stack.back(); - while (lex< block_comment >()) { + while (lex()) + { bool is_important = lexed.begin[2] == '!'; // flag on second param is to skip loosely over comments String_Obj contents = parse_interpolated_chunk(lexed, true); @@ -989,46 +1153,61 @@ namespace Sass { } } - Declaration_Obj Parser::parse_declaration() { + Declaration_Obj Parser::parse_declaration() + { String_Obj prop; - if (lex< sequence< optional< exactly<'*'> >, identifier_schema > >()) { + if (lex>, identifier_schema>>()) + { prop = parse_identifier_schema(); } - else if (lex< sequence< optional< exactly<'*'> >, identifier, zero_plus< block_comment > > >()) { + else if (lex>, identifier, zero_plus>>()) + { prop = SASS_MEMORY_NEW(String_Constant, pstate, lexed); } - else { + else + { css_error("Invalid CSS", " after ", ": expected \"}\", was "); } bool is_indented = true; const std::string property(lexed); - if (!lex_css< one_plus< exactly<':'> > >()) error("property \"" + property + "\" must be followed by a ':'", pstate); - lex < css_comments >(false); - if (peek_css< exactly<';'> >()) error("style declaration must contain a value", pstate); - if (peek_css< exactly<'{'> >()) is_indented = false; // don't indent if value is empty - if (peek_css< static_value >()) { - return SASS_MEMORY_NEW(Declaration, prop->pstate(), prop, parse_static_value()/*, lex()*/); - } - else { + if (!lex_css>>()) + error("property \"" + property + "\" must be followed by a ':'", pstate); + lex(false); + if (peek_css>()) error("style declaration must contain a value", pstate); + if (peek_css>()) is_indented = false; // don't indent if value is empty + if (peek_css()) + { + return SASS_MEMORY_NEW(Declaration, prop->pstate(), prop, parse_static_value() /*, lex()*/); + } + else + { Expression_Obj value; Lookahead lookahead = lookahead_for_value(position); - if (lookahead.found) { - if (lookahead.has_interpolants) { + if (lookahead.found) + { + if (lookahead.has_interpolants) + { value = parse_value_schema(lookahead.found); - } else { + } + else + { value = parse_list(DELAYED); } } - else { + else + { value = parse_list(DELAYED); - if (List_Ptr list = Cast(value)) { - if (!list->is_bracketed() && list->length() == 0 && !peek< exactly <'{'> >()) { + if (List_Ptr list = Cast(value)) + { + if (!list->is_bracketed() && list->length() == 0 && !peek>()) + { css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was "); } } } - lex < css_comments >(false); - Declaration_Obj decl = SASS_MEMORY_NEW(Declaration, prop->pstate(), prop, value/*, lex()*/); + lex(false); + Declaration_Obj decl = + SASS_MEMORY_NEW(Declaration, prop->pstate(), prop, value /*, lex()*/); decl->is_indented(is_indented); decl->update_pstate(pstate); return decl; @@ -1040,10 +1219,12 @@ namespace Sass { bool Parser::parse_number_prefix() { bool positive = true; - while(true) { - if (lex < block_comment >()) continue; - if (lex < number_prefix >()) continue; - if (lex < exactly < '-' > >()) { + while (true) + { + if (lex()) continue; + if (lex()) continue; + if (lex>()) + { positive = !positive; continue; } @@ -1058,24 +1239,30 @@ namespace Sass { List_Obj map = SASS_MEMORY_NEW(List, pstate, 0, SASS_HASH); // it's not a map so return the lexed value as a list value - if (!lex_css< exactly<':'> >()) - { return key; } + if (!lex_css>()) + { + return key; + } Expression_Obj value = parse_space_list(); map->append(key); map->append(value); - while (lex_css< exactly<','> >()) + while (lex_css>()) { // allow trailing commas - #495 - if (peek_css< exactly<')'> >(position)) - { break; } + if (peek_css>(position)) + { + break; + } key = parse_space_list(); - if (!(lex< exactly<':'> >())) - { css_error("Invalid CSS", " after ", ": expected \":\", was "); } + if (!(lex>())) + { + css_error("Invalid CSS", " after ", ": expected \":\", was "); + } value = parse_space_list(); @@ -1094,20 +1281,22 @@ namespace Sass { { // check if we have an empty list // return the empty list as such - if (peek_css< list_terminator >(position)) + if (peek_css(position)) { // return an empty list (nothing to delay) return SASS_MEMORY_NEW(List, pstate, 0, SASS_SPACE, false, true); } - bool has_paren = peek_css< exactly<'('> >() != NULL; + bool has_paren = peek_css>() != NULL; // now try to parse a space list Expression_Obj list = parse_space_list(); // if it's a singleton, return it (don't wrap it) - if (!peek_css< exactly<','> >(position)) { + if (!peek_css>(position)) + { List_Obj l = Cast(list); - if (!l || l->is_bracketed() || has_paren) { + if (!l || l->is_bracketed() || has_paren) + { List_Obj bracketed_list = SASS_MEMORY_NEW(List, pstate, 1, SASS_SPACE, false, true); bracketed_list->append(list); return bracketed_list; @@ -1121,11 +1310,13 @@ namespace Sass { // wrap the first expression bracketed_list->append(list); - while (lex_css< exactly<','> >()) + while (lex_css>()) { // check for abort condition - if (peek_css< list_terminator >(position) - ) { break; } + if (peek_css(position)) + { + break; + } // otherwise add another expression bracketed_list->append(parse_space_list()); } @@ -1146,7 +1337,7 @@ namespace Sass { { // check if we have an empty list // return the empty list as such - if (peek_css< list_terminator >(position)) + if (peek_css(position)) { // return an empty list (nothing to delay) return SASS_MEMORY_NEW(List, pstate, 0); @@ -1155,7 +1346,8 @@ namespace Sass { // now try to parse a space list Expression_Obj list = parse_space_list(); // if it's a singleton, return it (don't wrap it) - if (!peek_css< exactly<','> >(position)) { + if (!peek_css>(position)) + { // set_delay doesn't apply to list children // so this will only undelay single values if (!delayed) list->set_delayed(false); @@ -1167,11 +1359,13 @@ namespace Sass { // wrap the first expression comma_list->append(list); - while (lex_css< exactly<','> >()) + while (lex_css>()) { // check for abort condition - if (peek_css< list_terminator >(position) - ) { break; } + if (peek_css(position)) + { + break; + } // otherwise add another expression comma_list->append(parse_space_list()); } @@ -1185,17 +1379,16 @@ namespace Sass { { Expression_Obj disj1 = parse_disjunction(); // if it's a singleton, return it (don't wrap it) - if (peek_css< space_list_terminator >(position) - ) { - return disj1; } + if (peek_css(position)) + { + return disj1; + } List_Obj space_list = SASS_MEMORY_NEW(List, pstate, 2, SASS_SPACE); space_list->append(disj1); - while ( - !(peek_css< space_list_terminator >(position)) && - peek_css< optional_css_whitespace >() != end - ) { + while (!(peek_css(position)) && peek_css() != end) + { // the space is parsed implicitly? space_list->append(parse_disjunction()); } @@ -1213,7 +1406,7 @@ namespace Sass { Expression_Obj conj = parse_conjunction(); // parse multiple right hand sides std::vector operands; - while (lex_css< kwd_or >()) + while (lex_css()) operands.push_back(parse_conjunction()); // if it's a singleton, return it directly if (operands.size() == 0) return conj; @@ -1234,7 +1427,8 @@ namespace Sass { Expression_Obj rel = parse_relation(); // parse multiple right hand sides std::vector operands; - while (lex_css< kwd_and >()) { + while (lex_css()) + { operands.push_back(parse_relation()); } // if it's a singleton, return it directly @@ -1257,29 +1451,26 @@ namespace Sass { std::vector operands; std::vector operators; // if it's a singleton, return it (don't wrap it) - while (peek< alternatives < - kwd_eq, - kwd_neq, - kwd_gte, - kwd_gt, - kwd_lte, - kwd_lt - > >(position)) + while (peek>(position)) { // is directly adjancent to expression? - bool left_ws = peek < css_comments >() != NULL; + bool left_ws = peek() != NULL; // parse the operator - enum Sass_OP op - = lex() ? Sass_OP::EQ - : lex() ? Sass_OP::NEQ - : lex() ? Sass_OP::GTE - : lex() ? Sass_OP::LTE - : lex() ? Sass_OP::GT - : lex() ? Sass_OP::LT - // we checked the possibilities on top of fn - : Sass_OP::EQ; + enum Sass_OP op = lex() ? + Sass_OP::EQ : + lex() ? + Sass_OP::NEQ : + lex() ? + Sass_OP::GTE : + lex() ? + Sass_OP::LTE : + lex() ? Sass_OP::GT : + lex() ? Sass_OP::LT + // we checked the possibilities on top of fn + : + Sass_OP::EQ; // is directly adjacent to expression? - bool right_ws = peek < css_comments >() != NULL; + bool right_ws = peek() != NULL; operators.push_back({ op, left_ws, right_ws }); operands.push_back(parse_expression()); } @@ -1309,30 +1500,31 @@ namespace Sass { // NOTE: dashes do NOT count as subtract operation Expression_Obj lhs = parse_operators(); // if it's a singleton, return it (don't wrap it) - if (!(peek_css< exactly<'+'> >(position) || - // condition is a bit misterious, but some combinations should not be counted as operations - (peek< no_spaces >(position) && peek< sequence< negate< unsigned_number >, exactly<'-'>, negate< space > > >(position)) || - (peek< sequence< negate< unsigned_number >, exactly<'-'>, negate< unsigned_number > > >(position))) || - peek< sequence < zero_plus < exactly <'-' > >, identifier > >(position)) - { return lhs; } + if (!( + peek_css>(position) || + // condition is a bit misterious, but some combinations should not be counted as operations + (peek(position) && peek, exactly<'-'>, negate>>(position)) || + (peek, exactly<'-'>, negate>>(position))) || + peek>, identifier>>(position)) + { + return lhs; + } std::vector operands; std::vector operators; - bool left_ws = peek < css_comments >() != NULL; - while ( - lex_css< exactly<'+'> >() || + bool left_ws = peek() != NULL; + while (lex_css>() || - ( - ! peek_css< sequence < zero_plus < exactly <'-' > >, identifier > >(position) - && lex_css< sequence< negate< digit >, exactly<'-'> > >() - ) + (!peek_css>, identifier>>(position) && + lex_css, exactly<'-'>>>()) - ) { + ) + { - bool right_ws = peek < css_comments >() != NULL; + bool right_ws = peek() != NULL; operators.push_back({ lexed.to_string() == "+" ? Sass_OP::ADD : Sass_OP::SUB, left_ws, right_ws }); operands.push_back(parse_operators()); - left_ws = peek < css_comments >() != NULL; + left_ws = peek() != NULL; } if (operands.size() == 0) return lhs; @@ -1352,17 +1544,26 @@ namespace Sass { std::vector operands; // factors std::vector operators; // ops // lex operations to apply to lhs - const char* left_ws = peek < css_comments >(); - while (lex_css< class_char< static_ops > >()) { - const char* right_ws = peek < css_comments >(); - switch(*lexed.begin) { - case '*': operators.push_back({ Sass_OP::MUL, left_ws != 0, right_ws != 0 }); break; - case '/': operators.push_back({ Sass_OP::DIV, left_ws != 0, right_ws != 0 }); break; - case '%': operators.push_back({ Sass_OP::MOD, left_ws != 0, right_ws != 0 }); break; - default: throw std::runtime_error("unknown static op parsed"); + const char* left_ws = peek(); + while (lex_css>()) + { + const char* right_ws = peek(); + switch (*lexed.begin) + { + case '*': + operators.push_back({ Sass_OP::MUL, left_ws != 0, right_ws != 0 }); + break; + case '/': + operators.push_back({ Sass_OP::DIV, left_ws != 0, right_ws != 0 }); + break; + case '%': + operators.push_back({ Sass_OP::MOD, left_ws != 0, right_ws != 0 }); + break; + default: + throw std::runtime_error("unknown static op parsed"); } operands.push_back(parse_factor()); - left_ws = peek < css_comments >(); + left_ws = peek(); } // operands and operators to binary expression Expression_Obj ex = fold_operands(factor, operands, operators); @@ -1377,77 +1578,97 @@ namespace Sass { // called from parse_value_schema Expression_Obj Parser::parse_factor() { - lex < css_comments >(false); - if (lex_css< exactly<'('> >()) { + lex(false); + if (lex_css>()) + { // parse_map may return a list Expression_Obj value = parse_map(); // lex the expected closing parenthesis - if (!lex_css< exactly<')'> >()) error("unclosed parenthesis", pstate); + if (!lex_css>()) error("unclosed parenthesis", pstate); // expression can be evaluated return value; } - else if (lex_css< exactly<'['> >()) { + else if (lex_css>()) + { // explicit bracketed Expression_Obj value = parse_bracket_list(); // lex the expected closing square bracket - if (!lex_css< exactly<']'> >()) error("unclosed squared bracket", pstate); + if (!lex_css>()) error("unclosed squared bracket", pstate); return value; } // string may be interpolated // if (lex< quoted_string >()) { // return &parse_string(); // } - else if (peek< ie_property >()) { + else if (peek()) + { return parse_ie_property(); } - else if (peek< ie_keyword_arg >()) { + else if (peek()) + { return parse_ie_keyword_arg(); } - else if (peek< sequence < calc_fn_call, exactly <'('> > >()) { + else if (peek>>()) + { return parse_calc_function(); } - else if (lex < functional_schema >()) { + else if (lex()) + { return parse_function_call_schema(); } - else if (lex< identifier_schema >()) { + else if (lex()) + { String_Obj string = parse_identifier_schema(); - if (String_Schema_Ptr schema = Cast(string)) { - if (lex < exactly < '(' > >()) { + if (String_Schema_Ptr schema = Cast(string)) + { + if (lex>()) + { schema->append(parse_list()); - lex < exactly < ')' > >(); + lex>(); } } return string; } - else if (peek< sequence< uri_prefix, W, real_uri_value > >()) { + else if (peek>()) + { return parse_url_function_string(); } - else if (peek< re_functional >()) { + else if (peek()) + { return parse_function_call(); } - else if (lex< exactly<'+'> >()) { - Unary_Expression_Ptr ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::PLUS, parse_factor()); + else if (lex>()) + { + Unary_Expression_Ptr ex = + SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::PLUS, parse_factor()); if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed()); return ex; } - else if (lex< exactly<'-'> >()) { - Unary_Expression_Ptr ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::MINUS, parse_factor()); + else if (lex>()) + { + Unary_Expression_Ptr ex = + SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::MINUS, parse_factor()); if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed()); return ex; } - else if (lex< sequence< kwd_not > >()) { - Unary_Expression_Ptr ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::NOT, parse_factor()); + else if (lex>()) + { + Unary_Expression_Ptr ex = + SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::NOT, parse_factor()); if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed()); return ex; } // this whole branch is never hit via spec tests - else if (peek < sequence < one_plus < alternatives < css_whitespace, exactly<'-'>, exactly<'+'> > >, number > >()) { + else if (peek, exactly<'+'>>>, number>>()) + { if (parse_number_prefix()) return parse_value(); // prefix is positive - Unary_Expression_Ptr ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::MINUS, parse_value()); + Unary_Expression_Ptr ex = + SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::MINUS, parse_value()); if (ex->operand()) ex->is_delayed(ex->operand()->is_delayed()); return ex; } - else { + else + { return parse_value(); } } @@ -1455,19 +1676,13 @@ namespace Sass { bool number_has_zero(const std::string& parsed) { size_t L = parsed.length(); - return !( (L > 0 && parsed.substr(0, 1) == ".") || - (L > 1 && parsed.substr(0, 2) == "0.") || - (L > 1 && parsed.substr(0, 2) == "-.") || - (L > 2 && parsed.substr(0, 3) == "-0.") ); + return !((L > 0 && parsed.substr(0, 1) == ".") || (L > 1 && parsed.substr(0, 2) == "0.") || + (L > 1 && parsed.substr(0, 2) == "-.") || (L > 2 && parsed.substr(0, 3) == "-0.")); } Number_Ptr Parser::lexed_number(const ParserState& pstate, const std::string& parsed) { - Number_Ptr nr = SASS_MEMORY_NEW(Number, - pstate, - sass_atof(parsed.c_str()), - "", - number_has_zero(parsed)); + Number_Ptr nr = SASS_MEMORY_NEW(Number, pstate, sass_atof(parsed.c_str()), "", number_has_zero(parsed)); nr->is_interpolant(false); nr->is_delayed(true); return nr; @@ -1475,11 +1690,7 @@ namespace Sass { Number_Ptr Parser::lexed_percentage(const ParserState& pstate, const std::string& parsed) { - Number_Ptr nr = SASS_MEMORY_NEW(Number, - pstate, - sass_atof(parsed.c_str()), - "%", - true); + Number_Ptr nr = SASS_MEMORY_NEW(Number, pstate, sass_atof(parsed.c_str()), "%", true); nr->is_interpolant(false); nr->is_delayed(true); return nr; @@ -1493,11 +1704,8 @@ namespace Sass { size_t unit_pos = parsed.find_first_not_of("-+0123456789.", num_pos); if (unit_pos == std::string::npos) unit_pos = L; const std::string& num = parsed.substr(num_pos, unit_pos - num_pos); - Number_Ptr nr = SASS_MEMORY_NEW(Number, - pstate, - sass_atof(num.c_str()), - Token(number(parsed.c_str())), - number_has_zero(parsed)); + Number_Ptr nr = SASS_MEMORY_NEW(Number, pstate, sass_atof(num.c_str()), + Token(number(parsed.c_str())), number_has_zero(parsed)); nr->is_interpolant(false); nr->is_delayed(true); return nr; @@ -1506,47 +1714,44 @@ namespace Sass { Expression_Ptr Parser::lexed_hex_color(const ParserState& pstate, const std::string& parsed) { Color_Ptr color = NULL; - if (parsed[0] != '#') { + if (parsed[0] != '#') + { return SASS_MEMORY_NEW(String_Quoted, pstate, parsed); } // chop off the '#' std::string hext(parsed.substr(1)); - if (parsed.length() == 4) { + if (parsed.length() == 4) + { std::string r(2, parsed[1]); std::string g(2, parsed[2]); std::string b(2, parsed[3]); - color = SASS_MEMORY_NEW(Color, - pstate, - static_cast(strtol(r.c_str(), NULL, 16)), - static_cast(strtol(g.c_str(), NULL, 16)), - static_cast(strtol(b.c_str(), NULL, 16)), - 1, // alpha channel - parsed); - } - else if (parsed.length() == 7) { - std::string r(parsed.substr(1,2)); - std::string g(parsed.substr(3,2)); - std::string b(parsed.substr(5,2)); - color = SASS_MEMORY_NEW(Color, - pstate, - static_cast(strtol(r.c_str(), NULL, 16)), - static_cast(strtol(g.c_str(), NULL, 16)), - static_cast(strtol(b.c_str(), NULL, 16)), - 1, // alpha channel - parsed); - } - else if (parsed.length() == 9) { - std::string r(parsed.substr(1,2)); - std::string g(parsed.substr(3,2)); - std::string b(parsed.substr(5,2)); - std::string a(parsed.substr(7,2)); - color = SASS_MEMORY_NEW(Color, - pstate, - static_cast(strtol(r.c_str(), NULL, 16)), - static_cast(strtol(g.c_str(), NULL, 16)), - static_cast(strtol(b.c_str(), NULL, 16)), - static_cast(strtol(a.c_str(), NULL, 16)) / 255, - parsed); + color = SASS_MEMORY_NEW(Color, pstate, static_cast(strtol(r.c_str(), NULL, 16)), + static_cast(strtol(g.c_str(), NULL, 16)), + static_cast(strtol(b.c_str(), NULL, 16)), + 1, // alpha channel + parsed); + } + else if (parsed.length() == 7) + { + std::string r(parsed.substr(1, 2)); + std::string g(parsed.substr(3, 2)); + std::string b(parsed.substr(5, 2)); + color = SASS_MEMORY_NEW(Color, pstate, static_cast(strtol(r.c_str(), NULL, 16)), + static_cast(strtol(g.c_str(), NULL, 16)), + static_cast(strtol(b.c_str(), NULL, 16)), + 1, // alpha channel + parsed); + } + else if (parsed.length() == 9) + { + std::string r(parsed.substr(1, 2)); + std::string g(parsed.substr(3, 2)); + std::string b(parsed.substr(5, 2)); + std::string a(parsed.substr(7, 2)); + color = SASS_MEMORY_NEW(Color, pstate, static_cast(strtol(r.c_str(), NULL, 16)), + static_cast(strtol(g.c_str(), NULL, 16)), + static_cast(strtol(b.c_str(), NULL, 16)), + static_cast(strtol(a.c_str(), NULL, 16)) / 255, parsed); } color->is_interpolant(false); color->is_delayed(false); @@ -1556,72 +1761,109 @@ namespace Sass { // parse one value for a list Expression_Obj Parser::parse_value() { - lex< css_comments >(false); - if (lex< ampersand >()) + lex(false); + if (lex()) { - return SASS_MEMORY_NEW(Parent_Selector, pstate); } + return SASS_MEMORY_NEW(Parent_Selector, pstate); + } - if (lex< kwd_important >()) - { return SASS_MEMORY_NEW(String_Constant, pstate, "!important"); } + if (lex()) + { + return SASS_MEMORY_NEW(String_Constant, pstate, "!important"); + } // parse `10%4px` into separated items and not a schema - if (lex< sequence < percentage, lookahead < number > > >()) - { return lexed_percentage(lexed); } + if (lex>>()) + { + return lexed_percentage(lexed); + } - if (lex< sequence < number, lookahead< sequence < op, number > > > >()) - { return lexed_number(lexed); } + if (lex>>>()) + { + return lexed_number(lexed); + } // string may be interpolated - if (lex< sequence < quoted_string, lookahead < exactly <'-'> > > >()) - { return parse_string(); } + if (lex>>>()) + { + return parse_string(); + } - if (const char* stop = peek< value_schema >()) - { return parse_value_schema(stop); } + if (const char* stop = peek()) + { + return parse_value_schema(stop); + } // string may be interpolated - if (lex< quoted_string >()) - { return parse_string(); } + if (lex()) + { + return parse_string(); + } - if (lex< kwd_true >()) - { return SASS_MEMORY_NEW(Boolean, pstate, true); } + if (lex()) + { + return SASS_MEMORY_NEW(Boolean, pstate, true); + } - if (lex< kwd_false >()) - { return SASS_MEMORY_NEW(Boolean, pstate, false); } + if (lex()) + { + return SASS_MEMORY_NEW(Boolean, pstate, false); + } - if (lex< kwd_null >()) - { return SASS_MEMORY_NEW(Null, pstate); } + if (lex()) + { + return SASS_MEMORY_NEW(Null, pstate); + } - if (lex< identifier >()) { + if (lex()) + { return SASS_MEMORY_NEW(String_Constant, pstate, lexed); } - if (lex< percentage >()) - { return lexed_percentage(lexed); } + if (lex()) + { + return lexed_percentage(lexed); + } // match hex number first because 0x000 looks like a number followed by an identifier - if (lex< sequence < alternatives< hex, hex0 >, negate < exactly<'-'> > > >()) - { return lexed_hex_color(lexed); } + if (lex, negate>>>()) + { + return lexed_hex_color(lexed); + } - if (lex< sequence < exactly <'#'>, identifier > >()) - { return SASS_MEMORY_NEW(String_Quoted, pstate, lexed); } + if (lex, identifier>>()) + { + return SASS_MEMORY_NEW(String_Quoted, pstate, lexed); + } // also handle the 10em- foo special case - // alternatives < exactly < '.' >, .. > -- `1.5em-.75em` is split into a list, not a binary expression - if (lex< sequence< dimension, optional< sequence< exactly<'-'>, lookahead< alternatives < space > > > > > >()) - { return lexed_dimension(lexed); } + // alternatives < exactly < '.' >, .. > -- `1.5em-.75em` is split into a list, not a binary + // expression + if (lex, lookahead>>>>>()) + { + return lexed_dimension(lexed); + } - if (lex< sequence< static_component, one_plus< strict_identifier > > >()) - { return SASS_MEMORY_NEW(String_Constant, pstate, lexed); } + if (lex>>()) + { + return SASS_MEMORY_NEW(String_Constant, pstate, lexed); + } - if (lex< number >()) - { return lexed_number(lexed); } + if (lex()) + { + return lexed_number(lexed); + } - if (lex< variable >()) - { return SASS_MEMORY_NEW(Variable, pstate, Util::normalize_underscores(lexed)); } + if (lex()) + { + return SASS_MEMORY_NEW(Variable, pstate, Util::normalize_underscores(lexed)); + } // Special case handling for `%` proceeding an interpolant. - if (lex< sequence< exactly<'%'>, optional< percentage > > >()) - { return SASS_MEMORY_NEW(String_Constant, pstate, lexed); } + if (lex, optional>>()) + { + return SASS_MEMORY_NEW(String_Constant, pstate, lexed); + } css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was "); @@ -1635,10 +1877,11 @@ namespace Sass { { const char* i = chunk.begin; // see if there any interpolants - const char* p = constant ? find_first_in_interval< exactly >(i, chunk.end) : - find_first_in_interval< exactly, block_comment >(i, chunk.end); + const char* p = constant ? find_first_in_interval>(i, chunk.end) : + find_first_in_interval, block_comment>(i, chunk.end); - if (!p) { + if (!p) + { String_Quoted_Ptr str_quoted = SASS_MEMORY_NEW(String_Quoted, pstate, std::string(i, chunk.end)); if (!constant && str_quoted->quote_mark()) str_quoted->quote_mark('*'); return str_quoted; @@ -1646,38 +1889,48 @@ namespace Sass { String_Schema_Ptr schema = SASS_MEMORY_NEW(String_Schema, pstate); schema->is_interpolant(true); - while (i < chunk.end) { - p = constant ? find_first_in_interval< exactly >(i, chunk.end) : - find_first_in_interval< exactly, block_comment >(i, chunk.end); - if (p) { - if (i < p) { + while (i < chunk.end) + { + p = constant ? find_first_in_interval>(i, chunk.end) : + find_first_in_interval, block_comment>(i, chunk.end); + if (p) + { + if (i < p) + { // accumulate the preceding segment if it's nonempty schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(i, p))); } // we need to skip anything inside strings // create a new target in parser/prelexer - if (peek < sequence < optional_spaces, exactly > >(p+2)) { position = p+2; + if (peek>>(p + 2)) + { + position = p + 2; css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was "); } - const char* j = skip_over_scopes< exactly, exactly >(p + 2, chunk.end); // find the closing brace - if (j) { --j; + const char* j = skip_over_scopes, exactly>(p + 2, chunk.end); // find the closing brace + if (j) + { + --j; // parse the interpolant and accumulate it - Expression_Obj interp_node = Parser::from_token(Token(p+2, j), ctx, pstate, source).parse_list(); + Expression_Obj interp_node = Parser::from_token(Token(p + 2, j), ctx, pstate, source).parse_list(); interp_node->is_interpolant(true); schema->append(interp_node); i = j; } - else { + else + { // throw an error if the interpolant is unterminated error("unterminated interpolant inside string constant " + chunk.to_string(), pstate); } } - else { // no interpolants left; add the last segment if nonempty + else + { // no interpolants left; add the last segment if nonempty // check if we need quotes here (was not sure after merge) - if (i < chunk.end) schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(i, chunk.end))); + if (i < chunk.end) + schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(i, chunk.end))); break; } - ++ i; + ++i; } return schema; @@ -1685,11 +1938,11 @@ namespace Sass { String_Constant_Obj Parser::parse_static_value() { - lex< static_value >(); + lex(); Token str(lexed); // static values always have trailing white- // space and end delimiter (\s*[;]$) included - -- pstate.offset.column; + --pstate.offset.column; --str.end; --position; @@ -1704,40 +1957,52 @@ namespace Sass { String_Obj Parser::parse_ie_property() { - lex< ie_property >(); + lex(); Token str(lexed); const char* i = str.begin; // see if there any interpolants - const char* p = find_first_in_interval< exactly, block_comment >(str.begin, str.end); - if (!p) { + const char* p = find_first_in_interval, block_comment>(str.begin, str.end); + if (!p) + { return SASS_MEMORY_NEW(String_Quoted, pstate, std::string(str.begin, str.end)); } String_Schema_Ptr schema = SASS_MEMORY_NEW(String_Schema, pstate); - while (i < str.end) { - p = find_first_in_interval< exactly, block_comment >(i, str.end); - if (p) { - if (i < p) { - schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(i, p))); // accumulate the preceding segment if it's nonempty + while (i < str.end) + { + p = find_first_in_interval, block_comment>(i, str.end); + if (p) + { + if (i < p) + { + schema->append( + SASS_MEMORY_NEW(String_Constant, pstate, + std::string(i, p))); // accumulate the preceding segment if it's nonempty } - if (peek < sequence < optional_spaces, exactly > >(p+2)) { position = p+2; + if (peek>>(p + 2)) + { + position = p + 2; css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was "); } - const char* j = skip_over_scopes< exactly, exactly >(p+2, str.end); // find the closing brace - if (j) { + const char* j = skip_over_scopes, exactly>(p + 2, str.end); // find the closing brace + if (j) + { // parse the interpolant and accumulate it - Expression_Obj interp_node = Parser::from_token(Token(p+2, j), ctx, pstate, source).parse_list(); + Expression_Obj interp_node = Parser::from_token(Token(p + 2, j), ctx, pstate, source).parse_list(); interp_node->is_interpolant(true); schema->append(interp_node); i = j; } - else { + else + { // throw an error if the interpolant is unterminated error("unterminated interpolant inside IE function " + str.to_string(), pstate); } } - else { // no interpolants left; add the last segment if nonempty - if (i < str.end) { + else + { // no interpolants left; add the last segment if nonempty + if (i < str.end) + { schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(i, str.end))); } break; @@ -1749,21 +2014,29 @@ namespace Sass { String_Obj Parser::parse_ie_keyword_arg() { String_Schema_Ptr kwd_arg = SASS_MEMORY_NEW(String_Schema, pstate, 3); - if (lex< variable >()) { + if (lex()) + { kwd_arg->append(SASS_MEMORY_NEW(Variable, pstate, Util::normalize_underscores(lexed))); - } else { - lex< alternatives< identifier_schema, identifier > >(); + } + else + { + lex>(); kwd_arg->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed)); } - lex< exactly<'='> >(); + lex>(); kwd_arg->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed)); - if (peek< variable >()) kwd_arg->append(parse_list()); - else if (lex< number >()) { + if (peek()) + kwd_arg->append(parse_list()); + else if (lex()) + { std::string parsed(lexed); Util::normalize_decimals(parsed); kwd_arg->append(lexed_number(parsed)); } - else if (peek < ie_keyword_arg_value >()) { kwd_arg->append(parse_list()); } + else if (peek()) + { + kwd_arg->append(parse_list()); + } return kwd_arg; } @@ -1772,7 +2045,8 @@ namespace Sass { // initialize the string schema object to add tokens String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate); - if (peek>()) { + if (peek>()) + { css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was "); } @@ -1781,92 +2055,116 @@ namespace Sass { end = stop; size_t num_items = 0; bool need_space = false; - while (position < stop) { + while (position < stop) + { // parse space between tokens - if (lex< spaces >() && num_items) { + if (lex() && num_items) + { need_space = true; } - if (need_space) { + if (need_space) + { need_space = false; // schema->append(SASS_MEMORY_NEW(String_Constant, pstate, " ")); } - if ((e = peek< re_functional >()) && e < stop) { + if ((e = peek()) && e < stop) + { schema->append(parse_function_call()); } // lex an interpolant /#{...}/ - else if (lex< exactly < hash_lbrace > >()) { + else if (lex>()) + { // Try to lex static expression first - if (peek< exactly< rbrace > >()) { + if (peek>()) + { css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was "); } Expression_Obj ex; - if (lex< re_static_expression >()) { + if (lex()) + { ex = SASS_MEMORY_NEW(String_Constant, pstate, lexed); - } else { + } + else + { ex = parse_list(); } ex->is_interpolant(true); schema->append(ex); - if (!lex < exactly < rbrace > >()) { + if (!lex>()) + { css_error("Invalid CSS", " after ", ": expected \"}\", was "); } } // lex some string constants or other valid token // Note: [-+] chars are left over from i.e. `#{3}+3` - else if (lex< alternatives < exactly<'%'>, exactly < '-' >, exactly < '+' > > >()) { + else if (lex, exactly<'-'>, exactly<'+'>>>()) + { schema->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed)); } // lex a quoted string - else if (lex< quoted_string >()) { + else if (lex()) + { // need_space = true; // if (schema->length()) schema->append(SASS_MEMORY_NEW(String_Constant, pstate, " ")); // else need_space = true; schema->append(parse_string()); - if ((*position == '"' || *position == '\'') || peek < alternatives < alpha > >()) { + if ((*position == '"' || *position == '\'') || peek>()) + { // need_space = true; } - if (peek < exactly < '-' > >()) break; + if (peek>()) break; } - else if (lex< sequence < identifier > >()) { + else if (lex>()) + { schema->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed)); - if ((*position == '"' || *position == '\'') || peek < alternatives < alpha > >()) { - // need_space = true; + if ((*position == '"' || *position == '\'') || peek>()) + { + // need_space = true; } } // lex (normalized) variable - else if (lex< variable >()) { + else if (lex()) + { std::string name(Util::normalize_underscores(lexed)); schema->append(SASS_MEMORY_NEW(Variable, pstate, name)); } // lex percentage value - else if (lex< percentage >()) { + else if (lex()) + { schema->append(lexed_percentage(lexed)); } // lex dimension value - else if (lex< dimension >()) { + else if (lex()) + { schema->append(lexed_dimension(lexed)); } // lex number value - else if (lex< number >()) { + else if (lex()) + { schema->append(lexed_number(lexed)); } // lex hex color value - else if (lex< sequence < hex, negate < exactly < '-' > > > >()) { + else if (lex>>>()) + { schema->append(lexed_hex_color(lexed)); } - else if (lex< sequence < exactly <'#'>, identifier > >()) { + else if (lex, identifier>>()) + { schema->append(SASS_MEMORY_NEW(String_Quoted, pstate, lexed)); } // lex a value in parentheses - else if (peek< parenthese_scope >()) { + else if (peek()) + { schema->append(parse_factor()); } - else { + else + { break; } ++num_items; } - if (position != stop) { + if (position != stop) + { schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(position, stop))); position = stop; } @@ -1881,43 +2179,56 @@ namespace Sass { Token id(lexed); const char* i = id.begin; // see if there any interpolants - const char* p = find_first_in_interval< exactly, block_comment >(id.begin, id.end); - if (!p) { + const char* p = find_first_in_interval, block_comment>(id.begin, id.end); + if (!p) + { return SASS_MEMORY_NEW(String_Constant, pstate, std::string(id.begin, id.end)); } String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate); - while (i < id.end) { - p = find_first_in_interval< exactly, block_comment >(i, id.end); - if (p) { - if (i < p) { + while (i < id.end) + { + p = find_first_in_interval, block_comment>(i, id.end); + if (p) + { + if (i < p) + { // accumulate the preceding segment if it's nonempty - const char* o = position; position = i; + const char* o = position; + position = i; schema->append(parse_value_schema(p)); position = o; } // we need to skip anything inside strings // create a new target in parser/prelexer - if (peek < sequence < optional_spaces, exactly > >(p+2)) { position = p; + if (peek>>(p + 2)) + { + position = p; css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was "); } - const char* j = skip_over_scopes< exactly, exactly >(p+2, id.end); // find the closing brace - if (j) { + const char* j = skip_over_scopes, exactly>(p + 2, id.end); // find the closing brace + if (j) + { // parse the interpolant and accumulate it - Expression_Obj interp_node = Parser::from_token(Token(p+2, j), ctx, pstate, source).parse_list(DELAYED); + Expression_Obj interp_node = + Parser::from_token(Token(p + 2, j), ctx, pstate, source).parse_list(DELAYED); interp_node->is_interpolant(true); schema->append(interp_node); // schema->has_interpolants(true); i = j; } - else { + else + { // throw an error if the interpolant is unterminated error("unterminated interpolant inside interpolated identifier " + id.to_string(), pstate); } } - else { // no interpolants left; add the last segment if nonempty - if (i < end) { - const char* o = position; position = i; + else + { // no interpolants left; add the last segment if nonempty + if (i < end) + { + const char* o = position; + position = i; schema->append(parse_value_schema(id.end)); position = o; } @@ -1930,18 +2241,15 @@ namespace Sass { // calc functions should preserve arguments Function_Call_Obj Parser::parse_calc_function() { - lex< identifier >(); + lex(); std::string name(lexed); ParserState call_pos = pstate; - lex< exactly<'('> >(); + lex>(); ParserState arg_pos = pstate; const char* arg_beg = position; parse_list(); const char* arg_end = position; - lex< skip_over_scopes < - exactly < '(' >, - exactly < ')' > - > >(); + lex, exactly<')'>>>(); Argument_Obj arg = SASS_MEMORY_NEW(Argument, arg_pos, parse_interpolated_chunk(Token(arg_beg, arg_end))); Arguments_Obj args = SASS_MEMORY_NEW(Arguments, arg_pos); @@ -1952,30 +2260,36 @@ namespace Sass { String_Obj Parser::parse_url_function_string() { std::string prefix(""); - if (lex< uri_prefix >()) { + if (lex()) + { prefix = std::string(lexed); } - lex < optional_spaces >(); + lex(); String_Obj url_string = parse_url_function_argument(); std::string suffix(""); - if (lex< real_uri_suffix >()) { + if (lex()) + { suffix = std::string(lexed); } std::string uri(""); - if (url_string) { + if (url_string) + { uri = url_string->to_string({ NESTED, 5 }); } - if (String_Schema_Ptr schema = Cast(url_string)) { + if (String_Schema_Ptr schema = Cast(url_string)) + { String_Schema_Obj res = SASS_MEMORY_NEW(String_Schema, pstate); res->append(SASS_MEMORY_NEW(String_Constant, pstate, prefix)); res->append(schema); res->append(SASS_MEMORY_NEW(String_Constant, pstate, suffix)); return res; - } else { + } + else + { std::string res = prefix + uri + suffix; return SASS_MEMORY_NEW(String_Constant, pstate, res); } @@ -1986,20 +2300,24 @@ namespace Sass { const char* p = position; std::string uri(""); - if (lex< real_uri_value >(false)) { + if (lex(false)) + { uri = lexed.to_string(); } - if (peek< exactly< hash_lbrace > >()) { + if (peek>()) + { const char* pp = position; // TODO: error checking for unclosed interpolants - while (pp && peek< exactly< hash_lbrace > >(pp)) { - pp = sequence< interpolant, real_uri_value >(pp); + while (pp && peek>(pp)) + { + pp = sequence(pp); } position = pp; return parse_interpolated_chunk(Token(p, position)); } - else if (uri != "") { + else if (uri != "") + { std::string res = Util::rtrim(uri); return SASS_MEMORY_NEW(String_Constant, pstate, res); } @@ -2009,7 +2327,7 @@ namespace Sass { Function_Call_Obj Parser::parse_function_call() { - lex< identifier >(); + lex(); std::string name(lexed); ParserState call_pos = pstate; @@ -2042,11 +2360,13 @@ namespace Sass { // only throw away comment if we parse a case // we want all other comments to be parsed - if (lex_css< elseif_directive >()) { + if (lex_css()) + { alternative = SASS_MEMORY_NEW(Block, pstate); alternative->append(parse_if_directive(true)); } - else if (lex_css< kwd_else_directive >()) { + else if (lex_css()) + { alternative = parse_block(root); } stack.pop_back(); @@ -2060,12 +2380,15 @@ namespace Sass { bool root = block_stack.back()->is_root(); lex_variable(); std::string var(Util::normalize_underscores(lexed)); - if (!lex< kwd_from >()) error("expected 'from' keyword in @for directive", pstate); + if (!lex()) error("expected 'from' keyword in @for directive", pstate); Expression_Obj lower_bound = parse_expression(); bool inclusive = false; - if (lex< kwd_through >()) inclusive = true; - else if (lex< kwd_to >()) inclusive = false; - else error("expected 'through' or 'to' keyword in @for directive", pstate); + if (lex()) + inclusive = true; + else if (lex()) + inclusive = false; + else + error("expected 'through' or 'to' keyword in @for directive", pstate); Expression_Obj upper_bound = parse_expression(); Block_Obj body = parse_block(root); stack.pop_back(); @@ -2076,12 +2399,14 @@ namespace Sass { Token Parser::lex_variable() { // peek for dollar sign first - if (!peek< exactly <'$'> >()) { + if (!peek>()) + { css_error("Invalid CSS", " after ", ": expected \"$\", was "); } // we expect a simple identifier as the call name - if (!lex< sequence < exactly <'$'>, identifier > >()) { - lex< exactly <'$'> >(); // move pstate and position up + if (!lex, identifier>>()) + { + lex>(); // move pstate and position up css_error("Invalid CSS", " after ", ": expected identifier, was "); } // return object @@ -2091,7 +2416,8 @@ namespace Sass { Token Parser::lex_identifier() { // we expect a simple identifier as the call name - if (!lex< identifier >()) { // ToDo: pstate wrong? + if (!lex()) + { // ToDo: pstate wrong? css_error("Invalid CSS", " after ", ": expected identifier, was "); } // return object @@ -2106,11 +2432,12 @@ namespace Sass { std::vector vars; lex_variable(); vars.push_back(Util::normalize_underscores(lexed)); - while (lex< exactly<','> >()) { - if (!lex< variable >()) error("@each directive requires an iteration variable", pstate); + while (lex>()) + { + if (!lex()) error("@each directive requires an iteration variable", pstate); vars.push_back(Util::normalize_underscores(lexed)); } - if (!lex< kwd_in >()) error("expected 'in' keyword in @each directive", pstate); + if (!lex()) error("expected 'in' keyword in @each directive", pstate); Expression_Obj list = parse_list(); Block_Obj body = parse_block(root); stack.pop_back(); @@ -2155,8 +2482,9 @@ namespace Sass { { advanceToNextToken(); List_Obj queries = SASS_MEMORY_NEW(List, pstate, 0, SASS_COMMA); - if (!peek_css < exactly <'{'> >()) queries->append(parse_media_query()); - while (lex_css < exactly <','> >()) queries->append(parse_media_query()); + if (!peek_css>()) queries->append(parse_media_query()); + while (lex_css>()) + queries->append(parse_media_query()); queries->update_pstate(pstate); return queries.detach(); } @@ -2166,22 +2494,36 @@ namespace Sass { { advanceToNextToken(); Media_Query_Obj media_query = SASS_MEMORY_NEW(Media_Query, pstate); - if (lex < kwd_not >()) { media_query->is_negated(true); lex < css_comments >(false); } - else if (lex < kwd_only >()) { media_query->is_restricted(true); lex < css_comments >(false); } + if (lex()) + { + media_query->is_negated(true); + lex(false); + } + else if (lex()) + { + media_query->is_restricted(true); + lex(false); + } - if (lex < identifier_schema >()) media_query->media_type(parse_identifier_schema()); - else if (lex < identifier >()) media_query->media_type(parse_interpolated_chunk(lexed)); - else media_query->append(parse_media_expression()); + if (lex()) + media_query->media_type(parse_identifier_schema()); + else if (lex()) + media_query->media_type(parse_interpolated_chunk(lexed)); + else + media_query->append(parse_media_expression()); - while (lex_css < kwd_and >()) media_query->append(parse_media_expression()); - if (lex < identifier_schema >()) { + while (lex_css()) + media_query->append(parse_media_expression()); + if (lex()) + { String_Schema_Ptr schema = SASS_MEMORY_NEW(String_Schema, pstate); schema->append(media_query->media_type()); schema->append(SASS_MEMORY_NEW(String_Constant, pstate, " ")); schema->append(parse_identifier_schema()); media_query->media_type(schema); } - while (lex_css < kwd_and >()) media_query->append(parse_media_expression()); + while (lex_css()) + media_query->append(parse_media_expression()); media_query->update_pstate(pstate); @@ -2190,23 +2532,28 @@ namespace Sass { Media_Query_Expression_Obj Parser::parse_media_expression() { - if (lex < identifier_schema >()) { + if (lex()) + { String_Obj ss = parse_identifier_schema(); return SASS_MEMORY_NEW(Media_Query_Expression, pstate, ss, 0, true); } - if (!lex_css< exactly<'('> >()) { + if (!lex_css>()) + { error("media query expression must begin with '('", pstate); } Expression_Obj feature; - if (peek_css< exactly<')'> >()) { + if (peek_css>()) + { error("media feature required in media query expression", pstate); } feature = parse_expression(); Expression_Obj expression = 0; - if (lex_css< exactly<':'> >()) { + if (lex_css>()) + { expression = parse_list(DELAYED); } - if (!lex_css< exactly<')'> >()) { + if (!lex_css>()) + { error("unclosed parenthesis in media query expression", pstate); } return SASS_MEMORY_NEW(Media_Query_Expression, feature->pstate(), feature, expression); @@ -2230,7 +2577,7 @@ namespace Sass { // may encounter nested queries Supports_Condition_Obj Parser::parse_supports_condition() { - lex < css_whitespace >(); + lex(); Supports_Condition_Obj cond; if ((cond = parse_supports_negation())) return cond; if ((cond = parse_supports_operator())) return cond; @@ -2240,7 +2587,7 @@ namespace Sass { Supports_Condition_Obj Parser::parse_supports_negation() { - if (!lex < kwd_not >()) return 0; + if (!lex()) return 0; Supports_Condition_Obj cond = parse_supports_condition_in_parens(); return SASS_MEMORY_NEW(Supports_Negation, pstate, cond); } @@ -2250,15 +2597,23 @@ namespace Sass { Supports_Condition_Obj cond = parse_supports_condition_in_parens(); if (cond.isNull()) return 0; - while (true) { + while (true) + { Supports_Operator::Operand op = Supports_Operator::OR; - if (lex < kwd_and >()) { op = Supports_Operator::AND; } - else if(!lex < kwd_or >()) { break; } + if (lex()) + { + op = Supports_Operator::AND; + } + else if (!lex()) + { + break; + } - lex < css_whitespace >(); + lex(); Supports_Condition_Obj right = parse_supports_condition_in_parens(); - // Supports_Condition_Ptr cc = SASS_MEMORY_NEW(Supports_Condition, *static_cast(cond)); + // Supports_Condition_Ptr cc = SASS_MEMORY_NEW(Supports_Condition, + // *static_cast(cond)); cond = SASS_MEMORY_NEW(Supports_Operator, pstate, cond, right, op); } return cond; @@ -2266,7 +2621,7 @@ namespace Sass { Supports_Condition_Obj Parser::parse_supports_interpolation() { - if (!lex < interpolant >()) return 0; + if (!lex()) return 0; String_Obj interp = parse_interpolated_chunk(lexed); if (!interp) return 0; @@ -2282,10 +2637,8 @@ namespace Sass { // parse something declaration like Declaration_Obj declaration = parse_declaration(); if (!declaration) error("@supports condition expected declaration", pstate); - cond = SASS_MEMORY_NEW(Supports_Declaration, - declaration->pstate(), - declaration->property(), - declaration->value()); + cond = SASS_MEMORY_NEW(Supports_Declaration, declaration->pstate(), declaration->property(), + declaration->value()); // ToDo: maybe we need an additional error condition? return cond; } @@ -2295,17 +2648,20 @@ namespace Sass { Supports_Condition_Obj interp = parse_supports_interpolation(); if (interp != 0) return interp; - if (!lex < exactly <'('> >()) return 0; - lex < css_whitespace >(); + if (!lex>()) return 0; + lex(); Supports_Condition_Obj cond = parse_supports_condition(); - if (cond != 0) { - if (!lex < exactly <')'> >()) error("unclosed parenthesis in @supports declaration", pstate); - } else { + if (cond != 0) + { + if (!lex>()) error("unclosed parenthesis in @supports declaration", pstate); + } + else + { cond = parse_supports_declaration(); - if (!lex < exactly <')'> >()) error("unclosed parenthesis in @supports declaration", pstate); + if (!lex>()) error("unclosed parenthesis in @supports declaration", pstate); } - lex < css_whitespace >(); + lex(); return cond; } @@ -2315,14 +2671,17 @@ namespace Sass { Block_Obj body = 0; At_Root_Query_Obj expr; Lookahead lookahead_result; - if (lex_css< exactly<'('> >()) { + if (lex_css>()) + { expr = parse_at_root_query(); } - if (peek_css < exactly<'{'> >()) { - lex (); + if (peek_css>()) + { + lex(); body = parse_block(true); } - else if ((lookahead_result = lookahead_for_selector(position)).found) { + else if ((lookahead_result = lookahead_for_selector(position)).found) + { Ruleset_Obj r = parse_ruleset(lookahead_result); body = SASS_MEMORY_NEW(Block, r->pstate(), 1, true); body->append(r); @@ -2334,27 +2693,27 @@ namespace Sass { At_Root_Query_Obj Parser::parse_at_root_query() { - if (peek< exactly<')'> >()) error("at-root feature required in at-root expression", pstate); + if (peek>()) error("at-root feature required in at-root expression", pstate); - if (!peek< alternatives< kwd_with_directive, kwd_without_directive > >()) { + if (!peek>()) + { css_error("Invalid CSS", " after ", ": expected \"with\" or \"without\", was "); } Expression_Obj feature = parse_list(); - if (!lex_css< exactly<':'> >()) error("style declaration must contain a value", pstate); + if (!lex_css>()) error("style declaration must contain a value", pstate); Expression_Obj expression = parse_list(); List_Obj value = SASS_MEMORY_NEW(List, feature->pstate(), 1); - if (expression->concrete_type() == Expression::LIST) { - value = Cast(expression); + if (expression->concrete_type() == Expression::LIST) + { + value = Cast(expression); } - else value->append(expression); + else + value->append(expression); - At_Root_Query_Obj cond = SASS_MEMORY_NEW(At_Root_Query, - value->pstate(), - feature, - value); - if (!lex_css< exactly<')'> >()) error("unclosed parenthesis in @at-root expression", pstate); + At_Root_Query_Obj cond = SASS_MEMORY_NEW(At_Root_Query, value->pstate(), feature, value); + if (!lex_css>()) error("unclosed parenthesis in @at-root expression", pstate); return cond; } @@ -2368,21 +2727,26 @@ namespace Sass { Directive_Ptr at_rule = SASS_MEMORY_NEW(Directive, pstate, kwd); Lookahead lookahead = lookahead_for_include(position); - if (lookahead.found && !lookahead.has_interpolants) { + if (lookahead.found && !lookahead.has_interpolants) + { at_rule->selector(parse_selector_list(false)); } - lex < css_comments >(false); + lex(false); - if (lex < static_property >()) { + if (lex()) + { at_rule->value(parse_interpolated_chunk(Token(lexed))); - } else if (!(peek < alternatives < exactly<'{'>, exactly<'}'>, exactly<';'> > >())) { + } + else if (!(peek, exactly<'}'>, exactly<';'>>>())) + { at_rule->value(parse_list()); } - lex < css_comments >(false); + lex(false); - if (peek< exactly<'{'> >()) { + if (peek>()) + { at_rule->block(parse_block()); } @@ -2398,21 +2762,26 @@ namespace Sass { Directive_Obj at_rule = SASS_MEMORY_NEW(Directive, pstate, kwd); Lookahead lookahead = lookahead_for_include(position); - if (lookahead.found && !lookahead.has_interpolants) { + if (lookahead.found && !lookahead.has_interpolants) + { at_rule->selector(parse_selector_list(false)); } - lex < css_comments >(false); + lex(false); - if (lex < static_property >()) { + if (lex()) + { at_rule->value(parse_interpolated_chunk(Token(lexed))); - } else if (!(peek < alternatives < exactly<'{'>, exactly<'}'>, exactly<';'> > >())) { + } + else if (!(peek, exactly<'}'>, exactly<';'>>>())) + { at_rule->value(parse_list()); } - lex < css_comments >(false); + lex(false); - if (peek< exactly<'{'> >()) { + if (peek>()) + { at_rule->block(parse_block()); } @@ -2426,7 +2795,8 @@ namespace Sass { String_Schema_Obj val = parse_almost_any_value(); // strip left and right if they are of type string directive->value(val); - if (peek< exactly<'{'> >()) { + if (peek>()) + { directive->block(parse_block()); } return directive; @@ -2434,7 +2804,8 @@ namespace Sass { Expression_Obj Parser::lex_interpolation() { - if (lex < interpolant >(true) != NULL) { + if (lex(true) != NULL) + { return parse_interpolated_chunk(lexed, true); } return 0; @@ -2443,64 +2814,26 @@ namespace Sass { Expression_Obj Parser::lex_interp_uri() { // create a string schema by lexing optional interpolations - return lex_interp< re_string_uri_open, re_string_uri_close >(); + return lex_interp(); } Expression_Obj Parser::lex_interp_string() { Expression_Obj rv; - if ((rv = lex_interp< re_string_double_open, re_string_double_close >())) return rv; - if ((rv = lex_interp< re_string_single_open, re_string_single_close >())) return rv; + if ((rv = lex_interp())) return rv; + if ((rv = lex_interp())) return rv; return rv; } Expression_Obj Parser::lex_almost_any_value_chars() { const char* match = - lex < - one_plus < - alternatives < - sequence < - exactly <'\\'>, - any_char - >, - sequence < - negate < - sequence < - exactly < url_kwd >, - exactly <'('> - > - >, - neg_class_char < - almost_any_value_class - > - >, - sequence < - exactly <'/'>, - negate < - alternatives < - exactly <'/'>, - exactly <'*'> - > - > - >, - sequence < - exactly <'\\'>, - exactly <'#'>, - negate < - exactly <'{'> - > - >, - sequence < - exactly <'!'>, - negate < - alpha - > - > - > - > - >(false); - if (match) { + lex, any_char>, sequence, exactly<'('>>>, neg_class_char>, + sequence, negate, exactly<'*'>>>>, + sequence, exactly<'#'>, negate>>, sequence, negate>>>>( + false); + if (match) + { return SASS_MEMORY_NEW(String_Constant, pstate, lexed); } return NULL; @@ -2524,20 +2857,22 @@ namespace Sass { String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate); if (*position == 0) return 0; - lex < spaces >(false); + lex(false); Expression_Obj token = lex_almost_any_value_token(); if (!token) return 0; schema->append(token); - if (*position == 0) { + if (*position == 0) + { schema->rtrim(); return schema.detach(); } - while ((token = lex_almost_any_value_token())) { + while ((token = lex_almost_any_value_token())) + { schema->append(token); } - lex < css_whitespace >(); + lex(); schema->rtrim(); @@ -2546,11 +2881,9 @@ namespace Sass { Warning_Obj Parser::parse_warning() { - if (stack.back() != Scope::Root && - stack.back() != Scope::Function && - stack.back() != Scope::Mixin && - stack.back() != Scope::Control && - stack.back() != Scope::Rules) { + if (stack.back() != Scope::Root && stack.back() != Scope::Function && + stack.back() != Scope::Mixin && stack.back() != Scope::Control && stack.back() != Scope::Rules) + { error("Illegal nesting: Only properties may be nested beneath properties.", pstate); } return SASS_MEMORY_NEW(Warning, pstate, parse_list(DELAYED)); @@ -2558,11 +2891,9 @@ namespace Sass { Error_Obj Parser::parse_error() { - if (stack.back() != Scope::Root && - stack.back() != Scope::Function && - stack.back() != Scope::Mixin && - stack.back() != Scope::Control && - stack.back() != Scope::Rules) { + if (stack.back() != Scope::Root && stack.back() != Scope::Function && + stack.back() != Scope::Mixin && stack.back() != Scope::Control && stack.back() != Scope::Rules) + { error("Illegal nesting: Only properties may be nested beneath properties.", pstate); } return SASS_MEMORY_NEW(Error, pstate, parse_list(DELAYED)); @@ -2570,11 +2901,9 @@ namespace Sass { Debug_Obj Parser::parse_debug() { - if (stack.back() != Scope::Root && - stack.back() != Scope::Function && - stack.back() != Scope::Mixin && - stack.back() != Scope::Control && - stack.back() != Scope::Rules) { + if (stack.back() != Scope::Root && stack.back() != Scope::Function && + stack.back() != Scope::Mixin && stack.back() != Scope::Control && stack.back() != Scope::Rules) + { error("Illegal nesting: Only properties may be nested beneath properties.", pstate); } return SASS_MEMORY_NEW(Debug, pstate, parse_list(DELAYED)); @@ -2583,8 +2912,10 @@ namespace Sass { Return_Obj Parser::parse_return_directive() { // check that we do not have an empty list (ToDo: check if we got all cases) - if (peek_css < alternatives < exactly < ';' >, exactly < '}' >, end_of_file > >()) - { css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was "); } + if (peek_css, exactly<'}'>, end_of_file>>()) + { + css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was "); + } return SASS_MEMORY_NEW(Return, pstate, parse_list()); } @@ -2596,18 +2927,18 @@ namespace Sass { const char* p = start ? start : position; // match in one big "regex" rv.error = p; - if (const char* q = - peek < - re_selector_list - >(p) - ) { - while (p < q) { + if (const char* q = peek(p)) + { + while (p < q) + { // did we have interpolations? - if (*p == '#' && *(p+1) == '{') { + if (*p == '#' && *(p + 1) == '{') + { rv.has_interpolants = true; - p = q; break; + p = q; + break; } - ++ p; + ++p; } // store anyway } @@ -2617,19 +2948,19 @@ namespace Sass { rv.position = q; // check expected opening bracket // only after successfull matching - if (peek < exactly<'{'> >(q)) rv.found = q; + if (peek>(q)) rv.found = q; // else if (peek < end_of_file >(q)) rv.found = q; - else if (peek < exactly<'('> >(q)) rv.found = q; + else if (peek>(q)) + rv.found = q; // else if (peek < exactly<';'> >(q)) rv.found = q; // else if (peek < exactly<'}'> >(q)) rv.found = q; if (rv.found || *p == 0) rv.error = 0; } - rv.parsable = ! rv.has_interpolants; + rv.parsable = !rv.has_interpolants; // return result return rv; - } // EO lookahead_for_selector @@ -2640,10 +2971,13 @@ namespace Sass { // we actually just lookahead for a selector Lookahead rv = lookahead_for_selector(start); // but the "found" rules are different - if (const char* p = rv.position) { + if (const char* p = rv.position) + { // check for additional abort condition - if (peek < exactly<';'> >(p)) rv.found = p; - else if (peek < exactly<'}'> >(p)) rv.found = p; + if (peek>(p)) + rv.found = p; + else if (peek>(p)) + rv.found = p; } // return result return rv; @@ -2661,59 +2995,42 @@ namespace Sass { // get start position const char* p = start ? start : position; // match in one big "regex" - if (const char* q = - peek < - non_greedy < - alternatives < - // consume whitespace - block_comment, // spaces, - // main tokens - sequence < - interpolant, - optional < - quoted_string - > - >, - identifier, - variable, - // issue #442 - sequence < - parenthese_scope, - interpolant, - optional < - quoted_string - > - > - >, - sequence < - // optional_spaces, - alternatives < - // end_of_file, - exactly<'{'>, - exactly<'}'>, - exactly<';'> - > - > - > - >(p) - ) { + if (const char* q = peek>, identifier, variable, + // issue #442 + sequence>>, + sequence< + // optional_spaces, + alternatives< + // end_of_file, + exactly<'{'>, exactly<'}'>, exactly<';'>>>>>(p)) + { if (p == q) return rv; - while (p < q) { + while (p < q) + { // did we have interpolations? - if (*p == '#' && *(p+1) == '{') { + if (*p == '#' && *(p + 1) == '{') + { rv.has_interpolants = true; - p = q; break; + p = q; + break; } - ++ p; + ++p; } // store anyway // ToDo: remove rv.position = q; // check expected opening bracket // only after successful matching - if (peek < exactly<'{'> >(q)) rv.found = q; - else if (peek < exactly<';'> >(q)) rv.found = q; - else if (peek < exactly<'}'> >(q)) rv.found = q; + if (peek>(q)) + rv.found = q; + else if (peek>(q)) + rv.found = q; + else if (peek>(q)) + rv.found = q; } // return result @@ -2726,7 +3043,8 @@ namespace Sass { size_t skip = 0; std::string encoding; bool utf_8 = false; - switch ((unsigned char) source[0]) { + switch ((unsigned char)source[0]) + { case 0xEF: skip = check_bom_chars(source, end, utf_8_bom, 3); encoding = "UTF-8"; @@ -2746,11 +3064,9 @@ namespace Sass { encoding = "UTF-32 (big endian)"; break; case 0x2B: - skip = check_bom_chars(source, end, utf_7_bom_1, 4) - | check_bom_chars(source, end, utf_7_bom_2, 4) - | check_bom_chars(source, end, utf_7_bom_3, 4) - | check_bom_chars(source, end, utf_7_bom_4, 4) - | check_bom_chars(source, end, utf_7_bom_5, 5); + skip = check_bom_chars(source, end, utf_7_bom_1, 4) | + check_bom_chars(source, end, utf_7_bom_2, 4) | check_bom_chars(source, end, utf_7_bom_3, 4) | + check_bom_chars(source, end, utf_7_bom_4, 4) | check_bom_chars(source, end, utf_7_bom_5, 5); encoding = "UTF-7"; break; case 0xF7: @@ -2773,18 +3089,21 @@ namespace Sass { skip = check_bom_chars(source, end, gb_18030_bom, 4); encoding = "GB-18030"; break; - default: break; + default: + break; } - if (skip > 0 && !utf_8) error("only UTF-8 documents are currently supported; your document appears to be " + encoding, pstate); + if (skip > 0 && !utf_8) + error("only UTF-8 documents are currently supported; your document appears to be " + encoding, pstate); position += skip; } - size_t check_bom_chars(const char* src, const char *end, const unsigned char* bom, size_t len) + size_t check_bom_chars(const char* src, const char* end, const unsigned char* bom, size_t len) { size_t skip = 0; if (src + len > end) return 0; - for (size_t i = 0; i < len; ++i, ++skip) { - if ((unsigned char) src[i] != bom[i]) return 0; + for (size_t i = 0; i < len; ++i, ++skip) + { + if ((unsigned char)src[i] != bom[i]) return 0; } return skip; } @@ -2792,28 +3111,30 @@ namespace Sass { Expression_Obj Parser::fold_operands(Expression_Obj base, std::vector& operands, Operand op) { - for (size_t i = 0, S = operands.size(); i < S; ++i) { + for (size_t i = 0, S = operands.size(); i < S; ++i) + { base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), op, base, operands[i]); } return base; } - Expression_Obj Parser::fold_operands(Expression_Obj base, std::vector& operands, std::vector& ops, size_t i) + Expression_Obj Parser::fold_operands(Expression_Obj base, + std::vector& operands, + std::vector& ops, + size_t i) { - if (String_Schema_Ptr schema = Cast(base)) { + if (String_Schema_Ptr schema = Cast(base)) + { // return schema; - if (schema->has_interpolants()) { - if (i + 1 < operands.size() && ( - (ops[0].operand == Sass_OP::EQ) - || (ops[0].operand == Sass_OP::ADD) - || (ops[0].operand == Sass_OP::DIV) - || (ops[0].operand == Sass_OP::MUL) - || (ops[0].operand == Sass_OP::NEQ) - || (ops[0].operand == Sass_OP::LT) - || (ops[0].operand == Sass_OP::GT) - || (ops[0].operand == Sass_OP::LTE) - || (ops[0].operand == Sass_OP::GTE) - )) { + if (schema->has_interpolants()) + { + if (i + 1 < operands.size() && + ((ops[0].operand == Sass_OP::EQ) || (ops[0].operand == Sass_OP::ADD) || + (ops[0].operand == Sass_OP::DIV) || (ops[0].operand == Sass_OP::MUL) || + (ops[0].operand == Sass_OP::NEQ) || (ops[0].operand == Sass_OP::LT) || + (ops[0].operand == Sass_OP::GT) || (ops[0].operand == Sass_OP::LTE) || + (ops[0].operand == Sass_OP::GTE))) + { Expression_Obj rhs = fold_operands(operands[i], operands, ops, i + 1); rhs = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[0], schema, rhs); return rhs; @@ -2822,31 +3143,41 @@ namespace Sass { } } - for (size_t S = operands.size(); i < S; ++i) { - if (String_Schema_Ptr schema = Cast(operands[i])) { - if (schema->has_interpolants()) { - if (i + 1 < S) { + for (size_t S = operands.size(); i < S; ++i) + { + if (String_Schema_Ptr schema = Cast(operands[i])) + { + if (schema->has_interpolants()) + { + if (i + 1 < S) + { // this whole branch is never hit via spec tests - Expression_Obj rhs = fold_operands(operands[i+1], operands, ops, i + 2); + Expression_Obj rhs = fold_operands(operands[i + 1], operands, ops, i + 2); rhs = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], schema, rhs); base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], base, rhs); return base; } base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], base, operands[i]); return base; - } else { + } + else + { base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], base, operands[i]); } - } else { + } + else + { base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], base, operands[i]); } Binary_Expression_Ptr b = Cast(base.ptr()); - if (b && ops[i].operand == Sass_OP::DIV && b->left()->is_delayed() && b->right()->is_delayed()) { + if (b && ops[i].operand == Sass_OP::DIV && b->left()->is_delayed() && b->right()->is_delayed()) + { base->is_delayed(true); } } // nested binary expression are never to be delayed - if (Binary_Expression_Ptr b = Cast(base)) { + if (Binary_Expression_Ptr b = Cast(base)) + { if (Cast(b->left())) base->set_delayed(false); if (Cast(b->right())) base->set_delayed(false); } @@ -2863,15 +3194,18 @@ namespace Sass { { int max_len = 18; const char* end = this->end; - while (*end != 0) ++ end; - const char* pos = peek < optional_spaces >(); + while (*end != 0) + ++end; + const char* pos = peek(); const char* last_pos(pos); - if (last_pos > source) { + if (last_pos > source) + { utf8::prior(last_pos, source); } // backup position to last significant char - while (last_pos > source && last_pos < end) { + while (last_pos > source && last_pos < end) + { if (!Prelexer::is_space(*last_pos)) break; utf8::prior(last_pos, source); } @@ -2882,11 +3216,12 @@ namespace Sass { if (*pos_left) utf8::next(pos_left, end); if (*end_left) utf8::next(end_left, end); - while (pos_left > source) { - if (utf8::distance(pos_left, end_left) >= max_len) { + while (pos_left > source) + { + if (utf8::distance(pos_left, end_left) >= max_len) + { utf8::prior(pos_left, source); - ellipsis_left = *(pos_left) != '\n' && - *(pos_left) != '\r'; + ellipsis_left = *(pos_left) != '\n' && *(pos_left) != '\r'; utf8::next(pos_left, end); break; } @@ -2897,17 +3232,19 @@ namespace Sass { if (*prev == '\n') break; pos_left = prev; } - if (pos_left < source) { + if (pos_left < source) + { pos_left = source; } bool ellipsis_right = false; const char* end_right(pos); const char* pos_right(pos); - while (end_right < end) { - if (utf8::distance(pos_right, end_right) > max_len) { - ellipsis_left = *(pos_right) != '\n' && - *(pos_right) != '\r'; + while (end_right < end) + { + if (utf8::distance(pos_right, end_right) > max_len) + { + ellipsis_left = *(pos_right) != '\n' && *(pos_right) != '\r'; break; } if (*end_right == '\r') break; @@ -2925,5 +3262,4 @@ namespace Sass { // now pass new message to the more generic error function error(msg + prefix + quote(left) + middle + quote(right), pstate); } - } diff --git a/src/parser.hpp b/src/parser.hpp index 05d396527b..1ba417a726 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -10,7 +10,8 @@ #include "position.hpp" #include "prelexer.hpp" -struct Lookahead { +struct Lookahead +{ const char* found; const char* error; const char* position; @@ -18,12 +19,22 @@ struct Lookahead { bool has_interpolants; }; -namespace Sass { +namespace Sass +{ - class Parser : public ParserState { - public: - - enum Scope { Root, Mixin, Function, Media, Control, Properties, Rules }; + class Parser : public ParserState + { + public: + enum Scope + { + Root, + Mixin, + Function, + Media, + Control, + Properties, + Rules + }; Context& ctx; std::vector block_stack; @@ -41,23 +52,35 @@ namespace Sass { Token lexed; Parser(Context& ctx, const ParserState& pstate) - : ParserState(pstate), ctx(ctx), block_stack(), stack(0), last_media_block(), - source(0), position(0), end(0), before_token(pstate), after_token(pstate), pstate(pstate), indentation(0) - { stack.push_back(Scope::Root); } - - // static Parser from_string(const std::string& src, Context& ctx, ParserState pstate = ParserState("[STRING]")); - static Parser from_c_str(const char* src, Context& ctx, ParserState pstate = ParserState("[CSTRING]"), const char* source = 0); - static Parser from_c_str(const char* beg, const char* end, Context& ctx, ParserState pstate = ParserState("[CSTRING]"), const char* source = 0); - static Parser from_token(Token t, Context& ctx, ParserState pstate = ParserState("[TOKEN]"), const char* source = 0); + : ParserState(pstate), ctx(ctx), block_stack(), stack(0), last_media_block(), source(0), + position(0), end(0), before_token(pstate), after_token(pstate), pstate(pstate), indentation(0) + { + stack.push_back(Scope::Root); + } + + // static Parser from_string(const std::string& src, Context& ctx, ParserState pstate = + // ParserState("[STRING]")); + static Parser + from_c_str(const char* src, Context& ctx, ParserState pstate = ParserState("[CSTRING]"), const char* source = 0); + static Parser from_c_str(const char* beg, + const char* end, + Context& ctx, + ParserState pstate = ParserState("[CSTRING]"), + const char* source = 0); + static Parser + from_token(Token t, Context& ctx, ParserState pstate = ParserState("[TOKEN]"), const char* source = 0); // special static parsers to convert strings into certain selectors - static Selector_List_Obj parse_selector(const char* src, Context& ctx, ParserState pstate = ParserState("[SELECTOR]"), const char* source = 0); + static Selector_List_Obj parse_selector(const char* src, + Context& ctx, + ParserState pstate = ParserState("[SELECTOR]"), + const char* source = 0); #ifdef __clang__ - // lex and peak uses the template parameter to branch on the action, which - // triggers clangs tautological comparison on the single-comparison - // branches. This is not a bug, just a merging of behaviour into - // one function +// lex and peak uses the template parameter to branch on the action, which +// triggers clangs tautological comparison on the single-comparison +// branches. This is not a bug, just a merging of behaviour into +// one function #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wtautological-compare" @@ -72,8 +95,7 @@ namespace Sass { bool peek_newline(const char* start = 0); // skip over spaces, tabs and line comments - template - const char* sneak(const char* start = 0) + template const char* sneak(const char* start = 0) { using namespace Prelexer; @@ -81,14 +103,9 @@ namespace Sass { const char* it_position = start ? start : position; // skip white-space? - if (mx == spaces || - mx == no_spaces || - mx == css_comments || - mx == css_whitespace || - mx == optional_spaces || - mx == optional_css_comments || - mx == optional_css_whitespace - ) { + if (mx == spaces || mx == no_spaces || mx == css_comments || mx == css_whitespace || + mx == optional_spaces || mx == optional_css_comments || mx == optional_css_whitespace) + { return it_position; } @@ -96,13 +113,11 @@ namespace Sass { const char* pos = optional_css_whitespace(it_position); // always return a valid position return pos ? pos : it_position; - } // peek will only skip over space, tabs and line comment // return the position where the lexer match will occur - template - const char* match(const char* start = 0) + template const char* match(const char* start = 0) { // match the given prelexer return mx(position); @@ -110,20 +125,18 @@ namespace Sass { // peek will only skip over space, tabs and line comment // return the position where the lexer match will occur - template - const char* peek(const char* start = 0) + template const char* peek(const char* start = 0) { // sneak up to the actual token we want to lex // this should skip over white-space if desired - const char* it_before_token = sneak < mx >(start); + const char* it_before_token = sneak(start); // match the given prelexer const char* match = mx(it_before_token); // check if match is in valid range return match <= end ? match : 0; - } // white-space handling is built into the lexer @@ -132,8 +145,7 @@ namespace Sass { // we do not support start arg, since we manipulate // sourcemap offset and we modify the position pointer! // lex will only skip over space, tabs and line comment - template - const char* lex(bool lazy = true, bool force = false) + template const char* lex(bool lazy = true, bool force = false) { if (*position == 0) return 0; @@ -145,7 +157,7 @@ namespace Sass { // sneak up to the actual token we want to lex // this should skip over white-space if desired - if (lazy) it_before_token = sneak < mx >(position); + if (lazy) it_before_token = sneak(position); // now call matcher to get position after token const char* it_after_token = mx(it_before_token); @@ -154,7 +166,8 @@ namespace Sass { if (it_after_token > end) return 0; // maybe we want to update the parser state anyway? - if (force == false) { + if (force == false) + { // assertion that we got a valid match if (it_after_token == 0) return 0; // assertion that we actually lexed something @@ -175,14 +188,12 @@ namespace Sass { // advance internal char iterator return position = it_after_token; - } // lex_css skips over space, tabs, line and block comment // all block comments will be consumed and thrown away // source-map position will point to token after the comment - template - const char* lex_css() + template const char* lex_css() { // copy old token Token prev = lexed; @@ -193,11 +204,12 @@ namespace Sass { ParserState op = pstate; // throw away comments // update srcmap position - lex < Prelexer::css_comments >(); + lex(); // now lex a new token - const char* pos = lex< mx >(); + const char* pos = lex(); // maybe restore prev state - if (pos == 0) { + if (pos == 0) + { pstate = op; lexed = prev; position = oldpos; @@ -209,11 +221,10 @@ namespace Sass { } // all block comments will be skipped and thrown away - template - const char* peek_css(const char* start = 0) + template const char* peek_css(const char* start = 0) { // now peek a token (skip comments first) - return peek< mx >(peek < Prelexer::css_comments >(start)); + return peek(peek(start)); } #ifdef __clang__ @@ -225,9 +236,7 @@ namespace Sass { void error(std::string msg, Position pos); // generate message with given and expected sample // text before and in the middle are configurable - void css_error(const std::string& msg, - const std::string& prefix = " after ", - const std::string& middle = ", was: "); + void css_error(const std::string& msg, const std::string& prefix = " after ", const std::string& middle = ", was: "); void read_bom(); Block_Obj parse(); @@ -325,53 +334,75 @@ namespace Sass { Lookahead lookahead_for_include(const char* start = 0); Expression_Obj fold_operands(Expression_Obj base, std::vector& operands, Operand op); - Expression_Obj fold_operands(Expression_Obj base, std::vector& operands, std::vector& ops, size_t i = 0); + Expression_Obj fold_operands(Expression_Obj base, + std::vector& operands, + std::vector& ops, + size_t i = 0); void throw_syntax_error(std::string message, size_t ln = 0); void throw_read_error(std::string message, size_t ln = 0); - template - Expression_Obj lex_interp() + template Expression_Obj lex_interp() { - if (lex < open >(false)) { + if (lex(false)) + { String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate); // std::cerr << "LEX [[" << std::string(lexed) << "]]\n"; schema->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed)); - if (position[0] == '#' && position[1] == '{') { + if (position[0] == '#' && position[1] == '{') + { Expression_Obj itpl = lex_interpolation(); if (!itpl.isNull()) schema->append(itpl); - while (lex < close >(false)) { + while (lex(false)) + { // std::cerr << "LEX [[" << std::string(lexed) << "]]\n"; schema->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed)); - if (position[0] == '#' && position[1] == '{') { + if (position[0] == '#' && position[1] == '{') + { Expression_Obj itpl = lex_interpolation(); if (!itpl.isNull()) schema->append(itpl); - } else { + } + else + { return schema; } } - } else { + } + else + { return SASS_MEMORY_NEW(String_Constant, pstate, lexed); } } return 0; } - public: + public: static Number_Ptr lexed_number(const ParserState& pstate, const std::string& parsed); static Number_Ptr lexed_dimension(const ParserState& pstate, const std::string& parsed); static Number_Ptr lexed_percentage(const ParserState& pstate, const std::string& parsed); static Expression_Ptr lexed_hex_color(const ParserState& pstate, const std::string& parsed); - private: - Number_Ptr lexed_number(const std::string& parsed) { return lexed_number(pstate, parsed); }; - Number_Ptr lexed_dimension(const std::string& parsed) { return lexed_dimension(pstate, parsed); }; - Number_Ptr lexed_percentage(const std::string& parsed) { return lexed_percentage(pstate, parsed); }; - Expression_Ptr lexed_hex_color(const std::string& parsed) { return lexed_hex_color(pstate, parsed); }; + private: + Number_Ptr lexed_number(const std::string& parsed) + { + return lexed_number(pstate, parsed); + }; + Number_Ptr lexed_dimension(const std::string& parsed) + { + return lexed_dimension(pstate, parsed); + }; + Number_Ptr lexed_percentage(const std::string& parsed) + { + return lexed_percentage(pstate, parsed); + }; + Expression_Ptr lexed_hex_color(const std::string& parsed) + { + return lexed_hex_color(pstate, parsed); + }; }; - size_t check_bom_chars(const char* src, const char *end, const unsigned char* bom, size_t len); + size_t check_bom_chars(const char* src, const char* end, const unsigned char* bom, size_t len); } #endif diff --git a/src/paths.hpp b/src/paths.hpp index aabab94aee..c1c5377b76 100644 --- a/src/paths.hpp +++ b/src/paths.hpp @@ -6,43 +6,53 @@ #include -template -std::string vector_to_string(std::vector v) +template std::string vector_to_string(std::vector v) { std::stringstream buffer; buffer << "["; if (!v.empty()) - { buffer << v[0]; } + { + buffer << v[0]; + } else - { buffer << "]"; } + { + buffer << "]"; + } if (v.size() == 1) - { buffer << "]"; } + { + buffer << "]"; + } else { - for (size_t i = 1, S = v.size(); i < S; ++i) buffer << ", " << v[i]; + for (size_t i = 1, S = v.size(); i < S; ++i) + buffer << ", " << v[i]; buffer << "]"; } return buffer.str(); } -namespace Sass { +namespace Sass +{ - template - std::vector > paths(std::vector > strata, size_t from_end = 0) + template + std::vector> paths(std::vector> strata, size_t from_end = 0) { - if (strata.empty()) { - return std::vector >(); + if (strata.empty()) + { + return std::vector>(); } size_t end = strata.size() - from_end; - if (end <= 1) { - std::vector > starting_points; + if (end <= 1) + { + std::vector> starting_points; starting_points.reserve(strata[0].size()); - for (size_t i = 0, S = strata[0].size(); i < S; ++i) { + for (size_t i = 0, S = strata[0].size(); i < S; ++i) + { std::vector starting_point; starting_point.push_back(strata[0][i]); starting_points.push_back(starting_point); @@ -50,13 +60,15 @@ namespace Sass { return starting_points; } - std::vector > up_to_here = paths(strata, from_end + 1); - std::vector here = strata[end-1]; + std::vector> up_to_here = paths(strata, from_end + 1); + std::vector here = strata[end - 1]; - std::vector > branches; + std::vector> branches; branches.reserve(up_to_here.size() * here.size()); - for (size_t i = 0, S1 = up_to_here.size(); i < S1; ++i) { - for (size_t j = 0, S2 = here.size(); j < S2; ++j) { + for (size_t i = 0, S1 = up_to_here.size(); i < S1; ++i) + { + for (size_t j = 0, S2 = here.size(); j < S2; ++j) + { std::vector branch = up_to_here[i]; branch.push_back(here[j]); branches.push_back(branch); @@ -65,7 +77,6 @@ namespace Sass { return branches; } - } #endif diff --git a/src/plugins.cpp b/src/plugins.cpp index eecba78804..c38a9c2c19 100644 --- a/src/plugins.cpp +++ b/src/plugins.cpp @@ -12,18 +12,24 @@ #include #endif -namespace Sass { +namespace Sass +{ - Plugins::Plugins(void) { } + Plugins::Plugins(void) + { + } Plugins::~Plugins(void) { - for (auto function : functions) { + for (auto function : functions) + { sass_delete_function(function); } - for (auto importer : importers) { + for (auto importer : importers) + { sass_delete_importer(importer); } - for (auto header : headers) { + for (auto header : headers) + { sass_delete_importer(header); } } @@ -33,7 +39,7 @@ namespace Sass { // we try to be compatible between major versions inline bool compatibility(const char* their_version) { -// const char* their_version = "3.1.2"; + // const char* their_version = "3.1.2"; // first check if anyone has an unknown version const char* our_version = libsass_version(); if (!strcmp(their_version, "[na]")) return false; @@ -44,14 +50,19 @@ namespace Sass { if (pos != std::string::npos) pos = std::string(our_version).find('.', pos + 1); // if we do not have two dots we fallback to compare complete string - if (pos == std::string::npos) { return strcmp(their_version, our_version) ? 0 : 1; } + if (pos == std::string::npos) + { + return strcmp(their_version, our_version) ? 0 : 1; + } // otherwise only compare up to the second dot (major versions) - else { return strncmp(their_version, our_version, pos) ? 0 : 1; } - + else + { + return strncmp(their_version, our_version, pos) ? 0 : 1; + } } // load one specific plugin - bool Plugins::load_plugin (const std::string& path) + bool Plugins::load_plugin(const std::string& path) { typedef const char* (*__plugin_version__)(void); @@ -69,21 +80,33 @@ namespace Sass { if (LOAD_LIB_FN(__plugin_load_fns__, plugin_load_functions, "libsass_load_functions")) { Sass_Function_List fns = plugin_load_functions(), _p = fns; - while (fns && *fns) { functions.push_back(*fns); ++ fns; } + while (fns && *fns) + { + functions.push_back(*fns); + ++fns; + } sass_free_memory(_p); // only delete the container, items not yet } // try to get import address for "libsass_load_importers" if (LOAD_LIB_FN(__plugin_load_imps__, plugin_load_importers, "libsass_load_importers")) { Sass_Importer_List imps = plugin_load_importers(), _p = imps; - while (imps && *imps) { importers.push_back(*imps); ++ imps; } + while (imps && *imps) + { + importers.push_back(*imps); + ++imps; + } sass_free_memory(_p); // only delete the container, items not yet } // try to get import address for "libsass_load_headers" if (LOAD_LIB_FN(__plugin_load_imps__, plugin_load_headers, "libsass_load_headers")) { Sass_Importer_List imps = plugin_load_headers(), _p = imps; - while (imps && *imps) { headers.push_back(*imps); ++ imps; } + while (imps && *imps) + { + headers.push_back(*imps); + ++imps; + } sass_free_memory(_p); // only delete the container, items not yet } // success @@ -105,7 +128,6 @@ namespace Sass { } return false; - } size_t Plugins::load_plugins(const std::string& path) @@ -114,71 +136,70 @@ namespace Sass { // count plugins size_t loaded = 0; - #ifdef _WIN32 +#ifdef _WIN32 - try - { + try + { - // use wchar (utf16) - WIN32_FIND_DATAW data; - // trailing slash is guaranteed - std::string globsrch(path + "*.dll"); - // convert to wide chars (utf16) for system call - std::wstring wglobsrch(UTF_8::convert_to_utf16(globsrch)); - HANDLE hFile = FindFirstFileW(wglobsrch.c_str(), &data); - // check if system called returned a result - // ToDo: maybe we should print a debug message - if (hFile == INVALID_HANDLE_VALUE) return -1; - - // read directory - while (true) + // use wchar (utf16) + WIN32_FIND_DATAW data; + // trailing slash is guaranteed + std::string globsrch(path + "*.dll"); + // convert to wide chars (utf16) for system call + std::wstring wglobsrch(UTF_8::convert_to_utf16(globsrch)); + HANDLE hFile = FindFirstFileW(wglobsrch.c_str(), &data); + // check if system called returned a result + // ToDo: maybe we should print a debug message + if (hFile == INVALID_HANDLE_VALUE) return -1; + + // read directory + while (true) + { + try { - try - { - // the system will report the filenames with wide chars (utf16) - std::string entry = UTF_8::convert_from_utf16(data.cFileName); - // check if file ending matches exactly - if (!ends_with(entry, ".dll")) continue; - // load the plugin and increase counter - if (load_plugin(path + entry)) ++ loaded; - // check if there should be more entries - if (GetLastError() == ERROR_NO_MORE_FILES) break; - // load next entry (check for return type) - if (!FindNextFileW(hFile, &data)) break; - } - catch (...) - { - // report the error to the console (should not happen) - // seems like we got strange data from the system call? - std::cerr << "filename in plugin path has invalid utf8?" << std::endl; - } + // the system will report the filenames with wide chars (utf16) + std::string entry = UTF_8::convert_from_utf16(data.cFileName); + // check if file ending matches exactly + if (!ends_with(entry, ".dll")) continue; + // load the plugin and increase counter + if (load_plugin(path + entry)) ++loaded; + // check if there should be more entries + if (GetLastError() == ERROR_NO_MORE_FILES) break; + // load next entry (check for return type) + if (!FindNextFileW(hFile, &data)) break; + } + catch (...) + { + // report the error to the console (should not happen) + // seems like we got strange data from the system call? + std::cerr << "filename in plugin path has invalid utf8?" << std::endl; } } - catch (utf8::invalid_utf8) - { - // report the error to the console (should not happen) - // implementors should make sure to provide valid utf8 - std::cerr << "plugin path contains invalid utf8" << std::endl; - } + } + catch (utf8::invalid_utf8) + { + // report the error to the console (should not happen) + // implementors should make sure to provide valid utf8 + std::cerr << "plugin path contains invalid utf8" << std::endl; + } - #else - - DIR *dp; - struct dirent *dirp; - if((dp = opendir(path.c_str())) == NULL) return -1; - while ((dirp = readdir(dp)) != NULL) { - #if __APPLE__ - if (!ends_with(dirp->d_name, ".dylib")) continue; - #else - if (!ends_with(dirp->d_name, ".so")) continue; - #endif - if (load_plugin(path + dirp->d_name)) ++ loaded; - } - closedir(dp); +#else - #endif - return loaded; + DIR* dp; + struct dirent* dirp; + if ((dp = opendir(path.c_str())) == NULL) return -1; + while ((dirp = readdir(dp)) != NULL) + { +#if __APPLE__ + if (!ends_with(dirp->d_name, ".dylib")) continue; +#else + if (!ends_with(dirp->d_name, ".so")) continue; +#endif + if (load_plugin(path + dirp->d_name)) ++loaded; + } + closedir(dp); +#endif + return loaded; } - } diff --git a/src/plugins.hpp b/src/plugins.hpp index fe4eed010c..aded40356a 100644 --- a/src/plugins.hpp +++ b/src/plugins.hpp @@ -8,50 +8,59 @@ #ifdef _WIN32 - #define LOAD_LIB(var, path) HMODULE var = LoadLibraryW(UTF_8::convert_to_utf16(path).c_str()) - #define LOAD_LIB_WCHR(var, path_wide_str) HMODULE var = LoadLibraryW(path_wide_str.c_str()) - #define LOAD_LIB_FN(type, var, name) type var = (type) GetProcAddress(plugin, name) - #define CLOSE_LIB(var) FreeLibrary(var) +#define LOAD_LIB(var, path) HMODULE var = LoadLibraryW(UTF_8::convert_to_utf16(path).c_str()) +#define LOAD_LIB_WCHR(var, path_wide_str) HMODULE var = LoadLibraryW(path_wide_str.c_str()) +#define LOAD_LIB_FN(type, var, name) type var = (type)GetProcAddress(plugin, name) +#define CLOSE_LIB(var) FreeLibrary(var) - #ifndef dlerror - #define dlerror() 0 - #endif +#ifndef dlerror +#define dlerror() 0 +#endif #else - #define LOAD_LIB(var, path) void* var = dlopen(path.c_str(), RTLD_LAZY) - #define LOAD_LIB_FN(type, var, name) type var = (type) dlsym(plugin, name) - #define CLOSE_LIB(var) dlclose(var) +#define LOAD_LIB(var, path) void* var = dlopen(path.c_str(), RTLD_LAZY) +#define LOAD_LIB_FN(type, var, name) type var = (type)dlsym(plugin, name) +#define CLOSE_LIB(var) dlclose(var) #endif -namespace Sass { +namespace Sass +{ - class Plugins { + class Plugins + { public: // c-tor - Plugins(void); - ~Plugins(void); + Plugins(void); + ~Plugins(void); public: // methods - // load one specific plugin - bool load_plugin(const std::string& path); - // load all plugins from a directory - size_t load_plugins(const std::string& path); + // load one specific plugin + bool load_plugin(const std::string& path); + // load all plugins from a directory + size_t load_plugins(const std::string& path); public: // public accessors - const std::vector get_headers(void) { return headers; } - const std::vector get_importers(void) { return importers; } - const std::vector get_functions(void) { return functions; } + const std::vector get_headers(void) + { + return headers; + } + const std::vector get_importers(void) + { + return importers; + } + const std::vector get_functions(void) + { + return functions; + } private: // private vars - std::vector headers; - std::vector importers; - std::vector functions; - + std::vector headers; + std::vector importers; + std::vector functions; }; - } #endif diff --git a/src/position.cpp b/src/position.cpp index a8afe67d4e..f7a5111d69 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -1,29 +1,30 @@ #include "sass.hpp" #include "position.hpp" -namespace Sass { +namespace Sass +{ - Offset::Offset(const char* string) - : line(0), column(0) + Offset::Offset(const char* string) : line(0), column(0) { *this = inc(string, string + strlen(string)); } - Offset::Offset(const std::string& text) - : line(0), column(0) + Offset::Offset(const std::string& text) : line(0), column(0) { *this = inc(text.c_str(), text.c_str() + text.size()); } - Offset::Offset(const size_t line, const size_t column) - : line(line), column(column) { } + Offset::Offset(const size_t line, const size_t column) : line(line), column(column) + { + } // init/create instance from const char substring Offset Offset::init(const char* beg, const char* end) { Offset offset(0, 0); - if (end == 0) { + if (end == 0) + { end += strlen(beg); } offset.add(beg, end); @@ -36,13 +37,17 @@ namespace Sass { Offset Offset::add(const char* begin, const char* end) { if (end == 0) return *this; - while (begin < end && *begin) { - if (*begin == '\n') { - ++ line; + while (begin < end && *begin) + { + if (*begin == '\n') + { + ++line; // start new line column = 0; - } else { - ++ column; + } + else + { + ++column; } ++begin; } @@ -58,52 +63,63 @@ namespace Sass { return offset; } - bool Offset::operator== (const Offset &pos) const + bool Offset::operator==(const Offset& pos) const { return line == pos.line && column == pos.column; } - bool Offset::operator!= (const Offset &pos) const + bool Offset::operator!=(const Offset& pos) const { return line != pos.line || column != pos.column; } - void Offset::operator+= (const Offset &off) + void Offset::operator+=(const Offset& off) { *this = Offset(line + off.line, off.line > 0 ? off.column : column + off.column); } - Offset Offset::operator+ (const Offset &off) const + Offset Offset::operator+(const Offset& off) const { return Offset(line + off.line, off.line > 0 ? off.column : column + off.column); } - Offset Offset::operator- (const Offset &off) const + Offset Offset::operator-(const Offset& off) const { return Offset(line - off.line, off.line == line ? column - off.column : column); } - Position::Position(const size_t file) - : Offset(0, 0), file(file) { } + Position::Position(const size_t file) : Offset(0, 0), file(file) + { + } - Position::Position(const size_t file, const Offset& offset) - : Offset(offset), file(file) { } + Position::Position(const size_t file, const Offset& offset) : Offset(offset), file(file) + { + } - Position::Position(const size_t line, const size_t column) - : Offset(line, column), file(-1) { } + Position::Position(const size_t line, const size_t column) : Offset(line, column), file(-1) + { + } Position::Position(const size_t file, const size_t line, const size_t column) - : Offset(line, column), file(file) { } + : Offset(line, column), file(file) + { + } ParserState::ParserState(const char* path, const char* src, const size_t file) - : Position(file, 0, 0), path(path), src(src), offset(0, 0), token() { } + : Position(file, 0, 0), path(path), src(src), offset(0, 0), token() + { + } ParserState::ParserState(const char* path, const char* src, const Position& position, Offset offset) - : Position(position), path(path), src(src), offset(offset), token() { } + : Position(position), path(path), src(src), offset(offset), token() + { + } ParserState::ParserState(const char* path, const char* src, const Token& token, const Position& position, Offset offset) - : Position(position), path(path), src(src), offset(offset), token(token) { } + : Position(position), path(path), src(src), offset(offset), token(token) + { + } Position Position::add(const char* begin, const char* end) { @@ -118,27 +134,27 @@ namespace Sass { return Position(file, offset); } - bool Position::operator== (const Position &pos) const + bool Position::operator==(const Position& pos) const { return file == pos.file && line == pos.line && column == pos.column; } - bool Position::operator!= (const Position &pos) const + bool Position::operator!=(const Position& pos) const { return file == pos.file || line != pos.line || column != pos.column; } - void Position::operator+= (const Offset &off) + void Position::operator+=(const Offset& off) { *this = Position(file, line + off.line, off.line > 0 ? off.column : column + off.column); } - const Position Position::operator+ (const Offset &off) const + const Position Position::operator+(const Offset& off) const { return Position(file, line + off.line, off.line > 0 ? off.column : column + off.column); } - const Offset Position::operator- (const Offset &off) const + const Offset Position::operator-(const Offset& off) const { return Offset(line - off.line, off.line == line ? column - off.column : column); } @@ -159,5 +175,4 @@ namespace Sass { if (pos.column == string::npos) strm << "-1"; else strm << pos.column; return strm; } */ - } diff --git a/src/position.hpp b/src/position.hpp index 1aeb5d15a5..1b415f297e 100644 --- a/src/position.hpp +++ b/src/position.hpp @@ -5,119 +5,159 @@ #include // #include -namespace Sass { +namespace Sass +{ - class Offset { + class Offset + { public: // c-tor - Offset(const char* string); - Offset(const std::string& text); - Offset(const size_t line, const size_t column); + Offset(const char* string); + Offset(const std::string& text); + Offset(const size_t line, const size_t column); - // return new position, incremented by the given string - Offset add(const char* begin, const char* end); - Offset inc(const char* begin, const char* end) const; + // return new position, incremented by the given string + Offset add(const char* begin, const char* end); + Offset inc(const char* begin, const char* end) const; - // init/create instance from const char substring - static Offset init(const char* beg, const char* end); + // init/create instance from const char substring + static Offset init(const char* beg, const char* end); public: // overload operators for position - void operator+= (const Offset &pos); - bool operator== (const Offset &pos) const; - bool operator!= (const Offset &pos) const; - Offset operator+ (const Offset &off) const; - Offset operator- (const Offset &off) const; + void operator+=(const Offset& pos); + bool operator==(const Offset& pos) const; + bool operator!=(const Offset& pos) const; + Offset operator+(const Offset& off) const; + Offset operator-(const Offset& off) const; public: // overload output stream operator - // friend std::ostream& operator<<(std::ostream& strm, const Offset& off); + // friend std::ostream& operator<<(std::ostream& strm, const Offset& off); public: - Offset off() { return *this; } + Offset off() + { + return *this; + } public: - size_t line; - size_t column; - + size_t line; + size_t column; }; - class Position : public Offset { + class Position : public Offset + { public: // c-tor - Position(const size_t file); // line(0), column(0) - Position(const size_t file, const Offset& offset); - Position(const size_t line, const size_t column); // file(-1) - Position(const size_t file, const size_t line, const size_t column); + Position(const size_t file); // line(0), column(0) + Position(const size_t file, const Offset& offset); + Position(const size_t line, const size_t column); // file(-1) + Position(const size_t file, const size_t line, const size_t column); public: // overload operators for position - void operator+= (const Offset &off); - bool operator== (const Position &pos) const; - bool operator!= (const Position &pos) const; - const Position operator+ (const Offset &off) const; - const Offset operator- (const Offset &off) const; - // return new position, incremented by the given string - Position add(const char* begin, const char* end); - Position inc(const char* begin, const char* end) const; + void operator+=(const Offset& off); + bool operator==(const Position& pos) const; + bool operator!=(const Position& pos) const; + const Position operator+(const Offset& off) const; + const Offset operator-(const Offset& off) const; + // return new position, incremented by the given string + Position add(const char* begin, const char* end); + Position inc(const char* begin, const char* end) const; public: // overload output stream operator - // friend std::ostream& operator<<(std::ostream& strm, const Position& pos); + // friend std::ostream& operator<<(std::ostream& strm, const Position& pos); public: - size_t file; - + size_t file; }; // Token type for representing lexed chunks of text - class Token { - public: + class Token + { + public: const char* prefix; const char* begin; const char* end; - Token() - : prefix(0), begin(0), end(0) { } - Token(const char* b, const char* e) - : prefix(b), begin(b), end(e) { } - Token(const char* str) - : prefix(str), begin(str), end(str + strlen(str)) { } - Token(const char* p, const char* b, const char* e) - : prefix(p), begin(b), end(e) { } - - size_t length() const { return end - begin; } - std::string ws_before() const { return std::string(prefix, begin); } - const std::string to_string() const { return std::string(begin, end); } - std::string time_wspace() const { + Token() : prefix(0), begin(0), end(0) + { + } + Token(const char* b, const char* e) : prefix(b), begin(b), end(e) + { + } + Token(const char* str) : prefix(str), begin(str), end(str + strlen(str)) + { + } + Token(const char* p, const char* b, const char* e) : prefix(p), begin(b), end(e) + { + } + + size_t length() const + { + return end - begin; + } + std::string ws_before() const + { + return std::string(prefix, begin); + } + const std::string to_string() const + { + return std::string(begin, end); + } + std::string time_wspace() const + { std::string str(to_string()); std::string whitespaces(" \t\f\v\n\r"); - return str.erase(str.find_last_not_of(whitespaces)+1); + return str.erase(str.find_last_not_of(whitespaces) + 1); } - operator bool() { return begin && end && begin >= end; } - operator std::string() { return to_string(); } + operator bool() + { + return begin && end && begin >= end; + } + operator std::string() + { + return to_string(); + } - bool operator==(Token t) { return to_string() == t.to_string(); } + bool operator==(Token t) + { + return to_string() == t.to_string(); + } }; - class ParserState : public Position { + class ParserState : public Position + { public: // c-tor - ParserState(const char* path, const char* src = 0, const size_t file = std::string::npos); - ParserState(const char* path, const char* src, const Position& position, Offset offset = Offset(0, 0)); - ParserState(const char* path, const char* src, const Token& token, const Position& position, Offset offset = Offset(0, 0)); + ParserState(const char* path, const char* src = 0, const size_t file = std::string::npos); + ParserState(const char* path, const char* src, const Position& position, Offset offset = Offset(0, 0)); + ParserState(const char* path, + const char* src, + const Token& token, + const Position& position, + Offset offset = Offset(0, 0)); public: // down casts - Offset off() { return *this; } - Position pos() { return *this; } - ParserState pstate() { return *this; } + Offset off() + { + return *this; + } + Position pos() + { + return *this; + } + ParserState pstate() + { + return *this; + } public: - const char* path; - const char* src; - Offset offset; - Token token; - + const char* path; + const char* src; + Offset offset; + Token token; }; - } #endif diff --git a/src/prelexer.cpp b/src/prelexer.cpp index f6018eb0db..fcb75eee7a 100644 --- a/src/prelexer.cpp +++ b/src/prelexer.cpp @@ -8,11 +8,13 @@ #include "constants.hpp" -namespace Sass { +namespace Sass +{ // using namespace Lexer; using namespace Constants; - namespace Prelexer { + namespace Prelexer + { /* @@ -72,139 +74,71 @@ namespace Sass { extern const char string_double_negates[] = "\"\\#"; const char* re_string_double_close(const char* src) { - return sequence < - // valid chars - zero_plus < - alternatives < - // escaped char - sequence < - exactly <'\\'>, - any_char - >, - // non interpolate hash - sequence < - exactly <'#'>, - negate < - exactly <'{'> - > - >, - // other valid chars - neg_class_char < - string_double_negates - > - > - >, - // quoted string closer - // or interpolate opening - alternatives < - exactly <'"'>, - lookahead < exactly< hash_lbrace > > - > - >(src); + return sequence< + // valid chars + zero_plus, any_char>, + // non interpolate hash + sequence, negate>>, + // other valid chars + neg_class_char>>, + // quoted string closer + // or interpolate opening + alternatives, lookahead>>>(src); } const char* re_string_double_open(const char* src) { - return sequence < - // quoted string opener - exactly <'"'>, - // valid chars - zero_plus < - alternatives < - // escaped char - sequence < - exactly <'\\'>, - any_char - >, - // non interpolate hash - sequence < - exactly <'#'>, - negate < - exactly <'{'> - > - >, - // other valid chars - neg_class_char < - string_double_negates - > - > - >, - // quoted string closer - // or interpolate opening - alternatives < - exactly <'"'>, - lookahead < exactly< hash_lbrace > > - > - >(src); + return sequence< + // quoted string opener + exactly<'"'>, + // valid chars + zero_plus, any_char>, + // non interpolate hash + sequence, negate>>, + // other valid chars + neg_class_char>>, + // quoted string closer + // or interpolate opening + alternatives, lookahead>>>(src); } extern const char string_single_negates[] = "'\\#"; const char* re_string_single_close(const char* src) { - return sequence < - // valid chars - zero_plus < - alternatives < - // escaped char - sequence < - exactly <'\\'>, - any_char - >, - // non interpolate hash - sequence < - exactly <'#'>, - negate < - exactly <'{'> - > - >, - // other valid chars - neg_class_char < - string_single_negates - > - > - >, - // quoted string closer - // or interpolate opening - alternatives < - exactly <'\''>, - lookahead < exactly< hash_lbrace > > - > - >(src); + return sequence< + // valid chars + zero_plus, any_char>, + // non interpolate hash + sequence, negate>>, + // other valid chars + neg_class_char>>, + // quoted string closer + // or interpolate opening + alternatives, lookahead>>>(src); } const char* re_string_single_open(const char* src) { - return sequence < - // quoted string opener - exactly <'\''>, - // valid chars - zero_plus < - alternatives < - // escaped char - sequence < - exactly <'\\'>, - any_char - >, - // non interpolate hash - sequence < - exactly <'#'>, - negate < - exactly <'{'> - > - >, - // other valid chars - neg_class_char < - string_single_negates - > - > - >, - // quoted string closer - // or interpolate opening - alternatives < - exactly <'\''>, - lookahead < exactly< hash_lbrace > > - > - >(src); + return sequence< + // quoted string opener + exactly<'\''>, + // valid chars + zero_plus, any_char>, + // non interpolate hash + sequence, negate>>, + // other valid chars + neg_class_char>>, + // quoted string closer + // or interpolate opening + alternatives, lookahead>>>(src); } /* @@ -215,75 +149,29 @@ namespace Sass { */ const char* re_string_uri_close(const char* src) { - return sequence < - non_greedy< - alternatives< - class_char< real_uri_chars >, - uri_character, - NONASCII, - ESCAPE - >, - alternatives< - sequence < optional < W >, exactly <')'> >, - lookahead < exactly< hash_lbrace > > - > - >, - optional < - sequence < optional < W >, exactly <')'> > - > - >(src); + return sequence, uri_character, NONASCII, ESCAPE>, + alternatives, exactly<')'>>, lookahead>>>, + optional, exactly<')'>>>>(src); } const char* re_string_uri_open(const char* src) { - return sequence < - exactly <'u'>, - exactly <'r'>, - exactly <'l'>, - exactly <'('>, - W, - alternatives< - quoted_string, - non_greedy< - alternatives< - class_char< real_uri_chars >, - uri_character, - NONASCII, - ESCAPE - >, - alternatives< - sequence < W, exactly <')'> >, - exactly< hash_lbrace > - > - > - > - >(src); + return sequence, exactly<'r'>, exactly<'l'>, exactly<'('>, W, + alternatives, uri_character, NONASCII, ESCAPE>, + alternatives>, exactly>>>>( + src); } // Match a line comment (/.*?(?=\n|\r\n?|\Z)/. const char* line_comment(const char* src) { - return sequence< - exactly < - slash_slash - >, - non_greedy< - any_char, - end_of_line - > - >(src); + return sequence, non_greedy>(src); } // Match a block comment. const char* block_comment(const char* src) { - return sequence< - delimited_by< - slash_star, - star_slash, - false - > - >(src); + return sequence>(src); } /* not use anymore - remove? const char* block_comment_prefix(const char* src) { @@ -296,295 +184,176 @@ namespace Sass { */ // Match zero plus white-space or line_comments - const char* optional_css_whitespace(const char* src) { - return zero_plus< alternatives >(src); + const char* optional_css_whitespace(const char* src) + { + return zero_plus>(src); } - const char* css_whitespace(const char* src) { - return one_plus< alternatives >(src); + const char* css_whitespace(const char* src) + { + return one_plus>(src); } // Match optional_css_whitepace plus block_comments - const char* optional_css_comments(const char* src) { - return zero_plus< alternatives >(src); + const char* optional_css_comments(const char* src) + { + return zero_plus>(src); } - const char* css_comments(const char* src) { - return one_plus< alternatives >(src); + const char* css_comments(const char* src) + { + return one_plus>(src); } // Match one backslash escaped char /\\./ const char* escape_seq(const char* src) { - return sequence< - exactly<'\\'>, - alternatives < - minmax_range< - 1, 3, xdigit - >, - any_char - >, - optional < - exactly <' '> - > - >(src); + return sequence, alternatives, any_char>, optional>>(src); } // Match identifier start const char* identifier_alpha(const char* src) { - return alternatives< - unicode_seq, - alpha, - unicode, - exactly<'-'>, - exactly<'_'>, - NONASCII, - ESCAPE, - escape_seq - >(src); + return alternatives, exactly<'_'>, NONASCII, ESCAPE, escape_seq>(src); } // Match identifier after start const char* identifier_alnum(const char* src) { - return alternatives< - unicode_seq, - alnum, - unicode, - exactly<'-'>, - exactly<'_'>, - NONASCII, - ESCAPE, - escape_seq - >(src); + return alternatives, exactly<'_'>, NONASCII, ESCAPE, escape_seq>(src); } // Match CSS identifiers. const char* strict_identifier(const char* src) { - return sequence< - one_plus < strict_identifier_alpha >, - zero_plus < strict_identifier_alnum > - // word_boundary not needed - >(src); + return sequence, zero_plus + // word_boundary not needed + >(src); } // Match CSS identifiers. const char* identifier(const char* src) { - return sequence< - zero_plus< exactly<'-'> >, - one_plus < identifier_alpha >, - zero_plus < identifier_alnum > - // word_boundary not needed - >(src); + return sequence>, one_plus, zero_plus + // word_boundary not needed + >(src); } const char* strict_identifier_alpha(const char* src) { - return alternatives < - alpha, - unicode, - escape_seq, - exactly<'_'> - >(src); + return alternatives>(src); } const char* strict_identifier_alnum(const char* src) { - return alternatives < - alnum, - unicode, - escape_seq, - exactly<'_'> - >(src); + return alternatives>(src); } // Match a single CSS unit const char* one_unit(const char* src) { - return sequence < - optional < exactly <'-'> >, - strict_identifier_alpha, - zero_plus < alternatives< - strict_identifier_alnum, - sequence < - one_plus < exactly<'-'> >, - strict_identifier_alpha - > - > > - >(src); + return sequence>, strict_identifier_alpha, + zero_plus>, strict_identifier_alpha>>>>( + src); } // Match numerator/denominator CSS units const char* multiple_units(const char* src) { - return - sequence < - one_unit, - zero_plus < - sequence < - exactly <'*'>, - one_unit - > - > - >(src); + return sequence, one_unit>>>(src); } // Match complex CSS unit identifiers const char* unit_identifier(const char* src) { - return sequence < - multiple_units, - optional < - sequence < - exactly <'/'>, - multiple_units - > > - >(src); + return sequence, multiple_units>>>(src); } const char* identifier_alnums(const char* src) { - return one_plus< identifier_alnum >(src); + return one_plus(src); } // Match number prefix ([\+\-]+) - const char* number_prefix(const char* src) { - return alternatives < - exactly < '+' >, - sequence < - exactly < '-' >, - optional_css_whitespace, - exactly< '-' > - > - >(src); + const char* number_prefix(const char* src) + { + return alternatives, sequence, optional_css_whitespace, exactly<'-'>>>(src); } // Match interpolant schemas - const char* identifier_schema(const char* src) { - - return sequence < - one_plus < - sequence < - zero_plus < - alternatives < - sequence < - optional < - exactly <'$'> - >, - identifier - >, - exactly <'-'> - > - >, - interpolant, - zero_plus < - alternatives < - digits, - sequence < - optional < - exactly <'$'> - >, - identifier - >, - quoted_string, - exactly<'-'> - > - > - > - >, - negate < - exactly<'%'> - > - > (src); + const char* identifier_schema(const char* src) + { + + return sequence< + one_plus>, identifier>, exactly<'-'>>>, interpolant, + zero_plus>, identifier>, quoted_string, exactly<'-'>>>>>, + negate>>(src); } // interpolants can be recursive/nested - const char* interpolant(const char* src) { - return recursive_scopes< exactly, exactly >(src); + const char* interpolant(const char* src) + { + return recursive_scopes, exactly>(src); } // $re_squote = /'(?:$re_itplnt|\\.|[^'])*'/ - const char* single_quoted_string(const char* src) { + const char* single_quoted_string(const char* src) + { // match a single quoted string, while skipping interpolants - return sequence < - exactly <'\''>, - zero_plus < - alternatives < - // skip escapes - sequence < - exactly < '\\' >, - re_linebreak - >, - escape_seq, - unicode_seq, - // skip interpolants - interpolant, - // skip non delimiters - any_char_but < '\'' > - > - >, - exactly <'\''> - >(src); + return sequence, zero_plus, re_linebreak>, escape_seq, unicode_seq, + // skip interpolants + interpolant, + // skip non delimiters + any_char_but<'\''>>>, + exactly<'\''>>(src); } // $re_dquote = /"(?:$re_itp|\\.|[^"])*"/ - const char* double_quoted_string(const char* src) { + const char* double_quoted_string(const char* src) + { // match a single quoted string, while skipping interpolants - return sequence < - exactly <'"'>, - zero_plus < - alternatives < - // skip escapes - sequence < - exactly < '\\' >, - re_linebreak - >, - escape_seq, - unicode_seq, - // skip interpolants - interpolant, - // skip non delimiters - any_char_but < '"' > - > - >, - exactly <'"'> - >(src); + return sequence, zero_plus, re_linebreak>, escape_seq, unicode_seq, + // skip interpolants + interpolant, + // skip non delimiters + any_char_but<'"'>>>, + exactly<'"'>>(src); } // $re_quoted = /(?:$re_squote|$re_dquote)/ - const char* quoted_string(const char* src) { + const char* quoted_string(const char* src) + { // match a quoted string, while skipping interpolants - return alternatives< - single_quoted_string, - double_quoted_string - >(src); + return alternatives(src); } - const char* sass_value(const char* src) { - return alternatives < - quoted_string, - identifier, - percentage, - hex, - dimension, - number - >(src); + const char* sass_value(const char* src) + { + return alternatives(src); } // this is basically `one_plus < sass_value >` // takes care to not parse invalid combinations - const char* value_combinations(const char* src) { + const char* value_combinations(const char* src) + { // `2px-2px` is invalid combo bool was_number = false; const char* pos; - while (src) { - if ((pos = alternatives < quoted_string, identifier, percentage, hex >(src))) { + while (src) + { + if ((pos = alternatives(src))) + { was_number = false; src = pos; - } else if (!was_number && !exactly<'+'>(src) && (pos = alternatives < dimension, number >(src))) { + } + else if (!was_number && !exactly<'+'>(src) && (pos = alternatives(src))) + { was_number = true; src = pos; - } else { + } + else + { break; } } @@ -598,19 +367,12 @@ namespace Sass { // `2px1px` is valid number (unit `px1px`) const char* value_schema(const char* src) { - return sequence < - one_plus < - sequence < - optional < value_combinations >, - interpolant, - optional < value_combinations > - > - > - >(src); + return sequence, interpolant, optional>>>(src); } // Match CSS '@' keywords. - const char* at_keyword(const char* src) { + const char* at_keyword(const char* src) + { return sequence, identifier>(src); } @@ -631,72 +393,18 @@ namespace Sass { }xi) || tok(COMMENT) || tok(SINGLE_LINE_COMMENT) || interp_string || interp_uri || interpolation(:warn_for_color) */ - const char* re_almost_any_value_token(const char* src) { - - return alternatives < - one_plus < - alternatives < - sequence < - exactly <'\\'>, - any_char - >, - sequence < - negate < - sequence < - exactly < url_kwd >, - exactly <'('> - > - >, - neg_class_char < - almost_any_value_class - > - >, - sequence < - exactly <'/'>, - negate < - alternatives < - exactly <'/'>, - exactly <'*'> - > - > - >, - sequence < - exactly <'\\'>, - exactly <'#'>, - negate < - exactly <'{'> - > - >, - sequence < - exactly <'!'>, - negate < - alpha - > - > - > - >, - block_comment, - line_comment, - interpolant, - space, - sequence < - exactly<'u'>, - exactly<'r'>, - exactly<'l'>, - exactly<'('>, - zero_plus < - alternatives < - class_char< real_uri_chars >, - uri_character, - NONASCII, - ESCAPE - > - >, - // false => /url\(#{W}(#{URLCHAR}*?)(#{W}\)|#\{)/, - // true => /(#{URLCHAR}*?)(#{W}\)|#\{)/ - exactly<')'> - > - >(src); + const char* re_almost_any_value_token(const char* src) + { + + return alternatives< + one_plus, any_char>, sequence, exactly<'('>>>, neg_class_char>, + sequence, negate, exactly<'*'>>>>, + sequence, exactly<'#'>, negate>>, sequence, negate>>>, + block_comment, line_comment, interpolant, space, + sequence, exactly<'r'>, exactly<'l'>, exactly<'('>, zero_plus, uri_character, NONASCII, ESCAPE>>, + // false => /url\(#{W}(#{URLCHAR}*?)(#{W}\)|#\{)/, + // true => /(#{URLCHAR}*?)(#{W}\)|#\{)/ + exactly<')'>>>(src); } /* @@ -704,193 +412,169 @@ namespace Sass { :each, :while, :if, :else, :extend, :import, :media, :charset, :content, :_moz_document, :at_root, :error] */ - const char* re_special_directive(const char* src) { - return alternatives < - word < mixin_kwd >, - word < include_kwd >, - word < function_kwd >, - word < return_kwd >, - word < debug_kwd >, - word < warn_kwd >, - word < for_kwd >, - word < each_kwd >, - word < while_kwd >, - word < if_kwd >, - word < else_kwd >, - word < extend_kwd >, - word < import_kwd >, - word < media_kwd >, - word < charset_kwd >, - word < content_kwd >, - // exactly < moz_document_kwd >, - word < at_root_kwd >, - word < error_kwd > - >(src); - } - - const char* re_prefixed_directive(const char* src) { - return sequence < - optional < - sequence < - exactly <'-'>, - one_plus < alnum >, - exactly <'-'> - > - >, - exactly < supports_kwd > - >(src); - } - - const char* re_reference_combinator(const char* src) { - return sequence < - optional < - sequence < - zero_plus < - exactly <'-'> - >, - identifier, - exactly <'|'> - > - >, - zero_plus < - exactly <'-'> - >, - identifier - >(src); - } - - const char* static_reference_combinator(const char* src) { - return sequence < - exactly <'/'>, - re_reference_combinator, - exactly <'/'> - >(src); - } - - const char* schema_reference_combinator(const char* src) { - return sequence < - exactly <'/'>, - optional < - sequence < - css_ip_identifier, - exactly <'|'> - > - >, - css_ip_identifier, - exactly <'/'> - > (src); - } - - const char* kwd_import(const char* src) { + const char* re_special_directive(const char* src) + { + return alternatives, word, word, word, word, + word, word, word, word, word, word, + word, word, word, word, word, + // exactly < moz_document_kwd >, + word, word>(src); + } + + const char* re_prefixed_directive(const char* src) + { + return sequence, one_plus, exactly<'-'>>>, exactly>(src); + } + + const char* re_reference_combinator(const char* src) + { + return sequence>, identifier, exactly<'|'>>>, zero_plus>, identifier>( + src); + } + + const char* static_reference_combinator(const char* src) + { + return sequence, re_reference_combinator, exactly<'/'>>(src); + } + + const char* schema_reference_combinator(const char* src) + { + return sequence, optional>>, css_ip_identifier, exactly<'/'>>( + src); + } + + const char* kwd_import(const char* src) + { return word(src); } - const char* kwd_at_root(const char* src) { + const char* kwd_at_root(const char* src) + { return word(src); } - const char* kwd_with_directive(const char* src) { + const char* kwd_with_directive(const char* src) + { return word(src); } - const char* kwd_without_directive(const char* src) { + const char* kwd_without_directive(const char* src) + { return word(src); } - const char* kwd_media(const char* src) { + const char* kwd_media(const char* src) + { return word(src); } - const char* kwd_supports_directive(const char* src) { + const char* kwd_supports_directive(const char* src) + { return word(src); } - const char* kwd_mixin(const char* src) { + const char* kwd_mixin(const char* src) + { return word(src); } - const char* kwd_function(const char* src) { + const char* kwd_function(const char* src) + { return word(src); } - const char* kwd_return_directive(const char* src) { + const char* kwd_return_directive(const char* src) + { return word(src); } - const char* kwd_include_directive(const char* src) { + const char* kwd_include_directive(const char* src) + { return word(src); } - const char* kwd_content_directive(const char* src) { + const char* kwd_content_directive(const char* src) + { return word(src); } - const char* kwd_charset_directive(const char* src) { + const char* kwd_charset_directive(const char* src) + { return word(src); } - const char* kwd_extend(const char* src) { + const char* kwd_extend(const char* src) + { return word(src); } - const char* kwd_if_directive(const char* src) { + const char* kwd_if_directive(const char* src) + { return word(src); } - const char* kwd_else_directive(const char* src) { + const char* kwd_else_directive(const char* src) + { return word(src); } - const char* elseif_directive(const char* src) { - return sequence< exactly< else_kwd >, - optional_css_comments, - word< if_after_else_kwd > >(src); + const char* elseif_directive(const char* src) + { + return sequence, optional_css_comments, word>(src); } - const char* kwd_for_directive(const char* src) { + const char* kwd_for_directive(const char* src) + { return word(src); } - const char* kwd_from(const char* src) { + const char* kwd_from(const char* src) + { return word(src); } - const char* kwd_to(const char* src) { + const char* kwd_to(const char* src) + { return word(src); } - const char* kwd_through(const char* src) { + const char* kwd_through(const char* src) + { return word(src); } - const char* kwd_each_directive(const char* src) { + const char* kwd_each_directive(const char* src) + { return word(src); } - const char* kwd_in(const char* src) { + const char* kwd_in(const char* src) + { return word(src); } - const char* kwd_while_directive(const char* src) { + const char* kwd_while_directive(const char* src) + { return word(src); } - const char* name(const char* src) { - return one_plus< alternatives< alnum, - exactly<'-'>, - exactly<'_'>, - escape_seq > >(src); + const char* name(const char* src) + { + return one_plus, exactly<'_'>, escape_seq>>(src); } - const char* kwd_warn(const char* src) { + const char* kwd_warn(const char* src) + { return word(src); } - const char* kwd_err(const char* src) { + const char* kwd_err(const char* src) + { return word(src); } - const char* kwd_dbg(const char* src) { + const char* kwd_dbg(const char* src) + { return word(src); } @@ -899,125 +583,98 @@ namespace Sass { return sequence< exactly<'@'>, identifier >(src); } */ - const char* kwd_null(const char* src) { + const char* kwd_null(const char* src) + { return word(src); } - const char* css_identifier(const char* src) { - return sequence < - zero_plus < - exactly <'-'> - >, - identifier - >(src); + const char* css_identifier(const char* src) + { + return sequence>, identifier>(src); } - const char* css_ip_identifier(const char* src) { - return sequence < - zero_plus < - exactly <'-'> - >, - alternatives < - identifier, - interpolant - > - >(src); + const char* css_ip_identifier(const char* src) + { + return sequence>, alternatives>(src); } // Match CSS type selectors - const char* namespace_prefix(const char* src) { - return sequence < - optional < - alternatives < - exactly <'*'>, - css_identifier - > - >, - exactly <'|'>, - negate < - exactly <'='> - > - >(src); + const char* namespace_prefix(const char* src) + { + return sequence, css_identifier>>, exactly<'|'>, negate>>(src); } // Match CSS type selectors - const char* namespace_schema(const char* src) { - return sequence < - optional < - alternatives < - exactly <'*'>, - css_ip_identifier - > - >, - exactly<'|'>, - negate < - exactly <'='> - > - >(src); - } - - const char* hyphens_and_identifier(const char* src) { - return sequence< zero_plus< exactly< '-' > >, identifier_alnums >(src); - } - const char* hyphens_and_name(const char* src) { - return sequence< zero_plus< exactly< '-' > >, name >(src); - } - const char* universal(const char* src) { - return sequence< optional, exactly<'*'> >(src); + const char* namespace_schema(const char* src) + { + return sequence, css_ip_identifier>>, exactly<'|'>, negate>>(src); + } + + const char* hyphens_and_identifier(const char* src) + { + return sequence>, identifier_alnums>(src); + } + const char* hyphens_and_name(const char* src) + { + return sequence>, name>(src); + } + const char* universal(const char* src) + { + return sequence, exactly<'*'>>(src); } // Match CSS id names. - const char* id_name(const char* src) { - return sequence, identifier_alnums >(src); + const char* id_name(const char* src) + { + return sequence, identifier_alnums>(src); } // Match CSS class names. - const char* class_name(const char* src) { - return sequence, identifier >(src); + const char* class_name(const char* src) + { + return sequence, identifier>(src); } // Attribute name in an attribute selector. - const char* attribute_name(const char* src) { - return alternatives< sequence< optional, identifier>, - identifier >(src); + const char* attribute_name(const char* src) + { + return alternatives, identifier>, identifier>(src); } // match placeholder selectors - const char* placeholder(const char* src) { - return sequence, identifier_alnums >(src); + const char* placeholder(const char* src) + { + return sequence, identifier_alnums>(src); } // Match CSS numeric constants. - const char* op(const char* src) { + const char* op(const char* src) + { return class_char(src); } - const char* sign(const char* src) { + const char* sign(const char* src) + { return class_char(src); } - const char* unsigned_number(const char* src) { - return alternatives, - exactly<'.'>, - one_plus >, - digits>(src); - } - const char* number(const char* src) { - return sequence< optional, unsigned_number>(src); - } - const char* coefficient(const char* src) { - return alternatives< sequence< optional, digits >, - sign >(src); - } - const char* binomial(const char* src) { - return sequence < - optional < sign >, - optional < digits >, - exactly <'n'>, - zero_plus < sequence < - optional_css_whitespace, sign, - optional_css_whitespace, digits - > > - >(src); - } - const char* percentage(const char* src) { - return sequence< number, exactly<'%'> >(src); - } - const char* ampersand(const char* src) { + const char* unsigned_number(const char* src) + { + return alternatives, exactly<'.'>, one_plus>, digits>(src); + } + const char* number(const char* src) + { + return sequence, unsigned_number>(src); + } + const char* coefficient(const char* src) + { + return alternatives, digits>, sign>(src); + } + const char* binomial(const char* src) + { + return sequence, optional, exactly<'n'>, + zero_plus>>(src); + } + const char* percentage(const char* src) + { + return sequence>(src); + } + const char* ampersand(const char* src) + { return exactly<'&'>(src); } @@ -1025,21 +682,25 @@ namespace Sass { const char* em(const char* src) { return sequence< number, exactly >(src); } */ - const char* dimension(const char* src) { - return sequence(src); + const char* dimension(const char* src) + { + return sequence(src); } - const char* hex(const char* src) { - const char* p = sequence< exactly<'#'>, one_plus >(src); + const char* hex(const char* src) + { + const char* p = sequence, one_plus>(src); ptrdiff_t len = p - src; return (len != 4 && len != 7) ? 0 : p; } - const char* hexa(const char* src) { - const char* p = sequence< exactly<'#'>, one_plus >(src); + const char* hexa(const char* src) + { + const char* p = sequence, one_plus>(src); ptrdiff_t len = p - src; return (len != 4 && len != 7 && len != 9) ? 0 : p; } - const char* hex0(const char* src) { - const char* p = sequence< exactly<'0'>, exactly<'x'>, one_plus >(src); + const char* hex0(const char* src) + { + const char* p = sequence, exactly<'x'>, one_plus>(src); ptrdiff_t len = p - src; return (len != 5 && len != 8) ? 0 : p; } @@ -1050,21 +711,9 @@ namespace Sass { }*/ // Match CSS uri specifiers. - const char* uri_prefix(const char* src) { - return sequence < - exactly < - url_kwd - >, - zero_plus < - sequence < - exactly <'-'>, - one_plus < - alpha - > - > - >, - exactly <'('> - >(src); + const char* uri_prefix(const char* src) + { + return sequence, zero_plus, one_plus>>, exactly<'('>>(src); } // TODO: rename the following two functions @@ -1079,7 +728,8 @@ namespace Sass { /* no longer used - remove? const char* url_value(const char* src) { return sequence< optional< sequence< identifier, exactly<':'> > >, // optional protocol - one_plus< sequence< zero_plus< exactly<'/'> >, filename > >, // one or more folders and/or trailing filename + one_plus< sequence< zero_plus< exactly<'/'> >, filename > >, // one or more + folders and/or trailing filename optional< exactly<'/'> > >(src); }*/ /* no longer used - remove? @@ -1088,94 +738,90 @@ namespace Sass { filename_schema >(src); // optional trailing slash }*/ // Match CSS "!important" keyword. - const char* kwd_important(const char* src) { - return sequence< exactly<'!'>, - optional_css_whitespace, - word >(src); + const char* kwd_important(const char* src) + { + return sequence, optional_css_whitespace, word>(src); } // Match CSS "!optional" keyword. - const char* kwd_optional(const char* src) { - return sequence< exactly<'!'>, - optional_css_whitespace, - word >(src); + const char* kwd_optional(const char* src) + { + return sequence, optional_css_whitespace, word>(src); } // Match Sass "!default" keyword. - const char* default_flag(const char* src) { - return sequence< exactly<'!'>, - optional_css_whitespace, - word >(src); + const char* default_flag(const char* src) + { + return sequence, optional_css_whitespace, word>(src); } // Match Sass "!global" keyword. - const char* global_flag(const char* src) { - return sequence< exactly<'!'>, - optional_css_whitespace, - word >(src); + const char* global_flag(const char* src) + { + return sequence, optional_css_whitespace, word>(src); } // Match CSS pseudo-class/element prefixes. - const char* pseudo_prefix(const char* src) { - return sequence< exactly<':'>, optional< exactly<':'> > >(src); + const char* pseudo_prefix(const char* src) + { + return sequence, optional>>(src); } // Match CSS function call openers. - const char* functional_schema(const char* src) { - return sequence < - one_plus < - sequence < - zero_plus < - alternatives < - identifier, - exactly <'-'> - > - >, - one_plus < - sequence < - interpolant, - alternatives < - digits, - identifier, - exactly<'+'>, - exactly<'-'> - > - > - > - > - >, - negate < - exactly <'%'> - >, - lookahead < - exactly <'('> - > - > (src); - } - - const char* re_nothing(const char* src) { + const char* functional_schema(const char* src) + { + return sequence>>, + one_plus, exactly<'-'>>>>>>, + negate>, lookahead>>(src); + } + + const char* re_nothing(const char* src) + { return src; } - const char* re_functional(const char* src) { - return sequence< identifier, optional < block_comment >, exactly<'('> >(src); + const char* re_functional(const char* src) + { + return sequence, exactly<'('>>(src); } - const char* re_pseudo_selector(const char* src) { - return sequence< identifier, optional < block_comment >, exactly<'('> >(src); + const char* re_pseudo_selector(const char* src) + { + return sequence, exactly<'('>>(src); } // Match the CSS negation pseudo-class. - const char* pseudo_not(const char* src) { - return word< pseudo_not_kwd >(src); + const char* pseudo_not(const char* src) + { + return word(src); } // Match CSS 'odd' and 'even' keywords for functional pseudo-classes. - const char* even(const char* src) { + const char* even(const char* src) + { return word(src); } - const char* odd(const char* src) { + const char* odd(const char* src) + { return word(src); } // Match CSS attribute-matching operators. - const char* exact_match(const char* src) { return exactly<'='>(src); } - const char* class_match(const char* src) { return exactly(src); } - const char* dash_match(const char* src) { return exactly(src); } - const char* prefix_match(const char* src) { return exactly(src); } - const char* suffix_match(const char* src) { return exactly(src); } - const char* substring_match(const char* src) { return exactly(src); } + const char* exact_match(const char* src) + { + return exactly<'='>(src); + } + const char* class_match(const char* src) + { + return exactly(src); + } + const char* dash_match(const char* src) + { + return exactly(src); + } + const char* prefix_match(const char* src) + { + return exactly(src); + } + const char* suffix_match(const char* src) + { + return exactly(src); + } + const char* substring_match(const char* src) + { + return exactly(src); + } // Match CSS combinators. /* not used anymore - remove? const char* adjacent_to(const char* src) { @@ -1192,146 +838,116 @@ namespace Sass { }*/ // Match SCSS variable names. - const char* variable(const char* src) { + const char* variable(const char* src) + { return sequence, identifier>(src); } // parse `calc`, `-a-calc` and `--b-c-calc` // but do not parse `foocalc` or `foo-calc` - const char* calc_fn_call(const char* src) { - return sequence < - optional < sequence < - hyphens, - one_plus < sequence < - strict_identifier, - hyphens - > > - > >, - exactly < calc_fn_kwd >, - word_boundary - >(src); + const char* calc_fn_call(const char* src) + { + return sequence>>>, exactly, word_boundary>( + src); } // Match Sass boolean keywords. - const char* kwd_true(const char* src) { + const char* kwd_true(const char* src) + { return word(src); } - const char* kwd_false(const char* src) { + const char* kwd_false(const char* src) + { return word(src); } - const char* kwd_only(const char* src) { - return keyword < only_kwd >(src); + const char* kwd_only(const char* src) + { + return keyword(src); } - const char* kwd_and(const char* src) { - return keyword < and_kwd >(src); + const char* kwd_and(const char* src) + { + return keyword(src); } - const char* kwd_or(const char* src) { - return keyword < or_kwd >(src); + const char* kwd_or(const char* src) + { + return keyword(src); } - const char* kwd_not(const char* src) { - return keyword < not_kwd >(src); + const char* kwd_not(const char* src) + { + return keyword(src); } - const char* kwd_eq(const char* src) { + const char* kwd_eq(const char* src) + { return exactly(src); } - const char* kwd_neq(const char* src) { + const char* kwd_neq(const char* src) + { return exactly(src); } - const char* kwd_gt(const char* src) { + const char* kwd_gt(const char* src) + { return exactly(src); } - const char* kwd_gte(const char* src) { + const char* kwd_gte(const char* src) + { return exactly(src); } - const char* kwd_lt(const char* src) { + const char* kwd_lt(const char* src) + { return exactly(src); } - const char* kwd_lte(const char* src) { + const char* kwd_lte(const char* src) + { return exactly(src); } // match specific IE syntax - const char* ie_progid(const char* src) { - return sequence < - word, - exactly<':'>, - alternatives< identifier_schema, identifier >, - zero_plus< sequence< - exactly<'.'>, - alternatives< identifier_schema, identifier > - > >, - zero_plus < sequence< - exactly<'('>, - optional_css_whitespace, - optional < sequence< - alternatives< variable, identifier_schema, identifier >, - optional_css_whitespace, - exactly<'='>, - optional_css_whitespace, - alternatives< variable, identifier_schema, identifier, quoted_string, number, hexa >, - zero_plus< sequence< - optional_css_whitespace, - exactly<','>, - optional_css_whitespace, - sequence< - alternatives< variable, identifier_schema, identifier >, - optional_css_whitespace, - exactly<'='>, - optional_css_whitespace, - alternatives< variable, identifier_schema, identifier, quoted_string, number, hexa > - > - > > - > >, - optional_css_whitespace, - exactly<')'> - > > - >(src); - } - const char* ie_expression(const char* src) { - return sequence < word, exactly<'('>, skip_over_scopes< exactly<'('>, exactly<')'> > >(src); - } - const char* ie_property(const char* src) { - return alternatives < ie_expression, ie_progid >(src); + const char* ie_progid(const char* src) + { + return sequence< + word, exactly<':'>, alternatives, + zero_plus, alternatives>>, + zero_plus, optional_css_whitespace, + optional, optional_css_whitespace, exactly<'='>, optional_css_whitespace, + alternatives, + zero_plus, optional_css_whitespace, + sequence, optional_css_whitespace, exactly<'='>, optional_css_whitespace, + alternatives>>>>>, + optional_css_whitespace, exactly<')'>>>>(src); + } + const char* ie_expression(const char* src) + { + return sequence, exactly<'('>, skip_over_scopes, exactly<')'>>>(src); + } + const char* ie_property(const char* src) + { + return alternatives(src); } // const char* ie_args(const char* src) { - // return sequence< alternatives< ie_keyword_arg, value_schema, quoted_string, interpolant, number, identifier, delimited_by< '(', ')', true> >, - // zero_plus< sequence< optional_css_whitespace, exactly<','>, optional_css_whitespace, alternatives< ie_keyword_arg, value_schema, quoted_string, interpolant, number, identifier, delimited_by<'(', ')', true> > > > >(src); + // return sequence< alternatives< ie_keyword_arg, value_schema, quoted_string, interpolant, + // number, identifier, delimited_by< '(', ')', true> >, + // zero_plus< sequence< optional_css_whitespace, exactly<','>, + // optional_css_whitespace, alternatives< ie_keyword_arg, value_schema, + // quoted_string, interpolant, number, identifier, delimited_by<'(', ')', + // true> > > > >(src); // } - const char* ie_keyword_arg_property(const char* src) { - return alternatives < - variable, - identifier_schema, - identifier - >(src); - } - const char* ie_keyword_arg_value(const char* src) { - return alternatives < - variable, - identifier_schema, - identifier, - quoted_string, - number, - hexa, - sequence < - exactly < '(' >, - skip_over_scopes < - exactly < '(' >, - exactly < ')' > - > - > - >(src); - } - - const char* ie_keyword_arg(const char* src) { - return sequence < - ie_keyword_arg_property, - optional_css_whitespace, - exactly<'='>, - optional_css_whitespace, - ie_keyword_arg_value - >(src); + const char* ie_keyword_arg_property(const char* src) + { + return alternatives(src); + } + const char* ie_keyword_arg_value(const char* src) + { + return alternatives, skip_over_scopes, exactly<')'>>>>(src); + } + + const char* ie_keyword_arg(const char* src) + { + return sequence >(src); }*/ - const char* H(const char* src) { - return std::isxdigit(*src) ? src+1 : 0; + const char* H(const char* src) + { + return std::isxdigit(*src) ? src + 1 : 0; } - const char* W(const char* src) { - return zero_plus< alternatives< - space, - exactly< '\t' >, - exactly< '\r' >, - exactly< '\n' >, - exactly< '\f' > - > >(src); + const char* W(const char* src) + { + return zero_plus, exactly<'\r'>, exactly<'\n'>, exactly<'\f'>>>(src); } - const char* UUNICODE(const char* src) { - return sequence< exactly<'\\'>, - between, - optional< W > - >(src); + const char* UUNICODE(const char* src) + { + return sequence, between, optional>(src); } - const char* NONASCII(const char* src) { + const char* NONASCII(const char* src) + { return nonascii(src); } - const char* ESCAPE(const char* src) { - return alternatives< - UUNICODE, - sequence< - exactly<'\\'>, - alternatives< - NONASCII, - escapable_character - > - > - >(src); - } - - const char* list_terminator(const char* src) { - return alternatives < - exactly<';'>, - exactly<'}'>, - exactly<'{'>, - exactly<')'>, - exactly<']'>, - exactly<':'>, - end_of_file, - exactly, - default_flag, - global_flag - >(src); + const char* ESCAPE(const char* src) + { + return alternatives, alternatives>>(src); + } + + const char* list_terminator(const char* src) + { + return alternatives, exactly<'}'>, exactly<'{'>, exactly<')'>, exactly<']'>, + exactly<':'>, end_of_file, exactly, default_flag, global_flag>(src); }; - const char* space_list_terminator(const char* src) { - return alternatives < - exactly<','>, - list_terminator - >(src); + const char* space_list_terminator(const char* src) + { + return alternatives, list_terminator>(src); }; @@ -1449,262 +1041,131 @@ namespace Sass { // >(src); // } - const char* real_uri_suffix(const char* src) { - return sequence< W, exactly< ')' > >(src); + const char* real_uri_suffix(const char* src) + { + return sequence>(src); } - const char* real_uri_value(const char* src) { - return - sequence< - non_greedy< - alternatives< - class_char< real_uri_chars >, - uri_character, - NONASCII, - ESCAPE - >, - alternatives< - real_uri_suffix, - exactly< hash_lbrace > - > - > - > - (src); - } - - const char* static_string(const char* src) { + const char* real_uri_value(const char* src) + { + return sequence, uri_character, NONASCII, ESCAPE>, + alternatives>>>(src); + } + + const char* static_string(const char* src) + { const char* pos = src; - const char * s = quoted_string(pos); + const char* s = quoted_string(pos); Token t(pos, s); - const unsigned int p = count_interval< interpolant >(t.begin, t.end); + const unsigned int p = count_interval(t.begin, t.end); return (p == 0) ? t.end : 0; } - const char* unicode_seq(const char* src) { - return sequence < - alternatives < - exactly< 'U' >, - exactly< 'u' > - >, - exactly< '+' >, - padded_token < - 6, xdigit, - exactly < '?' > - > - >(src); - } - - const char* static_component(const char* src) { - return alternatives< identifier, - static_string, - percentage, - hex, - exactly<'|'>, - // exactly<'+'>, - sequence < number, unit_identifier >, - number, - sequence< exactly<'!'>, word > - >(src); - } - - const char* static_property(const char* src) { - return - sequence < - zero_plus< - sequence < - optional_css_comments, - alternatives < - exactly<','>, - exactly<'('>, - exactly<')'>, - kwd_optional, - quoted_string, - interpolant, - identifier, - percentage, - dimension, - variable, - alnum, - sequence < - exactly <'\\'>, - any_char - > - > - > - >, - lookahead < - sequence < - optional_css_comments, - alternatives < - exactly <';'>, - exactly <'}'>, - end_of_file - > - > - > - >(src); - } - - const char* static_value(const char* src) { - return sequence< sequence< - static_component, - zero_plus< identifier > - >, - zero_plus < sequence< - alternatives< - sequence< optional_spaces, alternatives< - exactly < '/' >, - exactly < ',' >, - exactly < ' ' > - >, optional_spaces >, - spaces - >, - static_component - > >, - zero_plus < spaces >, - alternatives< exactly<';'>, exactly<'}'> > - >(src); + const char* unicode_seq(const char* src) + { + return sequence, exactly<'u'>>, exactly<'+'>, padded_token<6, xdigit, exactly<'?'>>>(src); } - const char* parenthese_scope(const char* src) { - return sequence < - exactly < '(' >, - skip_over_scopes < - exactly < '(' >, - exactly < ')' > - > - >(src); - } - - const char* re_selector_list(const char* src) { - return alternatives < - // partial bem selector - sequence < - ampersand, - one_plus < - exactly < '-' > - >, - word_boundary, - optional_spaces - >, - // main selector matching - one_plus < - alternatives < - // consume whitespace and comments - spaces, block_comment, line_comment, - // match `/deep/` selector (pass-trough) - // there is no functionality for it yet - schema_reference_combinator, - // match selector ops /[*&%,\[\]]/ - class_char < selector_lookahead_ops >, - // match selector combinators /[>+~]/ - class_char < selector_combinator_ops >, - // match attribute compare operators - sequence < - exactly <'('>, - optional_spaces, - optional , - optional_spaces, - exactly <')'> - >, - alternatives < - exact_match, class_match, dash_match, - prefix_match, suffix_match, substring_match - >, - // main selector match - sequence < - // allow namespace prefix - optional < namespace_schema >, - // modifiers prefixes - alternatives < - sequence < - exactly <'#'>, - // not for interpolation - negate < exactly <'{'> > - >, - // class match - exactly <'.'>, - // single or double colon - optional < pseudo_prefix > - >, - // accept hypens in token - one_plus < sequence < - // can start with hyphens - zero_plus < exactly<'-'> >, - // now the main token - alternatives < - kwd_optional, - exactly <'*'>, - quoted_string, - interpolant, - identifier, - variable, - percentage, - binomial, - dimension, - alnum - > - > >, - // can also end with hyphens - zero_plus < exactly<'-'> > - > - > - > - >(src); - } - - const char* type_selector(const char* src) { - return sequence< optional, identifier>(src); - } - const char* re_type_selector(const char* src) { - return alternatives< type_selector, universal, quoted_string, dimension, percentage, number, identifier_alnums >(src); - } - const char* re_type_selector2(const char* src) { - return alternatives< type_selector, universal, quoted_string, dimension, percentage, number, identifier_alnums >(src); - } - const char* re_static_expression(const char* src) { - return sequence< number, optional_spaces, exactly<'/'>, optional_spaces, number >(src); + const char* static_component(const char* src) + { + return alternatives, + // exactly<'+'>, + sequence, number, sequence, word>>(src); + } + + const char* static_property(const char* src) + { + return sequence< + zero_plus, exactly<'('>, exactly<')'>, kwd_optional, quoted_string, interpolant, identifier, percentage, + dimension, variable, alnum, sequence, any_char>>>>, + lookahead, exactly<'}'>, end_of_file>>>>(src); + } + + const char* static_value(const char* src) + { + return sequence>, + zero_plus, exactly<','>, exactly<' '>>, optional_spaces>, spaces>, static_component>>, + zero_plus, alternatives, exactly<'}'>>>(src); + } + + const char* parenthese_scope(const char* src) + { + return sequence, skip_over_scopes, exactly<')'>>>(src); + } + + const char* re_selector_list(const char* src) + { + return alternatives< + // partial bem selector + sequence>, word_boundary, optional_spaces>, + // main selector matching + one_plus, + // match selector combinators /[>+~]/ + class_char, + // match attribute compare operators + sequence, optional_spaces, optional, optional_spaces, exactly<')'>>, + alternatives, + // main selector match + sequence< + // allow namespace prefix + optional, + // modifiers prefixes + alternatives, + // not for interpolation + negate>>, + // class match + exactly<'.'>, + // single or double colon + optional>, + // accept hypens in token + one_plus>, + // now the main token + alternatives, quoted_string, interpolant, identifier, variable, percentage, binomial, dimension, alnum>>>, + // can also end with hyphens + zero_plus>>>>>(src); + } + + const char* type_selector(const char* src) + { + return sequence, identifier>(src); + } + const char* re_type_selector(const char* src) + { + return alternatives(src); + } + const char* re_type_selector2(const char* src) + { + return alternatives(src); + } + const char* re_static_expression(const char* src) + { + return sequence, optional_spaces, number>(src); } // lexer special_fn: these functions cannot be overloaded // (/((-[\w-]+-)?(calc|element)|expression|progid:[a-z\.]*)\(/i) - const char* re_special_fun(const char* src) { + const char* re_special_fun(const char* src) + { // match this first as we test prefix hyphens - if (const char* calc = calc_fn_call(src)) { + if (const char* calc = calc_fn_call(src)) + { return calc; } - return sequence < - optional < - sequence < - exactly <'-'>, - one_plus < - alternatives < - alpha, - exactly <'+'>, - exactly <'-'> - > - > - > - >, - alternatives < - word < expression_kwd >, - sequence < - sequence < - exactly < progid_kwd >, - exactly <':'> - >, - zero_plus < - alternatives < - char_range <'a', 'z'>, - exactly <'.'> - > - > - > - > - >(src); + return sequence, one_plus, exactly<'-'>>>>>, + alternatives, sequence, exactly<':'>>, + zero_plus, exactly<'.'>>>>>>( + src); } - } } diff --git a/src/prelexer.hpp b/src/prelexer.hpp index 4d9f2eb0f0..91360057a6 100644 --- a/src/prelexer.hpp +++ b/src/prelexer.hpp @@ -4,9 +4,11 @@ #include #include "lexer.hpp" -namespace Sass { +namespace Sass +{ // using namespace Lexer; - namespace Prelexer { + namespace Prelexer + { //#################################### // KEYWORD "REGEX" MATCHERS @@ -41,12 +43,13 @@ namespace Sass { //#################################### // Match a sequence of characters delimited by the supplied chars. - template - const char* delimited_by(const char* src) { + template const char* delimited_by(const char* src) + { src = exactly(src); if (!src) return 0; const char* stop; - while (true) { + while (true) + { if (!*src) return 0; stop = exactly(src); if (stop && (!esc || *(src - 1) != '\\')) return stop; @@ -58,52 +61,61 @@ namespace Sass { // this will savely skip over all quoted strings // recursive skip stuff delimited by start/stop // first start/opener must be consumed already! - template - const char* skip_over_scopes(const char* src, const char* end) { + template + const char* skip_over_scopes(const char* src, const char* end) + { size_t level = 0; bool in_squote = false; bool in_dquote = false; // bool in_braces = false; - while (*src) { + while (*src) + { // check for abort condition if (end && src >= end) break; // has escaped sequence? - if (*src == '\\') { - ++ src; // skip this (and next) + if (*src == '\\') + { + ++src; // skip this (and next) } - else if (*src == '"') { - in_dquote = ! in_dquote; + else if (*src == '"') + { + in_dquote = !in_dquote; } - else if (*src == '\'') { - in_squote = ! in_squote; + else if (*src == '\'') + { + in_squote = !in_squote; } - else if (in_dquote || in_squote) { + else if (in_dquote || in_squote) + { // take everything literally } // find another opener inside? - else if (const char* pos = start(src)) { - ++ level; // increase counter + else if (const char* pos = start(src)) + { + ++level; // increase counter src = pos - 1; // advance position } // look for the closer (maybe final, maybe not) - else if (const char* final = stop(src)) { + else if (const char* final = stop(src)) + { // only close one level? - if (level > 0) -- level; + if (level > 0) --level; // return position at end of stop // delimiter may be multiple chars - else return final; + else + return final; // advance position src = final - 1; } // next - ++ src; + ++src; } return 0; @@ -117,14 +129,14 @@ namespace Sass { // this will savely skip over all quoted strings // recursive skip stuff delimited by start/stop // first start/opener must be consumed already! - template - const char* skip_over_scopes(const char* src) { + template const char* skip_over_scopes(const char* src) + { return skip_over_scopes(src, 0); } // Match a sequence of characters delimited by the supplied chars. - template - const char* recursive_scopes(const char* src) { + template const char* recursive_scopes(const char* src) + { // parse opener src = start(src); // abort if not found @@ -134,12 +146,13 @@ namespace Sass { } // Match a sequence of characters delimited by the supplied strings. - template - const char* delimited_by(const char* src) { + template const char* delimited_by(const char* src) + { src = exactly(src); if (!src) return 0; const char* stop; - while (true) { + while (true) + { if (!*src) return 0; stop = exactly(src); if (stop && (!esc || *(src - 1) != '\\')) return stop; @@ -148,13 +161,15 @@ namespace Sass { } // Tries to match a certain number of times (between the supplied interval). - template - const char* between(const char* src) { - for (size_t i = 0; i < lo; ++i) { + template const char* between(const char* src) + { + for (size_t i = 0; i < lo; ++i) + { src = mx(src); if (!src) return 0; } - for (size_t i = lo; i <= hi; ++i) { + for (size_t i = lo; i <= hi; ++i) + { const char* new_src = mx(src); if (!new_src) return src; src = new_src; @@ -381,100 +396,121 @@ namespace Sass { const char* static_value(const char* src); // Utility functions for finding and counting characters in a string. - template - const char* find_first(const char* src) { - while (*src && *src != c) ++src; + template const char* find_first(const char* src) + { + while (*src && *src != c) + ++src; return *src ? src : 0; } - template - const char* find_first(const char* src) { - while (*src && !mx(src)) ++src; + template const char* find_first(const char* src) + { + while (*src && !mx(src)) + ++src; return *src ? src : 0; } - template - const char* find_first_in_interval(const char* beg, const char* end) { + template const char* find_first_in_interval(const char* beg, const char* end) + { bool esc = false; - while ((beg < end) && *beg) { - if (esc) esc = false; - else if (*beg == '\\') esc = true; - else if (mx(beg)) return beg; + while ((beg < end) && *beg) + { + if (esc) + esc = false; + else if (*beg == '\\') + esc = true; + else if (mx(beg)) + return beg; ++beg; } return 0; } - template - const char* find_first_in_interval(const char* beg, const char* end) { + template + const char* find_first_in_interval(const char* beg, const char* end) + { bool esc = false; - while ((beg < end) && *beg) { - if (esc) esc = false; - else if (*beg == '\\') esc = true; - else if (const char* pos = skip(beg)) beg = pos; - else if (mx(beg)) return beg; + while ((beg < end) && *beg) + { + if (esc) + esc = false; + else if (*beg == '\\') + esc = true; + else if (const char* pos = skip(beg)) + beg = pos; + else if (mx(beg)) + return beg; ++beg; } return 0; } - template - unsigned int count_interval(const char* beg, const char* end) { + template unsigned int count_interval(const char* beg, const char* end) + { unsigned int counter = 0; bool esc = false; - while (beg < end && *beg) { + while (beg < end && *beg) + { const char* p; - if (esc) { + if (esc) + { esc = false; ++beg; - } else if (*beg == '\\') { + } + else if (*beg == '\\') + { esc = true; ++beg; - } else if ((p = mx(beg))) { + } + else if ((p = mx(beg))) + { ++counter; beg = p; } - else { + else + { ++beg; } } return counter; } - template - const char* padded_token(const char* src) + template const char* padded_token(const char* src) { size_t got = 0; const char* pos = src; - while (got < size) { + while (got < size) + { if (!mx(pos)) break; - ++ pos; ++ got; + ++pos; + ++got; } - while (got < size) { + while (got < size) + { if (!pad(pos)) break; - ++ pos; ++ got; + ++pos; + ++got; } return got ? pos : 0; } - template - const char* minmax_range(const char* src) + template const char* minmax_range(const char* src) { size_t got = 0; const char* pos = src; - while (got < max) { + while (got < max) + { if (!mx(pos)) break; - ++ pos; ++ got; + ++pos; + ++got; } if (got < min) return 0; if (got > max) return 0; return pos; } - template - const char* char_range(const char* src) + template const char* char_range(const char* src) { if (*src < min) return 0; if (*src > max) return 0; return src + 1; } - } } diff --git a/src/remove_placeholders.cpp b/src/remove_placeholders.cpp index 15cddace2e..510a5870f0 100644 --- a/src/remove_placeholders.cpp +++ b/src/remove_placeholders.cpp @@ -4,81 +4,98 @@ #include "inspect.hpp" #include -namespace Sass { +namespace Sass +{ - Remove_Placeholders::Remove_Placeholders() - { } + Remove_Placeholders::Remove_Placeholders() + { + } - void Remove_Placeholders::operator()(Block_Ptr b) { - for (size_t i = 0, L = b->length(); i < L; ++i) { - Statement_Ptr st = b->at(i); - st->perform(this); - } + void Remove_Placeholders::operator()(Block_Ptr b) + { + for (size_t i = 0, L = b->length(); i < L; ++i) + { + Statement_Ptr st = b->at(i); + st->perform(this); } + } - Selector_List_Ptr Remove_Placeholders::remove_placeholders(Selector_List_Ptr sl) - { - Selector_List_Ptr new_sl = SASS_MEMORY_NEW(Selector_List, sl->pstate()); + Selector_List_Ptr Remove_Placeholders::remove_placeholders(Selector_List_Ptr sl) + { + Selector_List_Ptr new_sl = SASS_MEMORY_NEW(Selector_List, sl->pstate()); - for (size_t i = 0, L = sl->length(); i < L; ++i) { - if (!sl->at(i)->contains_placeholder()) { - new_sl->append(sl->at(i)); - } + for (size_t i = 0, L = sl->length(); i < L; ++i) + { + if (!sl->at(i)->contains_placeholder()) + { + new_sl->append(sl->at(i)); } - - return new_sl; - } + return new_sl; + } + - void Remove_Placeholders::operator()(Ruleset_Ptr r) { - // Create a new selector group without placeholders - Selector_List_Obj sl = Cast(r->selector()); + void Remove_Placeholders::operator()(Ruleset_Ptr r) + { + // Create a new selector group without placeholders + Selector_List_Obj sl = Cast(r->selector()); - if (sl) { - // Set the new placeholder selector list - r->selector(remove_placeholders(sl)); - // Remove placeholders in wrapped selectors - for (Complex_Selector_Obj cs : sl->elements()) { - while (cs) { - if (cs->head()) { - for (Simple_Selector_Obj& ss : cs->head()->elements()) { - if (Wrapped_Selector_Ptr ws = Cast(ss)) { - if (Selector_List_Ptr wsl = Cast(ws->selector())) { - Selector_List_Ptr clean = remove_placeholders(wsl); - // also clean superflous parent selectors - // probably not really the correct place - clean->remove_parent_selectors(); - ws->selector(clean); - } - } + if (sl) + { + // Set the new placeholder selector list + r->selector(remove_placeholders(sl)); + // Remove placeholders in wrapped selectors + for (Complex_Selector_Obj cs : sl->elements()) + { + while (cs) + { + if (cs->head()) + { + for (Simple_Selector_Obj& ss : cs->head()->elements()) + { + if (Wrapped_Selector_Ptr ws = Cast(ss)) + { + if (Selector_List_Ptr wsl = Cast(ws->selector())) + { + Selector_List_Ptr clean = remove_placeholders(wsl); + // also clean superflous parent selectors + // probably not really the correct place + clean->remove_parent_selectors(); + ws->selector(clean); } } - cs = cs->tail(); } } + cs = cs->tail(); } - - // Iterate into child blocks - Block_Obj b = r->block(); - - for (size_t i = 0, L = b->length(); i < L; ++i) { - if (b->at(i)) { - Statement_Obj st = b->at(i); - st->perform(this); - } - } + } } - void Remove_Placeholders::operator()(Media_Block_Ptr m) { - operator()(m->block()); - } - void Remove_Placeholders::operator()(Supports_Block_Ptr m) { - operator()(m->block()); - } + // Iterate into child blocks + Block_Obj b = r->block(); - void Remove_Placeholders::operator()(Directive_Ptr a) { - if (a->block()) a->block()->perform(this); + for (size_t i = 0, L = b->length(); i < L; ++i) + { + if (b->at(i)) + { + Statement_Obj st = b->at(i); + st->perform(this); + } } + } + + void Remove_Placeholders::operator()(Media_Block_Ptr m) + { + operator()(m->block()); + } + void Remove_Placeholders::operator()(Supports_Block_Ptr m) + { + operator()(m->block()); + } + void Remove_Placeholders::operator()(Directive_Ptr a) + { + if (a->block()) a->block()->perform(this); + } } diff --git a/src/remove_placeholders.hpp b/src/remove_placeholders.hpp index c13b631349..5fb7370147 100644 --- a/src/remove_placeholders.hpp +++ b/src/remove_placeholders.hpp @@ -6,30 +6,37 @@ #include "ast.hpp" #include "operation.hpp" -namespace Sass { +namespace Sass +{ - class Remove_Placeholders : public Operation_CRTP { + class Remove_Placeholders : public Operation_CRTP + { - void fallback_impl(AST_Node_Ptr n) {} + void fallback_impl(AST_Node_Ptr n) + { + } public: - Selector_List_Ptr remove_placeholders(Selector_List_Ptr); + Selector_List_Ptr remove_placeholders(Selector_List_Ptr); public: - Remove_Placeholders(); - ~Remove_Placeholders() { } - - void operator()(Block_Ptr); - void operator()(Ruleset_Ptr); - void operator()(Media_Block_Ptr); - void operator()(Supports_Block_Ptr); - void operator()(Directive_Ptr); - - template - void fallback(U x) { return fallback_impl(x); } - }; - + Remove_Placeholders(); + ~Remove_Placeholders() + { + } + + void operator()(Block_Ptr); + void operator()(Ruleset_Ptr); + void operator()(Media_Block_Ptr); + void operator()(Supports_Block_Ptr); + void operator()(Directive_Ptr); + + template void fallback(U x) + { + return fallback_impl(x); + } + }; } #endif diff --git a/src/sass.cpp b/src/sass.cpp index 98e349f487..ceecd70e51 100644 --- a/src/sass.cpp +++ b/src/sass.cpp @@ -10,124 +10,124 @@ #include "sass_context.hpp" #include "sass_functions.hpp" -namespace Sass { +namespace Sass +{ // helper to convert string list to vector std::vector list2vec(struct string_list* cur) { std::vector list; - while (cur) { + while (cur) + { list.push_back(cur->string); cur = cur->next; } return list; } - } extern "C" { - using namespace Sass; - - // Allocate libsass heap memory - // Don't forget string termination! - void* ADDCALL sass_alloc_memory(size_t size) - { - void* ptr = malloc(size); - if (ptr == NULL) - out_of_memory(); - return ptr; - } - - char* ADDCALL sass_copy_c_string(const char* str) - { - size_t len = strlen(str) + 1; - char* cpy = (char*) sass_alloc_memory(len); - std::memcpy(cpy, str, len); - return cpy; - } +using namespace Sass; + +// Allocate libsass heap memory +// Don't forget string termination! +void* ADDCALL sass_alloc_memory(size_t size) +{ + void* ptr = malloc(size); + if (ptr == NULL) out_of_memory(); + return ptr; +} - // Deallocate libsass heap memory - void ADDCALL sass_free_memory(void* ptr) - { - if (ptr) free (ptr); - } +char* ADDCALL sass_copy_c_string(const char* str) +{ + size_t len = strlen(str) + 1; + char* cpy = (char*)sass_alloc_memory(len); + std::memcpy(cpy, str, len); + return cpy; +} - // caller must free the returned memory - char* ADDCALL sass_string_quote (const char *str, const char quote_mark) - { - std::string quoted = quote(str, quote_mark); - return sass_copy_c_string(quoted.c_str()); - } +// Deallocate libsass heap memory +void ADDCALL sass_free_memory(void* ptr) +{ + if (ptr) free(ptr); +} - // caller must free the returned memory - char* ADDCALL sass_string_unquote (const char *str) - { - std::string unquoted = unquote(str); - return sass_copy_c_string(unquoted.c_str()); - } +// caller must free the returned memory +char* ADDCALL sass_string_quote(const char* str, const char quote_mark) +{ + std::string quoted = quote(str, quote_mark); + return sass_copy_c_string(quoted.c_str()); +} - char* ADDCALL sass_compiler_find_include (const char* file, struct Sass_Compiler* compiler) - { - // get the last import entry to get current base directory - Sass_Import_Entry import = sass_compiler_get_last_import(compiler); - const std::vector& incs = compiler->cpp_ctx->include_paths; - // create the vector with paths to lookup - std::vector paths(1 + incs.size()); - paths.push_back(File::dir_name(import->abs_path)); - paths.insert( paths.end(), incs.begin(), incs.end() ); - // now resolve the file path relative to lookup paths - std::string resolved(File::find_include(file, paths)); - return sass_copy_c_string(resolved.c_str()); - } +// caller must free the returned memory +char* ADDCALL sass_string_unquote(const char* str) +{ + std::string unquoted = unquote(str); + return sass_copy_c_string(unquoted.c_str()); +} - char* ADDCALL sass_compiler_find_file (const char* file, struct Sass_Compiler* compiler) - { - // get the last import entry to get current base directory - Sass_Import_Entry import = sass_compiler_get_last_import(compiler); - const std::vector& incs = compiler->cpp_ctx->include_paths; - // create the vector with paths to lookup - std::vector paths(1 + incs.size()); - paths.push_back(File::dir_name(import->abs_path)); - paths.insert( paths.end(), incs.begin(), incs.end() ); - // now resolve the file path relative to lookup paths - std::string resolved(File::find_file(file, paths)); - return sass_copy_c_string(resolved.c_str()); - } +char* ADDCALL sass_compiler_find_include(const char* file, struct Sass_Compiler* compiler) +{ + // get the last import entry to get current base directory + Sass_Import_Entry import = sass_compiler_get_last_import(compiler); + const std::vector& incs = compiler->cpp_ctx->include_paths; + // create the vector with paths to lookup + std::vector paths(1 + incs.size()); + paths.push_back(File::dir_name(import->abs_path)); + paths.insert(paths.end(), incs.begin(), incs.end()); + // now resolve the file path relative to lookup paths + std::string resolved(File::find_include(file, paths)); + return sass_copy_c_string(resolved.c_str()); +} - // Make sure to free the returned value! - // Incs array has to be null terminated! - // this has the original resolve logic for sass include - char* ADDCALL sass_find_include (const char* file, struct Sass_Options* opt) - { - std::vector vec(list2vec(opt->include_paths)); - std::string resolved(File::find_include(file, vec)); - return sass_copy_c_string(resolved.c_str()); - } +char* ADDCALL sass_compiler_find_file(const char* file, struct Sass_Compiler* compiler) +{ + // get the last import entry to get current base directory + Sass_Import_Entry import = sass_compiler_get_last_import(compiler); + const std::vector& incs = compiler->cpp_ctx->include_paths; + // create the vector with paths to lookup + std::vector paths(1 + incs.size()); + paths.push_back(File::dir_name(import->abs_path)); + paths.insert(paths.end(), incs.begin(), incs.end()); + // now resolve the file path relative to lookup paths + std::string resolved(File::find_file(file, paths)); + return sass_copy_c_string(resolved.c_str()); +} - // Make sure to free the returned value! - // Incs array has to be null terminated! - char* ADDCALL sass_find_file (const char* file, struct Sass_Options* opt) - { - std::vector vec(list2vec(opt->include_paths)); - std::string resolved(File::find_file(file, vec)); - return sass_copy_c_string(resolved.c_str()); - } +// Make sure to free the returned value! +// Incs array has to be null terminated! +// this has the original resolve logic for sass include +char* ADDCALL sass_find_include(const char* file, struct Sass_Options* opt) +{ + std::vector vec(list2vec(opt->include_paths)); + std::string resolved(File::find_include(file, vec)); + return sass_copy_c_string(resolved.c_str()); +} - // Get compiled libsass version - const char* ADDCALL libsass_version(void) - { - return LIBSASS_VERSION; - } +// Make sure to free the returned value! +// Incs array has to be null terminated! +char* ADDCALL sass_find_file(const char* file, struct Sass_Options* opt) +{ + std::vector vec(list2vec(opt->include_paths)); + std::string resolved(File::find_file(file, vec)); + return sass_copy_c_string(resolved.c_str()); +} - // Get compiled libsass version - const char* ADDCALL libsass_language_version(void) - { - return LIBSASS_LANGUAGE_VERSION; - } +// Get compiled libsass version +const char* ADDCALL libsass_version(void) +{ + return LIBSASS_VERSION; +} +// Get compiled libsass version +const char* ADDCALL libsass_language_version(void) +{ + return LIBSASS_LANGUAGE_VERSION; +} } -namespace Sass { +namespace Sass +{ // helper to aid dreaded MSVC debug mode char* sass_copy_string(std::string str) @@ -145,5 +145,4 @@ namespace Sass { // function must hold on to the stack variable until it's done. return sass_copy_c_string(str.c_str()); } - } \ No newline at end of file diff --git a/src/sass.hpp b/src/sass.hpp index 1f4c88b6e2..ddccce9054 100644 --- a/src/sass.hpp +++ b/src/sass.hpp @@ -14,31 +14,31 @@ // aplies to MSVC and MinGW #ifdef _WIN32 // we do not want the ERROR macro -# define NOGDI +#define NOGDI // we do not want the min/max macro -# define NOMINMAX +#define NOMINMAX // we do not want the IN/OUT macro -# define _NO_W32_PSEUDO_MODIFIERS +#define _NO_W32_PSEUDO_MODIFIERS #endif // should we be case insensitive // when dealing with files or paths #ifndef FS_CASE_SENSITIVE -# ifdef _WIN32 -# define FS_CASE_SENSITIVE 0 -# else -# define FS_CASE_SENSITIVE 1 -# endif +#ifdef _WIN32 +#define FS_CASE_SENSITIVE 0 +#else +#define FS_CASE_SENSITIVE 1 +#endif #endif // path separation char #ifndef PATH_SEP -# ifdef _WIN32 -# define PATH_SEP ';' -# else -# define PATH_SEP ':' -# endif +#ifdef _WIN32 +#define PATH_SEP ';' +#else +#define PATH_SEP ':' +#endif #endif @@ -49,7 +49,8 @@ #include // output behaviours -namespace Sass { +namespace Sass +{ // create some C++ aliases for the most used options const static Sass_Output_Style NESTED = SASS_STYLE_NESTED; @@ -63,11 +64,11 @@ namespace Sass { // helper to aid dreaded MSVC debug mode // see implementation for more details char* sass_copy_string(std::string str); - } // input behaviours -enum Sass_Input_Style { +enum Sass_Input_Style +{ SASS_CONTEXT_NULL, SASS_CONTEXT_FILE, SASS_CONTEXT_DATA, @@ -75,13 +76,15 @@ enum Sass_Input_Style { }; // simple linked list -struct string_list { +struct string_list +{ string_list* next; char* string; }; // sass config options structure -struct Sass_Inspect_Options { +struct Sass_Inspect_Options +{ // Output style for the generated css code // A value from above SASS_STYLE_* constants @@ -91,15 +94,15 @@ struct Sass_Inspect_Options { int precision; // initialization list (constructor with defaults) - Sass_Inspect_Options(Sass_Output_Style style = Sass::NESTED, - int precision = 5) + Sass_Inspect_Options(Sass_Output_Style style = Sass::NESTED, int precision = 5) : output_style(style), precision(precision) - { } - + { + } }; // sass config options structure -struct Sass_Output_Options : Sass_Inspect_Options { +struct Sass_Output_Options : Sass_Inspect_Options +{ // String to be used for indentation const char* indent; @@ -115,10 +118,9 @@ struct Sass_Output_Options : Sass_Inspect_Options { const char* indent = " ", const char* linefeed = "\n", bool source_comments = false) - : Sass_Inspect_Options(opt), - indent(indent), linefeed(linefeed), - source_comments(source_comments) - { } + : Sass_Inspect_Options(opt), indent(indent), linefeed(linefeed), source_comments(source_comments) + { + } // initialization list (constructor with defaults) Sass_Output_Options(Sass_Output_Style style = Sass::NESTED, @@ -126,11 +128,10 @@ struct Sass_Output_Options : Sass_Inspect_Options { const char* indent = " ", const char* linefeed = "\n", bool source_comments = false) - : Sass_Inspect_Options(style, precision), - indent(indent), linefeed(linefeed), + : Sass_Inspect_Options(style, precision), indent(indent), linefeed(linefeed), source_comments(source_comments) - { } - + { + } }; #endif diff --git a/src/sass2scss.cpp b/src/sass2scss.cpp index 56333b38ea..85decee1a5 100644 --- a/src/sass2scss.cpp +++ b/src/sass2scss.cpp @@ -36,829 +36,829 @@ namespace Sass { - // return the actual prettify value from options - #define PRETTIFY(converter) (converter.options - (converter.options & 248)) - // query the options integer to check if the option is enables - #define KEEP_COMMENT(converter) ((converter.options & SASS2SCSS_KEEP_COMMENT) == SASS2SCSS_KEEP_COMMENT) - #define STRIP_COMMENT(converter) ((converter.options & SASS2SCSS_STRIP_COMMENT) == SASS2SCSS_STRIP_COMMENT) - #define CONVERT_COMMENT(converter) ((converter.options & SASS2SCSS_CONVERT_COMMENT) == SASS2SCSS_CONVERT_COMMENT) - - // some makros to access the indentation stack - #define INDENT(converter) (converter.indents.top()) - - // some makros to query comment parser status - #define IS_PARSING(converter) (converter.comment == "") - #define IS_COMMENT(converter) (converter.comment != "") - #define IS_SRC_COMMENT(converter) (converter.comment == "//" && ! CONVERT_COMMENT(converter)) - #define IS_CSS_COMMENT(converter) (converter.comment == "/*" || (converter.comment == "//" && CONVERT_COMMENT(converter))) - - // pretty printer helper function - static std::string closer (const converter& converter) - { - return PRETTIFY(converter) == 0 ? " }" : - PRETTIFY(converter) <= 1 ? " }" : - "\n" + INDENT(converter) + "}"; - } - - // pretty printer helper function - static std::string opener (const converter& converter) - { - return PRETTIFY(converter) == 0 ? " { " : - PRETTIFY(converter) <= 2 ? " {" : - "\n" + INDENT(converter) + "{"; - } - - // check if the given string is a pseudo selector - // needed to differentiate from sass property syntax - static bool isPseudoSelector (std::string& sel) - { - - size_t len = sel.length(); - if (len < 1) return false; - size_t pos = sel.find_first_not_of("abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ", 1); - if (pos != std::string::npos) sel.erase(pos, std::string::npos); - size_t i = sel.length(); - while (i -- > 0) { sel.at(i) = tolower(sel.at(i)); } - - // CSS Level 1 - Recommendation - if (sel == ":link") return true; - if (sel == ":visited") return true; - if (sel == ":active") return true; - - // CSS Level 2 (Revision 1) - Recommendation - if (sel == ":lang") return true; - if (sel == ":first-child") return true; - if (sel == ":hover") return true; - if (sel == ":focus") return true; - // disabled - also valid properties - // if (sel == ":left") return true; - // if (sel == ":right") return true; - if (sel == ":first") return true; - - // Selectors Level 3 - Recommendation - if (sel == ":target") return true; - if (sel == ":root") return true; - if (sel == ":nth-child") return true; - if (sel == ":nth-last-of-child") return true; - if (sel == ":nth-of-type") return true; - if (sel == ":nth-last-of-type") return true; - if (sel == ":last-child") return true; - if (sel == ":first-of-type") return true; - if (sel == ":last-of-type") return true; - if (sel == ":only-child") return true; - if (sel == ":only-of-type") return true; - if (sel == ":empty") return true; - if (sel == ":not") return true; - - // CSS Basic User Interface Module Level 3 - Working Draft - if (sel == ":default") return true; - if (sel == ":valid") return true; - if (sel == ":invalid") return true; - if (sel == ":in-range") return true; - if (sel == ":out-of-range") return true; - if (sel == ":required") return true; - if (sel == ":optional") return true; - if (sel == ":read-only") return true; - if (sel == ":read-write") return true; - if (sel == ":dir") return true; - if (sel == ":enabled") return true; - if (sel == ":disabled") return true; - if (sel == ":checked") return true; - if (sel == ":indeterminate") return true; - if (sel == ":nth-last-child") return true; - - // Selectors Level 4 - Working Draft - if (sel == ":any-link") return true; - if (sel == ":local-link") return true; - if (sel == ":scope") return true; - if (sel == ":active-drop-target") return true; - if (sel == ":valid-drop-target") return true; - if (sel == ":invalid-drop-target") return true; - if (sel == ":current") return true; - if (sel == ":past") return true; - if (sel == ":future") return true; - if (sel == ":placeholder-shown") return true; - if (sel == ":user-error") return true; - if (sel == ":blank") return true; - if (sel == ":nth-match") return true; - if (sel == ":nth-last-match") return true; - if (sel == ":nth-column") return true; - if (sel == ":nth-last-column") return true; - if (sel == ":matches") return true; - - // Fullscreen API - Living Standard - if (sel == ":fullscreen") return true; - - // not a pseudo selector - return false; - - } - - // check if there is some char data - // will ignore everything in comments - static bool hasCharData (std::string& sass) - { - - size_t col_pos = 0; - - while (true) - { - - // try to find some meaningfull char - col_pos = sass.find_first_not_of(" \t\n\v\f\r", col_pos); - - // there was no meaningfull char found - if (col_pos == std::string::npos) return false; - - // found a multiline comment opener - if (sass.substr(col_pos, 2) == "/*") - { - // find the multiline comment closer - col_pos = sass.find("*/", col_pos); - // maybe we did not find the closer here - if (col_pos == std::string::npos) return false; - // skip closer - col_pos += 2; - } - else - { - return true; - } - - } - - } - // EO hasCharData - - // find src comment opener - // correctly skips quoted strings - static size_t findCommentOpener (std::string& sass) - { - - size_t col_pos = 0; - bool apoed = false; - bool quoted = false; - bool comment = false; - size_t brackets = 0; - - while (col_pos != std::string::npos) - { - - // process all interesting chars - col_pos = sass.find_first_of("\"\'/\\*()", col_pos); - - // assertion for valid result - if (col_pos != std::string::npos) - { - char character = sass.at(col_pos); - - if (character == '(') - { - if (!quoted && !apoed) brackets ++; - } - else if (character == ')') - { - if (!quoted && !apoed) brackets --; - } - else if (character == '\"') - { - // invert quote bool - if (!apoed && !comment) quoted = !quoted; - } - else if (character == '\'') - { - // invert quote bool - if (!quoted && !comment) apoed = !apoed; - } - else if (col_pos > 0 && character == '/') - { - if (sass.at(col_pos - 1) == '*') - { - comment = false; - } - // next needs to be a slash too - else if (sass.at(col_pos - 1) == '/') - { - // only found if not in single or double quote, bracket or comment - if (!quoted && !apoed && !comment && brackets == 0) return col_pos - 1; - } - } - else if (character == '\\') - { - // skip next char if in quote - if (quoted || apoed) col_pos ++; - } - // this might be a comment opener - else if (col_pos > 0 && character == '*') - { - // opening a multiline comment - if (sass.at(col_pos - 1) == '/') - { - // we are now in a comment - if (!quoted && !apoed) comment = true; - } - } - - // skip char - col_pos ++; - - } - - } - // EO while - - return col_pos; - - } - // EO findCommentOpener - - // remove multiline comments from sass string - // correctly skips quoted strings - static std::string removeMultilineComment (std::string &sass) - { - - std::string clean = ""; - size_t col_pos = 0; - size_t open_pos = 0; - size_t close_pos = 0; - bool apoed = false; - bool quoted = false; - bool comment = false; - - // process sass til string end - while (col_pos != std::string::npos) - { - - // process all interesting chars - col_pos = sass.find_first_of("\"\'/\\*", col_pos); - - // assertion for valid result - if (col_pos != std::string::npos) - { - char character = sass.at(col_pos); - - // found quoted string delimiter - if (character == '\"') - { - if (!apoed && !comment) quoted = !quoted; - } - else if (character == '\'') - { - if (!quoted && !comment) apoed = !apoed; - } - // found possible comment closer - else if (character == '/') - { - // look back to see if it is actually a closer - if (comment && col_pos > 0 && sass.at(col_pos - 1) == '*') - { - close_pos = col_pos + 1; comment = false; - } - } - else if (character == '\\') - { - // skip escaped char - if (quoted || apoed) col_pos ++; - } - // this might be a comment opener - else if (character == '*') - { - // look back to see if it is actually an opener - if (!quoted && !apoed && col_pos > 0 && sass.at(col_pos - 1) == '/') - { - comment = true; open_pos = col_pos - 1; - clean += sass.substr(close_pos, open_pos - close_pos); - } - } - - // skip char - col_pos ++; - - } - - } - // EO while - - // add final parts (add half open comment text) - if (comment) clean += sass.substr(open_pos); - else clean += sass.substr(close_pos); - - // return string - return clean; - - } - // EO removeMultilineComment - - // right trim a given string - std::string rtrim(const std::string &sass) - { - std::string trimmed = sass; - size_t pos_ws = trimmed.find_last_not_of(" \t\n\v\f\r"); - if (pos_ws != std::string::npos) - { trimmed.erase(pos_ws + 1); } - else { trimmed.clear(); } - return trimmed; - } - // EO rtrim - - // flush whitespace and print additional text, but - // only print additional chars and buffer whitespace - std::string flush (std::string& sass, converter& converter) - { - - // return flushed - std::string scss = ""; - - // print whitespace buffer - scss += PRETTIFY(converter) > 0 ? - converter.whitespace : ""; - // reset whitespace buffer - converter.whitespace = ""; - - // remove possible newlines from string - size_t pos_right = sass.find_last_not_of("\n\r"); - if (pos_right == std::string::npos) return scss; - - // get the linefeeds from the string - std::string lfs = sass.substr(pos_right + 1); - sass = sass.substr(0, pos_right + 1); - - // find some source comment opener - size_t comment_pos = findCommentOpener(sass); - // check if there was a source comment - if (comment_pos != std::string::npos) - { - // convert comment (but only outside other coments) - if (CONVERT_COMMENT(converter) && !IS_COMMENT(converter)) - { - // convert to multiline comment - sass.at(comment_pos + 1) = '*'; - // add comment node to the whitespace - sass += " */"; - } - // not at line start - if (comment_pos > 0) - { - // also include whitespace before the actual comment opener - size_t ws_pos = sass.find_last_not_of(SASS2SCSS_FIND_WHITESPACE, comment_pos - 1); - comment_pos = ws_pos == std::string::npos ? 0 : ws_pos + 1; - } - if (!STRIP_COMMENT(converter)) - { - // add comment node to the whitespace - converter.whitespace += sass.substr(comment_pos); - } - else - { - // sass = removeMultilineComments(sass); - } - // update the actual sass code - sass = sass.substr(0, comment_pos); - } - - // add newline as getline discharged it - converter.whitespace += lfs + "\n"; - - // maybe remove any leading whitespace - if (PRETTIFY(converter) == 0) - { - // remove leading whitespace and update string - size_t pos_left = sass.find_first_not_of(SASS2SCSS_FIND_WHITESPACE); - if (pos_left != std::string::npos) sass = sass.substr(pos_left); - } - - // add flushed data - scss += sass; - - // return string - return scss; - - } - // EO flush - - // process a line of the sass text - std::string process (std::string& sass, converter& converter) - { - - // resulting string - std::string scss = ""; - - // strip multi line comments - if (STRIP_COMMENT(converter)) - { - sass = removeMultilineComment(sass); - } - - // right trim input - sass = rtrim(sass); - - // get postion of first meaningfull character in string - size_t pos_left = sass.find_first_not_of(SASS2SCSS_FIND_WHITESPACE); - - // special case for final run - if (converter.end_of_file) pos_left = 0; - - // maybe has only whitespace - if (pos_left == std::string::npos) - { - // just add complete whitespace - converter.whitespace += sass + "\n"; - } - // have meaningfull first char - else - { - - // extract and store indentation string - std::string indent = sass.substr(0, pos_left); - - // check if current line starts a comment - std::string open = sass.substr(pos_left, 2); - - // line has less or same indentation - // finalize previous open parser context - if (indent.length() <= INDENT(converter).length()) - { - - // close multilinie comment - if (IS_CSS_COMMENT(converter)) - { - // check if comments will be stripped anyway - if (!STRIP_COMMENT(converter)) scss += " */"; - } - // close src comment comment - else if (IS_SRC_COMMENT(converter)) - { - // add a newline to avoid closer on same line - // this would put the bracket in the comment node - // no longer needed since we parse them correctly - // if (KEEP_COMMENT(converter)) scss += "\n"; - } - // close css properties - else if (converter.property) - { - // add closer unless in concat mode - if (!converter.comma) - { - // if there was no colon we have a selector - // looks like there were no inner properties - if (converter.selector) scss += " {}"; - // add final semicolon - else if (!converter.semicolon) scss += ";"; - } - } - - // reset comment state - converter.comment = ""; - - } - - // make sure we close every "higher" block - while (indent.length() < INDENT(converter).length()) - { - // pop stacked context - converter.indents.pop(); - // print close bracket - if (IS_PARSING(converter)) - { scss += closer(converter); } - else { scss += " */"; } - // reset comment state - converter.comment = ""; - } - - // reset converter state - converter.selector = false; - - // looks like some undocumented behavior ... - // https://github.com/mgreter/sass2scss/issues/29 - if (sass.substr(pos_left, 1) == "\\") { - converter.selector = true; - sass[pos_left] = ' '; - } - - // check if we have sass property syntax - if (sass.substr(pos_left, 1) == ":" && sass.substr(pos_left, 2) != "::") - { - - // default to a selector - // change back if property found - converter.selector = true; - // get postion of first whitespace char - size_t pos_wspace = sass.find_first_of(SASS2SCSS_FIND_WHITESPACE, pos_left); - // assertion check for valid result - if (pos_wspace != std::string::npos) - { - // get the possible pseudo selector - std::string pseudo = sass.substr(pos_left, pos_wspace - pos_left); - // get position of the first real property value char - // pseudo selectors get this far, but have no actual value - size_t pos_value = sass.find_first_not_of(SASS2SCSS_FIND_WHITESPACE, pos_wspace); - // assertion check for valid result - if (pos_value != std::string::npos) - { - // only process if not (fallowed by a semicolon or is a pseudo selector) - if (!(sass.at(pos_value) == ':' || isPseudoSelector(pseudo))) - { - // create new string by interchanging the colon sign for property and value - sass = indent + sass.substr(pos_left + 1, pos_wspace - pos_left - 1) + ":" + sass.substr(pos_wspace); - // try to find a colon in the current line, but only ... - size_t pos_colon = sass.find_first_not_of(":", pos_left); - // assertion for valid result - if (pos_colon != std::string::npos) - { - // ... after the first word (skip begining colons) - pos_colon = sass.find_first_of(":", pos_colon); - // it is a selector if there was no colon found - converter.selector = pos_colon == std::string::npos; - } - } - } - } - - // check if we have a BEM property (one colon and no selector) - if (sass.substr(pos_left, 1) == ":" && converter.selector == true) { - size_t pos_wspace = sass.find_first_of(SASS2SCSS_FIND_WHITESPACE, pos_left); - sass = indent + sass.substr(pos_left + 1, pos_wspace) + ":"; - } - - } - - // terminate some statements immediately - else if ( - sass.substr(pos_left, 5) == "@warn" || - sass.substr(pos_left, 6) == "@debug" || - sass.substr(pos_left, 6) == "@error" || - sass.substr(pos_left, 8) == "@charset" || - sass.substr(pos_left, 10) == "@namespace" - ) { sass = indent + sass.substr(pos_left); } - // replace some specific sass shorthand directives (if not fallowed by a white space character) - else if (sass.substr(pos_left, 1) == "=") - { sass = indent + "@mixin " + sass.substr(pos_left + 1); } - else if (sass.substr(pos_left, 1) == "+") - { - // must be followed by a mixin call (no whitespace afterwards or at ending directly) - if (sass[pos_left+1] != 0 && sass[pos_left+1] != ' ' && sass[pos_left+1] != '\t') { - sass = indent + "@include " + sass.substr(pos_left + 1); - } - } - - // add quotes for import if needed - else if (sass.substr(pos_left, 7) == "@import") - { - // get positions for the actual import url - size_t pos_import = sass.find_first_of(SASS2SCSS_FIND_WHITESPACE, pos_left + 7); - size_t pos_quote = sass.find_first_not_of(SASS2SCSS_FIND_WHITESPACE, pos_import); - // leave proper urls untouched - if (sass.substr(pos_quote, 4) != "url(") - { - // check if the url appears to be already quoted - if (sass.substr(pos_quote, 1) != "\"" && sass.substr(pos_quote, 1) != "\'") - { - // get position of the last char on the line - size_t pos_end = sass.find_last_not_of(SASS2SCSS_FIND_WHITESPACE); - // assertion check for valid result - if (pos_end != std::string::npos) - { - // add quotes around the full line after the import statement - sass = sass.substr(0, pos_quote) + "\"" + sass.substr(pos_quote, pos_end - pos_quote + 1) + "\""; - } - } - } - - } - else if ( - sass.substr(pos_left, 7) != "@return" && - sass.substr(pos_left, 7) != "@extend" && - sass.substr(pos_left, 8) != "@include" && - sass.substr(pos_left, 8) != "@content" - ) { - - // probably a selector anyway - converter.selector = true; - // try to find first colon in the current line - size_t pos_colon = sass.find_first_of(":", pos_left); - // assertion that we have a colon - if (pos_colon != std::string::npos) - { - // it is not a selector if we have a space after a colon - if (sass[pos_colon+1] == ' ') converter.selector = false; - if (sass[pos_colon+1] == ' ') converter.selector = false; - } - - } - - // current line has more indentation - if (indent.length() >= INDENT(converter).length()) - { - // not in comment mode - if (IS_PARSING(converter)) - { - // has meaningfull chars - if (hasCharData(sass)) - { - // is probably a property - // also true for selectors - converter.property = true; - } - } - } - // current line has more indentation - if (indent.length() > INDENT(converter).length()) - { - // not in comment mode - if (IS_PARSING(converter)) - { - // had meaningfull chars - if (converter.property) - { - // print block opener - scss += opener(converter); - // push new stack context - converter.indents.push(""); - // store block indentation - INDENT(converter) = indent; - } - } - // is and will be a src comment - else if (!IS_CSS_COMMENT(converter)) - { - // scss does not allow multiline src comments - // therefore add forward slashes to all lines - sass.at(INDENT(converter).length()+0) = '/'; - // there is an edge case here if indentation - // is minimal (will overwrite the fist char) - sass.at(INDENT(converter).length()+1) = '/'; - // could code around that, but I dont' think - // this will ever be the cause for any trouble - } - } - - // line is opening a new comment - if (open == "/*" || open == "//") - { - // reset the property state - converter.property = false; - // close previous comment - if (IS_CSS_COMMENT(converter) && open != "") - { - if (!STRIP_COMMENT(converter) && !CONVERT_COMMENT(converter)) scss += " */"; - } - // force single line comments - // into a correct css comment - if (CONVERT_COMMENT(converter)) - { - if (IS_PARSING(converter)) - { sass.at(pos_left + 1) = '*'; } - } - // set comment flag - converter.comment = open; - - } - - // flush data only under certain conditions - if (!( - // strip css and src comments if option is set - (IS_COMMENT(converter) && STRIP_COMMENT(converter)) || - // strip src comment even if strip option is not set - // but only if the keep src comment option is not set - (IS_SRC_COMMENT(converter) && ! KEEP_COMMENT(converter)) - )) - { - // flush data and buffer whitespace - scss += flush(sass, converter); - } - - // get postion of last meaningfull char - size_t pos_right = sass.find_last_not_of(SASS2SCSS_FIND_WHITESPACE); - - // check for invalid result - if (pos_right != std::string::npos) - { - - // get the last meaningfull char - std::string close = sass.substr(pos_right, 1); - - // check if next line should be concatenated (list mode) - converter.comma = IS_PARSING(converter) && close == ","; - converter.semicolon = IS_PARSING(converter) && close == ";"; - - // check if we have more than - // one meaningfull char - if (pos_right > 0) - { - - // get the last two chars from string - std::string close = sass.substr(pos_right - 1, 2); - // update parser status for expicitly closed comment - if (close == "*/") converter.comment = ""; - - } - - } - // EO have meaningfull chars from end - - } - // EO have meaningfull chars from start - - // return scss - return scss; - - } - // EO process - - // read line with either CR, LF or CR LF format - // http://stackoverflow.com/a/6089413/1550314 - static std::istream& safeGetline(std::istream& is, std::string& t) - { - t.clear(); - - // The characters in the stream are read one-by-one using a std::streambuf. - // That is faster than reading them one-by-one using the std::istream. - // Code that uses streambuf this way must be guarded by a sentry object. - // The sentry object performs various tasks, - // such as thread synchronization and updating the stream state. - - std::istream::sentry se(is, true); - std::streambuf* sb = is.rdbuf(); - - for(;;) { - int c = sb->sbumpc(); - switch (c) { - case '\n': - return is; - case '\r': - if(sb->sgetc() == '\n') - sb->sbumpc(); - return is; - case EOF: - // Also handle the case when the last line has no line ending - if(t.empty()) - is.setstate(std::ios::eofbit); - return is; - default: - t += (char)c; - } - } - } - - // the main converter function for c++ - char* sass2scss (const std::string& sass, const int options) - { - - // local variables - std::string line; - std::string scss = ""; - std::stringstream stream(sass); - - // create converter variable - converter converter; - // initialise all options - converter.comma = false; - converter.property = false; - converter.selector = false; - converter.semicolon = false; - converter.end_of_file = false; - converter.comment = ""; - converter.whitespace = ""; - converter.indents.push(""); - converter.options = options; - - // read line by line and process them - while(safeGetline(stream, line) && !stream.eof()) - { scss += process(line, converter); } - - // create mutable string - std::string closer = ""; - // set the end of file flag - converter.end_of_file = true; - // process to close all open blocks - scss += process(closer, converter); - - // allocate new memory on the heap - // caller has to free it after use - char * cstr = (char*) malloc (scss.length() + 1); - // create a copy of the string - strcpy (cstr, scss.c_str()); - // return pointer - return &cstr[0]; - - } - // EO sass2scss - +// return the actual prettify value from options +#define PRETTIFY(converter) (converter.options - (converter.options & 248)) +// query the options integer to check if the option is enables +#define KEEP_COMMENT(converter) \ + ((converter.options & SASS2SCSS_KEEP_COMMENT) == SASS2SCSS_KEEP_COMMENT) +#define STRIP_COMMENT(converter) \ + ((converter.options & SASS2SCSS_STRIP_COMMENT) == SASS2SCSS_STRIP_COMMENT) +#define CONVERT_COMMENT(converter) \ + ((converter.options & SASS2SCSS_CONVERT_COMMENT) == SASS2SCSS_CONVERT_COMMENT) + +// some makros to access the indentation stack +#define INDENT(converter) (converter.indents.top()) + +// some makros to query comment parser status +#define IS_PARSING(converter) (converter.comment == "") +#define IS_COMMENT(converter) (converter.comment != "") +#define IS_SRC_COMMENT(converter) (converter.comment == "//" && !CONVERT_COMMENT(converter)) +#define IS_CSS_COMMENT(converter) \ + (converter.comment == "/*" || (converter.comment == "//" && CONVERT_COMMENT(converter))) + + // pretty printer helper function + static std::string closer(const converter& converter) + { + return PRETTIFY(converter) == 0 ? " }" : PRETTIFY(converter) <= 1 ? " }" : "\n" + INDENT(converter) + "}"; + } + + // pretty printer helper function + static std::string opener(const converter& converter) + { + return PRETTIFY(converter) == 0 ? " { " : PRETTIFY(converter) <= 2 ? " {" : "\n" + INDENT(converter) + "{"; + } + + // check if the given string is a pseudo selector + // needed to differentiate from sass property syntax + static bool isPseudoSelector(std::string& sel) + { + + size_t len = sel.length(); + if (len < 1) return false; + size_t pos = sel.find_first_not_of("abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ", 1); + if (pos != std::string::npos) sel.erase(pos, std::string::npos); + size_t i = sel.length(); + while (i-- > 0) + { + sel.at(i) = tolower(sel.at(i)); + } + + // CSS Level 1 - Recommendation + if (sel == ":link") return true; + if (sel == ":visited") return true; + if (sel == ":active") return true; + + // CSS Level 2 (Revision 1) - Recommendation + if (sel == ":lang") return true; + if (sel == ":first-child") return true; + if (sel == ":hover") return true; + if (sel == ":focus") return true; + // disabled - also valid properties + // if (sel == ":left") return true; + // if (sel == ":right") return true; + if (sel == ":first") return true; + + // Selectors Level 3 - Recommendation + if (sel == ":target") return true; + if (sel == ":root") return true; + if (sel == ":nth-child") return true; + if (sel == ":nth-last-of-child") return true; + if (sel == ":nth-of-type") return true; + if (sel == ":nth-last-of-type") return true; + if (sel == ":last-child") return true; + if (sel == ":first-of-type") return true; + if (sel == ":last-of-type") return true; + if (sel == ":only-child") return true; + if (sel == ":only-of-type") return true; + if (sel == ":empty") return true; + if (sel == ":not") return true; + + // CSS Basic User Interface Module Level 3 - Working Draft + if (sel == ":default") return true; + if (sel == ":valid") return true; + if (sel == ":invalid") return true; + if (sel == ":in-range") return true; + if (sel == ":out-of-range") return true; + if (sel == ":required") return true; + if (sel == ":optional") return true; + if (sel == ":read-only") return true; + if (sel == ":read-write") return true; + if (sel == ":dir") return true; + if (sel == ":enabled") return true; + if (sel == ":disabled") return true; + if (sel == ":checked") return true; + if (sel == ":indeterminate") return true; + if (sel == ":nth-last-child") return true; + + // Selectors Level 4 - Working Draft + if (sel == ":any-link") return true; + if (sel == ":local-link") return true; + if (sel == ":scope") return true; + if (sel == ":active-drop-target") return true; + if (sel == ":valid-drop-target") return true; + if (sel == ":invalid-drop-target") return true; + if (sel == ":current") return true; + if (sel == ":past") return true; + if (sel == ":future") return true; + if (sel == ":placeholder-shown") return true; + if (sel == ":user-error") return true; + if (sel == ":blank") return true; + if (sel == ":nth-match") return true; + if (sel == ":nth-last-match") return true; + if (sel == ":nth-column") return true; + if (sel == ":nth-last-column") return true; + if (sel == ":matches") return true; + + // Fullscreen API - Living Standard + if (sel == ":fullscreen") return true; + + // not a pseudo selector + return false; + } + + // check if there is some char data + // will ignore everything in comments + static bool hasCharData(std::string& sass) + { + + size_t col_pos = 0; + + while (true) + { + + // try to find some meaningfull char + col_pos = sass.find_first_not_of(" \t\n\v\f\r", col_pos); + + // there was no meaningfull char found + if (col_pos == std::string::npos) return false; + + // found a multiline comment opener + if (sass.substr(col_pos, 2) == "/*") + { + // find the multiline comment closer + col_pos = sass.find("*/", col_pos); + // maybe we did not find the closer here + if (col_pos == std::string::npos) return false; + // skip closer + col_pos += 2; + } + else + { + return true; + } + } + } + // EO hasCharData + + // find src comment opener + // correctly skips quoted strings + static size_t findCommentOpener(std::string& sass) + { + + size_t col_pos = 0; + bool apoed = false; + bool quoted = false; + bool comment = false; + size_t brackets = 0; + + while (col_pos != std::string::npos) + { + + // process all interesting chars + col_pos = sass.find_first_of("\"\'/\\*()", col_pos); + + // assertion for valid result + if (col_pos != std::string::npos) + { + char character = sass.at(col_pos); + + if (character == '(') + { + if (!quoted && !apoed) brackets++; + } + else if (character == ')') + { + if (!quoted && !apoed) brackets--; + } + else if (character == '\"') + { + // invert quote bool + if (!apoed && !comment) quoted = !quoted; + } + else if (character == '\'') + { + // invert quote bool + if (!quoted && !comment) apoed = !apoed; + } + else if (col_pos > 0 && character == '/') + { + if (sass.at(col_pos - 1) == '*') + { + comment = false; + } + // next needs to be a slash too + else if (sass.at(col_pos - 1) == '/') + { + // only found if not in single or double quote, bracket or comment + if (!quoted && !apoed && !comment && brackets == 0) return col_pos - 1; + } + } + else if (character == '\\') + { + // skip next char if in quote + if (quoted || apoed) col_pos++; + } + // this might be a comment opener + else if (col_pos > 0 && character == '*') + { + // opening a multiline comment + if (sass.at(col_pos - 1) == '/') + { + // we are now in a comment + if (!quoted && !apoed) comment = true; + } + } + + // skip char + col_pos++; + } + } + // EO while + + return col_pos; + } + // EO findCommentOpener + + // remove multiline comments from sass string + // correctly skips quoted strings + static std::string removeMultilineComment(std::string& sass) + { + + std::string clean = ""; + size_t col_pos = 0; + size_t open_pos = 0; + size_t close_pos = 0; + bool apoed = false; + bool quoted = false; + bool comment = false; + + // process sass til string end + while (col_pos != std::string::npos) + { + + // process all interesting chars + col_pos = sass.find_first_of("\"\'/\\*", col_pos); + + // assertion for valid result + if (col_pos != std::string::npos) + { + char character = sass.at(col_pos); + + // found quoted string delimiter + if (character == '\"') + { + if (!apoed && !comment) quoted = !quoted; + } + else if (character == '\'') + { + if (!quoted && !comment) apoed = !apoed; + } + // found possible comment closer + else if (character == '/') + { + // look back to see if it is actually a closer + if (comment && col_pos > 0 && sass.at(col_pos - 1) == '*') + { + close_pos = col_pos + 1; + comment = false; + } + } + else if (character == '\\') + { + // skip escaped char + if (quoted || apoed) col_pos++; + } + // this might be a comment opener + else if (character == '*') + { + // look back to see if it is actually an opener + if (!quoted && !apoed && col_pos > 0 && sass.at(col_pos - 1) == '/') + { + comment = true; + open_pos = col_pos - 1; + clean += sass.substr(close_pos, open_pos - close_pos); + } + } + + // skip char + col_pos++; + } + } + // EO while + + // add final parts (add half open comment text) + if (comment) + clean += sass.substr(open_pos); + else + clean += sass.substr(close_pos); + + // return string + return clean; + } + // EO removeMultilineComment + + // right trim a given string + std::string rtrim(const std::string& sass) + { + std::string trimmed = sass; + size_t pos_ws = trimmed.find_last_not_of(" \t\n\v\f\r"); + if (pos_ws != std::string::npos) + { + trimmed.erase(pos_ws + 1); + } + else + { + trimmed.clear(); + } + return trimmed; + } + // EO rtrim + + // flush whitespace and print additional text, but + // only print additional chars and buffer whitespace + std::string flush(std::string& sass, converter& converter) + { + + // return flushed + std::string scss = ""; + + // print whitespace buffer + scss += PRETTIFY(converter) > 0 ? converter.whitespace : ""; + // reset whitespace buffer + converter.whitespace = ""; + + // remove possible newlines from string + size_t pos_right = sass.find_last_not_of("\n\r"); + if (pos_right == std::string::npos) return scss; + + // get the linefeeds from the string + std::string lfs = sass.substr(pos_right + 1); + sass = sass.substr(0, pos_right + 1); + + // find some source comment opener + size_t comment_pos = findCommentOpener(sass); + // check if there was a source comment + if (comment_pos != std::string::npos) + { + // convert comment (but only outside other coments) + if (CONVERT_COMMENT(converter) && !IS_COMMENT(converter)) + { + // convert to multiline comment + sass.at(comment_pos + 1) = '*'; + // add comment node to the whitespace + sass += " */"; + } + // not at line start + if (comment_pos > 0) + { + // also include whitespace before the actual comment opener + size_t ws_pos = sass.find_last_not_of(SASS2SCSS_FIND_WHITESPACE, comment_pos - 1); + comment_pos = ws_pos == std::string::npos ? 0 : ws_pos + 1; + } + if (!STRIP_COMMENT(converter)) + { + // add comment node to the whitespace + converter.whitespace += sass.substr(comment_pos); + } + else + { + // sass = removeMultilineComments(sass); + } + // update the actual sass code + sass = sass.substr(0, comment_pos); + } + + // add newline as getline discharged it + converter.whitespace += lfs + "\n"; + + // maybe remove any leading whitespace + if (PRETTIFY(converter) == 0) + { + // remove leading whitespace and update string + size_t pos_left = sass.find_first_not_of(SASS2SCSS_FIND_WHITESPACE); + if (pos_left != std::string::npos) sass = sass.substr(pos_left); + } + + // add flushed data + scss += sass; + + // return string + return scss; + } + // EO flush + + // process a line of the sass text + std::string process(std::string& sass, converter& converter) + { + + // resulting string + std::string scss = ""; + + // strip multi line comments + if (STRIP_COMMENT(converter)) + { + sass = removeMultilineComment(sass); + } + + // right trim input + sass = rtrim(sass); + + // get postion of first meaningfull character in string + size_t pos_left = sass.find_first_not_of(SASS2SCSS_FIND_WHITESPACE); + + // special case for final run + if (converter.end_of_file) pos_left = 0; + + // maybe has only whitespace + if (pos_left == std::string::npos) + { + // just add complete whitespace + converter.whitespace += sass + "\n"; + } + // have meaningfull first char + else + { + + // extract and store indentation string + std::string indent = sass.substr(0, pos_left); + + // check if current line starts a comment + std::string open = sass.substr(pos_left, 2); + + // line has less or same indentation + // finalize previous open parser context + if (indent.length() <= INDENT(converter).length()) + { + + // close multilinie comment + if (IS_CSS_COMMENT(converter)) + { + // check if comments will be stripped anyway + if (!STRIP_COMMENT(converter)) scss += " */"; + } + // close src comment comment + else if (IS_SRC_COMMENT(converter)) + { + // add a newline to avoid closer on same line + // this would put the bracket in the comment node + // no longer needed since we parse them correctly + // if (KEEP_COMMENT(converter)) scss += "\n"; + } + // close css properties + else if (converter.property) + { + // add closer unless in concat mode + if (!converter.comma) + { + // if there was no colon we have a selector + // looks like there were no inner properties + if (converter.selector) scss += " {}"; + // add final semicolon + else if (!converter.semicolon) + scss += ";"; + } + } + + // reset comment state + converter.comment = ""; + } + + // make sure we close every "higher" block + while (indent.length() < INDENT(converter).length()) + { + // pop stacked context + converter.indents.pop(); + // print close bracket + if (IS_PARSING(converter)) + { + scss += closer(converter); + } + else + { + scss += " */"; + } + // reset comment state + converter.comment = ""; + } + + // reset converter state + converter.selector = false; + + // looks like some undocumented behavior ... + // https://github.com/mgreter/sass2scss/issues/29 + if (sass.substr(pos_left, 1) == "\\") + { + converter.selector = true; + sass[pos_left] = ' '; + } + + // check if we have sass property syntax + if (sass.substr(pos_left, 1) == ":" && sass.substr(pos_left, 2) != "::") + { + + // default to a selector + // change back if property found + converter.selector = true; + // get postion of first whitespace char + size_t pos_wspace = sass.find_first_of(SASS2SCSS_FIND_WHITESPACE, pos_left); + // assertion check for valid result + if (pos_wspace != std::string::npos) + { + // get the possible pseudo selector + std::string pseudo = sass.substr(pos_left, pos_wspace - pos_left); + // get position of the first real property value char + // pseudo selectors get this far, but have no actual value + size_t pos_value = sass.find_first_not_of(SASS2SCSS_FIND_WHITESPACE, pos_wspace); + // assertion check for valid result + if (pos_value != std::string::npos) + { + // only process if not (fallowed by a semicolon or is a pseudo selector) + if (!(sass.at(pos_value) == ':' || isPseudoSelector(pseudo))) + { + // create new string by interchanging the colon sign for property and value + sass = indent + sass.substr(pos_left + 1, pos_wspace - pos_left - 1) + ":" + sass.substr(pos_wspace); + // try to find a colon in the current line, but only ... + size_t pos_colon = sass.find_first_not_of(":", pos_left); + // assertion for valid result + if (pos_colon != std::string::npos) + { + // ... after the first word (skip begining colons) + pos_colon = sass.find_first_of(":", pos_colon); + // it is a selector if there was no colon found + converter.selector = pos_colon == std::string::npos; + } + } + } + } + + // check if we have a BEM property (one colon and no selector) + if (sass.substr(pos_left, 1) == ":" && converter.selector == true) + { + size_t pos_wspace = sass.find_first_of(SASS2SCSS_FIND_WHITESPACE, pos_left); + sass = indent + sass.substr(pos_left + 1, pos_wspace) + ":"; + } + } + + // terminate some statements immediately + else if (sass.substr(pos_left, 5) == "@warn" || sass.substr(pos_left, 6) == "@debug" || + sass.substr(pos_left, 6) == "@error" || sass.substr(pos_left, 8) == "@charset" || + sass.substr(pos_left, 10) == "@namespace") + { + sass = indent + sass.substr(pos_left); + } + // replace some specific sass shorthand directives (if not fallowed by a white space + // character) + else if (sass.substr(pos_left, 1) == "=") + { + sass = indent + "@mixin " + sass.substr(pos_left + 1); + } + else if (sass.substr(pos_left, 1) == "+") + { + // must be followed by a mixin call (no whitespace afterwards or at ending directly) + if (sass[pos_left + 1] != 0 && sass[pos_left + 1] != ' ' && sass[pos_left + 1] != '\t') + { + sass = indent + "@include " + sass.substr(pos_left + 1); + } + } + + // add quotes for import if needed + else if (sass.substr(pos_left, 7) == "@import") + { + // get positions for the actual import url + size_t pos_import = sass.find_first_of(SASS2SCSS_FIND_WHITESPACE, pos_left + 7); + size_t pos_quote = sass.find_first_not_of(SASS2SCSS_FIND_WHITESPACE, pos_import); + // leave proper urls untouched + if (sass.substr(pos_quote, 4) != "url(") + { + // check if the url appears to be already quoted + if (sass.substr(pos_quote, 1) != "\"" && sass.substr(pos_quote, 1) != "\'") + { + // get position of the last char on the line + size_t pos_end = sass.find_last_not_of(SASS2SCSS_FIND_WHITESPACE); + // assertion check for valid result + if (pos_end != std::string::npos) + { + // add quotes around the full line after the import statement + sass = sass.substr(0, pos_quote) + "\"" + sass.substr(pos_quote, pos_end - pos_quote + 1) + "\""; + } + } + } + } + else if (sass.substr(pos_left, 7) != "@return" && sass.substr(pos_left, 7) != "@extend" && + sass.substr(pos_left, 8) != "@include" && sass.substr(pos_left, 8) != "@content") + { + + // probably a selector anyway + converter.selector = true; + // try to find first colon in the current line + size_t pos_colon = sass.find_first_of(":", pos_left); + // assertion that we have a colon + if (pos_colon != std::string::npos) + { + // it is not a selector if we have a space after a colon + if (sass[pos_colon + 1] == ' ') converter.selector = false; + if (sass[pos_colon + 1] == ' ') converter.selector = false; + } + } + + // current line has more indentation + if (indent.length() >= INDENT(converter).length()) + { + // not in comment mode + if (IS_PARSING(converter)) + { + // has meaningfull chars + if (hasCharData(sass)) + { + // is probably a property + // also true for selectors + converter.property = true; + } + } + } + // current line has more indentation + if (indent.length() > INDENT(converter).length()) + { + // not in comment mode + if (IS_PARSING(converter)) + { + // had meaningfull chars + if (converter.property) + { + // print block opener + scss += opener(converter); + // push new stack context + converter.indents.push(""); + // store block indentation + INDENT(converter) = indent; + } + } + // is and will be a src comment + else if (!IS_CSS_COMMENT(converter)) + { + // scss does not allow multiline src comments + // therefore add forward slashes to all lines + sass.at(INDENT(converter).length() + 0) = '/'; + // there is an edge case here if indentation + // is minimal (will overwrite the fist char) + sass.at(INDENT(converter).length() + 1) = '/'; + // could code around that, but I dont' think + // this will ever be the cause for any trouble + } + } + + // line is opening a new comment + if (open == "/*" || open == "//") + { + // reset the property state + converter.property = false; + // close previous comment + if (IS_CSS_COMMENT(converter) && open != "") + { + if (!STRIP_COMMENT(converter) && !CONVERT_COMMENT(converter)) scss += " */"; + } + // force single line comments + // into a correct css comment + if (CONVERT_COMMENT(converter)) + { + if (IS_PARSING(converter)) + { + sass.at(pos_left + 1) = '*'; + } + } + // set comment flag + converter.comment = open; + } + + // flush data only under certain conditions + if (!( + // strip css and src comments if option is set + (IS_COMMENT(converter) && STRIP_COMMENT(converter)) || + // strip src comment even if strip option is not set + // but only if the keep src comment option is not set + (IS_SRC_COMMENT(converter) && !KEEP_COMMENT(converter)))) + { + // flush data and buffer whitespace + scss += flush(sass, converter); + } + + // get postion of last meaningfull char + size_t pos_right = sass.find_last_not_of(SASS2SCSS_FIND_WHITESPACE); + + // check for invalid result + if (pos_right != std::string::npos) + { + + // get the last meaningfull char + std::string close = sass.substr(pos_right, 1); + + // check if next line should be concatenated (list mode) + converter.comma = IS_PARSING(converter) && close == ","; + converter.semicolon = IS_PARSING(converter) && close == ";"; + + // check if we have more than + // one meaningfull char + if (pos_right > 0) + { + + // get the last two chars from string + std::string close = sass.substr(pos_right - 1, 2); + // update parser status for expicitly closed comment + if (close == "*/") converter.comment = ""; + } + } + // EO have meaningfull chars from end + } + // EO have meaningfull chars from start + + // return scss + return scss; + } + // EO process + + // read line with either CR, LF or CR LF format + // http://stackoverflow.com/a/6089413/1550314 + static std::istream& safeGetline(std::istream& is, std::string& t) + { + t.clear(); + + // The characters in the stream are read one-by-one using a std::streambuf. + // That is faster than reading them one-by-one using the std::istream. + // Code that uses streambuf this way must be guarded by a sentry object. + // The sentry object performs various tasks, + // such as thread synchronization and updating the stream state. + + std::istream::sentry se(is, true); + std::streambuf* sb = is.rdbuf(); + + for (;;) + { + int c = sb->sbumpc(); + switch (c) + { + case '\n': + return is; + case '\r': + if (sb->sgetc() == '\n') sb->sbumpc(); + return is; + case EOF: + // Also handle the case when the last line has no line ending + if (t.empty()) is.setstate(std::ios::eofbit); + return is; + default: + t += (char)c; + } + } + } + + // the main converter function for c++ + char* sass2scss(const std::string& sass, const int options) + { + + // local variables + std::string line; + std::string scss = ""; + std::stringstream stream(sass); + + // create converter variable + converter converter; + // initialise all options + converter.comma = false; + converter.property = false; + converter.selector = false; + converter.semicolon = false; + converter.end_of_file = false; + converter.comment = ""; + converter.whitespace = ""; + converter.indents.push(""); + converter.options = options; + + // read line by line and process them + while (safeGetline(stream, line) && !stream.eof()) + { + scss += process(line, converter); + } + + // create mutable string + std::string closer = ""; + // set the end of file flag + converter.end_of_file = true; + // process to close all open blocks + scss += process(closer, converter); + + // allocate new memory on the heap + // caller has to free it after use + char* cstr = (char*)malloc(scss.length() + 1); + // create a copy of the string + strcpy(cstr, scss.c_str()); + // return pointer + return &cstr[0]; + } + // EO sass2scss } // EO namespace // implement for c -extern "C" -{ +extern "C" { - char* ADDCALL sass2scss (const char* sass, const int options) - { - return Sass::sass2scss(sass, options); - } - - // Get compiled sass2scss version - const char* ADDCALL sass2scss_version(void) { - return SASS2SCSS_VERSION; - } +char* ADDCALL sass2scss(const char* sass, const int options) +{ + return Sass::sass2scss(sass, options); +} +// Get compiled sass2scss version +const char* ADDCALL sass2scss_version(void) +{ + return SASS2SCSS_VERSION; +} } diff --git a/src/sass_context.cpp b/src/sass_context.cpp index bf6215ac8c..858315e18b 100644 --- a/src/sass_context.cpp +++ b/src/sass_context.cpp @@ -19,7 +19,8 @@ #define LFEED "\n" // C++ helper -namespace Sass { +namespace Sass +{ // see sass_copy_c_string(std::string str) static inline JsonNode* json_mkstream(const std::stringstream& stream) { @@ -28,11 +29,14 @@ namespace Sass { return json_mkstring(str.c_str()); } - static int handle_error(Sass_Context* c_ctx) { - try { + static int handle_error(Sass_Context* c_ctx) + { + try + { throw; } - catch (Exception::Base& e) { + catch (Exception::Base& e) + { std::stringstream msg_stream; std::string cwd(Sass::File::get_cwd()); @@ -40,14 +44,18 @@ namespace Sass { bool got_newline = false; msg_stream << msg_prefix << ": "; const char* msg = e.what(); - while (msg && *msg) { - if (*msg == '\r') { + while (msg && *msg) + { + if (*msg == '\r') + { got_newline = true; } - else if (*msg == '\n') { + else if (*msg == '\n') + { got_newline = true; } - else if (got_newline) { + else if (got_newline) + { msg_stream << std::string(msg_prefix.size() + 2, ' '); got_newline = false; } @@ -55,8 +63,10 @@ namespace Sass { ++msg; } if (!got_newline) msg_stream << "\n"; - if (e.import_stack) { - for (size_t i = 1; i < e.import_stack->size() - 1; ++i) { + if (e.import_stack) + { + for (size_t i = 1; i < e.import_stack->size() - 1; ++i) + { std::string path((*e.import_stack)[i]->imp_path); std::string rel_path(Sass::File::abs2rel(path, cwd, cwd)); msg_stream << std::string(msg_prefix.size() + 2, ' '); @@ -64,30 +74,35 @@ namespace Sass { msg_stream << e.pstate.line + 1 << " of " << rel_path << "\n"; } } - else { + else + { std::string rel_path(Sass::File::abs2rel(e.pstate.path, cwd, cwd)); msg_stream << std::string(msg_prefix.size() + 2, ' '); msg_stream << " on line " << e.pstate.line + 1 << " of " << rel_path << "\n"; } // now create the code trace (ToDo: maybe have util functions?) - if (e.pstate.line != std::string::npos && e.pstate.column != std::string::npos) { + if (e.pstate.line != std::string::npos && e.pstate.column != std::string::npos) + { size_t line = e.pstate.line; const char* line_beg = e.pstate.src; - while (line_beg && *line_beg && line) { + while (line_beg && *line_beg && line) + { if (*line_beg == '\n') --line; ++line_beg; } const char* line_end = line_beg; - while (line_end && *line_end && *line_end != '\n') { + while (line_end && *line_end && *line_end != '\n') + { if (*line_end == '\n') break; if (*line_end == '\r') break; line_end++; } - size_t max_left = 42; size_t max_right = 78; + size_t max_left = 42; + size_t max_right = 78; size_t move_in = e.pstate.column > max_left ? e.pstate.column - max_left : 0; - size_t shorten = (line_end - line_beg) - move_in > max_right ? - (line_end - line_beg) - move_in - max_right : 0; + size_t shorten = + (line_end - line_beg) - move_in > max_right ? (line_end - line_beg) - move_in - max_right : 0; msg_stream << ">> " << std::string(line_beg + move_in, line_end - shorten) << "\n"; msg_stream << " " << std::string(e.pstate.column - move_in, '-') << "^\n"; } @@ -99,8 +114,13 @@ namespace Sass { json_append_member(json_err, "column", json_mknumber((double)(e.pstate.column + 1))); json_append_member(json_err, "message", json_mkstring(e.what())); json_append_member(json_err, "formatted", json_mkstream(msg_stream)); - try { c_ctx->error_json = json_stringify(json_err, " "); } - catch (...) {} + try + { + c_ctx->error_json = json_stringify(json_err, " "); + } + catch (...) + { + } c_ctx->error_message = sass_copy_string(msg_stream.str()); c_ctx->error_text = sass_copy_c_string(e.what()); c_ctx->error_status = 1; @@ -112,15 +132,21 @@ namespace Sass { c_ctx->source_map_string = 0; json_delete(json_err); } - catch (std::bad_alloc& ba) { + catch (std::bad_alloc& ba) + { std::stringstream msg_stream; JsonNode* json_err = json_mkobject(); msg_stream << "Unable to allocate memory: " << ba.what() << std::endl; json_append_member(json_err, "status", json_mknumber(2)); json_append_member(json_err, "message", json_mkstring(ba.what())); json_append_member(json_err, "formatted", json_mkstream(msg_stream)); - try { c_ctx->error_json = json_stringify(json_err, " "); } - catch (...) {} + try + { + c_ctx->error_json = json_stringify(json_err, " "); + } + catch (...) + { + } c_ctx->error_message = sass_copy_string(msg_stream.str()); c_ctx->error_text = sass_copy_c_string(ba.what()); c_ctx->error_status = 2; @@ -128,15 +154,21 @@ namespace Sass { c_ctx->source_map_string = 0; json_delete(json_err); } - catch (std::exception& e) { + catch (std::exception& e) + { std::stringstream msg_stream; JsonNode* json_err = json_mkobject(); msg_stream << "Internal Error: " << e.what() << std::endl; json_append_member(json_err, "status", json_mknumber(3)); json_append_member(json_err, "message", json_mkstring(e.what())); json_append_member(json_err, "formatted", json_mkstream(msg_stream)); - try { c_ctx->error_json = json_stringify(json_err, " "); } - catch (...) {} + try + { + c_ctx->error_json = json_stringify(json_err, " "); + } + catch (...) + { + } c_ctx->error_message = sass_copy_string(msg_stream.str()); c_ctx->error_text = sass_copy_c_string(e.what()); c_ctx->error_status = 3; @@ -144,15 +176,21 @@ namespace Sass { c_ctx->source_map_string = 0; json_delete(json_err); } - catch (std::string& e) { + catch (std::string& e) + { std::stringstream msg_stream; JsonNode* json_err = json_mkobject(); msg_stream << "Internal Error: " << e << std::endl; json_append_member(json_err, "status", json_mknumber(4)); json_append_member(json_err, "message", json_mkstring(e.c_str())); json_append_member(json_err, "formatted", json_mkstream(msg_stream)); - try { c_ctx->error_json = json_stringify(json_err, " "); } - catch (...) {} + try + { + c_ctx->error_json = json_stringify(json_err, " "); + } + catch (...) + { + } c_ctx->error_message = sass_copy_string(msg_stream.str()); c_ctx->error_text = sass_copy_c_string(e.c_str()); c_ctx->error_status = 4; @@ -160,15 +198,21 @@ namespace Sass { c_ctx->source_map_string = 0; json_delete(json_err); } - catch (const char* e) { + catch (const char* e) + { std::stringstream msg_stream; JsonNode* json_err = json_mkobject(); msg_stream << "Internal Error: " << e << std::endl; json_append_member(json_err, "status", json_mknumber(4)); json_append_member(json_err, "message", json_mkstring(e)); json_append_member(json_err, "formatted", json_mkstream(msg_stream)); - try { c_ctx->error_json = json_stringify(json_err, " "); } - catch (...) {} + try + { + c_ctx->error_json = json_stringify(json_err, " "); + } + catch (...) + { + } c_ctx->error_message = sass_copy_string(msg_stream.str()); c_ctx->error_text = sass_copy_c_string(e); c_ctx->error_status = 4; @@ -176,14 +220,20 @@ namespace Sass { c_ctx->source_map_string = 0; json_delete(json_err); } - catch (...) { + catch (...) + { std::stringstream msg_stream; JsonNode* json_err = json_mkobject(); msg_stream << "Unknown error occurred" << std::endl; json_append_member(json_err, "status", json_mknumber(5)); json_append_member(json_err, "message", json_mkstring("unknown")); - try { c_ctx->error_json = json_stringify(json_err, " "); } - catch (...) {} + try + { + c_ctx->error_json = json_stringify(json_err, " "); + } + catch (...) + { + } c_ctx->error_message = sass_copy_string(msg_stream.str()); c_ctx->error_text = sass_copy_c_string("unknown"); c_ctx->error_status = 5; @@ -196,9 +246,16 @@ namespace Sass { // allow one error handler to throw another error // this can happen with invalid utf8 and json lib - static int handle_errors(Sass_Context* c_ctx) { - try { return handle_error(c_ctx); } - catch (...) { return handle_error(c_ctx); } + static int handle_errors(Sass_Context* c_ctx) + { + try + { + return handle_error(c_ctx); + } + catch (...) + { + return handle_error(c_ctx); + } } static Block_Obj sass_parse_block(Sass_Compiler* compiler) throw() @@ -213,7 +270,8 @@ namespace Sass { compiler->cpp_ctx->c_compiler = compiler; compiler->state = SASS_COMPILER_PARSED; - try { + try + { // get input/output path from options std::string input_path = safe_str(c_ctx->input_path); @@ -240,548 +298,717 @@ namespace Sass { // return parsed block return root; - } // pass errors to generic error handler - catch (...) { handle_errors(c_ctx); } + catch (...) + { + handle_errors(c_ctx); + } // error return 0; - } - } extern "C" { - using namespace Sass; - - static void sass_clear_options (struct Sass_Options* options); - static void sass_reset_options (struct Sass_Options* options); - static void copy_options(struct Sass_Options* to, struct Sass_Options* from) { - // do not overwrite ourself - if (to == from) return; - // free assigned memory - sass_clear_options(to); - // move memory - *to = *from; - // Reset pointers on source - sass_reset_options(from); - } - - #define IMPLEMENT_SASS_OPTION_ACCESSOR(type, option) \ - type ADDCALL sass_option_get_##option (struct Sass_Options* options) { return options->option; } \ - void ADDCALL sass_option_set_##option (struct Sass_Options* options, type option) { options->option = option; } - #define IMPLEMENT_SASS_OPTION_STRING_GETTER(type, option, def) \ - type ADDCALL sass_option_get_##option (struct Sass_Options* options) { return safe_str(options->option, def); } - #define IMPLEMENT_SASS_OPTION_STRING_SETTER(type, option, def) \ - void ADDCALL sass_option_set_##option (struct Sass_Options* options, type option) \ - { free(options->option); options->option = option || def ? sass_copy_c_string(option ? option : def) : 0; } - #define IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(type, option, def) \ - IMPLEMENT_SASS_OPTION_STRING_GETTER(type, option, def) \ - IMPLEMENT_SASS_OPTION_STRING_SETTER(type, option, def) - - #define IMPLEMENT_SASS_CONTEXT_GETTER(type, option) \ - type ADDCALL sass_context_get_##option (struct Sass_Context* ctx) { return ctx->option; } - #define IMPLEMENT_SASS_CONTEXT_TAKER(type, option) \ - type sass_context_take_##option (struct Sass_Context* ctx) \ - { type foo = ctx->option; ctx->option = 0; return foo; } - - - // generic compilation function (not exported, use file/data compile instead) - static Sass_Compiler* sass_prepare_context (Sass_Context* c_ctx, Context* cpp_ctx) throw() - { - try { - // register our custom functions - if (c_ctx->c_functions) { - auto this_func_data = c_ctx->c_functions; - while (this_func_data && *this_func_data) { - cpp_ctx->add_c_function(*this_func_data); - ++this_func_data; - } - } +using namespace Sass; + +static void sass_clear_options(struct Sass_Options* options); +static void sass_reset_options(struct Sass_Options* options); +static void copy_options(struct Sass_Options* to, struct Sass_Options* from) +{ + // do not overwrite ourself + if (to == from) return; + // free assigned memory + sass_clear_options(to); + // move memory + *to = *from; + // Reset pointers on source + sass_reset_options(from); +} - // register our custom headers - if (c_ctx->c_headers) { - auto this_head_data = c_ctx->c_headers; - while (this_head_data && *this_head_data) { - cpp_ctx->add_c_header(*this_head_data); - ++this_head_data; - } +#define IMPLEMENT_SASS_OPTION_ACCESSOR(type, option) \ + type ADDCALL sass_option_get_##option(struct Sass_Options* options) \ + { \ + return options->option; \ + } \ + void ADDCALL sass_option_set_##option(struct Sass_Options* options, type option) \ + { \ + options->option = option; \ + } +#define IMPLEMENT_SASS_OPTION_STRING_GETTER(type, option, def) \ + type ADDCALL sass_option_get_##option(struct Sass_Options* options) \ + { \ + return safe_str(options->option, def); \ + } +#define IMPLEMENT_SASS_OPTION_STRING_SETTER(type, option, def) \ + void ADDCALL sass_option_set_##option(struct Sass_Options* options, type option) \ + { \ + free(options->option); \ + options->option = option || def ? sass_copy_c_string(option ? option : def) : 0; \ + } +#define IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(type, option, def) \ + IMPLEMENT_SASS_OPTION_STRING_GETTER(type, option, def) \ + IMPLEMENT_SASS_OPTION_STRING_SETTER(type, option, def) + +#define IMPLEMENT_SASS_CONTEXT_GETTER(type, option) \ + type ADDCALL sass_context_get_##option(struct Sass_Context* ctx) \ + { \ + return ctx->option; \ + } +#define IMPLEMENT_SASS_CONTEXT_TAKER(type, option) \ + type sass_context_take_##option(struct Sass_Context* ctx) \ + { \ + type foo = ctx->option; \ + ctx->option = 0; \ + return foo; \ + } + + +// generic compilation function (not exported, use file/data compile instead) +static Sass_Compiler* sass_prepare_context(Sass_Context* c_ctx, Context* cpp_ctx) throw() +{ + try + { + // register our custom functions + if (c_ctx->c_functions) + { + auto this_func_data = c_ctx->c_functions; + while (this_func_data && *this_func_data) + { + cpp_ctx->add_c_function(*this_func_data); + ++this_func_data; } + } - // register our custom importers - if (c_ctx->c_importers) { - auto this_imp_data = c_ctx->c_importers; - while (this_imp_data && *this_imp_data) { - cpp_ctx->add_c_importer(*this_imp_data); - ++this_imp_data; - } + // register our custom headers + if (c_ctx->c_headers) + { + auto this_head_data = c_ctx->c_headers; + while (this_head_data && *this_head_data) + { + cpp_ctx->add_c_header(*this_head_data); + ++this_head_data; } + } - // reset error status - c_ctx->error_json = 0; - c_ctx->error_text = 0; - c_ctx->error_message = 0; - c_ctx->error_status = 0; - // reset error position - c_ctx->error_src = 0; - c_ctx->error_file = 0; - c_ctx->error_line = std::string::npos; - c_ctx->error_column = std::string::npos; - - // allocate a new compiler instance - void* ctxmem = calloc(1, sizeof(struct Sass_Compiler)); - if (ctxmem == 0) { std::cerr << "Error allocating memory for context" << std::endl; return 0; } - Sass_Compiler* compiler = (struct Sass_Compiler*) ctxmem; - compiler->state = SASS_COMPILER_CREATED; - - // store in sass compiler - compiler->c_ctx = c_ctx; - compiler->cpp_ctx = cpp_ctx; - cpp_ctx->c_compiler = compiler; - - // use to parse block - return compiler; + // register our custom importers + if (c_ctx->c_importers) + { + auto this_imp_data = c_ctx->c_importers; + while (this_imp_data && *this_imp_data) + { + cpp_ctx->add_c_importer(*this_imp_data); + ++this_imp_data; + } + } + // reset error status + c_ctx->error_json = 0; + c_ctx->error_text = 0; + c_ctx->error_message = 0; + c_ctx->error_status = 0; + // reset error position + c_ctx->error_src = 0; + c_ctx->error_file = 0; + c_ctx->error_line = std::string::npos; + c_ctx->error_column = std::string::npos; + + // allocate a new compiler instance + void* ctxmem = calloc(1, sizeof(struct Sass_Compiler)); + if (ctxmem == 0) + { + std::cerr << "Error allocating memory for context" << std::endl; + return 0; } - // pass errors to generic error handler - catch (...) { handle_errors(c_ctx); } + Sass_Compiler* compiler = (struct Sass_Compiler*)ctxmem; + compiler->state = SASS_COMPILER_CREATED; - // error - return 0; + // store in sass compiler + compiler->c_ctx = c_ctx; + compiler->cpp_ctx = cpp_ctx; + cpp_ctx->c_compiler = compiler; + // use to parse block + return compiler; } - - // generic compilation function (not exported, use file/data compile instead) - static int sass_compile_context (Sass_Context* c_ctx, Context* cpp_ctx) + // pass errors to generic error handler + catch (...) { + handle_errors(c_ctx); + } - // prepare sass compiler with context and options - Sass_Compiler* compiler = sass_prepare_context(c_ctx, cpp_ctx); + // error + return 0; +} - try { - // call each compiler step - sass_compiler_parse(compiler); - sass_compiler_execute(compiler); - } - // pass errors to generic error handler - catch (...) { handle_errors(c_ctx); } +// generic compilation function (not exported, use file/data compile instead) +static int sass_compile_context(Sass_Context* c_ctx, Context* cpp_ctx) +{ - sass_delete_compiler(compiler); + // prepare sass compiler with context and options + Sass_Compiler* compiler = sass_prepare_context(c_ctx, cpp_ctx); - return c_ctx->error_status; + try + { + // call each compiler step + sass_compiler_parse(compiler); + sass_compiler_execute(compiler); } - - inline void init_options (struct Sass_Options* options) + // pass errors to generic error handler + catch (...) { - options->precision = 5; - options->indent = " "; - options->linefeed = LFEED; + handle_errors(c_ctx); } - Sass_Options* ADDCALL sass_make_options (void) + sass_delete_compiler(compiler); + + return c_ctx->error_status; +} + +inline void init_options(struct Sass_Options* options) +{ + options->precision = 5; + options->indent = " "; + options->linefeed = LFEED; +} + +Sass_Options* ADDCALL sass_make_options(void) +{ + struct Sass_Options* options = (struct Sass_Options*)calloc(1, sizeof(struct Sass_Options)); + if (options == 0) { - struct Sass_Options* options = (struct Sass_Options*) calloc(1, sizeof(struct Sass_Options)); - if (options == 0) { std::cerr << "Error allocating memory for options" << std::endl; return 0; } - init_options(options); - return options; + std::cerr << "Error allocating memory for options" << std::endl; + return 0; } + init_options(options); + return options; +} - Sass_File_Context* ADDCALL sass_make_file_context(const char* input_path) +Sass_File_Context* ADDCALL sass_make_file_context(const char* input_path) +{ + SharedObj::setTaint(true); // needed for static colors + struct Sass_File_Context* ctx = (struct Sass_File_Context*)calloc(1, sizeof(struct Sass_File_Context)); + if (ctx == 0) { - SharedObj::setTaint(true); // needed for static colors - struct Sass_File_Context* ctx = (struct Sass_File_Context*) calloc(1, sizeof(struct Sass_File_Context)); - if (ctx == 0) { std::cerr << "Error allocating memory for file context" << std::endl; return 0; } - ctx->type = SASS_CONTEXT_FILE; - init_options(ctx); - try { - if (input_path == 0) { throw(std::runtime_error("File context created without an input path")); } - if (*input_path == 0) { throw(std::runtime_error("File context created with empty input path")); } - sass_option_set_input_path(ctx, input_path); - } catch (...) { - handle_errors(ctx); - } - return ctx; + std::cerr << "Error allocating memory for file context" << std::endl; + return 0; } - - Sass_Data_Context* ADDCALL sass_make_data_context(char* source_string) + ctx->type = SASS_CONTEXT_FILE; + init_options(ctx); + try { - struct Sass_Data_Context* ctx = (struct Sass_Data_Context*) calloc(1, sizeof(struct Sass_Data_Context)); - if (ctx == 0) { std::cerr << "Error allocating memory for data context" << std::endl; return 0; } - ctx->type = SASS_CONTEXT_DATA; - init_options(ctx); - try { - if (source_string == 0) { throw(std::runtime_error("Data context created without a source string")); } - if (*source_string == 0) { throw(std::runtime_error("Data context created with empty source string")); } - ctx->source_string = source_string; - } catch (...) { - handle_errors(ctx); + if (input_path == 0) + { + throw(std::runtime_error("File context created without an input path")); + } + if (*input_path == 0) + { + throw(std::runtime_error("File context created with empty input path")); } - return ctx; + sass_option_set_input_path(ctx, input_path); } - - struct Sass_Compiler* ADDCALL sass_make_data_compiler (struct Sass_Data_Context* data_ctx) + catch (...) { - if (data_ctx == 0) return 0; - Context* cpp_ctx = new Data_Context(*data_ctx); - return sass_prepare_context(data_ctx, cpp_ctx); + handle_errors(ctx); } + return ctx; +} - struct Sass_Compiler* ADDCALL sass_make_file_compiler (struct Sass_File_Context* file_ctx) +Sass_Data_Context* ADDCALL sass_make_data_context(char* source_string) +{ + struct Sass_Data_Context* ctx = (struct Sass_Data_Context*)calloc(1, sizeof(struct Sass_Data_Context)); + if (ctx == 0) { - if (file_ctx == 0) return 0; - Context* cpp_ctx = new File_Context(*file_ctx); - return sass_prepare_context(file_ctx, cpp_ctx); + std::cerr << "Error allocating memory for data context" << std::endl; + return 0; } - - int ADDCALL sass_compile_data_context(Sass_Data_Context* data_ctx) + ctx->type = SASS_CONTEXT_DATA; + init_options(ctx); + try { - if (data_ctx == 0) return 1; - if (data_ctx->error_status) - return data_ctx->error_status; - try { - if (data_ctx->source_string == 0) { throw(std::runtime_error("Data context has no source string")); } - // empty source string is a valid case, even if not really usefull (different than with file context) - // if (*data_ctx->source_string == 0) { throw(std::runtime_error("Data context has empty source string")); } + if (source_string == 0) + { + throw(std::runtime_error("Data context created without a source string")); + } + if (*source_string == 0) + { + throw(std::runtime_error("Data context created with empty source string")); } - catch (...) { return handle_errors(data_ctx) | 1; } - Context* cpp_ctx = new Data_Context(*data_ctx); - return sass_compile_context(data_ctx, cpp_ctx); + ctx->source_string = source_string; } + catch (...) + { + handle_errors(ctx); + } + return ctx; +} - int ADDCALL sass_compile_file_context(Sass_File_Context* file_ctx) +struct Sass_Compiler* ADDCALL sass_make_data_compiler(struct Sass_Data_Context* data_ctx) +{ + if (data_ctx == 0) return 0; + Context* cpp_ctx = new Data_Context(*data_ctx); + return sass_prepare_context(data_ctx, cpp_ctx); +} + +struct Sass_Compiler* ADDCALL sass_make_file_compiler(struct Sass_File_Context* file_ctx) +{ + if (file_ctx == 0) return 0; + Context* cpp_ctx = new File_Context(*file_ctx); + return sass_prepare_context(file_ctx, cpp_ctx); +} + +int ADDCALL sass_compile_data_context(Sass_Data_Context* data_ctx) +{ + if (data_ctx == 0) return 1; + if (data_ctx->error_status) return data_ctx->error_status; + try { - if (file_ctx == 0) return 1; - if (file_ctx->error_status) - return file_ctx->error_status; - try { - if (file_ctx->input_path == 0) { throw(std::runtime_error("File context has no input path")); } - if (*file_ctx->input_path == 0) { throw(std::runtime_error("File context has empty input path")); } + if (data_ctx->source_string == 0) + { + throw(std::runtime_error("Data context has no source string")); } - catch (...) { return handle_errors(file_ctx) | 1; } - Context* cpp_ctx = new File_Context(*file_ctx); - return sass_compile_context(file_ctx, cpp_ctx); - } - - int ADDCALL sass_compiler_parse(struct Sass_Compiler* compiler) - { - if (compiler == 0) return 1; - if (compiler->state == SASS_COMPILER_PARSED) return 0; - if (compiler->state != SASS_COMPILER_CREATED) return -1; - if (compiler->c_ctx == NULL) return 1; - if (compiler->cpp_ctx == NULL) return 1; - if (compiler->c_ctx->error_status) - return compiler->c_ctx->error_status; - // parse the context we have set up (file or data) - compiler->root = sass_parse_block(compiler); - // success - return 0; + // empty source string is a valid case, even if not really usefull (different than with file + // context) + // if (*data_ctx->source_string == 0) { throw(std::runtime_error("Data context has empty source + // string")); } } - - int ADDCALL sass_compiler_execute(struct Sass_Compiler* compiler) + catch (...) { - if (compiler == 0) return 1; - if (compiler->state == SASS_COMPILER_EXECUTED) return 0; - if (compiler->state != SASS_COMPILER_PARSED) return -1; - if (compiler->c_ctx == NULL) return 1; - if (compiler->cpp_ctx == NULL) return 1; - if (compiler->root.isNull()) return 1; - if (compiler->c_ctx->error_status) - return compiler->c_ctx->error_status; - compiler->state = SASS_COMPILER_EXECUTED; - Context* cpp_ctx = compiler->cpp_ctx; - Block_Obj root = compiler->root; - // compile the parsed root block - try { compiler->c_ctx->output_string = cpp_ctx->render(root); } - // pass catched errors to generic error handler - catch (...) { return handle_errors(compiler->c_ctx) | 1; } - // generate source map json and store on context - compiler->c_ctx->source_map_string = cpp_ctx->render_srcmap(); - // success - return 0; + return handle_errors(data_ctx) | 1; } + Context* cpp_ctx = new Data_Context(*data_ctx); + return sass_compile_context(data_ctx, cpp_ctx); +} - // helper function, not exported, only accessible locally - static void sass_reset_options (struct Sass_Options* options) - { - // free pointer before - // or copy/move them - options->input_path = 0; - options->output_path = 0; - options->plugin_path = 0; - options->include_path = 0; - options->source_map_file = 0; - options->source_map_root = 0; - options->c_functions = 0; - options->c_importers = 0; - options->c_headers = 0; - options->plugin_paths = 0; - options->include_paths = 0; - } - - // helper function, not exported, only accessible locally - static void sass_clear_options (struct Sass_Options* options) - { - if (options == 0) return; - // Deallocate custom functions - if (options->c_functions) { - Sass_Function_List this_func_data = options->c_functions; - while (this_func_data && *this_func_data) { - free(*this_func_data); - ++this_func_data; - } +int ADDCALL sass_compile_file_context(Sass_File_Context* file_ctx) +{ + if (file_ctx == 0) return 1; + if (file_ctx->error_status) return file_ctx->error_status; + try + { + if (file_ctx->input_path == 0) + { + throw(std::runtime_error("File context has no input path")); } - // Deallocate custom headers - if (options->c_headers) { - Sass_Importer_List this_head_data = options->c_headers; - while (this_head_data && *this_head_data) { - free(*this_head_data); - ++this_head_data; - } + if (*file_ctx->input_path == 0) + { + throw(std::runtime_error("File context has empty input path")); } - // Deallocate custom importers - if (options->c_importers) { - Sass_Importer_List this_imp_data = options->c_importers; - while (this_imp_data && *this_imp_data) { - free(*this_imp_data); - ++this_imp_data; - } + } + catch (...) + { + return handle_errors(file_ctx) | 1; + } + Context* cpp_ctx = new File_Context(*file_ctx); + return sass_compile_context(file_ctx, cpp_ctx); +} + +int ADDCALL sass_compiler_parse(struct Sass_Compiler* compiler) +{ + if (compiler == 0) return 1; + if (compiler->state == SASS_COMPILER_PARSED) return 0; + if (compiler->state != SASS_COMPILER_CREATED) return -1; + if (compiler->c_ctx == NULL) return 1; + if (compiler->cpp_ctx == NULL) return 1; + if (compiler->c_ctx->error_status) return compiler->c_ctx->error_status; + // parse the context we have set up (file or data) + compiler->root = sass_parse_block(compiler); + // success + return 0; +} + +int ADDCALL sass_compiler_execute(struct Sass_Compiler* compiler) +{ + if (compiler == 0) return 1; + if (compiler->state == SASS_COMPILER_EXECUTED) return 0; + if (compiler->state != SASS_COMPILER_PARSED) return -1; + if (compiler->c_ctx == NULL) return 1; + if (compiler->cpp_ctx == NULL) return 1; + if (compiler->root.isNull()) return 1; + if (compiler->c_ctx->error_status) return compiler->c_ctx->error_status; + compiler->state = SASS_COMPILER_EXECUTED; + Context* cpp_ctx = compiler->cpp_ctx; + Block_Obj root = compiler->root; + // compile the parsed root block + try + { + compiler->c_ctx->output_string = cpp_ctx->render(root); + } + // pass catched errors to generic error handler + catch (...) + { + return handle_errors(compiler->c_ctx) | 1; + } + // generate source map json and store on context + compiler->c_ctx->source_map_string = cpp_ctx->render_srcmap(); + // success + return 0; +} + +// helper function, not exported, only accessible locally +static void sass_reset_options(struct Sass_Options* options) +{ + // free pointer before + // or copy/move them + options->input_path = 0; + options->output_path = 0; + options->plugin_path = 0; + options->include_path = 0; + options->source_map_file = 0; + options->source_map_root = 0; + options->c_functions = 0; + options->c_importers = 0; + options->c_headers = 0; + options->plugin_paths = 0; + options->include_paths = 0; +} + +// helper function, not exported, only accessible locally +static void sass_clear_options(struct Sass_Options* options) +{ + if (options == 0) return; + // Deallocate custom functions + if (options->c_functions) + { + Sass_Function_List this_func_data = options->c_functions; + while (this_func_data && *this_func_data) + { + free(*this_func_data); + ++this_func_data; } - // Deallocate inc paths - if (options->plugin_paths) { - struct string_list* cur; - struct string_list* next; - cur = options->plugin_paths; - while (cur) { - next = cur->next; - free(cur->string); - free(cur); - cur = next; - } + } + // Deallocate custom headers + if (options->c_headers) + { + Sass_Importer_List this_head_data = options->c_headers; + while (this_head_data && *this_head_data) + { + free(*this_head_data); + ++this_head_data; } - // Deallocate inc paths - if (options->include_paths) { - struct string_list* cur; - struct string_list* next; - cur = options->include_paths; - while (cur) { - next = cur->next; - free(cur->string); - free(cur); - cur = next; - } + } + // Deallocate custom importers + if (options->c_importers) + { + Sass_Importer_List this_imp_data = options->c_importers; + while (this_imp_data && *this_imp_data) + { + free(*this_imp_data); + ++this_imp_data; } - // Free options strings - free(options->input_path); - free(options->output_path); - free(options->plugin_path); - free(options->include_path); - free(options->source_map_file); - free(options->source_map_root); - // Free custom functions - free(options->c_functions); - // Free custom importers - free(options->c_importers); - free(options->c_headers); - // Reset our pointers - options->input_path = 0; - options->output_path = 0; - options->plugin_path = 0; - options->include_path = 0; - options->source_map_file = 0; - options->source_map_root = 0; - options->c_functions = 0; - options->c_importers = 0; - options->c_headers = 0; - options->plugin_paths = 0; - options->include_paths = 0; - } - - // helper function, not exported, only accessible locally - // sass_free_context is also defined in old sass_interface - static void sass_clear_context (struct Sass_Context* ctx) - { - if (ctx == 0) return; - // release the allocated memory (mostly via sass_copy_c_string) - if (ctx->output_string) free(ctx->output_string); - if (ctx->source_map_string) free(ctx->source_map_string); - if (ctx->error_message) free(ctx->error_message); - if (ctx->error_text) free(ctx->error_text); - if (ctx->error_json) free(ctx->error_json); - if (ctx->error_file) free(ctx->error_file); - free_string_array(ctx->included_files); - // play safe and reset properties - ctx->output_string = 0; - ctx->source_map_string = 0; - ctx->error_message = 0; - ctx->error_text = 0; - ctx->error_json = 0; - ctx->error_file = 0; - ctx->included_files = 0; - // debug leaked memory - #ifdef DEBUG_SHARED_PTR - SharedObj::dumpMemLeaks(); - #endif - // now clear the options - sass_clear_options(ctx); - } - - void ADDCALL sass_delete_compiler (struct Sass_Compiler* compiler) - { - if (compiler == 0) { - return; + } + // Deallocate inc paths + if (options->plugin_paths) + { + struct string_list* cur; + struct string_list* next; + cur = options->plugin_paths; + while (cur) + { + next = cur->next; + free(cur->string); + free(cur); + cur = next; } - Context* cpp_ctx = compiler->cpp_ctx; - if (cpp_ctx) delete(cpp_ctx); - compiler->cpp_ctx = NULL; - compiler->c_ctx = NULL; - compiler->root = NULL; - free(compiler); - } - - void ADDCALL sass_delete_options (struct Sass_Options* options) - { - sass_clear_options(options); free(options); - } - - // Deallocate all associated memory with file context - void ADDCALL sass_delete_file_context (struct Sass_File_Context* ctx) - { - // clear the context and free it - sass_clear_context(ctx); free(ctx); - } - // Deallocate all associated memory with data context - void ADDCALL sass_delete_data_context (struct Sass_Data_Context* ctx) - { - // clean the source string if it was not passed - // we reset this member once we start parsing - if (ctx->source_string) free(ctx->source_string); - // clear the context and free it - sass_clear_context(ctx); free(ctx); - } - - // Getters for sass context from specific implementations - struct Sass_Context* ADDCALL sass_file_context_get_context(struct Sass_File_Context* ctx) { return ctx; } - struct Sass_Context* ADDCALL sass_data_context_get_context(struct Sass_Data_Context* ctx) { return ctx; } - - // Getters for context options from Sass_Context - struct Sass_Options* ADDCALL sass_context_get_options(struct Sass_Context* ctx) { return ctx; } - struct Sass_Options* ADDCALL sass_file_context_get_options(struct Sass_File_Context* ctx) { return ctx; } - struct Sass_Options* ADDCALL sass_data_context_get_options(struct Sass_Data_Context* ctx) { return ctx; } - void ADDCALL sass_file_context_set_options (struct Sass_File_Context* ctx, struct Sass_Options* opt) { copy_options(ctx, opt); } - void ADDCALL sass_data_context_set_options (struct Sass_Data_Context* ctx, struct Sass_Options* opt) { copy_options(ctx, opt); } - - // Getters for Sass_Compiler options (get conected sass context) - enum Sass_Compiler_State ADDCALL sass_compiler_get_state(struct Sass_Compiler* compiler) { return compiler->state; } - struct Sass_Context* ADDCALL sass_compiler_get_context(struct Sass_Compiler* compiler) { return compiler->c_ctx; } - struct Sass_Options* ADDCALL sass_compiler_get_options(struct Sass_Compiler* compiler) { return compiler->c_ctx; } - // Getters for Sass_Compiler options (query import stack) - size_t ADDCALL sass_compiler_get_import_stack_size(struct Sass_Compiler* compiler) { return compiler->cpp_ctx->import_stack.size(); } - Sass_Import_Entry ADDCALL sass_compiler_get_last_import(struct Sass_Compiler* compiler) { return compiler->cpp_ctx->import_stack.back(); } - Sass_Import_Entry ADDCALL sass_compiler_get_import_entry(struct Sass_Compiler* compiler, size_t idx) { return compiler->cpp_ctx->import_stack[idx]; } - // Getters for Sass_Compiler options (query function stack) - size_t ADDCALL sass_compiler_get_callee_stack_size(struct Sass_Compiler* compiler) { return compiler->cpp_ctx->callee_stack.size(); } - Sass_Callee_Entry ADDCALL sass_compiler_get_last_callee(struct Sass_Compiler* compiler) { return &compiler->cpp_ctx->callee_stack.back(); } - Sass_Callee_Entry ADDCALL sass_compiler_get_callee_entry(struct Sass_Compiler* compiler, size_t idx) { return &compiler->cpp_ctx->callee_stack[idx]; } - - // Calculate the size of the stored null terminated array - size_t ADDCALL sass_context_get_included_files_size (struct Sass_Context* ctx) - { size_t l = 0; auto i = ctx->included_files; while (i && *i) { ++i; ++l; } return l; } - - // Create getter and setters for options - IMPLEMENT_SASS_OPTION_ACCESSOR(int, precision); - IMPLEMENT_SASS_OPTION_ACCESSOR(enum Sass_Output_Style, output_style); - IMPLEMENT_SASS_OPTION_ACCESSOR(bool, source_comments); - IMPLEMENT_SASS_OPTION_ACCESSOR(bool, source_map_embed); - IMPLEMENT_SASS_OPTION_ACCESSOR(bool, source_map_contents); - IMPLEMENT_SASS_OPTION_ACCESSOR(bool, source_map_file_urls); - IMPLEMENT_SASS_OPTION_ACCESSOR(bool, omit_source_map_url); - IMPLEMENT_SASS_OPTION_ACCESSOR(bool, is_indented_syntax_src); - IMPLEMENT_SASS_OPTION_ACCESSOR(Sass_Function_List, c_functions); - IMPLEMENT_SASS_OPTION_ACCESSOR(Sass_Importer_List, c_importers); - IMPLEMENT_SASS_OPTION_ACCESSOR(Sass_Importer_List, c_headers); - IMPLEMENT_SASS_OPTION_ACCESSOR(const char*, indent); - IMPLEMENT_SASS_OPTION_ACCESSOR(const char*, linefeed); - IMPLEMENT_SASS_OPTION_STRING_SETTER(const char*, plugin_path, 0); - IMPLEMENT_SASS_OPTION_STRING_SETTER(const char*, include_path, 0); - IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, input_path, 0); - IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, output_path, 0); - IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, source_map_file, 0); - IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, source_map_root, 0); - - // Create getter and setters for context - IMPLEMENT_SASS_CONTEXT_GETTER(int, error_status); - IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_json); - IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_message); - IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_text); - IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_file); - IMPLEMENT_SASS_CONTEXT_GETTER(size_t, error_line); - IMPLEMENT_SASS_CONTEXT_GETTER(size_t, error_column); - IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_src); - IMPLEMENT_SASS_CONTEXT_GETTER(const char*, output_string); - IMPLEMENT_SASS_CONTEXT_GETTER(const char*, source_map_string); - IMPLEMENT_SASS_CONTEXT_GETTER(char**, included_files); - - // Take ownership of memory (value on context is set to 0) - IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_json); - IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_message); - IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_text); - IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_file); - IMPLEMENT_SASS_CONTEXT_TAKER(char*, output_string); - IMPLEMENT_SASS_CONTEXT_TAKER(char*, source_map_string); - IMPLEMENT_SASS_CONTEXT_TAKER(char**, included_files); - - // Push function for include paths (no manipulation support for now) - void ADDCALL sass_option_push_include_path(struct Sass_Options* options, const char* path) - { - - struct string_list* include_path = (struct string_list*) calloc(1, sizeof(struct string_list)); - if (include_path == 0) return; - include_path->string = path ? sass_copy_c_string(path) : 0; - struct string_list* last = options->include_paths; - if (!options->include_paths) { - options->include_paths = include_path; - } else { - while (last->next) - last = last->next; - last->next = include_path; + } + // Deallocate inc paths + if (options->include_paths) + { + struct string_list* cur; + struct string_list* next; + cur = options->include_paths; + while (cur) + { + next = cur->next; + free(cur->string); + free(cur); + cur = next; } - } + // Free options strings + free(options->input_path); + free(options->output_path); + free(options->plugin_path); + free(options->include_path); + free(options->source_map_file); + free(options->source_map_root); + // Free custom functions + free(options->c_functions); + // Free custom importers + free(options->c_importers); + free(options->c_headers); + // Reset our pointers + options->input_path = 0; + options->output_path = 0; + options->plugin_path = 0; + options->include_path = 0; + options->source_map_file = 0; + options->source_map_root = 0; + options->c_functions = 0; + options->c_importers = 0; + options->c_headers = 0; + options->plugin_paths = 0; + options->include_paths = 0; +} - // Push function for include paths (no manipulation support for now) - size_t ADDCALL sass_option_get_include_path_size(struct Sass_Options* options) +// helper function, not exported, only accessible locally +// sass_free_context is also defined in old sass_interface +static void sass_clear_context(struct Sass_Context* ctx) +{ + if (ctx == 0) return; + // release the allocated memory (mostly via sass_copy_c_string) + if (ctx->output_string) free(ctx->output_string); + if (ctx->source_map_string) free(ctx->source_map_string); + if (ctx->error_message) free(ctx->error_message); + if (ctx->error_text) free(ctx->error_text); + if (ctx->error_json) free(ctx->error_json); + if (ctx->error_file) free(ctx->error_file); + free_string_array(ctx->included_files); + // play safe and reset properties + ctx->output_string = 0; + ctx->source_map_string = 0; + ctx->error_message = 0; + ctx->error_text = 0; + ctx->error_json = 0; + ctx->error_file = 0; + ctx->included_files = 0; +// debug leaked memory +#ifdef DEBUG_SHARED_PTR + SharedObj::dumpMemLeaks(); +#endif + // now clear the options + sass_clear_options(ctx); +} + +void ADDCALL sass_delete_compiler(struct Sass_Compiler* compiler) +{ + if (compiler == 0) { - size_t len = 0; - struct string_list* cur = options->include_paths; - while (cur) { len ++; cur = cur->next; } - return len; + return; } + Context* cpp_ctx = compiler->cpp_ctx; + if (cpp_ctx) delete (cpp_ctx); + compiler->cpp_ctx = NULL; + compiler->c_ctx = NULL; + compiler->root = NULL; + free(compiler); +} + +void ADDCALL sass_delete_options(struct Sass_Options* options) +{ + sass_clear_options(options); + free(options); +} - // Push function for include paths (no manipulation support for now) - const char* ADDCALL sass_option_get_include_path(struct Sass_Options* options, size_t i) +// Deallocate all associated memory with file context +void ADDCALL sass_delete_file_context(struct Sass_File_Context* ctx) +{ + // clear the context and free it + sass_clear_context(ctx); + free(ctx); +} +// Deallocate all associated memory with data context +void ADDCALL sass_delete_data_context(struct Sass_Data_Context* ctx) +{ + // clean the source string if it was not passed + // we reset this member once we start parsing + if (ctx->source_string) free(ctx->source_string); + // clear the context and free it + sass_clear_context(ctx); + free(ctx); +} + +// Getters for sass context from specific implementations +struct Sass_Context* ADDCALL sass_file_context_get_context(struct Sass_File_Context* ctx) +{ + return ctx; +} +struct Sass_Context* ADDCALL sass_data_context_get_context(struct Sass_Data_Context* ctx) +{ + return ctx; +} + +// Getters for context options from Sass_Context +struct Sass_Options* ADDCALL sass_context_get_options(struct Sass_Context* ctx) +{ + return ctx; +} +struct Sass_Options* ADDCALL sass_file_context_get_options(struct Sass_File_Context* ctx) +{ + return ctx; +} +struct Sass_Options* ADDCALL sass_data_context_get_options(struct Sass_Data_Context* ctx) +{ + return ctx; +} +void ADDCALL sass_file_context_set_options(struct Sass_File_Context* ctx, struct Sass_Options* opt) +{ + copy_options(ctx, opt); +} +void ADDCALL sass_data_context_set_options(struct Sass_Data_Context* ctx, struct Sass_Options* opt) +{ + copy_options(ctx, opt); +} + +// Getters for Sass_Compiler options (get conected sass context) +enum Sass_Compiler_State ADDCALL sass_compiler_get_state(struct Sass_Compiler* compiler) +{ + return compiler->state; +} +struct Sass_Context* ADDCALL sass_compiler_get_context(struct Sass_Compiler* compiler) +{ + return compiler->c_ctx; +} +struct Sass_Options* ADDCALL sass_compiler_get_options(struct Sass_Compiler* compiler) +{ + return compiler->c_ctx; +} +// Getters for Sass_Compiler options (query import stack) +size_t ADDCALL sass_compiler_get_import_stack_size(struct Sass_Compiler* compiler) +{ + return compiler->cpp_ctx->import_stack.size(); +} +Sass_Import_Entry ADDCALL sass_compiler_get_last_import(struct Sass_Compiler* compiler) +{ + return compiler->cpp_ctx->import_stack.back(); +} +Sass_Import_Entry ADDCALL sass_compiler_get_import_entry(struct Sass_Compiler* compiler, size_t idx) +{ + return compiler->cpp_ctx->import_stack[idx]; +} +// Getters for Sass_Compiler options (query function stack) +size_t ADDCALL sass_compiler_get_callee_stack_size(struct Sass_Compiler* compiler) +{ + return compiler->cpp_ctx->callee_stack.size(); +} +Sass_Callee_Entry ADDCALL sass_compiler_get_last_callee(struct Sass_Compiler* compiler) +{ + return &compiler->cpp_ctx->callee_stack.back(); +} +Sass_Callee_Entry ADDCALL sass_compiler_get_callee_entry(struct Sass_Compiler* compiler, size_t idx) +{ + return &compiler->cpp_ctx->callee_stack[idx]; +} + +// Calculate the size of the stored null terminated array +size_t ADDCALL sass_context_get_included_files_size(struct Sass_Context* ctx) +{ + size_t l = 0; + auto i = ctx->included_files; + while (i && *i) { - struct string_list* cur = options->include_paths; - while (i) { i--; cur = cur->next; } - return cur->string; + ++i; + ++l; } + return l; +} - // Push function for plugin paths (no manipulation support for now) - void ADDCALL sass_option_push_plugin_path(struct Sass_Options* options, const char* path) +// Create getter and setters for options +IMPLEMENT_SASS_OPTION_ACCESSOR(int, precision); +IMPLEMENT_SASS_OPTION_ACCESSOR(enum Sass_Output_Style, output_style); +IMPLEMENT_SASS_OPTION_ACCESSOR(bool, source_comments); +IMPLEMENT_SASS_OPTION_ACCESSOR(bool, source_map_embed); +IMPLEMENT_SASS_OPTION_ACCESSOR(bool, source_map_contents); +IMPLEMENT_SASS_OPTION_ACCESSOR(bool, source_map_file_urls); +IMPLEMENT_SASS_OPTION_ACCESSOR(bool, omit_source_map_url); +IMPLEMENT_SASS_OPTION_ACCESSOR(bool, is_indented_syntax_src); +IMPLEMENT_SASS_OPTION_ACCESSOR(Sass_Function_List, c_functions); +IMPLEMENT_SASS_OPTION_ACCESSOR(Sass_Importer_List, c_importers); +IMPLEMENT_SASS_OPTION_ACCESSOR(Sass_Importer_List, c_headers); +IMPLEMENT_SASS_OPTION_ACCESSOR(const char*, indent); +IMPLEMENT_SASS_OPTION_ACCESSOR(const char*, linefeed); +IMPLEMENT_SASS_OPTION_STRING_SETTER(const char*, plugin_path, 0); +IMPLEMENT_SASS_OPTION_STRING_SETTER(const char*, include_path, 0); +IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, input_path, 0); +IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, output_path, 0); +IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, source_map_file, 0); +IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, source_map_root, 0); + +// Create getter and setters for context +IMPLEMENT_SASS_CONTEXT_GETTER(int, error_status); +IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_json); +IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_message); +IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_text); +IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_file); +IMPLEMENT_SASS_CONTEXT_GETTER(size_t, error_line); +IMPLEMENT_SASS_CONTEXT_GETTER(size_t, error_column); +IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_src); +IMPLEMENT_SASS_CONTEXT_GETTER(const char*, output_string); +IMPLEMENT_SASS_CONTEXT_GETTER(const char*, source_map_string); +IMPLEMENT_SASS_CONTEXT_GETTER(char**, included_files); + +// Take ownership of memory (value on context is set to 0) +IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_json); +IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_message); +IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_text); +IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_file); +IMPLEMENT_SASS_CONTEXT_TAKER(char*, output_string); +IMPLEMENT_SASS_CONTEXT_TAKER(char*, source_map_string); +IMPLEMENT_SASS_CONTEXT_TAKER(char**, included_files); + +// Push function for include paths (no manipulation support for now) +void ADDCALL sass_option_push_include_path(struct Sass_Options* options, const char* path) +{ + + struct string_list* include_path = (struct string_list*)calloc(1, sizeof(struct string_list)); + if (include_path == 0) return; + include_path->string = path ? sass_copy_c_string(path) : 0; + struct string_list* last = options->include_paths; + if (!options->include_paths) + { + options->include_paths = include_path; + } + else { + while (last->next) + last = last->next; + last->next = include_path; + } +} - struct string_list* plugin_path = (struct string_list*) calloc(1, sizeof(struct string_list)); - if (plugin_path == 0) return; - plugin_path->string = path ? sass_copy_c_string(path) : 0; - struct string_list* last = options->plugin_paths; - if (!options->plugin_paths) { - options->plugin_paths = plugin_path; - } else { - while (last->next) - last = last->next; - last->next = plugin_path; - } +// Push function for include paths (no manipulation support for now) +size_t ADDCALL sass_option_get_include_path_size(struct Sass_Options* options) +{ + size_t len = 0; + struct string_list* cur = options->include_paths; + while (cur) + { + len++; + cur = cur->next; + } + return len; +} +// Push function for include paths (no manipulation support for now) +const char* ADDCALL sass_option_get_include_path(struct Sass_Options* options, size_t i) +{ + struct string_list* cur = options->include_paths; + while (i) + { + i--; + cur = cur->next; } + return cur->string; +} +// Push function for plugin paths (no manipulation support for now) +void ADDCALL sass_option_push_plugin_path(struct Sass_Options* options, const char* path) +{ + + struct string_list* plugin_path = (struct string_list*)calloc(1, sizeof(struct string_list)); + if (plugin_path == 0) return; + plugin_path->string = path ? sass_copy_c_string(path) : 0; + struct string_list* last = options->plugin_paths; + if (!options->plugin_paths) + { + options->plugin_paths = plugin_path; + } + else + { + while (last->next) + last = last->next; + last->next = plugin_path; + } +} } diff --git a/src/sass_context.hpp b/src/sass_context.hpp index 8ae1fb12cd..b6dd33d53e 100644 --- a/src/sass_context.hpp +++ b/src/sass_context.hpp @@ -6,7 +6,8 @@ #include "ast_fwd_decl.hpp" // sass config options structure -struct Sass_Options : Sass_Output_Options { +struct Sass_Options : Sass_Output_Options +{ // embed sourceMappingUrl as data uri bool source_map_embed; @@ -64,7 +65,6 @@ struct Sass_Options : Sass_Output_Options { // List of custom headers Sass_Importer_List c_headers; - }; @@ -94,28 +94,28 @@ struct Sass_Context : Sass_Options // report imported files char** included_files; - }; // struct for file compilation -struct Sass_File_Context : Sass_Context { +struct Sass_File_Context : Sass_Context +{ // no additional fields required // input_path is already on options - }; // struct for data compilation -struct Sass_Data_Context : Sass_Context { +struct Sass_Data_Context : Sass_Context +{ // provided source string char* source_string; char* srcmap_string; - }; // link c and cpp context -struct Sass_Compiler { +struct Sass_Compiler +{ // progress status Sass_Compiler_State state; // original c context diff --git a/src/sass_functions.cpp b/src/sass_functions.cpp index f7beda35f4..8805c00e85 100644 --- a/src/sass_functions.cpp +++ b/src/sass_functions.cpp @@ -7,201 +7,294 @@ #include "sass_functions.hpp" extern "C" { - using namespace Sass; +using namespace Sass; - Sass_Function_List ADDCALL sass_make_function_list(size_t length) - { - return (Sass_Function_List) calloc(length + 1, sizeof(Sass_Function_Entry)); - } +Sass_Function_List ADDCALL sass_make_function_list(size_t length) +{ + return (Sass_Function_List)calloc(length + 1, sizeof(Sass_Function_Entry)); +} - Sass_Function_Entry ADDCALL sass_make_function(const char* signature, Sass_Function_Fn function, void* cookie) - { - Sass_Function_Entry cb = (Sass_Function_Entry) calloc(1, sizeof(Sass_Function)); - if (cb == 0) return 0; - cb->signature = strdup(signature); - cb->function = function; - cb->cookie = cookie; - return cb; - } +Sass_Function_Entry ADDCALL sass_make_function(const char* signature, Sass_Function_Fn function, void* cookie) +{ + Sass_Function_Entry cb = (Sass_Function_Entry)calloc(1, sizeof(Sass_Function)); + if (cb == 0) return 0; + cb->signature = strdup(signature); + cb->function = function; + cb->cookie = cookie; + return cb; +} - void ADDCALL sass_delete_function(Sass_Function_Entry entry) - { - free(entry->signature); - free(entry); - } +void ADDCALL sass_delete_function(Sass_Function_Entry entry) +{ + free(entry->signature); + free(entry); +} - // Deallocator for the allocated memory - void ADDCALL sass_delete_function_list(Sass_Function_List list) +// Deallocator for the allocated memory +void ADDCALL sass_delete_function_list(Sass_Function_List list) +{ + Sass_Function_List it = list; + if (list == 0) return; + while (*list) { - Sass_Function_List it = list; - if (list == 0) return; - while(*list) { - sass_delete_function(*list); - ++list; - } - free(it); + sass_delete_function(*list); + ++list; } + free(it); +} - // Setters and getters for callbacks on function lists - Sass_Function_Entry ADDCALL sass_function_get_list_entry(Sass_Function_List list, size_t pos) { return list[pos]; } - void sass_function_set_list_entry(Sass_Function_List list, size_t pos, Sass_Function_Entry cb) { list[pos] = cb; } +// Setters and getters for callbacks on function lists +Sass_Function_Entry ADDCALL sass_function_get_list_entry(Sass_Function_List list, size_t pos) +{ + return list[pos]; +} +void sass_function_set_list_entry(Sass_Function_List list, size_t pos, Sass_Function_Entry cb) +{ + list[pos] = cb; +} - const char* ADDCALL sass_function_get_signature(Sass_Function_Entry cb) { return cb->signature; } - Sass_Function_Fn ADDCALL sass_function_get_function(Sass_Function_Entry cb) { return cb->function; } - void* ADDCALL sass_function_get_cookie(Sass_Function_Entry cb) { return cb->cookie; } +const char* ADDCALL sass_function_get_signature(Sass_Function_Entry cb) +{ + return cb->signature; +} +Sass_Function_Fn ADDCALL sass_function_get_function(Sass_Function_Entry cb) +{ + return cb->function; +} +void* ADDCALL sass_function_get_cookie(Sass_Function_Entry cb) +{ + return cb->cookie; +} - Sass_Importer_Entry ADDCALL sass_make_importer(Sass_Importer_Fn importer, double priority, void* cookie) - { - Sass_Importer_Entry cb = (Sass_Importer_Entry) calloc(1, sizeof(Sass_Importer)); - if (cb == 0) return 0; - cb->importer = importer; - cb->priority = priority; - cb->cookie = cookie; - return cb; - } +Sass_Importer_Entry ADDCALL sass_make_importer(Sass_Importer_Fn importer, double priority, void* cookie) +{ + Sass_Importer_Entry cb = (Sass_Importer_Entry)calloc(1, sizeof(Sass_Importer)); + if (cb == 0) return 0; + cb->importer = importer; + cb->priority = priority; + cb->cookie = cookie; + return cb; +} - Sass_Importer_Fn ADDCALL sass_importer_get_function(Sass_Importer_Entry cb) { return cb->importer; } - double ADDCALL sass_importer_get_priority (Sass_Importer_Entry cb) { return cb->priority; } - void* ADDCALL sass_importer_get_cookie(Sass_Importer_Entry cb) { return cb->cookie; } +Sass_Importer_Fn ADDCALL sass_importer_get_function(Sass_Importer_Entry cb) +{ + return cb->importer; +} +double ADDCALL sass_importer_get_priority(Sass_Importer_Entry cb) +{ + return cb->priority; +} +void* ADDCALL sass_importer_get_cookie(Sass_Importer_Entry cb) +{ + return cb->cookie; +} - // Just in case we have some stray import structs - void ADDCALL sass_delete_importer (Sass_Importer_Entry cb) - { - free(cb); - } +// Just in case we have some stray import structs +void ADDCALL sass_delete_importer(Sass_Importer_Entry cb) +{ + free(cb); +} - // Creator for sass custom importer function list - Sass_Importer_List ADDCALL sass_make_importer_list(size_t length) - { - return (Sass_Importer_List) calloc(length + 1, sizeof(Sass_Importer_Entry)); - } +// Creator for sass custom importer function list +Sass_Importer_List ADDCALL sass_make_importer_list(size_t length) +{ + return (Sass_Importer_List)calloc(length + 1, sizeof(Sass_Importer_Entry)); +} - // Deallocator for the allocated memory - void ADDCALL sass_delete_importer_list(Sass_Importer_List list) +// Deallocator for the allocated memory +void ADDCALL sass_delete_importer_list(Sass_Importer_List list) +{ + Sass_Importer_List it = list; + if (list == 0) return; + while (*list) { - Sass_Importer_List it = list; - if (list == 0) return; - while(*list) { - sass_delete_importer(*list); - ++list; - } - free(it); + sass_delete_importer(*list); + ++list; } + free(it); +} - Sass_Importer_Entry ADDCALL sass_importer_get_list_entry(Sass_Importer_List list, size_t idx) { return list[idx]; } - void ADDCALL sass_importer_set_list_entry(Sass_Importer_List list, size_t idx, Sass_Importer_Entry cb) { list[idx] = cb; } +Sass_Importer_Entry ADDCALL sass_importer_get_list_entry(Sass_Importer_List list, size_t idx) +{ + return list[idx]; +} +void ADDCALL sass_importer_set_list_entry(Sass_Importer_List list, size_t idx, Sass_Importer_Entry cb) +{ + list[idx] = cb; +} - // Creator for sass custom importer return argument list - Sass_Import_List ADDCALL sass_make_import_list(size_t length) - { - return (Sass_Import**) calloc(length + 1, sizeof(Sass_Import*)); - } +// Creator for sass custom importer return argument list +Sass_Import_List ADDCALL sass_make_import_list(size_t length) +{ + return (Sass_Import**)calloc(length + 1, sizeof(Sass_Import*)); +} - // Creator for a single import entry returned by the custom importer inside the list - // We take ownership of the memory for source and srcmap (freed when context is destroyd) - Sass_Import_Entry ADDCALL sass_make_import(const char* imp_path, const char* abs_path, char* source, char* srcmap) - { - Sass_Import* v = (Sass_Import*) calloc(1, sizeof(Sass_Import)); - if (v == 0) return 0; - v->imp_path = imp_path ? sass_copy_c_string(imp_path) : 0; - v->abs_path = abs_path ? sass_copy_c_string(abs_path) : 0; - v->source = source; - v->srcmap = srcmap; - v->error = 0; - v->line = -1; - v->column = -1; - return v; - } +// Creator for a single import entry returned by the custom importer inside the list +// We take ownership of the memory for source and srcmap (freed when context is destroyd) +Sass_Import_Entry ADDCALL sass_make_import(const char* imp_path, const char* abs_path, char* source, char* srcmap) +{ + Sass_Import* v = (Sass_Import*)calloc(1, sizeof(Sass_Import)); + if (v == 0) return 0; + v->imp_path = imp_path ? sass_copy_c_string(imp_path) : 0; + v->abs_path = abs_path ? sass_copy_c_string(abs_path) : 0; + v->source = source; + v->srcmap = srcmap; + v->error = 0; + v->line = -1; + v->column = -1; + return v; +} - // Older style, but somehow still valid - keep around or deprecate? - Sass_Import_Entry ADDCALL sass_make_import_entry(const char* path, char* source, char* srcmap) - { - return sass_make_import(path, path, source, srcmap); - } +// Older style, but somehow still valid - keep around or deprecate? +Sass_Import_Entry ADDCALL sass_make_import_entry(const char* path, char* source, char* srcmap) +{ + return sass_make_import(path, path, source, srcmap); +} - // Upgrade a normal import entry to throw an error (original path can be re-used by error reporting) - Sass_Import_Entry ADDCALL sass_import_set_error(Sass_Import_Entry import, const char* error, size_t line, size_t col) - { - if (import == 0) return 0; - if (import->error) free(import->error); - import->error = error ? sass_copy_c_string(error) : 0; - import->line = line ? line : -1; - import->column = col ? col : -1; - return import; - } +// Upgrade a normal import entry to throw an error (original path can be re-used by error reporting) +Sass_Import_Entry ADDCALL sass_import_set_error(Sass_Import_Entry import, const char* error, size_t line, size_t col) +{ + if (import == 0) return 0; + if (import->error) free(import->error); + import->error = error ? sass_copy_c_string(error) : 0; + import->line = line ? line : -1; + import->column = col ? col : -1; + return import; +} - // Setters and getters for entries on the import list - void ADDCALL sass_import_set_list_entry(Sass_Import_List list, size_t idx, Sass_Import_Entry entry) { list[idx] = entry; } - Sass_Import_Entry ADDCALL sass_import_get_list_entry(Sass_Import_List list, size_t idx) { return list[idx]; } +// Setters and getters for entries on the import list +void ADDCALL sass_import_set_list_entry(Sass_Import_List list, size_t idx, Sass_Import_Entry entry) +{ + list[idx] = entry; +} +Sass_Import_Entry ADDCALL sass_import_get_list_entry(Sass_Import_List list, size_t idx) +{ + return list[idx]; +} - // Deallocator for the allocated memory - void ADDCALL sass_delete_import_list(Sass_Import_List list) +// Deallocator for the allocated memory +void ADDCALL sass_delete_import_list(Sass_Import_List list) +{ + Sass_Import_List it = list; + if (list == 0) return; + while (*list) { - Sass_Import_List it = list; - if (list == 0) return; - while(*list) { - sass_delete_import(*list); - ++list; - } - free(it); + sass_delete_import(*list); + ++list; } + free(it); +} - // Just in case we have some stray import structs - void ADDCALL sass_delete_import(Sass_Import_Entry import) - { - free(import->imp_path); - free(import->abs_path); - free(import->source); - free(import->srcmap); - free(import->error); - free(import); - } +// Just in case we have some stray import structs +void ADDCALL sass_delete_import(Sass_Import_Entry import) +{ + free(import->imp_path); + free(import->abs_path); + free(import->source); + free(import->srcmap); + free(import->error); + free(import); +} - // Getter for callee entry - const char* ADDCALL sass_callee_get_name(Sass_Callee_Entry entry) { return entry->name; } - const char* ADDCALL sass_callee_get_path(Sass_Callee_Entry entry) { return entry->path; } - size_t ADDCALL sass_callee_get_line(Sass_Callee_Entry entry) { return entry->line; } - size_t ADDCALL sass_callee_get_column(Sass_Callee_Entry entry) { return entry->column; } - enum Sass_Callee_Type ADDCALL sass_callee_get_type(Sass_Callee_Entry entry) { return entry->type; } - Sass_Env_Frame ADDCALL sass_callee_get_env (Sass_Callee_Entry entry) { return &entry->env; } - - // Getters and Setters for environments (lexical, local and global) - union Sass_Value* ADDCALL sass_env_get_lexical (Sass_Env_Frame env, const char* name) { - Expression_Ptr ex = Cast((*env->frame)[name]); - return ex != NULL ? ast_node_to_sass_value(ex) : NULL; - } - void ADDCALL sass_env_set_lexical (Sass_Env_Frame env, const char* name, union Sass_Value* val) { - (*env->frame)[name] = sass_value_to_ast_node(val); - } - union Sass_Value* ADDCALL sass_env_get_local (Sass_Env_Frame env, const char* name) { - Expression_Ptr ex = Cast(env->frame->get_local(name)); - return ex != NULL ? ast_node_to_sass_value(ex) : NULL; - } - void ADDCALL sass_env_set_local (Sass_Env_Frame env, const char* name, union Sass_Value* val) { - env->frame->set_local(name, sass_value_to_ast_node(val)); - } - union Sass_Value* ADDCALL sass_env_get_global (Sass_Env_Frame env, const char* name) { - Expression_Ptr ex = Cast(env->frame->get_global(name)); - return ex != NULL ? ast_node_to_sass_value(ex) : NULL; - } - void ADDCALL sass_env_set_global (Sass_Env_Frame env, const char* name, union Sass_Value* val) { - env->frame->set_global(name, sass_value_to_ast_node(val)); - } +// Getter for callee entry +const char* ADDCALL sass_callee_get_name(Sass_Callee_Entry entry) +{ + return entry->name; +} +const char* ADDCALL sass_callee_get_path(Sass_Callee_Entry entry) +{ + return entry->path; +} +size_t ADDCALL sass_callee_get_line(Sass_Callee_Entry entry) +{ + return entry->line; +} +size_t ADDCALL sass_callee_get_column(Sass_Callee_Entry entry) +{ + return entry->column; +} +enum Sass_Callee_Type ADDCALL sass_callee_get_type(Sass_Callee_Entry entry) +{ + return entry->type; +} +Sass_Env_Frame ADDCALL sass_callee_get_env(Sass_Callee_Entry entry) +{ + return &entry->env; +} - // Getter for import entry - const char* ADDCALL sass_import_get_imp_path(Sass_Import_Entry entry) { return entry->imp_path; } - const char* ADDCALL sass_import_get_abs_path(Sass_Import_Entry entry) { return entry->abs_path; } - const char* ADDCALL sass_import_get_source(Sass_Import_Entry entry) { return entry->source; } - const char* ADDCALL sass_import_get_srcmap(Sass_Import_Entry entry) { return entry->srcmap; } +// Getters and Setters for environments (lexical, local and global) +union Sass_Value* ADDCALL sass_env_get_lexical(Sass_Env_Frame env, const char* name) +{ + Expression_Ptr ex = Cast((*env->frame)[name]); + return ex != NULL ? ast_node_to_sass_value(ex) : NULL; +} +void ADDCALL sass_env_set_lexical(Sass_Env_Frame env, const char* name, union Sass_Value* val) +{ + (*env->frame)[name] = sass_value_to_ast_node(val); +} +union Sass_Value* ADDCALL sass_env_get_local(Sass_Env_Frame env, const char* name) +{ + Expression_Ptr ex = Cast(env->frame->get_local(name)); + return ex != NULL ? ast_node_to_sass_value(ex) : NULL; +} +void ADDCALL sass_env_set_local(Sass_Env_Frame env, const char* name, union Sass_Value* val) +{ + env->frame->set_local(name, sass_value_to_ast_node(val)); +} +union Sass_Value* ADDCALL sass_env_get_global(Sass_Env_Frame env, const char* name) +{ + Expression_Ptr ex = Cast(env->frame->get_global(name)); + return ex != NULL ? ast_node_to_sass_value(ex) : NULL; +} +void ADDCALL sass_env_set_global(Sass_Env_Frame env, const char* name, union Sass_Value* val) +{ + env->frame->set_global(name, sass_value_to_ast_node(val)); +} - // Getter for import error entry - size_t ADDCALL sass_import_get_error_line(Sass_Import_Entry entry) { return entry->line; } - size_t ADDCALL sass_import_get_error_column(Sass_Import_Entry entry) { return entry->column; } - const char* ADDCALL sass_import_get_error_message(Sass_Import_Entry entry) { return entry->error; } +// Getter for import entry +const char* ADDCALL sass_import_get_imp_path(Sass_Import_Entry entry) +{ + return entry->imp_path; +} +const char* ADDCALL sass_import_get_abs_path(Sass_Import_Entry entry) +{ + return entry->abs_path; +} +const char* ADDCALL sass_import_get_source(Sass_Import_Entry entry) +{ + return entry->source; +} +const char* ADDCALL sass_import_get_srcmap(Sass_Import_Entry entry) +{ + return entry->srcmap; +} - // Explicit functions to take ownership of the memory - // Resets our own property since we do not know if it is still alive - char* ADDCALL sass_import_take_source(Sass_Import_Entry entry) { char* ptr = entry->source; entry->source = 0; return ptr; } - char* ADDCALL sass_import_take_srcmap(Sass_Import_Entry entry) { char* ptr = entry->srcmap; entry->srcmap = 0; return ptr; } +// Getter for import error entry +size_t ADDCALL sass_import_get_error_line(Sass_Import_Entry entry) +{ + return entry->line; +} +size_t ADDCALL sass_import_get_error_column(Sass_Import_Entry entry) +{ + return entry->column; +} +const char* ADDCALL sass_import_get_error_message(Sass_Import_Entry entry) +{ + return entry->error; +} +// Explicit functions to take ownership of the memory +// Resets our own property since we do not know if it is still alive +char* ADDCALL sass_import_take_source(Sass_Import_Entry entry) +{ + char* ptr = entry->source; + entry->source = 0; + return ptr; +} +char* ADDCALL sass_import_take_srcmap(Sass_Import_Entry entry) +{ + char* ptr = entry->srcmap; + entry->srcmap = 0; + return ptr; +} } diff --git a/src/sass_functions.hpp b/src/sass_functions.hpp index 3b646d67ed..a7a73bc413 100644 --- a/src/sass_functions.hpp +++ b/src/sass_functions.hpp @@ -6,16 +6,18 @@ #include "functions.hpp" // Struct to hold custom function callback -struct Sass_Function { - char* signature; +struct Sass_Function +{ + char* signature; Sass_Function_Fn function; - void* cookie; + void* cookie; }; // External import entry -struct Sass_Import { +struct Sass_Import +{ char* imp_path; // path as found in the import statement - char *abs_path; // path after importer has resolved it + char* abs_path; // path after importer has resolved it char* source; char* srcmap; // error handling @@ -25,13 +27,15 @@ struct Sass_Import { }; // External environments -struct Sass_Env { +struct Sass_Env +{ // links to parent frames Sass::Env* frame; }; // External call entry -struct Sass_Callee { +struct Sass_Callee +{ const char* name; const char* path; size_t line; @@ -41,10 +45,11 @@ struct Sass_Callee { }; // Struct to hold importer callback -struct Sass_Importer { +struct Sass_Importer +{ Sass_Importer_Fn importer; - double priority; - void* cookie; + double priority; + void* cookie; }; #endif \ No newline at end of file diff --git a/src/sass_util.cpp b/src/sass_util.cpp index 3aef2bc728..dd99894c2e 100644 --- a/src/sass_util.cpp +++ b/src/sass_util.cpp @@ -1,7 +1,8 @@ #include "sass.hpp" #include "node.hpp" -namespace Sass { +namespace Sass +{ /* @@ -23,7 +24,8 @@ namespace Sass { should be able to drop it into ruby 3.2.19 and get the same results from ruby sass. def paths(arrs) - // I changed the inject and maps to an iterative approach to make it easier to implement in C++ + // I changed the inject and maps to an iterative approach to make it easier to implement in + C++ loopStart = [[]] for arr in arrs do @@ -37,25 +39,30 @@ namespace Sass { end end */ - Node paths(const Node& arrs) { + Node paths(const Node& arrs) + { Node loopStart = Node::createCollection(); loopStart.collection()->push_back(Node::createCollection()); for (NodeDeque::iterator arrsIter = arrs.collection()->begin(), arrsEndIter = arrs.collection()->end(); - arrsIter != arrsEndIter; ++arrsIter) { + arrsIter != arrsEndIter; ++arrsIter) + { Node& arr = *arrsIter; Node permutations = Node::createCollection(); for (NodeDeque::iterator arrIter = arr.collection()->begin(), arrIterEnd = arr.collection()->end(); - arrIter != arrIterEnd; ++arrIter) { + arrIter != arrIterEnd; ++arrIter) + { Node& e = *arrIter; - for (NodeDeque::iterator loopStartIter = loopStart.collection()->begin(), loopStartIterEnd = loopStart.collection()->end(); - loopStartIter != loopStartIterEnd; ++loopStartIter) { + for (NodeDeque::iterator loopStartIter = loopStart.collection()->begin(), + loopStartIterEnd = loopStart.collection()->end(); + loopStartIter != loopStartIterEnd; ++loopStartIter) + { Node& path = *loopStartIter; @@ -108,8 +115,10 @@ namespace Sass { return flattened end */ - Node flatten(Node& arr, int n) { - if (n != -1 && n == 0) { + Node flatten(Node& arr, int n) + { + if (n != -1 && n == 0) + { return arr; } @@ -117,30 +126,36 @@ namespace Sass { if (arr.got_line_feed) flattened.got_line_feed = true; for (NodeDeque::iterator iter = arr.collection()->begin(), iterEnd = arr.collection()->end(); - iter != iterEnd; iter++) { - Node& e = *iter; + iter != iterEnd; iter++) + { + Node& e = *iter; // e has the lf set - if (e.isCollection()) { + if (e.isCollection()) + { - // e.collection().got_line_feed = e.got_line_feed; - Node recurseFlattened = flatten(e, n - 1); + // e.collection().got_line_feed = e.got_line_feed; + Node recurseFlattened = flatten(e, n - 1); - if(e.got_line_feed) { - flattened.got_line_feed = e.got_line_feed; - recurseFlattened.got_line_feed = e.got_line_feed; - } + if (e.got_line_feed) + { + flattened.got_line_feed = e.got_line_feed; + recurseFlattened.got_line_feed = e.got_line_feed; + } - for(auto i : (*recurseFlattened.collection())) { - if (recurseFlattened.got_line_feed) { + for (auto i : (*recurseFlattened.collection())) + { + if (recurseFlattened.got_line_feed) + { i.got_line_feed = true; } flattened.collection()->push_back(i); - } - - } else { - flattened.collection()->push_back(e); + } + } + else + { + flattened.collection()->push_back(e); } } diff --git a/src/sass_util.hpp b/src/sass_util.hpp index 816da5fd80..334446193b 100644 --- a/src/sass_util.hpp +++ b/src/sass_util.hpp @@ -5,9 +5,8 @@ #include "node.hpp" #include "debug.hpp" -namespace Sass { - - +namespace Sass +{ /* @@ -16,7 +15,8 @@ namespace Sass { /* - # Return a Node collection of all possible paths through the given Node collection of Node collections. + # Return a Node collection of all possible paths through the given Node collection of Node + collections. # # @param arrs [NodeCollection>] # @return [NodeCollection>] @@ -32,15 +32,19 @@ namespace Sass { /* - This class is a default implementation of a Node comparator that can be passed to the lcs function below. + This class is a default implementation of a Node comparator that can be passed to the lcs function + below. It uses operator== for equality comparision. It then returns one if the Nodes are equal. */ - class DefaultLcsComparator { - public: - bool operator()(const Node& one, const Node& two, Node& out) const { + class DefaultLcsComparator + { + public: + bool operator()(const Node& one, const Node& two, Node& out) const + { // TODO: Is this the correct C++ interpretation? // block ||= proc {|a, b| a == b && a} - if (one == two) { + if (one == two) + { out = one; return true; } @@ -50,20 +54,23 @@ namespace Sass { }; - typedef std::vector > LCSTable; + typedef std::vector> LCSTable; /* This is the equivalent of ruby's Sass::Util.lcs_backtrace. # Computes a single longest common subsequence for arrays x and y. - # Algorithm from http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Reading_out_an_LCS + # Algorithm from + http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Reading_out_an_LCS */ - template - Node lcs_backtrace(const LCSTable& c, const Node& x, const Node& y, int i, int j, const ComparatorType& comparator) { + template + Node lcs_backtrace(const LCSTable& c, const Node& x, const Node& y, int i, int j, const ComparatorType& comparator) + { DEBUG_PRINTLN(LCS, "LCSBACK: X=" << x << " Y=" << y << " I=" << i << " J=" << j) - if (i == 0 || j == 0) { + if (i == 0 || j == 0) + { DEBUG_PRINTLN(LCS, "RETURNING EMPTY") return Node::createCollection(); } @@ -72,14 +79,16 @@ namespace Sass { NodeDeque& yChildren = *(y.collection()); Node compareOut = Node::createNil(); - if (comparator(xChildren[i], yChildren[j], compareOut)) { + if (comparator(xChildren[i], yChildren[j], compareOut)) + { DEBUG_PRINTLN(LCS, "RETURNING AFTER ELEM COMPARE") Node result = lcs_backtrace(c, x, y, i - 1, j - 1, comparator); result.collection()->push_back(compareOut); return result; } - if (c[i][j - 1] > c[i - 1][j]) { + if (c[i][j - 1] > c[i - 1][j]) + { DEBUG_PRINTLN(LCS, "RETURNING AFTER TABLE COMPARE") return lcs_backtrace(c, x, y, i, j - 1, comparator); } @@ -93,10 +102,12 @@ namespace Sass { This is the equivalent of ruby's Sass::Util.lcs_table. # Calculates the memoization table for the Least Common Subsequence algorithm. - # Algorithm from http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Computing_the_length_of_the_LCS + # Algorithm from + http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Computing_the_length_of_the_LCS */ - template - void lcs_table(const Node& x, const Node& y, const ComparatorType& comparator, LCSTable& out) { + template + void lcs_table(const Node& x, const Node& y, const ComparatorType& comparator, LCSTable& out) + { DEBUG_PRINTLN(LCS, "LCSTABLE: X=" << x << " Y=" << y) NodeDeque& xChildren = *(x.collection()); @@ -108,13 +119,18 @@ namespace Sass { // x.size.times {|i| c[i][0] = 0} // y.size.times {|j| c[0][j] = 0} - for (size_t i = 1; i < xChildren.size(); i++) { - for (size_t j = 1; j < yChildren.size(); j++) { + for (size_t i = 1; i < xChildren.size(); i++) + { + for (size_t j = 1; j < yChildren.size(); j++) + { Node compareOut = Node::createNil(); - if (comparator(xChildren[i], yChildren[j], compareOut)) { + if (comparator(xChildren[i], yChildren[j], compareOut)) + { c[i][j] = c[i - 1][j - 1] + 1; - } else { + } + else + { c[i][j] = std::max(c[i][j - 1], c[i - 1][j]); } } @@ -138,8 +154,8 @@ namespace Sass { http://en.wikipedia.org/wiki/Longest_common_subsequence_problem */ - template - Node lcs(Node& x, Node& y, const ComparatorType& comparator) { + template Node lcs(Node& x, Node& y, const ComparatorType& comparator) + { DEBUG_PRINTLN(LCS, "LCS: X=" << x << " Y=" << y) Node newX = Node::createCollection(); @@ -153,7 +169,8 @@ namespace Sass { LCSTable table; lcs_table(newX, newY, comparator, table); - return lcs_backtrace(table, newX, newY, static_cast(newX.collection()->size()) - 1, static_cast(newY.collection()->size()) - 1, comparator); + return lcs_backtrace(table, newX, newY, static_cast(newX.collection()->size()) - 1, + static_cast(newY.collection()->size()) - 1, comparator); } @@ -216,41 +233,49 @@ namespace Sass { end */ - template - void group_by_to_a(std::vector& enumeration, KeyFunctorType& keyFunc, std::vector > >& arr /*out*/) { + template + void group_by_to_a(std::vector& enumeration, + KeyFunctorType& keyFunc, + std::vector>>& arr /*out*/) + { std::map order; - std::map > grouped; + std::map> grouped; - for (typename std::vector::iterator enumIter = enumeration.begin(), enumIterEnd = enumeration.end(); enumIter != enumIterEnd; enumIter++) { + for (typename std::vector::iterator enumIter = enumeration.begin(), + enumIterEnd = enumeration.end(); + enumIter != enumIterEnd; enumIter++) + { EnumType& e = *enumIter; KeyType key = keyFunc(e); - if (grouped.find(key->hash()) == grouped.end()) { + if (grouped.find(key->hash()) == grouped.end()) + { order.insert(std::make_pair((unsigned int)order.size(), key)); std::vector newCollection; newCollection.push_back(e); grouped.insert(std::make_pair(key->hash(), newCollection)); - } else { + } + else + { std::vector& collection = grouped.at(key->hash()); collection.push_back(e); } } - for (unsigned int index = 0; index < order.size(); index++) { + for (unsigned int index = 0; index < order.size(); index++) + { KeyType& key = order.at(index); std::vector& values = grouped.at(key->hash()); - std::pair > grouping = std::make_pair(key, values); + std::pair> grouping = std::make_pair(key, values); arr.push_back(grouping); } } - - } #endif diff --git a/src/sass_values.cpp b/src/sass_values.cpp index 25abd49ba1..3dad6ea0e9 100644 --- a/src/sass_values.cpp +++ b/src/sass_values.cpp @@ -8,349 +8,576 @@ #include "sass_values.hpp" extern "C" { - using namespace Sass; - - // Return the sass tag for a generic sass value - enum Sass_Tag ADDCALL sass_value_get_tag(const union Sass_Value* v) { return v->unknown.tag; } - - // Check value for specified type - bool ADDCALL sass_value_is_null(const union Sass_Value* v) { return v->unknown.tag == SASS_NULL; } - bool ADDCALL sass_value_is_number(const union Sass_Value* v) { return v->unknown.tag == SASS_NUMBER; } - bool ADDCALL sass_value_is_string(const union Sass_Value* v) { return v->unknown.tag == SASS_STRING; } - bool ADDCALL sass_value_is_boolean(const union Sass_Value* v) { return v->unknown.tag == SASS_BOOLEAN; } - bool ADDCALL sass_value_is_color(const union Sass_Value* v) { return v->unknown.tag == SASS_COLOR; } - bool ADDCALL sass_value_is_list(const union Sass_Value* v) { return v->unknown.tag == SASS_LIST; } - bool ADDCALL sass_value_is_map(const union Sass_Value* v) { return v->unknown.tag == SASS_MAP; } - bool ADDCALL sass_value_is_error(const union Sass_Value* v) { return v->unknown.tag == SASS_ERROR; } - bool ADDCALL sass_value_is_warning(const union Sass_Value* v) { return v->unknown.tag == SASS_WARNING; } - - // Getters and setters for Sass_Number - double ADDCALL sass_number_get_value(const union Sass_Value* v) { return v->number.value; } - void ADDCALL sass_number_set_value(union Sass_Value* v, double value) { v->number.value = value; } - const char* ADDCALL sass_number_get_unit(const union Sass_Value* v) { return v->number.unit; } - void ADDCALL sass_number_set_unit(union Sass_Value* v, char* unit) { v->number.unit = unit; } - - // Getters and setters for Sass_String - const char* ADDCALL sass_string_get_value(const union Sass_Value* v) { return v->string.value; } - void ADDCALL sass_string_set_value(union Sass_Value* v, char* value) { v->string.value = value; } - bool ADDCALL sass_string_is_quoted(const union Sass_Value* v) { return v->string.quoted; } - void ADDCALL sass_string_set_quoted(union Sass_Value* v, bool quoted) { v->string.quoted = quoted; } - - // Getters and setters for Sass_Boolean - bool ADDCALL sass_boolean_get_value(const union Sass_Value* v) { return v->boolean.value; } - void ADDCALL sass_boolean_set_value(union Sass_Value* v, bool value) { v->boolean.value = value; } - - // Getters and setters for Sass_Color - double ADDCALL sass_color_get_r(const union Sass_Value* v) { return v->color.r; } - void ADDCALL sass_color_set_r(union Sass_Value* v, double r) { v->color.r = r; } - double ADDCALL sass_color_get_g(const union Sass_Value* v) { return v->color.g; } - void ADDCALL sass_color_set_g(union Sass_Value* v, double g) { v->color.g = g; } - double ADDCALL sass_color_get_b(const union Sass_Value* v) { return v->color.b; } - void ADDCALL sass_color_set_b(union Sass_Value* v, double b) { v->color.b = b; } - double ADDCALL sass_color_get_a(const union Sass_Value* v) { return v->color.a; } - void ADDCALL sass_color_set_a(union Sass_Value* v, double a) { v->color.a = a; } - - // Getters and setters for Sass_List - size_t ADDCALL sass_list_get_length(const union Sass_Value* v) { return v->list.length; } - enum Sass_Separator ADDCALL sass_list_get_separator(const union Sass_Value* v) { return v->list.separator; } - void ADDCALL sass_list_set_separator(union Sass_Value* v, enum Sass_Separator separator) { v->list.separator = separator; } - bool ADDCALL sass_list_get_is_bracketed(const union Sass_Value* v) { return v->list.is_bracketed; } - void ADDCALL sass_list_set_is_bracketed(union Sass_Value* v, bool is_bracketed) { v->list.is_bracketed = is_bracketed; } - // Getters and setters for Sass_List values - union Sass_Value* ADDCALL sass_list_get_value(const union Sass_Value* v, size_t i) { return v->list.values[i]; } - void ADDCALL sass_list_set_value(union Sass_Value* v, size_t i, union Sass_Value* value) { v->list.values[i] = value; } - - // Getters and setters for Sass_Map - size_t ADDCALL sass_map_get_length(const union Sass_Value* v) { return v->map.length; } - // Getters and setters for Sass_List keys and values - union Sass_Value* ADDCALL sass_map_get_key(const union Sass_Value* v, size_t i) { return v->map.pairs[i].key; } - union Sass_Value* ADDCALL sass_map_get_value(const union Sass_Value* v, size_t i) { return v->map.pairs[i].value; } - void ADDCALL sass_map_set_key(union Sass_Value* v, size_t i, union Sass_Value* key) { v->map.pairs[i].key = key; } - void ADDCALL sass_map_set_value(union Sass_Value* v, size_t i, union Sass_Value* val) { v->map.pairs[i].value = val; } - - // Getters and setters for Sass_Error - char* ADDCALL sass_error_get_message(const union Sass_Value* v) { return v->error.message; }; - void ADDCALL sass_error_set_message(union Sass_Value* v, char* msg) { v->error.message = msg; }; - - // Getters and setters for Sass_Warning - char* ADDCALL sass_warning_get_message(const union Sass_Value* v) { return v->warning.message; }; - void ADDCALL sass_warning_set_message(union Sass_Value* v, char* msg) { v->warning.message = msg; }; - - // Creator functions for all value types - - union Sass_Value* ADDCALL sass_make_boolean(bool val) - { - union Sass_Value* v = (Sass_Value*) calloc(1, sizeof(Sass_Value)); - if (v == 0) return 0; - v->boolean.tag = SASS_BOOLEAN; - v->boolean.value = val; - return v; - } - - union Sass_Value* ADDCALL sass_make_number(double val, const char* unit) - { - union Sass_Value* v = (Sass_Value*) calloc(1, sizeof(Sass_Value)); - if (v == 0) return 0; - v->number.tag = SASS_NUMBER; - v->number.value = val; - v->number.unit = unit ? sass_copy_c_string(unit) : 0; - if (v->number.unit == 0) { free(v); return 0; } - return v; - } - - union Sass_Value* ADDCALL sass_make_color(double r, double g, double b, double a) - { - union Sass_Value* v = (Sass_Value*) calloc(1, sizeof(Sass_Value)); - if (v == 0) return 0; - v->color.tag = SASS_COLOR; - v->color.r = r; - v->color.g = g; - v->color.b = b; - v->color.a = a; - return v; - } - - union Sass_Value* ADDCALL sass_make_string(const char* val) - { - union Sass_Value* v = (Sass_Value*) calloc(1, sizeof(Sass_Value)); - if (v == 0) return 0; - v->string.quoted = false; - v->string.tag = SASS_STRING; - v->string.value = val ? sass_copy_c_string(val) : 0; - if (v->string.value == 0) { free(v); return 0; } - return v; - } - - union Sass_Value* ADDCALL sass_make_qstring(const char* val) - { - union Sass_Value* v = (Sass_Value*) calloc(1, sizeof(Sass_Value)); - if (v == 0) return 0; - v->string.quoted = true; - v->string.tag = SASS_STRING; - v->string.value = val ? sass_copy_c_string(val) : 0; - if (v->string.value == 0) { free(v); return 0; } - return v; - } - - union Sass_Value* ADDCALL sass_make_list(size_t len, enum Sass_Separator sep, bool is_bracketed) - { - union Sass_Value* v = (Sass_Value*) calloc(1, sizeof(Sass_Value)); - if (v == 0) return 0; - v->list.tag = SASS_LIST; - v->list.length = len; - v->list.separator = sep; - v->list.is_bracketed = is_bracketed; - v->list.values = (union Sass_Value**) calloc(len, sizeof(union Sass_Value*)); - if (v->list.values == 0) { free(v); return 0; } - return v; - } - - union Sass_Value* ADDCALL sass_make_map(size_t len) - { - union Sass_Value* v = (Sass_Value*) calloc(1, sizeof(Sass_Value)); - if (v == 0) return 0; - v->map.tag = SASS_MAP; - v->map.length = len; - v->map.pairs = (struct Sass_MapPair*) calloc(len, sizeof(struct Sass_MapPair)); - if (v->map.pairs == 0) { free(v); return 0; } - return v; - } - - union Sass_Value* ADDCALL sass_make_null(void) - { - union Sass_Value* v = (Sass_Value*) calloc(1, sizeof(Sass_Value)); - if (v == 0) return 0; - v->null.tag = SASS_NULL; - return v; - } - - union Sass_Value* ADDCALL sass_make_error(const char* msg) - { - union Sass_Value* v = (Sass_Value*) calloc(1, sizeof(Sass_Value)); - if (v == 0) return 0; - v->error.tag = SASS_ERROR; - v->error.message = msg ? sass_copy_c_string(msg) : 0; - if (v->error.message == 0) { free(v); return 0; } - return v; - } - - union Sass_Value* ADDCALL sass_make_warning(const char* msg) - { - union Sass_Value* v = (Sass_Value*) calloc(1, sizeof(Sass_Value)); - if (v == 0) return 0; - v->warning.tag = SASS_WARNING; - v->warning.message = msg ? sass_copy_c_string(msg) : 0; - if (v->warning.message == 0) { free(v); return 0; } - return v; - } - - // will free all associated sass values - void ADDCALL sass_delete_value(union Sass_Value* val) { - - size_t i; - if (val == 0) return; - switch(val->unknown.tag) { - case SASS_NULL: { - } break; - case SASS_BOOLEAN: { - } break; - case SASS_NUMBER: { - free(val->number.unit); - } break; - case SASS_COLOR: { - } break; - case SASS_STRING: { - free(val->string.value); - } break; - case SASS_LIST: { - for (i=0; ilist.length; i++) { - sass_delete_value(val->list.values[i]); - } - free(val->list.values); - } break; - case SASS_MAP: { - for (i=0; imap.length; i++) { - sass_delete_value(val->map.pairs[i].key); - sass_delete_value(val->map.pairs[i].value); - } - free(val->map.pairs); - } break; - case SASS_ERROR: { - free(val->error.message); - } break; - case SASS_WARNING: { - free(val->error.message); - } break; - default: break; - } +using namespace Sass; - free(val); +// Return the sass tag for a generic sass value +enum Sass_Tag ADDCALL sass_value_get_tag(const union Sass_Value* v) +{ + return v->unknown.tag; +} - } +// Check value for specified type +bool ADDCALL sass_value_is_null(const union Sass_Value* v) +{ + return v->unknown.tag == SASS_NULL; +} +bool ADDCALL sass_value_is_number(const union Sass_Value* v) +{ + return v->unknown.tag == SASS_NUMBER; +} +bool ADDCALL sass_value_is_string(const union Sass_Value* v) +{ + return v->unknown.tag == SASS_STRING; +} +bool ADDCALL sass_value_is_boolean(const union Sass_Value* v) +{ + return v->unknown.tag == SASS_BOOLEAN; +} +bool ADDCALL sass_value_is_color(const union Sass_Value* v) +{ + return v->unknown.tag == SASS_COLOR; +} +bool ADDCALL sass_value_is_list(const union Sass_Value* v) +{ + return v->unknown.tag == SASS_LIST; +} +bool ADDCALL sass_value_is_map(const union Sass_Value* v) +{ + return v->unknown.tag == SASS_MAP; +} +bool ADDCALL sass_value_is_error(const union Sass_Value* v) +{ + return v->unknown.tag == SASS_ERROR; +} +bool ADDCALL sass_value_is_warning(const union Sass_Value* v) +{ + return v->unknown.tag == SASS_WARNING; +} - // Make a deep cloned copy of the given sass value - union Sass_Value* ADDCALL sass_clone_value (const union Sass_Value* val) - { - - size_t i; - if (val == 0) return 0; - switch(val->unknown.tag) { - case SASS_NULL: { - return sass_make_null(); - } - case SASS_BOOLEAN: { - return sass_make_boolean(val->boolean.value); - } - case SASS_NUMBER: { - return sass_make_number(val->number.value, val->number.unit); - } - case SASS_COLOR: { - return sass_make_color(val->color.r, val->color.g, val->color.b, val->color.a); - } - case SASS_STRING: { - return sass_string_is_quoted(val) ? sass_make_qstring(val->string.value) : sass_make_string(val->string.value); - } - case SASS_LIST: { - union Sass_Value* list = sass_make_list(val->list.length, val->list.separator, val->list.is_bracketed); - for (i = 0; i < list->list.length; i++) { - list->list.values[i] = sass_clone_value(val->list.values[i]); - } - return list; - } - case SASS_MAP: { - union Sass_Value* map = sass_make_map(val->map.length); - for (i = 0; i < val->map.length; i++) { - map->map.pairs[i].key = sass_clone_value(val->map.pairs[i].key); - map->map.pairs[i].value = sass_clone_value(val->map.pairs[i].value); - } - return map; - } - case SASS_ERROR: { - return sass_make_error(val->error.message); - } - case SASS_WARNING: { - return sass_make_warning(val->warning.message); - } - default: break; - } +// Getters and setters for Sass_Number +double ADDCALL sass_number_get_value(const union Sass_Value* v) +{ + return v->number.value; +} +void ADDCALL sass_number_set_value(union Sass_Value* v, double value) +{ + v->number.value = value; +} +const char* ADDCALL sass_number_get_unit(const union Sass_Value* v) +{ + return v->number.unit; +} +void ADDCALL sass_number_set_unit(union Sass_Value* v, char* unit) +{ + v->number.unit = unit; +} + +// Getters and setters for Sass_String +const char* ADDCALL sass_string_get_value(const union Sass_Value* v) +{ + return v->string.value; +} +void ADDCALL sass_string_set_value(union Sass_Value* v, char* value) +{ + v->string.value = value; +} +bool ADDCALL sass_string_is_quoted(const union Sass_Value* v) +{ + return v->string.quoted; +} +void ADDCALL sass_string_set_quoted(union Sass_Value* v, bool quoted) +{ + v->string.quoted = quoted; +} + +// Getters and setters for Sass_Boolean +bool ADDCALL sass_boolean_get_value(const union Sass_Value* v) +{ + return v->boolean.value; +} +void ADDCALL sass_boolean_set_value(union Sass_Value* v, bool value) +{ + v->boolean.value = value; +} + +// Getters and setters for Sass_Color +double ADDCALL sass_color_get_r(const union Sass_Value* v) +{ + return v->color.r; +} +void ADDCALL sass_color_set_r(union Sass_Value* v, double r) +{ + v->color.r = r; +} +double ADDCALL sass_color_get_g(const union Sass_Value* v) +{ + return v->color.g; +} +void ADDCALL sass_color_set_g(union Sass_Value* v, double g) +{ + v->color.g = g; +} +double ADDCALL sass_color_get_b(const union Sass_Value* v) +{ + return v->color.b; +} +void ADDCALL sass_color_set_b(union Sass_Value* v, double b) +{ + v->color.b = b; +} +double ADDCALL sass_color_get_a(const union Sass_Value* v) +{ + return v->color.a; +} +void ADDCALL sass_color_set_a(union Sass_Value* v, double a) +{ + v->color.a = a; +} + +// Getters and setters for Sass_List +size_t ADDCALL sass_list_get_length(const union Sass_Value* v) +{ + return v->list.length; +} +enum Sass_Separator ADDCALL sass_list_get_separator(const union Sass_Value* v) +{ + return v->list.separator; +} +void ADDCALL sass_list_set_separator(union Sass_Value* v, enum Sass_Separator separator) +{ + v->list.separator = separator; +} +bool ADDCALL sass_list_get_is_bracketed(const union Sass_Value* v) +{ + return v->list.is_bracketed; +} +void ADDCALL sass_list_set_is_bracketed(union Sass_Value* v, bool is_bracketed) +{ + v->list.is_bracketed = is_bracketed; +} +// Getters and setters for Sass_List values +union Sass_Value* ADDCALL sass_list_get_value(const union Sass_Value* v, size_t i) +{ + return v->list.values[i]; +} +void ADDCALL sass_list_set_value(union Sass_Value* v, size_t i, union Sass_Value* value) +{ + v->list.values[i] = value; +} + +// Getters and setters for Sass_Map +size_t ADDCALL sass_map_get_length(const union Sass_Value* v) +{ + return v->map.length; +} +// Getters and setters for Sass_List keys and values +union Sass_Value* ADDCALL sass_map_get_key(const union Sass_Value* v, size_t i) +{ + return v->map.pairs[i].key; +} +union Sass_Value* ADDCALL sass_map_get_value(const union Sass_Value* v, size_t i) +{ + return v->map.pairs[i].value; +} +void ADDCALL sass_map_set_key(union Sass_Value* v, size_t i, union Sass_Value* key) +{ + v->map.pairs[i].key = key; +} +void ADDCALL sass_map_set_value(union Sass_Value* v, size_t i, union Sass_Value* val) +{ + v->map.pairs[i].value = val; +} + +// Getters and setters for Sass_Error +char* ADDCALL sass_error_get_message(const union Sass_Value* v) +{ + return v->error.message; +}; +void ADDCALL sass_error_set_message(union Sass_Value* v, char* msg) +{ + v->error.message = msg; +}; + +// Getters and setters for Sass_Warning +char* ADDCALL sass_warning_get_message(const union Sass_Value* v) +{ + return v->warning.message; +}; +void ADDCALL sass_warning_set_message(union Sass_Value* v, char* msg) +{ + v->warning.message = msg; +}; + +// Creator functions for all value types + +union Sass_Value* ADDCALL sass_make_boolean(bool val) +{ + union Sass_Value* v = (Sass_Value*)calloc(1, sizeof(Sass_Value)); + if (v == 0) return 0; + v->boolean.tag = SASS_BOOLEAN; + v->boolean.value = val; + return v; +} + +union Sass_Value* ADDCALL sass_make_number(double val, const char* unit) +{ + union Sass_Value* v = (Sass_Value*)calloc(1, sizeof(Sass_Value)); + if (v == 0) return 0; + v->number.tag = SASS_NUMBER; + v->number.value = val; + v->number.unit = unit ? sass_copy_c_string(unit) : 0; + if (v->number.unit == 0) + { + free(v); + return 0; + } + return v; +} + +union Sass_Value* ADDCALL sass_make_color(double r, double g, double b, double a) +{ + union Sass_Value* v = (Sass_Value*)calloc(1, sizeof(Sass_Value)); + if (v == 0) return 0; + v->color.tag = SASS_COLOR; + v->color.r = r; + v->color.g = g; + v->color.b = b; + v->color.a = a; + return v; +} + +union Sass_Value* ADDCALL sass_make_string(const char* val) +{ + union Sass_Value* v = (Sass_Value*)calloc(1, sizeof(Sass_Value)); + if (v == 0) return 0; + v->string.quoted = false; + v->string.tag = SASS_STRING; + v->string.value = val ? sass_copy_c_string(val) : 0; + if (v->string.value == 0) + { + free(v); + return 0; + } + return v; +} + +union Sass_Value* ADDCALL sass_make_qstring(const char* val) +{ + union Sass_Value* v = (Sass_Value*)calloc(1, sizeof(Sass_Value)); + if (v == 0) return 0; + v->string.quoted = true; + v->string.tag = SASS_STRING; + v->string.value = val ? sass_copy_c_string(val) : 0; + if (v->string.value == 0) + { + free(v); + return 0; + } + return v; +} + +union Sass_Value* ADDCALL sass_make_list(size_t len, enum Sass_Separator sep, bool is_bracketed) +{ + union Sass_Value* v = (Sass_Value*)calloc(1, sizeof(Sass_Value)); + if (v == 0) return 0; + v->list.tag = SASS_LIST; + v->list.length = len; + v->list.separator = sep; + v->list.is_bracketed = is_bracketed; + v->list.values = (union Sass_Value**)calloc(len, sizeof(union Sass_Value*)); + if (v->list.values == 0) + { + free(v); + return 0; + } + return v; +} + +union Sass_Value* ADDCALL sass_make_map(size_t len) +{ + union Sass_Value* v = (Sass_Value*)calloc(1, sizeof(Sass_Value)); + if (v == 0) return 0; + v->map.tag = SASS_MAP; + v->map.length = len; + v->map.pairs = (struct Sass_MapPair*)calloc(len, sizeof(struct Sass_MapPair)); + if (v->map.pairs == 0) + { + free(v); + return 0; + } + return v; +} + +union Sass_Value* ADDCALL sass_make_null(void) +{ + union Sass_Value* v = (Sass_Value*)calloc(1, sizeof(Sass_Value)); + if (v == 0) return 0; + v->null.tag = SASS_NULL; + return v; +} + +union Sass_Value* ADDCALL sass_make_error(const char* msg) +{ + union Sass_Value* v = (Sass_Value*)calloc(1, sizeof(Sass_Value)); + if (v == 0) return 0; + v->error.tag = SASS_ERROR; + v->error.message = msg ? sass_copy_c_string(msg) : 0; + if (v->error.message == 0) + { + free(v); + return 0; + } + return v; +} +union Sass_Value* ADDCALL sass_make_warning(const char* msg) +{ + union Sass_Value* v = (Sass_Value*)calloc(1, sizeof(Sass_Value)); + if (v == 0) return 0; + v->warning.tag = SASS_WARNING; + v->warning.message = msg ? sass_copy_c_string(msg) : 0; + if (v->warning.message == 0) + { + free(v); return 0; + } + return v; +} +// will free all associated sass values +void ADDCALL sass_delete_value(union Sass_Value* val) +{ + + size_t i; + if (val == 0) return; + switch (val->unknown.tag) + { + case SASS_NULL: + { + } + break; + case SASS_BOOLEAN: + { + } + break; + case SASS_NUMBER: + { + free(val->number.unit); + } + break; + case SASS_COLOR: + { + } + break; + case SASS_STRING: + { + free(val->string.value); + } + break; + case SASS_LIST: + { + for (i = 0; i < val->list.length; i++) + { + sass_delete_value(val->list.values[i]); + } + free(val->list.values); + } + break; + case SASS_MAP: + { + for (i = 0; i < val->map.length; i++) + { + sass_delete_value(val->map.pairs[i].key); + sass_delete_value(val->map.pairs[i].value); + } + free(val->map.pairs); + } + break; + case SASS_ERROR: + { + free(val->error.message); + } + break; + case SASS_WARNING: + { + free(val->error.message); + } + break; + default: + break; } - union Sass_Value* ADDCALL sass_value_stringify (const union Sass_Value* v, bool compressed, int precision) - { - Value_Obj val = sass_value_to_ast_node(v); - Sass_Inspect_Options options(compressed ? COMPRESSED : NESTED, precision); - std::string str(val->to_string(options)); - return sass_make_qstring(str.c_str()); - } - - union Sass_Value* ADDCALL sass_value_op (enum Sass_OP op, const union Sass_Value* a, const union Sass_Value* b) - { - - Sass::Value_Ptr rv; - - try { - - Value_Obj lhs = sass_value_to_ast_node(a); - Value_Obj rhs = sass_value_to_ast_node(b); - struct Sass_Inspect_Options options(NESTED, 5); - - // see if it's a relational expression - switch(op) { - case Sass_OP::EQ: return sass_make_boolean(Eval::eq(lhs, rhs)); - case Sass_OP::NEQ: return sass_make_boolean(!Eval::eq(lhs, rhs)); - case Sass_OP::GT: return sass_make_boolean(!Eval::lt(lhs, rhs, "gt") && !Eval::eq(lhs, rhs)); - case Sass_OP::GTE: return sass_make_boolean(!Eval::lt(lhs, rhs, "gte")); - case Sass_OP::LT: return sass_make_boolean(Eval::lt(lhs, rhs, "lt")); - case Sass_OP::LTE: return sass_make_boolean(Eval::lt(lhs, rhs, "lte") || Eval::eq(lhs, rhs)); - case Sass_OP::AND: return ast_node_to_sass_value(lhs->is_false() ? lhs : rhs); - case Sass_OP::OR: return ast_node_to_sass_value(lhs->is_false() ? rhs : lhs); - default: break; - } - - if (sass_value_is_number(a) && sass_value_is_number(b)) { - Number_Ptr_Const l_n = Cast(lhs); - Number_Ptr_Const r_n = Cast(rhs); - rv = Eval::op_numbers(op, *l_n, *r_n, options, l_n->pstate()); - } - else if (sass_value_is_number(a) && sass_value_is_color(a)) { - Number_Ptr_Const l_n = Cast(lhs); - Color_Ptr_Const r_c = Cast(rhs); - rv = Eval::op_number_color(op, *l_n, *r_c, options, l_n->pstate()); - } - else if (sass_value_is_color(a) && sass_value_is_number(b)) { - Color_Ptr_Const l_c = Cast(lhs); - Number_Ptr_Const r_n = Cast(rhs); - rv = Eval::op_color_number(op, *l_c, *r_n, options, l_c->pstate()); - } - else if (sass_value_is_color(a) && sass_value_is_color(b)) { - Color_Ptr_Const l_c = Cast(lhs); - Color_Ptr_Const r_c = Cast(rhs); - rv = Eval::op_colors(op, *l_c, *r_c, options, l_c->pstate()); - } - else /* convert other stuff to string and apply operation */ { - Value_Ptr l_v = Cast(lhs); - Value_Ptr r_v = Cast(rhs); - rv = Eval::op_strings(op, *l_v, *r_v, options, l_v->pstate()); - } - - // ToDo: maybe we should should return null value? - if (!rv) return sass_make_error("invalid return value"); - - // convert result back to ast node - return ast_node_to_sass_value(rv); + free(val); +} +// Make a deep cloned copy of the given sass value +union Sass_Value* ADDCALL sass_clone_value(const union Sass_Value* val) +{ + + size_t i; + if (val == 0) return 0; + switch (val->unknown.tag) + { + case SASS_NULL: + { + return sass_make_null(); + } + case SASS_BOOLEAN: + { + return sass_make_boolean(val->boolean.value); + } + case SASS_NUMBER: + { + return sass_make_number(val->number.value, val->number.unit); + } + case SASS_COLOR: + { + return sass_make_color(val->color.r, val->color.g, val->color.b, val->color.a); + } + case SASS_STRING: + { + return sass_string_is_quoted(val) ? sass_make_qstring(val->string.value) : + sass_make_string(val->string.value); + } + case SASS_LIST: + { + union Sass_Value* list = sass_make_list(val->list.length, val->list.separator, val->list.is_bracketed); + for (i = 0; i < list->list.length; i++) + { + list->list.values[i] = sass_clone_value(val->list.values[i]); + } + return list; + } + case SASS_MAP: + { + union Sass_Value* map = sass_make_map(val->map.length); + for (i = 0; i < val->map.length; i++) + { + map->map.pairs[i].key = sass_clone_value(val->map.pairs[i].key); + map->map.pairs[i].value = sass_clone_value(val->map.pairs[i].value); + } + return map; + } + case SASS_ERROR: + { + return sass_make_error(val->error.message); + } + case SASS_WARNING: + { + return sass_make_warning(val->warning.message); + } + default: + break; + } + + return 0; +} + +union Sass_Value* ADDCALL sass_value_stringify(const union Sass_Value* v, bool compressed, int precision) +{ + Value_Obj val = sass_value_to_ast_node(v); + Sass_Inspect_Options options(compressed ? COMPRESSED : NESTED, precision); + std::string str(val->to_string(options)); + return sass_make_qstring(str.c_str()); +} + +union Sass_Value* ADDCALL sass_value_op(enum Sass_OP op, const union Sass_Value* a, const union Sass_Value* b) +{ + + Sass::Value_Ptr rv; + + try + { + + Value_Obj lhs = sass_value_to_ast_node(a); + Value_Obj rhs = sass_value_to_ast_node(b); + struct Sass_Inspect_Options options(NESTED, 5); + + // see if it's a relational expression + switch (op) + { + case Sass_OP::EQ: + return sass_make_boolean(Eval::eq(lhs, rhs)); + case Sass_OP::NEQ: + return sass_make_boolean(!Eval::eq(lhs, rhs)); + case Sass_OP::GT: + return sass_make_boolean(!Eval::lt(lhs, rhs, "gt") && !Eval::eq(lhs, rhs)); + case Sass_OP::GTE: + return sass_make_boolean(!Eval::lt(lhs, rhs, "gte")); + case Sass_OP::LT: + return sass_make_boolean(Eval::lt(lhs, rhs, "lt")); + case Sass_OP::LTE: + return sass_make_boolean(Eval::lt(lhs, rhs, "lte") || Eval::eq(lhs, rhs)); + case Sass_OP::AND: + return ast_node_to_sass_value(lhs->is_false() ? lhs : rhs); + case Sass_OP::OR: + return ast_node_to_sass_value(lhs->is_false() ? rhs : lhs); + default: + break; } - // simply pass the error message back to the caller for now - catch (Exception::InvalidSass& e) { return sass_make_error(e.what()); } - catch (std::bad_alloc&) { return sass_make_error("memory exhausted"); } - catch (std::exception& e) { return sass_make_error(e.what()); } - catch (std::string& e) { return sass_make_error(e.c_str()); } - catch (const char* e) { return sass_make_error(e); } - catch (...) { return sass_make_error("unknown"); } + if (sass_value_is_number(a) && sass_value_is_number(b)) + { + Number_Ptr_Const l_n = Cast(lhs); + Number_Ptr_Const r_n = Cast(rhs); + rv = Eval::op_numbers(op, *l_n, *r_n, options, l_n->pstate()); + } + else if (sass_value_is_number(a) && sass_value_is_color(a)) + { + Number_Ptr_Const l_n = Cast(lhs); + Color_Ptr_Const r_c = Cast(rhs); + rv = Eval::op_number_color(op, *l_n, *r_c, options, l_n->pstate()); + } + else if (sass_value_is_color(a) && sass_value_is_number(b)) + { + Color_Ptr_Const l_c = Cast(lhs); + Number_Ptr_Const r_n = Cast(rhs); + rv = Eval::op_color_number(op, *l_c, *r_n, options, l_c->pstate()); + } + else if (sass_value_is_color(a) && sass_value_is_color(b)) + { + Color_Ptr_Const l_c = Cast(lhs); + Color_Ptr_Const r_c = Cast(rhs); + rv = Eval::op_colors(op, *l_c, *r_c, options, l_c->pstate()); + } + else /* convert other stuff to string and apply operation */ + { + Value_Ptr l_v = Cast(lhs); + Value_Ptr r_v = Cast(rhs); + rv = Eval::op_strings(op, *l_v, *r_v, options, l_v->pstate()); + } + + // ToDo: maybe we should should return null value? + if (!rv) return sass_make_error("invalid return value"); + + // convert result back to ast node + return ast_node_to_sass_value(rv); } + // simply pass the error message back to the caller for now + catch (Exception::InvalidSass& e) + { + return sass_make_error(e.what()); + } + catch (std::bad_alloc&) + { + return sass_make_error("memory exhausted"); + } + catch (std::exception& e) + { + return sass_make_error(e.what()); + } + catch (std::string& e) + { + return sass_make_error(e.c_str()); + } + catch (const char* e) + { + return sass_make_error(e); + } + catch (...) + { + return sass_make_error("unknown"); + } +} } diff --git a/src/sass_values.hpp b/src/sass_values.hpp index 9aa5cdb337..0d869407b0 100644 --- a/src/sass_values.hpp +++ b/src/sass_values.hpp @@ -3,78 +3,89 @@ #include "sass.h" -struct Sass_Unknown { +struct Sass_Unknown +{ enum Sass_Tag tag; }; -struct Sass_Boolean { +struct Sass_Boolean +{ enum Sass_Tag tag; - bool value; + bool value; }; -struct Sass_Number { +struct Sass_Number +{ enum Sass_Tag tag; - double value; - char* unit; + double value; + char* unit; }; -struct Sass_Color { +struct Sass_Color +{ enum Sass_Tag tag; - double r; - double g; - double b; - double a; + double r; + double g; + double b; + double a; }; -struct Sass_String { +struct Sass_String +{ enum Sass_Tag tag; - bool quoted; - char* value; + bool quoted; + char* value; }; -struct Sass_List { - enum Sass_Tag tag; +struct Sass_List +{ + enum Sass_Tag tag; enum Sass_Separator separator; - bool is_bracketed; - size_t length; + bool is_bracketed; + size_t length; // null terminated "array" - union Sass_Value** values; + union Sass_Value** values; }; -struct Sass_Map { - enum Sass_Tag tag; - size_t length; +struct Sass_Map +{ + enum Sass_Tag tag; + size_t length; struct Sass_MapPair* pairs; }; -struct Sass_Null { +struct Sass_Null +{ enum Sass_Tag tag; }; -struct Sass_Error { +struct Sass_Error +{ enum Sass_Tag tag; - char* message; + char* message; }; -struct Sass_Warning { +struct Sass_Warning +{ enum Sass_Tag tag; - char* message; + char* message; }; union Sass_Value { struct Sass_Unknown unknown; struct Sass_Boolean boolean; - struct Sass_Number number; - struct Sass_Color color; - struct Sass_String string; - struct Sass_List list; - struct Sass_Map map; - struct Sass_Null null; - struct Sass_Error error; + struct Sass_Number number; + struct Sass_Color color; + struct Sass_String string; + struct Sass_List list; + struct Sass_Map map; + struct Sass_Null null; + struct Sass_Error error; struct Sass_Warning warning; }; -struct Sass_MapPair { +struct Sass_MapPair +{ union Sass_Value* key; union Sass_Value* value; }; diff --git a/src/source_map.cpp b/src/source_map.cpp index 62e6b00191..94f1a6311a 100644 --- a/src/source_map.cpp +++ b/src/source_map.cpp @@ -10,11 +10,17 @@ #include "position.hpp" #include "source_map.hpp" -namespace Sass { - SourceMap::SourceMap() : current_position(0, 0, 0), file("stdin") { } - SourceMap::SourceMap(const std::string& file) : current_position(0, 0, 0), file(file) { } +namespace Sass +{ + SourceMap::SourceMap() : current_position(0, 0, 0), file("stdin") + { + } + SourceMap::SourceMap(const std::string& file) : current_position(0, 0, 0), file(file) + { + } - std::string SourceMap::render_srcmap(Context &ctx) { + std::string SourceMap::render_srcmap(Context& ctx) + { const bool include_sources = ctx.c_options.source_map_contents; const std::vector links = ctx.srcmap_links; @@ -24,63 +30,72 @@ namespace Sass { json_append_member(json_srcmap, "version", json_mknumber(3)); - const char *file_name = file.c_str(); - JsonNode *json_file_name = json_mkstring(file_name); + const char* file_name = file.c_str(); + JsonNode* json_file_name = json_mkstring(file_name); json_append_member(json_srcmap, "file", json_file_name); // pass-through sourceRoot option - if (!ctx.source_map_root.empty()) { + if (!ctx.source_map_root.empty()) + { JsonNode* root = json_mkstring(ctx.source_map_root.c_str()); json_append_member(json_srcmap, "sourceRoot", root); } - JsonNode *json_sources = json_mkarray(); - for (size_t i = 0; i < source_index.size(); ++i) { + JsonNode* json_sources = json_mkarray(); + for (size_t i = 0; i < source_index.size(); ++i) + { std::string source(links[source_index[i]]); - if (ctx.c_options.source_map_file_urls) { + if (ctx.c_options.source_map_file_urls) + { source = File::rel2abs(source); // check for windows abs path - if (source[0] == '/') { + if (source[0] == '/') + { // ends up with three slashes source = "file://" + source; - } else { + } + else + { // needs an additional slash source = "file:///" + source; } } const char* source_name = source.c_str(); - JsonNode *json_source_name = json_mkstring(source_name); + JsonNode* json_source_name = json_mkstring(source_name); json_append_element(json_sources, json_source_name); } json_append_member(json_srcmap, "sources", json_sources); - if (include_sources && source_index.size()) { - JsonNode *json_contents = json_mkarray(); - for (size_t i = 0; i < source_index.size(); ++i) { + if (include_sources && source_index.size()) + { + JsonNode* json_contents = json_mkarray(); + for (size_t i = 0; i < source_index.size(); ++i) + { const Resource& resource(sources[source_index[i]]); - JsonNode *json_content = json_mkstring(resource.contents); + JsonNode* json_content = json_mkstring(resource.contents); json_append_element(json_contents, json_content); } json_append_member(json_srcmap, "sourcesContent", json_contents); } - JsonNode *json_names = json_mkarray(); + JsonNode* json_names = json_mkarray(); // so far we have no implementation for names // no problem as we do not alter any identifiers json_append_member(json_srcmap, "names", json_names); std::string mappings = serialize_mappings(); - JsonNode *json_mappings = json_mkstring(mappings.c_str()); + JsonNode* json_mappings = json_mkstring(mappings.c_str()); json_append_member(json_srcmap, "mappings", json_mappings); - char *str = json_stringify(json_srcmap, "\t"); + char* str = json_stringify(json_srcmap, "\t"); std::string result = std::string(str); free(str); json_delete(json_srcmap); return result; } - std::string SourceMap::serialize_mappings() { + std::string SourceMap::serialize_mappings() + { std::string result = ""; size_t previous_generated_line = 0; @@ -88,26 +103,31 @@ namespace Sass { size_t previous_original_line = 0; size_t previous_original_column = 0; size_t previous_original_file = 0; - for (size_t i = 0; i < mappings.size(); ++i) { + for (size_t i = 0; i < mappings.size(); ++i) + { const size_t generated_line = mappings[i].generated_position.line; const size_t generated_column = mappings[i].generated_position.column; const size_t original_line = mappings[i].original_position.line; const size_t original_column = mappings[i].original_position.column; const size_t original_file = mappings[i].original_position.file; - if (generated_line != previous_generated_line) { + if (generated_line != previous_generated_line) + { previous_generated_column = 0; - if (generated_line > previous_generated_line) { + if (generated_line > previous_generated_line) + { result += std::string(generated_line - previous_generated_line, ';'); previous_generated_line = generated_line; } } - else if (i > 0) { + else if (i > 0) + { result += ","; } // generated column - result += base64vlq.encode(static_cast(generated_column) - static_cast(previous_generated_column)); + result += + base64vlq.encode(static_cast(generated_column) - static_cast(previous_generated_column)); previous_generated_column = generated_column; // file result += base64vlq.encode(static_cast(original_file) - static_cast(previous_original_file)); @@ -116,7 +136,8 @@ namespace Sass { result += base64vlq.encode(static_cast(original_line) - static_cast(previous_original_line)); previous_original_line = original_line; // source column - result += base64vlq.encode(static_cast(original_column) - static_cast(previous_original_column)); + result += + base64vlq.encode(static_cast(original_column) - static_cast(previous_original_column)); previous_original_column = original_column; } @@ -126,12 +147,16 @@ namespace Sass { void SourceMap::prepend(const OutputBuffer& out) { Offset size(out.smap.current_position); - for (Mapping mapping : out.smap.mappings) { - if (mapping.generated_position.line > size.line) { + for (Mapping mapping : out.smap.mappings) + { + if (mapping.generated_position.line > size.line) + { throw(std::runtime_error("prepend sourcemap has illegal line")); } - if (mapping.generated_position.line == size.line) { - if (mapping.generated_position.column > size.column) { + if (mapping.generated_position.line == size.line) + { + if (mapping.generated_position.column > size.column) + { throw(std::runtime_error("prepend sourcemap has illegal column")); } } @@ -149,17 +174,21 @@ namespace Sass { void SourceMap::prepend(const Offset& offset) { - if (offset.line != 0 || offset.column != 0) { - for (Mapping& mapping : mappings) { + if (offset.line != 0 || offset.column != 0) + { + for (Mapping& mapping : mappings) + { // move stuff on the first old line - if (mapping.generated_position.line == 0) { + if (mapping.generated_position.line == 0) + { mapping.generated_position.column += offset.column; } // make place for the new lines mapping.generated_position.line += offset.line; } } - if (current_position.line == 0) { + if (current_position.line == 0) + { current_position.column += offset.column; } current_position.line += offset.line; @@ -180,16 +209,15 @@ namespace Sass { mappings.push_back(Mapping(node->pstate() + node->pstate().offset, current_position)); } - ParserState SourceMap::remap(const ParserState& pstate) { - for (size_t i = 0; i < mappings.size(); ++i) { - if ( - mappings[i].generated_position.file == pstate.file && - mappings[i].generated_position.line == pstate.line && - mappings[i].generated_position.column == pstate.column - ) return ParserState(pstate.path, pstate.src, mappings[i].original_position, pstate.offset); + ParserState SourceMap::remap(const ParserState& pstate) + { + for (size_t i = 0; i < mappings.size(); ++i) + { + if (mappings[i].generated_position.file == pstate.file && + mappings[i].generated_position.line == pstate.line && + mappings[i].generated_position.column == pstate.column) + return ParserState(pstate.path, pstate.src, mappings[i].original_position, pstate.offset); } return ParserState(pstate.path, pstate.src, Position(-1, -1, -1), Offset(0, 0)); - } - } diff --git a/src/source_map.hpp b/src/source_map.hpp index 07785640f9..d6a5a00190 100644 --- a/src/source_map.hpp +++ b/src/source_map.hpp @@ -12,14 +12,16 @@ #define VECTOR_PUSH(vec, ins) vec.insert(vec.end(), ins.begin(), ins.end()) #define VECTOR_UNSHIFT(vec, ins) vec.insert(vec.begin(), ins.begin(), ins.end()) -namespace Sass { +namespace Sass +{ class Context; class OutputBuffer; - class SourceMap { + class SourceMap + { - public: + public: std::vector source_index; SourceMap(); SourceMap(const std::string& file); @@ -31,32 +33,33 @@ namespace Sass { void add_open_mapping(const AST_Node_Ptr node); void add_close_mapping(const AST_Node_Ptr node); - std::string render_srcmap(Context &ctx); + std::string render_srcmap(Context& ctx); ParserState remap(const ParserState& pstate); - private: - + private: std::string serialize_mappings(); std::vector mappings; Position current_position; -public: + + public: std::string file; -private: + + private: Base64VLQ base64vlq; }; - class OutputBuffer { + class OutputBuffer + { public: - OutputBuffer(void) - : buffer(""), - smap() - { } + OutputBuffer(void) : buffer(""), smap() + { + } + public: - std::string buffer; - SourceMap smap; + std::string buffer; + SourceMap smap; }; - } #endif diff --git a/src/subset_map.cpp b/src/subset_map.cpp index 24513e4981..c576b5b6f0 100644 --- a/src/subset_map.cpp +++ b/src/subset_map.cpp @@ -2,7 +2,8 @@ #include "ast.hpp" #include "subset_map.hpp" -namespace Sass { +namespace Sass +{ void Subset_Map::put(const Compound_Selector_Obj& sel, const SubSetMapPair& value) { @@ -19,16 +20,21 @@ namespace Sass { { SimpleSelectorDict dict(sel->begin(), sel->end()); // XXX Set std::vector indices; - for (size_t i = 0, S = sel->length(); i < S; ++i) { - if (!hash_.count((*sel)[i])) { + for (size_t i = 0, S = sel->length(); i < S; ++i) + { + if (!hash_.count((*sel)[i])) + { continue; } - const std::vector >& subsets = hash_[(*sel)[i]]; - for (const std::pair& item : subsets) { + const std::vector>& subsets = hash_[(*sel)[i]]; + for (const std::pair& item : subsets) + { bool include = true; - for (const Simple_Selector_Obj& it : item.first->elements()) { + for (const Simple_Selector_Obj& it : item.first->elements()) + { auto found = dict.find(it); - if (found == dict.end()) { + if (found == dict.end()) + { include = false; break; } @@ -41,7 +47,8 @@ namespace Sass { indices.resize(distance(indices.begin(), indices_end)); std::vector results; - for (size_t i = 0, S = indices.size(); i < S; ++i) { + for (size_t i = 0, S = indices.size(); i < S; ++i) + { results.push_back(values_[indices[i]]); } return results; @@ -51,5 +58,4 @@ namespace Sass { { return get_kv(sel); } - } \ No newline at end of file diff --git a/src/subset_map.hpp b/src/subset_map.hpp index 5c091e685f..794d01d467 100644 --- a/src/subset_map.hpp +++ b/src/subset_map.hpp @@ -56,21 +56,33 @@ // return buffer.str(); // } -namespace Sass { +namespace Sass +{ - class Subset_Map { - private: + class Subset_Map + { + private: std::vector values_; - std::map >, OrderNodes > hash_; - public: + std::map>, OrderNodes> hash_; + + public: void put(const Compound_Selector_Obj& sel, const SubSetMapPair& value); std::vector get_kv(const Compound_Selector_Obj& s); std::vector get_v(const Compound_Selector_Obj& s); - bool empty() { return values_.empty(); } - void clear() { values_.clear(); hash_.clear(); } - const std::vector values(void) { return values_; } + bool empty() + { + return values_.empty(); + } + void clear() + { + values_.clear(); + hash_.clear(); + } + const std::vector values(void) + { + return values_; + } }; - } #endif diff --git a/src/to_c.cpp b/src/to_c.cpp index 8a6ea8d515..01a1544a05 100644 --- a/src/to_c.cpp +++ b/src/to_c.cpp @@ -2,42 +2,61 @@ #include "to_c.hpp" #include "ast.hpp" -namespace Sass { +namespace Sass +{ union Sass_Value* To_C::fallback_impl(AST_Node_Ptr n) - { return sass_make_error("unknown type for C-API"); } + { + return sass_make_error("unknown type for C-API"); + } union Sass_Value* To_C::operator()(Boolean_Ptr b) - { return sass_make_boolean(b->value()); } + { + return sass_make_boolean(b->value()); + } union Sass_Value* To_C::operator()(Number_Ptr n) - { return sass_make_number(n->value(), n->unit().c_str()); } + { + return sass_make_number(n->value(), n->unit().c_str()); + } union Sass_Value* To_C::operator()(Custom_Warning_Ptr w) - { return sass_make_warning(w->message().c_str()); } + { + return sass_make_warning(w->message().c_str()); + } union Sass_Value* To_C::operator()(Custom_Error_Ptr e) - { return sass_make_error(e->message().c_str()); } + { + return sass_make_error(e->message().c_str()); + } union Sass_Value* To_C::operator()(Color_Ptr c) - { return sass_make_color(c->r(), c->g(), c->b(), c->a()); } + { + return sass_make_color(c->r(), c->g(), c->b(), c->a()); + } union Sass_Value* To_C::operator()(String_Constant_Ptr s) { - if (s->quote_mark()) { + if (s->quote_mark()) + { return sass_make_qstring(s->value().c_str()); - } else { + } + else + { return sass_make_string(s->value().c_str()); } } union Sass_Value* To_C::operator()(String_Quoted_Ptr s) - { return sass_make_qstring(s->value().c_str()); } + { + return sass_make_qstring(s->value().c_str()); + } union Sass_Value* To_C::operator()(List_Ptr l) { union Sass_Value* v = sass_make_list(l->length(), l->separator(), l->is_bracketed()); - for (size_t i = 0, L = l->length(); i < L; ++i) { + for (size_t i = 0, L = l->length(); i < L; ++i) + { sass_list_set_value(v, i, (*l)[i]->perform(this)); } return v; @@ -47,7 +66,8 @@ namespace Sass { { union Sass_Value* v = sass_make_map(m->length()); int i = 0; - for (auto key : m->keys()) { + for (auto key : m->keys()) + { sass_map_set_key(v, i, key->perform(this)); sass_map_set_value(v, i, m->at(key)->perform(this)); i++; @@ -58,17 +78,21 @@ namespace Sass { union Sass_Value* To_C::operator()(Arguments_Ptr a) { union Sass_Value* v = sass_make_list(a->length(), SASS_COMMA, false); - for (size_t i = 0, L = a->length(); i < L; ++i) { + for (size_t i = 0, L = a->length(); i < L; ++i) + { sass_list_set_value(v, i, (*a)[i]->perform(this)); } return v; } union Sass_Value* To_C::operator()(Argument_Ptr a) - { return a->value()->perform(this); } + { + return a->value()->perform(this); + } // not strictly necessary because of the fallback union Sass_Value* To_C::operator()(Null_Ptr n) - { return sass_make_null(); } - + { + return sass_make_null(); + } }; diff --git a/src/to_c.hpp b/src/to_c.hpp index a5331e3bf1..e92af64f16 100644 --- a/src/to_c.hpp +++ b/src/to_c.hpp @@ -5,16 +5,21 @@ #include "operation.hpp" #include "sass/values.h" -namespace Sass { +namespace Sass +{ - class To_C : public Operation_CRTP { + class To_C : public Operation_CRTP + { // override this to define a catch-all union Sass_Value* fallback_impl(AST_Node_Ptr n); - public: - - To_C() { } - ~To_C() { } + public: + To_C() + { + } + ~To_C() + { + } union Sass_Value* operator()(Boolean_Ptr); union Sass_Value* operator()(Number_Ptr); @@ -31,9 +36,10 @@ namespace Sass { // dispatch to fallback implementation union Sass_Value* fallback(AST_Node_Ptr x) - { return fallback_impl(x); } + { + return fallback_impl(x); + } }; - } #endif diff --git a/src/to_value.cpp b/src/to_value.cpp index e81a3b9ee7..2a9ecc6d21 100644 --- a/src/to_value.cpp +++ b/src/to_value.cpp @@ -2,7 +2,8 @@ #include "ast.hpp" #include "to_value.hpp" -namespace Sass { +namespace Sass +{ Value_Ptr To_Value::fallback_impl(AST_Node_Ptr n) { @@ -56,12 +57,9 @@ namespace Sass { // List is a valid value Value_Ptr To_Value::operator()(List_Ptr l) { - List_Obj ll = SASS_MEMORY_NEW(List, - l->pstate(), - l->length(), - l->separator(), - l->is_arglist()); - for (size_t i = 0, L = l->length(); i < L; ++i) { + List_Obj ll = SASS_MEMORY_NEW(List, l->pstate(), l->length(), l->separator(), l->is_arglist()); + for (size_t i = 0, L = l->length(); i < L; ++i) + { ll->append((*l)[i]->perform(this)); } return ll.detach(); @@ -89,17 +87,12 @@ namespace Sass { // Selector_List is converted to a string Value_Ptr To_Value::operator()(Selector_List_Ptr s) { - return SASS_MEMORY_NEW(String_Quoted, - s->pstate(), - s->to_string(ctx.c_options)); + return SASS_MEMORY_NEW(String_Quoted, s->pstate(), s->to_string(ctx.c_options)); } // Binary_Expression is converted to a string Value_Ptr To_Value::operator()(Binary_Expression_Ptr s) { - return SASS_MEMORY_NEW(String_Quoted, - s->pstate(), - s->to_string(ctx.c_options)); + return SASS_MEMORY_NEW(String_Quoted, s->pstate(), s->to_string(ctx.c_options)); } - }; diff --git a/src/to_value.hpp b/src/to_value.hpp index e6c88dd691..bf5a9072b5 100644 --- a/src/to_value.hpp +++ b/src/to_value.hpp @@ -5,22 +5,24 @@ #include "sass/values.h" #include "ast_fwd_decl.hpp" -namespace Sass { +namespace Sass +{ - class To_Value : public Operation_CRTP { + class To_Value : public Operation_CRTP + { Value_Ptr fallback_impl(AST_Node_Ptr n); - private: - + private: Context& ctx; - public: - - To_Value(Context& ctx) - : ctx(ctx) - { } - ~To_Value() { } + public: + To_Value(Context& ctx) : ctx(ctx) + { + } + ~To_Value() + { + } using Operation::operator(); Value_Ptr operator()(Argument_Ptr); @@ -40,10 +42,11 @@ namespace Sass { Value_Ptr operator()(Binary_Expression_Ptr); // fallback throws error - template - Value_Ptr fallback(U x) { return fallback_impl(x); } + template Value_Ptr fallback(U x) + { + return fallback_impl(x); + } }; - } #endif diff --git a/src/units.cpp b/src/units.cpp index fd5f096bde..ab84f3d3a2 100644 --- a/src/units.cpp +++ b/src/units.cpp @@ -3,63 +3,70 @@ #include "units.hpp" #include "error_handling.hpp" -namespace Sass { +namespace Sass +{ /* the conversion matrix can be readed the following way */ /* if you go down, the factor is for the numerator (multiply) */ /* if you go right, the factor is for the denominator (divide) */ /* and yes, we actually use both, not sure why, but why not!? */ - const double size_conversion_factors[6][6] = - { - /* in cm pc mm pt px */ - /* in */ { 1, 2.54, 6, 25.4, 72, 96, }, - /* cm */ { 1.0/2.54, 1, 6.0/2.54, 10, 72.0/2.54, 96.0/2.54 }, - /* pc */ { 1.0/6.0, 2.54/6.0, 1, 25.4/6.0, 72.0/6.0, 96.0/6.0 }, - /* mm */ { 1.0/25.4, 1.0/10.0, 6.0/25.4, 1, 72.0/25.4, 96.0/25.4 }, - /* pt */ { 1.0/72.0, 2.54/72.0, 6.0/72.0, 25.4/72.0, 1, 96.0/72.0 }, - /* px */ { 1.0/96.0, 2.54/96.0, 6.0/96.0, 25.4/96.0, 72.0/96.0, 1, } + const double size_conversion_factors[6][6] = { + /* in cm pc mm pt px */ + /* in */ { + 1, 2.54, 6, 25.4, 72, 96, + }, + /* cm */ { 1.0 / 2.54, 1, 6.0 / 2.54, 10, 72.0 / 2.54, 96.0 / 2.54 }, + /* pc */ { 1.0 / 6.0, 2.54 / 6.0, 1, 25.4 / 6.0, 72.0 / 6.0, 96.0 / 6.0 }, + /* mm */ { 1.0 / 25.4, 1.0 / 10.0, 6.0 / 25.4, 1, 72.0 / 25.4, 96.0 / 25.4 }, + /* pt */ { 1.0 / 72.0, 2.54 / 72.0, 6.0 / 72.0, 25.4 / 72.0, 1, 96.0 / 72.0 }, + /* px */ + { + 1.0 / 96.0, 2.54 / 96.0, 6.0 / 96.0, 25.4 / 96.0, 72.0 / 96.0, 1, + } }; - const double angle_conversion_factors[4][4] = - { - /* deg grad rad turn */ - /* deg */ { 1, 40.0/36.0, PI/180.0, 1.0/360.0 }, - /* grad */ { 36.0/40.0, 1, PI/200.0, 1.0/400.0 }, - /* rad */ { 180.0/PI, 200.0/PI, 1, 0.5/PI }, - /* turn */ { 360.0, 400.0, 2.0*PI, 1 } + const double angle_conversion_factors[4][4] = { + /* deg grad rad turn */ + /* deg */ { 1, 40.0 / 36.0, PI / 180.0, 1.0 / 360.0 }, + /* grad */ { 36.0 / 40.0, 1, PI / 200.0, 1.0 / 400.0 }, + /* rad */ { 180.0 / PI, 200.0 / PI, 1, 0.5 / PI }, + /* turn */ { 360.0, 400.0, 2.0 * PI, 1 } }; - const double time_conversion_factors[2][2] = - { - /* s ms */ - /* s */ { 1, 1000.0 }, - /* ms */ { 1/1000.0, 1 } + const double time_conversion_factors[2][2] = { + /* s ms */ + /* s */ { 1, 1000.0 }, + /* ms */ { 1 / 1000.0, 1 } }; - const double frequency_conversion_factors[2][2] = - { - /* Hz kHz */ - /* Hz */ { 1, 1/1000.0 }, - /* kHz */ { 1000.0, 1 } + const double frequency_conversion_factors[2][2] = { + /* Hz kHz */ + /* Hz */ { 1, 1 / 1000.0 }, + /* kHz */ { 1000.0, 1 } }; - const double resolution_conversion_factors[3][3] = - { - /* dpi dpcm dppx */ - /* dpi */ { 1, 1/2.54, 1/96.0 }, - /* dpcm */ { 2.54, 1, 2.54/96 }, - /* dppx */ { 96, 96/2.54, 1 } + const double resolution_conversion_factors[3][3] = { + /* dpi dpcm dppx */ + /* dpi */ { 1, 1 / 2.54, 1 / 96.0 }, + /* dpcm */ { 2.54, 1, 2.54 / 96 }, + /* dppx */ { 96, 96 / 2.54, 1 } }; UnitClass get_unit_type(UnitType unit) { switch (unit & 0xFF00) { - case UnitClass::LENGTH: return UnitClass::LENGTH; - case UnitClass::ANGLE: return UnitClass::ANGLE; - case UnitClass::TIME: return UnitClass::TIME; - case UnitClass::FREQUENCY: return UnitClass::FREQUENCY; - case UnitClass::RESOLUTION: return UnitClass::RESOLUTION; - default: return UnitClass::INCOMMENSURABLE; + case UnitClass::LENGTH: + return UnitClass::LENGTH; + case UnitClass::ANGLE: + return UnitClass::ANGLE; + case UnitClass::TIME: + return UnitClass::TIME; + case UnitClass::FREQUENCY: + return UnitClass::FREQUENCY; + case UnitClass::RESOLUTION: + return UnitClass::RESOLUTION; + default: + return UnitClass::INCOMMENSURABLE; } }; @@ -67,96 +74,156 @@ namespace Sass { { switch (unit & 0xFF00) { - case UnitClass::LENGTH: return "LENGTH"; - case UnitClass::ANGLE: return "ANGLE"; - case UnitClass::TIME: return "TIME"; - case UnitClass::FREQUENCY: return "FREQUENCY"; - case UnitClass::RESOLUTION: return "RESOLUTION"; - default: return "INCOMMENSURABLE"; + case UnitClass::LENGTH: + return "LENGTH"; + case UnitClass::ANGLE: + return "ANGLE"; + case UnitClass::TIME: + return "TIME"; + case UnitClass::FREQUENCY: + return "FREQUENCY"; + case UnitClass::RESOLUTION: + return "RESOLUTION"; + default: + return "INCOMMENSURABLE"; } }; UnitType string_to_unit(const std::string& s) { // size units - if (s == "px") return UnitType::PX; - else if (s == "pt") return UnitType::PT; - else if (s == "pc") return UnitType::PC; - else if (s == "mm") return UnitType::MM; - else if (s == "cm") return UnitType::CM; - else if (s == "in") return UnitType::IN; + if (s == "px") + return UnitType::PX; + else if (s == "pt") + return UnitType::PT; + else if (s == "pc") + return UnitType::PC; + else if (s == "mm") + return UnitType::MM; + else if (s == "cm") + return UnitType::CM; + else if (s == "in") + return UnitType::IN; // angle units - else if (s == "deg") return UnitType::DEG; - else if (s == "grad") return UnitType::GRAD; - else if (s == "rad") return UnitType::RAD; - else if (s == "turn") return UnitType::TURN; + else if (s == "deg") + return UnitType::DEG; + else if (s == "grad") + return UnitType::GRAD; + else if (s == "rad") + return UnitType::RAD; + else if (s == "turn") + return UnitType::TURN; // time units - else if (s == "s") return UnitType::SEC; - else if (s == "ms") return UnitType::MSEC; + else if (s == "s") + return UnitType::SEC; + else if (s == "ms") + return UnitType::MSEC; // frequency units - else if (s == "Hz") return UnitType::HERTZ; - else if (s == "kHz") return UnitType::KHERTZ; + else if (s == "Hz") + return UnitType::HERTZ; + else if (s == "kHz") + return UnitType::KHERTZ; // resolutions units - else if (s == "dpi") return UnitType::DPI; - else if (s == "dpcm") return UnitType::DPCM; - else if (s == "dppx") return UnitType::DPPX; + else if (s == "dpi") + return UnitType::DPI; + else if (s == "dpcm") + return UnitType::DPCM; + else if (s == "dppx") + return UnitType::DPPX; // for unknown units - else return UnitType::UNKNOWN; + else + return UnitType::UNKNOWN; } const char* unit_to_string(UnitType unit) { - switch (unit) { - // size units - case UnitType::PX: return "px"; - case UnitType::PT: return "pt"; - case UnitType::PC: return "pc"; - case UnitType::MM: return "mm"; - case UnitType::CM: return "cm"; - case UnitType::IN: return "in"; - // angle units - case UnitType::DEG: return "deg"; - case UnitType::GRAD: return "grad"; - case UnitType::RAD: return "rad"; - case UnitType::TURN: return "turn"; - // time units - case UnitType::SEC: return "s"; - case UnitType::MSEC: return "ms"; - // frequency units - case UnitType::HERTZ: return "Hz"; - case UnitType::KHERTZ: return "kHz"; - // resolutions units - case UnitType::DPI: return "dpi"; - case UnitType::DPCM: return "dpcm"; - case UnitType::DPPX: return "dppx"; - // for unknown units - default: return ""; + switch (unit) + { + // size units + case UnitType::PX: + return "px"; + case UnitType::PT: + return "pt"; + case UnitType::PC: + return "pc"; + case UnitType::MM: + return "mm"; + case UnitType::CM: + return "cm"; + case UnitType::IN: + return "in"; + // angle units + case UnitType::DEG: + return "deg"; + case UnitType::GRAD: + return "grad"; + case UnitType::RAD: + return "rad"; + case UnitType::TURN: + return "turn"; + // time units + case UnitType::SEC: + return "s"; + case UnitType::MSEC: + return "ms"; + // frequency units + case UnitType::HERTZ: + return "Hz"; + case UnitType::KHERTZ: + return "kHz"; + // resolutions units + case UnitType::DPI: + return "dpi"; + case UnitType::DPCM: + return "dpcm"; + case UnitType::DPPX: + return "dppx"; + // for unknown units + default: + return ""; } } std::string unit_to_class(const std::string& s) { - if (s == "px") return "LENGTH"; - else if (s == "pt") return "LENGTH"; - else if (s == "pc") return "LENGTH"; - else if (s == "mm") return "LENGTH"; - else if (s == "cm") return "LENGTH"; - else if (s == "in") return "LENGTH"; + if (s == "px") + return "LENGTH"; + else if (s == "pt") + return "LENGTH"; + else if (s == "pc") + return "LENGTH"; + else if (s == "mm") + return "LENGTH"; + else if (s == "cm") + return "LENGTH"; + else if (s == "in") + return "LENGTH"; // angle units - else if (s == "deg") return "ANGLE"; - else if (s == "grad") return "ANGLE"; - else if (s == "rad") return "ANGLE"; - else if (s == "turn") return "ANGLE"; + else if (s == "deg") + return "ANGLE"; + else if (s == "grad") + return "ANGLE"; + else if (s == "rad") + return "ANGLE"; + else if (s == "turn") + return "ANGLE"; // time units - else if (s == "s") return "TIME"; - else if (s == "ms") return "TIME"; + else if (s == "s") + return "TIME"; + else if (s == "ms") + return "TIME"; // frequency units - else if (s == "Hz") return "FREQUENCY"; - else if (s == "kHz") return "FREQUENCY"; + else if (s == "Hz") + return "FREQUENCY"; + else if (s == "kHz") + return "FREQUENCY"; // resolutions units - else if (s == "dpi") return "RESOLUTION"; - else if (s == "dpcm") return "RESOLUTION"; - else if (s == "dppx") return "RESOLUTION"; + else if (s == "dpi") + return "RESOLUTION"; + else if (s == "dpcm") + return "RESOLUTION"; + else if (s == "dppx") + return "RESOLUTION"; // for unknown units return "CUSTOM:" + s; } @@ -180,20 +247,28 @@ namespace Sass { // don't error for multiplication and division if (strict && t1 != t2) throw Exception::IncompatibleUnits(u1, u2); // only process known units - if (u1 != UNKNOWN && u2 != UNKNOWN) { - switch (t1) { - case UnitClass::LENGTH: return size_conversion_factors[i1][i2]; - case UnitClass::ANGLE: return angle_conversion_factors[i1][i2]; - case UnitClass::TIME: return time_conversion_factors[i1][i2]; - case UnitClass::FREQUENCY: return frequency_conversion_factors[i1][i2]; - case UnitClass::RESOLUTION: return resolution_conversion_factors[i1][i2]; - // ToDo: should we throw error here? - case UnitClass::INCOMMENSURABLE: return 0; - default: break; + if (u1 != UNKNOWN && u2 != UNKNOWN) + { + switch (t1) + { + case UnitClass::LENGTH: + return size_conversion_factors[i1][i2]; + case UnitClass::ANGLE: + return angle_conversion_factors[i1][i2]; + case UnitClass::TIME: + return time_conversion_factors[i1][i2]; + case UnitClass::FREQUENCY: + return frequency_conversion_factors[i1][i2]; + case UnitClass::RESOLUTION: + return resolution_conversion_factors[i1][i2]; + // ToDo: should we throw error here? + case UnitClass::INCOMMENSURABLE: + return 0; + default: + break; } } // fallback return 0; } - } diff --git a/src/units.hpp b/src/units.hpp index e0e0375969..e92209cdd8 100644 --- a/src/units.hpp +++ b/src/units.hpp @@ -5,11 +5,13 @@ #include #include -namespace Sass { +namespace Sass +{ const double PI = std::acos(-1); - enum UnitClass { + enum UnitClass + { LENGTH = 0x000, ANGLE = 0x100, TIME = 0x200, @@ -18,7 +20,8 @@ namespace Sass { INCOMMENSURABLE = 0x500 }; - enum UnitType { + enum UnitType + { // size units IN = UnitClass::LENGTH, @@ -65,7 +68,6 @@ namespace Sass { std::string unit_to_class(const std::string&); // throws incompatibleUnits exceptions double conversion_factor(const std::string&, const std::string&, bool = true); - } #endif diff --git a/src/utf8_string.cpp b/src/utf8_string.cpp index ba4d7a25f9..7c66c40643 100644 --- a/src/utf8_string.cpp +++ b/src/utf8_string.cpp @@ -6,8 +6,10 @@ #include "utf8.h" -namespace Sass { - namespace UTF_8 { +namespace Sass +{ + namespace UTF_8 + { using std::string; // naming conventions: @@ -15,24 +17,29 @@ namespace Sass { // position: code point offset (0 based) // index: code point offset (1 based or negative) - // function that will count the number of code points (utf-8 characters) from the given beginning to the given end - size_t code_point_count(const string& str, size_t start, size_t end) { + // function that will count the number of code points (utf-8 characters) from the given + // beginning to the given end + size_t code_point_count(const string& str, size_t start, size_t end) + { return utf8::distance(str.begin() + start, str.begin() + end); } - size_t code_point_count(const string& str) { + size_t code_point_count(const string& str) + { return utf8::distance(str.begin(), str.end()); } // function that will return the byte offset at a code point position - size_t offset_at_position(const string& str, size_t position) { + size_t offset_at_position(const string& str, size_t position) + { string::const_iterator it = str.begin(); utf8::advance(it, position, str.end()); return distance(str.begin(), it); } // function that returns number of bytes in a character at offset - size_t code_point_size_at_offset(const string& str, size_t offset) { + size_t code_point_size_at_offset(const string& str, size_t offset) + { // get iterator from string and forward by offset string::const_iterator stop = str.begin() + offset; // check if beyond boundary @@ -40,36 +47,42 @@ namespace Sass { // advance by one code point utf8::advance(stop, 1, str.end()); // calculate offset for code point - return stop - str.begin() - offset; + return stop - str.begin() - offset; } // function that will return a normalized index, given a crazy one - size_t normalize_index(int index, size_t len) { + size_t normalize_index(int index, size_t len) + { long signed_len = static_cast(len); // assuming the index is 1-based // we are returning a 0-based index - if (index > 0 && index <= signed_len) { + if (index > 0 && index <= signed_len) + { // positive and within string length - return index-1; + return index - 1; } - else if (index > signed_len) { + else if (index > signed_len) + { // positive and past string length return len; } - else if (index == 0) { + else if (index == 0) + { return 0; } - else if (std::abs((double)index) <= signed_len) { + else if (std::abs((double)index) <= signed_len) + { // negative and within string length return index + signed_len; } - else { + else + { // negative and past string length return 0; } } - #ifdef _WIN32 +#ifdef _WIN32 // utf16 functions using std::wstring; @@ -79,9 +92,8 @@ namespace Sass { { string utf8; // pre-allocate expected memory - utf8.reserve(sizeof(utf16)/2); - utf8::utf16to8(utf16.begin(), utf16.end(), - back_inserter(utf8)); + utf8.reserve(sizeof(utf16) / 2); + utf8::utf16to8(utf16.begin(), utf16.end(), back_inserter(utf8)); return utf8; } @@ -90,13 +102,11 @@ namespace Sass { { wstring utf16; // pre-allocate expected memory - utf16.reserve(code_point_count(utf8)*2); - utf8::utf8to16(utf8.begin(), utf8.end(), - back_inserter(utf16)); + utf16.reserve(code_point_count(utf8) * 2); + utf8::utf8to16(utf8.begin(), utf8.end(), back_inserter(utf16)); return utf16; } - #endif - +#endif } } diff --git a/src/utf8_string.hpp b/src/utf8_string.hpp index 5e879bec38..6b5427b021 100644 --- a/src/utf8_string.hpp +++ b/src/utf8_string.hpp @@ -4,15 +4,18 @@ #include #include "utf8.h" -namespace Sass { - namespace UTF_8 { +namespace Sass +{ + namespace UTF_8 + { // naming conventions: // offset: raw byte offset (0 based) // position: code point offset (0 based) // index: code point offset (1 based or negative) - // function that will count the number of code points (utf-8 characters) from the beginning to the given end + // function that will count the number of code points (utf-8 characters) from the beginning to + // the given end size_t code_point_count(const std::string& str, size_t start, size_t end); size_t code_point_count(const std::string& str); @@ -25,12 +28,11 @@ namespace Sass { // function that will return a normalized index, given a crazy one size_t normalize_index(int index, size_t len); - #ifdef _WIN32 +#ifdef _WIN32 // functions to handle unicode paths on windows std::string convert_from_utf16(const std::wstring& wstr); std::wstring convert_to_utf16(const std::string& str); - #endif - +#endif } } diff --git a/src/util.cpp b/src/util.cpp index a7ca769758..7e427d00c2 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -13,21 +13,24 @@ #include #endif -namespace Sass { +namespace Sass +{ double round(double val, size_t precision) { - // Disable FMA3-optimized implementation when compiling with VS2013 for x64 targets - // See https://github.com/sass/node-sass/issues/1854 for details - // FIXME: Remove this workaround when we switch to VS2015+ - #if defined(_MSC_VER) && _MSC_VER >= 1800 && _MSC_VER < 1900 && defined(_M_X64) - static std::once_flag flag; - std::call_once(flag, []() { _set_FMA3_enable(0); }); - #endif +// Disable FMA3-optimized implementation when compiling with VS2013 for x64 targets +// See https://github.com/sass/node-sass/issues/1854 for details +// FIXME: Remove this workaround when we switch to VS2015+ +#if defined(_MSC_VER) && _MSC_VER >= 1800 && _MSC_VER < 1900 && defined(_M_X64) + static std::once_flag flag; + std::call_once(flag, []() { _set_FMA3_enable(0); }); +#endif // https://github.com/sass/sass/commit/4e3e1d5684cc29073a507578fc977434ff488c93 - if (fmod(val, 1) - 0.5 > - std::pow(0.1, precision + 1)) return std::ceil(val); - else if (fmod(val, 1) - 0.5 > std::pow(0.1, precision)) return std::floor(val); + if (fmod(val, 1) - 0.5 > -std::pow(0.1, precision + 1)) + return std::ceil(val); + else if (fmod(val, 1) - 0.5 > std::pow(0.1, precision)) + return std::floor(val); // work around some compiler issue // cygwin has it not defined in std using namespace std; @@ -35,18 +38,20 @@ namespace Sass { } /* Locale unspecific atof function. */ - double sass_atof(const char *str) + double sass_atof(const char* str) { char separator = *(localeconv()->decimal_point); - if(separator != '.'){ + if (separator != '.') + { // The current locale specifies another // separator. convert the separator to the // one understood by the locale if needed - const char *found = strchr(str, '.'); - if(found != NULL){ + const char* found = strchr(str, '.'); + if (found != NULL) + { // substitution is required. perform the substitution on a copy // of the string. This is slower but it is thread safe. - char *copy = sass_copy_c_string(str); + char* copy = sass_copy_c_string(str); *(copy + (found - str)) = separator; double res = atof(copy); free(copy); @@ -58,16 +63,18 @@ namespace Sass { } // helper for safe access to c_ctx - const char* safe_str (const char* str, const char* alt) { + const char* safe_str(const char* str, const char* alt) + { return str == NULL ? alt : str; } - void free_string_array(char ** arr) { - if(!arr) - return; + void free_string_array(char** arr) + { + if (!arr) return; - char **it = arr; - while (it && (*it)) { + char** it = arr; + while (it && (*it)) + { free(*it); ++it; } @@ -75,17 +82,19 @@ namespace Sass { free(arr); } - char **copy_strings(const std::vector& strings, char*** array, int skip) { + char** copy_strings(const std::vector& strings, char*** array, int skip) + { int num = static_cast(strings.size()) - skip; - char** arr = (char**) calloc(num + 1, sizeof(char*)); - if (arr == 0) - return *array = (char **)NULL; + char** arr = (char**)calloc(num + 1, sizeof(char*)); + if (arr == 0) return *array = (char**)NULL; - for(int i = 0; i < num; i++) { - arr[i] = (char*) malloc(sizeof(char) * (strings[i + skip].size() + 1)); - if (arr[i] == 0) { + for (int i = 0; i < num; i++) + { + arr[i] = (char*)malloc(sizeof(char) * (strings[i + skip].size() + 1)); + if (arr[i] == 0) + { free_string_array(arr); - return *array = (char **)NULL; + return *array = (char**)NULL; } std::copy(strings[i + skip].begin(), strings[i + skip].end(), arr[i]); arr[i][strings[i + skip].size()] = '\0'; @@ -100,16 +109,24 @@ namespace Sass { { std::string out(""); bool esc = false; - for (auto i : str) { - if (i == '\\') { - esc = ! esc; - } else if (esc && i == '\r') { + for (auto i : str) + { + if (i == '\\') + { + esc = !esc; + } + else if (esc && i == '\r') + { continue; - } else if (esc && i == '\n') { - out.resize (out.size () - 1); + } + else if (esc && i == '\n') + { + out.resize(out.size() - 1); esc = false; continue; - } else { + } + else + { esc = false; } out.push_back(i); @@ -127,24 +144,34 @@ namespace Sass { { std::string out(""); bool esc = false; - for (auto i : str) { - if (i == '\\' && !esc) { + for (auto i : str) + { + if (i == '\\' && !esc) + { out += '\\'; out += '\\'; esc = true; - } else if (esc && i == '"') { + } + else if (esc && i == '"') + { out += '\\'; out += i; esc = false; - } else if (esc && i == '\'') { + } + else if (esc && i == '\'') + { out += '\\'; out += i; esc = false; - } else if (esc && i == '\\') { + } + else if (esc && i == '\\') + { out += '\\'; out += i; esc = false; - } else { + } + else + { esc = false; out += i; } @@ -168,11 +195,15 @@ namespace Sass { { std::string out(""); bool lf = false; - for (auto i : str) { - if (i == '\n') { + for (auto i : str) + { + if (i == '\n') + { out += ' '; lf = true; - } else if (!(lf && isspace(i))) { + } + else if (!(lf && isspace(i))) + { out += i; lf = false; } @@ -186,30 +217,57 @@ namespace Sass { size_t has = 0; char prev = 0; bool clean = false; - for (auto i : text) { - if (clean) { - if (i == '\n') { has = 0; } - else if (i == '\r') { has = 0; } - else if (i == '\t') { ++ has; } - else if (i == ' ') { ++ has; } - else if (i == '*') {} - else { + for (auto i : text) + { + if (clean) + { + if (i == '\n') + { + has = 0; + } + else if (i == '\r') + { + has = 0; + } + else if (i == '\t') + { + ++has; + } + else if (i == ' ') + { + ++has; + } + else if (i == '*') + { + } + else + { clean = false; str += ' '; - if (prev == '*' && i == '/') str += "*/"; - else str += i; + if (prev == '*' && i == '/') + str += "*/"; + else + str += i; } - } else if (i == '\n') { + } + else if (i == '\n') + { clean = true; - } else if (i == '\r') { + } + else if (i == '\r') + { clean = true; - } else { + } + else + { str += i; } prev = i; } - if (has) return str; - else return text; + if (has) + return str; + else + return text; } // find best quote_mark by detecting if the string contains any single @@ -220,14 +278,21 @@ namespace Sass { { // ensure valid fallback quote_mark char quote_mark = qm && qm != '*' ? qm : '"'; - while (*s) { + while (*s) + { // force double quotes as soon // as one single quote is found - if (*s == '\'') { return '"'; } + if (*s == '\'') + { + return '"'; + } // a single does not force quote_mark // maybe we see a double quote later - else if (*s == '"') { quote_mark = '\''; } - ++ s; + else if (*s == '"') + { + quote_mark = '\''; + } + ++s; } return quote_mark; } @@ -244,18 +309,23 @@ namespace Sass { // this is no guarantee that the unquoting will work // what about whitespace before/after the quote_mark? - if (*s.begin() == '"' && *s.rbegin() == '"') q = '"'; - else if (*s.begin() == '\'' && *s.rbegin() == '\'') q = '\''; - else return s; + if (*s.begin() == '"' && *s.rbegin() == '"') + q = '"'; + else if (*s.begin() == '\'' && *s.rbegin() == '\'') + q = '\''; + else + return s; std::string unq; - unq.reserve(s.length()-2); + unq.reserve(s.length() - 2); - for (size_t i = 1, L = s.length() - 1; i < L; ++i) { + for (size_t i = 1, L = s.length() - 1; i < L; ++i) + { // implement the same strange ruby sass behavior // an escape sequence can also mean a unicode char - if (s[i] == '\\' && !skipped) { + if (s[i] == '\\' && !skipped) + { // remember skipped = true; @@ -269,18 +339,22 @@ namespace Sass { // parse as many sequence chars as possible // ToDo: Check if ruby aborts after possible max - while (i + len < L && s[i + len] && isxdigit(s[i + len])) ++ len; + while (i + len < L && s[i + len] && isxdigit(s[i + len])) + ++len; // hex string? - if (keep_utf8_sequences) { + if (keep_utf8_sequences) + { unq.push_back(s[i]); - } else if (len > 1) { + } + else if (len > 1) + { // convert the extracted hex string to code point value // ToDo: Maybe we could do this without creating a substring - uint32_t cp = strtol(s.substr (i + 1, len - 1).c_str(), NULL, 16); + uint32_t cp = strtol(s.substr(i + 1, len - 1).c_str(), NULL, 16); - if (s[i + len] == ' ') ++ len; + if (s[i + len] == ' ') ++len; // assert invalid code points if (cp == 0) cp = 0xFFFD; @@ -291,15 +365,15 @@ namespace Sass { // maybe there is a more elegant way; maybe we shoud // convert the whole output from string to a stream!? // allocate memory for utf8 char and convert to utf8 - unsigned char u[5] = {0,0,0,0,0}; utf8::append(cp, u); - for(size_t m = 0; u[m] && m < 5; m++) unq.push_back(u[m]); + unsigned char u[5] = { 0, 0, 0, 0, 0 }; + utf8::append(cp, u); + for (size_t m = 0; u[m] && m < 5; m++) + unq.push_back(u[m]); // skip some more chars? - i += len - 1; skipped = false; - + i += len - 1; + skipped = false; } - - } // check for unexpected delimiter // be strict and throw error back @@ -307,21 +381,25 @@ namespace Sass { // // don't be that strict // return s; // // this basically always means an internal error and not users fault - // error("Unescaped delimiter in string to unquote found. [" + s + "]", ParserState("[UNQUOTE]")); + // error("Unescaped delimiter in string to unquote found. [" + s + "]", + // ParserState("[UNQUOTE]")); // } - else { - if (strict && !skipped) { + else + { + if (strict && !skipped) + { if (s[i] == q) return s; } skipped = false; unq.push_back(s[i]); } - } - if (skipped) { return s; } + if (skipped) + { + return s; + } if (qd) *qd = q; return unq; - } std::string quote(const std::string& s, char q) @@ -334,17 +412,21 @@ namespace Sass { if (s.empty()) return std::string(2, q ? q : '"'); std::string quoted; - quoted.reserve(s.length()+2); + quoted.reserve(s.length() + 2); quoted.push_back(q); const char* it = s.c_str(); const char* end = it + strlen(it) + 1; - while (*it && it < end) { + while (*it && it < end) + { const char* now = it; - if (*it == q) { + if (*it == q) + { quoted.push_back('\\'); - } else if (*it == '\\') { + } + else if (*it == '\\') + { quoted.push_back('\\'); } @@ -352,31 +434,35 @@ namespace Sass { // in case of \r, check if the next in sequence // is \n and then advance the iterator and skip \r - if (cp == '\r' && it < end && utf8::peek_next(it, end) == '\n') { + if (cp == '\r' && it < end && utf8::peek_next(it, end) == '\n') + { cp = utf8::next(it, end); } - if (cp == '\n') { + if (cp == '\n') + { quoted.push_back('\\'); quoted.push_back('a'); // we hope we can remove this flag once we figure out // why ruby sass has these different output behaviors // gsub(/\n(?![a-fA-F0-9\s])/, "\\a").gsub("\n", "\\a ") using namespace Prelexer; - if (alternatives < - Prelexer::char_range<'a', 'f'>, - Prelexer::char_range<'A', 'F'>, - Prelexer::char_range<'0', '9'>, - space - >(it) != NULL) { + if (alternatives, Prelexer::char_range<'A', 'F'>, Prelexer::char_range<'0', '9'>, space>( + it) != NULL) + { quoted.push_back(' '); } - } else if (cp < 127) { - quoted.push_back((char) cp); - } else { - while (now < it) { + } + else if (cp < 127) + { + quoted.push_back((char)cp); + } + else + { + while (now < it) + { quoted.push_back(*now); - ++ now; + ++now; } } } @@ -387,10 +473,9 @@ namespace Sass { bool is_hex_doublet(double n) { - return n == 0x00 || n == 0x11 || n == 0x22 || n == 0x33 || - n == 0x44 || n == 0x55 || n == 0x66 || n == 0x77 || - n == 0x88 || n == 0x99 || n == 0xAA || n == 0xBB || - n == 0xCC || n == 0xDD || n == 0xEE || n == 0xFF ; + return n == 0x00 || n == 0x11 || n == 0x22 || n == 0x33 || n == 0x44 || n == 0x55 || + n == 0x66 || n == 0x77 || n == 0x88 || n == 0x99 || n == 0xAA || n == 0xBB || + n == 0xCC || n == 0xDD || n == 0xEE || n == 0xFF; } bool is_color_doublet(double r, double g, double b) @@ -402,55 +487,54 @@ namespace Sass { { using namespace Prelexer; using namespace Constants; - return sequence < - zero_plus < - alternatives < - exactly <' '>, - exactly <'\t'>, - line_comment, - block_comment, - delimited_by < - slash_star, - star_slash, - false - > - > - >, - re_linebreak - >(start) != 0; + return sequence, exactly<'\t'>, line_comment, block_comment, delimited_by>>, re_linebreak>( + start) != 0; } - namespace Util { + namespace Util + { using std::string; - std::string rtrim(const std::string &str) { + std::string rtrim(const std::string& str) + { std::string trimmed = str; size_t pos_ws = trimmed.find_last_not_of(" \t\n\v\f\r"); if (pos_ws != std::string::npos) - { trimmed.erase(pos_ws + 1); } - else { trimmed.clear(); } + { + trimmed.erase(pos_ws + 1); + } + else + { + trimmed.clear(); + } return trimmed; } - std::string normalize_underscores(const std::string& str) { + std::string normalize_underscores(const std::string& str) + { std::string normalized = str; - for(size_t i = 0, L = normalized.length(); i < L; ++i) { - if(normalized[i] == '_') { + for (size_t i = 0, L = normalized.length(); i < L; ++i) + { + if (normalized[i] == '_') + { normalized[i] = '-'; } } return normalized; } - std::string normalize_decimals(const std::string& str) { + std::string normalize_decimals(const std::string& str) + { std::string prefix = "0"; std::string normalized = str; return normalized[0] == '.' ? normalized.insert(0, prefix) : normalized; } - bool isPrintable(Ruleset_Ptr r, Sass_Output_Style style) { - if (r == NULL) { + bool isPrintable(Ruleset_Ptr r, Sass_Output_Style style) + { + if (r == NULL) + { return false; } @@ -459,37 +543,52 @@ namespace Sass { Selector_List_Ptr sl = Cast(r->selector()); bool hasSelectors = sl ? sl->length() > 0 : false; - if (!hasSelectors) { + if (!hasSelectors) + { return false; } bool hasDeclarations = false; bool hasPrintableChildBlocks = false; - for (size_t i = 0, L = b->length(); i < L; ++i) { + for (size_t i = 0, L = b->length(); i < L; ++i) + { Statement_Obj stm = b->at(i); - if (Cast(stm)) { + if (Cast(stm)) + { return true; - } else if (Declaration_Ptr d = Cast(stm)) { + } + else if (Declaration_Ptr d = Cast(stm)) + { return isPrintable(d, style); - } else if (Has_Block_Ptr p = Cast(stm)) { + } + else if (Has_Block_Ptr p = Cast(stm)) + { Block_Obj pChildBlock = p->block(); - if (isPrintable(pChildBlock, style)) { + if (isPrintable(pChildBlock, style)) + { hasPrintableChildBlocks = true; } - } else if (Comment_Ptr c = Cast(stm)) { + } + else if (Comment_Ptr c = Cast(stm)) + { // keep for uncompressed - if (style != COMPRESSED) { + if (style != COMPRESSED) + { hasDeclarations = true; } // output style compressed - if (c->is_important()) { + if (c->is_important()) + { hasDeclarations = c->is_important(); } - } else { + } + else + { hasDeclarations = true; } - if (hasDeclarations || hasPrintableChildBlocks) { + if (hasDeclarations || hasPrintableChildBlocks) + { return true; } } @@ -499,7 +598,7 @@ namespace Sass { bool isPrintable(String_Constant_Ptr s, Sass_Output_Style style) { - return ! s->value().empty(); + return !s->value().empty(); } bool isPrintable(String_Quoted_Ptr s, Sass_Output_Style style) @@ -515,8 +614,10 @@ namespace Sass { return true; } - bool isPrintable(Supports_Block_Ptr f, Sass_Output_Style style) { - if (f == NULL) { + bool isPrintable(Supports_Block_Ptr f, Sass_Output_Style style) + { + if (f == NULL) + { return false; } @@ -524,19 +625,24 @@ namespace Sass { bool hasDeclarations = false; bool hasPrintableChildBlocks = false; - for (size_t i = 0, L = b->length(); i < L; ++i) { + for (size_t i = 0, L = b->length(); i < L; ++i) + { Statement_Obj stm = b->at(i); - if (Cast(stm) || Cast(stm)) { + if (Cast(stm) || Cast(stm)) + { hasDeclarations = true; } - else if (Has_Block_Ptr b = Cast(stm)) { + else if (Has_Block_Ptr b = Cast(stm)) + { Block_Obj pChildBlock = b->block(); - if (isPrintable(pChildBlock, style)) { + if (isPrintable(pChildBlock, style)) + { hasPrintableChildBlocks = true; } } - if (hasDeclarations || hasPrintableChildBlocks) { + if (hasDeclarations || hasPrintableChildBlocks) + { return true; } } @@ -549,32 +655,45 @@ namespace Sass { if (m == 0) return false; Block_Obj b = m->block(); if (b == 0) return false; - for (size_t i = 0, L = b->length(); i < L; ++i) { + for (size_t i = 0, L = b->length(); i < L; ++i) + { Statement_Obj stm = b->at(i); - if (Cast(stm)) return true; - else if (Cast(stm)) return true; - else if (Comment_Ptr c = Cast(stm)) { - if (isPrintable(c, style)) { + if (Cast(stm)) + return true; + else if (Cast(stm)) + return true; + else if (Comment_Ptr c = Cast(stm)) + { + if (isPrintable(c, style)) + { return true; } } - else if (Ruleset_Ptr r = Cast(stm)) { - if (isPrintable(r, style)) { + else if (Ruleset_Ptr r = Cast(stm)) + { + if (isPrintable(r, style)) + { return true; } } - else if (Supports_Block_Ptr f = Cast(stm)) { - if (isPrintable(f, style)) { + else if (Supports_Block_Ptr f = Cast(stm)) + { + if (isPrintable(f, style)) + { return true; } } - else if (Media_Block_Ptr mb = Cast(stm)) { - if (isPrintable(mb, style)) { + else if (Media_Block_Ptr mb = Cast(stm)) + { + if (isPrintable(mb, style)) + { return true; } } - else if (Has_Block_Ptr b = Cast(stm)) { - if (isPrintable(b->block(), style)) { + else if (Has_Block_Ptr b = Cast(stm)) + { + if (isPrintable(b->block(), style)) + { return true; } } @@ -585,49 +704,65 @@ namespace Sass { bool isPrintable(Comment_Ptr c, Sass_Output_Style style) { // keep for uncompressed - if (style != COMPRESSED) { + if (style != COMPRESSED) + { return true; } // output style compressed - if (c->is_important()) { + if (c->is_important()) + { return true; } // not printable return false; }; - bool isPrintable(Block_Obj b, Sass_Output_Style style) { - if (!b) { + bool isPrintable(Block_Obj b, Sass_Output_Style style) + { + if (!b) + { return false; } - for (size_t i = 0, L = b->length(); i < L; ++i) { + for (size_t i = 0, L = b->length(); i < L; ++i) + { Statement_Obj stm = b->at(i); - if (Cast(stm) || Cast(stm)) { + if (Cast(stm) || Cast(stm)) + { return true; } - else if (Comment_Ptr c = Cast(stm)) { - if (isPrintable(c, style)) { + else if (Comment_Ptr c = Cast(stm)) + { + if (isPrintable(c, style)) + { return true; } } - else if (Ruleset_Ptr r = Cast(stm)) { - if (isPrintable(r, style)) { + else if (Ruleset_Ptr r = Cast(stm)) + { + if (isPrintable(r, style)) + { return true; } } - else if (Supports_Block_Ptr f = Cast(stm)) { - if (isPrintable(f, style)) { + else if (Supports_Block_Ptr f = Cast(stm)) + { + if (isPrintable(f, style)) + { return true; } } - else if (Media_Block_Ptr m = Cast(stm)) { - if (isPrintable(m, style)) { + else if (Media_Block_Ptr m = Cast(stm)) + { + if (isPrintable(m, style)) + { return true; } } - else if (Has_Block_Ptr b = Cast(stm)) { - if (isPrintable(b->block(), style)) { + else if (Has_Block_Ptr b = Cast(stm)) + { + if (isPrintable(b->block(), style)) + { return true; } } @@ -636,9 +771,9 @@ namespace Sass { return false; } - bool isAscii(const char chr) { + bool isAscii(const char chr) + { return unsigned(chr) < 128; } - } } diff --git a/src/util.hpp b/src/util.hpp index ceed7d7253..da01ea20b4 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -8,20 +8,23 @@ #include "sass/base.h" #include "ast_fwd_decl.hpp" -#define SASS_ASSERT(cond, msg) assert(cond && msg) +#define SASS_ASSERT(cond, msg) assert(cond&& msg) -namespace Sass { +namespace Sass +{ - #define out_of_memory() do { \ - std::cerr << "Out of memory.\n"; \ - exit(EXIT_FAILURE); \ - } while (0) +#define out_of_memory() \ + do \ + { \ + std::cerr << "Out of memory.\n"; \ + exit(EXIT_FAILURE); \ + } while (0) double round(double val, size_t precision = 0); double sass_atof(const char* str); - const char* safe_str(const char *, const char* = ""); - void free_string_array(char **); - char **copy_strings(const std::vector&, char ***, int = 0); + const char* safe_str(const char*, const char* = ""); + void free_string_array(char**); + char** copy_strings(const std::vector&, char***, int = 0); std::string read_css_string(const std::string& str); std::string evacuate_escapes(const std::string& str); std::string string_to_output(const std::string& str); @@ -37,7 +40,8 @@ namespace Sass { bool peek_linefeed(const char* start); - namespace Util { + namespace Util + { std::string rtrim(const std::string& str); @@ -53,7 +57,6 @@ namespace Sass { bool isPrintable(String_Quoted_Ptr s, Sass_Output_Style style = NESTED); bool isPrintable(Declaration_Ptr d, Sass_Output_Style style = NESTED); bool isAscii(const char chr); - } } #endif diff --git a/src/values.cpp b/src/values.cpp index 0f2fd48d73..148ba00165 100644 --- a/src/values.cpp +++ b/src/values.cpp @@ -4,10 +4,11 @@ #include -namespace Sass { +namespace Sass +{ // convert value from C++ side to C-API - union Sass_Value* ast_node_to_sass_value (const Expression_Ptr val) + union Sass_Value* ast_node_to_sass_value(const Expression_Ptr val) { if (val->concrete_type() == Expression::NUMBER) { @@ -23,7 +24,8 @@ namespace Sass { { List_Ptr_Const l = Cast(val); union Sass_Value* list = sass_make_list(l->size(), l->separator(), l->is_bracketed()); - for (size_t i = 0, L = l->length(); i < L; ++i) { + for (size_t i = 0, L = l->length(); i < L; ++i) + { Expression_Obj obj = l->at(i); auto val = ast_node_to_sass_value(obj); sass_list_set_value(list, i, val); @@ -34,10 +36,12 @@ namespace Sass { { Map_Ptr_Const m = Cast(val); union Sass_Value* map = sass_make_map(m->length()); - size_t i = 0; for (Expression_Obj key : m->keys()) { + size_t i = 0; + for (Expression_Obj key : m->keys()) + { sass_map_set_key(map, i, ast_node_to_sass_value(key)); sass_map_set_value(map, i, ast_node_to_sass_value(m->at(key))); - ++ i; + ++i; } return map; } @@ -65,67 +69,54 @@ namespace Sass { } // convert value from C-API to C++ side - Value_Ptr sass_value_to_ast_node (const union Sass_Value* val) + Value_Ptr sass_value_to_ast_node(const union Sass_Value* val) { - switch (sass_value_get_tag(val)) { - case SASS_NUMBER: - return SASS_MEMORY_NEW(Number, - ParserState("[C-VALUE]"), - sass_number_get_value(val), - sass_number_get_unit(val)); - case SASS_BOOLEAN: - return SASS_MEMORY_NEW(Boolean, - ParserState("[C-VALUE]"), - sass_boolean_get_value(val)); - case SASS_COLOR: - return SASS_MEMORY_NEW(Color, - ParserState("[C-VALUE]"), - sass_color_get_r(val), - sass_color_get_g(val), - sass_color_get_b(val), - sass_color_get_a(val)); - case SASS_STRING: - if (sass_string_is_quoted(val)) { - return SASS_MEMORY_NEW(String_Quoted, - ParserState("[C-VALUE]"), - sass_string_get_value(val)); - } - return SASS_MEMORY_NEW(String_Constant, - ParserState("[C-VALUE]"), - sass_string_get_value(val)); - case SASS_LIST: { - List_Ptr l = SASS_MEMORY_NEW(List, - ParserState("[C-VALUE]"), - sass_list_get_length(val), - sass_list_get_separator(val)); - for (size_t i = 0, L = sass_list_get_length(val); i < L; ++i) { - l->append(sass_value_to_ast_node(sass_list_get_value(val, i))); - } - l->is_bracketed(sass_list_get_is_bracketed(val)); - return l; + switch (sass_value_get_tag(val)) + { + case SASS_NUMBER: + return SASS_MEMORY_NEW(Number, ParserState("[C-VALUE]"), sass_number_get_value(val), + sass_number_get_unit(val)); + case SASS_BOOLEAN: + return SASS_MEMORY_NEW(Boolean, ParserState("[C-VALUE]"), sass_boolean_get_value(val)); + case SASS_COLOR: + return SASS_MEMORY_NEW(Color, ParserState("[C-VALUE]"), sass_color_get_r(val), + sass_color_get_g(val), sass_color_get_b(val), sass_color_get_a(val)); + case SASS_STRING: + if (sass_string_is_quoted(val)) + { + return SASS_MEMORY_NEW(String_Quoted, ParserState("[C-VALUE]"), sass_string_get_value(val)); + } + return SASS_MEMORY_NEW(String_Constant, ParserState("[C-VALUE]"), sass_string_get_value(val)); + case SASS_LIST: + { + List_Ptr l = SASS_MEMORY_NEW(List, ParserState("[C-VALUE]"), sass_list_get_length(val), + sass_list_get_separator(val)); + for (size_t i = 0, L = sass_list_get_length(val); i < L; ++i) + { + l->append(sass_value_to_ast_node(sass_list_get_value(val, i))); } - case SASS_MAP: { - Map_Ptr m = SASS_MEMORY_NEW(Map, ParserState("[C-VALUE]")); - for (size_t i = 0, L = sass_map_get_length(val); i < L; ++i) { - *m << std::make_pair( - sass_value_to_ast_node(sass_map_get_key(val, i)), - sass_value_to_ast_node(sass_map_get_value(val, i))); - } - return m; + l->is_bracketed(sass_list_get_is_bracketed(val)); + return l; + } + case SASS_MAP: + { + Map_Ptr m = SASS_MEMORY_NEW(Map, ParserState("[C-VALUE]")); + for (size_t i = 0, L = sass_map_get_length(val); i < L; ++i) + { + *m << std::make_pair(sass_value_to_ast_node(sass_map_get_key(val, i)), + sass_value_to_ast_node(sass_map_get_value(val, i))); } - case SASS_NULL: - return SASS_MEMORY_NEW(Null, ParserState("[C-VALUE]")); - case SASS_ERROR: - return SASS_MEMORY_NEW(Custom_Error, - ParserState("[C-VALUE]"), - sass_error_get_message(val)); - case SASS_WARNING: - return SASS_MEMORY_NEW(Custom_Warning, - ParserState("[C-VALUE]"), - sass_warning_get_message(val)); - default: break; + return m; + } + case SASS_NULL: + return SASS_MEMORY_NEW(Null, ParserState("[C-VALUE]")); + case SASS_ERROR: + return SASS_MEMORY_NEW(Custom_Error, ParserState("[C-VALUE]"), sass_error_get_message(val)); + case SASS_WARNING: + return SASS_MEMORY_NEW(Custom_Warning, ParserState("[C-VALUE]"), sass_warning_get_message(val)); + default: + break; } return 0; } - } diff --git a/src/values.hpp b/src/values.hpp index f78ca12811..9e9aad8995 100644 --- a/src/values.hpp +++ b/src/values.hpp @@ -3,10 +3,10 @@ #include "ast.hpp" -namespace Sass { - - union Sass_Value* ast_node_to_sass_value (const Expression_Ptr val); - Value_Ptr sass_value_to_ast_node (const union Sass_Value* val); +namespace Sass +{ + union Sass_Value* ast_node_to_sass_value(const Expression_Ptr val); + Value_Ptr sass_value_to_ast_node(const union Sass_Value* val); } #endif diff --git a/test/test_node.cpp b/test/test_node.cpp index 905dc18991..ec51dc4829 100644 --- a/test/test_node.cpp +++ b/test/test_node.cpp @@ -5,41 +5,42 @@ #include "parser.hpp" -#define STATIC_ARRAY_SIZE(array) (sizeof((array))/sizeof((array[0]))) +#define STATIC_ARRAY_SIZE(array) (sizeof((array)) / sizeof((array[0]))) -namespace Sass { +namespace Sass +{ Context ctx = Context::Data(); - const char* const ROUNDTRIP_TESTS[] = { - NULL, - "~", - "CMPD", - "~ CMPD", - "CMPD >", - "> > CMPD", - "CMPD ~ ~", - "> + CMPD1.CMPD2 > ~", - "> + CMPD1.CMPD2 CMPD3.CMPD4 > ~", - "+ CMPD1 CMPD2 ~ CMPD3 + CMPD4 > CMPD5 > ~" - }; + const char* const ROUNDTRIP_TESTS[] = { NULL, + "~", + "CMPD", + "~ CMPD", + "CMPD >", + "> > CMPD", + "CMPD ~ ~", + "> + CMPD1.CMPD2 > ~", + "> + CMPD1.CMPD2 CMPD3.CMPD4 > ~", + "+ CMPD1 CMPD2 ~ CMPD3 + CMPD4 > CMPD5 > ~" }; - - static Complex_Selector* createComplexSelector(std::string src) { + static Complex_Selector* createComplexSelector(std::string src) + { std::string temp(src); temp += ";"; return (*Parser::from_c_str(temp.c_str(), ctx, "", Position()).parse_selector_list())[0]; } - void roundtripTest(const char* toTest) { + void roundtripTest(const char* toTest) + { // Create the initial selector Complex_Selector* pOrigSelector = NULL; - if (toTest) { + if (toTest) + { pOrigSelector = createComplexSelector(toTest); } @@ -67,21 +68,23 @@ namespace Sass { // Test that they are equal using the equality operator - assert( (!pOrigSelector && !pNewSelector ) || (pOrigSelector && pNewSelector) ); - if (pOrigSelector) { - assert( *pOrigSelector == *pNewSelector ); + assert((!pOrigSelector && !pNewSelector) || (pOrigSelector && pNewSelector)); + if (pOrigSelector) + { + assert(*pOrigSelector == *pNewSelector); } // Test that they are equal by comparing the string versions of the selectors assert(expected == result); - } - int main() { - for (int index = 0; index < STATIC_ARRAY_SIZE(ROUNDTRIP_TESTS); index++) { + int main() + { + for (int index = 0; index < STATIC_ARRAY_SIZE(ROUNDTRIP_TESTS); index++) + { const char* const toTest = ROUNDTRIP_TESTS[index]; cout << "\nINPUT STRING: " << (toTest ? toTest : "NULL") << endl; roundtripTest(toTest); @@ -89,6 +92,4 @@ namespace Sass { cout << "\nTesting Done.\n"; } - - } diff --git a/test/test_paths.cpp b/test/test_paths.cpp index bfcf8ec6dc..35421cb10a 100644 --- a/test/test_paths.cpp +++ b/test/test_paths.cpp @@ -3,8 +3,7 @@ using namespace Sass; -template -std::vector& operator<<(std::vector& v, const T& e) +template std::vector& operator<<(std::vector& v, const T& e) { v.push_back(e); return v; @@ -17,11 +16,12 @@ int main() v2 << 3; v3 << 4 << 5 << 6; - std::vector > ss; + std::vector> ss; ss << v1 << v2 << v3; - std::vector > ps = paths(ss); - for (size_t i = 0, S = ps.size(); i < S; ++i) { + std::vector> ps = paths(ss); + for (size_t i = 0, S = ps.size(); i < S; ++i) + { std::cout << vector_to_string(ps[i]) << std::endl; } return 0; diff --git a/test/test_selector_difference.cpp b/test/test_selector_difference.cpp index e2880c0b08..f6e1db364d 100644 --- a/test/test_selector_difference.cpp +++ b/test/test_selector_difference.cpp @@ -9,11 +9,14 @@ using namespace Sass; Context ctx = Context::Data(); Compound_Selector* selector(std::string src) -{ return Parser::from_c_str(src.c_str(), ctx, "", Position()).parse_compound_selector(); } +{ + return Parser::from_c_str(src.c_str(), ctx, "", Position()).parse_compound_selector(); +} void diff(std::string s, std::string t) { - std::cout << s << " - " << t << " = " << selector(s + ";")->minus(selector(t + ";"), ctx)->to_string() << std::endl; + std::cout << s << " - " << t << " = " + << selector(s + ";")->minus(selector(t + ";"), ctx)->to_string() << std::endl; } int main() diff --git a/test/test_specificity.cpp b/test/test_specificity.cpp index ba9bbfc46e..5d569256ba 100644 --- a/test/test_specificity.cpp +++ b/test/test_specificity.cpp @@ -9,10 +9,14 @@ using namespace Sass; Context ctx = Context::Data(); Selector* selector(std::string src) -{ return Parser::from_c_str(src.c_str(), ctx, "", Position()).parse_selector_list(); } +{ + return Parser::from_c_str(src.c_str(), ctx, "", Position()).parse_selector_list(); +} void spec(std::string sel) -{ std::cout << sel << "\t::\t" << selector(sel + ";")->specificity() << std::endl; } +{ + std::cout << sel << "\t::\t" << selector(sel + ";")->specificity() << std::endl; +} int main() { diff --git a/test/test_subset_map.cpp b/test/test_subset_map.cpp index 37945143f0..c31ab25c54 100644 --- a/test/test_subset_map.cpp +++ b/test/test_subset_map.cpp @@ -9,7 +9,8 @@ string toString(std::vector v); string toString(std::vector>> v); void assertEqual(string std::sExpected, std::string sResult); -void setup() { +void setup() +{ ssm.clear(); //@ssm[Set[1, 2]] = "Foo" @@ -51,16 +52,17 @@ void setup() { ssm.put(s6, "Thram"); } -void testEqualKeys() { +void testEqualKeys() +{ std::cout << "testEqualKeys" << std::endl; - //assert_equal [["Foo", Set[1, 2]]], @ssm.get(Set[1, 2]) + // assert_equal [["Foo", Set[1, 2]]], @ssm.get(Set[1, 2]) std::vector k1; k1.push_back("1"); k1.push_back("2"); assertEqual("[[Foo, Set[1, 2]]]", toString(ssm.get_kv(k1))); - //assert_equal [["Bar", Set["fizz", "fazz"]]], @ssm.get(Set["fizz", "fazz"]) + // assert_equal [["Bar", Set["fizz", "fazz"]]], @ssm.get(Set["fizz", "fazz"]) std::vector k2; k2.push_back("fizz"); k2.push_back("fazz"); @@ -69,17 +71,18 @@ void testEqualKeys() { std::cout << std::endl; } -void testSubsetKeys() { +void testSubsetKeys() +{ std::cout << "testSubsetKeys" << std::endl; - //assert_equal [["Foo", Set[1, 2]]], @ssm.get(Set[1, 2, "fuzz"]) + // assert_equal [["Foo", Set[1, 2]]], @ssm.get(Set[1, 2, "fuzz"]) std::vector k1; k1.push_back("1"); k1.push_back("2"); k1.push_back("fuzz"); assertEqual("[[Foo, Set[1, 2]]]", toString(ssm.get_kv(k1))); - //assert_equal [["Bar", Set["fizz", "fazz"]]], @ssm.get(Set["fizz", "fazz", 3]) + // assert_equal [["Bar", Set["fizz", "fazz"]]], @ssm.get(Set["fizz", "fazz", 3]) std::vector k2; k2.push_back("fizz"); k2.push_back("fazz"); @@ -89,25 +92,26 @@ void testSubsetKeys() { std::cout << std::endl; } -void testSupersetKeys() { +void testSupersetKeys() +{ std::cout << "testSupersetKeys" << std::endl; - //assert_equal [], @ssm.get(Set[1]) + // assert_equal [], @ssm.get(Set[1]) std::vector k1; k1.push_back("1"); assertEqual("[]", toString(ssm.get_kv(k1))); - //assert_equal [], @ssm.get(Set[2]) + // assert_equal [], @ssm.get(Set[2]) std::vector k2; k2.push_back("2"); assertEqual("[]", toString(ssm.get_kv(k2))); - //assert_equal [], @ssm.get(Set["fizz"]) + // assert_equal [], @ssm.get(Set["fizz"]) std::vector k3; k3.push_back("fizz"); assertEqual("[]", toString(ssm.get_kv(k3))); - //assert_equal [], @ssm.get(Set["fazz"]) + // assert_equal [], @ssm.get(Set["fazz"]) std::vector k4; k4.push_back("fazz"); assertEqual("[]", toString(ssm.get_kv(k4))); @@ -115,22 +119,23 @@ void testSupersetKeys() { std::cout << std::endl; } -void testDisjointKeys() { +void testDisjointKeys() +{ std::cout << "testDisjointKeys" << std::endl; - //assert_equal [], @ssm.get(Set[3, 4]) + // assert_equal [], @ssm.get(Set[3, 4]) std::vector k1; k1.push_back("3"); k1.push_back("4"); assertEqual("[]", toString(ssm.get_kv(k1))); - //assert_equal [], @ssm.get(Set["fuzz", "frizz"]) + // assert_equal [], @ssm.get(Set["fuzz", "frizz"]) std::vector k2; k2.push_back("fuzz"); k2.push_back("frizz"); assertEqual("[]", toString(ssm.get_kv(k2))); - //assert_equal [], @ssm.get(Set["gran", 15]) + // assert_equal [], @ssm.get(Set["gran", 15]) std::vector k3; k3.push_back("gran"); k3.push_back("15"); @@ -139,22 +144,23 @@ void testDisjointKeys() { std::cout << std::endl; } -void testSemiDisjointKeys() { +void testSemiDisjointKeys() +{ std::cout << "testSemiDisjointKeys" << std::endl; - //assert_equal [], @ssm.get(Set[2, 3]) + // assert_equal [], @ssm.get(Set[2, 3]) std::vector k1; k1.push_back("2"); k1.push_back("3"); assertEqual("[]", toString(ssm.get_kv(k1))); - //assert_equal [], @ssm.get(Set["fizz", "fuzz"]) + // assert_equal [], @ssm.get(Set["fizz", "fuzz"]) std::vector k2; k2.push_back("fizz"); k2.push_back("fuzz"); assertEqual("[]", toString(ssm.get_kv(k2))); - //assert_equal [], @ssm.get(Set[1, "fazz"]) + // assert_equal [], @ssm.get(Set[1, "fazz"]) std::vector k3; k3.push_back("1"); k3.push_back("fazz"); @@ -163,32 +169,38 @@ void testSemiDisjointKeys() { std::cout << std::endl; } -void testEmptyKeySet() { +void testEmptyKeySet() +{ std::cout << "testEmptyKeySet" << std::endl; - //assert_raises(ArgumentError) {@ssm[Set[]] = "Fail"} + // assert_raises(ArgumentError) {@ssm[Set[]] = "Fail"} std::vector s1; - try { + try + { ssm.put(s1, "Fail"); } - catch (const char* &e) { + catch (const char*& e) + { assertEqual("internal error: subset map keys may not be empty", e); } } -void testEmptyKeyGet() { +void testEmptyKeyGet() +{ std::cout << "testEmptyKeyGet" << std::endl; - //assert_equal [], @ssm.get(Set[]) + // assert_equal [], @ssm.get(Set[]) std::vector k1; assertEqual("[]", toString(ssm.get_kv(k1))); std::cout << std::endl; } -void testMultipleSubsets() { +void testMultipleSubsets() +{ std::cout << "testMultipleSubsets" << std::endl; - //assert_equal [["Foo", Set[1, 2]], ["Bar", Set["fizz", "fazz"]]], @ssm.get(Set[1, 2, "fizz", "fazz"]) + // assert_equal [["Foo", Set[1, 2]], ["Bar", Set["fizz", "fazz"]]], @ssm.get(Set[1, 2, "fizz", + // "fazz"]) std::vector k1; k1.push_back("1"); k1.push_back("2"); @@ -196,7 +208,8 @@ void testMultipleSubsets() { k1.push_back("fazz"); assertEqual("[[Foo, Set[1, 2]], [Bar, Set[fizz, fazz]]]", toString(ssm.get_kv(k1))); - //assert_equal [["Foo", Set[1, 2]], ["Bar", Set["fizz", "fazz"]]], @ssm.get(Set[1, 2, 3, "fizz", "fazz", "fuzz"]) + // assert_equal [["Foo", Set[1, 2]], ["Bar", Set["fizz", "fazz"]]], @ssm.get(Set[1, 2, 3, "fizz", + // "fazz", "fuzz"]) std::vector k2; k2.push_back("1"); k2.push_back("2"); @@ -206,13 +219,14 @@ void testMultipleSubsets() { k2.push_back("fuzz"); assertEqual("[[Foo, Set[1, 2]], [Bar, Set[fizz, fazz]]]", toString(ssm.get_kv(k2))); - //assert_equal [["Baz", Set[:foo, :bar]]], @ssm.get(Set[:foo, :bar]) + // assert_equal [["Baz", Set[:foo, :bar]]], @ssm.get(Set[:foo, :bar]) std::vector k3; k3.push_back(":foo"); k3.push_back(":bar"); assertEqual("[[Baz, Set[:foo, :bar]]]", toString(ssm.get_kv(k3))); - //assert_equal [["Baz", Set[:foo, :bar]], ["Bang", Set[:foo, :bar, :baz]]], @ssm.get(Set[:foo, :bar, :baz]) + // assert_equal [["Baz", Set[:foo, :bar]], ["Bang", Set[:foo, :bar, :baz]]], @ssm.get(Set[:foo, + // :bar, :baz]) std::vector k4; k4.push_back(":foo"); k4.push_back(":bar"); @@ -221,17 +235,18 @@ void testMultipleSubsets() { std::cout << std::endl; } -void testBracketBracket() { +void testBracketBracket() +{ std::cout << "testBracketBracket" << std::endl; - //assert_equal ["Foo"], @ssm[Set[1, 2, "fuzz"]] + // assert_equal ["Foo"], @ssm[Set[1, 2, "fuzz"]] std::vector k1; k1.push_back("1"); k1.push_back("2"); k1.push_back("fuzz"); assertEqual("[Foo]", toString(ssm.get_v(k1))); - //assert_equal ["Baz", "Bang"], @ssm[Set[:foo, :bar, :baz]] + // assert_equal ["Baz", "Bang"], @ssm[Set[:foo, :bar, :baz]] std::vector k2; k2.push_back(":foo"); k2.push_back(":bar"); @@ -241,10 +256,11 @@ void testBracketBracket() { std::cout << std::endl; } -void testKeyOrder() { +void testKeyOrder() +{ std::cout << "testEqualKeys" << std::endl; - //assert_equal [["Foo", Set[1, 2]]], @ssm.get(Set[2, 1]) + // assert_equal [["Foo", Set[1, 2]]], @ssm.get(Set[2, 1]) std::vector k1; k1.push_back("2"); k1.push_back("1"); @@ -253,7 +269,8 @@ void testKeyOrder() { std::cout << std::endl; } -void testOrderPreserved() { +void testOrderPreserved() +{ std::cout << "testOrderPreserved" << std::endl; //@ssm[Set[10, 11, 12]] = 1 std::vector s1; @@ -294,18 +311,22 @@ void testOrderPreserved() { s6.push_back("13"); ssm.put(s6, "6"); - //assert_equal([[1, Set[10, 11, 12]], [2, Set[10, 11]], [3, Set[11]], [4, Set[11, 12]], [5, Set[9, 10, 11, 12, 13]], [6, Set[10, 13]]], @ssm.get(Set[9, 10, 11, 12, 13])) + // assert_equal([[1, Set[10, 11, 12]], [2, Set[10, 11]], [3, Set[11]], [4, Set[11, 12]], [5, + // Set[9, 10, 11, 12, 13]], [6, Set[10, 13]]], @ssm.get(Set[9, 10, 11, 12, 13])) std::vector k1; k1.push_back("9"); k1.push_back("10"); k1.push_back("11"); k1.push_back("12"); k1.push_back("13"); - assertEqual("[[1, Set[10, 11, 12]], [2, Set[10, 11]], [3, Set[11]], [4, Set[11, 12]], [5, Set[9, 10, 11, 12, 13]], [6, Set[10, 13]]]", toString(ssm.get_kv(k1))); + assertEqual("[[1, Set[10, 11, 12]], [2, Set[10, 11]], [3, Set[11]], [4, Set[11, 12]], [5, Set[9, " + "10, 11, 12, 13]], [6, Set[10, 13]]]", + toString(ssm.get_kv(k1))); std::cout << std::endl; } -void testMultipleEqualValues() { +void testMultipleEqualValues() +{ std::cout << "testMultipleEqualValues" << std::endl; //@ssm[Set[11, 12]] = 1 std::vector s1; @@ -331,14 +352,16 @@ void testMultipleEqualValues() { s4.push_back("15"); ssm.put(s4, "1"); - //assert_equal([[1, Set[11, 12]], [2, Set[12, 13]], [1, Set[13, 14]], [1, Set[14, 15]]], @ssm.get(Set[11, 12, 13, 14, 15])) + // assert_equal([[1, Set[11, 12]], [2, Set[12, 13]], [1, Set[13, 14]], [1, Set[14, 15]]], + // @ssm.get(Set[11, 12, 13, 14, 15])) std::vector k1; k1.push_back("11"); k1.push_back("12"); k1.push_back("13"); k1.push_back("14"); k1.push_back("15"); - assertEqual("[[1, Set[11, 12]], [2, Set[12, 13]], [1, Set[13, 14]], [1, Set[14, 15]]]", toString(ssm.get_kv(k1))); + assertEqual("[[1, Set[11, 12]], [2, Set[12, 13]], [1, Set[13, 14]], [1, Set[14, 15]]]", + toString(ssm.get_kv(k1))); std::cout << std::endl; } @@ -366,10 +389,11 @@ int main() s4.push_back("2"); s4.push_back("3"); - std::vector > > fetched(ssm.get_kv(s4)); + std::vector>> fetched(ssm.get_kv(s4)); std::cout << "PRINTING RESULTS:" << std::endl; - for (size_t i = 0, S = fetched.size(); i < S; ++i) { + for (size_t i = 0, S = fetched.size(); i < S; ++i) + { std::cout << fetched[i].first << std::endl; } @@ -378,10 +402,11 @@ int main() ssm2.put(s2, "bar"); ssm2.put(s4, "hux"); - std::vector > > fetched2(ssm2.get_kv(s4)); + std::vector>> fetched2(ssm2.get_kv(s4)); std::cout << std::endl << "PRINTING RESULTS:" << std::endl; - for (size_t i = 0, S = fetched2.size(); i < S; ++i) { + for (size_t i = 0, S = fetched2.size(); i < S; ++i) + { std::cout << fetched2[i].first << std::endl; } @@ -398,9 +423,10 @@ int main() actual.push_back(".mine"); sel_ssm.put(target, "has-aquarium"); - std::vector > > fetched3(sel_ssm.get_kv(actual)); + std::vector>> fetched3(sel_ssm.get_kv(actual)); std::cout << "RESULTS:" << std::endl; - for (size_t i = 0, S = fetched3.size(); i < S; ++i) { + for (size_t i = 0, S = fetched3.size(); i < S; ++i) + { std::cout << fetched3[i].first << std::endl; } @@ -433,17 +459,21 @@ string toString(std::vector>> v) { std::stringstream buffer; buffer << "["; - for (size_t i = 0, S = v.size(); i < S; ++i) { + for (size_t i = 0, S = v.size(); i < S; ++i) + { buffer << "[" << v[i].first; buffer << ", Set["; - for (size_t j = 0, S = v[i].second.size(); j < S; ++j) { + for (size_t j = 0, S = v[i].second.size(); j < S; ++j) + { buffer << v[i].second[j]; - if (j < S-1) { + if (j < S - 1) + { buffer << ", "; } } buffer << "]]"; - if (i < S-1) { + if (i < S - 1) + { buffer << ", "; } } @@ -455,9 +485,11 @@ string toString(std::vector v) { std::stringstream buffer; buffer << "["; - for (size_t i = 0, S = v.size(); i < S; ++i) { + for (size_t i = 0, S = v.size(); i < S; ++i) + { buffer << v[i]; - if (i < S-1) { + if (i < S - 1) + { buffer << ", "; } } @@ -465,7 +497,8 @@ string toString(std::vector v) return buffer.str(); } -void assertEqual(string sExpected, string sResult) { +void assertEqual(string sExpected, string sResult) +{ std::cout << "Expected: " << sExpected << std::endl; std::cout << "Result: " << sResult << std::endl; assert(sExpected == sResult); diff --git a/test/test_superselector.cpp b/test/test_superselector.cpp index bf21c7c4d7..9e00c22e86 100644 --- a/test/test_superselector.cpp +++ b/test/test_superselector.cpp @@ -8,31 +8,25 @@ using namespace Sass; Context ctx = Context(Context::Data()); Compound_Selector* compound_selector(std::string src) -{ return Parser::from_c_str(src.c_str(), ctx, "", Position()).parse_compound_selector(); } +{ + return Parser::from_c_str(src.c_str(), ctx, "", Position()).parse_compound_selector(); +} Complex_Selector* complex_selector(std::string src) -{ return Parser::from_c_str(src.c_str(), ctx, "", Position()).parse_complex_selector(false); } +{ + return Parser::from_c_str(src.c_str(), ctx, "", Position()).parse_complex_selector(false); +} void check_compound(std::string s1, std::string s2) { - std::cout << "Is " - << s1 - << " a superselector of " - << s2 - << "?\t" - << compound_selector(s1 + ";")->is_superselector_of(compound_selector(s2 + ";")) - << std::endl; + std::cout << "Is " << s1 << " a superselector of " << s2 << "?\t" + << compound_selector(s1 + ";")->is_superselector_of(compound_selector(s2 + ";")) << std::endl; } void check_complex(std::string s1, std::string s2) { - std::cout << "Is " - << s1 - << " a superselector of " - << s2 - << "?\t" - << complex_selector(s1 + ";")->is_superselector_of(complex_selector(s2 + ";")) - << std::endl; + std::cout << "Is " << s1 << " a superselector of " << s2 << "?\t" + << complex_selector(s1 + ";")->is_superselector_of(complex_selector(s2 + ";")) << std::endl; } int main() @@ -65,5 +59,3 @@ int main() return 0; } - - diff --git a/test/test_unification.cpp b/test/test_unification.cpp index 5c663ee90f..b5f221d83e 100644 --- a/test/test_unification.cpp +++ b/test/test_unification.cpp @@ -8,12 +8,15 @@ using namespace Sass; Context ctx = Context(Context::Data()); Compound_Selector* selector(std::string src) -{ return Parser::from_c_str(src.c_str(), ctx, "", Position()).parse_compound_selector(); } +{ + return Parser::from_c_str(src.c_str(), ctx, "", Position()).parse_compound_selector(); +} void unify(std::string lhs, std::string rhs) { Compound_Selector* unified = selector(lhs + ";")->unify_with(selector(rhs + ";"), ctx); - std::cout << lhs << " UNIFIED WITH " << rhs << " =\t" << (unified ? unified->to_string() : "NOTHING") << std::endl; + std::cout << lhs << " UNIFIED WITH " << rhs << " =\t" + << (unified ? unified->to_string() : "NOTHING") << std::endl; } int main()