Commit f5dfac98 by Aaron Leung

Handling hex arithmetic. Ignoring more janky edge cases. Probably need to handle…

Handling hex arithmetic. Ignoring more janky edge cases. Probably need to handle decimal rgb formats too.
parent 12fcaccb
...@@ -56,19 +56,12 @@ namespace Sass { ...@@ -56,19 +56,12 @@ namespace Sass {
return Node(expr.line_number, numval); return Node(expr.line_number, numval);
} break; } break;
case Node::textual_hex: { case Node::textual_hex: {
// long numval = std::strtol(expr.token.begin + 1, NULL, 16);
// Node result(expr.line_number, numval);
// result.is_hex = true;
// return result;
Node triple(expr.line_number, Node::hex_triple, 3); Node triple(expr.line_number, Node::hex_triple, 3);
Token hext(expr.token.begin+1, expr.token.end); Token hext(expr.token.begin+1, expr.token.end);
if (hext.length() == 6) { if (hext.length() == 6) {
for (int i = 0; i < 6; i += 2) { for (int i = 0; i < 6; i += 2) {
Node thing(expr.line_number, static_cast<double>(std::strtol(string(hext.begin+i, 2).c_str(), NULL, 16))); Node thing(expr.line_number, static_cast<double>(std::strtol(string(hext.begin+i, 2).c_str(), NULL, 16)));
cerr << "evaled a hex triplet: " << thing.to_string("") << endl;
triple << Node(expr.line_number, static_cast<double>(std::strtol(string(hext.begin+i, 2).c_str(), NULL, 16))); triple << Node(expr.line_number, static_cast<double>(std::strtol(string(hext.begin+i, 2).c_str(), NULL, 16)));
} }
} }
...@@ -77,9 +70,7 @@ namespace Sass { ...@@ -77,9 +70,7 @@ namespace Sass {
triple << Node(expr.line_number, static_cast<double>(std::strtol(string(2, hext.begin[i]).c_str(), NULL, 16))); triple << Node(expr.line_number, static_cast<double>(std::strtol(string(2, hext.begin[i]).c_str(), NULL, 16)));
} }
} }
return triple;
return triple;
} break; } break;
default: { default: {
...@@ -88,7 +79,6 @@ namespace Sass { ...@@ -88,7 +79,6 @@ namespace Sass {
} }
} }
Node accumulate(const Node::Type op, Node& acc, Node& rhs) Node accumulate(const Node::Type op, Node& acc, Node& rhs)
{ {
Node lhs(acc.children->back()); Node lhs(acc.children->back());
...@@ -100,6 +90,7 @@ namespace Sass { ...@@ -100,6 +90,7 @@ namespace Sass {
acc.children->pop_back(); acc.children->pop_back();
acc.children->push_back(result); acc.children->push_back(result);
} }
// TO DO: find a way to merge the following two clauses
else if (lhs.type == Node::number && rhs.type == Node::numeric_dimension) { else if (lhs.type == Node::number && rhs.type == Node::numeric_dimension) {
// TO DO: disallow division // TO DO: disallow division
Node result(acc.line_number, operate(op, lnum, rnum), rhs.token); Node result(acc.line_number, operate(op, lnum, rnum), rhs.token);
...@@ -121,6 +112,42 @@ namespace Sass { ...@@ -121,6 +112,42 @@ namespace Sass {
acc.children->pop_back(); acc.children->pop_back();
acc.children->push_back(result); acc.children->push_back(result);
} }
// TO DO: find a way to merge the following two clauses
else if (lhs.type == Node::number && rhs.type == Node::hex_triple) {
if (op != Node::sub && op != Node::div) {
double h1 = operate(op, lhs.numeric_value, rhs.children->at(0).numeric_value);
double h2 = operate(op, lhs.numeric_value, rhs.children->at(1).numeric_value);
double h3 = operate(op, lhs.numeric_value, rhs.children->at(2).numeric_value);
acc.children->pop_back();
acc << Node(acc.line_number, h1, h2, h3);
}
// trying to handle weird edge cases ... not sure if it's worth it
else if (op == Node::div) {
acc << Node(acc.line_number, Node::div);
acc << rhs;
}
else if (op == Node::sub) {
acc << Node(acc.line_number, Node::sub);
acc << rhs;
}
else {
acc << rhs;
}
}
else if (lhs.type == Node::hex_triple && rhs.type == Node::number) {
double h1 = operate(op, lhs.children->at(0).numeric_value, rhs.numeric_value);
double h2 = operate(op, lhs.children->at(1).numeric_value, rhs.numeric_value);
double h3 = operate(op, lhs.children->at(2).numeric_value, rhs.numeric_value);
acc.children->pop_back();
acc << Node(acc.line_number, h1, h2, h3);
}
else if (lhs.type == Node::hex_triple && rhs.type == Node::hex_triple) {
double h1 = operate(op, lhs.children->at(0).numeric_value, rhs.children->at(0).numeric_value);
double h2 = operate(op, lhs.children->at(1).numeric_value, rhs.children->at(1).numeric_value);
double h3 = operate(op, lhs.children->at(2).numeric_value, rhs.children->at(2).numeric_value);
acc.children->pop_back();
acc << Node(acc.line_number, h1, h2, h3);
}
else { else {
// TO DO: disallow division and multiplication on lists // TO DO: disallow division and multiplication on lists
acc.children->push_back(rhs); acc.children->push_back(rhs);
......
...@@ -11,5 +11,11 @@ div { ...@@ -11,5 +11,11 @@ div {
p10: #000000 - 1; // black p10: #000000 - 1; // black
p11: #000000 - #000001; // black p11: #000000 - #000001; // black
p12: #ffff00 + #010100; // yellow p12: #ffff00 + #010100; // yellow
p13: (#101010 / 7) p13: (#101010 / 7);
p14: #000 + 0;
p15: 10 - #222;
p16: #000 - #001;
p17: #f0f + #101;
p18: 10 #222 + 1;
p19: (10 / #222);
} }
\ No newline at end of file
...@@ -78,9 +78,8 @@ namespace Sass { ...@@ -78,9 +78,8 @@ namespace Sass {
case attribute_selector: { case attribute_selector: {
string result("["); string result("[");
result += children->at(0).to_string(prefix); for (int i = 0; i < 3; ++i)
result += children->at(1).to_string(prefix); { result += children->at(i).to_string(prefix); }
result += children->at(2).to_string(prefix);
result += ']'; result += ']';
return result; return result;
} break; } break;
...@@ -116,7 +115,7 @@ namespace Sass { ...@@ -116,7 +115,7 @@ namespace Sass {
// } // }
for (int i = 1; i < children->size(); ++i) { for (int i = 1; i < children->size(); ++i) {
if (!(children->at(i).type == add || if (!(children->at(i).type == add ||
children->at(i).type == sub || // children->at(i).type == sub || // another edge case -- consider uncommenting
children->at(i).type == mul)) { children->at(i).type == mul)) {
result += children->at(i).to_string(prefix); result += children->at(i).to_string(prefix);
} }
...@@ -124,6 +123,15 @@ namespace Sass { ...@@ -124,6 +123,15 @@ namespace Sass {
return result; return result;
} break; } break;
//edge case
case sub: {
return "-";
} break;
case div: {
return "/";
} break;
case numeric_dimension: { case numeric_dimension: {
stringstream ss; stringstream ss;
// ss.setf(std::ios::fixed, std::ios::floatfield); // ss.setf(std::ios::fixed, std::ios::floatfield);
...@@ -141,12 +149,37 @@ namespace Sass { ...@@ -141,12 +149,37 @@ namespace Sass {
} break; } break;
case hex_triple: { case hex_triple: {
stringstream ss; double a = children->at(0).numeric_value;
ss << '#' << std::setw(2) << std::setfill('0'); double b = children->at(1).numeric_value;
for (int i = 0; i < 3; ++i) { double c = children->at(2).numeric_value;
ss << std::hex << std::setw(2) << static_cast<long>(children->at(i).numeric_value); if (a > 0xff && b > 0xff && c > 0xff)
{ return "white"; }
else if (a > 0xff && b > 0xff && c == 0)
{ return "yellow"; }
else if (a == 0 && b > 0xff && c > 0xff)
{ return "aqua"; }
else if (a > 0xff && b == 0 && c > 0xff)
{ return "fuchsia"; }
else if (a > 0xff && b == 0 && c == 0)
{ return "red"; }
else if (a == 0 && b > 0xff && c == 0)
{ return "green"; }
else if (a == 0 && b == 0 && c > 0xff)
{ return "blue"; }
else if (a <= 0 && b <= 0 && c <= 0)
{ return "black"; }
else
{
stringstream ss;
ss << '#' << std::setw(2) << std::setfill('0') << std::hex;
for (int i = 0; i < 3; ++i) {
double x = children->at(i).numeric_value;
if (x > 0xff) x = 0xff;
else if (x < 0) x = 0;
ss << std::hex << std::setw(2) << static_cast<unsigned long>(x);
}
return ss.str();
} }
return ss.str();
} break; } break;
default: { default: {
...@@ -218,12 +251,14 @@ namespace Sass { ...@@ -218,12 +251,14 @@ namespace Sass {
size_t depth, size_t depth,
const vector<string>& prefixes) const vector<string>& prefixes)
{ {
switch (type) { switch (type)
{
case root: case root:
for (int i = 0; i < children->size(); ++i) { for (int i = 0; i < children->size(); ++i) {
children->at(i).emit_nested_css(buf, depth, prefixes); children->at(i).emit_nested_css(buf, depth, prefixes);
} }
break; break;
case ruleset: { case ruleset: {
Node sel_group(children->at(0)); Node sel_group(children->at(0));
Node block(children->at(1)); Node block(children->at(1));
...@@ -268,6 +303,7 @@ namespace Sass { ...@@ -268,6 +303,7 @@ namespace Sass {
if (block.has_rules_or_comments) --depth; if (block.has_rules_or_comments) --depth;
if (depth == 0 && prefixes.empty()) buf << endl; if (depth == 0 && prefixes.empty()) buf << endl;
} break; } break;
default: default:
emit_nested_css(buf, depth); // pass it along to the simpler version emit_nested_css(buf, depth); // pass it along to the simpler version
break; break;
...@@ -276,26 +312,31 @@ namespace Sass { ...@@ -276,26 +312,31 @@ namespace Sass {
void Node::emit_nested_css(stringstream& buf, size_t depth) void Node::emit_nested_css(stringstream& buf, size_t depth)
{ {
switch (type) { switch (type)
{
case rule: case rule:
buf << endl << string(2*depth, ' '); buf << endl << string(2*depth, ' ');
children->at(0).emit_nested_css(buf, depth); // property children->at(0).emit_nested_css(buf, depth); // property
children->at(1).emit_nested_css(buf, depth); // values children->at(1).emit_nested_css(buf, depth); // values
buf << ";"; buf << ";";
break; break;
case property: case property:
buf << string(token) << ": "; buf << string(token) << ": ";
break; break;
case values: case values:
for (int i = 0; i < children->size(); ++i) { for (int i = 0; i < children->size(); ++i) {
buf << " " << string(children->at(i).token); buf << " " << string(children->at(i).token);
} }
break; break;
case comment: case comment:
if (depth != 0) buf << endl; if (depth != 0) buf << endl;
buf << string(2*depth, ' ') << string(token); buf << string(2*depth, ' ') << string(token);
if (depth == 0) buf << endl; if (depth == 0) buf << endl;
break; break;
default: default:
buf << to_string(""); buf << to_string("");
break; break;
......
...@@ -191,6 +191,27 @@ namespace Sass { ...@@ -191,6 +191,27 @@ namespace Sass {
is_hex(false) is_hex(false)
{ ++fresh; } { ++fresh; }
Node(size_t line_number, double a, double b, double c)
: line_number(line_number),
children(new vector<Node>()),
token(Token()),
numeric_value(0),
type(hex_triple),
has_rules_or_comments(false),
has_rulesets(false),
has_propsets(false),
has_backref(false),
from_variable(false),
eval_me(false),
is_hex(true)
{
children->reserve(3);
children->push_back(Node(line_number, a));
children->push_back(Node(line_number, b));
children->push_back(Node(line_number, c));
++fresh;
}
//~Node() { delete children; } //~Node() { delete children; }
Node& operator=(const Node& n) Node& operator=(const Node& n)
......
div {
p01: #abc;
p02: #aabbcc;
p03: #abc + hello;
p04: #abc + 1; // add 1 to each triplet
p05: #abc + #001; // triplet-wise addition
p06: #0000ff + 1; // add 1 to each triplet; ignore overflow because it doesn't correspond to a color name
p07: #0000ff + #000001; // convert overflow to name of color (blue)
p08: #00ffff + #000101; // aqua
p09: #000000;
p10: #000000 - 1; // black
p11: #000000 - #000001; // black
p12: #ffff00 + #010100; // yellow
p13: (#101010 / 7);
p14: #000 + 0;
p15: 10 - #222;
p16: #000 - #001;
p17: #f0f + #101;
p18: 10 #222 + 1;
p19: (10 / #222);
}
\ No newline at end of file
div {
p01: #abc;
p02: #aabbcc;
p03: #aabbcchello;
p04: #abbccd;
p05: #aabbdd;
p06: #0101ff;
p07: blue;
p08: aqua;
p09: #000000;
p10: black;
p11: black;
p12: yellow;
p13: #020202;
p14: black;
p15: 10-#222222;
p16: black;
p17: fuchsia;
p18: 10 #232323;
p19: 10/#222222; }
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