From bbfcf49332176a926ee86006ccae65c4705ce5d3 Mon Sep 17 00:00:00 2001 From: Marcel Greter Date: Sat, 17 Mar 2018 04:34:06 +0100 Subject: [PATCH] Add distinct `Parent_Reference` class for values --- src/ast.cpp | 5 +++-- src/ast.hpp | 18 ++++++++++++++++++ src/ast_fwd_decl.hpp | 5 +++++ src/debugger.hpp | 9 +++++++++ src/eval.cpp | 17 +++++++++++++++++ src/eval.hpp | 1 + src/operation.hpp | 2 ++ src/parser.cpp | 2 +- 8 files changed, 56 insertions(+), 3 deletions(-) diff --git a/src/ast.cpp b/src/ast.cpp index f03eb9ccc..357bd778d 100644 --- a/src/ast.cpp +++ b/src/ast.cpp @@ -1590,8 +1590,8 @@ namespace Sass { bool Selector_Schema::has_real_parent_ref() const { 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(); + if (schema->length() == 0) return false; + return Cast(schema->at(0)); } return false; } @@ -2188,6 +2188,7 @@ namespace Sass { IMPLEMENT_AST_OPERATORS(Color); IMPLEMENT_AST_OPERATORS(Null); IMPLEMENT_AST_OPERATORS(Parent_Selector); + IMPLEMENT_AST_OPERATORS(Parent_Reference); IMPLEMENT_AST_OPERATORS(Import); IMPLEMENT_AST_OPERATORS(Import_Stub); IMPLEMENT_AST_OPERATORS(Function_Call); diff --git a/src/ast.hpp b/src/ast.hpp index f7874b36e..7ea0557d0 100644 --- a/src/ast.hpp +++ b/src/ast.hpp @@ -2403,6 +2403,24 @@ namespace Sass { ATTACH_CRTP_PERFORM_METHODS() }; + ////////////////////////////////// + // The Parent Reference Expression. + ////////////////////////////////// + class Parent_Reference : public Value { + public: + Parent_Reference(ParserState pstate) + : Value(pstate) {} + Parent_Reference(const Parent_Reference* ptr) + : Value(ptr) {} + std::string type() const { return "parent"; } + static std::string type_name() { return "parent"; } + virtual bool operator==(const Expression& rhs) const { + return true; // can they ever be not equal? + }; + ATTACH_AST_OPERATIONS(Parent_Reference) + ATTACH_CRTP_PERFORM_METHODS() + }; + ///////////////////////////////////////////////////////////////////////// // Placeholder selectors (e.g., "%foo") for use in extend-only selectors. ///////////////////////////////////////////////////////////////////////// diff --git a/src/ast_fwd_decl.hpp b/src/ast_fwd_decl.hpp index 6176233b9..611995df9 100644 --- a/src/ast_fwd_decl.hpp +++ b/src/ast_fwd_decl.hpp @@ -30,6 +30,10 @@ namespace Sass { typedef Simple_Selector* Simple_Selector_Ptr; typedef Simple_Selector const* Simple_Selector_Ptr_Const; + class Parent_Reference; + typedef Parent_Reference* Parent_Reference_Ptr; + typedef Parent_Reference const* Parent_Reference_Ptr_Const; + class PreValue; typedef PreValue* PreValue_Ptr; typedef PreValue const* PreValue_Ptr_Const; @@ -336,6 +340,7 @@ namespace Sass { IMPL_MEM_OBJ(At_Root_Query); IMPL_MEM_OBJ(Null); IMPL_MEM_OBJ(Parent_Selector); + IMPL_MEM_OBJ(Parent_Reference); IMPL_MEM_OBJ(Parameter); IMPL_MEM_OBJ(Parameters); IMPL_MEM_OBJ(Argument); diff --git a/src/debugger.hpp b/src/debugger.hpp index 40186140e..e969ea38b 100644 --- a/src/debugger.hpp +++ b/src/debugger.hpp @@ -111,6 +111,15 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) // Expression_Ptr expression = Cast(node); // std::cerr << ind << "Expression " << expression << " " << expression->concrete_type() << std::endl; + } else if (Cast(node)) { + Parent_Reference_Ptr selector = Cast(node); + std::cerr << ind << "Parent_Reference " << selector; +// if (selector->not_selector()) cerr << " [in_declaration]"; + std::cerr << " (" << pstate_source_position(node) << ")"; + std::cerr << " <" << selector->hash() << ">"; + std::cerr << " <" << prettyprint(selector->pstate().token.ws_before()) << ">" << std::endl; +// debug_ast(selector->selector(), ind + "->", env); + } else if (Cast(node)) { Parent_Selector_Ptr selector = Cast(node); std::cerr << ind << "Parent_Selector " << selector; diff --git a/src/eval.cpp b/src/eval.cpp index 17bc910cd..83e8a2d64 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -1173,6 +1173,11 @@ namespace Sass { // XXX: this is never hit via spec tests ex = ex->perform(this); } + // parent selector needs another go + if (Cast(ex)) { + // XXX: this is never hit via spec tests + ex = ex->perform(this); + } if (List_Ptr l = Cast(ex)) { List_Obj ll = SASS_MEMORY_NEW(List, l->pstate(), 0, l->separator()); @@ -1575,6 +1580,18 @@ namespace Sass { } } + Expression_Ptr Eval::operator()(Parent_Reference_Ptr p) + { + 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 { + return SASS_MEMORY_NEW(Null, p->pstate()); + } + } + Simple_Selector_Ptr Eval::operator()(Simple_Selector_Ptr s) { return s; diff --git a/src/eval.hpp b/src/eval.hpp index 76bbb91e9..004ebe66c 100644 --- a/src/eval.hpp +++ b/src/eval.hpp @@ -86,6 +86,7 @@ namespace Sass { // actual evaluated selectors Selector_List_Ptr operator()(Selector_Schema_Ptr); Expression_Ptr operator()(Parent_Selector_Ptr); + Expression_Ptr operator()(Parent_Reference_Ptr); // generic fallback template diff --git a/src/operation.hpp b/src/operation.hpp index 92bb44680..415e52b3a 100644 --- a/src/operation.hpp +++ b/src/operation.hpp @@ -81,6 +81,7 @@ namespace Sass { virtual T operator()(Media_Query_Expression_Ptr x) = 0; virtual T operator()(At_Root_Query_Ptr x) = 0; virtual T operator()(Parent_Selector_Ptr x) = 0; + virtual T operator()(Parent_Reference_Ptr x) = 0; // parameters and arguments virtual T operator()(Parameter_Ptr x) = 0; virtual T operator()(Parameters_Ptr x) = 0; @@ -161,6 +162,7 @@ namespace Sass { 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()(Parent_Selector_Ptr x) { return static_cast(this)->fallback(x); } + T operator()(Parent_Reference_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); } diff --git a/src/parser.cpp b/src/parser.cpp index 5b1fd81ed..15b5cf9a1 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1637,7 +1637,7 @@ namespace Sass { if (match< ampersand >()) { warning("In Sass, \"&&\" means two copies of the parent selector. You probably want to use \"and\" instead.", pstate); } - return SASS_MEMORY_NEW(Parent_Selector, pstate); } + return SASS_MEMORY_NEW(Parent_Reference, pstate); } if (lex< kwd_important >()) { return SASS_MEMORY_NEW(String_Constant, pstate, "!important"); }