Commit 9180b5c4 by Dean Mao

add callback support and add newlines at end of files

parent c4ce49a4
......@@ -6,13 +6,12 @@ Node bindings to libsass
## Install
cd libsass && make && cd ..
node-waf configure && node-waf build
npm install
## Usage
var sass = require('./sass');
sass.render('body{background:blue; a{color:black;}}', function(css){
sass.render('body{background:blue; a{color:black;}}', function(err, css){
console.log(css)
});
......@@ -40,4 +39,4 @@ Heavily inspired by <https://github.com/LearnBoost/stylus>
* publish npm
* use node-gyp for builds
* file context
* folder context
\ No newline at end of file
* folder context
#include <v8.h>
#include <node.h>
#include <string>
#include <cstdlib>
#include "libsass/sass_interface.h"
using namespace v8;
void WorkOnContext(uv_work_t* req) {
sass_context* ctx = static_cast<sass_context*>(req->data);
sass_compile(ctx);
}
void MakeCallback(uv_work_t* req) {
HandleScope scope;
TryCatch try_catch;
sass_context* ctx = static_cast<sass_context*>(req->data);
if (ctx->error_status == 0) {
// if no error, do callback(null, result)
const unsigned argc = 2;
Local<Value> argv[argc] = {
Local<Value>::New(Null()),
Local<Value>::New(String::New(ctx->output_string))
};
ctx->callback->Call(Context::GetCurrent()->Global(), argc, argv);
} else {
// if error, do callback(error)
const unsigned argc = 1;
Local<Value> argv[argc] = {
Local<Value>::New(String::New(ctx->error_message))
};
ctx->callback->Call(Context::GetCurrent()->Global(), argc, argv);
}
if (try_catch.HasCaught()) {
node::FatalException(try_catch);
}
}
Handle<Value> Render(const Arguments& args) {
HandleScope scope;
struct sass_context* ctx = sass_new_context();
String::AsciiValue astr(args[0]);
char * cs = *astr;
sass_context* ctx = sass_new_context();
String::AsciiValue astr(args[0]);
Local<Function> callback = Local<Function>::Cast(args[1]);
ctx->source_string = cs;
ctx->source_string = new char[strlen(*astr)+1];
strcpy(ctx->source_string, *astr);
ctx->options.include_paths = 0;
ctx->options.output_style = SASS_STYLE_NESTED;
ctx->callback = Persistent<Function>::New(callback);
ctx->request.data = ctx;
sass_compile(ctx);
int status = uv_queue_work(uv_default_loop(), &ctx->request, WorkOnContext, MakeCallback);
assert(status == 0);
return scope.Close(String::New(ctx->output_string));
return Undefined();
}
void RegisterModule(v8::Handle<v8::Object> target) {
......
......@@ -20,13 +20,13 @@ var imports = {};
* when undefined defaults to `src`.
*
* Examples:
*
*
* Pass the middleware to Connect, grabbing .scss files from this directory
* and saving .css files to _./public_.
*
*
* Following that we have a `staticProvider` layer setup to serve the .css
* files generated by Sass.
*
*
* var server = connect.createServer(
* sass.middleware({
* src: __dirname
......@@ -34,7 +34,7 @@ var imports = {};
* })
* , connect.static(__dirname + '/public')
* );
*
*
* @param {Object} options
* @return {Function}
* @api public
......@@ -99,8 +99,8 @@ module.exports = function(options){
var style = options.compile();
var paths = [];
delete imports[sassPath];
style.render(str, function(css){
// if (err) return next(err);
style.render(str, function(err, css){
if (err) return next(err);
if (debug) log('render', sassPath);
imports[sassPath] = paths;
mkdirp(dirname(cssPath), 0700, function(err){
......@@ -187,4 +187,4 @@ function checkImports(path, fn) {
function log(key, val) {
console.error(' \033[90m%s :\033[0m \033[36m%s\033[0m', key, val);
}
\ No newline at end of file
}
......@@ -6,7 +6,7 @@ using std::cerr; using std::endl;
namespace Sass {
using std::pair;
void Context::collect_include_paths(const char* paths_str)
{
const size_t wd_len = 1024;
......@@ -39,7 +39,7 @@ namespace Sass {
// cerr << include_paths[i] << endl;
// }
}
Context::Context(const char* paths_str)
: global_env(Environment()),
function_env(map<pair<string, size_t>, Function>()),
......@@ -54,7 +54,7 @@ namespace Sass {
register_functions();
collect_include_paths(paths_str);
}
Context::~Context()
{
for (size_t i = 0; i < source_refs.size(); ++i) {
......@@ -64,19 +64,19 @@ namespace Sass {
new_Node.free();
// cerr << "Deallocated " << i << " source string(s)." << endl;
}
inline void Context::register_function(Function_Descriptor d, Implementation ip)
{
Function f(d, ip);
function_env[pair<string, size_t>(f.name, f.parameters.size())] = f;
}
inline void Context::register_function(Function_Descriptor d, Implementation ip, size_t arity)
{
Function f(d, ip);
function_env[pair<string, size_t>(f.name, arity)] = f;
}
void Context::register_functions()
{
using namespace Functions;
......@@ -122,5 +122,6 @@ namespace Sass {
// Boolean Functions
register_function(not_descriptor, not_impl);
}
}
......@@ -9,29 +9,29 @@
namespace Sass {
using std::pair;
using std::map;
struct Environment {
map<Token, Node> current_frame;
Environment* parent;
Environment* global;
Environment()
: current_frame(map<Token, Node>()), parent(0), global(0)
{ }
void link(Environment& env)
{
parent = &env;
global = parent->global ? parent->global : parent;
}
bool query(const Token& key) const
{
if (current_frame.count(key)) return true;
else if (parent) return parent->query(key);
else return false;
}
Node& operator[](const Token& key)
{
if (current_frame.count(key)) return current_frame[key];
......@@ -56,10 +56,11 @@ namespace Sass {
void collect_include_paths(const char* paths_str);
Context(const char* paths_str = 0);
~Context();
void register_function(Function_Descriptor d, Implementation ip);
void register_function(Function_Descriptor d, Implementation ip, size_t arity);
void register_functions();
};
}
......@@ -90,17 +90,17 @@ namespace Sass {
return doc;
}
void Document::throw_syntax_error(string message, size_t ln)
{ throw Error(Error::syntax, path, ln ? ln : line, message); }
void Document::throw_read_error(string message, size_t ln)
{ throw Error(Error::read, path, ln ? ln : line, message); }
using std::string;
using std::stringstream;
using std::endl;
string Document::emit_css(CSS_Style style) {
stringstream output;
switch (style) {
......@@ -121,3 +121,4 @@ namespace Sass {
return retval;
}
}
......@@ -25,7 +25,7 @@ namespace Sass {
struct Document {
enum CSS_Style { nested, expanded, compact, compressed, echo };
string path;
char* source;
const char* position;
......@@ -34,7 +34,7 @@ namespace Sass {
bool own_source;
Context& context;
Node root;
Token lexed;
......@@ -84,7 +84,7 @@ namespace Sass {
return 0;
}
}
template <prelexer mx>
const char* lex()
{
......@@ -123,7 +123,7 @@ namespace Sass {
return 0;
}
}
void parse_scss();
Node parse_import();
Node parse_include();
......@@ -163,13 +163,14 @@ namespace Sass {
Node parse_if_directive(Node surrounding_ruleset);
Node parse_for_directive(Node surrounding_ruleset);
Selector_Lookahead lookahead_for_selector(const char* start = 0);
void throw_syntax_error(string message, size_t ln = 0);
void throw_read_error(string message, size_t ln = 0);
string emit_css(CSS_Style style);
};
}
\ No newline at end of file
}
......@@ -149,7 +149,7 @@ namespace Sass {
the_call << name << args;
return the_call;
}
Node Document::parse_arguments()
{
Token name(lexed);
......@@ -169,7 +169,7 @@ namespace Sass {
}
return args;
}
Node Document::parse_argument()
{
if (peek< sequence < variable, spaces_and_comments, exactly<':'> > >()) {
......@@ -196,7 +196,7 @@ namespace Sass {
assn << var << val;
return assn;
}
Node Document::parse_propset()
{
lex< identifier >();
......@@ -237,7 +237,7 @@ namespace Sass {
extern const char hash_lbrace[] = "#{";
extern const char rbrace[] = "}";
Node Document::parse_selector_schema(const char* end_of_selector)
{
{
const char* i = position;
const char* p;
Node schema(context.new_Node(Node::selector_schema, path, line, 1));
......@@ -267,7 +267,7 @@ namespace Sass {
{
Node sel1(parse_selector());
if (!peek< exactly<','> >()) return sel1;
Node group(context.new_Node(Node::selector_group, path, line, 2));
group << sel1;
while (lex< exactly<','> >()) group << parse_selector();
......@@ -280,7 +280,7 @@ namespace Sass {
if (peek< exactly<','> >() ||
peek< exactly<')'> >() ||
peek< exactly<'{'> >()) return seq1;
Node selector(context.new_Node(Node::selector, path, line, 2));
selector << seq1;
......@@ -297,7 +297,7 @@ namespace Sass {
lex< exactly<'~'> >() ||
lex< exactly<'>'> >())
{ return context.new_Node(Node::selector_combinator, path, line, lexed); }
// check for backref or type selector, which are only allowed at the front
Node simp1;
if (lex< exactly<'&'> >()) {
......@@ -309,7 +309,7 @@ namespace Sass {
else {
simp1 = parse_simple_selector();
}
// now we have one simple/atomic selector -- see if that's all
if (peek< spaces >() || peek< exactly<'>'> >() ||
peek< exactly<'+'> >() || peek< exactly<'~'> >() ||
......@@ -320,7 +320,7 @@ namespace Sass {
// otherwise, we have a sequence of simple selectors
Node seq(context.new_Node(Node::simple_selector_sequence, path, line, 2));
seq << simp1;
while (!peek< spaces >(position) &&
!(peek < exactly<'+'> >(position) ||
peek < exactly<'~'> >(position) ||
......@@ -333,14 +333,14 @@ namespace Sass {
}
return seq;
}
Node Document::parse_selector_combinator()
{
lex< exactly<'+'> >() || lex< exactly<'~'> >() ||
lex< exactly<'>'> >() || lex< ancestor_of >();
return context.new_Node(Node::selector_combinator, path, line, lexed);
}
Node Document::parse_simple_selector()
{
if (lex< id_name >() || lex< class_name >()) {
......@@ -358,7 +358,7 @@ namespace Sass {
// unreachable statement
return Node();
}
Node Document::parse_pseudo() {
if (lex< pseudo_not >()) {
Node ps_not(context.new_Node(Node::pseudo_negation, path, line, 2));
......@@ -410,7 +410,7 @@ namespace Sass {
// unreachable statement
return Node();
}
Node Document::parse_attribute_selector()
{
Node attr_sel(context.new_Node(Node::attribute_selector, path, line, 3));
......@@ -532,12 +532,12 @@ namespace Sass {
rule << parse_list();
return rule;
}
Node Document::parse_list()
{
return parse_comma_list();
}
Node Document::parse_comma_list()
{
if (peek< exactly<';'> >(position) ||
......@@ -548,21 +548,21 @@ namespace Sass {
Node list1(parse_space_list());
// if it's a singleton, return it directly; don't wrap it
if (!peek< exactly<','> >(position)) return list1;
Node comma_list(context.new_Node(Node::comma_list, path, line, 2));
comma_list << list1;
comma_list.should_eval() |= list1.should_eval();
while (lex< exactly<','> >())
{
Node list(parse_space_list());
comma_list << list;
comma_list.should_eval() |= list.should_eval();
}
return comma_list;
}
Node Document::parse_space_list()
{
Node disj1(parse_disjunction());
......@@ -573,11 +573,11 @@ namespace Sass {
peek< exactly<')'> >(position) ||
peek< exactly<','> >(position))
{ return disj1; }
Node space_list(context.new_Node(Node::space_list, path, line, 2));
space_list << disj1;
space_list.should_eval() |= disj1.should_eval();
while (!(peek< exactly<';'> >(position) ||
peek< exactly<'}'> >(position) ||
peek< exactly<'{'> >(position) ||
......@@ -588,37 +588,37 @@ namespace Sass {
space_list << disj;
space_list.should_eval() |= disj.should_eval();
}
return space_list;
}
Node Document::parse_disjunction()
{
Node conj1(parse_conjunction());
// if it's a singleton, return it directly; don't wrap it
if (!peek< sequence< or_kwd, negate< identifier > > >()) return conj1;
Node disjunction(context.new_Node(Node::disjunction, path, line, 2));
disjunction << conj1;
while (lex< sequence< or_kwd, negate< identifier > > >()) disjunction << parse_conjunction();
disjunction.should_eval() = true;
return disjunction;
}
Node Document::parse_conjunction()
{
Node rel1(parse_relation());
// if it's a singleton, return it directly; don't wrap it
if (!peek< sequence< and_kwd, negate< identifier > > >()) return rel1;
Node conjunction(context.new_Node(Node::conjunction, path, line, 2));
conjunction << rel1;
while (lex< sequence< and_kwd, negate< identifier > > >()) conjunction << parse_relation();
conjunction.should_eval() = true;
return conjunction;
}
Node Document::parse_relation()
{
Node expr1(parse_expression());
......@@ -630,26 +630,26 @@ namespace Sass {
peek< lt_op >(position) ||
peek< lte_op >(position)))
{ return expr1; }
Node relation(context.new_Node(Node::relation, path, line, 3));
expr1.should_eval() = true;
relation << expr1;
if (lex< eq_op >()) relation << context.new_Node(Node::eq, path, line, lexed);
else if (lex< neq_op >()) relation << context.new_Node(Node::neq, path, line, lexed);
else if (lex< gte_op >()) relation << context.new_Node(Node::gte, path, line, lexed);
else if (lex< lte_op >()) relation << context.new_Node(Node::lte, path, line, lexed);
else if (lex< gt_op >()) relation << context.new_Node(Node::gt, path, line, lexed);
else if (lex< lt_op >()) relation << context.new_Node(Node::lt, path, line, lexed);
Node expr2(parse_expression());
expr2.should_eval() = true;
relation << expr2;
relation.should_eval() = true;
return relation;
}
Node Document::parse_expression()
{
Node term1(parse_term());
......@@ -657,11 +657,11 @@ namespace Sass {
if (!(peek< exactly<'+'> >(position) ||
peek< sequence< negate< number >, exactly<'-'> > >(position)))
{ return term1; }
Node expression(context.new_Node(Node::expression, path, line, 3));
term1.should_eval() = true;
expression << term1;
while (lex< exactly<'+'> >() || lex< sequence< negate< number >, exactly<'-'> > >()) {
if (lexed.begin[0] == '+') {
expression << context.new_Node(Node::add, path, line, lexed);
......@@ -677,7 +677,7 @@ namespace Sass {
return expression;
}
Node Document::parse_term()
{
Node fact1(parse_factor());
......@@ -705,7 +705,7 @@ namespace Sass {
return term;
}
Node Document::parse_factor()
{
if (lex< exactly<'('> >()) {
......@@ -733,7 +733,7 @@ namespace Sass {
return parse_value();
}
}
Node Document::parse_value()
{
if (lex< uri_prefix >())
......@@ -748,19 +748,19 @@ namespace Sass {
lex< exactly<')'> >();
return result;
}
if (lex< value_schema >())
{ return Document::make_from_token(context, lexed, path, line).parse_value_schema(); }
if (lex< sequence< true_kwd, negate< identifier > > >())
{ return context.new_Node(Node::boolean, path, line, true); }
if (lex< sequence< false_kwd, negate< identifier > > >())
{ return context.new_Node(Node::boolean, path, line, false); }
if (peek< functional >())
{ return parse_function_call(); }
if (lex< important >())
{ return context.new_Node(Node::important, path, line, lexed); }
......@@ -780,7 +780,7 @@ namespace Sass {
{ return context.new_Node(Node::textual_hex, path, line, lexed); }
if (peek< string_constant >())
{ return parse_string(); }
{ return parse_string(); }
if (lex< variable >())
{
......@@ -788,15 +788,15 @@ namespace Sass {
var.should_eval() = true;
return var;
}
throw_syntax_error("error reading values after " + lexed.to_string());
// unreachable statement
return Node();
}
Node Document::parse_string()
{
{
lex< string_constant >();
Token str(lexed);
const char* i = str.begin;
......@@ -805,7 +805,7 @@ namespace Sass {
if (!p) {
return context.new_Node(Node::string_constant, path, line, str);
}
Node schema(context.new_Node(Node::string_schema, path, line, 1));
while (i < str.end) {
p = find_first_in_interval< sequence< negate< exactly<'\\'> >, exactly<hash_lbrace> > >(i, str.end);
......@@ -833,11 +833,11 @@ namespace Sass {
}
return schema;
}
Node Document::parse_value_schema()
{
{
Node schema(context.new_Node(Node::value_schema, path, line, 1));
while (position < end) {
if (lex< interpolant >()) {
Token insides(Token::make(lexed.begin + 2, lexed.end - 1));
......@@ -872,7 +872,7 @@ namespace Sass {
schema.should_eval() = true;
return schema;
}
Node Document::parse_function_call()
{
lex< identifier >();
......@@ -924,7 +924,7 @@ namespace Sass {
loop << var << lower_bound << upper_bound << body;
return loop;
}
Selector_Lookahead Document::lookahead_for_selector(const char* start)
{
const char* p = start ? start : position;
......@@ -974,5 +974,6 @@ namespace Sass {
return result;
}
}
\ No newline at end of file
}
namespace Sass {
struct Error {
enum Type { read, write, syntax, evaluation };
Type type;
string path;
size_t line;
string message;
Error(Type type, string path, size_t line, string message)
: type(type), path(path), line(line), message(message)
{ }
};
}
\ No newline at end of file
}
......@@ -27,7 +27,7 @@ namespace Sass {
env[expr[0].token()] = expr;
return expr;
} break;
case Node::expansion: {
Token name(expr[0].token());
Node args(expr[1]);
......@@ -39,7 +39,7 @@ namespace Sass {
expr += expansion;
return expr;
} break;
case Node::propset: {
eval(expr[1], prefix, env, f_env, new_Node, ctx);
return expr;
......@@ -91,14 +91,14 @@ namespace Sass {
Node sel(needs_reparsing.parse_selector_group());
return sel;
} break;
case Node::root: {
for (size_t i = 0, S = expr.size(); i < S; ++i) {
expr[i] = eval(expr[i], prefix, env, f_env, new_Node, ctx);
}
return expr;
} break;
case Node::block: {
Environment new_frame;
new_frame.link(env);
......@@ -107,7 +107,7 @@ namespace Sass {
}
return expr;
} break;
case Node::assignment: {
Node val(expr[1]);
if (val.type() == Node::comma_list || val.type() == Node::space_list) {
......@@ -149,7 +149,7 @@ namespace Sass {
if (expr.should_eval()) expr[0] = eval(expr[0], prefix, env, f_env, new_Node, ctx);
return expr;
} break;
case Node::disjunction: {
Node result;
for (size_t i = 0, S = expr.size(); i < S; ++i) {
......@@ -159,7 +159,7 @@ namespace Sass {
}
return result;
} break;
case Node::conjunction: {
Node result;
for (size_t i = 0, S = expr.size(); i < S; ++i) {
......@@ -168,16 +168,16 @@ namespace Sass {
}
return result;
} break;
case Node::relation: {
Node lhs(eval(expr[0], prefix, env, f_env, new_Node, ctx));
Node op(expr[1]);
Node rhs(eval(expr[2], prefix, env, f_env, new_Node, ctx));
// TO DO: don't allocate both T and F
Node T(new_Node(Node::boolean, lhs.path(), lhs.line(), true));
Node F(new_Node(Node::boolean, lhs.path(), lhs.line(), false));
switch (op.type())
{
case Node::eq: return (lhs == rhs) ? T : F;
......@@ -231,12 +231,12 @@ namespace Sass {
Token::make(Prelexer::number(expr.token().begin),
expr.token().end));
} break;
case Node::textual_number: {
return new_Node(expr.path(), expr.line(), std::atof(expr.token().begin));
} break;
case Node::textual_hex: {
case Node::textual_hex: {
Node triple(new_Node(Node::numeric_color, expr.path(), expr.line(), 4));
Token hext(Token::make(expr.token().begin+1, expr.token().end));
if (hext.length() == 6) {
......@@ -252,19 +252,19 @@ namespace Sass {
triple << new_Node(expr.path(), expr.line(), 1.0);
return triple;
} break;
case Node::variable: {
if (!env.query(expr.token())) throw_eval_error("reference to unbound variable " + expr.token().to_string(), expr.path(), expr.line());
return env[expr.token()];
} break;
case Node::function_call: {
// TO DO: default-constructed Function should be a generic callback (maybe)
pair<string, size_t> sig(expr[0].token().to_string(), expr[1].size());
if (!f_env.count(sig)) return expr;
return apply_function(f_env[sig], expr[1], prefix, env, f_env, new_Node, ctx);
} break;
case Node::unary_plus: {
Node arg(eval(expr[0], prefix, env, f_env, new_Node, ctx));
if (arg.is_numeric()) {
......@@ -275,7 +275,7 @@ namespace Sass {
return expr;
}
} break;
case Node::unary_minus: {
Node arg(eval(expr[0], prefix, env, f_env, new_Node, ctx));
if (arg.is_numeric()) {
......@@ -286,7 +286,7 @@ namespace Sass {
return expr;
}
} break;
case Node::string_schema:
case Node::value_schema: {
for (size_t i = 0, S = expr.size(); i < S; ++i) {
......@@ -294,7 +294,7 @@ namespace Sass {
}
return expr;
} break;
case Node::css_import: {
expr[0] = eval(expr[0], prefix, env, f_env, new_Node, ctx);
return expr;
......@@ -359,7 +359,7 @@ namespace Sass {
Node lhs(acc.back());
double lnum = lhs.numeric_value();
double rnum = rhs.numeric_value();
if (lhs.type() == Node::number && rhs.type() == Node::number) {
Node result(new_Node(acc.path(), acc.line(), operate(op, lnum, rnum)));
acc.pop_back();
......@@ -451,7 +451,7 @@ namespace Sass {
// Apply a mixin -- bind the arguments in a new environment, link the new
// environment to the current one, then copy the body and eval in the new
// environment.
Node apply_mixin(Node mixin, const Node args, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& ctx)
{
Node params(mixin[1]);
......@@ -510,7 +510,7 @@ namespace Sass {
// Apply a function -- bind the arguments and pass them to the underlying
// primitive function implementation, then return its value.
Node apply_function(const Function& f, const Node args, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& ctx)
{
map<Token, Node> bindings;
......@@ -855,3 +855,4 @@ namespace Sass {
{ return selector_but(sel, new_Node, 0, 1); }
}
......@@ -10,11 +10,11 @@
namespace Sass {
using std::map;
Node eval(Node expr, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& src_refs);
Node accumulate(Node::Type op, Node acc, Node rhs, Node_Factory& new_Node);
double operate(Node::Type op, double lhs, double rhs);
Node apply_mixin(Node mixin, const Node args, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& src_refs);
Node apply_function(const Function& f, const Node args, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& src_refs);
Node expand_selector(Node sel, Node pre, Node_Factory& new_Node);
......@@ -28,4 +28,5 @@ namespace Sass {
Node selector_butfirst(Node sel, Node_Factory& new_Node);
Node selector_butlast(Node sel, Node_Factory& new_Node);
}
\ No newline at end of file
}
......@@ -21,7 +21,7 @@ namespace Sass {
// RGB Functions ///////////////////////////////////////////////////////
Function_Descriptor rgb_descriptor =
Function_Descriptor rgb_descriptor =
{ "rgb", "$red", "$green", "$blue", 0 };
Node rgb(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node r(bindings[parameters[0]]);
......@@ -33,7 +33,7 @@ namespace Sass {
return new_Node(r.path(), r.line(), r.numeric_value(), g.numeric_value(), b.numeric_value(), 1.0);
}
Function_Descriptor rgba_4_descriptor =
Function_Descriptor rgba_4_descriptor =
{ "rgba", "$red", "$green", "$blue", "$alpha", 0 };
Node rgba_4(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node r(bindings[parameters[0]]);
......@@ -45,8 +45,8 @@ namespace Sass {
}
return new_Node(r.path(), r.line(), r.numeric_value(), g.numeric_value(), b.numeric_value(), a.numeric_value());
}
Function_Descriptor rgba_2_descriptor =
Function_Descriptor rgba_2_descriptor =
{ "rgba", "$color", "$alpha", 0 };
Node rgba_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0]]);
......@@ -57,7 +57,7 @@ namespace Sass {
if (color.type() != Node::numeric_color || a.type() != Node::number) throw_eval_error("arguments to rgba must be a color and a number", color.path(), color.line());
return new_Node(color.path(), color.line(), r.numeric_value(), g.numeric_value(), b.numeric_value(), a.numeric_value());
}
Function_Descriptor red_descriptor =
{ "red", "$color", 0 };
Node red(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
......@@ -65,7 +65,7 @@ namespace Sass {
if (color.type() != Node::numeric_color) throw_eval_error("argument to red must be a color", color.path(), color.line());
return color[0];
}
Function_Descriptor green_descriptor =
{ "green", "$color", 0 };
Node green(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
......@@ -73,7 +73,7 @@ namespace Sass {
if (color.type() != Node::numeric_color) throw_eval_error("argument to green must be a color", color.path(), color.line());
return color[1];
}
Function_Descriptor blue_descriptor =
{ "blue", "$color", 0 };
Node blue(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
......@@ -81,7 +81,7 @@ namespace Sass {
if (color.type() != Node::numeric_color) throw_eval_error("argument to blue must be a color", color.path(), color.line());
return color[2];
}
Node mix_impl(Node color1, Node color2, double weight, Node_Factory& new_Node) {
if (!(color1.type() == Node::numeric_color && color2.type() == Node::numeric_color)) {
throw_eval_error("first two arguments to mix must be colors", color1.path(), color1.line());
......@@ -89,10 +89,10 @@ namespace Sass {
double p = weight/100;
double w = 2*p - 1;
double a = color1[3].numeric_value() - color2[3].numeric_value();
double w1 = (((w * a == -1) ? w : (w + a)/(1 + w*a)) + 1)/2.0;
double w2 = 1 - w1;
Node mixed(new_Node(Node::numeric_color, color1.path(), color1.line(), 4));
for (int i = 0; i < 3; ++i) {
mixed << new_Node(mixed.path(), mixed.line(),
......@@ -102,13 +102,13 @@ namespace Sass {
mixed << new_Node(mixed.path(), mixed.line(), alpha);
return mixed;
}
Function_Descriptor mix_2_descriptor =
{ "mix", "$color1", "$color2", 0 };
Node mix_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
return mix_impl(bindings[parameters[0]], bindings[parameters[1]], 50, new_Node);
}
Function_Descriptor mix_3_descriptor =
{ "mix", "$color1", "$color2", "$weight", 0 };
Node mix_3(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
......@@ -121,9 +121,9 @@ namespace Sass {
percentage.numeric_value(),
new_Node);
}
// HSL Functions ///////////////////////////////////////////////////////
double h_to_rgb(double m1, double m2, double h) {
if (h < 0) ++h;
if (h > 1) --h;
......@@ -145,7 +145,7 @@ namespace Sass {
double r = h_to_rgb(m1, m2, h+1.0/3.0) * 255.0;
double g = h_to_rgb(m1, m2, h) * 255.0;
double b = h_to_rgb(m1, m2, h-1.0/3.0) * 255.0;
return new_Node("", 0, r, g, b, a);
}
......@@ -157,7 +157,7 @@ namespace Sass {
bindings[parameters[2]].is_numeric() &&
bindings[parameters[3]].is_numeric())) {
throw_eval_error("arguments to hsla must be numeric", bindings[parameters[0]].path(), bindings[parameters[0]].line());
}
}
double h = bindings[parameters[0]].numeric_value();
double s = bindings[parameters[1]].numeric_value();
double l = bindings[parameters[2]].numeric_value();
......@@ -166,7 +166,7 @@ namespace Sass {
// color.line() = bindings[parameters[0]].line();
return color;
}
Function_Descriptor hsl_descriptor =
{ "hsl", "$hue", "$saturation", "$lightness", 0 };
Node hsl(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
......@@ -174,7 +174,7 @@ namespace Sass {
bindings[parameters[1]].is_numeric() &&
bindings[parameters[2]].is_numeric())) {
throw_eval_error("arguments to hsl must be numeric", bindings[parameters[0]].path(), bindings[parameters[0]].line());
}
}
double h = bindings[parameters[0]].numeric_value();
double s = bindings[parameters[1]].numeric_value();
double l = bindings[parameters[2]].numeric_value();
......@@ -182,7 +182,7 @@ namespace Sass {
// color.line() = bindings[parameters[0]].line();
return color;
}
Function_Descriptor invert_descriptor =
{ "invert", "$color", 0 };
Node invert(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
......@@ -194,9 +194,9 @@ namespace Sass {
255 - orig[2].numeric_value(),
orig[3].numeric_value());
}
// Opacity Functions ///////////////////////////////////////////////////
Function_Descriptor alpha_descriptor =
{ "alpha", "$color", 0 };
Function_Descriptor opacity_descriptor =
......@@ -206,7 +206,7 @@ namespace Sass {
if (color.type() != Node::numeric_color) throw_eval_error("argument to alpha must be a color", color.path(), color.line());
return color[3];
}
Function_Descriptor opacify_descriptor =
{ "opacify", "$color", "$amount", 0 };
Function_Descriptor fade_in_descriptor =
......@@ -226,7 +226,7 @@ namespace Sass {
return new_Node(color.path(), color.line(),
color[0].numeric_value(), color[1].numeric_value(), color[2].numeric_value(), alpha);
}
Function_Descriptor transparentize_descriptor =
{ "transparentize", "$color", "$amount", 0 };
Function_Descriptor fade_out_descriptor =
......@@ -246,9 +246,9 @@ namespace Sass {
return new_Node(color.path(), color.line(),
color[0].numeric_value(), color[1].numeric_value(), color[2].numeric_value(), alpha);
}
// String Functions ////////////////////////////////////////////////////
Function_Descriptor unquote_descriptor =
{ "unquote", "$string", 0 };
Node unquote(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
......@@ -259,7 +259,7 @@ namespace Sass {
cpy.is_unquoted() = true;
return cpy;
}
Function_Descriptor quote_descriptor =
{ "quote", "$string", 0 };
Node quote(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
......@@ -271,9 +271,9 @@ namespace Sass {
cpy.is_unquoted() = false;
return cpy;
}
// Number Functions ////////////////////////////////////////////////////
Function_Descriptor percentage_descriptor =
{ "percentage", "$value", 0 };
Node percentage(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
......@@ -403,7 +403,7 @@ namespace Sass {
// unreachable statement
return Node();
}
// List Functions //////////////////////////////////////////////////////
Function_Descriptor length_descriptor =
......@@ -429,7 +429,7 @@ namespace Sass {
// unreachable statement
return Node();
}
Function_Descriptor nth_descriptor =
{ "nth", "$list", "$n", 0 };
Node nth(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
......@@ -451,7 +451,7 @@ namespace Sass {
}
return l[n_prim - 1];
}
extern const char separator_kwd[] = "$separator";
Node join_impl(const vector<Token>& parameters, map<Token, Node>& bindings, bool has_sep, Node_Factory& new_Node) {
// if the args aren't lists, turn them into singleton lists
......@@ -490,27 +490,27 @@ namespace Sass {
if (l2.type() != Node::nil) lr += l2;
return lr;
}
Function_Descriptor join_2_descriptor =
{ "join", "$list1", "$list2", 0 };
Node join_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
return join_impl(parameters, bindings, false, new_Node);
}
Function_Descriptor join_3_descriptor =
{ "join", "$list1", "$list2", "$separator", 0 };
Node join_3(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
return join_impl(parameters, bindings, true, new_Node);
}
// Introspection Functions /////////////////////////////////////////////
extern const char number_name[] = "number";
extern const char string_name[] = "string";
extern const char bool_name[] = "bool";
extern const char color_name[] = "color";
extern const char list_name[] = "list";
Function_Descriptor type_of_descriptor =
{ "type-of", "$value", 0 };
Node type_of(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
......@@ -546,10 +546,10 @@ namespace Sass {
type.is_unquoted() = true;
return type;
}
extern const char empty_str[] = "";
extern const char percent_str[] = "%";
Function_Descriptor unit_descriptor =
{ "unit", "$number", 0 };
Node unit(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
......@@ -598,7 +598,7 @@ namespace Sass {
// unreachable statement
return Node();
}
Function_Descriptor comparable_descriptor =
{ "comparable", "$number_1", "$number_2", 0 };
Node comparable(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
......@@ -632,7 +632,7 @@ namespace Sass {
// default to false if we missed anything
return new_Node(Node::boolean, n1.path(), n1.line(), false);
}
// Boolean Functions ///////////////////////////////////////////////////
Function_Descriptor not_descriptor =
{ "not", "value", 0 };
......@@ -648,3 +648,4 @@ namespace Sass {
}
}
......@@ -7,20 +7,20 @@
namespace Sass {
using std::map;
typedef Node (*Implementation)(const vector<Token>&, map<Token, Node>&, Node_Factory& new_Node);
typedef const char* str;
typedef str Function_Descriptor[];
struct Function {
string name;
vector<Token> parameters;
Implementation implementation;
Function()
{ /* TO DO: set up the generic callback here */ }
Function(Function_Descriptor d, Implementation ip)
: name(d[0]),
parameters(vector<Token>()),
......@@ -28,7 +28,7 @@ namespace Sass {
{
size_t len = 0;
while (d[len+1]) ++len;
parameters.reserve(len);
for (size_t i = 0; i < len; ++i) {
const char* p = d[i+1];
......@@ -36,12 +36,12 @@ namespace Sass {
parameters.push_back(name);
}
}
Node operator()(map<Token, Node>& bindings, Node_Factory& new_Node) const
{ return implementation(parameters, bindings, new_Node); }
};
namespace Functions {
// RGB Functions ///////////////////////////////////////////////////////
......@@ -51,58 +51,58 @@ namespace Sass {
extern Function_Descriptor rgba_4_descriptor;
Node rgba_4(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor rgba_2_descriptor;
Node rgba_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor red_descriptor;
Node red(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor green_descriptor;
Node green(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor blue_descriptor;
Node blue(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor mix_2_descriptor;
Node mix_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor mix_3_descriptor;
Node mix_3(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// HSL Functions ///////////////////////////////////////////////////////
extern Function_Descriptor hsla_descriptor;
Node hsla(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor hsl_descriptor;
Node hsl(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor invert_descriptor;
Node invert(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Opacity Functions ///////////////////////////////////////////////////
extern Function_Descriptor alpha_descriptor;
extern Function_Descriptor opacity_descriptor;
Node alpha(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor opacify_descriptor;
extern Function_Descriptor fade_in_descriptor;
Node opacify(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor transparentize_descriptor;
extern Function_Descriptor fade_out_descriptor;
Node transparentize(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// String Functions ////////////////////////////////////////////////////
extern Function_Descriptor unquote_descriptor;
Node unquote(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor quote_descriptor;
Node quote(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Number Functions ////////////////////////////////////////////////////
extern Function_Descriptor percentage_descriptor;
......@@ -117,42 +117,43 @@ namespace Sass {
extern Function_Descriptor floor_descriptor;
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, Node_Factory& new_Node);
// List Functions //////////////////////////////////////////////////////
extern Function_Descriptor length_descriptor;
Node length(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor nth_descriptor;
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, 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, Node_Factory& new_Node);
// Introspection Functions /////////////////////////////////////////////
extern Function_Descriptor type_of_descriptor;
Node type_of(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor unit_descriptor;
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, Node_Factory& new_Node);
extern Function_Descriptor comparable_descriptor;
extern Function_Descriptor comparable_descriptor;
Node comparable(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Boolean Functions ///////////////////////////////////////////////////
extern Function_Descriptor not_descriptor;
Node not_impl(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
}
}
......@@ -51,7 +51,7 @@ namespace Sass {
}
return true;
} break;
case variable:
case identifier:
case uri:
......@@ -62,12 +62,12 @@ namespace Sass {
case string_constant: {
return token().unquote() == rhs.token().unquote();
} break;
case number:
case numeric_percentage: {
return numeric_value() == rhs.numeric_value();
} break;
case numeric_dimension: {
if (unit() == rhs.unit()) {
return numeric_value() == rhs.numeric_value();
......@@ -76,26 +76,26 @@ namespace Sass {
return false;
}
} break;
case boolean: {
return boolean_value() == rhs.boolean_value();
} break;
default: {
return true;
} break;
}
return false;
}
bool Node::operator!=(Node rhs) const
{ return !(*this == rhs); }
bool Node::operator<(Node rhs) const
{
Type lhs_type = type();
Type rhs_type = rhs.type();
// comparing atomic numbers
if ((lhs_type == number && rhs_type == number) ||
(lhs_type == numeric_percentage && rhs_type == numeric_percentage)) {
......@@ -158,13 +158,13 @@ namespace Sass {
throw Error(Error::evaluation, path(), line(), "incomparable types");
}
}
bool Node::operator<=(Node rhs) const
{ return *this < rhs || *this == rhs; }
bool Node::operator>(Node rhs) const
{ return !(*this <= rhs); }
bool Node::operator>=(Node rhs) const
{ return !(*this < rhs); }
......@@ -172,7 +172,7 @@ namespace Sass {
// ------------------------------------------------------------------------
// Token method implementations
// ------------------------------------------------------------------------
string Token::unquote() const
{
string result;
......@@ -210,7 +210,7 @@ namespace Sass {
return result;
}
}
void Token::unquote_to_stream(std::stringstream& buf) const
{
const char* p = begin;
......@@ -247,7 +247,7 @@ namespace Sass {
return;
}
}
bool Token::operator<(const Token& rhs) const
{
const char* first1 = begin;
......@@ -262,15 +262,15 @@ namespace Sass {
}
return (first2 != last2);
}
bool Token::operator==(const Token& rhs) const
{
if (length() != rhs.length()) return false;
if ((begin[0] == '"' || begin[0] == '\'') &&
(rhs.begin[0] == '"' || rhs.begin[0] == '\''))
{ return unquote() == rhs.unquote(); }
const char* p = begin;
const char* q = rhs.begin;
for (; p < end; ++p, ++q) if (*p != *q) return false;
......@@ -298,7 +298,7 @@ namespace Sass {
// if you reach this point, you've got a logic error somewhere
return 0;
}
extern const char percent_str[] = "%";
extern const char empty_str[] = "";
Token Node_Impl::unit()
......@@ -308,14 +308,15 @@ namespace Sass {
case Node::numeric_percentage: {
return Token::make(percent_str);
} break;
case Node::numeric_dimension: {
return value.dimension.unit;
} break;
default: break;
}
return Token::make(empty_str);
}
}
\ No newline at end of file
}
......@@ -46,7 +46,7 @@ namespace Sass {
string unquote() const;
void unquote_to_stream(std::stringstream& buf) const;
operator bool()
{ return begin && end && begin >= end; }
......@@ -58,7 +58,7 @@ namespace Sass {
double numeric;
Token unit;
};
struct Node_Impl;
class Node {
......@@ -199,7 +199,7 @@ namespace Sass {
bool is_null_ptr() const;
void flatten();
bool operator==(Node rhs) const;
bool operator!=(Node rhs) const;
bool operator<(Node rhs) const;
......@@ -214,7 +214,7 @@ namespace Sass {
void emit_expanded_css(stringstream& buf, const string& prefix);
};
struct Node_Impl {
union value_t {
bool boolean;
......@@ -255,13 +255,13 @@ namespace Sass {
should_eval(false),
is_unquoted(false)
{ }
bool is_numeric()
{ return type >= Node::number && type <= Node::numeric_dimension; }
size_t size()
{ return children.size(); }
bool empty()
{ return children.empty(); }
......@@ -321,7 +321,7 @@ namespace Sass {
bool& boolean_value()
{ return value.boolean; }
double numeric_value();
Token unit();
};
......@@ -332,11 +332,11 @@ namespace Sass {
// -- in the header file so they can easily be declared inline
// -- outside of their class definition to get the right declaration order
// ------------------------------------------------------------------------
inline Node::Node(Node_Impl* ip) : ip_(ip) { }
inline Node::Type Node::type() const { return ip_->type; }
inline bool Node::has_children() const { return ip_->has_children; }
inline bool Node::has_statements() const { return ip_->has_statements; }
inline bool Node::has_blocks() const { return ip_->has_blocks; }
......@@ -346,12 +346,12 @@ namespace Sass {
inline bool& Node::should_eval() const { return ip_->should_eval; }
inline bool& Node::is_unquoted() const { return ip_->is_unquoted; }
inline bool Node::is_numeric() const { return ip_->is_numeric(); }
inline string& Node::path() const { return ip_->path; }
inline size_t Node::line() const { return ip_->line; }
inline size_t Node::size() const { return ip_->size(); }
inline bool Node::empty() const { return ip_->empty(); }
inline Node& Node::at(size_t i) const { return ip_->at(i); }
inline Node& Node::back() const { return ip_->back(); }
inline Node& Node::operator[](size_t i) const { return at(i); }
......@@ -390,3 +390,4 @@ namespace Sass {
inline bool Node::is_null_ptr() const { return !ip_; }
}
......@@ -27,10 +27,10 @@ namespace Sass {
}
return result;
} break;
case selector: {
string result;
result += at(0).to_string();
for (size_t i = 1, S = size(); i < S; ++i) {
result += " ";
......@@ -38,11 +38,11 @@ namespace Sass {
}
return result;
} break;
case selector_combinator: {
return token().to_string();
} break;
case simple_selector_sequence: {
string result;
for (size_t i = 0, S = size(); i < S; ++i) {
......@@ -50,12 +50,12 @@ namespace Sass {
}
return result;
} break;
case pseudo:
case simple_selector: {
return token().to_string();
} break;
case pseudo_negation: {
string result;
result += at(0).to_string();
......@@ -63,7 +63,7 @@ namespace Sass {
result += ')';
return result;
} break;
case functional_pseudo: {
string result;
result += at(0).to_string();
......@@ -73,7 +73,7 @@ namespace Sass {
result += ')';
return result;
} break;
case attribute_selector: {
string result;
result += "[";
......@@ -93,7 +93,7 @@ namespace Sass {
}
return result;
} break;
case space_list: {
string result(at(0).to_string());
for (size_t i = 1, S = size(); i < S; ++i) {
......@@ -103,7 +103,7 @@ namespace Sass {
}
return result;
} break;
case expression:
case term: {
string result(at(0).to_string());
......@@ -116,16 +116,16 @@ namespace Sass {
}
return result;
} break;
//edge case
case sub: {
return "-";
} break;
case div: {
return "/";
} break;
case css_import: {
stringstream ss;
ss << "@import url(";
......@@ -134,7 +134,7 @@ namespace Sass {
ss << ")";
return ss.str();
}
case function_call: {
stringstream ss;
ss << at(0).to_string();
......@@ -143,7 +143,7 @@ namespace Sass {
ss << ")";
return ss.str();
}
case arguments: {
stringstream ss;
size_t S = size();
......@@ -156,40 +156,40 @@ namespace Sass {
}
return ss.str();
}
case unary_plus: {
stringstream ss;
ss << "+";
ss << at(0).to_string();
return ss.str();
}
case unary_minus: {
stringstream ss;
ss << "-";
ss << at(0).to_string();
return ss.str();
}
case numeric_percentage: {
stringstream ss;
ss << numeric_value();
ss << '%';
return ss.str();
}
case numeric_dimension: {
stringstream ss;
ss << numeric_value() << unit().to_string();
return ss.str();
} break;
case number: {
stringstream ss;
ss << numeric_value();
return ss.str();
} break;
case numeric_color: {
if (at(3).numeric_value() >= 1.0)
{
......@@ -201,7 +201,7 @@ namespace Sass {
else if (a >= 0xff && b >= 0xff && c == 0)
{ return "yellow"; }
else if (a == 0 && b >= 0xff && c >= 0xff)
{ return "aqua"; }
{ return "aqua"; }
else if (a >= 0xff && b == 0 && c >= 0xff)
{ return "fuchsia"; }
else if (a >= 0xff && b == 0 && c == 0)
......@@ -236,7 +236,7 @@ namespace Sass {
return ss.str();
}
} break;
case uri: {
string result("url(");
result += token().to_string();
......@@ -248,7 +248,7 @@ namespace Sass {
// ignore it
return "";
} break;
case string_constant: {
if (is_unquoted()) return token().unquote();
else {
......@@ -257,22 +257,22 @@ namespace Sass {
else return result;
}
} break;
case boolean: {
if (boolean_value()) return "true";
else return "false";
} break;
case important: {
return "!important";
} break;
case value_schema: {
string result;
for (size_t i = 0, S = size(); i < S; ++i) result += at(i).to_string();
return result;
} break;
case string_schema: {
string result;
for (size_t i = 0, S = size(); i < S; ++i) {
......@@ -286,7 +286,7 @@ namespace Sass {
}
return result;
} break;
default: {
// return content.token.to_string();
if (!has_children()) return token().to_string();
......@@ -338,14 +338,14 @@ namespace Sass {
case propset: {
emit_propset(buf, depth, "");
} break;
case rule: {
buf << endl << string(2*depth, ' ');
at(0).emit_nested_css(buf, depth); // property
at(1).emit_nested_css(buf, depth); // values
buf << ";";
} break;
case css_import: {
buf << string(2*depth, ' ');
buf << to_string();
......@@ -373,7 +373,7 @@ namespace Sass {
} break;
}
}
void Node::emit_propset(stringstream& buf, size_t depth, const string& prefix)
{
string new_prefix(prefix);
......@@ -405,4 +405,5 @@ namespace Sass {
void Node::echo(stringstream& buf, size_t depth) { }
void Node::emit_expanded_css(stringstream& buf, const string& prefix) { }
}
\ No newline at end of file
}
#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();
......@@ -69,7 +69,7 @@ namespace Sass {
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)
{
......@@ -84,4 +84,5 @@ namespace Sass {
void Node_Factory::free()
{ for (size_t i = 0, S = pool_.size(); i < S; ++i) delete pool_[i]; }
}
\ No newline at end of file
}
......@@ -9,7 +9,7 @@ namespace Sass {
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);
......@@ -33,5 +33,6 @@ namespace Sass {
void free();
};
}
\ No newline at end of file
}
......@@ -3,7 +3,7 @@
namespace Sass {
namespace Prelexer {
// Matches zero characters (always succeeds without consuming input).
const char* epsilon(char *src) {
return src;
......@@ -12,10 +12,10 @@ namespace Sass {
const char* empty(char *src) {
return *src ? 0 : src;
}
// Match any single character.
const char* any_char(const char* src) { return *src ? src++ : src; }
// Match a single character satisfying the ctype predicates.
const char* space(const char* src) { return std::isspace(*src) ? src+1 : 0; }
const char* alpha(const char* src) { return std::isalpha(*src) ? src+1 : 0; }
......@@ -30,7 +30,7 @@ namespace Sass {
const char* xdigits(const char* src) { return one_plus<xdigit>(src); }
const char* alnums(const char* src) { return one_plus<alnum>(src); }
const char* puncts(const char* src) { return one_plus<punct>(src); }
// Match a line comment.
extern const char slash_slash[] = "//";
const char* line_comment(const char* src) { return to_endl<slash_slash>(src); }
......@@ -60,7 +60,7 @@ namespace Sass {
const char* interpolant(const char* src) {
return delimited_by<hash_lbrace, rbrace, false>(src);
}
// Whitespace handling.
const char* optional_spaces(const char* src) { return optional<spaces>(src); }
const char* optional_comment(const char* src) { return optional<comment>(src); }
......@@ -70,7 +70,7 @@ namespace Sass {
const char* no_spaces(const char* src) {
return negate< spaces >(src);
}
// Match CSS identifiers.
const char* identifier(const char* src) {
return sequence< optional< exactly<'-'> >,
......@@ -79,8 +79,8 @@ namespace Sass {
exactly<'-'>,
exactly<'_'> > > >(src);
}
// Match interpolant schemas
const char* identifier_schema(const char* src) {
// follows this pattern: (x*ix*)+
......@@ -94,7 +94,7 @@ namespace Sass {
interpolant,
zero_plus< alternatives< identifier, percentage, dimension, hex, number, string_constant > > > >(src);
}
// Match CSS '@' keywords.
const char* at_keyword(const char* src) {
return sequence<exactly<'@'>, identifier>(src);
......@@ -156,7 +156,7 @@ namespace Sass {
const char* while_directive(const char* src) {
return exactly<while_kwd>(src);
}
const char* name(const char* src) {
return one_plus< alternatives< alnum,
exactly<'-'>,
......@@ -305,12 +305,12 @@ namespace Sass {
const char* ancestor_of(const char* src) {
return sequence< spaces, negate< exactly<'{'> > >(src);
}
// Match SCSS variable names.
const char* variable(const char* src) {
return sequence<exactly<'$'>, name>(src);
}
// Match Sass boolean keywords.
extern const char and_chars[] = "and";
extern const char or_chars[] = "or";
......@@ -357,7 +357,7 @@ namespace Sass {
const char* lte_op(const char* src) {
return exactly<lte_chars>(src);
}
// Path matching functions.
const char* folder(const char* src) {
return sequence< zero_plus< any_char_except<'/'> >,
......@@ -367,4 +367,5 @@ namespace Sass {
return zero_plus< folder >(src);
}
}
}
\ No newline at end of file
}
......@@ -11,7 +11,7 @@ namespace Sass {
const char* exactly(const char* src) {
return *src == pre ? src + 1 : 0;
}
// Match a string constant.
template <const char* prefix>
const char* exactly(const char* src) {
......@@ -49,7 +49,7 @@ namespace Sass {
while (class_char<char_class>(p)) ++p;
return p == src ? 0 : p;
}
// Match a sequence of characters up to the next newline.
template <const char* prefix>
const char* to_endl(const char* src) {
......@@ -57,7 +57,7 @@ namespace Sass {
while (*src && *src != '\n') ++src;
return src;
}
// Match a sequence of characters delimited by the supplied chars.
template <char beg, char end, bool esc>
const char* delimited_by(const char* src) {
......@@ -71,7 +71,7 @@ namespace Sass {
src = stop ? stop : src + 1;
}
}
// Match a sequence of characters delimited by the supplied strings.
template <const char* beg, const char* end, bool esc>
const char* delimited_by(const char* src) {
......@@ -85,7 +85,7 @@ namespace Sass {
src = stop ? stop : src + 1;
}
}
// Match any single character.
const char* any_char(const char* src);
// Match any single character except the supplied one.
......@@ -93,19 +93,19 @@ namespace Sass {
const char* any_char_except(const char* src) {
return (*src && *src != c) ? src+1 : 0;
}
// Matches zero characters (always succeeds without consuming input).
const char* epsilon(const char*);
// Matches the empty string.
const char* empty(const char*);
// Succeeds of the supplied matcher fails, and vice versa.
template <prelexer mx>
const char* negate(const char* src) {
return mx(src) ? 0 : src;
}
// Tries the matchers in sequence and returns the first match (or none)
template <prelexer mx1, prelexer mx2>
const char* alternatives(const char* src) {
......@@ -113,7 +113,7 @@ namespace Sass {
(rslt = mx1(src)) || (rslt = mx2(src));
return rslt;
}
// Same as above, but with 3 arguments.
template <prelexer mx1, prelexer mx2, prelexer mx3>
const char* alternatives(const char* src) {
......@@ -121,7 +121,7 @@ namespace Sass {
(rslt = mx1(src)) || (rslt = mx2(src)) || (rslt = mx3(src));
return rslt;
}
// Same as above, but with 4 arguments.
template <prelexer mx1, prelexer mx2, prelexer mx3, prelexer mx4>
const char* alternatives(const char* src) {
......@@ -130,7 +130,7 @@ namespace Sass {
(rslt = mx3(src)) || (rslt = mx4(src));
return rslt;
}
// Same as above, but with 5 arguments.
template <prelexer mx1, prelexer mx2, prelexer mx3,
prelexer mx4, prelexer mx5>
......@@ -140,7 +140,7 @@ namespace Sass {
(rslt = mx4(src)) || (rslt = mx5(src));
return rslt;
}
// Same as above, but with 6 arguments.
template <prelexer mx1, prelexer mx2, prelexer mx3,
prelexer mx4, prelexer mx5, prelexer mx6>
......@@ -150,7 +150,7 @@ namespace Sass {
(rslt = mx4(src)) || (rslt = mx5(src)) || (rslt = mx6(src));
return rslt;
}
// Same as above, but with 7 arguments.
template <prelexer mx1, prelexer mx2,
prelexer mx3, prelexer mx4,
......@@ -164,7 +164,7 @@ namespace Sass {
(rslt = mx7(rslt));
return rslt;
}
// Same as above, but with 8 arguments.
template <prelexer mx1, prelexer mx2,
prelexer mx3, prelexer mx4,
......@@ -178,7 +178,7 @@ namespace Sass {
(rslt = mx7(rslt)) || (rslt = mx8(rslt));
return rslt;
}
// Tries the matchers in sequence and succeeds if they all succeed.
template <prelexer mx1, prelexer mx2>
const char* sequence(const char* src) {
......@@ -186,7 +186,7 @@ namespace Sass {
(rslt = mx1(rslt)) && (rslt = mx2(rslt));
return rslt;
}
// Same as above, but with 3 arguments.
template <prelexer mx1, prelexer mx2, prelexer mx3>
const char* sequence(const char* src) {
......@@ -194,7 +194,7 @@ namespace Sass {
(rslt = mx1(rslt)) && (rslt = mx2(rslt)) && (rslt = mx3(rslt));
return rslt;
}
// Same as above, but with 4 arguments.
template <prelexer mx1, prelexer mx2, prelexer mx3, prelexer mx4>
const char* sequence(const char* src) {
......@@ -203,7 +203,7 @@ namespace Sass {
(rslt = mx3(rslt)) && (rslt = mx4(rslt));
return rslt;
}
// Same as above, but with 5 arguments.
template <prelexer mx1, prelexer mx2,
prelexer mx3, prelexer mx4,
......@@ -215,7 +215,7 @@ namespace Sass {
(rslt = mx5(rslt));
return rslt;
}
// Same as above, but with 6 arguments.
template <prelexer mx1, prelexer mx2,
prelexer mx3, prelexer mx4,
......@@ -227,7 +227,7 @@ namespace Sass {
(rslt = mx5(rslt)) && (rslt = mx6(rslt));
return rslt;
}
// Same as above, but with 7 arguments.
template <prelexer mx1, prelexer mx2,
prelexer mx3, prelexer mx4,
......@@ -241,14 +241,14 @@ namespace Sass {
(rslt = mx7(rslt));
return rslt;
}
// Match a pattern or not. Always succeeds.
template <prelexer mx>
const char* optional(const char* src) {
const char* p = mx(src);
return p ? p : src;
}
// Match zero or more of the supplied pattern
template <prelexer mx>
const char* zero_plus(const char* src) {
......@@ -256,7 +256,7 @@ namespace Sass {
while (p) src = p, p = mx(src);
return src;
}
// Match one or more of the supplied pattern
template <prelexer mx>
const char* one_plus(const char* src) {
......@@ -265,7 +265,7 @@ namespace Sass {
while (p) src = p, p = mx(src);
return src;
}
// Match a single character satisfying the ctype predicates.
const char* space(const char* src);
const char* alpha(const char* src);
......@@ -280,7 +280,7 @@ namespace Sass {
const char* xdigits(const char* src);
const char* alnums(const char* src);
const char* puncts(const char* src);
// Match a line comment.
const char* line_comment(const char* src);
// Match a block comment.
......@@ -368,10 +368,10 @@ namespace Sass {
const char* precedes(const char* src);
const char* parent_of(const char* src);
const char* ancestor_of(const char* src);
// Match SCSS variable names.
const char* variable(const char* src);
// Match Sass boolean keywords.
const char* true_kwd(const char* src);
const char* false_kwd(const char* src);
......@@ -384,11 +384,11 @@ namespace Sass {
const char* gte_op(const char* src);
const char* lt_op(const char* src);
const char* lte_op(const char* src);
// Path matching functions.
const char* folder(const char* src);
const char* folders(const char* src);
// Utility functions for finding and counting characters in a string.
template<char c>
const char* find_first(const char* src) {
......@@ -433,6 +433,7 @@ namespace Sass {
}
return counter;
}
}
}
......@@ -14,9 +14,9 @@ extern "C" {
sass_context* sass_new_context()
{ return (sass_context*) calloc(1, sizeof(sass_context)); }
void sass_free_context(sass_context* ctx)
{
{
if (ctx->output_string)
free(ctx->output_string);
free(ctx);
......@@ -24,14 +24,14 @@ extern "C" {
sass_file_context* sass_new_file_context()
{ return (sass_file_context*) calloc(1, sizeof(sass_file_context)); }
void sass_free_file_context(sass_file_context* ctx)
{
{
if (ctx->output_string)
free(ctx->output_string);
free(ctx);
}
sass_folder_context* sass_new_folder_context()
{ return (sass_folder_context*) calloc(1, sizeof(sass_folder_context)); }
......@@ -86,7 +86,7 @@ extern "C" {
// TO DO: CATCH EVERYTHING ELSE
return 0;
}
int sass_compile_file(sass_file_context* c_ctx)
{
using namespace Sass;
......@@ -123,10 +123,11 @@ extern "C" {
// TO DO: CATCH EVERYTHING ELSE
return 0;
}
int sass_compile_folder(sass_folder_context* c_ctx)
{
return 1;
}
}
#include <node.h>
#ifdef __cplusplus
extern "C" {
#endif
......@@ -18,6 +20,8 @@ struct sass_context {
struct sass_options options;
int error_status;
char* error_message;
uv_work_t request;
v8::Persistent<v8::Function> callback;
};
struct sass_file_context {
......@@ -50,4 +54,5 @@ int sass_compile_folder (struct sass_folder_context* ctx);
#ifdef __cplusplus
}
#endif
\ No newline at end of file
#endif
......@@ -14,36 +14,36 @@ 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;
......@@ -92,4 +92,5 @@ int main()
new_Node.free();
return 0;
}
\ No newline at end of file
}
var binding = require('./build/Release/binding')
var render = function(str, cb){
cb(binding.render(str))
}
exports.render = render
exports.middleware = require('./lib/middleware');
\ No newline at end of file
exports.render = binding.render
exports.middleware = require('./lib/middleware');
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