Commit 0dbb5f9c by Aaron Leung

Optimizing selector representation.

parent fff0027c
...@@ -9,4 +9,15 @@ div { ...@@ -9,4 +9,15 @@ div {
b: hey orelse ho andalso hoo; b: hey orelse ho andalso hoo;
c: hoogoo ! important blah; c: hoogoo ! important blah;
d: boogoo !important; d: boogoo !important;
> span {
foo: bar;
hux: blux;
}
}
a {
blah: blah;
f &.b {
blee: blee;
}
} }
\ No newline at end of file
...@@ -148,80 +148,105 @@ namespace Sass { ...@@ -148,80 +148,105 @@ namespace Sass {
{ {
Node ruleset(Node::ruleset, line_number, 2); Node ruleset(Node::ruleset, line_number, 2);
ruleset << parse_selector_group(); ruleset << parse_selector_group();
// if (ruleset[0].type == Node::selector) cerr << "ruleset starts with selector" << endl;
// if (ruleset[0].type == Node::selector_group) cerr << "ruleset starts with selector_group" << endl;
ruleset << parse_block(definition); ruleset << parse_block(definition);
return ruleset; return ruleset;
} }
Node Document::parse_selector_group() Node Document::parse_selector_group()
{ {
Node group(Node::selector_group, line_number, 1); // Node group(Node::selector_group, line_number, 1);
group << parse_selector(); // group << parse_selector();
while (lex< exactly<','> >()) group << parse_selector();
return group;
// Node sel1(parse_selector());
// if (!lex< exactly<','> >()) return sel1;
//
// Node group(Node::selector_group, line_number, 2);
// group << sel1;
// while (lex< exactly<','> >()) group << parse_selector(); // while (lex< exactly<','> >()) group << parse_selector();
// return group; // return group;
Node sel1(parse_selector());
if (!peek< exactly<','> >()) return sel1;
Node group(Node::selector_group, line_number, 2);
group << sel1;
while (lex< exactly<','> >()) group << parse_selector();
return group;
} }
Node Document::parse_selector() Node Document::parse_selector()
{ {
Node selector(Node::selector, line_number, 1); // Node selector(Node::selector, line_number, 1);
if (lex< exactly<'+'> >() || // if (lex< exactly<'+'> >() ||
lex< exactly<'~'> >() || // lex< exactly<'~'> >() ||
lex< exactly<'>'> >()) { // lex< exactly<'>'> >()) {
selector << Node(Node::selector_combinator, line_number, lexed); // selector << Node(Node::selector_combinator, line_number, lexed);
} // }
Node s(parse_simple_selector_sequence()); // Node s(parse_simple_selector_sequence());
if (s.has_backref) selector.has_backref = true; // if (s.has_backref) selector.has_backref = true;
selector << s; // selector << s;
while (lex< exactly<'+'> >() || // while (lex< exactly<'+'> >() ||
lex< exactly<'~'> >() || // lex< exactly<'~'> >() ||
lex< exactly<'>'> >() || // lex< exactly<'>'> >() ||
lex< ancestor_of >() /*|| // lex< ancestor_of >() /*||
s.terminal_backref && lex< no_spaces >()*/) { // s.terminal_backref && lex< no_spaces >()*/) {
selector << Node(Node::selector_combinator, line_number, lexed); // selector << Node(Node::selector_combinator, line_number, lexed);
s = parse_simple_selector_sequence(); // s = parse_simple_selector_sequence();
if (s.has_backref) selector.has_backref = true; // if (s.has_backref) selector.has_backref = true;
selector << s; // selector << s;
}
return selector;
// Node seq1(parse_simple_selector_sequence());
// if (lex< exactly<','> >()) return seq1;
//
// Node selector(Node::selector, line_number, 2);
// if (seq1.has_backref) selector.has_backref = true;
// selector << seq1;
// while (!lex< exactly<','> >()) {
// Node seq(parse_simple_selector_sequence());
// if (seq.has_backref) selector.has_backref = true;
// selector << seq;
// } // }
// return selector; // return selector;
Node seq1(parse_simple_selector_sequence());
if (peek< exactly<','> >() ||
peek< exactly<')'> >() ||
peek< exactly<'{'> >()) return seq1;
Node selector(Node::selector, line_number, 2);
if (seq1.has_backref) selector.has_backref = true;
selector << seq1;
while (!peek< exactly<'{'> >() && !peek< exactly<','> >()) {
Node seq(parse_simple_selector_sequence());
if (seq.has_backref) selector.has_backref = true;
selector << seq;
}
return selector;
} }
Node Document::parse_simple_selector_sequence() Node Document::parse_simple_selector_sequence()
{ {
Node seq(Node::simple_selector_sequence, line_number, 1); // check for initial and trailing combinators
if (lex< alternatives < type_selector, universal > >()) { if (lex< exactly<'+'> >() ||
seq << Node(Node::simple_selector, line_number, lexed); lex< exactly<'~'> >() ||
lex< exactly<'>'> >())
{ return Node(Node::selector_combinator, line_number, lexed); }
// check for backref or type selector, which are only allowed at the front
Node simp1;
bool saw_backref = false;
if (lex< exactly<'&'> >()) {
simp1 = Node(Node::backref, line_number, lexed);
simp1.has_backref = true;
saw_backref = true;
cerr << "parsed a backref" << endl;
} }
else if (lex< exactly<'&'> >()) { else if (lex< alternatives< type_selector, universal > >()) {
seq << Node(Node::backref, line_number, lexed); simp1 = Node(Node::simple_selector, line_number, lexed);
seq.has_backref = true;
// if (peek< sequence< no_spaces, alternatives< type_selector, universal > > >(position)) {
// seq.terminal_backref = true;
// return seq;
// }
} }
else { else {
seq << parse_simple_selector(); simp1 = parse_simple_selector();
} }
// now we have one simple/atomic selector -- see if there are more
if (peek< spaces >() || peek< exactly<'>'> >() ||
peek< exactly<'+'> >() || peek< exactly<'~'> >() ||
peek< exactly<','> >() || peek< exactly<')'> >() ||
peek< exactly<'{'> >())
{ return simp1; }
// now we know we have a sequence of simple selectors
Node seq(Node::simple_selector_sequence, line_number, 2);
seq << simp1;
seq.has_backref = saw_backref;
while (!peek< spaces >(position) && while (!peek< spaces >(position) &&
!(peek < exactly<'+'> >(position) || !(peek < exactly<'+'> >(position) ||
peek < exactly<'~'> >(position) || peek < exactly<'~'> >(position) ||
...@@ -232,6 +257,33 @@ namespace Sass { ...@@ -232,6 +257,33 @@ namespace Sass {
seq << parse_simple_selector(); seq << parse_simple_selector();
} }
return seq; return seq;
//
// Node seq(Node::simple_selector_sequence, line_number, 1);
// if (lex< alternatives < type_selector, universal > >()) {
// seq << Node(Node::simple_selector, line_number, lexed);
// }
// else if (lex< exactly<'&'> >()) {
// seq << Node(Node::backref, line_number, lexed);
// seq.has_backref = true;
// // if (peek< sequence< no_spaces, alternatives< type_selector, universal > > >(position)) {
// // seq.terminal_backref = true;
// // return seq;
// // }
// }
// else {
// seq << parse_simple_selector();
// }
// while (!peek< spaces >(position) &&
// !(peek < exactly<'+'> >(position) ||
// peek < exactly<'~'> >(position) ||
// peek < exactly<'>'> >(position) ||
// peek < exactly<','> >(position) ||
// peek < exactly<')'> >(position) ||
// peek < exactly<'{'> >(position))) {
// seq << parse_simple_selector();
// }
// return seq;
} }
Node Document::parse_selector_combinator() Node Document::parse_selector_combinator()
......
...@@ -48,50 +48,78 @@ namespace Sass { ...@@ -48,50 +48,78 @@ namespace Sass {
result += prefix; result += prefix;
result += ' '; result += ' ';
} }
if (at(0).type == selector_combinator) {
result += at(0).content.token.to_string(); // if (at(0).type == selector_combinator) {
result += ' '; // result += at(0).content.token.to_string();
} // result += ' ';
else { // }
result += at(0).to_string(prefix); // else {
} // Node::Type t = at(0).type;
// result += at(0).to_string(t == backref ? prefix : "");
// }
Node::Type t = at(0).type;
result += at(0).to_string(at(0).has_backref ? prefix : "");
for (int i = 1; i < size(); ++i) { for (int i = 1; i < size(); ++i) {
result += at(i).to_string(prefix); Node::Type t = at(i).type;
result += " ";
result += at(i).to_string(at(0).has_backref ? prefix : "");
} }
return result; return result;
} break; } break;
case selector_combinator: { case selector_combinator: {
if (std::isspace(content.token.begin[0])) return string(" "); return content.token.to_string();
else return string(" ") += string(content.token) += string(" "); // if (std::isspace(content.token.begin[0])) return string(" ");
// else return string(content.token);
} break; } break;
case simple_selector_sequence: { case simple_selector_sequence: {
string result; string result;
if (!has_backref && !prefix.empty()) {
result += prefix;
result += " ";
}
for (int i = 0; i < size(); ++i) { for (int i = 0; i < size(); ++i) {
result += at(i).to_string(prefix); Node::Type t = at(i).type;
result += at(i).to_string(t == backref ? prefix : "");
} }
return result; return result;
} break; } break;
case pseudo:
case simple_selector: {
string result(prefix);
if (!prefix.empty()) result += " ";
result += content.token.to_string();
return result;
} break;
case pseudo_negation: { case pseudo_negation: {
string result(at(0).to_string(prefix)); string result(prefix);
result += at(1).to_string(prefix); if (!prefix.empty()) result += " ";
result += at(0).to_string("");
result += at(1).to_string("");
result += ')'; result += ')';
return result; return result;
} break; } break;
case functional_pseudo: { case functional_pseudo: {
string result(at(0).to_string(prefix)); string result(prefix);
if (!prefix.empty()) result += " ";
result += at(0).to_string("");
for (int i = 1; i < size(); ++i) { for (int i = 1; i < size(); ++i) {
result += at(i).to_string(prefix); result += at(i).to_string("");
} }
result += ')'; result += ')';
return result; return result;
} break; } break;
case attribute_selector: { case attribute_selector: {
string result("["); string result(prefix);
if (!prefix.empty()) result += " ";
result += "[";
for (int i = 0; i < 3; ++i) for (int i = 0; i < 3; ++i)
{ result += at(i).to_string(prefix); } { result += at(i).to_string(prefix); }
result += ']'; result += ']';
...@@ -326,23 +354,24 @@ namespace Sass { ...@@ -326,23 +354,24 @@ namespace Sass {
case ruleset: { case ruleset: {
Node sel_group(at(0)); Node sel_group(at(0));
size_t sel_group_size = (sel_group.type == selector_group) ? sel_group.size() : 1; // parser ensures no singletons
Node block(at(1)); Node block(at(1));
vector<string> new_prefixes; vector<string> new_prefixes;
if (prefixes.empty()) { if (prefixes.empty()) {
new_prefixes.reserve(sel_group.size()); new_prefixes.reserve(sel_group_size);
for (int i = 0; i < sel_group.size(); ++i) { for (int i = 0; i < sel_group_size; ++i) {
new_prefixes.push_back(sel_group[i].to_string(string())); new_prefixes.push_back(sel_group_size > 1 ? sel_group[i].to_string(string()) : sel_group.to_string(string()));
} }
} }
else { else {
new_prefixes.reserve(prefixes.size() * sel_group.size()); new_prefixes.reserve(prefixes.size() * sel_group_size);
for (int i = 0; i < prefixes.size(); ++i) { for (int i = 0; i < prefixes.size(); ++i) {
for (int j = 0; j < sel_group.size(); ++j) { for (int j = 0; j < sel_group_size; ++j) {
new_prefixes.push_back(sel_group[j].to_string(prefixes[i])); new_prefixes.push_back(sel_group_size > 1 ? sel_group[j].to_string(prefixes[i]) : sel_group.to_string(prefixes[i]));
} }
} }
} }
if (block[0].has_expansions) block.flatten(); if (block[0].has_expansions) block.flatten();
if (block[0].has_statements) { if (block[0].has_statements) {
buf << string(2*depth, ' ') << new_prefixes[0]; buf << string(2*depth, ' ') << new_prefixes[0];
...@@ -355,12 +384,6 @@ namespace Sass { ...@@ -355,12 +384,6 @@ namespace Sass {
if (stm_type == comment || stm_type == rule) { if (stm_type == comment || stm_type == rule) {
block[i].emit_nested_css(buf, depth+1); // NEED OVERLOADED VERSION FOR COMMENTS AND RULES block[i].emit_nested_css(buf, depth+1); // NEED OVERLOADED VERSION FOR COMMENTS AND RULES
} }
// else if (stm_type == expansion) {
// // buf << string(2*(depth+1), ' ') << block[i].to_string(""); // TEMPORARY
// for (int j = 0; j < block[i].size(); ++j) {
// block[i][j].emit_nested_css(buf, depth+1);
// }
// }
} }
buf << " }" << endl; buf << " }" << endl;
++depth; // if we printed content at this level, we need to indent any nested rulesets ++depth; // if we printed content at this level, we need to indent any nested rulesets
...@@ -372,7 +395,7 @@ namespace Sass { ...@@ -372,7 +395,7 @@ namespace Sass {
} }
} }
} }
if (block[0].has_statements) --depth; if (block[0].has_statements) --depth; // see previous comment
if (depth == 0 && prefixes.empty()) buf << endl; if (depth == 0 && prefixes.empty()) buf << endl;
} break; } break;
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
div, span { div, span {
some: nested stuff; some: nested stuff;
foo, bar { foo, bar {
more: stuff and so forth; more: stuff so forth;
blah: blah; blah: blah;
} }
} }
......
...@@ -11,7 +11,7 @@ a { ...@@ -11,7 +11,7 @@ a {
a div, a span { a div, a span {
some: nested stuff; } some: nested stuff; }
a div foo, a div bar, a span foo, a span bar { a div foo, a div bar, a span foo, a span bar {
more: stuff and so forth; more: stuff so forth;
blah: blah; } blah: blah; }
div { div {
......
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