Commit d58dae2b by Hampton Catlin

Merge branch 'master' of github.com:hcatlin/libsass

parents 19f9e84a b1580330
...@@ -104,6 +104,7 @@ div { ...@@ -104,6 +104,7 @@ div {
b: hey or ho or false or hoo; b: hey or ho or false or hoo;
c: false and hey and ho; c: false and hey and ho;
d: true and false and (1/0); d: true and false and (1/0);
e: (()()()()()()()()25()()()()()()()()()()()()()()()()()()()()()()());
/* e: 1 < 3 and 3 < 5; /* e: 1 < 3 and 3 < 5;
f: (1 2 3) and (4 5 6);*/ f: (1 2 3) and (4 5 6);*/
......
...@@ -33,15 +33,16 @@ namespace Sass { ...@@ -33,15 +33,16 @@ namespace Sass {
} }
} }
for (int i = 0; i < include_paths.size(); ++i) { // for (int i = 0; i < include_paths.size(); ++i) {
cerr << include_paths[i] << endl; // cerr << include_paths[i] << endl;
} // }
} }
Context::Context(const char* paths_str) Context::Context(const char* paths_str)
: global_env(Environment()), : global_env(Environment()),
function_env(map<pair<string, size_t>, Function>()), function_env(map<pair<string, size_t>, Function>()),
source_refs(vector<char*>()), source_refs(vector<char*>()),
registry(vector<vector<Node>*>()),
include_paths(vector<string>()), include_paths(vector<string>()),
ref_count(0) ref_count(0)
{ {
...@@ -51,9 +52,11 @@ namespace Sass { ...@@ -51,9 +52,11 @@ namespace Sass {
Context::~Context() Context::~Context()
{ {
for (int i = 0; i < source_refs.size(); ++i) { int i;
for (i = 0; i < source_refs.size(); ++i) {
delete[] source_refs[i]; delete[] source_refs[i];
} }
cerr << "Deallocated " << i << " source string(s)." << endl;
} }
inline void Context::register_function(Function_Descriptor d, Implementation ip) inline void Context::register_function(Function_Descriptor d, Implementation ip)
......
...@@ -45,6 +45,7 @@ namespace Sass { ...@@ -45,6 +45,7 @@ namespace Sass {
Environment global_env; Environment global_env;
map<pair<string, size_t>, Function> function_env; map<pair<string, size_t>, Function> function_env;
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
size_t ref_count; size_t ref_count;
void collect_include_paths(const char* paths_str); void collect_include_paths(const char* paths_str);
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include <cstring> #include <cstring>
#include "document.hpp" #include "document.hpp"
#include "eval_apply.hpp" #include "eval_apply.hpp"
#include "error.hpp"
#include <iostream> #include <iostream>
namespace Sass { namespace Sass {
...@@ -11,7 +12,7 @@ namespace Sass { ...@@ -11,7 +12,7 @@ namespace Sass {
source(source_str), source(source_str),
line_number(1), line_number(1),
context(ctx), context(ctx),
root(Node(Node::root, 1)), root(Node(Node::root, context.registry, 1)),
lexed(Token::make()) lexed(Token::make())
{ {
if (source_str) { if (source_str) {
...@@ -48,22 +49,24 @@ namespace Sass { ...@@ -48,22 +49,24 @@ namespace Sass {
: path(path), source(source), : path(path), source(source),
line_number(1), own_source(false), line_number(1), own_source(false),
context(*(new Context())), context(*(new Context())),
root(Node(Node::root, 1)), root(Node(Node::root, context.registry, 1)),
lexed(Token::make()) lexed(Token::make())
{ {
if (!source) { if (!source) {
std::FILE *f; std::FILE *f;
// TO DO: CHECK f AGAINST NULL/0
f = std::fopen(path.c_str(), "rb"); f = std::fopen(path.c_str(), "rb");
std::fseek(f, 0, SEEK_END); if (!f) throw path;
if (std::fseek(f, 0, SEEK_END)) throw path;
int len = std::ftell(f); int len = std::ftell(f);
if (len < 0) throw path;
std::rewind(f); std::rewind(f);
// TO DO: WRAP THE new[] IN A TRY/CATCH BLOCK // TO DO: CATCH THE POTENTIAL badalloc EXCEPTION
source = new char[len + 1]; source = new char[len + 1];
std::fread(source, sizeof(char), len, f); std::fread(source, sizeof(char), len, f);
if (std::ferror(f)) throw path;
source[len] = '\0'; source[len] = '\0';
end = source + len; end = source + len;
std::fclose(f); if (std::fclose(f)) throw path;
own_source = true; own_source = true;
} }
position = source; position = source;
...@@ -75,35 +78,37 @@ namespace Sass { ...@@ -75,35 +78,37 @@ namespace Sass {
: path(path), source(0), : path(path), source(0),
line_number(1), own_source(false), line_number(1), own_source(false),
context(context), context(context),
root(Node(Node::root, 1)), root(Node(Node::root, context.registry, 1)),
lexed(Token::make()) lexed(Token::make())
{ {
std::FILE *f; std::FILE *f;
// TO DO: CHECK f AGAINST NULL/0
f = std::fopen(path.c_str(), "rb"); f = std::fopen(path.c_str(), "rb");
std::fseek(f, 0, SEEK_END); if (!f) throw path;
if (std::fseek(f, 0, SEEK_END)) throw path;
int len = std::ftell(f); int len = std::ftell(f);
if (len < 0) throw path;
std::rewind(f); std::rewind(f);
// TO DO: WRAP THE new[] IN A TRY/CATCH BLOCK // TO DO: CATCH THE POTENTIAL badalloc EXCEPTION
source = new char[len + 1]; source = new char[len + 1];
std::fread(source, sizeof(char), len, f); std::fread(source, sizeof(char), len, f);
if (std::ferror(f)) throw path;
source[len] = '\0'; source[len] = '\0';
end = source + len; end = source + len;
std::fclose(f); if (std::fclose(f)) throw path;
position = source; position = source;
context.source_refs.push_back(source); context.source_refs.push_back(source);
++context.ref_count; ++context.ref_count;
} }
Document::Document(size_t line_number, Token t, Context& context) Document::Document(const string& path, size_t line_number, Token t, Context& context)
: path(string()), : path(path),
source(const_cast<char*>(t.begin)), source(const_cast<char*>(t.begin)),
position(t.begin), position(t.begin),
end(t.end), end(t.end),
line_number(line_number), line_number(line_number),
own_source(false), own_source(false),
context(context), context(context),
root(Node(Node::root, 1)), root(Node(Node::root, context.registry, 1)),
lexed(Token::make()) lexed(Token::make())
{ } { }
...@@ -112,12 +117,11 @@ namespace Sass { ...@@ -112,12 +117,11 @@ namespace Sass {
// if (context.ref_count == 0) delete &context; // if (context.ref_count == 0) delete &context;
} }
// void Document::eval_pending() void Document::syntax_error(string message, size_t ln)
// { { throw Error(Error::syntax, ln ? ln : line_number, path, message); }
// for (int i = 0; i < context.pending.size(); ++i) {
// eval(context.pending[i], context.global_env); void Document::read_error(string message, size_t ln)
// } { throw Error(Error::read, ln ? ln : line_number, path, message); }
// }
using std::string; using std::string;
using std::stringstream; using std::stringstream;
......
...@@ -30,7 +30,7 @@ namespace Sass { ...@@ -30,7 +30,7 @@ namespace Sass {
Document(char* path_str, char* source_str, Context& ctx); Document(char* path_str, char* source_str, Context& ctx);
Document(string path, char* source = 0); Document(string path, char* source = 0);
Document(string path, Context& context); Document(string path, Context& context);
Document(size_t line_number, Token t, Context& context); Document(const string& path, size_t line_number, Token t, Context& context);
~Document(); ~Document();
template <prelexer mx> template <prelexer mx>
...@@ -142,6 +142,7 @@ namespace Sass { ...@@ -142,6 +142,7 @@ namespace Sass {
Node parse_identifier(); Node parse_identifier();
Node parse_variable(); Node parse_variable();
Node parse_function_call(); Node parse_function_call();
Node parse_value_schema();
const char* look_for_rule(const char* start = 0); const char* look_for_rule(const char* start = 0);
const char* look_for_values(const char* start = 0); const char* look_for_values(const char* start = 0);
...@@ -153,7 +154,9 @@ namespace Sass { ...@@ -153,7 +154,9 @@ namespace Sass {
const char* look_for_pseudo(const char* start = 0); const char* look_for_pseudo(const char* start = 0);
const char* look_for_attrib(const char* start = 0); const char* look_for_attrib(const char* start = 0);
void eval_pending(); 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);
}; };
......
namespace Sass {
struct Error {
enum Type { read, write, syntax, evaluation };
Type type;
size_t line_number;
string file_name;
string message;
Error(Type type, size_t line_number, string file_name, string message)
: type(type), line_number(line_number), file_name(file_name), message(message)
{ }
};
}
\ No newline at end of file
...@@ -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); Node eval(Node& expr, Environment& env, map<pair<string, size_t>, Function>& f_env, vector<vector<Node>*>& registry);
Node accumulate(Node::Type op, Node& acc, Node& rhs); Node accumulate(Node::Type op, Node& acc, Node& rhs, vector<vector<Node>*>& registry);
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); Node apply_mixin(Node& mixin, 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 apply_function(const Function& f, const Node& args, Environment& env, map<pair<string, size_t>, Function>& f_env, vector<vector<Node>*>& registry);
} }
\ No newline at end of file
$x: 1 2 3;
bobo + mogo {
hey: hoo;
}
@mixin moogoo() {
hey: ho;
div {
blah: blah;
bloo: (1/0) + 5;
}
}
:nth-of-type(2) {
foo: bar;
}
div[hux ~= "hello"] {
hux: blux;
foo: boo;
dux: "hello" + "goodbye";
shux: 'hello' + 12;
frux: 12 + 'hello';
blah: blah;
hoo: blah == 12;
//moo: rgba(0,0,0,.5) + rgba(0,0,0,.6);
moo: rgba(0,0,0,.5) + 3;
}
$y: hey;
@mixin foo($x) {
foofoo: $x $y;
}
div {
@include foo();
hoo: rgba(1, 3, 3, .4);
blah: fade_out(#123, 1px);
flah: unquote("hello");
grah: quote(hello);
hrah: quote(mukluk);
mwah: join((), 2, "comma");
gwah: comparable(foo, bar);
}
\ 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>&); typedef Node (*Implementation)(const vector<Token>&, map<Token, Node>&, vector<vector<Node>*>& registry);
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) const Node operator()(map<Token, Node>& bindings, vector<vector<Node>*>& registry) const
{ return implementation(parameters, bindings); } { return implementation(parameters, bindings, registry); }
}; };
...@@ -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); Node rgb(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor rgba_4_descriptor; extern Function_Descriptor rgba_4_descriptor;
Node rgba_4(const vector<Token>& parameters, map<Token, Node>& bindings); Node rgba_4(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor rgba_2_descriptor; extern Function_Descriptor rgba_2_descriptor;
Node rgba_2(const vector<Token>& parameters, map<Token, Node>& bindings); Node rgba_2(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor red_descriptor; extern Function_Descriptor red_descriptor;
Node red(const vector<Token>& parameters, map<Token, Node>& bindings); Node red(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor green_descriptor; extern Function_Descriptor green_descriptor;
Node green(const vector<Token>& parameters, map<Token, Node>& bindings); Node green(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor blue_descriptor; extern Function_Descriptor blue_descriptor;
Node blue(const vector<Token>& parameters, map<Token, Node>& bindings); Node blue(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor mix_2_descriptor; extern Function_Descriptor mix_2_descriptor;
Node mix_2(const vector<Token>& parameters, map<Token, Node>& bindings); Node mix_2(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor mix_3_descriptor; extern Function_Descriptor mix_3_descriptor;
Node mix_3(const vector<Token>& parameters, map<Token, Node>& bindings); Node mix_3(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
// HSL Functions /////////////////////////////////////////////////////// // HSL Functions ///////////////////////////////////////////////////////
extern Function_Descriptor hsla_descriptor; extern Function_Descriptor hsla_descriptor;
Node hsla(const vector<Token>& parameters, map<Token, Node>& bindings); Node hsla(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor hsl_descriptor; extern Function_Descriptor hsl_descriptor;
Node hsl(const vector<Token>& parameters, map<Token, Node>& bindings); Node hsl(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor invert_descriptor; extern Function_Descriptor invert_descriptor;
Node invert(const vector<Token>& parameters, map<Token, Node>& bindings); Node invert(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
// 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); Node alpha(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
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); Node opacify(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
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); Node transparentize(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
// String Functions //////////////////////////////////////////////////// // String Functions ////////////////////////////////////////////////////
extern Function_Descriptor unquote_descriptor; extern Function_Descriptor unquote_descriptor;
Node unquote(const vector<Token>& parameters, map<Token, Node>& bindings); Node unquote(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor quote_descriptor; extern Function_Descriptor quote_descriptor;
Node quote(const vector<Token>& parameters, map<Token, Node>& bindings); Node quote(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
// Number Functions //////////////////////////////////////////////////// // Number Functions ////////////////////////////////////////////////////
extern Function_Descriptor percentage_descriptor; extern Function_Descriptor percentage_descriptor;
Node percentage(const vector<Token>& parameters, map<Token, Node>& bindings); Node percentage(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor round_descriptor; extern Function_Descriptor round_descriptor;
Node round(const vector<Token>& parameters, map<Token, Node>& bindings); Node round(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor ceil_descriptor; extern Function_Descriptor ceil_descriptor;
Node ceil(const vector<Token>& parameters, map<Token, Node>& bindings); Node ceil(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor floor_descriptor; extern Function_Descriptor floor_descriptor;
Node floor(const vector<Token>& parameters, map<Token, Node>& bindings); Node floor(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor abs_descriptor; extern Function_Descriptor abs_descriptor;
Node abs(const vector<Token>& parameters, map<Token, Node>& bindings); Node abs(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
// List Functions ////////////////////////////////////////////////////// // List Functions //////////////////////////////////////////////////////
extern Function_Descriptor length_descriptor; extern Function_Descriptor length_descriptor;
Node length(const vector<Token>& parameters, map<Token, Node>& bindings); Node length(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor nth_descriptor; extern Function_Descriptor nth_descriptor;
Node nth(const vector<Token>& parameters, map<Token, Node>& bindings); Node nth(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor join_2_descriptor; extern Function_Descriptor join_2_descriptor;
Node join_2(const vector<Token>& parameters, map<Token, Node>& bindings); Node join_2(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor join_3_descriptor; extern Function_Descriptor join_3_descriptor;
Node join_3(const vector<Token>& parameters, map<Token, Node>& bindings); Node join_3(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
// 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); Node type_of(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor unit_descriptor; extern Function_Descriptor unit_descriptor;
Node unit(const vector<Token>& parameters, map<Token, Node>& bindings); Node unit(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor unitless_descriptor; extern Function_Descriptor unitless_descriptor;
Node unitless(const vector<Token>& parameters, map<Token, Node>& bindings); Node unitless(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor comparable_descriptor; extern Function_Descriptor comparable_descriptor;
Node comparable(const vector<Token>& parameters, map<Token, Node>& bindings); Node comparable(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
// 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); Node not_impl(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
} }
......
$x: bar;
$blux: inside blux;
div {
a: blah foo#{$x};
b: (1#{2+3}) + 4;
b: (1 (2+3)) + 4;
c: 1#{2 + 3} + 4;
d: type-of(false);
e: type-of(fa#{lse});
e: 12fa#{lse}345;
f: 12+#{3}, 12(#{3});
g: (12)34, 12(34);
h: #fff#{f};
j: $bl#{ux};
}
\ No newline at end of file
#include <stdio.h>
#include "sass_interface.h"
#include <sys/resource.h>
int main(int argc, char** argv)
{
if (argc < 2) {
printf("Hey, I need an input file!\n");
return 0;
}
int who = RUSAGE_SELF;
struct rusage r;
while (1) {
getrusage(who, &r);
printf("Memory usage: %ld\n", r.ru_maxrss);
struct sass_file_context* ctx = sass_new_file_context();
ctx->options.include_paths = "::/blah/bloo/fuzz:/slub/flub/chub::/Users/Aaron/dev/libsass/::::/huzz/buzz:::";
ctx->options.output_style = SASS_STYLE_NESTED;
ctx->input_path = argv[1];
sass_compile_file(ctx);
if (ctx->error_status) {
if (ctx->error_message) printf("%s", ctx->error_message);
else printf("An error occured; no error message available.\n");
sass_free_file_context(ctx);
break;
}
else if (ctx->output_string) {
sass_free_file_context(ctx);
continue;
}
else {
printf("Unknown internal error.\n");
sass_free_file_context(ctx);
break;
}
}
return 0;
}
\ No newline at end of file
...@@ -14,8 +14,9 @@ using std::endl; ...@@ -14,8 +14,9 @@ using std::endl;
namespace Sass { namespace Sass {
size_t Node::allocations = 0; size_t Node::allocations = 0;
size_t Node::destructed = 0;
Node Node::clone() const Node Node::clone(vector<vector<Node>*>& registry) const
{ {
Node n(*this); Node n(*this);
if (has_children) { if (has_children) {
...@@ -23,8 +24,9 @@ namespace Sass { ...@@ -23,8 +24,9 @@ namespace Sass {
++allocations; ++allocations;
n.content.children->reserve(size()); n.content.children->reserve(size());
for (int i = 0; i < size(); ++i) { for (int i = 0; i < size(); ++i) {
n << at(i).clone(); n << at(i).clone(registry);
} }
registry.push_back(n.content.children);
} }
return n; return n;
} }
...@@ -270,6 +272,12 @@ namespace Sass { ...@@ -270,6 +272,12 @@ namespace Sass {
return "!important"; return "!important";
} break; } break;
case value_schema: {
string result;
for (int i = 0; i < size(); ++i) result += at(i).to_string("");
return result;
} break;
default: { default: {
// return content.token.to_string(); // return content.token.to_string();
if (!has_children && type != flags) return content.token.to_string(); if (!has_children && type != flags) return content.token.to_string();
......
...@@ -76,6 +76,8 @@ namespace Sass { ...@@ -76,6 +76,8 @@ namespace Sass {
boolean, boolean,
important, important,
value_schema,
function_call, function_call,
mixin, mixin,
parameters, parameters,
...@@ -110,14 +112,17 @@ namespace Sass { ...@@ -110,14 +112,17 @@ namespace Sass {
bool boolean_value; bool boolean_value;
} content; } content;
const char* file_name;
static size_t allocations; static size_t allocations;
static size_t destructed;
void clear() void clear()
{ {
type = none; line_number = 0; has_children = false; type = none; line_number = 0; file_name = 0;
has_statements = false; has_blocks = false; has_expansions = false; has_children = false; has_statements = false; has_blocks = false;
has_backref = false; from_variable = false; eval_me = false; has_expansions = false; has_backref = false; from_variable = false;
unquoted = false; eval_me = false; unquoted = false;
} }
size_t size() const size_t size() const
...@@ -135,6 +140,20 @@ namespace Sass { ...@@ -135,6 +140,20 @@ namespace Sass {
return *this; 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 double numeric_value() const
{ {
switch (type) switch (type)
...@@ -174,7 +193,7 @@ namespace Sass { ...@@ -174,7 +193,7 @@ namespace Sass {
void emit_nested_css(stringstream& buf, size_t depth); void emit_nested_css(stringstream& buf, size_t depth);
void emit_expanded_css(stringstream& buf, const string& prefix); void emit_expanded_css(stringstream& buf, const string& prefix);
Node clone() const; Node clone(vector<vector<Node>*>& registry) const;
void flatten(); void flatten();
Node() Node()
...@@ -183,12 +202,13 @@ namespace Sass { ...@@ -183,12 +202,13 @@ namespace Sass {
Node(Type t) // flags or booleans Node(Type t) // flags or booleans
{ clear(); type = t; } { clear(); type = t; }
Node(Type t, unsigned int ln, size_t s = 0) // nodes with children Node(Type t, vector<vector<Node>*>& registry, unsigned int ln, size_t s = 0) // nodes with children
{ {
clear(); clear();
type = t; type = t;
line_number = ln; line_number = ln;
content.children = new vector<Node>; content.children = new vector<Node>;
registry.push_back(content.children);
content.children->reserve(s); content.children->reserve(s);
has_children = true; has_children = true;
++allocations; ++allocations;
...@@ -220,12 +240,13 @@ namespace Sass { ...@@ -220,12 +240,13 @@ namespace Sass {
content.dimension.unit = tok.begin; content.dimension.unit = tok.begin;
} }
Node(unsigned int ln, double r, double g, double b, double a = 1.0) // colors Node(vector<vector<Node>*>& registry, unsigned int ln, double r, double g, double b, double a = 1.0) // colors
{ {
clear(); clear();
type = numeric_color; type = numeric_color;
line_number = ln; line_number = ln;
content.children = new vector<Node>; content.children = new vector<Node>;
registry.push_back(content.children);
content.children->reserve(4); content.children->reserve(4);
content.children->push_back(Node(ln, r)); content.children->push_back(Node(ln, r));
content.children->push_back(Node(ln, g)); content.children->push_back(Node(ln, g));
...@@ -234,5 +255,7 @@ namespace Sass { ...@@ -234,5 +255,7 @@ namespace Sass {
has_children = true; has_children = true;
++allocations; ++allocations;
} }
~Node() { ++destructed; }
}; };
} }
\ No newline at end of file
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <cstdlib> #include <cstdlib>
#include <cmath> #include <cmath>
#include "node.hpp" #include "node.hpp"
#include "error.hpp"
using std::string; using std::string;
using std::stringstream; using std::stringstream;
...@@ -31,6 +32,7 @@ namespace Sass { ...@@ -31,6 +32,7 @@ namespace Sass {
return true; return true;
} break; } break;
case variable:
case identifier: case identifier:
case uri: case uri:
case textual_percentage: case textual_percentage:
...@@ -82,11 +84,11 @@ namespace Sass { ...@@ -82,11 +84,11 @@ namespace Sass {
return numeric_value() < rhs.numeric_value(); return numeric_value() < rhs.numeric_value();
} }
else { else {
// TO DO: throw an exception ("units don't match") throw Error(Error::evaluation, line_number, file_name, "incompatible units");
} }
} }
else { else {
// TO DO: throw an exception ("incomparable types") throw Error(Error::evaluation, line_number, file_name, "incomparable types");
} }
} }
......
...@@ -79,6 +79,15 @@ namespace Sass { ...@@ -79,6 +79,15 @@ namespace Sass {
exactly<'-'>, exactly<'-'>,
exactly<'_'> > > >(src); exactly<'_'> > > >(src);
} }
// Match interpolant schemas
const char* value_schema(const char* src) {
// follows this pattern: ([xyz]*i[xyz]*)+
return one_plus< sequence< zero_plus< alternatives< identifier, number > >,
interpolant,
zero_plus< alternatives< identifier, number > > > >(src);
}
// Match CSS '@' keywords. // Match CSS '@' keywords.
const char* at_keyword(const char* src) { const char* at_keyword(const char* src) {
return sequence<exactly<'@'>, identifier>(src); return sequence<exactly<'@'>, identifier>(src);
......
...@@ -274,6 +274,8 @@ namespace Sass { ...@@ -274,6 +274,8 @@ namespace Sass {
// Match a CSS identifier. // Match a CSS identifier.
const char* identifier(const char* src); const char* identifier(const char* src);
// Match interpolant schemas
const char* value_schema(const char* src);
// Match CSS '@' keywords. // Match CSS '@' keywords.
const char* at_keyword(const char* src); const char* at_keyword(const char* src);
const char* import(const char* src); const char* import(const char* src);
......
#include <iostream> #include <iostream>
#include <sstream>
#include <string> #include <string>
#include <cstdlib> #include <cstdlib>
#include <unistd.h> #include <unistd.h>
#include <iostream>
#include "document.hpp" #include "document.hpp"
#include "eval_apply.hpp" #include "eval_apply.hpp"
#include "error.hpp"
#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*) malloc(sizeof(sass_context)); } { return (sass_context*) malloc(sizeof(sass_context)); }
void sass_free_context(sass_context* ctx) void sass_free_context(sass_context* ctx)
{ {
...@@ -20,7 +22,7 @@ extern "C" { ...@@ -20,7 +22,7 @@ extern "C" {
} }
sass_file_context* sass_new_file_context() sass_file_context* sass_new_file_context()
{ return (sass_file_context*) malloc(sizeof(sass_file_context)); } { return (sass_file_context*) malloc(sizeof(sass_file_context)); }
void sass_free_file_context(sass_file_context* ctx) void sass_free_file_context(sass_file_context* ctx)
{ {
...@@ -29,15 +31,27 @@ extern "C" { ...@@ -29,15 +31,27 @@ extern "C" {
} }
sass_folder_context* sass_new_folder_context() sass_folder_context* sass_new_folder_context()
{ return (sass_folder_context*) malloc(sizeof(sass_folder_context)); } { return (sass_folder_context*) malloc(sizeof(sass_folder_context)); }
static char* process_document(Sass::Document& doc, int style) static char* process_document(Sass::Document& doc, int style)
{ {
using namespace Sass; using namespace Sass;
doc.parse_scss(); doc.parse_scss();
eval(doc.root, doc.context.global_env, doc.context.function_env); cerr << "PARSED" << endl;
eval(doc.root, doc.context.global_env, doc.context.function_env, doc.context.registry);
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 << "Allocations:\t" << Node::allocations << endl;
cerr << "Destructions:\t" << Node::destructed << endl;
cerr << "Registry size:\t" << doc.context.registry.size() << endl;
int i;
for (i = 0; i < doc.context.registry.size(); ++i) {
delete doc.context.registry[i];
}
cerr << "Deallocations:\t" << i << endl;
char* c_output = (char*) malloc(output.size() + 1); char* c_output = (char*) malloc(output.size() + 1);
strcpy(c_output, output.c_str()); strcpy(c_output, output.c_str());
...@@ -47,22 +61,70 @@ extern "C" { ...@@ -47,22 +61,70 @@ extern "C" {
int sass_compile(sass_context* c_ctx) int sass_compile(sass_context* c_ctx)
{ {
using namespace Sass; using namespace Sass;
// TO DO: CATCH ALL EXCEPTIONS 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); 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_status = 0;
}
catch (Error& e) {
stringstream msg_stream;
msg_stream << "ERROR -- " << e.file_name << ", line " << e.line_number << ": " << e.message << endl;
string msg(msg_stream.str());
char* msg_str = (char*) malloc(msg.size() + 1);
strcpy(msg_str, msg.c_str());
c_ctx->error_status = 1;
c_ctx->output_string = 0;
c_ctx->error_message = msg_str;
}
catch(bad_alloc& ba) {
stringstream msg_stream;
msg_stream << "ERROR -- unable to allocate memory: " << ba.what() << endl;
string msg(msg_stream.str());
char* msg_str = (char*) malloc(msg.size() + 1);
strcpy(msg_str, msg.c_str());
c_ctx->error_status = 1;
c_ctx->output_string = 0;
c_ctx->error_message = msg_str;
}
// TO DO: CATCH EVERYTHING ELSE
return 0; return 0;
} }
int sass_compile_file(sass_file_context* c_ctx) int sass_compile_file(sass_file_context* c_ctx)
{ {
using namespace Sass; using namespace Sass;
// TO DO: CATCH ALL EXCEPTIONS 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); cerr << "MADE A DOC AND CONTEXT OBJ" << endl;
c_ctx->output_string = process_document(doc, c_ctx->options.output_style); cerr << "REGISTRY: " << doc.context.registry.size() << endl;
c_ctx->output_string = process_document(doc, c_ctx->options.output_style);
c_ctx->error_message = 0;
c_ctx->error_status = 0;
}
catch (Error& e) {
stringstream msg_stream;
msg_stream << "ERROR -- " << e.file_name << ", line " << e.line_number << ": " << e.message << endl;
string msg(msg_stream.str());
char* msg_str = (char*) malloc(msg.size() + 1);
strcpy(msg_str, msg.c_str());
c_ctx->error_status = 1;
c_ctx->output_string = 0;
c_ctx->error_message = msg_str;
}
catch(bad_alloc& ba) {
stringstream msg_stream;
msg_stream << "ERROR -- unable to allocate memory: " << ba.what() << endl;
string msg(msg_stream.str());
char* msg_str = (char*) malloc(msg.size() + 1);
strcpy(msg_str, msg.c_str());
c_ctx->error_status = 1;
c_ctx->output_string = 0;
c_ctx->error_message = msg_str;
}
// TO DO: CATCH EVERYTHING ELSE
return 0; return 0;
} }
......
...@@ -16,27 +16,39 @@ struct sass_context { ...@@ -16,27 +16,39 @@ struct sass_context {
char* input_string; char* input_string;
char* output_string; char* output_string;
struct sass_options options; struct sass_options options;
int error_status;
char* error_message;
}; };
struct sass_folder_context { struct sass_folder_context {
char* search_path; char* search_path;
char* output_path; char* output_path;
struct sass_options options; struct sass_options options;
int error_status;
char* error_message;
}; };
struct sass_file_context { struct sass_file_context {
char* input_path; char* input_path;
char* output_string; char* output_string;
struct sass_options options; struct sass_options options;
int error_status;
char* error_message;
}; };
struct sass_context* sass_new_context (); struct sass_context* sass_new_context ();
struct sass_folder_context* sass_new_folder_context (); struct sass_folder_context* sass_new_folder_context ();
struct sass_file_context* sass_new_file_context (); struct sass_file_context* sass_new_file_context ();
int sass_compile (struct sass_context*); void sass_free_context (struct sass_context* ctx);
// int sass_folder_compile (struct sass_folder_context*); void sass_free_folder_context (struct sass_folder_context* ctx);
int sass_file_compile (struct sass_file_context*); void sass_free_file_context (struct sass_file_context* ctx);
int sass_compile (struct sass_context*);
//int sass_compile_folder (struct sass_folder_context*);
int sass_compile_file (struct sass_file_context*);
void sass_free_file_context (struct sass_file_context* ctx);
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -34,7 +34,16 @@ int main(int argc, char** argv) ...@@ -34,7 +34,16 @@ int main(int argc, char** argv)
sass_compile_file(ctx); sass_compile_file(ctx);
printf("%s", ctx->output_string); if (ctx->error_status) {
if (ctx->error_message) printf("%s", ctx->error_message);
else printf("An error occured; no error message available.\n");
}
else if (ctx->output_string) {
printf("%s", ctx->output_string);
}
else {
printf("Unknown internal error.\n");
}
sass_free_file_context(ctx); sass_free_file_context(ctx);
return 0; return 0;
......
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