diff --git a/ast.cpp b/ast.cpp index 61eca23c35..4cf7bf3faf 100644 --- a/ast.cpp +++ b/ast.cpp @@ -422,40 +422,40 @@ namespace Sass { // catch-all return false; } - + Selector_List* Complex_Selector::unify_with(Complex_Selector* other, Context& ctx) { To_String to_string; - + Compound_Selector* thisBase = base(); Compound_Selector* rhsBase = other->base(); - + if( thisBase == 0 || rhsBase == 0 ) return 0; - + // Not sure about this check, but closest way I could check to see if this is a ruby 'SimpleSequence' equivalent if( tail()->combinator() != Combinator::ANCESTOR_OF || other->tail()->combinator() != Combinator::ANCESTOR_OF ) return 0; - + Compound_Selector* unified = rhsBase->unify_with(thisBase, ctx); if( unified == 0 ) return 0; - + Node lhsNode = complexSelectorToNode(this, ctx); Node rhsNode = complexSelectorToNode(other, ctx); - + // Create a temp Complex_Selector, turn it into a Node, and combine it with the existing RHS node Complex_Selector* fakeComplexSelector = new (ctx.mem) Complex_Selector(ParserState("[NODE]"), Complex_Selector::ANCESTOR_OF, unified, NULL); Node unifiedNode = complexSelectorToNode(fakeComplexSelector, ctx); rhsNode.plus(unifiedNode); - + Node node = Extend::subweave(lhsNode, rhsNode, ctx); - + Selector_List* result = new (ctx.mem) Selector_List(pstate()); for (NodeDeque::iterator iter = node.collection()->begin(), iterEnd = node.collection()->end(); iter != iterEnd; iter++) { Node childNode = *iter; childNode = Node::naiveTrim(childNode, ctx); - + Complex_Selector* childNodeAsComplexSelector = nodeToComplexSelector(childNode, ctx); if( childNodeAsComplexSelector ) { (*result) << childNodeAsComplexSelector; } } - + return result->length() ? result : 0; } @@ -597,16 +597,15 @@ namespace Sass { } return false; } - + Selector_List* Selector_List::unify_with(Selector_List* rhs, Context& ctx) { - 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) { Complex_Selector* seq1 = (*this)[lhs_i]; for(size_t rhs_i = 0, rhs_L = rhs->length(); rhs_i < rhs_L; ++rhs_i) { Complex_Selector* seq2 = (*rhs)[rhs_i]; - + Selector_List* result = seq1->unify_with(seq2, ctx); if( result ) { for(size_t i = 0, L = result->length(); i < L; ++i) { @@ -615,24 +614,23 @@ namespace Sass { } } } - + // Creates the final Selector_List by combining all the complex selectors Selector_List* final_result = new (ctx.mem) Selector_List(pstate()); for (auto itr = unified_complex_selectors.begin(); itr != unified_complex_selectors.end(); ++itr) { *final_result << *itr; } - return final_result; } - + void Selector_List::populate_extends(Selector_List* extendee, Context& ctx, ExtensionSubsetMap& extends) { To_String to_string; - + Selector_List* extender = this; for (auto complex_sel : extendee->elements()) { Complex_Selector* c = complex_sel; - - + + // Ignore any parent selectors, until we find the first non Selector_Reference head Compound_Selector* compound_sel = c->head(); Complex_Selector* pIter = complex_sel; @@ -642,63 +640,21 @@ namespace Sass { compound_sel = pHead; break; } - + pIter = 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) { - // let's test this out - cerr << "REGISTERING EXTENSION REQUEST: " << (*extender)[i]->perform(&to_string) << " <- " << compound_sel->perform(&to_string) << endl; extends.put(compound_sel->to_str_vec(), make_pair((*extender)[i], compound_sel)); } } }; - - - /* not used anymore - remove? - Selector_Placeholder* Selector_List::find_placeholder() - { - if (has_placeholder()) { - for (size_t i = 0, L = length(); i < L; ++i) { - if ((*this)[i]->has_placeholder()) return (*this)[i]->find_placeholder(); - } - } - return 0; - }*/ - - /* not used anymore - remove? - Selector_Placeholder* Complex_Selector::find_placeholder() - { - if (has_placeholder()) { - if (head() && head()->has_placeholder()) return head()->find_placeholder(); - else if (tail() && tail()->has_placeholder()) return tail()->find_placeholder(); - } - return 0; - }*/ - - /* not used anymore - remove? - Selector_Placeholder* Compound_Selector::find_placeholder() - { - if (has_placeholder()) { - for (size_t i = 0, L = length(); i < L; ++i) { - if ((*this)[i]->has_placeholder()) return (*this)[i]->find_placeholder(); - } - // return this; - } - return 0; - }*/ - - /* not used anymore - remove? - Selector_Placeholder* Selector_Placeholder::find_placeholder() - { - return this; - }*/ vector Compound_Selector::to_str_vec() { diff --git a/ast.hpp b/ast.hpp index 302c862d44..4140f78f96 100644 --- a/ast.hpp +++ b/ast.hpp @@ -272,7 +272,7 @@ namespace Sass { RULESET, MEDIA, DIRECTIVE, - FEATURE, + SUPPORTS, ATROOT, BUBBLE, KEYFRAMERULE @@ -398,16 +398,16 @@ namespace Sass { ATTACH_OPERATIONS() }; - /////////////////// - // Feature queries. - /////////////////// - class Feature_Block : public Has_Block { - ADD_PROPERTY(Feature_Query*, feature_queries) + ////////////////// + // Query features. + ////////////////// + class Supports_Block : public Has_Block { + ADD_PROPERTY(Supports_Query*, queries) ADD_PROPERTY(Selector*, selector) public: - Feature_Block(ParserState pstate, Feature_Query* fqs, Block* b) - : Has_Block(pstate, b), feature_queries_(fqs), selector_(0) - { statement_type(FEATURE); } + Supports_Block(ParserState pstate, Supports_Query* queries = 0, Block* block = 0) + : Has_Block(pstate, block), queries_(queries), selector_(0) + { statement_type(SUPPORTS); } bool is_hoistable() { return true; } bool bubbles() { return true; } ATTACH_OPERATIONS() @@ -663,7 +663,6 @@ namespace Sass { ADD_PROPERTY(Native_Function, native_function) ADD_PROPERTY(Sass_Function_Entry, c_function) ADD_PROPERTY(void*, cookie) - ADD_PROPERTY(Context*, ctx) ADD_PROPERTY(bool, is_overload_stub) ADD_PROPERTY(Signature, signature) public: @@ -671,7 +670,6 @@ namespace Sass { string n, Parameters* params, Block* b, - Context* ctx, Type t) : Has_Block(pstate, b), name_(n), @@ -681,7 +679,6 @@ namespace Sass { native_function_(0), c_function_(0), cookie_(0), - ctx_(ctx), is_overload_stub_(false), signature_(0) { } @@ -690,7 +687,6 @@ namespace Sass { string n, Parameters* params, Native_Function func_ptr, - Context* ctx, bool overload_stub = false) : Has_Block(pstate, 0), name_(n), @@ -700,7 +696,6 @@ namespace Sass { native_function_(func_ptr), c_function_(0), cookie_(0), - ctx_(ctx), is_overload_stub_(overload_stub), signature_(sig) { } @@ -709,7 +704,6 @@ namespace Sass { string n, Parameters* params, Sass_Function_Entry c_func, - Context* ctx, bool whatever, bool whatever2) : Has_Block(pstate, 0), @@ -720,7 +714,6 @@ namespace Sass { native_function_(0), c_function_(c_func), cookie_(sass_function_get_cookie(c_func)), - ctx_(ctx), is_overload_stub_(false), signature_(sig) { } @@ -1472,10 +1465,10 @@ namespace Sass { /////////////////// // Feature queries. /////////////////// - class Feature_Query : public Expression, public Vectorized { + class Supports_Query : public Expression, public Vectorized { public: - Feature_Query(ParserState pstate, size_t s = 0) - : Expression(pstate), Vectorized(s) + Supports_Query(ParserState pstate, size_t s = 0) + : Expression(pstate), Vectorized(s) { } ATTACH_OPERATIONS() }; @@ -1483,7 +1476,7 @@ namespace Sass { //////////////////////////////////////////////////////// // Feature expressions (for use inside feature queries). //////////////////////////////////////////////////////// - class Feature_Query_Condition : public Expression, public Vectorized { + class Supports_Condition : public Expression, public Vectorized { public: enum Operand { NONE, AND, OR, NOT }; private: @@ -1492,9 +1485,9 @@ namespace Sass { ADD_PROPERTY(Operand, operand) ADD_PROPERTY(bool, is_root) public: - Feature_Query_Condition(ParserState pstate, size_t s = 0, String* f = 0, + Supports_Condition(ParserState pstate, size_t s = 0, String* f = 0, Expression* v = 0, Operand o = NONE, bool r = false) - : Expression(pstate), Vectorized(s), + : Expression(pstate), Vectorized(s), feature_(f), value_(v), operand_(o), is_root_(r) { } ATTACH_OPERATIONS() @@ -1567,7 +1560,7 @@ namespace Sass { { return expression()->exclude("rule"); } - if (s->statement_type() == Statement::FEATURE) + if (s->statement_type() == Statement::SUPPORTS) { return expression()->exclude("supports"); } @@ -1947,7 +1940,6 @@ namespace Sass { : Selector(pstate), Vectorized(s) { } - Compound_Selector* unify_with(Compound_Selector* rhs, Context& ctx); // virtual Selector_Placeholder* find_placeholder(); Simple_Selector* base() @@ -2007,9 +1999,9 @@ namespace Sass { ADD_PROPERTY(Complex_Selector*, tail) public: Complex_Selector(ParserState pstate, - Combinator c, - Compound_Selector* h, - Complex_Selector* t) + Combinator c = ANCESTOR_OF, + Compound_Selector* h = 0, + Complex_Selector* t = 0) : Selector(pstate), combinator_(c), head_(h), tail_(t) { if ((h && h->has_reference()) || (t && t->has_reference())) has_reference(true); @@ -2023,7 +2015,7 @@ namespace Sass { bool is_superselector_of(Complex_Selector* sub); bool is_superselector_of(Selector_List* sub); // virtual Selector_Placeholder* find_placeholder(); - + Selector_List* unify_with(Complex_Selector* rhs, Context& ctx); Combinator clear_innermost(); @@ -2093,7 +2085,6 @@ namespace Sass { }; typedef deque ComplexSelectorDeque; - typedef Subset_Map > ExtensionSubsetMap; /////////////////////////////////// @@ -2117,7 +2108,7 @@ namespace Sass { Selector_List* unify_with(Selector_List*, Context&); void populate_extends(Selector_List*, Context&, ExtensionSubsetMap&); - + virtual unsigned long specificity() { unsigned long sum = 0; diff --git a/ast_factory.hpp b/ast_factory.hpp index 33646ff8b8..f4a886de86 100644 --- a/ast_factory.hpp +++ b/ast_factory.hpp @@ -15,7 +15,7 @@ namespace Sass { Block* new_Block(string p, size_t l, size_t s = 0, bool r = false); Ruleset* new_Ruleset(string p, size_t l, Selector* s, Block* b); Propset* new_Propset(string p, size_t l, String* pf, Block* b); - Feature_Query* new_Feature_Query(string p, size_t l, Feature_Query* f, Block* b); + Supports_Query* new_Supports_Query(string p, size_t l, Supports_Query* f, Block* b); Media_Query* new_Media_Query(string p, size_t l, List* q, Block* b); At_Root_Block* new_At_Root_Block(string p, size_t l, Selector* sel, Block* b); At_Rule* new_At_Rule(string p, size_t l, string kwd, Selector* sel, Block* b); @@ -67,7 +67,7 @@ namespace Sass { String_Constant* new_String_Constant(string p, size_t l, string val); String_Constant* new_String_Constant(string p, size_t l, const char* beg); String_Constant* new_String_Constant(string p, size_t l, const char* beg, const char* end); - Feature_Query_Condition* new_Feature_Query_Condition(string p, size_t l, String* f, Expression* v); + Supports_Condition* new_Supports_Condition(string p, size_t l, String* f, Expression* v); Media_Expression* new_Media_Expression(string p, size_t l, String* f, Expression* v); Parent_Selector* new_Parent_Selector(string p, size_t l, Selector* s); // parameters and arguments diff --git a/ast_fwd_decl.hpp b/ast_fwd_decl.hpp index 7da1fa7012..d5deca2ca4 100644 --- a/ast_fwd_decl.hpp +++ b/ast_fwd_decl.hpp @@ -16,7 +16,7 @@ namespace Sass { class Propset; class Bubble; class Media_Block; - class Feature_Block; + class Supports_Block; class At_Rule; class Keyframe_Rule; class At_Root_Block; @@ -56,8 +56,8 @@ namespace Sass { class String_Quoted; class Media_Query; class Media_Query_Expression; - class Feature_Query; - class Feature_Query_Condition; + class Supports_Query; + class Supports_Condition; class At_Root_Expression; class Null; class Parent_Selector; diff --git a/context.cpp b/context.cpp index 06b0e8cd20..4b7a3cef19 100644 --- a/context.cpp +++ b/context.cpp @@ -319,38 +319,55 @@ namespace Sass { 0, 0 ); import_stack.push_back(import); - Parser p(Parser::from_c_str(queue[i].source, *this, ParserState(queue[i].abs_path, queue[i].source, i))); + const char* path = sass_strdup(queue[i].abs_path.c_str()); + Parser p(Parser::from_c_str(queue[i].source, *this, ParserState(path, queue[i].source, i))); Block* ast = p.parse(); sass_delete_import(import_stack.back()); import_stack.pop_back(); if (i == 0) root = ast; + // ToDo: we store by load_path, which can lead + // to duplicates if importer reports the same path + // Maybe we should add an error for duplicates!? style_sheets[queue[i].load_path] = ast; } if (root == 0) return 0; - Env tge; + + Env global; // create root environment + // register built-in functions on env + 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]); } + // create initial backtrace entry Backtrace backtrace(0, ParserState("", 0), ""); - register_built_in_functions(*this, &tge); - for (size_t i = 0, S = c_functions.size(); i < S; ++i) { - register_c_function(*this, &tge, c_functions[i]); - } - Contextualize contextualize(*this, &tge, &backtrace); + Contextualize contextualize(*this, &global, &backtrace); Listize listize(*this); - Eval eval(*this, &contextualize, &listize, &tge, &backtrace); - Contextualize_Eval contextualize_eval(*this, &eval, &tge, &backtrace); - Expand expand(*this, &eval, &contextualize_eval, &tge, &backtrace); - Cssize cssize(*this, &tge, &backtrace); + Eval eval(*this, &contextualize, &listize, &global, &backtrace); + Contextualize_Eval contextualize_eval(*this, &eval, &global, &backtrace); + // create crtp visitor objects + Expand expand(*this, &eval, &contextualize_eval, &global, &backtrace); + Cssize cssize(*this, &backtrace); + // expand and eval the tree root = root->perform(&expand)->block(); + // merge and bubble certain rules root = root->perform(&cssize)->block(); + // should we extend something? if (!subset_map.empty()) { + // create crtp visitor object Extend extend(*this, subset_map); + // extend tree nodes root->perform(&extend); } + // clean up by removing empty placeholders + // ToDo: maybe we can do this somewhere else? Remove_Placeholders remove_placeholders(*this); root->perform(&remove_placeholders); + // return processed tree return root; } + // EO parse_file Block* Context::parse_string() { @@ -439,12 +456,11 @@ namespace Sass { void register_overload_stub(Context& ctx, string name, Env* env) { Definition* stub = new (ctx.mem) Definition(ParserState("[built-in function]"), - 0, - name, - 0, - 0, - &ctx, - true); + 0, + name, + 0, + 0, + true); (*env)[name + "[f]"] = stub; } diff --git a/contextualize_eval.cpp b/contextualize_eval.cpp index ba2b25d1d5..483bd8a252 100644 --- a/contextualize_eval.cpp +++ b/contextualize_eval.cpp @@ -30,7 +30,7 @@ namespace Sass { To_String to_string; string result_str(s->contents()->perform(eval)->perform(&to_string)); result_str += '{'; // the parser looks for a brace to end the selector - Selector* result_sel = Parser::from_c_str(result_str.c_str(), ctx, s->pstate()).parse_selector_group(); + Selector* result_sel = Parser::from_c_str(result_str.c_str(), ctx, s->pstate()).parse_selector_list(); return result_sel->perform(this); } diff --git a/cssize.cpp b/cssize.cpp index c5ae2959e6..2b01857930 100644 --- a/cssize.cpp +++ b/cssize.cpp @@ -8,9 +8,8 @@ namespace Sass { - Cssize::Cssize(Context& ctx, Env* env, Backtrace* bt) + Cssize::Cssize(Context& ctx, Backtrace* bt) : ctx(ctx), - env(env), block_stack(vector()), p_stack(vector()), backtrace(bt) @@ -23,15 +22,11 @@ namespace Sass { Statement* Cssize::operator()(Block* b) { - Env new_env; - new_env.link(*env); - env = &new_env; Block* bb = new (ctx.mem) Block(b->pstate(), b->length(), b->is_root()); // bb->tabs(b->tabs()); block_stack.push_back(bb); append_block(b); block_stack.pop_back(); - env = env->parent(); return bb; } @@ -161,7 +156,7 @@ namespace Sass { return debubble(mm->block(), mm)->block(); } - Statement* Cssize::operator()(Feature_Block* m) + Statement* Cssize::operator()(Supports_Block* m) { if (!m->block()->length()) { return m; } @@ -171,8 +166,8 @@ namespace Sass { p_stack.push_back(m); - Feature_Block* mm = new (ctx.mem) Feature_Block(m->pstate(), - m->feature_queries(), + Supports_Block* mm = new (ctx.mem) Supports_Block(m->pstate(), + m->queries(), m->block()->perform(this)->block()); mm->tabs(m->tabs()); @@ -252,7 +247,7 @@ namespace Sass { return bubble; } - Statement* Cssize::bubble(Feature_Block* m) + Statement* Cssize::bubble(Supports_Block* m) { Ruleset* parent = static_cast(shallow_copy(this->parent())); @@ -268,8 +263,8 @@ namespace Sass { Block* wrapper_block = new (ctx.mem) Block(m->block()->pstate()); *wrapper_block << new_rule; - Feature_Block* mm = new (ctx.mem) Feature_Block(m->pstate(), - m->feature_queries(), + Supports_Block* mm = new (ctx.mem) Supports_Block(m->pstate(), + m->queries(), wrapper_block); mm->tabs(m->tabs()); @@ -364,8 +359,8 @@ namespace Sass { return new (ctx.mem) Bubble(*static_cast(s)); case Statement::DIRECTIVE: return new (ctx.mem) At_Rule(*static_cast(s)); - case Statement::FEATURE: - return new (ctx.mem) Feature_Block(*static_cast(s)); + case Statement::SUPPORTS: + return new (ctx.mem) Supports_Block(*static_cast(s)); case Statement::ATROOT: return new (ctx.mem) At_Root_Block(*static_cast(s)); case Statement::KEYFRAMERULE: @@ -427,10 +422,9 @@ namespace Sass { else { List* mq = merge_media_queries(static_cast(b->node()), static_cast(parent)); - if (mq->length()) { - static_cast(b->node())->media_queries(mq); - ss = b->node(); - } + if (!mq->length()) continue; + static_cast(b->node())->media_queries(mq); + ss = b->node(); } if (!ss) continue; diff --git a/cssize.hpp b/cssize.hpp index 54cf70f5cb..f6829c88bf 100644 --- a/cssize.hpp +++ b/cssize.hpp @@ -18,7 +18,6 @@ namespace Sass { class Cssize : public Operation_CRTP { Context& ctx; - Env* env; vector block_stack; vector p_stack; Backtrace* backtrace; @@ -26,7 +25,7 @@ namespace Sass { Statement* fallback_impl(AST_Node* n); public: - Cssize(Context&, Env*, Backtrace*); + Cssize(Context&, Backtrace*); virtual ~Cssize() { } using Operation::operator(); @@ -36,7 +35,7 @@ namespace Sass { // Statement* operator()(Propset*); // Statement* operator()(Bubble*); Statement* operator()(Media_Block*); - Statement* operator()(Feature_Block*); + Statement* operator()(Supports_Block*); Statement* operator()(At_Root_Block*); Statement* operator()(At_Rule*); Statement* operator()(Keyframe_Rule*); @@ -63,7 +62,7 @@ namespace Sass { Statement* bubble(At_Rule*); Statement* bubble(At_Root_Block*); Statement* bubble(Media_Block*); - Statement* bubble(Feature_Block*); + Statement* bubble(Supports_Block*); Statement* shallow_copy(Statement*); Statement* debubble(Block* children, Statement* parent = 0); Statement* flatten(Statement*); diff --git a/debugger.hpp b/debugger.hpp index 3a9af65dce..403705988f 100644 --- a/debugger.hpp +++ b/debugger.hpp @@ -224,9 +224,9 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0) debug_ast(block->media_queries(), ind + " =@ "); debug_ast(block->selector(), ind + " -@ "); if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); } - } else if (dynamic_cast(node)) { - Feature_Block* block = dynamic_cast(node); - cerr << ind << "Feature_Block " << block; + } else if (dynamic_cast(node)) { + Supports_Block* block = dynamic_cast(node); + cerr << ind << "Supports_Block " << block; cerr << " (" << pstate_source_position(node) << ")"; cerr << " " << block->tabs() << endl; if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); } diff --git a/emitter.cpp b/emitter.cpp index 9d7a8a0130..555cefdf52 100644 --- a/emitter.cpp +++ b/emitter.cpp @@ -171,7 +171,7 @@ namespace Sass { void Emitter::append_comma_separator() { - scheduled_space = 0; + // scheduled_space = 0; append_string(","); append_optional_space(); } diff --git a/emitter.hpp b/emitter.hpp index a69f28f5b2..2ee538a24e 100644 --- a/emitter.hpp +++ b/emitter.hpp @@ -18,7 +18,7 @@ namespace Sass { protected: OutputBuffer wbuf; public: - const string buffer(void) { return wbuf.buffer; } + const string& buffer(void) { return wbuf.buffer; } const SourceMap smap(void) { return wbuf.smap; } const OutputBuffer output(void) { return wbuf; } // proxy methods for source maps diff --git a/environment.hpp b/environment.hpp index 3e80e90eff..2f3d797f0c 100644 --- a/environment.hpp +++ b/environment.hpp @@ -42,7 +42,7 @@ namespace Sass { // there is still a parent around // not sure what it is actually use for // I guess we store functions etc. there - bool is_root_scope() const + bool is_global() const { return parent_ && ! parent_->parent_; } diff --git a/eval.cpp b/eval.cpp index 1e4cd77ad2..a55dda62b7 100644 --- a/eval.cpp +++ b/eval.cpp @@ -629,6 +629,7 @@ namespace Sass { env = old_env; } // else if it's a user-defined c function + // convert call into C-API compatible form else if (c_function) { Sass_Function_Fn c_func = sass_function_get_function(c_function); @@ -919,10 +920,7 @@ namespace Sass { { string acc; for (size_t i = 0, L = s->length(); i < L; ++i) { - // if (String_Quoted* str_quoted = dynamic_cast((*s)[i])) { - // if (!str_quoted->is_delayed()) str_quoted->value(string_eval_escapes(str_quoted->value())); - // } - acc += interpolation((*s)[i]); + if ((*s)[i]) acc += interpolation((*s)[i]); } String_Quoted* str = new (ctx.mem) String_Quoted(s->pstate(), acc); if (!str->quote_mark()) { @@ -945,29 +943,29 @@ namespace Sass { return s; } - Expression* Eval::operator()(Feature_Query* q) + Expression* Eval::operator()(Supports_Query* q) { - Feature_Query* qq = new (ctx.mem) Feature_Query(q->pstate(), + Supports_Query* qq = new (ctx.mem) Supports_Query(q->pstate(), q->length()); for (size_t i = 0, L = q->length(); i < L; ++i) { - *qq << static_cast((*q)[i]->perform(this)); + *qq << static_cast((*q)[i]->perform(this)); } return qq; } - Expression* Eval::operator()(Feature_Query_Condition* c) + Expression* Eval::operator()(Supports_Condition* c) { String* feature = c->feature(); Expression* value = c->value(); value = (value ? value->perform(this) : 0); - Feature_Query_Condition* cc = new (ctx.mem) Feature_Query_Condition(c->pstate(), + Supports_Condition* cc = new (ctx.mem) Supports_Condition(c->pstate(), c->length(), feature, value, c->operand(), c->is_root()); for (size_t i = 0, L = c->length(); i < L; ++i) { - *cc << static_cast((*c)[i]->perform(this)); + *cc << static_cast((*c)[i]->perform(this)); } return cc; } diff --git a/eval.hpp b/eval.hpp index 86e95eee83..cabcf712a2 100644 --- a/eval.hpp +++ b/eval.hpp @@ -63,8 +63,8 @@ namespace Sass { Expression* operator()(Media_Query*); Expression* operator()(Media_Query_Expression*); Expression* operator()(At_Root_Expression*); - Expression* operator()(Feature_Query*); - Expression* operator()(Feature_Query_Condition*); + Expression* operator()(Supports_Query*); + Expression* operator()(Supports_Condition*); Expression* operator()(Null*); Expression* operator()(Argument*); Expression* operator()(Arguments*); diff --git a/expand.cpp b/expand.cpp index 2c990b0feb..6019deed54 100644 --- a/expand.cpp +++ b/expand.cpp @@ -72,7 +72,7 @@ namespace Sass { p.source = str.c_str(); p.position = str.c_str(); p.end = str.c_str() + strlen(str.c_str()); - Selector_List* sel_lst = p.parse_selector_group(); + Selector_List* sel_lst = p.parse_selector_list(); // sel_lst->pstate(isp.remap(sel_lst->pstate())); for(size_t i = 0; i < sel_lst->length(); i++) { @@ -137,11 +137,11 @@ namespace Sass { return 0; } - Statement* Expand::operator()(Feature_Block* f) + Statement* Expand::operator()(Supports_Block* f) { - Expression* feature_queries = f->feature_queries()->perform(eval->with(env, backtrace)); - Feature_Block* ff = new (ctx.mem) Feature_Block(f->pstate(), - static_cast(feature_queries), + Expression* queries = f->queries()->perform(eval->with(env, backtrace)); + Supports_Block* ff = new (ctx.mem) Supports_Block(f->pstate(), + static_cast(queries), f->block()->perform(this)->block()); ff->selector(selector_stack.back()); return ff; @@ -534,7 +534,6 @@ namespace Sass { "@content", new (ctx.mem) Parameters(c->pstate()), c->block(), - &ctx, Definition::MIXIN); thunk->environment(env); new_env.local_frame()["@content[m]"] = thunk; @@ -558,6 +557,7 @@ namespace Sass { return call->perform(this); } + // produce an error if something is not implemented inline Statement* Expand::fallback_impl(AST_Node* n) { error("unknown internal error; please contact the LibSass maintainers", n->pstate(), backtrace); diff --git a/expand.hpp b/expand.hpp index 58c6d4ea02..32290eedf5 100644 --- a/expand.hpp +++ b/expand.hpp @@ -46,7 +46,7 @@ namespace Sass { Statement* operator()(Ruleset*); Statement* operator()(Propset*); Statement* operator()(Media_Block*); - Statement* operator()(Feature_Block*); + Statement* operator()(Supports_Block*); Statement* operator()(At_Root_Block*); Statement* operator()(At_Rule*); Statement* operator()(Declaration*); diff --git a/extend.cpp b/extend.cpp index 65fb6ef273..48e163b136 100644 --- a/extend.cpp +++ b/extend.cpp @@ -1596,7 +1596,6 @@ namespace Sass { if (pSelector && pSelector->has_line_feed()) pNewSelector->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. DEBUG_PRINTLN(EXTEND_COMPOUND, "SOURCES SETTING ON NEW SEQ: " << complexSelectorToNode(pNewSelector, ctx)) @@ -1961,7 +1960,7 @@ namespace Sass { (pNewSelectorList->perform(&to_string) + ";").c_str(), ctx, pNewSelectorList->pstate() - ).parse_selector_group() + ).parse_selector_list() ); } else { DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND DID NOT TRY TO EXTEND ANYTHING") @@ -1988,7 +1987,7 @@ namespace Sass { pRuleset->block()->perform(this); } - void Extend::operator()(Feature_Block* pFeatureBlock) + void Extend::operator()(Supports_Block* pFeatureBlock) { if (pFeatureBlock->selector()) { extendObjectWithSelectorAndBlock(pFeatureBlock, ctx, subset_map); diff --git a/extend.hpp b/extend.hpp index eb2dd9d197..1f5a5bb4fd 100644 --- a/extend.hpp +++ b/extend.hpp @@ -26,6 +26,8 @@ namespace Sass { void fallback_impl(AST_Node* n) { } public: + static Node subweave(Node& one, Node& two, Context& ctx); + static Selector_List* extendSelectorList(Selector_List* pSelectorList, Context& ctx, ExtensionSubsetMap& subsetMap, bool isReplace, bool& extendedSomething); Extend(Context&, ExtensionSubsetMap&); virtual ~Extend() { } @@ -33,15 +35,12 @@ namespace Sass { void operator()(Block*); void operator()(Ruleset*); - void operator()(Feature_Block*); + void operator()(Supports_Block*); void operator()(Media_Block*); void operator()(At_Rule*); template void fallback(U x) { return fallback_impl(x); } - - static Node subweave(Node& one, Node& two, Context& ctx); - static Selector_List* extendSelectorList(Selector_List* pSelectorList, Context& ctx, ExtensionSubsetMap& subsetMap, bool isReplace, bool& extendedSomething); }; } diff --git a/functions.cpp b/functions.cpp index ee9b42765f..511600b9ce 100644 --- a/functions.cpp +++ b/functions.cpp @@ -47,7 +47,6 @@ namespace Sass { name, params, func, - &ctx, false); } @@ -68,7 +67,6 @@ namespace Sass { name, params, c_func, - &ctx, false, true); } @@ -118,12 +116,12 @@ 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 string& argname, Env& env, Signature sig, ParserState pstate, Backtrace* backtrace, Context& ctx); - + template <> Selector_List* get_arg_sel(const string& argname, Env& env, Signature sig, ParserState pstate, Backtrace* backtrace, Context& ctx) { To_String to_string(&ctx, false); @@ -131,7 +129,7 @@ namespace Sass { string exp_src = exp->perform(&to_string) + "{"; return Parser::parse_selector(exp_src.c_str(), ctx); } - + template <> Complex_Selector* get_arg_sel(const string& argname, Env& env, Signature sig, ParserState pstate, Backtrace* backtrace, Context& ctx) { To_String to_string(&ctx, false); @@ -140,7 +138,7 @@ namespace Sass { Selector_List* sel_list = Parser::parse_selector(exp_src.c_str(), ctx); return (sel_list->length() > 0) ? sel_list->first() : 0; } - + template <> Compound_Selector* get_arg_sel(const string& argname, Env& env, Signature sig, ParserState pstate, Backtrace* backtrace, Context& ctx) { To_String to_string(&ctx, false); @@ -150,7 +148,7 @@ namespace Sass { return (sel_list->length() > 0) ? sel_list->first()->tail()->head() : 0; } -#ifdef __MINGW32__ + #ifdef __MINGW32__ uint64_t GetSeed() { HCRYPTPROV hp = 0; @@ -164,13 +162,13 @@ namespace Sass { return seed; } -#else + #else static random_device rd; uint64_t GetSeed() { - return rd(); - } -#endif + return rd(); + } + #endif // note: the performance of many implementations of // random_device degrades sharply once the entropy pool @@ -854,7 +852,7 @@ namespace Sass { error(msg, pstate, backtrace); } catch (...) { throw; } - // handle any invalid utf8 errors + // return something even if we had an error (-1) return new (ctx.mem) Number(pstate, len); } @@ -945,7 +943,7 @@ namespace Sass { error(msg, pstate, backtrace); } catch (...) { throw; } - // handle any invalid utf8 errors + // return something even if we had an error (-1) return new (ctx.mem) Number(pstate, index); } @@ -1608,13 +1606,13 @@ namespace Sass { Signature selector_nest_sig = "selector-nest($selectors...)"; BUILT_IN(selector_nest) { - To_String to_string; + To_String to_string(&ctx, false); List* arglist = ARG("$selectors", List); - + // Not enough parameters if( arglist->length() == 0 ) error("$selectors: At least one selector must be passed", pstate); - + // Parse args into vector of selectors vector parsedSelectors; for (size_t i = 0, L = arglist->length(); i < L; ++i) { @@ -1623,21 +1621,21 @@ namespace Sass { Selector_List* sel = Parser::parse_selector(exp_src.c_str(), ctx); parsedSelectors.push_back(sel); } - + // Nothing to do if( parsedSelectors.empty() ) { return new (ctx.mem) Null(pstate); } - + // 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* result = *itr; ++itr; - + for(;itr != parsedSelectors.end(); ++itr) { Selector_List* child = *itr; - vector newElements; - + vector exploded; + // For every COMPLEX_SELECTOR in `child` // For every COMPLEX_SELECTOR in `result` // let parentSeqClone equal a copy of result->elements[i] @@ -1647,32 +1645,30 @@ namespace Sass { // 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) { - Complex_Selector* parentSeqClone = (*result)[i]->cloneFully(ctx); - Complex_Selector* childSeq = (*child)[j]; - - parentSeqClone->innermost()->tail(childSeq); // Set seq as the new tail of parentSeqClone - newElements.push_back(parentSeqClone); + Complex_Selector* parent = (*result)[i]->cloneFully(ctx); + Complex_Selector* selector = (*child)[j]; + parent->innermost()->tail(selector); + exploded.push_back(parent); } } - - result->elements(newElements); + + result->elements(exploded); } - - + Listize listize(ctx); return result->perform(&listize); } - + Signature selector_append_sig = "selector-append($selectors...)"; BUILT_IN(selector_append) { To_String to_string; List* arglist = ARG("$selectors", List); - + // Not enough parameters if( arglist->length() == 0 ) error("$selectors: At least one selector must be passed", pstate); - + // Parse args into vector of selectors vector parsedSelectors; for (size_t i = 0, L = arglist->length(); i < L; ++i) { @@ -1681,21 +1677,21 @@ namespace Sass { Selector_List* sel = Parser::parse_selector(exp_src.c_str(), ctx); parsedSelectors.push_back(sel); } - + // Nothing to do if( parsedSelectors.empty() ) { return new (ctx.mem) Null(pstate); } - + // 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* result = *itr; ++itr; - + for(;itr != parsedSelectors.end(); ++itr) { Selector_List* child = *itr; vector newElements; - + // For every COMPLEX_SELECTOR in `result` // For every COMPLEX_SELECTOR in `child` // let parentSeqClone equal a copy of result->elements[i] @@ -1708,7 +1704,7 @@ namespace Sass { Complex_Selector* parentSeqClone = (*result)[i]->cloneFully(ctx); Complex_Selector* childSeq = (*child)[j]; Complex_Selector* base = childSeq->tail(); - + // Must be a simple sequence if( childSeq->combinator() != Complex_Selector::Combinator::ANCESTOR_OF ) { string msg("Can't append `"); @@ -1718,7 +1714,7 @@ namespace Sass { msg += "`"; error(msg, pstate, backtrace); } - + // Cannot be a Universal selector Type_Selector* pType = dynamic_cast(base->head()->first()); if(pType && pType->name() == "*") { @@ -1729,71 +1725,101 @@ namespace Sass { msg += "`"; error(msg, pstate, backtrace); } - + // TODO: Add check for namespace stuff - + // append any selectors in childSeq's head *(parentSeqClone->innermost()->head()) += (base->head()); - + // Set parentSeqClone new tail parentSeqClone->innermost()->tail( base->tail() ); - + newElements.push_back(parentSeqClone); } } - + result->elements(newElements); } - + + Listize listize(ctx); + return result->perform(&listize); + } + + Signature selector_unify_sig = "selector-unify($selector1, $selector2)"; + BUILT_IN(selector_unify) + { + Selector_List* selector1 = ARGSEL("$selector1", Selector_List, p_contextualize); + Selector_List* selector2 = ARGSEL("$selector2", Selector_List, p_contextualize); + + Selector_List* result = selector1->unify_with(selector2, ctx); Listize listize(ctx); return result->perform(&listize); } - + + Signature simple_selectors_sig = "simple-selectors($selector)"; + BUILT_IN(simple_selectors) + { + Compound_Selector* sel = ARGSEL("$selector", Compound_Selector, p_contextualize); + + To_String to_string; + List* l = new (ctx.mem) List(sel->pstate(), sel->length(), List::COMMA); + + for (size_t i = 0, L = sel->length(); i < L; ++i) { + Simple_Selector* ss = (*sel)[i]; + string ss_string = ss->perform(&to_string) ; + + *l << new (ctx.mem) String_Constant(ss->pstate(), ss_string); + } + + return l; + } + Signature selector_extend_sig = "selector-extend($selector, $extendee, $extender)"; BUILT_IN(selector_extend) { To_String to_string; - + Selector_List* selector = ARGSEL("$selector", Selector_List, p_contextualize); Selector_List* extendee = ARGSEL("$extendee", Selector_List, p_contextualize); Selector_List* extender = ARGSEL("$extender", Selector_List, p_contextualize); - + ExtensionSubsetMap subset_map; extender->populate_extends(extendee, ctx, subset_map); - + bool extendedSomething; Selector_List* result = Extend::extendSelectorList(selector, ctx, subset_map, false, extendedSomething); - + Listize listize(ctx); return result->perform(&listize); } - + Signature selector_replace_sig = "selector-replace($selector, $original, $replacement)"; BUILT_IN(selector_replace) { Selector_List* selector = ARGSEL("$selector", Selector_List, p_contextualize); Selector_List* original = ARGSEL("$original", Selector_List, p_contextualize); Selector_List* replacement = ARGSEL("$replacement", Selector_List, p_contextualize); - + ExtensionSubsetMap subset_map; replacement->populate_extends(original, ctx, subset_map); - + bool extendedSomething; Selector_List* result = Extend::extendSelectorList(selector, ctx, subset_map, true, extendedSomething); - + Listize listize(ctx); return result->perform(&listize); } - - Signature selector_unify_sig = "selector-unify($selector1, $selector2)"; - BUILT_IN(selector_unify) + + Signature selector_parse_sig = "selector-parse($selector)"; + BUILT_IN(selector_parse) { - Selector_List* selector1 = ARGSEL("$selector1", Selector_List, p_contextualize); - Selector_List* selector2 = ARGSEL("$selector2", Selector_List, p_contextualize); - - Selector_List* result = selector1->unify_with(selector2, ctx); + To_String to_string(&ctx, false); + Expression* exp = ARG("$selector", Expression); + string sel_src = exp->perform(&to_string) + "{"; + Selector_List* sel = Parser::parse_selector(sel_src.c_str(), ctx); + Listize listize(ctx); - return result->perform(&listize); + return sel->perform(&listize); } Signature is_superselector_sig = "is-superselector($super, $sub)"; @@ -1809,37 +1835,6 @@ namespace Sass { bool result = sel_sup->is_superselector_of(sel_sub); return new (ctx.mem) Boolean(pstate, result); } - - Signature simple_selectors_sig = "simple_selectors($selector)"; - BUILT_IN(simple_selectors) - { - Compound_Selector* sel = ARGSEL("$selector", Compound_Selector, p_contextualize); - - To_String to_string; - List* l = new (ctx.mem) List(sel->pstate(), sel->length(), List::COMMA); - - for (size_t i = 0, L = sel->length(); i < L; ++i) { - Simple_Selector* ss = (*sel)[i]; - string ss_string = ss->perform(&to_string) ; - - *l << new (ctx.mem) String_Constant(ss->pstate(), ss_string); - } - - - return l; - } - - Signature selector_parse_sig = "selector-parse($selector)"; - BUILT_IN(selector_parse) - { - To_String to_string(&ctx, false); - Expression* exp = ARG("$selector", Expression); - string sel_src = exp->perform(&to_string) + "{"; - Selector_List* sel = Parser::parse_selector(sel_src.c_str(), ctx); - - Listize listize(ctx); - return sel->perform(&listize); - } Signature unique_id_sig = "unique-id()"; BUILT_IN(unique_id) diff --git a/functions.hpp b/functions.hpp index 8b993e9176..96f3cedf1f 100644 --- a/functions.hpp +++ b/functions.hpp @@ -191,8 +191,6 @@ namespace Sass { BUILT_IN(is_superselector); BUILT_IN(simple_selectors); BUILT_IN(selector_parse); - - } } diff --git a/inspect.cpp b/inspect.cpp index ba56a3c8f6..9d1faf59dd 100644 --- a/inspect.cpp +++ b/inspect.cpp @@ -76,12 +76,12 @@ namespace Sass { media_block->block()->perform(this); } - void Inspect::operator()(Feature_Block* feature_block) + void Inspect::operator()(Supports_Block* feature_block) { append_indentation(); append_token("@supports", feature_block); append_mandatory_space(); - feature_block->feature_queries()->perform(this); + feature_block->queries()->perform(this); feature_block->block()->perform(this); } @@ -657,7 +657,7 @@ namespace Sass { } } - void Inspect::operator()(Feature_Query* fq) + void Inspect::operator()(Supports_Query* fq) { size_t i = 0; (*fq)[i++]->perform(this); @@ -666,17 +666,17 @@ namespace Sass { } } - void Inspect::operator()(Feature_Query_Condition* fqc) + void Inspect::operator()(Supports_Condition* fqc) { - if (fqc->operand() == Feature_Query_Condition::AND) { + if (fqc->operand() == Supports_Condition::AND) { append_mandatory_space(); append_token("and", fqc); append_mandatory_space(); - } else if (fqc->operand() == Feature_Query_Condition::OR) { + } else if (fqc->operand() == Supports_Condition::OR) { append_mandatory_space(); append_token("or", fqc); append_mandatory_space(); - } else if (fqc->operand() == Feature_Query_Condition::NOT) { + } else if (fqc->operand() == Supports_Condition::NOT) { append_mandatory_space(); append_token("not", fqc); append_mandatory_space(); diff --git a/inspect.hpp b/inspect.hpp index 7cd0f51c18..fccd3ed49d 100644 --- a/inspect.hpp +++ b/inspect.hpp @@ -28,7 +28,7 @@ namespace Sass { virtual void operator()(Ruleset*); virtual void operator()(Propset*); virtual void operator()(Bubble*); - virtual void operator()(Feature_Block*); + virtual void operator()(Supports_Block*); virtual void operator()(Media_Block*); virtual void operator()(At_Root_Block*); virtual void operator()(At_Rule*); @@ -65,8 +65,8 @@ namespace Sass { virtual void operator()(String_Schema*); virtual void operator()(String_Constant*); virtual void operator()(String_Quoted*); - virtual void operator()(Feature_Query*); - virtual void operator()(Feature_Query_Condition*); + virtual void operator()(Supports_Query*); + virtual void operator()(Supports_Condition*); virtual void operator()(Media_Query*); virtual void operator()(Media_Query_Expression*); virtual void operator()(At_Root_Expression*); diff --git a/json.cpp b/json.cpp index f92f096a24..32fda7bc98 100644 --- a/json.cpp +++ b/json.cpp @@ -21,6 +21,11 @@ THE SOFTWARE. */ +#ifdef _MSC_VER +#define _CRT_SECURE_NO_WARNINGS +#define _CRT_NONSTDC_NO_DEPRECATE +#endif + #include "json.hpp" #include diff --git a/lexer.hpp b/lexer.hpp index de425d6d8f..0bf7081848 100644 --- a/lexer.hpp +++ b/lexer.hpp @@ -110,7 +110,7 @@ namespace Sass { } // Match for members of char class. - // Regex equivalent: /[axy]/ + // Regex equivalent: /[axy]+/ template const char* class_chars(const char* src) { const char* p = src; diff --git a/listize.cpp b/listize.cpp index 3e27803904..3457d59e63 100644 --- a/listize.cpp +++ b/listize.cpp @@ -17,6 +17,7 @@ namespace Sass { { List* l = new (ctx.mem) List(sel->pstate(), sel->length(), List::COMMA); for (size_t i = 0, L = sel->length(); i < L; ++i) { + // if (!(*sel)[i]) continue; *l << (*sel)[i]->perform(this); } return l; diff --git a/operation.hpp b/operation.hpp index b470fe8ad8..a3dd6b8636 100644 --- a/operation.hpp +++ b/operation.hpp @@ -19,7 +19,7 @@ namespace Sass { virtual T operator()(Ruleset* x) = 0; virtual T operator()(Propset* x) = 0; virtual T operator()(Bubble* x) = 0; - virtual T operator()(Feature_Block* x) = 0; + virtual T operator()(Supports_Block* x) = 0; virtual T operator()(Media_Block* x) = 0; virtual T operator()(At_Root_Block* x) = 0; virtual T operator()(At_Rule* x) = 0; @@ -55,8 +55,8 @@ namespace Sass { virtual T operator()(Boolean* x) = 0; virtual T operator()(String_Schema* x) = 0; virtual T operator()(String_Constant* x) = 0; - virtual T operator()(Feature_Query* x) = 0; - virtual T operator()(Feature_Query_Condition* x)= 0; + virtual T operator()(Supports_Query* x) = 0; + virtual T operator()(Supports_Condition* x)= 0; virtual T operator()(Media_Query* x) = 0; virtual T operator()(Media_Query_Expression* x) = 0; virtual T operator()(At_Root_Expression* x) = 0; @@ -69,7 +69,6 @@ namespace Sass { virtual T operator()(Arguments* x) = 0; // selectors virtual T operator()(Selector_Schema* x) = 0; - virtual T operator()(Selector_Reference* x) = 0; virtual T operator()(Selector_Placeholder* x) = 0; virtual T operator()(Type_Selector* x) = 0; virtual T operator()(Selector_Qualifier* x) = 0; @@ -94,7 +93,7 @@ namespace Sass { virtual T operator()(Ruleset* x) { return static_cast(this)->fallback(x); } virtual T operator()(Propset* x) { return static_cast(this)->fallback(x); } virtual T operator()(Bubble* x) { return static_cast(this)->fallback(x); } - virtual T operator()(Feature_Block* x) { return static_cast(this)->fallback(x); } + virtual T operator()(Supports_Block* x) { return static_cast(this)->fallback(x); } virtual T operator()(Media_Block* x) { return static_cast(this)->fallback(x); } virtual T operator()(At_Root_Block* x) { return static_cast(this)->fallback(x); } virtual T operator()(At_Rule* x) { return static_cast(this)->fallback(x); } @@ -130,8 +129,8 @@ namespace Sass { virtual T operator()(Boolean* x) { return static_cast(this)->fallback(x); } virtual T operator()(String_Schema* x) { return static_cast(this)->fallback(x); } virtual T operator()(String_Constant* x) { return static_cast(this)->fallback(x); } - virtual T operator()(Feature_Query* x) { return static_cast(this)->fallback(x); } - virtual T operator()(Feature_Query_Condition* x){ return static_cast(this)->fallback(x); } + virtual T operator()(Supports_Query* x) { return static_cast(this)->fallback(x); } + virtual T operator()(Supports_Condition* x) { return static_cast(this)->fallback(x); } virtual T operator()(Media_Query* x) { return static_cast(this)->fallback(x); } virtual T operator()(Media_Query_Expression* x) { return static_cast(this)->fallback(x); } virtual T operator()(At_Root_Expression* x) { return static_cast(this)->fallback(x); } @@ -144,7 +143,6 @@ namespace Sass { virtual T operator()(Arguments* x) { return static_cast(this)->fallback(x); } // selectors virtual T operator()(Selector_Schema* x) { return static_cast(this)->fallback(x); } - virtual T operator()(Selector_Reference* x) { return static_cast(this)->fallback(x); } virtual T operator()(Selector_Placeholder* x) { return static_cast(this)->fallback(x); } virtual T operator()(Type_Selector* x) { return static_cast(this)->fallback(x); } virtual T operator()(Selector_Qualifier* x) { return static_cast(this)->fallback(x); } diff --git a/output.cpp b/output.cpp index b0a9d24e3f..1589d5e6e9 100644 --- a/output.cpp +++ b/output.cpp @@ -196,11 +196,11 @@ namespace Sass { append_scope_closer(); } - void Output::operator()(Feature_Block* f) + void Output::operator()(Supports_Block* f) { if (f->is_invisible()) return; - Feature_Query* q = f->feature_queries(); + Supports_Query* q = f->queries(); Block* b = f->block(); // Filter out feature blocks that aren't printable (process its children though) diff --git a/output.hpp b/output.hpp index 6727866b00..90ef35e103 100644 --- a/output.hpp +++ b/output.hpp @@ -37,7 +37,7 @@ namespace Sass { virtual void operator()(Ruleset*); // virtual void operator()(Propset*); - virtual void operator()(Feature_Block*); + virtual void operator()(Supports_Block*); virtual void operator()(Media_Block*); virtual void operator()(At_Rule*); virtual void operator()(Keyframe_Rule*); diff --git a/parser.cpp b/parser.cpp index c570966ecb..2d6dcf737b 100644 --- a/parser.cpp +++ b/parser.cpp @@ -46,7 +46,7 @@ namespace Sass { Parser p = Parser::from_c_str(src, ctx, pstate); // ToDo: ruby sass errors on parent references // ToDo: remap the source-map entries somehow - return p.parse_selector_group(); + return p.parse_selector_list(); } bool Parser::peek_newline(const char* start) @@ -89,7 +89,7 @@ namespace Sass { bool semicolon = false; string error_message; lex< optional_spaces >(); - Selector_Lookahead lookahead_result; + Lookahead lookahead_result; while (position < end) { parse_block_comments(root); if (peek< kwd_import >()) { @@ -114,8 +114,8 @@ namespace Sass { // parse comment blocks - else if (peek< kwd_include >() /* || peek< exactly<'+'> >() */) { - Mixin_Call* mixin_call = parse_mixin_call(); + else if (peek< kwd_include_directive >() /* || peek< exactly<'+'> >() */) { + Mixin_Call* mixin_call = parse_include_directive(); (*root) << mixin_call; if (!mixin_call->block()) { semicolon = true; @@ -140,8 +140,8 @@ namespace Sass { else if (peek< kwd_at_root >()) { (*root) << parse_at_root_block(); } - else if (peek< kwd_supports >()) { - (*root) << parse_feature_block(); + else if (peek< kwd_supports_directive >()) { + (*root) << parse_supports_directive(); } else if (peek< kwd_warn >()) { (*root) << parse_warning(); @@ -358,7 +358,7 @@ namespace Sass { else stack.push_back(function_def); Block* body = parse_block(); stack.pop_back(); - Definition* def = new (ctx.mem) Definition(source_position_of_def, name, params, body, &ctx, which_type); + Definition* def = new (ctx.mem) Definition(source_position_of_def, name, params, body, which_type); return def; } @@ -399,9 +399,9 @@ namespace Sass { return p; } - Mixin_Call* Parser::parse_mixin_call() + Mixin_Call* Parser::parse_include_directive() { - lex< kwd_include >() /* || lex< exactly<'+'> >() */; + lex< kwd_include_directive >() /* || lex< exactly<'+'> >() */; if (!lex< identifier >()) error("invalid name in @include directive", pstate); ParserState source_position_of_call = pstate; string name(Util::normalize_underscores(lexed)); @@ -469,7 +469,7 @@ namespace Sass { ParserState var_source_position = pstate; if (!lex< exactly<':'> >()) error("expected ':' after " + name + " in assignment statement", pstate); Expression* val; - Selector_Lookahead lookahead = lookahead_for_value(position); + Lookahead lookahead = lookahead_for_value(position); if (lookahead.has_interpolants && lookahead.found) { val = parse_value_schema(lookahead.found); } else { @@ -487,14 +487,14 @@ namespace Sass { } // a ruleset connects a selector and a block - Ruleset* Parser::parse_ruleset(Selector_Lookahead lookahead) + Ruleset* Parser::parse_ruleset(Lookahead lookahead) { Selector* sel; if (lookahead.has_interpolants) { sel = parse_selector_schema(lookahead.found); } else { - sel = parse_selector_group(); + sel = parse_selector_list(); } bool old_in_at_root = in_at_root; ParserState r_source_position = pstate; @@ -544,20 +544,24 @@ namespace Sass { else { // make sure to add the last bits of the string up to the end (if any) if (i < end_of_selector) (*schema) << new (ctx.mem) String_Quoted(pstate, string(i, end_of_selector)); - break; + // exit loop + i = end_of_selector; } } // EO until eos - position = end_of_selector; + + // update position + position = i; + Selector_Schema* selector_schema = new (ctx.mem) Selector_Schema(pstate, schema); selector_schema->media_block(last_media_block); selector_schema->last_block(block_stack.back()); - // return parsed result + // update position return selector_schema; } // EO parse_selector_schema - Selector_List* Parser::parse_selector_group() + Selector_List* Parser::parse_selector_list() { bool reloop = true; To_String to_string(&ctx); @@ -574,7 +578,7 @@ namespace Sass { exactly<';'> > >()) break; // in case there are superfluous commas at the end - Complex_Selector* comb = parse_selector_combination(); + Complex_Selector* comb = parse_complex_selector(); if (!comb->has_reference() && !in_at_root) { ParserState sel_source_position = pstate; Selector_Reference* ref = new (ctx.mem) Selector_Reference(sel_source_position); @@ -607,13 +611,13 @@ namespace Sass { (*group) << comb; } while (reloop); - while (lex< optional >()) { + while (lex< kwd_optional >()) { group->is_optional(true); } return group; } - Complex_Selector* Parser::parse_selector_combination() + Complex_Selector* Parser::parse_complex_selector() { Position sel_source_position(-1); Compound_Selector* lhs; @@ -625,7 +629,7 @@ namespace Sass { // parse the left hand side { lhs = 0; } else { - lhs = parse_simple_selector_sequence(); + lhs = parse_compound_selector(); sel_source_position = before_token; lhs->has_line_break(peek_newline()); } @@ -644,12 +648,12 @@ namespace Sass { exactly<'{'>, exactly<'}'>, exactly<';'>, - optional + kwd_optional > >()) // parse combinator between lhs and rhs { rhs = 0; } else { - rhs = parse_selector_combination(); + rhs = parse_complex_selector(); sel_source_position = before_token; } if (!sel_source_position.line) sel_source_position = before_token; @@ -660,7 +664,7 @@ namespace Sass { return cpx; } - Compound_Selector* Parser::parse_simple_selector_sequence() + Compound_Selector* Parser::parse_compound_selector() { Compound_Selector* seq = new (ctx.mem) Compound_Selector(pstate); seq->media_block(last_media_block); @@ -678,10 +682,10 @@ namespace Sass { return seq; } } - if (sawsomething && lex_css< sequence< negate< functional >, alternatives< identifier_alnums, universal, quoted_string, dimension, percentage, number > > >()) { + if (sawsomething && lex_css< sequence< negate< re_pseudo_selector >, alternatives< identifier_alnums, universal, quoted_string, dimension, percentage, number > > >()) { // peek for abort conditions (*seq) << new (ctx.mem) Type_Selector(pstate, unquote(lexed)); - } else if (lex_css< sequence< negate< functional >, alternatives< type_selector, universal, quoted_string, dimension, percentage, number > > >()) { + } else if (lex_css< sequence< negate< re_pseudo_selector >, alternatives< type_selector, universal, quoted_string, dimension, percentage, number > > >()) { // otherwise parse another simple selector (*seq) << new (ctx.mem) Type_Selector(pstate, lexed); sawsomething = true; @@ -722,7 +726,7 @@ namespace Sass { else if (peek< pseudo_not >()) { return parse_negated_selector(); } - else if (peek< exactly<':'> >(position) || peek< functional >()) { + else if (peek< exactly<':'> >(position) || peek< re_pseudo_selector >()) { return parse_pseudo_selector(); } else if (peek< exactly<'['> >(position)) { @@ -746,7 +750,7 @@ namespace Sass { lex< pseudo_not >(); string name(lexed); ParserState nsource_position = pstate; - Selector* negated = parse_selector_group(); + Selector* negated = parse_selector_list(); if (!lex< exactly<')'> >()) { error("negated selector is missing ')'", pstate); } @@ -754,7 +758,7 @@ namespace Sass { } Simple_Selector* Parser::parse_pseudo_selector() { - if (lex< sequence< pseudo_prefix, functional > >() || lex< functional >()) { + if (lex< sequence< pseudo_prefix, re_pseudo_selector > >() || lex< re_pseudo_selector >()) { string name(lexed); String* expr = 0; ParserState p = pstate; @@ -790,7 +794,7 @@ namespace Sass { expr = new (ctx.mem) String_Constant(p, ""); } else { - wrapped = parse_selector_group(); + wrapped = parse_selector_list(); } if (!lex< exactly<')'> >()) error("unterminated argument to " + name + "...)", pstate); if (wrapped) { @@ -850,7 +854,7 @@ namespace Sass { { lex< exactly<'{'> >(); bool semicolon = false; - Selector_Lookahead lookahead_result; + Lookahead lookahead_result; Block* block = new (ctx.mem) Block(pstate); block_stack.push_back(block); lex< zero_plus < alternatives < space, line_comment > > >(); @@ -900,8 +904,8 @@ namespace Sass { else if (peek < kwd_while_directive >()) { (*block) << parse_while_directive(); } - else if (lex < kwd_return_directive >()) { - (*block) << new (ctx.mem) Return(pstate, parse_list()); + else if (peek < kwd_return_directive >()) { + (*block) << parse_return_directive(); semicolon = true; } else if (peek< kwd_warn >()) { @@ -922,8 +926,8 @@ namespace Sass { else if (peek< kwd_mixin >() || peek< kwd_function >()) { (*block) << parse_definition(); } - else if (peek< kwd_include >(position)) { - Mixin_Call* the_call = parse_mixin_call(); + else if (peek< kwd_include_directive >(position)) { + Mixin_Call* the_call = parse_include_directive(); (*block) << the_call; // don't need a semicolon after a content block semicolon = (the_call->block()) ? false : true; @@ -942,19 +946,19 @@ namespace Sass { } */ else if (lex< kwd_extend >()) { - Selector_Lookahead lookahead = lookahead_for_extension_target(position); + Lookahead lookahead = lookahead_for_include(position); if (!lookahead.found) error("invalid selector for @extend", pstate); Selector* target; if (lookahead.has_interpolants) target = parse_selector_schema(lookahead.found); - else target = parse_selector_group(); + else target = parse_selector_list(); (*block) << new (ctx.mem) Extension(pstate, target); semicolon = true; } else if (peek< kwd_media >()) { (*block) << parse_media_block(); } - else if (peek< kwd_supports >()) { - (*block) << parse_feature_block(); + else if (peek< kwd_supports_directive >()) { + (*block) << parse_supports_directive(); } else if (peek< kwd_at_root >()) { (*block) << parse_at_root_block(); @@ -1028,7 +1032,7 @@ namespace Sass { } else { Expression* value; - Selector_Lookahead lookahead = lookahead_for_value(position); + Lookahead lookahead = lookahead_for_value(position); if (lookahead.found) { if (lookahead.has_interpolants) { value = parse_value_schema(lookahead.found); @@ -1263,7 +1267,7 @@ namespace Sass { Expression* Parser::parse_expression() { - Expression* term1 = parse_term(); + Expression* term1 = parse_operators(); // if it's a singleton, return it (don't wrap it) if (!(peek< exactly<'+'> >(position) || (peek< no_spaces >(position) && peek< sequence< negate< unsigned_number >, exactly<'-'>, negate< space > > >(position)) || @@ -1275,13 +1279,13 @@ namespace Sass { vector operators; while (lex< exactly<'+'> >() || lex< sequence< negate< digit >, exactly<'-'> > >()) { operators.push_back(lexed.to_string() == "+" ? Binary_Expression::ADD : Binary_Expression::SUB); - operands.push_back(parse_term()); + operands.push_back(parse_operators()); } return fold_operands(term1, operands, operators); } - Expression* Parser::parse_term() + Expression* Parser::parse_operators() { Expression* factor = parse_factor(); // Special case: Ruby sass never tries to modulo if the lhs contains an interpolant @@ -1347,7 +1351,7 @@ namespace Sass { else if (peek< sequence< identifier_schema, negate< exactly<'%'> > > >()) { return parse_identifier_schema(); } - else if (peek< functional >()) { + else if (peek< re_pseudo_selector >()) { return parse_function_call(); } else if (lex< sequence< exactly<'+'>, optional_css_whitespace, negate< number > > >()) { @@ -1373,13 +1377,12 @@ namespace Sass { lex< css_comments >(); if (lex< ampersand >()) { - return new (ctx.mem) Parent_Selector(pstate, parse_selector_group()); } + return new (ctx.mem) Parent_Selector(pstate, parse_selector_list()); } - if (lex< important >()) + if (lex< kwd_important >()) { return new (ctx.mem) String_Constant(pstate, "!important"); } - const char* stop; - if ((stop = peek< value_schema >())) + if (const char* stop = peek< value_schema >()) { return parse_value_schema(stop); } if (lex< kwd_true >()) @@ -1639,7 +1642,6 @@ namespace Sass { return schema; } - // this parses interpolation outside other strings // means the result must not be quoted again later String* Parser::parse_identifier_schema() { @@ -1880,28 +1882,28 @@ namespace Sass { return new (ctx.mem) Media_Query_Expression(feature->pstate(), feature, expression); } - Feature_Block* Parser::parse_feature_block() + Supports_Block* Parser::parse_supports_directive() { - lex< kwd_supports >(); + lex< kwd_supports_directive >(); ParserState supports_source_position = pstate; - Feature_Query* feature_queries = parse_feature_queries(); + Supports_Query* queries = parse_supports_queries(); if (!peek< exactly<'{'> >()) { error("expected '{' in feature query", pstate); } Block* block = parse_block(); - return new (ctx.mem) Feature_Block(supports_source_position, feature_queries, block); + return new (ctx.mem) Supports_Block(supports_source_position, queries, block); } - Feature_Query* Parser::parse_feature_queries() + Supports_Query* Parser::parse_supports_queries() { - Feature_Query* fq = new (ctx.mem) Feature_Query(pstate); - Feature_Query_Condition* cond = new (ctx.mem) Feature_Query_Condition(pstate); + Supports_Query* fq = new (ctx.mem) Supports_Query(pstate); + Supports_Condition* cond = new (ctx.mem) Supports_Condition(pstate); cond->is_root(true); while (!peek< exactly<')'> >(position) && !peek< exactly<'{'> >(position)) - (*cond) << parse_feature_query(); + (*cond) << parse_supports_query(); (*fq) << cond; if (fq->empty()) error("expected @supports condition (e.g. (display: flexbox))", pstate); @@ -1909,7 +1911,7 @@ namespace Sass { return fq; } - Feature_Query_Condition* Parser::parse_feature_query() + Supports_Condition* Parser::parse_supports_query() { if (peek< kwd_not >(position)) return parse_supports_negation(); else if (peek< kwd_and >(position)) return parse_supports_conjunction(); @@ -1918,52 +1920,52 @@ namespace Sass { else return parse_supports_declaration(); } - Feature_Query_Condition* Parser::parse_feature_query_in_parens() + Supports_Condition* Parser::parse_feature_query_in_parens() { - Feature_Query_Condition* cond = new (ctx.mem) Feature_Query_Condition(pstate); + Supports_Condition* cond = new (ctx.mem) Supports_Condition(pstate); if (!lex< exactly<'('> >()) error("@supports declaration expected '('", pstate); while (!peek< exactly<')'> >(position) && !peek< exactly<'{'> >(position)) - (*cond) << parse_feature_query(); + (*cond) << parse_supports_query(); if (!lex< exactly<')'> >()) error("unclosed parenthesis in @supports declaration", pstate); return (cond->length() == 1) ? (*cond)[0] : cond; } - Feature_Query_Condition* Parser::parse_supports_negation() + Supports_Condition* Parser::parse_supports_negation() { lex< kwd_not >(); - Feature_Query_Condition* cond = parse_feature_query(); - cond->operand(Feature_Query_Condition::NOT); + Supports_Condition* cond = parse_supports_query(); + cond->operand(Supports_Condition::NOT); return cond; } - Feature_Query_Condition* Parser::parse_supports_conjunction() + Supports_Condition* Parser::parse_supports_conjunction() { lex< kwd_and >(); - Feature_Query_Condition* cond = parse_feature_query(); - cond->operand(Feature_Query_Condition::AND); + Supports_Condition* cond = parse_supports_query(); + cond->operand(Supports_Condition::AND); return cond; } - Feature_Query_Condition* Parser::parse_supports_disjunction() + Supports_Condition* Parser::parse_supports_disjunction() { lex< kwd_or >(); - Feature_Query_Condition* cond = parse_feature_query(); - cond->operand(Feature_Query_Condition::OR); + Supports_Condition* cond = parse_supports_query(); + cond->operand(Supports_Condition::OR); return cond; } - Feature_Query_Condition* Parser::parse_supports_declaration() + Supports_Condition* Parser::parse_supports_declaration() { Declaration* declaration = parse_declaration(); - Feature_Query_Condition* cond = new (ctx.mem) Feature_Query_Condition(declaration->pstate(), + Supports_Condition* cond = new (ctx.mem) Supports_Condition(declaration->pstate(), 1, declaration->property(), declaration->value()); @@ -1976,7 +1978,7 @@ namespace Sass { ParserState at_source_position = pstate; Block* body = 0; At_Root_Expression* expr = 0; - Selector_Lookahead lookahead_result; + Lookahead lookahead_result; in_at_root = true; if (peek< exactly<'('> >()) { expr = parse_at_root_expression(); @@ -2027,13 +2029,13 @@ namespace Sass { ParserState at_source_position = pstate; Selector* sel = 0; Expression* val = 0; - Selector_Lookahead lookahead = lookahead_for_extension_target(position); + Lookahead lookahead = lookahead_for_include(position); if (lookahead.found) { if (lookahead.has_interpolants) { sel = parse_selector_schema(lookahead.found); } else { - sel = parse_selector_group(); + sel = parse_selector_list(); } } else if (!(peek >() || peek >() || peek >())) { @@ -2064,7 +2066,13 @@ namespace Sass { return new (ctx.mem) Debug(pstate, parse_list()); } - Selector_Lookahead Parser::lookahead_for_selector(const char* start) + Return* Parser::parse_return_directive() + { + lex< kwd_return_directive >(); + return new (ctx.mem) Return(pstate, parse_list()); + } + + Lookahead Parser::lookahead_for_selector(const char* start) { const char* p = start ? start : position; const char* q; @@ -2121,14 +2129,14 @@ namespace Sass { if (*(p - 1) == '}') saw_interpolant = true; } - Selector_Lookahead result; + Lookahead result; result.found = saw_stuff && peek< exactly<'{'> >(p) ? p : 0; result.has_interpolants = saw_interpolant; return result; } - Selector_Lookahead Parser::lookahead_for_extension_target(const char* start) + Lookahead Parser::lookahead_for_include(const char* start) { const char* p = start ? start : position; const char* q; @@ -2176,13 +2184,13 @@ namespace Sass { (q = peek< sequence< one_plus< exactly<'-'> >, interpolant > >(p)) || (q = peek< sequence< pseudo_prefix, interpolant > >(p)) || (q = peek< interpolant >(p)) || - (q = peek< optional >(p))) { + (q = peek< kwd_optional >(p))) { p = q; if (*(p - 1) == '}') saw_interpolant = true; saw_stuff = true; } - Selector_Lookahead result; + Lookahead result; result.found = peek< alternatives< exactly<';'>, exactly<'}'>, exactly<'{'> > >(p) && saw_stuff ? p : 0; result.has_interpolants = saw_interpolant; @@ -2190,7 +2198,7 @@ namespace Sass { } - Selector_Lookahead Parser::lookahead_for_value(const char* start) + Lookahead Parser::lookahead_for_value(const char* start) { const char* p = start ? start : position; const char* q; @@ -2226,13 +2234,13 @@ namespace Sass { (q = peek< sequence< one_plus< exactly<'-'> >, interpolant > >(p)) || (q = peek< sequence< pseudo_prefix, interpolant > >(p)) || (q = peek< interpolant >(p)) || - (q = peek< optional >(p))) { + (q = peek< kwd_optional >(p))) { p = q; if (*(p - 1) == '}') saw_interpolant = true; saw_stuff = true; } - Selector_Lookahead result; + Lookahead result; result.found = peek< alternatives< exactly<';'>, exactly<'}'>, exactly<'{'> > >(p) && saw_stuff ? p : 0; result.has_interpolants = saw_interpolant; diff --git a/parser.hpp b/parser.hpp index d5cd3123fe..0a8303d47f 100644 --- a/parser.hpp +++ b/parser.hpp @@ -11,8 +11,9 @@ #include "position.hpp" #include "prelexer.hpp" -struct Selector_Lookahead { +struct Lookahead { const char* found; + const char* position; bool has_interpolants; }; @@ -27,7 +28,6 @@ namespace Sass { void add_single_file (Import* imp, string import_path); void import_single_file (Import* imp, string import_path); public: - class AST_Node; enum Syntactic_Context { nothing, mixin_def, function_def }; bool do_import(const string& import_path, Import* imp, vector importers, bool only_one = true); @@ -144,7 +144,7 @@ namespace Sass { // assertion that we actually lexed something if (it_after_token == it_before_token) return 0; - // create new lexed token object (holds all parse result information) + // create new lexed token object (holds the parse results) lexed = Token(position, it_before_token, it_after_token); // advance position (add whitespace before current token) @@ -207,16 +207,16 @@ namespace Sass { Definition* parse_definition(); Parameters* parse_parameters(); Parameter* parse_parameter(); - Mixin_Call* parse_mixin_call(); + Mixin_Call* parse_include_directive(); Arguments* parse_arguments(bool has_url = false); Argument* parse_argument(bool has_url = false); Assignment* parse_assignment(); // Propset* parse_propset(); - Ruleset* parse_ruleset(Selector_Lookahead lookahead); + Ruleset* parse_ruleset(Lookahead lookahead); Selector_Schema* parse_selector_schema(const char* end_of_selector); - Selector_List* parse_selector_group(); - Complex_Selector* parse_selector_combination(); - Compound_Selector* parse_simple_selector_sequence(); + Selector_List* parse_selector_list(); + Complex_Selector* parse_complex_selector(); + Compound_Selector* parse_compound_selector(); Simple_Selector* parse_simple_selector(); Wrapped_Selector* parse_negated_selector(); Simple_Selector* parse_pseudo_selector(); @@ -233,7 +233,7 @@ namespace Sass { Expression* parse_conjunction(); Expression* parse_relation(); Expression* parse_expression(); - Expression* parse_term(); + Expression* parse_operators(); Expression* parse_factor(); Expression* parse_value(); Function_Call* parse_calc_function(); @@ -253,18 +253,19 @@ namespace Sass { For* parse_for_directive(); Each* parse_each_directive(); While* parse_while_directive(); + Return* parse_return_directive(); Media_Block* parse_media_block(); List* parse_media_queries(); Media_Query* parse_media_query(); Media_Query_Expression* parse_media_expression(); - Feature_Block* parse_feature_block(); - Feature_Query* parse_feature_queries(); - Feature_Query_Condition* parse_feature_query(); - Feature_Query_Condition* parse_feature_query_in_parens(); - Feature_Query_Condition* parse_supports_negation(); - Feature_Query_Condition* parse_supports_conjunction(); - Feature_Query_Condition* parse_supports_disjunction(); - Feature_Query_Condition* parse_supports_declaration(); + Supports_Block* parse_supports_directive(); + Supports_Query* parse_supports_queries(); + Supports_Condition* parse_supports_query(); + Supports_Condition* parse_feature_query_in_parens(); + Supports_Condition* parse_supports_negation(); + Supports_Condition* parse_supports_conjunction(); + Supports_Condition* parse_supports_disjunction(); + Supports_Condition* parse_supports_declaration(); At_Root_Block* parse_at_root_block(); At_Root_Expression* parse_at_root_expression(); At_Rule* parse_at_rule(); @@ -274,9 +275,9 @@ namespace Sass { void parse_block_comments(Block* block); - Selector_Lookahead lookahead_for_value(const char* start = 0); - Selector_Lookahead lookahead_for_selector(const char* start = 0); - Selector_Lookahead lookahead_for_extension_target(const char* start = 0); + Lookahead lookahead_for_value(const char* start = 0); + Lookahead lookahead_for_selector(const char* start = 0); + Lookahead lookahead_for_include(const char* start = 0); Expression* fold_operands(Expression* base, vector& operands, Binary_Expression::Type op); Expression* fold_operands(Expression* base, vector& operands, vector& ops); diff --git a/position.cpp b/position.cpp index 31b7a733e1..fae784c557 100644 --- a/position.cpp +++ b/position.cpp @@ -96,13 +96,13 @@ namespace Sass { : Offset(line, column), file(file) { } - ParserState::ParserState(string path, const char* src, const size_t 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() { } - ParserState::ParserState(string path, const char* src, Position position, Offset offset) + ParserState::ParserState(const char* path, const char* src, const Position& position, Offset offset) : Position(position), path(path), src(src), offset(offset), token() { } - ParserState::ParserState(string path, const char* src, Token token, Position position, Offset offset) + 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::add(const char* begin, const char* end) diff --git a/position.hpp b/position.hpp index 1d19fcaf6f..eca275722a 100644 --- a/position.hpp +++ b/position.hpp @@ -104,9 +104,9 @@ namespace Sass { class ParserState : public Position { public: // c-tor - ParserState(string path, const char* src = 0, const size_t file = string::npos); - ParserState(string path, const char* src, Position position, Offset offset = Offset(0, 0)); - ParserState(string path, const char* src, Token token, Position position, Offset offset = Offset(0, 0)); + ParserState(const char* path, const char* src = 0, const size_t file = 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; } @@ -114,7 +114,7 @@ namespace Sass { ParserState pstate() { return *this; } public: - string path; + const char* path; const char* src; Offset offset; Token token; diff --git a/posix/getopt.c b/posix/getopt.c index ac1fda426e..e65eb0d57d 100644 --- a/posix/getopt.c +++ b/posix/getopt.c @@ -49,6 +49,11 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#ifdef _MSC_VER +#define _CRT_SECURE_NO_WARNINGS +#define _CRT_NONSTDC_NO_DEPRECATE +#endif + #include #include #include diff --git a/prelexer.cpp b/prelexer.cpp index 132a6ee376..ca65af561b 100644 --- a/prelexer.cpp +++ b/prelexer.cpp @@ -151,8 +151,7 @@ namespace Sass { // skip escapes sequence < exactly < '\\' >, - exactly < '\r' >, - exactly < '\n' > + re_linebreak >, escape_seq, // skip interpolants @@ -175,8 +174,7 @@ namespace Sass { // skip escapes sequence < exactly < '\\' >, - exactly < '\r' >, - exactly < '\n' > + re_linebreak >, escape_seq, // skip interpolants @@ -240,7 +238,7 @@ namespace Sass { return word(src); } - const char* kwd_supports(const char* src) { + const char* kwd_supports_directive(const char* src) { return word(src); } @@ -256,7 +254,7 @@ namespace Sass { return word(src); } - const char* kwd_include(const char* src) { + const char* kwd_include_directive(const char* src) { return word(src); } @@ -477,13 +475,13 @@ namespace Sass { filename_schema >(src); // optional trailing slash }*/ // Match CSS "!important" keyword. - const char* important(const char* src) { + const char* kwd_important(const char* src) { return sequence< exactly<'!'>, optional_css_whitespace, word >(src); } // Match CSS "!optional" keyword. - const char* optional(const char* src) { + const char* kwd_optional(const char* src) { return sequence< exactly<'!'>, optional_css_whitespace, word >(src); @@ -508,8 +506,8 @@ namespace Sass { const char* functional_schema(const char* src) { return sequence< identifier_schema, exactly<'('> >(src); } - const char* functional(const char* src) { - return sequence< identifier, exactly<'('> >(src); + const char* re_pseudo_selector(const char* src) { + return sequence< identifier, optional < block_comment >, exactly<'('> >(src); } // Match the CSS negation pseudo-class. const char* pseudo_not(const char* src) { diff --git a/prelexer.hpp b/prelexer.hpp index 7d519c6fc0..333a5fc9b1 100644 --- a/prelexer.hpp +++ b/prelexer.hpp @@ -215,13 +215,13 @@ namespace Sass { const char* kwd_with_directive(const char* src); const char* kwd_without_directive(const char* src); const char* kwd_media(const char* src); - const char* kwd_supports(const char* src); + const char* kwd_supports_directive(const char* src); // const char* keyframes(const char* src); // const char* keyf(const char* src); const char* kwd_mixin(const char* src); const char* kwd_function(const char* src); const char* kwd_return_directive(const char* src); - const char* kwd_include(const char* src); + const char* kwd_include_directive(const char* src); const char* kwd_content(const char* src); const char* kwd_extend(const char* src); @@ -276,16 +276,16 @@ namespace Sass { const char* uri_prefix(const char* src); const char* uri_value(const char* src); // Match CSS "!important" keyword. - const char* important(const char* src); + const char* kwd_important(const char* src); // Match CSS "!optional" keyword. - const char* optional(const char* src); + const char* kwd_optional(const char* src); // Match Sass "!default" keyword. const char* default_flag(const char* src); const char* global_flag(const char* src); // Match CSS pseudo-class/element prefixes const char* pseudo_prefix(const char* src); // Match CSS function call openers. - const char* functional(const char* src); + const char* re_pseudo_selector(const char* src); const char* functional_schema(const char* src); const char* pseudo_not(const char* src); // Match CSS 'odd' and 'even' keywords for functional pseudo-classes. diff --git a/sass.h b/sass.h index b2841b5b11..cb5eef2514 100644 --- a/sass.h +++ b/sass.h @@ -1,6 +1,12 @@ #ifndef SASS_H #define SASS_H +#ifdef _MSC_VER +#define _SCL_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#define _CRT_NONSTDC_NO_DEPRECATE +#endif + #include #include diff --git a/sass2scss.cpp b/sass2scss.cpp index 54e65382d9..6477c2575a 100644 --- a/sass2scss.cpp +++ b/sass2scss.cpp @@ -1,3 +1,8 @@ +#ifdef _MSC_VER +#define _CRT_SECURE_NO_WARNINGS +#define _CRT_NONSTDC_NO_DEPRECATE +#endif + // include library #include #include diff --git a/sass_context.cpp b/sass_context.cpp index 24e02f1e07..de82bec332 100644 --- a/sass_context.cpp +++ b/sass_context.cpp @@ -226,7 +226,7 @@ extern "C" { string cwd(Sass::File::get_cwd()); JsonNode* json_err = json_mkobject(); json_append_member(json_err, "status", json_mknumber(1)); - json_append_member(json_err, "file", json_mkstring(e.pstate.path.c_str())); + json_append_member(json_err, "file", json_mkstring(e.pstate.path)); json_append_member(json_err, "line", json_mknumber(e.pstate.line+1)); json_append_member(json_err, "column", json_mknumber(e.pstate.column+1)); json_append_member(json_err, "message", json_mkstring(e.message.c_str())); @@ -236,7 +236,9 @@ extern "C" { bool got_newline = false; msg_stream << msg_prefix; for (char chr : e.message) { - if (chr == '\n') { + if (chr == '\r') { + got_newline = true; + } else if (chr == '\n') { got_newline = true; } else if (got_newline) { msg_stream << string(msg_prefix.size(), ' '); @@ -272,9 +274,9 @@ extern "C" { c_ctx->error_json = json_stringify(json_err, " ");; c_ctx->error_message = sass_strdup(msg_stream.str().c_str()); - c_ctx->error_text = strdup(e.message.c_str()); + c_ctx->error_text = sass_strdup(e.message.c_str()); c_ctx->error_status = 1; - c_ctx->error_file = sass_strdup(e.pstate.path.c_str()); + c_ctx->error_file = sass_strdup(e.pstate.path); c_ctx->error_line = e.pstate.line+1; c_ctx->error_column = e.pstate.column+1; c_ctx->error_src = e.pstate.src; @@ -290,7 +292,7 @@ extern "C" { json_append_member(json_err, "message", json_mkstring(ba.what())); c_ctx->error_json = json_stringify(json_err, " ");; c_ctx->error_message = sass_strdup(msg_stream.str().c_str()); - c_ctx->error_text = strdup(ba.what()); + c_ctx->error_text = sass_strdup(ba.what()); c_ctx->error_status = 2; c_ctx->output_string = 0; c_ctx->source_map_string = 0; @@ -304,7 +306,7 @@ extern "C" { json_append_member(json_err, "message", json_mkstring(e.what())); c_ctx->error_json = json_stringify(json_err, " ");; c_ctx->error_message = sass_strdup(msg_stream.str().c_str()); - c_ctx->error_text = strdup(e.what()); + c_ctx->error_text = sass_strdup(e.what()); c_ctx->error_status = 3; c_ctx->output_string = 0; c_ctx->source_map_string = 0; @@ -318,7 +320,7 @@ extern "C" { json_append_member(json_err, "message", json_mkstring(e.c_str())); c_ctx->error_json = json_stringify(json_err, " ");; c_ctx->error_message = sass_strdup(msg_stream.str().c_str()); - c_ctx->error_text = strdup(e.c_str()); + c_ctx->error_text = sass_strdup(e.c_str()); c_ctx->error_status = 4; c_ctx->output_string = 0; c_ctx->source_map_string = 0; @@ -332,7 +334,7 @@ extern "C" { json_append_member(json_err, "message", json_mkstring("unknown")); c_ctx->error_json = json_stringify(json_err, " ");; c_ctx->error_message = sass_strdup(msg_stream.str().c_str()); - c_ctx->error_text = strdup("unknown"); + c_ctx->error_text = sass_strdup("unknown"); c_ctx->error_status = 5; c_ctx->output_string = 0; c_ctx->source_map_string = 0; @@ -665,8 +667,8 @@ extern "C" { if (compiler->c_ctx->error_status) return compiler->c_ctx->error_status; compiler->state = SASS_COMPILER_EXECUTED; - Context* cpp_ctx = (Context*) compiler->cpp_ctx; - Block* root = (Block*) compiler->root; + Context* cpp_ctx = compiler->cpp_ctx; + Block* root = compiler->root; // compile the parsed root block try { compiler->c_ctx->output_string = cpp_ctx->compile_block(root); } // pass catched errors to generic error handler @@ -780,9 +782,9 @@ extern "C" { void ADDCALL sass_delete_compiler (struct Sass_Compiler* compiler) { if (compiler == 0) return; - Context* cpp_ctx = (Context*) compiler->cpp_ctx; + Context* cpp_ctx = compiler->cpp_ctx; + if (cpp_ctx) delete(cpp_ctx); compiler->cpp_ctx = 0; - delete cpp_ctx; free(compiler); } diff --git a/sass_functions.cpp b/sass_functions.cpp index 52c037554a..f0db3349d1 100644 --- a/sass_functions.cpp +++ b/sass_functions.cpp @@ -124,7 +124,7 @@ extern "C" { { if (import == 0) return 0; if (import->error) free(import->error); - import->error = error ? strdup(error) : 0; + import->error = error ? sass_strdup(error) : 0; import->line = line ? line : -1; import->column = col ? col : -1; return import; diff --git a/sass_util.cpp b/sass_util.cpp index 7510e718b2..fda191aeff 100644 --- a/sass_util.cpp +++ b/sass_util.cpp @@ -108,7 +108,7 @@ namespace Sass { return flattened end */ - Node flatten(const Node& arr, Context& ctx, int n = -1) { + Node flatten(Node& arr, Context& ctx, int n = -1) { if (n != -1 && n == 0) { return arr; } diff --git a/sass_util.hpp b/sass_util.hpp index 3fc4ec0f0f..acff5b64f7 100644 --- a/sass_util.hpp +++ b/sass_util.hpp @@ -173,7 +173,7 @@ namespace Sass { # @param n [int] The number of levels to flatten # @return [NodeCollection] The flattened array */ - Node flatten(const Node& arr, Context& ctx, int n = -1); + Node flatten(Node& arr, Context& ctx, int n = -1); /* diff --git a/test/test_node.cpp b/test/test_node.cpp index fb6ee2c96f..88ba1b2122 100644 --- a/test/test_node.cpp +++ b/test/test_node.cpp @@ -34,7 +34,7 @@ namespace Sass { static Complex_Selector* createComplexSelector(string src) { string temp(src); temp += ";"; - return (*Parser::from_c_str(temp.c_str(), ctx, "", Position()).parse_selector_group())[0]; + return (*Parser::from_c_str(temp.c_str(), ctx, "", Position()).parse_selector_list())[0]; } diff --git a/test/test_selector_difference.cpp b/test/test_selector_difference.cpp index 9f6e465296..95d78d9ecd 100644 --- a/test/test_selector_difference.cpp +++ b/test/test_selector_difference.cpp @@ -12,7 +12,7 @@ Context ctx = Context::Data(); To_String to_string; Compound_Selector* selector(string src) -{ return Parser::from_c_str(src.c_str(), ctx, "", Position()).parse_simple_selector_sequence(); } +{ return Parser::from_c_str(src.c_str(), ctx, "", Position()).parse_compound_selector(); } void diff(string s, string t) { diff --git a/test/test_specificity.cpp b/test/test_specificity.cpp index c0e15a7a72..7147587d37 100644 --- a/test/test_specificity.cpp +++ b/test/test_specificity.cpp @@ -12,7 +12,7 @@ Context ctx = Context::Data(); To_String to_string; Selector* selector(string src) -{ return Parser::from_c_str(src.c_str(), ctx, "", Position()).parse_selector_group(); } +{ return Parser::from_c_str(src.c_str(), ctx, "", Position()).parse_selector_list(); } void spec(string sel) { cout << sel << "\t::\t" << selector(sel + ";")->specificity() << endl; } diff --git a/test/test_superselector.cpp b/test/test_superselector.cpp index 48c8535559..8e25389a7b 100644 --- a/test/test_superselector.cpp +++ b/test/test_superselector.cpp @@ -10,10 +10,10 @@ Context ctx = Context(Context::Data()); To_String to_string; Compound_Selector* compound_selector(string src) -{ return Parser::from_c_str(src.c_str(), ctx, "", Position()).parse_simple_selector_sequence(); } +{ return Parser::from_c_str(src.c_str(), ctx, "", Position()).parse_compound_selector(); } Complex_Selector* complex_selector(string src) -{ return Parser::from_c_str(src.c_str(), ctx, "", Position()).parse_selector_combination(); } +{ return Parser::from_c_str(src.c_str(), ctx, "", Position()).parse_complex_selector(); } void check_compound(string s1, string s2) { diff --git a/test/test_unification.cpp b/test/test_unification.cpp index 4d957e4b52..c9a38e0ce3 100644 --- a/test/test_unification.cpp +++ b/test/test_unification.cpp @@ -10,7 +10,7 @@ Context ctx = Context(Context::Data()); To_String to_string; Compound_Selector* selector(string src) -{ return Parser::from_c_str(src.c_str(), ctx, "", Position()).parse_simple_selector_sequence(); } +{ return Parser::from_c_str(src.c_str(), ctx, "", Position()).parse_compound_selector(); } void unify(string lhs, string rhs) { diff --git a/to_string.cpp b/to_string.cpp index 361c47facc..cedd8f4145 100644 --- a/to_string.cpp +++ b/to_string.cpp @@ -20,7 +20,7 @@ namespace Sass { Emitter emitter(ctx); Inspect i(emitter); i.in_declaration = in_declaration; - n->perform(&i); + if (n) n->perform(&i); return i.get_buffer(); } diff --git a/util.cpp b/util.cpp index 778f3241d6..e440facc90 100644 --- a/util.cpp +++ b/util.cpp @@ -1,7 +1,9 @@ -#include +#include #include "ast.hpp" #include "util.hpp" +#include "lexer.hpp" #include "prelexer.hpp" +#include "constants.hpp" #include "utf8/checked.h" namespace Sass { @@ -460,12 +462,23 @@ namespace Sass { bool peek_linefeed(const char* start) { - while (*start) { - if (*start == '\n' || *start == '\r') return true; - if (*start != ' ' && *start != '\t') return false; - ++ start; - } - return false; + using namespace Prelexer; + using namespace Constants; + return sequence < + zero_plus < + alternatives < + exactly <' '>, + exactly <'\t'>, + line_comment, + delimited_by < + slash_star, + star_slash, + false + > + > + >, + re_linebreak + >(start) != 0; } namespace Util { @@ -568,7 +581,7 @@ namespace Sass { return isPrintable(e, style); } - bool isPrintable(Feature_Block* f, Output_Style style) { + bool isPrintable(Supports_Block* f, Output_Style style) { if (f == NULL) { return false; } @@ -661,8 +674,8 @@ namespace Sass { return true; } } - else if (typeid(*stm) == typeid(Feature_Block)) { - Feature_Block* f = (Feature_Block*) stm; + else if (typeid(*stm) == typeid(Supports_Block)) { + Supports_Block* f = (Supports_Block*) stm; if (isPrintable(f, style)) { return true; } diff --git a/util.hpp b/util.hpp index 09d08f43af..10237318f1 100644 --- a/util.hpp +++ b/util.hpp @@ -40,7 +40,7 @@ namespace Sass { bool containsAnyPrintableStatements(Block* b); bool isPrintable(Ruleset* r, Output_Style style = NESTED); - bool isPrintable(Feature_Block* r, Output_Style style = NESTED); + bool isPrintable(Supports_Block* r, Output_Style style = NESTED); bool isPrintable(Media_Block* r, Output_Style style = NESTED); bool isPrintable(Block* b, Output_Style style = NESTED); bool isPrintable(String_Constant* s, Output_Style style = NESTED);