Commit 2e2d97a8 by Aaron Leung

Working on selector normalization and ordering.

parent 4e8099aa
......@@ -5,7 +5,7 @@ SOURCES = \
constants.cpp context.cpp functions.cpp document.cpp \
document_parser.cpp eval_apply.cpp node.cpp \
node_factory.cpp node_emitters.cpp prelexer.cpp \
sass_interface.cpp
selector.cpp sass_interface.cpp
OBJECTS = $(SOURCES:.cpp=.o)
all: $(OBJECTS)
......
......@@ -4,7 +4,7 @@ lib_LTLIBRARIES = libsass.la
libsass_la_SOURCES = context.cpp functions.cpp document.cpp \
constants.cpp document_parser.cpp eval_apply.cpp node.cpp \
node_factory.cpp node_emitters.cpp prelexer.cpp \
sass_interface.cpp
selector.cpp sass_interface.cpp
libsass_la_LDFLAGS = -no-undefined -version-info 0:0:0
include_HEADERS = sass_interface.h
......@@ -86,7 +86,7 @@ LTLIBRARIES = $(lib_LTLIBRARIES)
libsass_la_LIBADD =
am_libsass_la_OBJECTS = context.lo functions.lo document.lo \
constants.lo document_parser.lo eval_apply.lo node.lo node_factory.lo \
node_emitters.lo prelexer.lo sass_interface.lo
node_emitters.lo prelexer.lo selector.lo sass_interface.lo
libsass_la_OBJECTS = $(am_libsass_la_OBJECTS)
libsass_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
......@@ -247,7 +247,7 @@ lib_LTLIBRARIES = libsass.la
libsass_la_SOURCES = context.cpp functions.cpp document.cpp \
constants.cpp document_parser.cpp eval_apply.cpp node.cpp \
node_factory.cpp node_emitters.cpp prelexer.cpp \
sass_interface.cpp
selector.cpp sass_interface.cpp
libsass_la_LDFLAGS = -no-undefined -version-info 0:0:0
include_HEADERS = sass_interface.h
......@@ -355,6 +355,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node_emitters.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node_factory.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prelexer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/selector.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sass_interface.Plo@am__quote@
.cpp.o:
......
#include "eval_apply.hpp"
#include "selector.hpp"
#include "constants.hpp"
#include "prelexer.hpp"
#include "document.hpp"
......@@ -106,6 +107,8 @@ namespace Sass {
// }
// expand the body with the newly expanded selector as the prefix
cerr << "ORIGINAL SELECTOR:\t" << expr[2].to_string() << endl;
cerr << "NORMALIZED SELECTOR:\t" << normalize_selector(expr[2], new_Node).to_string() << endl << endl;
expand(expr[1], expr.back(), env, f_env, new_Node, ctx);
} break;
......@@ -1112,8 +1115,11 @@ namespace Sass {
for (multimap<Node, Node>::iterator request = extension_requests.lower_bound(sel);
request != extension_requests.upper_bound(sel);
++request) {
group << generate_extension(expr[2], request->second, new_Node);
Node ext(generate_extension(expr[2], request->second, new_Node));
if (ext.type() == Node::selector_group) group += ext;
else group << ext;
}
group = remove_duplicate_selectors(group, new_Node);
group.has_been_extended() = true;
expr[2] = group;
}
......@@ -1132,13 +1138,16 @@ namespace Sass {
for (multimap<Node, Node>::iterator request = extension_requests.lower_bound(sel);
request != extension_requests.upper_bound(sel);
++request) {
new_group << generate_extension(group[i], request->second, new_Node);
Node ext(generate_extension(group[i], request->second, new_Node));
if (ext.type() == Node::selector_group) new_group += ext;
else new_group << ext;
}
group[i].has_been_extended() = true;
}
}
if (new_group.size() > 0) {
group.has_been_extended() = true;
new_group = remove_duplicate_selectors(new_group, new_Node);
new_group.has_been_extended() = true;
expr[2] = new_group;
}
......
......@@ -61,6 +61,19 @@ namespace Sass {
string Node::unquote() const
{
Type t = type();
switch (type())
{
case string_constant:
case identifier: {
return token().unquote();
} break;
default: {
// do nothing; fall though to the rest
} break;
}
string intermediate(to_string());
if (!intermediate.empty() && (intermediate[0] == '"' || intermediate[0] == '\'')) {
return intermediate.substr(1, intermediate.length() - 2);
......@@ -74,8 +87,11 @@ namespace Sass {
{
Type t = type(), u = rhs.type();
if ((t == identifier || t == string_constant || t == string_schema || t == concatenation) &&
(u == identifier || u == string_constant || u == string_schema || u == concatenation)) {
// if ((t == identifier || t == string_constant || t == string_schema || t == concatenation) &&
// (u == identifier || u == string_constant || u == string_schema || u == concatenation)) {
// return unquote() == rhs.unquote();
// }
if (is_string() && rhs.is_string()) {
return unquote() == rhs.unquote();
}
else if (t != u) {
......@@ -126,8 +142,25 @@ namespace Sass {
return boolean_value() == rhs.boolean_value();
} break;
case selector: {
if (has_children() && rhs.has_children() && (size() == rhs.size())) {
for (size_t i = 0, S = size(); i < S; ++i) {
if (at(i) == rhs[i]) continue;
else return false;
}
return true;
}
else {
return false;
}
} break;
case simple_selector: {
if (token() == rhs.token()) return true;
} break;
default: {
return true;
return false;
} break;
}
return false;
......@@ -163,12 +196,16 @@ namespace Sass {
}
// comparing identifiers and strings (treat them as comparable)
else if ((lhs_type == identifier || lhs_type == string_constant || lhs_type == value) &&
(rhs_type == identifier || lhs_type == string_constant || rhs_type == value)) {
return token().unquote() < rhs.token().unquote();
else if (is_string() && rhs.is_string()) {
return unquote() < rhs.unquote();
}
// COMPARING SELECTORS -- IMPORTANT FOR INHERITANCE
// else if ((lhs_type == identifier || lhs_type == string_constant || lhs_type == value) &&
// (rhs_type == identifier || lhs_type == string_constant || rhs_type == value)) {
// return token().unquote() < rhs.token().unquote();
// }
// COMPARING SELECTORS -- IMPORTANT FOR ORDERING AND NORMALIZING
else if ((type() >= selector_group && type() <=selector_schema) &&
(rhs.type() >= selector_group && rhs.type() <=selector_schema)) {
......@@ -183,13 +220,15 @@ namespace Sass {
return token() < rhs.token();
} break;
// assumes selectors are normalized by the time they're compared
case selector:
case attribute_selector: {
case simple_selector_sequence:
case attribute_selector:
case functional_pseudo:
case pseudo_not: {
return lexicographical_compare(begin(), end(), rhs.begin(), rhs.end());
} break;
default: {
return false;
} break;
......
#include <set>
#include "selector.hpp"
namespace Sass {
using namespace std;
Node normalize_selector(Node s, Node_Factory& new_Node)
{
switch (s.type())
{
case Node::selector_group: {
Node normalized(new_Node(Node::selector_group, s.path(), s.line(), 1));
set<Node> normalizer;
for (size_t i = 0, S = s.size(); i < S; ++i)
normalizer.insert(normalize_selector(s[i], new_Node));
for (set<Node>::iterator i = normalizer.begin(); i != normalizer.end(); ++i)
normalized << *i;
return normalized;
} break;
case Node::selector: {
Node normalized(new_Node(Node::selector, s.path(), s.line(), s.size()));
for (size_t i = 0, S = s.size(); i < S; ++i)
normalized << normalize_selector(s[i], new_Node);
return normalized;
} break;
case Node::simple_selector_sequence: {
Node normalized(new_Node(Node::simple_selector_sequence, s.path(), s.line(), 1));
set<Node> normalizer;
size_t i = 0;
if (!selector_is_qualifier(s[0])) {
normalized << s[0];
i = 1;
}
for (size_t S = s.size(); i < S; ++i)
normalizer.insert(normalize_selector(s[i], new_Node));
for (set<Node>::iterator i = normalizer.begin(); i != normalizer.end(); ++i)
normalized << *i;
return normalized;
} break;
default: {
return s;
} break;
}
return s;
}
// Remove duplicate selectors from a selector group. Used when extending.
Node remove_duplicate_selectors(Node group, Node_Factory& new_Node)
{
if (group.type() != Node::selector_group) return group;
Node filtered(new_Node(Node::selector_group, group.path(), group.line(), 1));
for (size_t i = 0, S = group.size(); i < S; ++i) {
bool found_dup = false;
for (size_t j = 0; j < filtered.size(); ++j) {
if (group[i] == filtered[j]) {
found_dup = true;
break;
}
}
if (!found_dup) filtered << group[i];
}
return filtered;
}
bool selector_is_qualifier(Node s)
{
switch (s.type())
{
case Node::pseudo:
case Node::pseudo_negation:
case Node::functional_pseudo:
case Node::attribute_selector: {
return true;
} break;
case Node::simple_selector: {
if ((*s.token().begin == '.') || (*s.token().begin == '#')) return true;
} break;
default: {
return false;
} break;
}
return false;
}
// Node selector_is_specialization_of(Node s, Node t)
// {
// }
}
\ No newline at end of file
#ifndef SASS_NODE
#include "node.hpp"
#endif
#ifndef SASS_NODE_FACTORY
#include "node_factory.hpp"
#endif
namespace Sass {
Node normalize_selector(Node s, Node_Factory& new_Node);
Node remove_duplicate_selectors(Node group, Node_Factory& new_Node);
bool selector_is_qualifier(Node s);
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment