Commit 4f8d92e5 by Aaron Leung

Merge branch 'node_pimpl'

Conflicts:
	eval_apply.cpp
	node.hpp
parents 40a251ea 61423540
...@@ -4,7 +4,7 @@ LDFLAGS= ...@@ -4,7 +4,7 @@ LDFLAGS=
SOURCES = \ SOURCES = \
context.cpp functions.cpp document.cpp \ context.cpp functions.cpp document.cpp \
document_parser.cpp eval_apply.cpp node.cpp \ document_parser.cpp eval_apply.cpp node.cpp \
node_comparisons.cpp values.cpp prelexer.cpp \ node_factory.cpp node_emitters.cpp prelexer.cpp \
sass_interface.cpp sass_interface.cpp
OBJECTS = $(SOURCES:.cpp=.o) OBJECTS = $(SOURCES:.cpp=.o)
......
#include "context.hpp" #include "context.hpp"
#include <iostream> #include <iostream>
#include <unistd.h>
#include "prelexer.hpp"
using std::cerr; using std::endl; using std::cerr; using std::endl;
namespace Sass { namespace Sass {
...@@ -44,6 +46,7 @@ namespace Sass { ...@@ -44,6 +46,7 @@ namespace Sass {
source_refs(vector<char*>()), source_refs(vector<char*>()),
registry(vector<vector<Node>*>()), registry(vector<vector<Node>*>()),
include_paths(vector<string>()), include_paths(vector<string>()),
new_Node(Node_Factory()),
ref_count(0) ref_count(0)
{ {
register_functions(); register_functions();
...@@ -55,6 +58,8 @@ namespace Sass { ...@@ -55,6 +58,8 @@ namespace Sass {
for (size_t i = 0; i < source_refs.size(); ++i) { for (size_t i = 0; i < source_refs.size(); ++i) {
delete[] source_refs[i]; delete[] source_refs[i];
} }
new_Node.free();
// cerr << "Deallocated " << i << " source string(s)." << endl; // cerr << "Deallocated " << i << " source string(s)." << endl;
} }
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <utility> #include <utility>
#include <map> #include <map>
#include "node_factory.hpp"
#include "functions.hpp" #include "functions.hpp"
namespace Sass { namespace Sass {
...@@ -45,6 +46,7 @@ namespace Sass { ...@@ -45,6 +46,7 @@ namespace Sass {
vector<char*> source_refs; // all the source c-strings vector<char*> source_refs; // all the source c-strings
vector<vector<Node>*> registry; // all the child vectors vector<vector<Node>*> registry; // all the child vectors
vector<string> include_paths; vector<string> include_paths;
Node_Factory new_Node;
size_t ref_count; size_t ref_count;
string sass_path; string sass_path;
string css_path; string css_path;
......
...@@ -4,124 +4,97 @@ ...@@ -4,124 +4,97 @@
#include "eval_apply.hpp" #include "eval_apply.hpp"
#include "error.hpp" #include "error.hpp"
#include <iostream> #include <iostream>
#include <sstream>
namespace Sass { namespace Sass {
Document::Document(char* path_str, char* source_str, Context& ctx) Document::Document(Context& ctx) : context(ctx)
: path(string()), { ++context.ref_count; }
source(source_str),
line_number(1),
context(ctx),
root(Node(Node::root, context.registry, 1)),
lexed(Token::make())
{
if (source_str) {
own_source = false;
position = source;
end = position + std::strlen(source);
}
else if (path_str) {
path = string(path_str);
std::FILE *f;
// TO DO: CHECK f AGAINST NULL/0
f = std::fopen(path.c_str(), "rb");
std::fseek(f, 0, SEEK_END);
int len = std::ftell(f);
std::rewind(f);
// TO DO: WRAP THE new[] IN A TRY/CATCH BLOCK
source = new char[len + 1];
std::fread(source, sizeof(char), len, f);
source[len] = '\0';
end = source + len;
std::fclose(f);
own_source = true;
position = source;
context.source_refs.push_back(source);
}
else {
// report an error
}
++context.ref_count;
}
Document::Document(const Document& doc)
: path(doc.path),
source(doc.source),
position(doc.position),
end(doc.end),
line(doc.line),
own_source(doc.own_source),
context(doc.context),
root(doc.root),
lexed(doc.lexed)
{ ++doc.context.ref_count; }
Document::Document(string path, char* source) Document::~Document()
: path(path), source(source), { --context.ref_count; }
line_number(1), own_source(false),
context(*(new Context())), Document Document::make_from_file(Context& ctx, string path)
root(Node(Node::root, context.registry, 1)),
lexed(Token::make())
{ {
if (!source) {
std::FILE *f; std::FILE *f;
f = std::fopen(path.c_str(), "rb"); f = std::fopen(path.c_str(), "rb");
if (!f) throw path; if (!f) throw path;
if (std::fseek(f, 0, SEEK_END)) throw path; if (std::fseek(f, 0, SEEK_END)) throw path;
int len = std::ftell(f); int status = std::ftell(f);
if (len < 0) throw path; if (status < 0) throw path;
size_t len = status;
std::rewind(f); std::rewind(f);
// TO DO: CATCH THE POTENTIAL badalloc EXCEPTION char* source = new char[len + 1];
source = new char[len + 1]; size_t bytes_read = std::fread(source, sizeof(char), len, f);
std::fread(source, sizeof(char), len, f); if (bytes_read != len) {
std::cerr << "Warning: possible error reading from " << path << std::endl;
}
if (std::ferror(f)) throw path; if (std::ferror(f)) throw path;
source[len] = '\0'; source[len] = '\0';
end = source + len; char* end = source + len;
if (std::fclose(f)) throw path; if (std::fclose(f)) throw path;
own_source = true;
} Document doc(ctx);
position = source; doc.path = path;
context.source_refs.push_back(source); doc.line = 1;
++context.ref_count; doc.root = ctx.new_Node(Node::root, path, 1, 0);
doc.lexed = Token::make();
doc.own_source = true;
doc.source = source;
doc.end = end;
doc.position = source;
doc.context.source_refs.push_back(source);
return doc;
} }
Document::Document(string path, Context& context) Document Document::make_from_source_chars(Context& ctx, char* src, string path)
: path(path), source(0),
line_number(1), own_source(false),
context(context),
root(Node(Node::root, context.registry, 1)),
lexed(Token::make())
{ {
std::FILE *f; Document doc(ctx);
f = std::fopen(path.c_str(), "rb"); doc.path = path;
if (!f) throw path; doc.line = 1;
if (std::fseek(f, 0, SEEK_END)) throw path; doc.root = ctx.new_Node(Node::root, path, 1, 0);
int len = std::ftell(f); doc.lexed = Token::make();
if (len < 0) throw path; doc.own_source = false;
std::rewind(f); doc.source = src;
// TO DO: CATCH THE POTENTIAL badalloc EXCEPTION doc.end = src + std::strlen(src);
source = new char[len + 1]; doc.position = doc.end;
std::fread(source, sizeof(char), len, f);
if (std::ferror(f)) throw path; return doc;
source[len] = '\0';
end = source + len;
if (std::fclose(f)) throw path;
position = source;
context.source_refs.push_back(source);
++context.ref_count;
} }
Document::Document(const string& path, size_t line_number, Token t, Context& context) Document Document::make_from_token(Context& ctx, Token t, string path, size_t line_number)
: path(path), {
source(const_cast<char*>(t.begin)), Document doc(ctx);
position(t.begin), doc.path = path;
end(t.end), doc.line = line_number;
line_number(line_number), doc.root = ctx.new_Node(Node::root, path, 1, 0);
own_source(false), doc.lexed = Token::make();
context(context), doc.own_source = false;
root(Node(Node::root, context.registry, 1)), doc.source = const_cast<char*>(t.begin);
lexed(Token::make()) doc.end = t.end;
{ } doc.position = doc.source;
Document::~Document() { return doc;
--context.ref_count;
// if (context.ref_count == 0) delete &context;
} }
void Document::syntax_error(string message, size_t ln) void Document::throw_syntax_error(string message, size_t ln)
{ throw Error(Error::syntax, ln ? ln : line_number, path, message); } { throw Error(Error::syntax, path, ln ? ln : line, message); }
void Document::read_error(string message, size_t ln) void Document::throw_read_error(string message, size_t ln)
{ throw Error(Error::read, ln ? ln : line_number, path, message); } { throw Error(Error::read, path, ln ? ln : line, message); }
using std::string; using std::string;
using std::stringstream; using std::stringstream;
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "node.hpp" #include "node.hpp"
#endif #endif
#include "prelexer.hpp"
#include "context.hpp" #include "context.hpp"
namespace Sass { namespace Sass {
...@@ -19,7 +20,7 @@ namespace Sass { ...@@ -19,7 +20,7 @@ namespace Sass {
char* source; char* source;
const char* position; const char* position;
const char* end; const char* end;
size_t line_number; size_t line;
bool own_source; bool own_source;
Context& context; Context& context;
...@@ -27,12 +28,17 @@ namespace Sass { ...@@ -27,12 +28,17 @@ namespace Sass {
Node root; Node root;
Token lexed; Token lexed;
Document(char* path_str, char* source_str, Context& ctx); private:
Document(string path, char* source = 0); // force the use of the "make_from_..." factory funtions
Document(string path, Context& context); Document(Context& ctx);
Document(const string& path, size_t line_number, Token t, Context& context); public:
Document(const Document& doc);
~Document(); ~Document();
static Document make_from_file(Context& ctx, string path);
static Document make_from_source_chars(Context& ctx, char* src, string path = "");
static Document make_from_token(Context& ctx, Token t, string path = "", size_t line_number = 1);
template <prelexer mx> template <prelexer mx>
const char* peek(const char* start = 0) const char* peek(const char* start = 0)
{ {
...@@ -83,7 +89,7 @@ namespace Sass { ...@@ -83,7 +89,7 @@ namespace Sass {
else if (mx == spaces) { else if (mx == spaces) {
after_whitespace = spaces(position); after_whitespace = spaces(position);
if (after_whitespace) { if (after_whitespace) {
line_number += count_interval<'\n'>(position, after_whitespace); line += count_interval<'\n'>(position, after_whitespace);
lexed = Token::make(position, after_whitespace); lexed = Token::make(position, after_whitespace);
return position = after_whitespace; return position = after_whitespace;
} }
...@@ -99,7 +105,7 @@ namespace Sass { ...@@ -99,7 +105,7 @@ namespace Sass {
} }
const char* after_token = mx(after_whitespace); const char* after_token = mx(after_whitespace);
if (after_token) { if (after_token) {
line_number += count_interval<'\n'>(position, after_token); line += count_interval<'\n'>(position, after_token);
lexed = Token::make(after_whitespace, after_token); lexed = Token::make(after_whitespace, after_token);
return position = after_token; return position = after_token;
} }
...@@ -140,26 +146,14 @@ namespace Sass { ...@@ -140,26 +146,14 @@ namespace Sass {
Node parse_term(); Node parse_term();
Node parse_factor(); Node parse_factor();
Node parse_value(); Node parse_value();
Node parse_identifier();
Node parse_variable();
Node parse_function_call(); Node parse_function_call();
Node parse_string(); Node parse_string();
Node parse_value_schema(); Node parse_value_schema();
const char* lookahead_for_selector(const char* start = 0); const char* lookahead_for_selector(const char* start = 0);
const char* look_for_rule(const char* start = 0); void throw_syntax_error(string message, size_t ln = 0);
const char* look_for_values(const char* start = 0); void throw_read_error(string message, size_t ln = 0);
const char* look_for_selector_group(const char* start = 0);
const char* look_for_selector(const char* start = 0);
const char* look_for_simple_selector_sequence(const char* start = 0);
const char* look_for_simple_selector(const char* start = 0);
const char* look_for_pseudo(const char* start = 0);
const char* look_for_attrib(const char* start = 0);
void syntax_error(string message, size_t ln = 0);
void read_error(string message, size_t ln = 0);
string emit_css(CSS_Style style); string emit_css(CSS_Style style);
......
...@@ -4,12 +4,12 @@ namespace Sass { ...@@ -4,12 +4,12 @@ namespace Sass {
enum Type { read, write, syntax, evaluation }; enum Type { read, write, syntax, evaluation };
Type type; Type type;
size_t line_number; string path;
string file_name; size_t line;
string message; string message;
Error(Type type, size_t line_number, string file_name, string message) Error(Type type, string path, size_t line, string message)
: type(type), line_number(line_number), file_name(file_name), message(message) : type(type), path(path), line(line), message(message)
{ } { }
}; };
......
...@@ -11,10 +11,10 @@ ...@@ -11,10 +11,10 @@
namespace Sass { namespace Sass {
using std::map; using std::map;
Node eval(Node& expr, Environment& env, map<pair<string, size_t>, Function>& f_env, vector<vector<Node>*>& registry); Node eval(Node& expr, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node);
Node accumulate(Node::Type op, Node& acc, Node& rhs, vector<vector<Node>*>& registry); Node accumulate(Node::Type op, Node& acc, Node& rhs, Node_Factory& new_Node);
double operate(Node::Type op, double lhs, double rhs); double operate(Node::Type op, double lhs, double rhs);
Node apply_mixin(Node& mixin, const Node& args, Environment& env, map<pair<string, size_t>, Function>& f_env, vector<vector<Node>*>& registry); Node apply_mixin(Node& mixin, const Node& args, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node);
Node apply_function(const Function& f, const Node& args, Environment& env, map<pair<string, size_t>, Function>& f_env, vector<vector<Node>*>& registry); Node apply_function(const Function& f, const Node& args, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node);
} }
\ No newline at end of file
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
namespace Sass { namespace Sass {
using std::map; using std::map;
typedef Node (*Implementation)(const vector<Token>&, map<Token, Node>&, vector<vector<Node>*>& registry); typedef Node (*Implementation)(const vector<Token>&, map<Token, Node>&, Node_Factory& new_Node);
typedef const char* str; typedef const char* str;
typedef str Function_Descriptor[]; typedef str Function_Descriptor[];
...@@ -37,8 +37,8 @@ namespace Sass { ...@@ -37,8 +37,8 @@ namespace Sass {
} }
} }
Node operator()(map<Token, Node>& bindings, vector<vector<Node>*>& registry) const Node operator()(map<Token, Node>& bindings, Node_Factory& new_Node) const
{ return implementation(parameters, bindings, registry); } { return implementation(parameters, bindings, new_Node); }
}; };
...@@ -47,111 +47,111 @@ namespace Sass { ...@@ -47,111 +47,111 @@ namespace Sass {
// RGB Functions /////////////////////////////////////////////////////// // RGB Functions ///////////////////////////////////////////////////////
extern Function_Descriptor rgb_descriptor; extern Function_Descriptor rgb_descriptor;
Node rgb(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node rgb(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor rgba_4_descriptor; extern Function_Descriptor rgba_4_descriptor;
Node rgba_4(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node rgba_4(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor rgba_2_descriptor; extern Function_Descriptor rgba_2_descriptor;
Node rgba_2(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node rgba_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor red_descriptor; extern Function_Descriptor red_descriptor;
Node red(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node red(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor green_descriptor; extern Function_Descriptor green_descriptor;
Node green(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node green(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor blue_descriptor; extern Function_Descriptor blue_descriptor;
Node blue(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node blue(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor mix_2_descriptor; extern Function_Descriptor mix_2_descriptor;
Node mix_2(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node mix_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor mix_3_descriptor; extern Function_Descriptor mix_3_descriptor;
Node mix_3(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node mix_3(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// HSL Functions /////////////////////////////////////////////////////// // HSL Functions ///////////////////////////////////////////////////////
extern Function_Descriptor hsla_descriptor; extern Function_Descriptor hsla_descriptor;
Node hsla(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node hsla(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor hsl_descriptor; extern Function_Descriptor hsl_descriptor;
Node hsl(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node hsl(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor invert_descriptor; extern Function_Descriptor invert_descriptor;
Node invert(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node invert(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Opacity Functions /////////////////////////////////////////////////// // Opacity Functions ///////////////////////////////////////////////////
extern Function_Descriptor alpha_descriptor; extern Function_Descriptor alpha_descriptor;
extern Function_Descriptor opacity_descriptor; extern Function_Descriptor opacity_descriptor;
Node alpha(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node alpha(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor opacify_descriptor; extern Function_Descriptor opacify_descriptor;
extern Function_Descriptor fade_in_descriptor; extern Function_Descriptor fade_in_descriptor;
Node opacify(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node opacify(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor transparentize_descriptor; extern Function_Descriptor transparentize_descriptor;
extern Function_Descriptor fade_out_descriptor; extern Function_Descriptor fade_out_descriptor;
Node transparentize(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node transparentize(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// String Functions //////////////////////////////////////////////////// // String Functions ////////////////////////////////////////////////////
extern Function_Descriptor unquote_descriptor; extern Function_Descriptor unquote_descriptor;
Node unquote(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node unquote(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor quote_descriptor; extern Function_Descriptor quote_descriptor;
Node quote(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node quote(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Number Functions //////////////////////////////////////////////////// // Number Functions ////////////////////////////////////////////////////
extern Function_Descriptor percentage_descriptor; extern Function_Descriptor percentage_descriptor;
Node percentage(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node percentage(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor round_descriptor; extern Function_Descriptor round_descriptor;
Node round(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node round(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor ceil_descriptor; extern Function_Descriptor ceil_descriptor;
Node ceil(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node ceil(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor floor_descriptor; extern Function_Descriptor floor_descriptor;
Node floor(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node floor(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor abs_descriptor; extern Function_Descriptor abs_descriptor;
Node abs(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node abs(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// List Functions ////////////////////////////////////////////////////// // List Functions //////////////////////////////////////////////////////
extern Function_Descriptor length_descriptor; extern Function_Descriptor length_descriptor;
Node length(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node length(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor nth_descriptor; extern Function_Descriptor nth_descriptor;
Node nth(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node nth(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor join_2_descriptor; extern Function_Descriptor join_2_descriptor;
Node join_2(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node join_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor join_3_descriptor; extern Function_Descriptor join_3_descriptor;
Node join_3(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node join_3(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Introspection Functions ///////////////////////////////////////////// // Introspection Functions /////////////////////////////////////////////
extern Function_Descriptor type_of_descriptor; extern Function_Descriptor type_of_descriptor;
Node type_of(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node type_of(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor unit_descriptor; extern Function_Descriptor unit_descriptor;
Node unit(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node unit(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor unitless_descriptor; extern Function_Descriptor unitless_descriptor;
Node unitless(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node unitless(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor comparable_descriptor; extern Function_Descriptor comparable_descriptor;
Node comparable(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node comparable(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Boolean Functions /////////////////////////////////////////////////// // Boolean Functions ///////////////////////////////////////////////////
extern Function_Descriptor not_descriptor; extern Function_Descriptor not_descriptor;
Node not_impl(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node not_impl(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
} }
......
#include "node_factory.hpp"
namespace Sass {
Node_Impl* Node_Factory::alloc_Node_Impl(Node::Type type, string path, size_t line)
{
Node_Impl* ip = new Node_Impl();
ip->type = type;
if (type == Node::backref) ip->has_backref = true;
ip->path = path;
ip->line = line;
pool_.push_back(ip);
return ip;
}
// returns a deep-copy of its argument
Node_Impl* Node_Factory::alloc_Node_Impl(Node_Impl* ip)
{
Node_Impl* ip_cpy = new Node_Impl(*ip);
pool_.push_back(ip_cpy);
if (ip_cpy->has_children) {
for (size_t i = 0, S = ip_cpy->size(); i < S; ++i) {
Node n(ip_cpy->at(i));
ip_cpy->at(i) = (*this)(n);
}
}
return ip_cpy;
}
// for cloning nodes
Node Node_Factory::operator()(const Node& n1)
{
Node_Impl* ip_cpy = alloc_Node_Impl(n1.ip_); // deep-copy the implementation object
return Node(ip_cpy);
}
// for making leaf nodes out of terminals/tokens
Node Node_Factory::operator()(Node::Type type, string path, size_t line, Token t)
{
Node_Impl* ip = alloc_Node_Impl(type, path, line);
ip->value.token = t;
return Node(ip);
}
// for making boolean values or interior nodes that have children
Node Node_Factory::operator()(Node::Type type, string path, size_t line, size_t size)
{
Node_Impl* ip = alloc_Node_Impl(type, path, line);
if (type == Node::boolean) ip->value.boolean = size;
else ip->children.reserve(size);
return Node(ip);
}
// for making nodes representing numbers
Node Node_Factory::operator()(string path, size_t line, double v, Node::Type type)
{
Node_Impl* ip = alloc_Node_Impl(type, path, line);
ip->value.numeric = v;
return Node(ip);
}
// for making nodes representing numeric dimensions (e.g. 5px, 3em)
Node Node_Factory::operator()(string path, size_t line, double v, const Token& t)
{
Node_Impl* ip = alloc_Node_Impl(Node::numeric_dimension, path, line);
ip->value.dimension.numeric = v;
ip->value.dimension.unit = t;
return Node(ip);
}
// for making nodes representing rgba color quads
Node Node_Factory::operator()(string path, size_t line, double r, double g, double b, double a)
{
Node color((*this)(Node::numeric_color, path, line, 4));
color << (*this)(path, line, r)
<< (*this)(path, line, g)
<< (*this)(path, line, b)
<< (*this)(path, line, a);
return color;
}
void Node_Factory::free()
{ for (size_t i = 0, S = pool_.size(); i < S; ++i) delete pool_[i]; }
}
\ No newline at end of file
#include <vector>
#ifndef SASS_NODE_INCLUDED
#include "node.hpp"
#endif
namespace Sass {
using namespace std;
struct Token;
struct Node_Impl;
class Node_Factory {
vector<Node_Impl*> pool_;
Node_Impl* alloc_Node_Impl(Node::Type type, string file, size_t line);
// returns a deep-copy of its argument
Node_Impl* alloc_Node_Impl(Node_Impl* ip);
public:
// for cloning nodes
Node operator()(const Node& n1);
// for making leaf nodes out of terminals/tokens
Node operator()(Node::Type type, string file, size_t line, Token t);
// for making boolean values or interior nodes that have children
Node operator()(Node::Type type, string file, size_t line, size_t size);
// // for making nodes representing boolean values
// Node operator()(Node::Type type, string file, size_t line, bool b);
// for making nodes representing numbers
Node operator()(string file, size_t line, double v, Node::Type type = Node::number);
// for making nodes representing numeric dimensions (e.g. 5px, 3em)
Node operator()(string file, size_t line, double v, const Token& t);
// for making nodes representing rgba color quads
Node operator()(string file, size_t line, double r, double g, double b, double a = 1.0);
void free();
};
}
\ No newline at end of file
This diff is collapsed. Click to expand it.
#define SASS_NODE_INCLUDED
#include <vector>
#include <sstream>
#include "values.hpp"
#include <iostream>
namespace Sass {
using std::string;
using std::vector;
using std::stringstream;
using std::cerr; using std::endl;
struct Node {
enum Type {
root,
ruleset,
propset,
selector_group,
selector,
selector_combinator,
simple_selector_sequence,
backref,
simple_selector,
type_selector,
class_selector,
id_selector,
pseudo,
pseudo_negation,
functional_pseudo,
attribute_selector,
block,
rule,
property,
nil,
comma_list,
space_list,
disjunction,
conjunction,
relation,
eq,
neq,
gt,
gte,
lt,
lte,
expression,
add,
sub,
term,
mul,
div,
factor,
unary_plus,
unary_minus,
values,
value,
identifier,
uri,
textual_percentage,
textual_dimension,
textual_number,
textual_hex,
color_name,
string_constant,
numeric_percentage,
numeric_dimension,
number,
numeric_color,
boolean,
important,
value_schema,
string_schema,
css_import,
function_call,
mixin,
parameters,
expansion,
arguments,
variable,
assignment,
comment,
none,
flags
};
Type type;
unsigned int line_number;
bool has_children;
bool has_statements;
bool has_blocks;
bool has_expansions;
bool has_backref;
bool from_variable;
bool eval_me;
bool unquoted;
union {
Token token;
mutable vector<Node>* children;
Dimension dimension;
double numeric_value;
bool boolean_value;
} content;
const char* file_name;
static size_t allocations;
static size_t destructed;
void clear()
{
type = none; line_number = 0; file_name = 0;
has_children = false; has_statements = false; has_blocks = false;
has_expansions = false; has_backref = false; from_variable = false;
eval_me = false; unquoted = false;
}
size_t size() const
{ return content.children->size(); }
Node& operator[](const size_t i) const
{ return content.children->at(i); }
Node& at(const size_t i) const
{ return content.children->at(i); }
Node& operator<<(const Node& n)
{
content.children->push_back(n);
return *this;
}
bool is_numeric() const
{
switch (type)
{
case number:
case numeric_percentage:
case numeric_dimension:
return true;
break;
default:
return false;
}
}
double numeric_value() const
{
switch (type)
{
case number:
case numeric_percentage:
return content.numeric_value;
case numeric_dimension:
return content.dimension.numeric_value;
default:
break;
// throw an exception?
}
}
void set_numeric_value(double v)
{
switch (type)
{
case number:
case numeric_percentage:
content.numeric_value = v;
case numeric_dimension:
content.dimension.numeric_value = v;
default:
break;
// throw an exception?
}
}
Node& operator+=(const Node& n)
{
for (size_t i = 0; i < n.size(); ++i) {
content.children->push_back(n[i]);
}
return *this;
}
bool operator==(const Node& rhs) const;
bool operator!=(const Node& rhs) const;
bool operator<(const Node& rhs) const;
bool operator<=(const Node& rhs) const;
bool operator>(const Node& rhs) const;
bool operator>=(const Node& rhs) const;
string to_string(const string& prefix) const;
void echo(stringstream& buf, size_t depth = 0);
void emit_nested_css(stringstream& buf,
size_t depth,
const vector<string>& prefixes);
void emit_nested_css(stringstream& buf, size_t depth);
void emit_propset(stringstream& buf, size_t depth, const string& prefix);
void emit_expanded_css(stringstream& buf, const string& prefix);
Node clone(vector<vector<Node>*>& registry) const;
void flatten();
Node()
{ clear(); }
Node(Type t) // flags or booleans
{ clear(); type = t; }
Node(Type t, vector<vector<Node>*>& registry, unsigned int ln, size_t s = 0) // nodes with children
{
clear();
type = t;
line_number = ln;
content.children = new vector<Node>;
registry.push_back(content.children);
content.children->reserve(s);
has_children = true;
++allocations;
}
Node(Type t, unsigned int ln, const Token& tok) // nodes with a single token
{
clear();
type = t;
line_number = ln;
content.token = tok;
}
Node(unsigned int ln, double val) // numeric values
{
clear();
type = number;
line_number = ln;
content.numeric_value = val;
}
Node(unsigned int ln, double val, const Token& tok) // dimensions
{
clear();
type = numeric_dimension;
line_number = ln;
content.dimension = Dimension();
content.dimension.numeric_value = val;
content.dimension.unit = tok.begin;
}
Node(vector<vector<Node>*>& registry, unsigned int ln, double r, double g, double b, double a = 1.0) // colors
{
clear();
type = numeric_color;
line_number = ln;
content.children = new vector<Node>;
registry.push_back(content.children);
content.children->reserve(4);
content.children->push_back(Node(ln, r));
content.children->push_back(Node(ln, g));
content.children->push_back(Node(ln, b));
content.children->push_back(Node(ln, a));
has_children = true;
++allocations;
}
~Node() { ++destructed; }
};
}
...@@ -10,8 +10,8 @@ ...@@ -10,8 +10,8 @@
#include "sass_interface.h" #include "sass_interface.h"
extern "C" { extern "C" {
using namespace std; using namespace std;
sass_context* sass_new_context() sass_context* sass_new_context()
{ return (sass_context*) calloc(1, sizeof(sass_context)); } { return (sass_context*) calloc(1, sizeof(sass_context)); }
...@@ -40,7 +40,7 @@ extern "C" { ...@@ -40,7 +40,7 @@ extern "C" {
using namespace Sass; using namespace Sass;
doc.parse_scss(); doc.parse_scss();
// cerr << "PARSED" << endl; // cerr << "PARSED" << endl;
eval(doc.root, doc.context.global_env, doc.context.function_env, doc.context.registry); eval(doc.root, doc.context.global_env, doc.context.function_env, doc.context.new_Node);
// cerr << "EVALUATED" << endl; // cerr << "EVALUATED" << endl;
string output(doc.emit_css(static_cast<Document::CSS_Style>(style))); string output(doc.emit_css(static_cast<Document::CSS_Style>(style)));
// cerr << "EMITTED" << endl; // cerr << "EMITTED" << endl;
...@@ -49,9 +49,9 @@ extern "C" { ...@@ -49,9 +49,9 @@ extern "C" {
// cerr << "Destructions:\t" << Node::destructed << endl; // cerr << "Destructions:\t" << Node::destructed << endl;
// cerr << "Registry size:\t" << doc.context.registry.size() << endl; // cerr << "Registry size:\t" << doc.context.registry.size() << endl;
for (size_t i = 0; i < doc.context.registry.size(); ++i) { // for (size_t i = 0; i < doc.context.registry.size(); ++i) {
delete doc.context.registry[i]; // delete doc.context.registry[i];
} // }
// cerr << "Deallocations:\t" << i << endl; // cerr << "Deallocations:\t" << i << endl;
char* c_output = (char*) malloc(output.size() + 1); char* c_output = (char*) malloc(output.size() + 1);
...@@ -64,14 +64,15 @@ extern "C" { ...@@ -64,14 +64,15 @@ extern "C" {
using namespace Sass; using namespace Sass;
try { try {
Context cpp_ctx(c_ctx->options.include_paths); Context cpp_ctx(c_ctx->options.include_paths);
Document doc(0, c_ctx->input_string, cpp_ctx); // Document doc(0, c_ctx->input_string, cpp_ctx);
Document doc(Document::make_from_source_chars(cpp_ctx, c_ctx->source_string));
c_ctx->output_string = process_document(doc, c_ctx->options.output_style); c_ctx->output_string = process_document(doc, c_ctx->options.output_style);
c_ctx->error_message = 0; c_ctx->error_message = 0;
c_ctx->error_status = 0; c_ctx->error_status = 0;
} }
catch (Error& e) { catch (Error& e) {
stringstream msg_stream; stringstream msg_stream;
msg_stream << "ERROR -- " << e.file_name << ", line " << e.line_number << ": " << e.message << endl; msg_stream << "ERROR -- " << e.path << ", line " << e.line << ": " << e.message << endl;
string msg(msg_stream.str()); string msg(msg_stream.str());
char* msg_str = (char*) malloc(msg.size() + 1); char* msg_str = (char*) malloc(msg.size() + 1);
strcpy(msg_str, msg.c_str()); strcpy(msg_str, msg.c_str());
...@@ -98,7 +99,8 @@ extern "C" { ...@@ -98,7 +99,8 @@ extern "C" {
using namespace Sass; using namespace Sass;
try { try {
Context cpp_ctx(c_ctx->options.include_paths); Context cpp_ctx(c_ctx->options.include_paths);
Document doc(c_ctx->input_path, 0, cpp_ctx); // Document doc(c_ctx->input_path, 0, cpp_ctx);
Document doc(Document::make_from_file(cpp_ctx, string(c_ctx->input_path)));
// cerr << "MADE A DOC AND CONTEXT OBJ" << endl; // cerr << "MADE A DOC AND CONTEXT OBJ" << endl;
// cerr << "REGISTRY: " << doc.context.registry.size() << endl; // cerr << "REGISTRY: " << doc.context.registry.size() << endl;
c_ctx->output_string = process_document(doc, c_ctx->options.output_style); c_ctx->output_string = process_document(doc, c_ctx->options.output_style);
...@@ -107,7 +109,7 @@ extern "C" { ...@@ -107,7 +109,7 @@ extern "C" {
} }
catch (Error& e) { catch (Error& e) {
stringstream msg_stream; stringstream msg_stream;
msg_stream << "ERROR -- " << e.file_name << ", line " << e.line_number << ": " << e.message << endl; msg_stream << "ERROR -- " << e.path << ", line " << e.line << ": " << e.message << endl;
string msg(msg_stream.str()); string msg(msg_stream.str());
char* msg_str = (char*) malloc(msg.size() + 1); char* msg_str = (char*) malloc(msg.size() + 1);
strcpy(msg_str, msg.c_str()); strcpy(msg_str, msg.c_str());
......
...@@ -13,7 +13,7 @@ struct sass_options { ...@@ -13,7 +13,7 @@ struct sass_options {
}; };
struct sass_context { struct sass_context {
char* input_string; char* source_string;
char* output_string; char* output_string;
struct sass_options options; struct sass_options options;
int error_status; int error_status;
......
#include <iostream>
#ifndef SASS_NODE_INCLUDED
#include "node.hpp"
#endif
#include "node_factory.hpp"
int main()
{
using namespace Sass;
using namespace std;
cout << sizeof(Node_Impl*) << endl;
cout << sizeof(Node) << endl;
cout << sizeof(Node_Impl) << endl << endl;
Node_Factory new_Node = Node_Factory();
Node interior(new_Node(Node::block, "", 0, 3));
cout << interior.size() << endl;
cout << interior.has_children() << endl;
cout << interior.should_eval() << endl << endl;
Node num(new_Node("", 0, 255, 123, 32));
Node num2(new_Node("", 0, 255, 123, 32));
Node num3(new_Node("", 0, 255, 122, 20, .75));
cout << num.size() << endl;
cout << num.has_children() << endl;
cout << num.has_statements() << endl << endl;
cout << num[1].is_numeric() << endl;
cout << num[1].numeric_value() << endl << endl;
cout << (num == num2) << endl;
cout << (num == num3) << endl << endl;
cout << (num3[2] < num2[2]) << endl;
cout << (num2[3] < num3[3]) << endl << endl;
cout << (num2[2] >= num3[2]) << endl;
cout << (num2[3] != num3[3]) << endl << endl;
Node num4(new_Node(num3));
cout << num3[3].numeric_value() << endl;
cout << num4[3].numeric_value() << endl;
num4[3] = new_Node("", 0, 0.4567);
cout << num3[3].numeric_value() << endl;
cout << num4[3].numeric_value() << endl << endl;
Node block1(new_Node(Node::block, "block", 1, 2));
block1 << num2 << num4;
Node block2(new_Node(block1));
cout << (block1 == block2) << endl;
cout << block1[1][3].numeric_value() << endl;
cout << block2[1][3].numeric_value() << endl;
block2[1][3] = new_Node("", 0, .9876);
cout << block1[1][3].numeric_value() << endl;
cout << block2[1][3].numeric_value() << endl;
new_Node.free();
return 0;
}
\ 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