Commit 71c31368 by Aaron Leung

Improving the node struct, and working on new parsing functionaity.

parent 9a893f9d
......@@ -12,10 +12,10 @@ namespace Sass {
char* path;
char* source;
char* position;
unsigned int line_number;
size_t line_number;
// TO DO: move the environment up into the context class when it's ready
map<string, Node> environment;
map<Token, Node> environment;
vector<Node> statements;
Token top;
......@@ -24,7 +24,8 @@ namespace Sass {
Document(char* _path, char* _source = 0);
~Document();
inline Token& peek() { return top; }
template <prelexer mx>
char* peek() { return mx(position); }
template <prelexer mx>
bool try_munching() {
......@@ -68,7 +69,7 @@ namespace Sass {
Node parse_var_def();
Node parse_ruleset();
Node parse_selector();
Node parse_clauses();
Node parse_block();
Node parse_values();
string emit_css(CSS_Style style);
......
......@@ -3,88 +3,112 @@
namespace Sass {
void Document::parse_scss() {
try_munching<optional_spaces>();
while (*position) {
// try_munching<optional_spaces>();
// while (*position) {
// statements.push_back(parse_statement());
// try_munching<optional_spaces>();
// }
lex<optional_spaces>();
while(*position) {
statements.push_back(parse_statement());
try_munching<optional_spaces>();
lex<optional_spaces>();
}
}
Node Document::parse_statement() {
if (try_munching<block_comment>()) {
return Node(Node::comment, top);
// if (try_munching<block_comment>()) {
// return Node(line_number, Node::comment, top);
// }
// else if (try_munching<variable>()) {
// return parse_var_def();
// }
// else return parse_ruleset();
if (lex<block_comment>()) {
return Node(line_number, Node::comment, lexed);
}
else if (try_munching<variable>()) {
else if (lex<variable>()) {
return parse_var_def();
}
else return parse_ruleset();
}
Node Document::parse_var_def() {
const Token key = top;
try_munching<exactly<':'> >();
environment[string(key)] = parse_values();
try_munching<exactly<';'> >();
return Node(Node::nil);
// const Token key(top);
// try_munching<exactly<':'> >();
// environment[key] = parse_values();
// try_munching<exactly<';'> >();
// return Node(line_number, Node::nil, top);
const Token key(lexed);
lex< exactly<':'> >();
environment[key] = parse_values();
lex< exactly<';'> >();
return Node();
}
Node Document::parse_ruleset() {
Node ruleset(Node::ruleset);
ruleset.push_child(parse_selector());
ruleset.push_child(parse_clauses());
Node ruleset(line_number, Node::ruleset, 2);
ruleset << parse_selector();
ruleset << parse_block();
return ruleset;
}
Node Document::parse_selector() {
try_munching<identifier>();
return Node(Node::selector, top);
return Node(line_number, Node::selector, top);
}
Node Document::parse_clauses() {
Node Document::parse_block() {
try_munching<exactly<'{'> >();
Node decls(Node::clauses);
Node decls(line_number, Node::block);
while(!try_munching<exactly<'}'> >()) {
if (try_munching<block_comment>()) {
decls.push_child(Node(Node::comment, top));
decls << Node(line_number, Node::comment, top);
continue;
}
else if (try_munching<variable>()) {
decls.push_child(parse_var_def());
decls << parse_var_def();
continue;
}
try_munching<identifier>();
Token id = top;
if (try_munching<exactly<':'> >()) {
Node rule(Node::rule);
rule.push_child(Node(Node::property, id));
rule.push_child(parse_values());
decls.push_child(rule);
Node rule(line_number, Node::rule, 2);
rule << Node(line_number, Node::property, id);
rule << parse_values();
decls << rule;
decls.has_rules = true;
try_munching<exactly<';'> >();
}
else {
Node ruleset(Node::ruleset);
ruleset.push_child(Node(Node::selector, id));
ruleset.push_child(parse_clauses());
decls.push_opt_child(ruleset);
Node ruleset(line_number, Node::ruleset, 2);
ruleset << Node(line_number, Node::selector, id);
ruleset << parse_block();
decls << ruleset;
decls.has_rulesets = true;
}
}
return decls;
}
Node Document::parse_values() {
Node values(Node::values);
Node values(line_number, Node::values);
while(try_munching<identifier>() || try_munching<dimension>() ||
try_munching<percentage>() || try_munching<number>() ||
try_munching<hex>() || try_munching<string_constant>() ||
try_munching<variable>()) {
if (top.begin[0] == '$') {
Node stuff(environment[string(top)]);
Node stuff(environment[top]);
for (int i = 0; i < stuff.children->size(); ++i) {
values.push_child((*(stuff.children))[i]);
values << stuff.children->at(i);
}
}
else
values.push_child(Node(Node::value, top));
{
values << Node(line_number, Node::value, top);
}
}
return values;
}
......
......@@ -5,43 +5,44 @@
using std::string;
using std::stringstream;
using std::cout;
using std::cerr;
using std::endl;
namespace Sass {
unsigned int Node::fresh = 0;
unsigned int Node::copied = 0;
Node::Node() { ++fresh; children = 0; opt_children = 0; }
Node::Node(Node_Type _type) {
type = _type;
children = new vector<Node>;
opt_children = new vector<Node>;
++fresh;
}
Node::Node(Node_Type _type, Token& _token) {
type = _type;
token = _token;
children = 0;
opt_children = 0;
++fresh;
}
Node::Node(const Node& n) {
type = n.type;
token = n.token;
children = n.children;
opt_children = n.opt_children;
++copied;
}
size_t Node::fresh = 0;
size_t Node::copied = 0;
// Node::Node() { ++fresh; children = 0; opt_children = 0; }
// Node::Node(Node_Type _type) {
// type = _type;
// children = new vector<Node>;
// opt_children = new vector<Node>;
// ++fresh;
// }
// Node::Node(Node_Type _type, Token& _token) {
// type = _type;
// token = _token;
// children = 0;
// opt_children = 0;
// ++fresh;
// }
// Node::Node(const Node& n) {
// type = n.type;
// token = n.token;
// children = n.children;
// opt_children = n.opt_children;
// ++copied;
// }
//
// void Node::push_child(const Node& node) {
// if (!children) children = new vector<Node>;
// children->push_back(node);
// }
// void Node::push_opt_child(const Node& node) {
// if (!opt_children) opt_children = new vector<Node>;
// opt_children->push_back(node);
// }
void Node::push_child(const Node& node) {
if (!children) children = new vector<Node>;
children->push_back(node);
}
void Node::push_opt_child(const Node& node) {
if (!opt_children) opt_children = new vector<Node>;
opt_children->push_back(node);
}
void Node::dump(unsigned int depth) {
// void Node::dump(unsigned int depth) {
// switch (type) {
// case comment:
// for (int i = depth; i > 0; --i) cout << " ";
......@@ -84,35 +85,32 @@ namespace Sass {
// break;
// default: cout << "HUH?"; break;
// }
}
// }
void Node::emit_nested_css(stringstream& buf,
const string& prefix,
size_t depth) {
string indentation(2 * depth, ' ');
bool has_rules, has_nested_rulesets;
vector<Node>* nodes;
if (type == ruleset) {
// has_rules = !((*children)[1].children->empty());
has_rules = !(children->at(1).children->empty());
// has_nested_rulesets = !((*children)[1].opt_children->empty());
has_nested_rulesets = !(children->at(1).opt_children->empty());
nodes = children->at(1).children;
has_rules = children->at(1).has_rules;
has_rulesets = children->at(1).has_rulesets;
}
switch (type) {
case ruleset:
if (has_rules) {
buf << indentation;
// (*children)[0].emit_nested_css(buf, prefix, depth); // selector
children->at(0).emit_nested_css(buf, prefix, depth); // selector
buf << " {";
for (int i = 0; i < (*children)[1].children->size(); ++i) {
// (*(*children)[1].children)[i].emit_nested_css(buf, "", depth + 1); // rules
children->at(1).children->at(i).emit_nested_css(buf, "", depth + 1); // rules
for (int i = 0; i < nodes->size(); ++i) {
if (nodes->at(i).type == rule) nodes->at(i).emit_nested_css(buf, "", depth + 1); // rules
}
buf << " }" << endl;
}
if (has_nested_rulesets) {
for (int i = 0; i < children->at(1).opt_children->size(); ++i) { // do each nested ruleset
children->at(1).opt_children->at(i).emit_nested_css(buf, prefix + (prefix.empty() ? "" : " ") + string((*children)[0].token), depth + (has_rules ? 1 : 0));
if (has_rulesets) {
for (int i = 0; i < nodes->size(); ++i) { // do each nested ruleset
if (nodes->at(i).type == ruleset) nodes->at(i).emit_nested_css(buf, prefix + (prefix.empty() ? "" : " ") + string((*children)[0].token), depth + (has_rules ? 1 : 0));
}
}
if (depth == 0 && prefix.empty()) buf << endl;
......
......@@ -6,102 +6,156 @@ namespace Sass {
using std::vector;
using std::stringstream;
// struct Node {
// enum Node_Type {
// nil,
// comment,
// ruleset,
// clauses,
// selector_group,
// selector,
// simple_selector_sequence,
// simple_selector,
// rule,
// property,
// values,
// value
// };
//
// static unsigned int fresh;
// static unsigned int copied;
//
// Node_Type type;
// Token token;
// vector<Node>* children;
// vector<Node>* opt_children;
//
// Node();
// Node(Node_Type _type);
// Node(Node_Type _type, Token& _token);
// Node(const Node& n);
//
// void push_child(const Node& node);
// void push_opt_child(const Node& node);
// void dump(unsigned int depth = 0);
// void emit_nested_css(stringstream& buf, const string& prefix, size_t depth);
// void emit_expanded_css(stringstream& buf, const string& prefix);
// };
struct Node {
enum Node_Type {
enum Type {
nil,
comment,
ruleset,
clauses,
propset,
selector_group,
selector,
simple_selector_sequence,
simple_selector,
type_selector,
class_selector,
id_selector,
attribute_selector,
block,
rule,
property,
values,
value
};
static unsigned int fresh;
static unsigned int copied;
static size_t fresh;
static size_t copied;
Node_Type type;
size_t line_number;
mutable vector<Node>* children;
Token token;
vector<Node>* children;
vector<Node>* opt_children;
Type type;
bool has_rules;
bool has_rulesets;
bool has_propsets;
Node() { ++fresh; }
Node(const Node& n)
: line_number(n.line_number),
children(n.children),
token(n.token),
type(n.type),
has_rules(n.has_rules),
has_rulesets(n.has_rulesets),
has_propsets(n.has_propsets)
{ /*n.release();*/ ++copied; } // No joint custody.
Node(size_t line_number, Type type, size_t length = 0)
: line_number(line_number),
children(new vector<Node>),
token(Token()),
type(type),
has_rules(false),
has_rulesets(false),
has_propsets(false)
{ children->reserve(length); ++fresh; }
Node();
Node(Node_Type _type);
Node(Node_Type _type, Token& _token);
Node(const Node& n);
Node(size_t line_number, Type type, const Node& n)
: line_number(line_number),
children(new vector<Node>(1, n)),
token(Token()),
type(type),
has_rules(false),
has_rulesets(false),
has_propsets(false)
{ ++fresh; }
Node(size_t line_number, Type type, const Node& n, const Node& m)
: line_number(line_number),
children(new vector<Node>),
token(Token()),
type(type),
has_rules(false),
has_rulesets(false),
has_propsets(false)
{
children->reserve(2);
children->push_back(n);
children->push_back(m);
++fresh;
}
Node(size_t line_number, Type type, Token& token)
: line_number(line_number),
children(0),
token(token),
type(type),
has_rules(false),
has_rulesets(false),
has_propsets(false)
{ ++fresh; }
//~Node() { delete children; }
Node& operator=(const Node& n)
{
line_number = n.line_number;
children = n.children;
// n.release();
token = n.token;
type = n.type;
has_rules = n.has_rules;
has_rulesets = n.has_rulesets;
has_propsets = n.has_propsets;
++copied;
return *this;
}
// Node& operator+=(const Node& node);
Node& operator<<(const Node& n)
{
children->push_back(n);
return *this;
}
void release() const { children = 0; }
void push_child(const Node& node);
void push_opt_child(const Node& node);
void dump(unsigned int depth = 0);
void emit_nested_css(stringstream& buf, const string& prefix, size_t depth);
void emit_expanded_css(stringstream& buf, const string& prefix);
};
// struct Node {
// enum Type {
// nil,
// comment,
// ruleset,
// selector_group,
// selector,
// simple_selector_sequence,
// type_selector,
// class_selector,
// id_selector,
// attribute_selector,
// clauses,
// rule,
// property,
// values,
// value
// };
//
// size_t line_number;
// mutable vector<Node>* children;
// Token token;
// Type type;
// bool has_rules;
// bool has_rulesets;
// bool has_nested_properties;
//
// Node(const Node& n)
// : line_number(n.line_number),
// children(n.children),
// token(n.token),
// type(n.type),
// has_rules(n.has_rules),
// has_rulesets(n.has_rulesets),
// has_nested_properties(n.has_nested_properties)
// { n.release(); } // No joint custody.
//
// Node(size_t line_number, Type type, size_t length = 0)
// : line_number(line_number),
// children(new vector<Node>),
// token(Token()),
// type(type),
// has_rules(false),
// has_rulesets(false),
// has_nested_properties(false)
// { children->reserve(length); }
//
// Node(size_t line_number, Type type, Token& token)
// : line_number(line_number),
// children(0),
// token(token),
// type(type),
// has_rules(false),
// has_rulesets(false),
// has_nested_properties(false)
// { }
//
// Node& operator=(const Node& node);
// Node& operator+=(const Node& node);
// Node& operator<<(const Node& node);
// void release() const { children = 0; }
// };
}
\ No newline at end of file
......@@ -40,4 +40,20 @@ namespace Sass {
return;
}
}
using std::lexicographical_compare;
bool Token::operator<(const Token& rhs) const
{
const char* first1 = begin;
const char* last1 = end;
const char* first2 = rhs.begin;
const char* last2 = rhs.end;
while (first1!=last1)
{
if (first2==last2 || *first2<*first1) return false;
else if (*first1<*first2) return true;
first1++; first2++;
}
return (first2!=last2);
}
}
\ No newline at end of file
......@@ -21,5 +21,7 @@ namespace Sass {
void stream_unquoted(std::stringstream& buf) const;
bool operator<(const Token& rhs) const;
};
}
\ 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