Commit 0dbb5f9c by Aaron Leung

Optimizing selector representation.

parent fff0027c
......@@ -9,4 +9,15 @@ div {
b: hey orelse ho andalso hoo;
c: hoogoo ! important blah;
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 {
{
Node ruleset(Node::ruleset, line_number, 2);
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);
return ruleset;
}
Node Document::parse_selector_group()
{
Node group(Node::selector_group, line_number, 1);
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;
// Node group(Node::selector_group, line_number, 1);
// group << parse_selector();
// while (lex< exactly<','> >()) group << parse_selector();
// 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 selector(Node::selector, line_number, 1);
if (lex< exactly<'+'> >() ||
lex< exactly<'~'> >() ||
lex< exactly<'>'> >()) {
selector << Node(Node::selector_combinator, line_number, lexed);
}
Node s(parse_simple_selector_sequence());
if (s.has_backref) selector.has_backref = true;
selector << s;
while (lex< exactly<'+'> >() ||
lex< exactly<'~'> >() ||
lex< exactly<'>'> >() ||
lex< ancestor_of >() /*||
s.terminal_backref && lex< no_spaces >()*/) {
selector << Node(Node::selector_combinator, line_number, lexed);
s = parse_simple_selector_sequence();
if (s.has_backref) selector.has_backref = true;
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;
// Node selector(Node::selector, line_number, 1);
// if (lex< exactly<'+'> >() ||
// lex< exactly<'~'> >() ||
// lex< exactly<'>'> >()) {
// selector << Node(Node::selector_combinator, line_number, lexed);
// }
// Node s(parse_simple_selector_sequence());
// if (s.has_backref) selector.has_backref = true;
// selector << s;
// while (lex< exactly<'+'> >() ||
// lex< exactly<'~'> >() ||
// lex< exactly<'>'> >() ||
// lex< ancestor_of >() /*||
// s.terminal_backref && lex< no_spaces >()*/) {
// selector << Node(Node::selector_combinator, line_number, lexed);
// s = parse_simple_selector_sequence();
// if (s.has_backref) selector.has_backref = true;
// selector << s;
// }
// 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 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;
// }
// check for initial and trailing combinators
if (lex< exactly<'+'> >() ||
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< alternatives< type_selector, universal > >()) {
simp1 = Node(Node::simple_selector, line_number, lexed);
}
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) &&
!(peek < exactly<'+'> >(position) ||
peek < exactly<'~'> >(position) ||
......@@ -231,7 +256,34 @@ namespace Sass {
peek < exactly<'{'> >(position))) {
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()
......
......@@ -48,50 +48,78 @@ namespace Sass {
result += prefix;
result += ' ';
}
if (at(0).type == selector_combinator) {
result += at(0).content.token.to_string();
result += ' ';
}
else {
result += at(0).to_string(prefix);
}
// if (at(0).type == selector_combinator) {
// result += at(0).content.token.to_string();
// result += ' ';
// }
// 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) {
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;
} break;
case selector_combinator: {
if (std::isspace(content.token.begin[0])) return string(" ");
else return string(" ") += string(content.token) += string(" ");
return content.token.to_string();
// if (std::isspace(content.token.begin[0])) return string(" ");
// else return string(content.token);
} break;
case simple_selector_sequence: {
string result;
if (!has_backref && !prefix.empty()) {
result += prefix;
result += " ";
}
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;
} break;
case pseudo:
case simple_selector: {
string result(prefix);
if (!prefix.empty()) result += " ";
result += content.token.to_string();
return result;
} break;
case pseudo_negation: {
string result(at(0).to_string(prefix));
result += at(1).to_string(prefix);
string result(prefix);
if (!prefix.empty()) result += " ";
result += at(0).to_string("");
result += at(1).to_string("");
result += ')';
return result;
} break;
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) {
result += at(i).to_string(prefix);
result += at(i).to_string("");
}
result += ')';
return result;
} break;
case attribute_selector: {
string result("[");
string result(prefix);
if (!prefix.empty()) result += " ";
result += "[";
for (int i = 0; i < 3; ++i)
{ result += at(i).to_string(prefix); }
result += ']';
......@@ -326,23 +354,24 @@ namespace Sass {
case ruleset: {
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));
vector<string> new_prefixes;
if (prefixes.empty()) {
new_prefixes.reserve(sel_group.size());
for (int i = 0; i < sel_group.size(); ++i) {
new_prefixes.push_back(sel_group[i].to_string(string()));
new_prefixes.reserve(sel_group_size);
for (int i = 0; i < sel_group_size; ++i) {
new_prefixes.push_back(sel_group_size > 1 ? sel_group[i].to_string(string()) : sel_group.to_string(string()));
}
}
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 j = 0; j < sel_group.size(); ++j) {
new_prefixes.push_back(sel_group[j].to_string(prefixes[i]));
for (int j = 0; j < sel_group_size; ++j) {
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_statements) {
buf << string(2*depth, ' ') << new_prefixes[0];
......@@ -355,12 +384,6 @@ namespace Sass {
if (stm_type == comment || stm_type == rule) {
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;
++depth; // if we printed content at this level, we need to indent any nested rulesets
......@@ -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;
} break;
......
......@@ -11,7 +11,7 @@
div, span {
some: nested stuff;
foo, bar {
more: stuff and so forth;
more: stuff so forth;
blah: blah;
}
}
......
......@@ -11,7 +11,7 @@ a {
a div, a span {
some: nested stuff; }
a div foo, a div bar, a span foo, a span bar {
more: stuff and so forth;
more: stuff so forth;
blah: blah; }
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