Commit 25186694 by Andrew Nesbitt

Updated libsass

parent 9e72e9c3
...@@ -10,7 +10,7 @@ Handle<Value> Render(const Arguments& args) { ...@@ -10,7 +10,7 @@ Handle<Value> Render(const Arguments& args) {
String::AsciiValue astr(args[0]); String::AsciiValue astr(args[0]);
char * cs = *astr; char * cs = *astr;
ctx->input_string = cs; ctx->source_string = cs;
ctx->options.include_paths = 0; ctx->options.include_paths = 0;
ctx->options.output_style = SASS_STYLE_NESTED; ctx->options.output_style = SASS_STYLE_NESTED;
......
CC=g++
CFLAGS=-c -Wall -O2
LDFLAGS=
SOURCES = \
context.cpp functions.cpp document.cpp \
document_parser.cpp eval_apply.cpp node.cpp \
node_factory.cpp node_emitters.cpp prelexer.cpp \
sass_interface.cpp
OBJECTS = $(SOURCES:.cpp=.o)
CPP_FILES = \ all: $(OBJECTS)
context.cpp \ ar rvs libsass.a $(OBJECTS)
functions.cpp \
document.cpp \
document_parser.cpp \
eval_apply.cpp \
node.cpp \
node_comparisons.cpp \
values.cpp \
prelexer.cpp
libsass: libsass_objs .cpp.o:
ar rvs libsass.a \ $(CC) $(CFLAGS) $< -o $@
sass_interface.o \
context.o \
functions.o \
document.o \
document_parser.o \
eval_apply.o \
node.o \
node_comparisons.o \
values.o \
prelexer.o
libsass_objs: sass_interface.cpp $(CPP_FILES)
g++ -O2 -Wall -c -combine sass_interface.cpp $(CPP_FILES)
clean: clean:
rm -rf *.o *.a rm -rf *.o *.a
\ No newline at end of file
...@@ -3,6 +3,8 @@ Libsass ...@@ -3,6 +3,8 @@ Libsass
by Aaron Leung and Hampton Catlin (@hcatlin) by Aaron Leung and Hampton Catlin (@hcatlin)
[![Build Status](https://secure.travis-ci.org/hcatlin/sassc.png?branch=master)](http://travis-ci.org/hcatlin/sassc)
http://github.com/hcatlin/libsass http://github.com/hcatlin/libsass
Libsass is just a library, but if you want to RUN libsass, Libsass is just a library, but if you want to RUN libsass,
...@@ -17,6 +19,20 @@ Libsass is a C/C++ port of the Sass CSS precompiler. The original version was wr ...@@ -17,6 +19,20 @@ Libsass is a C/C++ port of the Sass CSS precompiler. The original version was wr
This library strives to be light, simple, and easy to build and integrate with a variety of platforms and languages. This library strives to be light, simple, and easy to build and integrate with a variety of platforms and languages.
Developing
----------
As you may have noticed, the libsass repo itself has
no executables and no tests. Oh noes! How can you develop???
Well, luckily, SassC is the official binary wrapper for
libsass and is *always* kept in sync. SassC uses a git submodule
to include libsass. When developing libsass, its best to actually
check out SassC and develop in that directory with the SassC spec
and tests there.
We even run Travis tests for SassC!
Usage Usage
----- -----
...@@ -28,9 +44,9 @@ First, you create a sass context struct. We use these objects to define ...@@ -28,9 +44,9 @@ First, you create a sass context struct. We use these objects to define
different execution parameters for the library. There are three different execution parameters for the library. There are three
different context types. different context types.
sass_context //string-in-string-out compilation sass_context // string-in-string-out compilation
sass_file_context //file-based compilation sass_file_context // file-based compilation
sass_folder_context //full-folder multi-file sass_folder_context // full-folder multi-file
Each of the context's have slightly different behavior and are Each of the context's have slightly different behavior and are
implemented seperately. This does add extra work to implementing implemented seperately. This does add extra work to implementing
......
#include "context.hpp" #include "context.hpp"
#include <iostream> #include <iostream>
#include <unistd.h>
#include "prelexer.hpp"
using std::cerr; using std::endl; using std::cerr; using std::endl;
namespace Sass { namespace Sass {
...@@ -41,10 +43,13 @@ namespace Sass { ...@@ -41,10 +43,13 @@ namespace Sass {
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>()),
extensions(multimap<Node, Node>()),
pending_extensions(vector<pair<Node, Node> >()),
source_refs(vector<char*>()), source_refs(vector<char*>()),
registry(vector<vector<Node>*>()),
include_paths(vector<string>()), include_paths(vector<string>()),
ref_count(0) new_Node(Node_Factory()),
ref_count(0),
has_extensions(false)
{ {
register_functions(); register_functions();
collect_include_paths(paths_str); collect_include_paths(paths_str);
...@@ -55,6 +60,8 @@ namespace Sass { ...@@ -55,6 +60,8 @@ namespace Sass {
for (size_t i = 0; i < source_refs.size(); ++i) { for (size_t i = 0; i < source_refs.size(); ++i) {
delete[] source_refs[i]; delete[] source_refs[i];
} }
new_Node.free();
// cerr << "Deallocated " << i << " source string(s)." << endl; // cerr << "Deallocated " << i << " source string(s)." << endl;
} }
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <utility> #include <utility>
#include <map> #include <map>
#include "node_factory.hpp"
#include "functions.hpp" #include "functions.hpp"
namespace Sass { namespace Sass {
...@@ -42,12 +43,15 @@ namespace Sass { ...@@ -42,12 +43,15 @@ namespace Sass {
struct Context { struct Context {
Environment global_env; Environment global_env;
map<pair<string, size_t>, Function> function_env; map<pair<string, size_t>, Function> function_env;
multimap<Node, Node> extensions;
vector<pair<Node, Node> > pending_extensions;
vector<char*> source_refs; // all the source c-strings vector<char*> source_refs; // all the source c-strings
vector<vector<Node>*> registry; // all the child vectors
vector<string> include_paths; vector<string> include_paths;
Node_Factory new_Node;
size_t ref_count; size_t ref_count;
string sass_path; string sass_path;
string css_path; string css_path;
bool has_extensions;
void collect_include_paths(const char* paths_str); void collect_include_paths(const char* paths_str);
Context(const char* paths_str = 0); Context(const char* paths_str = 0);
......
...@@ -4,124 +4,98 @@ ...@@ -4,124 +4,98 @@
#include "eval_apply.hpp" #include "eval_apply.hpp"
#include "error.hpp" #include "error.hpp"
#include <iostream> #include <iostream>
#include <sstream>
namespace Sass { namespace Sass {
Document::Document(char* path_str, char* source_str, Context& ctx) Document::Document(Context& ctx) : context(ctx)
: path(string()), { ++context.ref_count; }
source(source_str),
line_number(1),
context(ctx),
root(Node(Node::root, context.registry, 1)),
lexed(Token::make())
{
if (source_str) {
own_source = false;
position = source;
end = position + std::strlen(source);
}
else if (path_str) {
path = string(path_str);
std::FILE *f;
// TO DO: CHECK f AGAINST NULL/0
f = std::fopen(path.c_str(), "rb");
std::fseek(f, 0, SEEK_END);
int len = std::ftell(f);
std::rewind(f);
// TO DO: WRAP THE new[] IN A TRY/CATCH BLOCK
source = new char[len + 1];
std::fread(source, sizeof(char), len, f);
source[len] = '\0';
end = source + len;
std::fclose(f);
own_source = true;
position = source;
context.source_refs.push_back(source);
}
else {
// report an error
}
++context.ref_count;
}
Document::Document(const Document& doc)
: path(doc.path),
source(doc.source),
position(doc.position),
end(doc.end),
line(doc.line),
own_source(doc.own_source),
context(doc.context),
root(doc.root),
lexed(doc.lexed)
{ ++doc.context.ref_count; }
Document::Document(string path, char* source) Document::~Document()
: path(path), source(source), { --context.ref_count; }
line_number(1), own_source(false),
context(*(new Context())), Document Document::make_from_file(Context& ctx, string path)
root(Node(Node::root, context.registry, 1)),
lexed(Token::make())
{ {
if (!source) {
std::FILE *f; std::FILE *f;
f = std::fopen(path.c_str(), "rb"); f = std::fopen(path.c_str(), "rb");
if (!f) throw path; if (!f) throw path;
if (std::fseek(f, 0, SEEK_END)) throw path; if (std::fseek(f, 0, SEEK_END)) throw path;
int len = std::ftell(f); int status = std::ftell(f);
if (len < 0) throw path; if (status < 0) throw path;
size_t len = status;
std::rewind(f); std::rewind(f);
// TO DO: CATCH THE POTENTIAL badalloc EXCEPTION char* source = new char[len + 1];
source = new char[len + 1]; size_t bytes_read = std::fread(source, sizeof(char), len, f);
std::fread(source, sizeof(char), len, f); if (bytes_read != len) {
std::cerr << "Warning: possible error reading from " << path << std::endl;
}
if (std::ferror(f)) throw path; if (std::ferror(f)) throw path;
source[len] = '\0'; source[len] = '\0';
end = source + len; char* end = source + len;
if (std::fclose(f)) throw path; if (std::fclose(f)) throw path;
own_source = true;
} Document doc(ctx);
position = source; doc.path = path;
context.source_refs.push_back(source); doc.line = 1;
++context.ref_count; doc.root = ctx.new_Node(Node::root, path, 1, 0);
doc.lexed = Token::make();
doc.own_source = true;
doc.source = source;
doc.end = end;
doc.position = source;
doc.context.source_refs.push_back(source);
return doc;
} }
Document::Document(string path, Context& context) Document Document::make_from_source_chars(Context& ctx, char* src, string path, bool own_source)
: path(path), source(0),
line_number(1), own_source(false),
context(context),
root(Node(Node::root, context.registry, 1)),
lexed(Token::make())
{ {
std::FILE *f; Document doc(ctx);
f = std::fopen(path.c_str(), "rb"); doc.path = path;
if (!f) throw path; doc.line = 1;
if (std::fseek(f, 0, SEEK_END)) throw path; doc.root = ctx.new_Node(Node::root, path, 1, 0);
int len = std::ftell(f); doc.lexed = Token::make();
if (len < 0) throw path; doc.own_source = own_source;
std::rewind(f); doc.source = src;
// TO DO: CATCH THE POTENTIAL badalloc EXCEPTION doc.end = src + std::strlen(src);
source = new char[len + 1]; doc.position = src;
std::fread(source, sizeof(char), len, f); if (own_source) doc.context.source_refs.push_back(src);
if (std::ferror(f)) throw path;
source[len] = '\0'; return doc;
end = source + len;
if (std::fclose(f)) throw path;
position = source;
context.source_refs.push_back(source);
++context.ref_count;
} }
Document::Document(const string& path, size_t line_number, Token t, Context& context) Document Document::make_from_token(Context& ctx, Token t, string path, size_t line_number)
: path(path), {
source(const_cast<char*>(t.begin)), Document doc(ctx);
position(t.begin), doc.path = path;
end(t.end), doc.line = line_number;
line_number(line_number), doc.root = ctx.new_Node(Node::root, path, 1, 0);
own_source(false), doc.lexed = Token::make();
context(context), doc.own_source = false;
root(Node(Node::root, context.registry, 1)), doc.source = const_cast<char*>(t.begin);
lexed(Token::make()) doc.end = t.end;
{ } doc.position = doc.source;
Document::~Document() { return doc;
--context.ref_count;
// if (context.ref_count == 0) delete &context;
} }
void Document::syntax_error(string message, size_t ln) void Document::throw_syntax_error(string message, size_t ln)
{ throw Error(Error::syntax, ln ? ln : line_number, path, message); } { throw Error(Error::syntax, path, ln ? ln : line, message); }
void Document::read_error(string message, size_t ln) void Document::throw_read_error(string message, size_t ln)
{ throw Error(Error::read, ln ? ln : line_number, path, message); } { throw Error(Error::read, path, ln ? ln : line, message); }
using std::string; using std::string;
using std::stringstream; using std::stringstream;
...@@ -134,7 +108,7 @@ namespace Sass { ...@@ -134,7 +108,7 @@ namespace Sass {
root.echo(output); root.echo(output);
break; break;
case nested: case nested:
root.emit_nested_css(output, 0, vector<string>()); root.emit_nested_css(output, 0, true);
break; break;
case expanded: case expanded:
root.emit_expanded_css(output, ""); root.emit_expanded_css(output, "");
......
#include <map> #include <map>
#ifndef SASS_PRELEXER_INCLUDED
#include "prelexer.hpp"
#endif
#ifndef SASS_NODE_INCLUDED #ifndef SASS_NODE_INCLUDED
#include "node.hpp" #include "node.hpp"
#endif #endif
#ifndef SASS_CONTEXT_INCLUDED
#include "context.hpp" #include "context.hpp"
#endif
struct Selector_Lookahead {
const char* found;
bool has_interpolants;
};
namespace Sass { namespace Sass {
using std::string; using std::string;
...@@ -19,7 +30,7 @@ namespace Sass { ...@@ -19,7 +30,7 @@ namespace Sass {
char* source; char* source;
const char* position; const char* position;
const char* end; const char* end;
size_t line_number; size_t line;
bool own_source; bool own_source;
Context& context; Context& context;
...@@ -27,12 +38,17 @@ namespace Sass { ...@@ -27,12 +38,17 @@ namespace Sass {
Node root; Node root;
Token lexed; Token lexed;
Document(char* path_str, char* source_str, Context& ctx); private:
Document(string path, char* source = 0); // force the use of the "make_from_..." factory funtions
Document(string path, Context& context); Document(Context& ctx);
Document(const string& path, size_t line_number, Token t, Context& context); public:
Document(const Document& doc);
~Document(); ~Document();
static Document make_from_file(Context& ctx, string path);
static Document make_from_source_chars(Context& ctx, char* src, string path = "", bool own_source = false);
static Document make_from_token(Context& ctx, Token t, string path = "", size_t line_number = 1);
template <prelexer mx> template <prelexer mx>
const char* peek(const char* start = 0) const char* peek(const char* start = 0)
{ {
...@@ -83,7 +99,7 @@ namespace Sass { ...@@ -83,7 +99,7 @@ namespace Sass {
else if (mx == spaces) { else if (mx == spaces) {
after_whitespace = spaces(position); after_whitespace = spaces(position);
if (after_whitespace) { if (after_whitespace) {
line_number += count_interval<'\n'>(position, after_whitespace); line += count_interval<'\n'>(position, after_whitespace);
lexed = Token::make(position, after_whitespace); lexed = Token::make(position, after_whitespace);
return position = after_whitespace; return position = after_whitespace;
} }
...@@ -99,7 +115,7 @@ namespace Sass { ...@@ -99,7 +115,7 @@ namespace Sass {
} }
const char* after_token = mx(after_whitespace); const char* after_token = mx(after_whitespace);
if (after_token) { if (after_token) {
line_number += count_interval<'\n'>(position, after_token); line += count_interval<'\n'>(position, after_token);
lexed = Token::make(after_whitespace, after_token); lexed = Token::make(after_whitespace, after_token);
return position = after_token; return position = after_token;
} }
...@@ -119,7 +135,8 @@ namespace Sass { ...@@ -119,7 +135,8 @@ namespace Sass {
Node parse_argument(); Node parse_argument();
Node parse_assignment(); Node parse_assignment();
Node parse_propset(); Node parse_propset();
Node parse_ruleset(bool definition = false); Node parse_ruleset(Selector_Lookahead lookahead, bool in_definition = false);
Node parse_selector_schema(const char* end_of_selector);
Node parse_selector_group(); Node parse_selector_group();
Node parse_selector(); Node parse_selector();
Node parse_selector_combinator(); Node parse_selector_combinator();
...@@ -127,7 +144,7 @@ namespace Sass { ...@@ -127,7 +144,7 @@ namespace Sass {
Node parse_simple_selector(); Node parse_simple_selector();
Node parse_pseudo(); Node parse_pseudo();
Node parse_attribute_selector(); Node parse_attribute_selector();
Node parse_block(bool definition = false); Node parse_block(Node surrounding_rulesetbool, bool in_definition = false);
Node parse_rule(); Node parse_rule();
Node parse_values(); Node parse_values();
Node parse_list(); Node parse_list();
...@@ -140,26 +157,17 @@ namespace Sass { ...@@ -140,26 +157,17 @@ namespace Sass {
Node parse_term(); Node parse_term();
Node parse_factor(); Node parse_factor();
Node parse_value(); Node parse_value();
Node parse_identifier();
Node parse_variable();
Node parse_function_call(); Node parse_function_call();
Node parse_string(); Node parse_string();
Node parse_value_schema(); Node parse_value_schema();
Node parse_if_directive(Node surrounding_ruleset);
Node parse_for_directive(Node surrounding_ruleset);
const char* lookahead_for_selector(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_selector_group(const char* start = 0); Selector_Lookahead lookahead_for_selector(const char* start = 0);
const char* look_for_selector(const char* start = 0);
const char* look_for_simple_selector_sequence(const char* start = 0);
const char* look_for_simple_selector(const char* start = 0);
const char* look_for_pseudo(const char* start = 0);
const char* look_for_attrib(const char* start = 0);
void syntax_error(string message, size_t ln = 0); void throw_syntax_error(string message, size_t ln = 0);
void read_error(string message, size_t ln = 0); void throw_read_error(string message, size_t ln = 0);
string emit_css(CSS_Style style); string emit_css(CSS_Style style);
......
...@@ -4,12 +4,12 @@ namespace Sass { ...@@ -4,12 +4,12 @@ namespace Sass {
enum Type { read, write, syntax, evaluation }; enum Type { read, write, syntax, evaluation };
Type type; Type type;
size_t line_number; string path;
string file_name; size_t line;
string message; string message;
Error(Type type, size_t line_number, string file_name, string message) Error(Type type, string path, size_t line, string message)
: type(type), line_number(line_number), file_name(file_name), message(message) : type(type), path(path), line(line), message(message)
{ } { }
}; };
......
...@@ -11,10 +11,21 @@ ...@@ -11,10 +11,21 @@
namespace Sass { namespace Sass {
using std::map; using std::map;
Node eval(Node& expr, Environment& env, map<pair<string, size_t>, Function>& f_env, vector<vector<Node>*>& registry); Node eval(Node expr, 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, vector<vector<Node>*>& registry); Node accumulate(Node::Type op, Node acc, Node rhs, Node_Factory& new_Node);
double operate(Node::Type op, double lhs, double rhs); double operate(Node::Type op, double lhs, double rhs);
Node apply_mixin(Node& mixin, const Node& args, Environment& env, map<pair<string, size_t>, Function>& f_env, vector<vector<Node>*>& registry); Node apply_mixin(Node mixin, const Node args, 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, Environment& env, map<pair<string, size_t>, Function>& f_env, vector<vector<Node>*>& registry); 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);
Node expand_backref(Node sel, Node pre);
void extend_selectors(vector<pair<Node, Node> >&, Node_Factory&);
Node generate_extension(Node extendee, Node extender, Node_Factory& new_Node);
Node selector_prefix(Node sel, Node_Factory& new_Node);
Node selector_base(Node sel);
Node selector_butfirst(Node sel, Node_Factory& new_Node);
Node selector_butlast(Node sel, Node_Factory& new_Node);
} }
\ No newline at end of file
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
namespace Sass { namespace Sass {
using std::map; using std::map;
typedef Node (*Implementation)(const vector<Token>&, map<Token, Node>&, vector<vector<Node>*>& registry); typedef Node (*Implementation)(const vector<Token>&, map<Token, Node>&, Node_Factory& new_Node);
typedef const char* str; typedef const char* str;
typedef str Function_Descriptor[]; typedef str Function_Descriptor[];
...@@ -37,8 +37,8 @@ namespace Sass { ...@@ -37,8 +37,8 @@ namespace Sass {
} }
} }
Node operator()(map<Token, Node>& bindings, vector<vector<Node>*>& registry) const Node operator()(map<Token, Node>& bindings, Node_Factory& new_Node) const
{ return implementation(parameters, bindings, registry); } { return implementation(parameters, bindings, new_Node); }
}; };
...@@ -47,111 +47,111 @@ namespace Sass { ...@@ -47,111 +47,111 @@ namespace Sass {
// RGB Functions /////////////////////////////////////////////////////// // RGB Functions ///////////////////////////////////////////////////////
extern Function_Descriptor rgb_descriptor; extern Function_Descriptor rgb_descriptor;
Node rgb(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node rgb(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor rgba_4_descriptor; extern Function_Descriptor rgba_4_descriptor;
Node rgba_4(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node rgba_4(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor rgba_2_descriptor; extern Function_Descriptor rgba_2_descriptor;
Node rgba_2(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node rgba_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor red_descriptor; extern Function_Descriptor red_descriptor;
Node red(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node red(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor green_descriptor; extern Function_Descriptor green_descriptor;
Node green(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node green(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor blue_descriptor; extern Function_Descriptor blue_descriptor;
Node blue(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node blue(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor mix_2_descriptor; extern Function_Descriptor mix_2_descriptor;
Node mix_2(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node mix_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor mix_3_descriptor; extern Function_Descriptor mix_3_descriptor;
Node mix_3(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node mix_3(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// HSL Functions /////////////////////////////////////////////////////// // HSL Functions ///////////////////////////////////////////////////////
extern Function_Descriptor hsla_descriptor; extern Function_Descriptor hsla_descriptor;
Node hsla(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node hsla(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor hsl_descriptor; extern Function_Descriptor hsl_descriptor;
Node hsl(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node hsl(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor invert_descriptor; extern Function_Descriptor invert_descriptor;
Node invert(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node invert(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Opacity Functions /////////////////////////////////////////////////// // Opacity Functions ///////////////////////////////////////////////////
extern Function_Descriptor alpha_descriptor; extern Function_Descriptor alpha_descriptor;
extern Function_Descriptor opacity_descriptor; extern Function_Descriptor opacity_descriptor;
Node alpha(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node alpha(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor opacify_descriptor; extern Function_Descriptor opacify_descriptor;
extern Function_Descriptor fade_in_descriptor; extern Function_Descriptor fade_in_descriptor;
Node opacify(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node opacify(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor transparentize_descriptor; extern Function_Descriptor transparentize_descriptor;
extern Function_Descriptor fade_out_descriptor; extern Function_Descriptor fade_out_descriptor;
Node transparentize(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node transparentize(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// String Functions //////////////////////////////////////////////////// // String Functions ////////////////////////////////////////////////////
extern Function_Descriptor unquote_descriptor; extern Function_Descriptor unquote_descriptor;
Node unquote(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node unquote(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor quote_descriptor; extern Function_Descriptor quote_descriptor;
Node quote(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node quote(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Number Functions //////////////////////////////////////////////////// // Number Functions ////////////////////////////////////////////////////
extern Function_Descriptor percentage_descriptor; extern Function_Descriptor percentage_descriptor;
Node percentage(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node percentage(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor round_descriptor; extern Function_Descriptor round_descriptor;
Node round(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node round(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor ceil_descriptor; extern Function_Descriptor ceil_descriptor;
Node ceil(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node ceil(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor floor_descriptor; extern Function_Descriptor floor_descriptor;
Node floor(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node floor(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor abs_descriptor; extern Function_Descriptor abs_descriptor;
Node abs(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node abs(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// List Functions ////////////////////////////////////////////////////// // List Functions //////////////////////////////////////////////////////
extern Function_Descriptor length_descriptor; extern Function_Descriptor length_descriptor;
Node length(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node length(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor nth_descriptor; extern Function_Descriptor nth_descriptor;
Node nth(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node nth(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor join_2_descriptor; extern Function_Descriptor join_2_descriptor;
Node join_2(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node join_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor join_3_descriptor; extern Function_Descriptor join_3_descriptor;
Node join_3(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node join_3(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Introspection Functions ///////////////////////////////////////////// // Introspection Functions /////////////////////////////////////////////
extern Function_Descriptor type_of_descriptor; extern Function_Descriptor type_of_descriptor;
Node type_of(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node type_of(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor unit_descriptor; extern Function_Descriptor unit_descriptor;
Node unit(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node unit(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor unitless_descriptor; extern Function_Descriptor unitless_descriptor;
Node unitless(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node unitless(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor comparable_descriptor; extern Function_Descriptor comparable_descriptor;
Node comparable(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node comparable(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Boolean Functions /////////////////////////////////////////////////// // Boolean Functions ///////////////////////////////////////////////////
extern Function_Descriptor not_descriptor; extern Function_Descriptor not_descriptor;
Node not_impl(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node not_impl(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
} }
......
#include <iostream>
#include <iomanip>
#include <string>
#include <cctype>
#include <cstdlib>
#include <cmath>
#include "node.hpp"
#include "error.hpp"
using std::string;
using std::stringstream;
using std::cout;
using std::cerr;
using std::endl;
namespace Sass {
bool Node::operator==(const Node& rhs) const
{
if (type != rhs.type) return false;
switch (type)
{
case comma_list:
case space_list:
case expression:
case term: {
for (size_t i = 0; i < size(); ++i) {
if (at(i) == rhs[i]) continue;
else return false;
}
return true;
} break;
case variable:
case identifier:
case uri:
case textual_percentage:
case textual_dimension:
case textual_number:
case textual_hex:
case string_constant: {
return content.token.unquote() == rhs.content.token.unquote();
} break;
case number:
case numeric_percentage: {
return numeric_value() == rhs.numeric_value();
} break;
case numeric_dimension: {
if (Token::make(content.dimension.unit, Prelexer::identifier(content.dimension.unit)) ==
Token::make(rhs.content.dimension.unit, Prelexer::identifier(rhs.content.dimension.unit))) {
return numeric_value() == rhs.numeric_value();
}
else {
return false;
}
} break;
case boolean: {
return content.boolean_value == rhs.content.boolean_value;
} break;
default: {
return true;
} break;
}
}
bool Node::operator!=(const Node& rhs) const
{ return !(*this == rhs); }
bool Node::operator<(const Node& rhs) const
{
if (type == number && rhs.type == number ||
type == numeric_percentage && rhs.type == numeric_percentage) {
return numeric_value() < rhs.numeric_value();
}
else if (type == numeric_dimension && rhs.type == numeric_dimension) {
if (Token::make(content.dimension.unit, Prelexer::identifier(content.dimension.unit)) ==
Token::make(rhs.content.dimension.unit, Prelexer::identifier(rhs.content.dimension.unit))) {
return numeric_value() < rhs.numeric_value();
}
else {
throw Error(Error::evaluation, line_number, file_name, "incompatible units");
}
}
else {
throw Error(Error::evaluation, line_number, file_name, "incomparable types");
}
}
bool Node::operator<=(const Node& rhs) const
{ return *this < rhs || *this == rhs; }
bool Node::operator>(const Node& rhs) const
{ return !(*this <= rhs); }
bool Node::operator>=(const Node& rhs) const
{ return !(*this < rhs); }
}
#include "node_factory.hpp"
namespace Sass {
Node_Impl* Node_Factory::alloc_Node_Impl(Node::Type type, string path, size_t line)
{
Node_Impl* ip = new Node_Impl();
ip->type = type;
if (type == Node::backref) ip->has_backref = true;
ip->path = path;
ip->line = line;
pool_.push_back(ip);
return ip;
}
// returns a deep-copy of its argument
Node_Impl* Node_Factory::alloc_Node_Impl(Node_Impl* ip)
{
Node_Impl* ip_cpy = new Node_Impl(*ip);
pool_.push_back(ip_cpy);
if (ip_cpy->has_children) {
for (size_t i = 0, S = ip_cpy->size(); i < S; ++i) {
Node n(ip_cpy->at(i));
ip_cpy->at(i) = (*this)(n);
}
}
return ip_cpy;
}
// for cloning nodes
Node Node_Factory::operator()(const Node& n1)
{
Node_Impl* ip_cpy = alloc_Node_Impl(n1.ip_); // deep-copy the implementation object
return Node(ip_cpy);
}
// for making leaf nodes out of terminals/tokens
Node Node_Factory::operator()(Node::Type type, string path, size_t line, Token t)
{
Node_Impl* ip = alloc_Node_Impl(type, path, line);
ip->value.token = t;
return Node(ip);
}
// for making boolean values or interior nodes that have children
Node Node_Factory::operator()(Node::Type type, string path, size_t line, size_t size)
{
Node_Impl* ip = alloc_Node_Impl(type, path, line);
if (type == Node::boolean) ip->value.boolean = size;
else ip->children.reserve(size);
return Node(ip);
}
// for making nodes representing numbers
Node Node_Factory::operator()(string path, size_t line, double v, Node::Type type)
{
Node_Impl* ip = alloc_Node_Impl(type, path, line);
ip->value.numeric = v;
return Node(ip);
}
// for making nodes representing numeric dimensions (e.g. 5px, 3em)
Node Node_Factory::operator()(string path, size_t line, double v, const Token& t)
{
Node_Impl* ip = alloc_Node_Impl(Node::numeric_dimension, path, line);
ip->value.dimension.numeric = v;
ip->value.dimension.unit = t;
return Node(ip);
}
// for making nodes representing rgba color quads
Node Node_Factory::operator()(string path, size_t line, double r, double g, double b, double a)
{
Node color((*this)(Node::numeric_color, path, line, 4));
color << (*this)(path, line, r)
<< (*this)(path, line, g)
<< (*this)(path, line, b)
<< (*this)(path, line, a);
return color;
}
void Node_Factory::free()
{ for (size_t i = 0, S = pool_.size(); i < S; ++i) delete pool_[i]; }
}
\ No newline at end of file
#include <vector>
#ifndef SASS_NODE_INCLUDED
#include "node.hpp"
#endif
namespace Sass {
using namespace std;
struct Token;
struct Node_Impl;
class Node_Factory {
vector<Node_Impl*> pool_;
Node_Impl* alloc_Node_Impl(Node::Type type, string file, size_t line);
// returns a deep-copy of its argument
Node_Impl* alloc_Node_Impl(Node_Impl* ip);
public:
// for cloning nodes
Node operator()(const Node& n1);
// for making leaf nodes out of terminals/tokens
Node operator()(Node::Type type, string file, size_t line, Token t);
// for making boolean values or interior nodes that have children
Node operator()(Node::Type type, string file, size_t line, size_t size);
// // for making nodes representing boolean values
// Node operator()(Node::Type type, string file, size_t line, bool b);
// for making nodes representing numbers
Node operator()(string file, size_t line, double v, Node::Type type = Node::number);
// for making nodes representing numeric dimensions (e.g. 5px, 3em)
Node operator()(string file, size_t line, double v, const Token& t);
// for making nodes representing rgba color quads
Node operator()(string file, size_t line, double r, double g, double b, double a = 1.0);
void free();
};
}
\ No newline at end of file
...@@ -111,6 +111,51 @@ namespace Sass { ...@@ -111,6 +111,51 @@ namespace Sass {
const char* include(const char* src) { const char* include(const char* src) {
return exactly<include_kwd>(src); return exactly<include_kwd>(src);
} }
extern const char extend_kwd[] = "@extend";
const char* extend(const char* src) {
return exactly<extend_kwd>(src);
}
extern const char if_kwd[] = "@if";
extern const char if_chars[] = "if";
const char* if_directive(const char* src) {
return exactly<if_kwd>(src);
}
extern const char else_kwd[] = "@else";
const char* else_directive(const char* src) {
return exactly<else_kwd>(src);
}
const char* elseif_directive(const char* src) {
return sequence< else_directive,
spaces_and_comments,
exactly< if_chars > >(src);
}
extern const char for_kwd[] = "@for";
const char* for_directive(const char* src) {
return exactly<for_kwd>(src);
}
extern const char from_kwd[] = "from";
const char* from(const char* src) {
return exactly<from_kwd>(src);
}
extern const char to_kwd[] = "to";
const char* to(const char* src) {
return exactly<to_kwd>(src);
}
extern const char through_kwd[] = "through";
const char* through(const char* src) {
return exactly<through_kwd>(src);
}
extern const char each_kwd[] = "@each";
const char* each_directive(const char* src) {
return exactly<each_kwd>(src);
}
extern const char while_kwd[] = "@while";
const char* while_directive(const char* src) {
return exactly<while_kwd>(src);
}
const char* name(const char* src) { const char* name(const char* src) {
return one_plus< alternatives< alnum, return one_plus< alternatives< alnum,
......
...@@ -310,6 +310,21 @@ namespace Sass { ...@@ -310,6 +310,21 @@ namespace Sass {
const char* import(const char* src); const char* import(const char* src);
const char* mixin(const char* src); const char* mixin(const char* src);
const char* include(const char* src); const char* include(const char* src);
const char* extend(const char* src);
const char* if_directive(const char* src);
const char* else_directive(const char* src);
const char* elseif_directive(const char* src);
const char* for_directive(const char* src);
const char* from(const char* src);
const char* to(const char* src);
const char* through(const char* src);
const char* each_directive(const char* src);
const char* while_directive(const char* src);
// Match CSS type selectors // Match CSS type selectors
const char* namespace_prefix(const char* src); const char* namespace_prefix(const char* src);
const char* type_selector(const char* src); const char* type_selector(const char* src);
...@@ -388,10 +403,10 @@ namespace Sass { ...@@ -388,10 +403,10 @@ namespace Sass {
template<prelexer mx> template<prelexer mx>
const char* find_first_in_interval(const char* beg, const char* end) { const char* find_first_in_interval(const char* beg, const char* end) {
while ((beg < end) && *beg) { while ((beg < end) && *beg) {
const char* p = mx(beg); if (mx(beg)) return beg;
if (p) return p;
++beg; ++beg;
} }
return 0; return 0;
} }
template <char c> template <char c>
......
...@@ -10,8 +10,8 @@ ...@@ -10,8 +10,8 @@
#include "sass_interface.h" #include "sass_interface.h"
extern "C" { extern "C" {
using namespace std; using namespace std;
sass_context* sass_new_context() sass_context* sass_new_context()
{ return (sass_context*) calloc(1, sizeof(sass_context)); } { return (sass_context*) calloc(1, sizeof(sass_context)); }
...@@ -39,21 +39,14 @@ extern "C" { ...@@ -39,21 +39,14 @@ extern "C" {
{ {
using namespace Sass; using namespace Sass;
doc.parse_scss(); doc.parse_scss();
// cerr << "PARSED" << endl; eval(doc.root,
eval(doc.root, doc.context.global_env, doc.context.function_env, doc.context.registry); doc.context.new_Node(Node::none, doc.path, doc.line, 0),
// cerr << "EVALUATED" << endl; doc.context.global_env,
doc.context.function_env,
doc.context.new_Node,
doc.context);
extend_selectors(doc.context.pending_extensions, doc.context.new_Node);
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;
for (size_t 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());
return c_output; return c_output;
...@@ -64,14 +57,15 @@ extern "C" { ...@@ -64,14 +57,15 @@ extern "C" {
using namespace Sass; using namespace Sass;
try { try {
Context cpp_ctx(c_ctx->options.include_paths); Context cpp_ctx(c_ctx->options.include_paths);
Document doc(0, c_ctx->input_string, cpp_ctx); // Document doc(0, c_ctx->input_string, cpp_ctx);
Document doc(Document::make_from_source_chars(cpp_ctx, c_ctx->source_string));
c_ctx->output_string = process_document(doc, c_ctx->options.output_style); c_ctx->output_string = process_document(doc, c_ctx->options.output_style);
c_ctx->error_message = 0; c_ctx->error_message = 0;
c_ctx->error_status = 0; c_ctx->error_status = 0;
} }
catch (Error& e) { catch (Error& e) {
stringstream msg_stream; stringstream msg_stream;
msg_stream << "ERROR -- " << e.file_name << ", line " << e.line_number << ": " << e.message << endl; msg_stream << "ERROR -- " << e.path << ", line " << e.line << ": " << e.message << endl;
string msg(msg_stream.str()); string msg(msg_stream.str());
char* msg_str = (char*) malloc(msg.size() + 1); char* msg_str = (char*) malloc(msg.size() + 1);
strcpy(msg_str, msg.c_str()); strcpy(msg_str, msg.c_str());
...@@ -98,7 +92,8 @@ extern "C" { ...@@ -98,7 +92,8 @@ extern "C" {
using namespace Sass; using namespace Sass;
try { try {
Context cpp_ctx(c_ctx->options.include_paths); Context cpp_ctx(c_ctx->options.include_paths);
Document doc(c_ctx->input_path, 0, cpp_ctx); // Document doc(c_ctx->input_path, 0, cpp_ctx);
Document doc(Document::make_from_file(cpp_ctx, string(c_ctx->input_path)));
// cerr << "MADE A DOC AND CONTEXT OBJ" << endl; // cerr << "MADE A DOC AND CONTEXT OBJ" << endl;
// cerr << "REGISTRY: " << doc.context.registry.size() << endl; // cerr << "REGISTRY: " << doc.context.registry.size() << endl;
c_ctx->output_string = process_document(doc, c_ctx->options.output_style); c_ctx->output_string = process_document(doc, c_ctx->options.output_style);
...@@ -107,7 +102,7 @@ extern "C" { ...@@ -107,7 +102,7 @@ extern "C" {
} }
catch (Error& e) { catch (Error& e) {
stringstream msg_stream; stringstream msg_stream;
msg_stream << "ERROR -- " << e.file_name << ", line " << e.line_number << ": " << e.message << endl; msg_stream << "ERROR -- " << e.path << ", line " << e.line << ": " << e.message << endl;
string msg(msg_stream.str()); string msg(msg_stream.str());
char* msg_str = (char*) malloc(msg.size() + 1); char* msg_str = (char*) malloc(msg.size() + 1);
strcpy(msg_str, msg.c_str()); strcpy(msg_str, msg.c_str());
......
...@@ -13,7 +13,7 @@ struct sass_options { ...@@ -13,7 +13,7 @@ struct sass_options {
}; };
struct sass_context { struct sass_context {
char* input_string; char* source_string;
char* output_string; char* output_string;
struct sass_options options; struct sass_options options;
int error_status; int error_status;
......
#include <iostream>
#include <string>
#include <tr1/unordered_map>
#include <map>
#include <algorithm>
#ifndef SASS_NODE_INCLUDED
#include "node.hpp"
#endif
#include "node_factory.hpp"
int main()
{
using namespace Sass;
using namespace std;
cout << sizeof(Node_Impl*) << endl;
cout << sizeof(Node) << endl;
cout << sizeof(Node_Impl) << endl << endl;
Node_Factory new_Node = Node_Factory();
Node interior(new_Node(Node::block, "", 0, 3));
cout << interior.size() << endl;
cout << interior.has_children() << endl;
cout << interior.should_eval() << endl << endl;
Node num(new_Node("", 0, 255, 123, 32));
Node num2(new_Node("", 0, 255, 123, 32));
Node num3(new_Node("", 0, 255, 122, 20, .75));
cout << num.size() << endl;
cout << num.has_children() << endl;
cout << num.has_statements() << endl << endl;
cout << num[1].is_numeric() << endl;
cout << num[1].numeric_value() << endl << endl;
cout << (num == num2) << endl;
cout << (num == num3) << endl << endl;
cout << (num3[2] < num2[2]) << endl;
cout << (num2[3] < num3[3]) << endl << endl;
cout << (num2[2] >= num3[2]) << endl;
cout << (num2[3] != num3[3]) << endl << endl;
Node num4(new_Node(num3));
cout << num3[3].numeric_value() << endl;
cout << num4[3].numeric_value() << endl;
num4[3] = new_Node("", 0, 0.4567);
cout << num3[3].numeric_value() << endl;
cout << num4[3].numeric_value() << endl << endl;
Node block1(new_Node(Node::block, "block", 1, 2));
block1 << num2 << num4;
Node block2(new_Node(block1));
cout << (block1 == block2) << endl;
cout << block1[1][3].numeric_value() << endl;
cout << block2[1][3].numeric_value() << endl;
block2[1][3] = new_Node("", 0, .9876);
cout << block1[1][3].numeric_value() << endl;
cout << block2[1][3].numeric_value() << endl << endl;
map<Node, string> dict;
Node n(new_Node("", 0, 42));
Node m(new_Node("", 0, 41));
dict[n] = "hello";
dict[m] = "goodbye";
cout << dict[m] << " " << dict[n] << endl;
cout << "Lexicographical comparison: " << endl;
cout << lexicographical_compare(num2.begin(), num2.end(),
num3.begin(), num3.end())
<< endl;
cout << lexicographical_compare(num.begin(), num.end(),
num2.begin(), num2.end())
<< endl;
cout << lexicographical_compare(num3.begin(), num3.end(),
num.begin(), num.end())
<< endl << endl;
new_Node.free();
return 0;
}
\ No newline at end of file
#include "values.hpp"
namespace Sass {
// Token::Token() : begin(0), end(0) { }
// Token::Token(const char* begin, const char* end)
// : begin(begin), end(end) { }
string Token::unquote() const {
string result;
const char* p = begin;
if (*begin == '\'' || *begin == '"') {
++p;
while (p < end) {
if (*p == '\\') {
switch (*(++p)) {
case 'n': result += '\n'; break;
case 't': result += '\t'; break;
case 'b': result += '\b'; break;
case 'r': result += '\r'; break;
case 'f': result += '\f'; break;
case 'v': result += '\v'; break;
case 'a': result += '\a'; break;
case '\\': result += '\\'; break;
default: result += *p; break;
}
}
else if (p == end - 1) {
return result;
}
else {
result += *p;
}
++p;
}
return result;
}
else {
while (p < end) {
result += *(p++);
}
return result;
}
}
void Token::unquote_to_stream(std::stringstream& buf) const {
const char* p = begin;
if (*begin == '\'' || *begin == '"') {
++p;
while (p < end) {
if (*p == '\\') {
switch (*(++p)) {
case 'n': buf << '\n'; break;
case 't': buf << '\t'; break;
case 'b': buf << '\b'; break;
case 'r': buf << '\r'; break;
case 'f': buf << '\f'; break;
case 'v': buf << '\v'; break;
case 'a': buf << '\a'; break;
case '\\': buf << '\\'; break;
default: buf << *p; break;
}
}
else if (p == end - 1) {
return;
}
else {
buf << *p;
}
++p;
}
return;
}
else {
while (p < end) {
buf << *(p++);
}
return;
}
}
bool Token::operator<(const Token& rhs) const
{
const char* first1 = begin;
const char* last1 = end;
const char* first2 = rhs.begin;
const char* last2 = rhs.end;
while (first1!=last1)
{
if (first2==last2 || *first2<*first1) return false;
else if (*first1<*first2) return true;
first1++; first2++;
}
return (first2!=last2);
}
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;
return true;
}
}
\ No newline at end of file
#include <string>
#include <sstream>
#include <cstring>
#ifndef SASS_PRELEXER_INCLUDED
#include "prelexer.hpp"
#endif
namespace Sass {
using std::string;
struct Token {
const char* begin;
const char* end;
// Token();
// Token(const char* begin, const char* end);
size_t length() const
{ return end - begin; }
inline operator string() const
{ return string(begin, end - begin); }
string to_string() const
{ return string(begin, end - begin); }
string unquote() const;
void unquote_to_stream(std::stringstream& buf) const;
bool operator<(const Token& rhs) const;
bool operator==(const Token& rhs) const;
operator bool()
{ return begin && end && begin >= end; }
static Token make()
{
Token t;
t.begin = 0;
t.end = 0;
return t;
}
static Token make(const char* s)
{
Token t;
t.begin = s;
t.end = s + std::strlen(s);
return t;
}
static Token make(const char* b, const char* e)
{
Token t;
t.begin = b;
t.end = e;
return t;
}
};
struct Dimension {
double numeric_value;
const char* unit;
};
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment