Commit 0a31ae6d by litek
parents f0313c3d e9971023
CC=g++ CC = g++
CFLAGS=-c -Wall -O2 -fPIC CFLAGS = -Wall -O2 -fPIC
LDFLAGS= -fPIC LDFLAGS = -fPIC
SOURCES = \
context.cpp functions.cpp document.cpp \ PREFIX = /usr/local
document_parser.cpp eval_apply.cpp node.cpp \ LIBDIR = $(PREFIX)/lib
node_factory.cpp node_emitters.cpp prelexer.cpp \
sass_interface.cpp SOURCES = constants.cpp context.cpp functions.cpp document.cpp \
document_parser.cpp eval_apply.cpp node.cpp \
node_factory.cpp node_emitters.cpp prelexer.cpp \
selector.cpp sass_interface.cpp
OBJECTS = $(SOURCES:.cpp=.o) OBJECTS = $(SOURCES:.cpp=.o)
all: $(OBJECTS) static: libsass.a
ar rvs libsass.a $(OBJECTS) shared: libsass.so
libsass.a: $(OBJECTS)
ar rvs $@ $(OBJECTS)
shared: $(OBJECTS) libsass.so: $(OBJECTS)
$(CC) -shared -o libsass.so *.o $(CC) -shared $(LDFLAGS) -o $@ $(OBJECTS)
.cpp.o: .cpp.o:
$(CC) $(CFLAGS) $< -o $@ $(CC) $(CFLAGS) -c -o $@ $<
install: libsass.a
install -Dpm0755 $< $(DESTDIR)$(LIBDIR)/$<
install-shared: libsass.so
install -Dpm0755 $< $(DESTDIR)$(LIBDIR)/$<
clean: clean:
rm -rf *.o *.a *.so rm -f $(OBJECTS) *.a *.so
\ No newline at end of file
.PHONY: static shared install install-shared clean
...@@ -2,9 +2,9 @@ ACLOCAL_AMFLAGS = -I m4 ...@@ -2,9 +2,9 @@ ACLOCAL_AMFLAGS = -I m4
lib_LTLIBRARIES = libsass.la lib_LTLIBRARIES = libsass.la
libsass_la_SOURCES = context.cpp functions.cpp document.cpp \ libsass_la_SOURCES = context.cpp functions.cpp document.cpp \
document_parser.cpp eval_apply.cpp node.cpp \ constants.cpp document_parser.cpp eval_apply.cpp node.cpp \
node_factory.cpp node_emitters.cpp prelexer.cpp \ node_factory.cpp node_emitters.cpp prelexer.cpp \
sass_interface.cpp selector.cpp sass_interface.cpp
libsass_la_LDFLAGS = -no-undefined -version-info 0:0:0 libsass_la_LDFLAGS = -no-undefined -version-info 0:0:0
include_HEADERS = sass_interface.h include_HEADERS = sass_interface.h
...@@ -85,8 +85,8 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)" ...@@ -85,8 +85,8 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"
LTLIBRARIES = $(lib_LTLIBRARIES) LTLIBRARIES = $(lib_LTLIBRARIES)
libsass_la_LIBADD = libsass_la_LIBADD =
am_libsass_la_OBJECTS = context.lo functions.lo document.lo \ am_libsass_la_OBJECTS = context.lo functions.lo document.lo \
document_parser.lo eval_apply.lo node.lo node_factory.lo \ constants.lo document_parser.lo eval_apply.lo node.lo node_factory.lo \
node_emitters.lo prelexer.lo sass_interface.lo node_emitters.lo prelexer.lo selector.lo sass_interface.lo
libsass_la_OBJECTS = $(am_libsass_la_OBJECTS) libsass_la_OBJECTS = $(am_libsass_la_OBJECTS)
libsass_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ libsass_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
...@@ -245,9 +245,9 @@ top_srcdir = @top_srcdir@ ...@@ -245,9 +245,9 @@ top_srcdir = @top_srcdir@
ACLOCAL_AMFLAGS = -I m4 ACLOCAL_AMFLAGS = -I m4
lib_LTLIBRARIES = libsass.la lib_LTLIBRARIES = libsass.la
libsass_la_SOURCES = context.cpp functions.cpp document.cpp \ libsass_la_SOURCES = context.cpp functions.cpp document.cpp \
document_parser.cpp eval_apply.cpp node.cpp \ constants.cpp document_parser.cpp eval_apply.cpp node.cpp \
node_factory.cpp node_emitters.cpp prelexer.cpp \ node_factory.cpp node_emitters.cpp prelexer.cpp \
sass_interface.cpp selector.cpp sass_interface.cpp
libsass_la_LDFLAGS = -no-undefined -version-info 0:0:0 libsass_la_LDFLAGS = -no-undefined -version-info 0:0:0
include_HEADERS = sass_interface.h include_HEADERS = sass_interface.h
...@@ -347,6 +347,7 @@ distclean-compile: ...@@ -347,6 +347,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/context.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/context.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/document.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/document.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/constants.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/document_parser.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/document_parser.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eval_apply.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eval_apply.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/functions.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/functions.Plo@am__quote@
...@@ -354,6 +355,7 @@ distclean-compile: ...@@ -354,6 +355,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node_emitters.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node_emitters.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node_factory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node_factory.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prelexer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prelexer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/selector.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sass_interface.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sass_interface.Plo@am__quote@
.cpp.o: .cpp.o:
......
#define SASS_COLOR_NAMES_INCLUDED #define SASS_COLOR_NAMES
namespace Sass { namespace Sass {
......
#include "constants.hpp"
namespace Sass {
namespace Constants {
// hidden variable name for the image path (for the image-url built-in)
extern const char image_path_var[] = "$[image path]";
// sass keywords
extern const char import_kwd[] = "@import";
extern const char mixin_kwd[] = "@mixin";
extern const char function_kwd[] = "@function";
extern const char return_kwd[] = "@return";
extern const char include_kwd[] = "@include";
extern const char extend_kwd[] = "@extend";
extern const char if_kwd[] = "@if";
extern const char else_kwd[] = "@else";
extern const char if_after_else_kwd[] = "if";
extern const char for_kwd[] = "@for";
extern const char from_kwd[] = "from";
extern const char to_kwd[] = "to";
extern const char through_kwd[] = "through";
extern const char each_kwd[] = "@each";
extern const char in_kwd[] = "in";
extern const char while_kwd[] = "@while";
extern const char warn_kwd[] = "@warn";
extern const char default_kwd[] = "default";
// css standard units
extern const char em_kwd[] = "em";
extern const char ex_kwd[] = "ex";
extern const char px_kwd[] = "px";
extern const char cm_kwd[] = "cm";
extern const char mm_kwd[] = "mm";
extern const char pt_kwd[] = "pt";
extern const char pc_kwd[] = "pc";
extern const char deg_kwd[] = "deg";
extern const char rad_kwd[] = "rad";
extern const char grad_kwd[] = "grad";
extern const char ms_kwd[] = "ms";
extern const char s_kwd[] = "s";
extern const char Hz_kwd[] = "Hz";
extern const char kHz_kwd[] = "kHz";
// css functions and keywords
extern const char media_kwd[] = "@media";
extern const char only_kwd[] = "only";
extern const char rgb_kwd[] = "rgb(";
extern const char url_kwd[] = "url(";
extern const char image_url_kwd[] = "image-url(";
extern const char important_kwd[] = "important";
extern const char pseudo_not_kwd[] = ":not(";
extern const char even_kwd[] = "even";
extern const char odd_kwd[] = "odd";
// css attribute-matching operators
extern const char tilde_equal[] = "~=";
extern const char pipe_equal[] = "|=";
extern const char caret_equal[] = "^=";
extern const char dollar_equal[] = "$=";
extern const char star_equal[] = "*=";
// relational & logical operators and constants
extern const char and_kwd[] = "and";
extern const char or_kwd[] = "or";
extern const char not_kwd[] = "not";
extern const char gt[] = ">";
extern const char gte[] = ">=";
extern const char lt[] = "<";
extern const char lte[] = "<=";
extern const char eq[] = "==";
extern const char neq[] = "!=";
extern const char true_kwd[] = "true";
extern const char false_kwd[] = "false";
// miscellaneous punctuation and delimiters
extern const char percent_str[] = "%";
extern const char empty_str[] = "";
extern const char slash_slash[] = "//";
extern const char slash_star[] = "/*";
extern const char star_slash[] = "*/";
extern const char hash_lbrace[] = "#{";
extern const char rbrace[] = "}";
extern const char rparen[] = ")";
extern const char sign_chars[] = "-+";
// type names
extern const char numeric_name[] = "numeric value";
extern const char number_name[] = "number";
extern const char percentage_name[] = "percentage";
extern const char dimension_name[] = "numeric dimension";
extern const char string_name[] = "string";
extern const char bool_name[] = "bool";
extern const char color_name[] = "color";
extern const char list_name[] = "list";
}
}
\ No newline at end of file
#define SASS_CONSTANTS
namespace Sass {
namespace Constants {
// hidden variable name for the image path (for the image-url built-in)
extern const char image_path_var[];
// sass keywords
extern const char import_kwd[];
extern const char mixin_kwd[];
extern const char function_kwd[];
extern const char return_kwd[];
extern const char include_kwd[];
extern const char extend_kwd[];
extern const char if_kwd[];
extern const char else_kwd[];
extern const char if_after_else_kwd[];
extern const char for_kwd[];
extern const char from_kwd[];
extern const char to_kwd[];
extern const char through_kwd[];
extern const char each_kwd[];
extern const char in_kwd[];
extern const char while_kwd[];
extern const char warn_kwd[];
extern const char default_kwd[];
// css standard units
extern const char em_kwd[];
extern const char ex_kwd[];
extern const char px_kwd[];
extern const char cm_kwd[];
extern const char mm_kwd[];
extern const char pt_kwd[];
extern const char pc_kwd[];
extern const char deg_kwd[];
extern const char rad_kwd[];
extern const char grad_kwd[];
extern const char ms_kwd[];
extern const char s_kwd[];
extern const char Hz_kwd[];
extern const char kHz_kwd[];
// css functions and keywords
extern const char media_kwd[];
extern const char only_kwd[];
extern const char rgb_kwd[];
extern const char url_kwd[];
extern const char image_url_kwd[];
extern const char important_kwd[];
extern const char pseudo_not_kwd[];
extern const char even_kwd[];
extern const char odd_kwd[];
// css attribute-matching operators
extern const char tilde_equal[];
extern const char pipe_equal[];
extern const char caret_equal[];
extern const char dollar_equal[];
extern const char star_equal[];
// relational & logical operators and constants
extern const char and_kwd[];
extern const char or_kwd[];
extern const char not_kwd[];
extern const char gt[];
extern const char gte[];
extern const char lt[];
extern const char lte[];
extern const char eq[];
extern const char neq[];
extern const char true_kwd[];
extern const char false_kwd[];
// miscellaneous punctuation and delimiters
extern const char percent_str[];
extern const char empty_str[];
extern const char slash_slash[];
extern const char slash_star[];
extern const char star_slash[];
extern const char hash_lbrace[];
extern const char rbrace[];
extern const char rparen[];
extern const char sign_chars[];
// type names
extern const char numeric_name[];
extern const char number_name[];
extern const char percentage_name[];
extern const char dimension_name[];
extern const char string_name[];
extern const char bool_name[];
extern const char color_name[];
extern const char list_name[];
}
}
\ No newline at end of file
#include "context.hpp" #ifdef _WIN32
#include <direct.h>
#define getcwd _getcwd
#else
#include <unistd.h>
#endif
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
#include <unistd.h> #include <sstream>
#include "prelexer.hpp" #include "context.hpp"
#include "constants.hpp"
#include "color_names.hpp" #include "color_names.hpp"
using std::cerr; using std::endl; #include "prelexer.hpp"
namespace Sass { namespace Sass {
using std::pair; using namespace Constants;
using std::pair; using std::cerr; using std::endl;
void Context::collect_include_paths(const char* paths_str) void Context::collect_include_paths(const char* paths_str)
{ {
const size_t wd_len = 1024; const size_t wd_len = 1024;
...@@ -64,6 +73,9 @@ namespace Sass { ...@@ -64,6 +73,9 @@ namespace Sass {
path_string = "'" + path_string + "/'"; path_string = "'" + path_string + "/'";
image_path = new char[path_string.length() + 1]; image_path = new char[path_string.length() + 1];
std::strcpy(image_path, path_string.c_str()); std::strcpy(image_path, path_string.c_str());
// stash this hidden variable for the image-url built-in to use
global_env[Token::make(image_path_var)] = new_Node(Node::string_constant, "[IMAGE PATH]", 0, Token::make(image_path));
} }
Context::~Context() Context::~Context()
...@@ -73,21 +85,20 @@ namespace Sass { ...@@ -73,21 +85,20 @@ namespace Sass {
} }
delete[] image_path; delete[] image_path;
new_Node.free(); new_Node.free();
// cerr << "Deallocated " << i << " source string(s)." << endl;
} }
inline void Context::register_function(Function_Descriptor d, Primitive ip) inline void Context::register_function(Signature sig, Primitive ip)
{ {
Function f(d, ip, new_Node); Function f(const_cast<char*>(sig), ip, *this);
// function_env[pair<string, size_t>(f.name, f.parameters.size())] = f;
function_env[f.name] = f; function_env[f.name] = f;
} }
inline void Context::register_function(Function_Descriptor d, Primitive ip, size_t arity) inline void Context::register_function(Signature sig, Primitive ip, size_t arity)
{ {
Function f(d, ip, new_Node); Function f(const_cast<char*>(sig), ip, *this);
// function_env[pair<string, size_t>(f.name, arity)] = f; std::stringstream stub;
function_env[f.name] = f; stub << f.name << " " << arity;
function_env[stub.str()] = f;
} }
inline void Context::register_overload_stub(string name) inline void Context::register_overload_stub(string name)
...@@ -98,67 +109,80 @@ namespace Sass { ...@@ -98,67 +109,80 @@ namespace Sass {
void Context::register_functions() void Context::register_functions()
{ {
using namespace Functions; using namespace Functions;
// RGB Functions // RGB Functions
register_function(rgb_descriptor, rgb); register_function(rgb_sig, rgb);
register_overload_stub("rgba"); register_overload_stub("rgba");
register_function(rgba_4_descriptor, rgba_4); register_function(rgba_4_sig, rgba_4, 4);
register_function(rgba_2_descriptor, rgba_2); register_function(rgba_2_sig, rgba_2, 2);
register_function(red_descriptor, red); register_function(red_sig, red);
register_function(green_descriptor, green); register_function(green_sig, green);
register_function(blue_descriptor, blue); register_function(blue_sig, blue);
register_overload_stub("mix"); register_function(mix_sig, mix);
register_function(mix_2_descriptor, mix_2);
register_function(mix_3_descriptor, mix_3);
// HSL Functions // HSL Functions
register_function(hsla_descriptor, hsla); register_function(hsl_sig, hsl);
register_function(hsl_descriptor, hsl); register_function(hsla_sig, hsla);
register_function(invert_descriptor, invert); register_function(hue_sig, hue);
register_function(saturation_sig, saturation);
register_function(lightness_sig, lightness);
register_function(adjust_hue_sig, adjust_hue);
register_function(lighten_sig, lighten);
register_function(darken_sig, darken);
register_function(saturate_sig, saturate);
register_function(desaturate_sig, desaturate);
register_function(grayscale_sig, grayscale);
register_function(complement_sig, complement);
register_function(invert_sig, invert);
// Opacity Functions // Opacity Functions
register_function(alpha_descriptor, alpha); register_function(alpha_sig, alpha);
register_function(opacity_descriptor, alpha); register_function(opacity_sig, opacity);
register_function(opacify_descriptor, opacify); register_function(opacify_sig, opacify);
register_function(fade_in_descriptor, opacify); register_function(fade_in_sig, fade_in);
register_function(transparentize_descriptor, transparentize); register_function(transparentize_sig, transparentize);
register_function(fade_out_descriptor, transparentize); register_function(fade_out_sig, fade_out);
// Other Color Functions
register_function(adjust_color_sig, adjust_color);
register_function(scale_color_sig, scale_color);
register_function(change_color_sig, change_color);
// String Functions // String Functions
register_function(unquote_descriptor, unquote); register_function(unquote_sig, unquote);
register_function(quote_descriptor, quote); register_function(quote_sig, quote);
// Number Functions // Number Functions
register_function(percentage_descriptor, percentage); register_function(percentage_sig, percentage);
register_function(round_descriptor, round); register_function(round_sig, round);
register_function(ceil_descriptor, ceil); register_function(ceil_sig, ceil);
register_function(floor_descriptor, floor); register_function(floor_sig, floor);
register_function(abs_descriptor, abs); register_function(abs_sig, abs);
// List Functions // List Functions
register_function(length_descriptor, length); register_function(length_sig, length);
register_function(nth_descriptor, nth); register_function(nth_sig, nth);
register_overload_stub("join"); register_function(index_sig, index);
register_function(join_2_descriptor, join_2); register_function(join_sig, join);
register_function(join_3_descriptor, join_3); register_function(append_sig, append);
register_overload_stub("append");
register_function(append_2_descriptor, append_2);
register_function(append_3_descriptor, append_3);
register_overload_stub("compact"); register_overload_stub("compact");
register_function(compact_1_descriptor, compact); register_function(compact_1_sig, compact_1, 1);
register_function(compact_2_descriptor, compact); register_function(compact_n_sig, compact_n, 0);
register_function(compact_3_descriptor, compact); register_function(compact_n_sig, compact_n, 2);
register_function(compact_4_descriptor, compact); register_function(compact_n_sig, compact_n, 3);
register_function(compact_5_descriptor, compact); register_function(compact_n_sig, compact_n, 4);
register_function(compact_6_descriptor, compact); register_function(compact_n_sig, compact_n, 5);
register_function(compact_7_descriptor, compact); register_function(compact_n_sig, compact_n, 6);
register_function(compact_8_descriptor, compact); register_function(compact_n_sig, compact_n, 7);
register_function(compact_9_descriptor, compact); register_function(compact_n_sig, compact_n, 8);
register_function(compact_10_descriptor, compact); register_function(compact_n_sig, compact_n, 9);
register_function(compact_11_descriptor, compact); register_function(compact_n_sig, compact_n, 10);
register_function(compact_12_descriptor, compact); register_function(compact_n_sig, compact_n, 11);
register_function(compact_n_sig, compact_n, 12);
// Introspection Functions // Introspection Functions
register_function(type_of_descriptor, type_of); register_function(type_of_sig, type_of);
register_function(unit_descriptor, unit); register_function(unit_sig, unit);
register_function(unitless_descriptor, unitless); register_function(unitless_sig, unitless);
register_function(comparable_descriptor, comparable); register_function(comparable_sig, comparable);
// Boolean Functions // Boolean Functions
register_function(not_descriptor, not_impl); register_function(not_sig, not_impl);
register_function(if_descriptor, if_impl); register_function(if_sig, if_impl);
// Path Functions
register_function(image_url_sig, image_url);
} }
void Context::setup_color_map() void Context::setup_color_map()
......
#define SASS_CONTEXT_INCLUDED #define SASS_CONTEXT
//#ifndef SASS_ENVIRONMENT
#include "environment.hpp"
//#endif
#include <utility> #include <utility>
#include <map>
#ifndef SASS_NODE_FACTORY
#include "node_factory.hpp" #include "node_factory.hpp"
#endif
#ifndef SASS_FUNCTIONS
#include "functions.hpp" #include "functions.hpp"
#endif
namespace Sass { namespace Sass {
using std::pair; using std::pair;
using std::map; 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];
else if (parent) return (*parent)[key];
else return current_frame[key];
}
};
struct Context { struct Context {
Environment global_env; Environment global_env;
map<string, Function> function_env; map<string, Function> function_env;
...@@ -59,9 +37,9 @@ namespace Sass { ...@@ -59,9 +37,9 @@ namespace Sass {
void collect_include_paths(const char* paths_str); void collect_include_paths(const char* paths_str);
Context(const char* paths_str = 0, const char* img_path_str = 0); Context(const char* paths_str = 0, const char* img_path_str = 0);
~Context(); ~Context();
void register_function(Function_Descriptor d, Primitive ip); void register_function(Signature sig, Primitive ip);
void register_function(Function_Descriptor d, Primitive ip, size_t arity); void register_function(Signature sig, Primitive ip, size_t arity);
void register_overload_stub(string name); void register_overload_stub(string name);
void register_functions(); void register_functions();
void setup_color_map(); void setup_color_map();
......
#ifdef _WIN32
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#endif
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include "document.hpp" #include "document.hpp"
......
#define SASS_DOCUMENT
#include <map> #include <map>
#ifndef SASS_PRELEXER_INCLUDED #ifndef SASS_PRELEXER
#include "prelexer.hpp" #include "prelexer.hpp"
#endif #endif
#ifndef SASS_NODE_INCLUDED #ifndef SASS_NODE
#include "node.hpp" #include "node.hpp"
#endif #endif
#ifndef SASS_CONTEXT_INCLUDED #ifndef SASS_CONTEXT
#include "context.hpp" #include "context.hpp"
#endif #endif
...@@ -130,10 +132,10 @@ namespace Sass { ...@@ -130,10 +132,10 @@ namespace Sass {
Node parse_mixin_definition(); Node parse_mixin_definition();
Node parse_function_definition(); Node parse_function_definition();
Node parse_parameters(); Node parse_parameters();
Node parse_parameter(); Node parse_parameter(Node::Type);
Node parse_mixin_call(); Node parse_mixin_call();
Node parse_arguments(); Node parse_arguments();
Node parse_argument(); Node parse_argument(Node::Type);
Node parse_assignment(); Node parse_assignment();
Node parse_propset(); Node parse_propset();
Node parse_ruleset(Selector_Lookahead lookahead, Node::Type inside_of = Node::none); Node parse_ruleset(Selector_Lookahead lookahead, Node::Type inside_of = Node::none);
...@@ -162,6 +164,7 @@ namespace Sass { ...@@ -162,6 +164,7 @@ namespace Sass {
Node parse_string(); Node parse_string();
Node parse_value_schema(); Node parse_value_schema();
Node parse_identifier_schema(); Node parse_identifier_schema();
Node parse_url_schema();
Node parse_if_directive(Node surrounding_ruleset, Node::Type inside_of = Node::none); Node parse_if_directive(Node surrounding_ruleset, Node::Type inside_of = Node::none);
Node parse_for_directive(Node surrounding_ruleset, Node::Type inside_of = Node::none); Node parse_for_directive(Node surrounding_ruleset, Node::Type inside_of = Node::none);
Node parse_each_directive(Node surrounding_ruleset, Node::Type inside_of = Node::none); Node parse_each_directive(Node surrounding_ruleset, Node::Type inside_of = Node::none);
...@@ -172,7 +175,8 @@ namespace Sass { ...@@ -172,7 +175,8 @@ namespace Sass {
Node parse_warning(); Node parse_warning();
Selector_Lookahead lookahead_for_selector(const char* start = 0); Selector_Lookahead lookahead_for_selector(const char* start = 0);
Selector_Lookahead lookahead_for_extension_target(const char* start = 0);
void throw_syntax_error(string message, size_t ln = 0); void throw_syntax_error(string message, size_t ln = 0);
void throw_read_error(string message, size_t ln = 0); void throw_read_error(string message, size_t ln = 0);
......
#define SASS_ENVIRONMENT
#include <map>
#ifndef SASS_NODE
#include "node.hpp"
#endif
namespace Sass {
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];
else if (parent) return (*parent)[key];
else return current_frame[key];
}
void print()
{
for (map<Token, Node>::iterator i = current_frame.begin(); i != current_frame.end(); ++i) {
cerr << i->first.to_string() << ": " << i->second.to_string() << endl;
}
if (parent) {
cerr << "---" << endl;
parent->print();
}
}
};
}
\ No newline at end of file
#define SASS_ERROR
namespace Sass { namespace Sass {
struct Error { struct Error {
......
#define SASS_EVAL_APPLY
#include <map> #include <map>
#ifndef SASS_NODE_INCLUDED #ifndef SASS_NODE
#include "node.hpp" #include "node.hpp"
#endif #endif
#ifndef SASS_CONTEXT_INCLUDED #ifndef SASS_CONTEXT
#include "context.hpp" #include "context.hpp"
#endif #endif
namespace Sass { namespace Sass {
using std::map; using std::map;
void expand(Node expr, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool function_name = false);
Node eval(Node expr, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool function_name = false); Node eval(Node expr, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool function_name = false);
Node function_eval(string name, Node stm, Environment& bindings, Node_Factory& new_Node, Context& ctx, bool toplevel = false); Node eval_arguments(Node args, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx);
Node eval_function(string name, Node stm, Environment& bindings, Node_Factory& new_Node, Context& ctx, bool toplevel = false);
Node reduce(Node list, size_t head, Node acc, Node_Factory& new_Node);
Node accumulate(Node::Type op, Node acc, Node rhs, Node_Factory& new_Node); 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 op, double lhs, double rhs);
Node apply_mixin(Node mixin, const Node args, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool dynamic_scope = false); Node apply_mixin(Node mixin, const Node args, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool dynamic_scope = false);
Node apply_function(const Function& f, const Node args, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx); Node apply_function(const Function& f, const Node args, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, string& path, size_t line);
Node expand_selector(Node sel, Node pre, Node_Factory& new_Node); Node expand_selector(Node sel, Node pre, Node_Factory& new_Node);
Node expand_backref(Node sel, Node pre); Node expand_backref(Node sel, Node pre);
void extend(Node expr, multimap<Node, Node>& extension_requests, Node_Factory& new_Node);
void extend_selectors(vector<pair<Node, Node> >&, multimap<Node, Node>&, Node_Factory&); void extend_selectors(vector<pair<Node, Node> >&, multimap<Node, Node>&, Node_Factory&);
Node generate_extension(Node extendee, Node extender, Node_Factory& new_Node); Node generate_extension(Node extendee, Node extender, Node_Factory& new_Node);
......
#include <sstream> #include <sstream>
#include <algorithm> #include <algorithm>
#include <iostream>
#include "node.hpp" #include "node.hpp"
#include "constants.hpp"
#include "error.hpp" #include "error.hpp"
#include <iostream>
namespace Sass { namespace Sass {
using namespace std; using namespace std;
using namespace Constants;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Node method implementations // Node method implementations
...@@ -16,8 +18,9 @@ namespace Sass { ...@@ -16,8 +18,9 @@ namespace Sass {
switch (type()) switch (type())
{ {
case block: case block:
case expansion: case mixin_call:
case root: case root:
case if_directive:
case for_through_directive: case for_through_directive:
case for_to_directive: case for_to_directive:
case each_directive: case each_directive:
...@@ -31,8 +34,9 @@ namespace Sass { ...@@ -31,8 +34,9 @@ namespace Sass {
for (size_t i = 0; i < size(); ++i) { for (size_t i = 0; i < size(); ++i) {
switch (at(i).type()) switch (at(i).type())
{ {
case expansion: case mixin_call:
case block: case block:
case if_directive:
case for_through_directive: case for_through_directive:
case for_to_directive: case for_to_directive:
case each_directive: case each_directive:
...@@ -57,6 +61,18 @@ namespace Sass { ...@@ -57,6 +61,18 @@ namespace Sass {
string Node::unquote() const string Node::unquote() const
{ {
switch (type())
{
case string_constant:
case identifier: {
return token().unquote();
} break;
default: {
// do nothing; fall though to the rest
} break;
}
string intermediate(to_string()); string intermediate(to_string());
if (!intermediate.empty() && (intermediate[0] == '"' || intermediate[0] == '\'')) { if (!intermediate.empty() && (intermediate[0] == '"' || intermediate[0] == '\'')) {
return intermediate.substr(1, intermediate.length() - 2); return intermediate.substr(1, intermediate.length() - 2);
...@@ -70,8 +86,11 @@ namespace Sass { ...@@ -70,8 +86,11 @@ namespace Sass {
{ {
Type t = type(), u = rhs.type(); Type t = type(), u = rhs.type();
if ((t == identifier || t == string_constant || t == string_schema || t == concatenation) && // if ((t == identifier || t == string_constant || t == string_schema || t == concatenation) &&
(u == identifier || u == string_constant || u == string_schema || u == concatenation)) { // (u == identifier || u == string_constant || u == string_schema || u == concatenation)) {
// return unquote() == rhs.unquote();
// }
if (is_string() && rhs.is_string()) {
return unquote() == rhs.unquote(); return unquote() == rhs.unquote();
} }
else if (t != u) { else if (t != u) {
...@@ -80,12 +99,12 @@ namespace Sass { ...@@ -80,12 +99,12 @@ namespace Sass {
switch (t) switch (t)
{ {
case comma_list: case list:
case space_list:
case expression: case expression:
case term: case term:
case numeric_color: { case numeric_color: {
if (size() != rhs.size()) return false; if (size() != rhs.size()) return false;
if ((t == list) && (is_comma_separated() != rhs.is_comma_separated())) return false;
for (size_t i = 0, L = size(); i < L; ++i) { for (size_t i = 0, L = size(); i < L; ++i) {
if (at(i) == rhs[i]) continue; if (at(i) == rhs[i]) continue;
else return false; else return false;
...@@ -122,8 +141,25 @@ namespace Sass { ...@@ -122,8 +141,25 @@ namespace Sass {
return boolean_value() == rhs.boolean_value(); return boolean_value() == rhs.boolean_value();
} break; } break;
case selector: {
if (has_children() && rhs.has_children() && (size() == rhs.size())) {
for (size_t i = 0, S = size(); i < S; ++i) {
if (at(i) == rhs[i]) continue;
else return false;
}
return true;
}
else {
return false;
}
} break;
case simple_selector: {
if (token() == rhs.token()) return true;
} break;
default: { default: {
return true; return false;
} break; } break;
} }
return false; return false;
...@@ -159,12 +195,17 @@ namespace Sass { ...@@ -159,12 +195,17 @@ namespace Sass {
} }
// comparing identifiers and strings (treat them as comparable) // comparing identifiers and strings (treat them as comparable)
else if ((lhs_type == identifier || lhs_type == string_constant || lhs_type == value) && else if ((is_string() && rhs.is_string()) ||
(rhs_type == identifier || lhs_type == string_constant || rhs_type == value)) { (lhs_type == value && rhs_type == value)) {
return token().unquote() < rhs.token().unquote(); return unquote() < rhs.unquote();
} }
// COMPARING SELECTORS -- IMPORTANT FOR INHERITANCE // else if ((lhs_type == identifier || lhs_type == string_constant || lhs_type == value) &&
// (rhs_type == identifier || lhs_type == string_constant || rhs_type == value)) {
// return token().unquote() < rhs.token().unquote();
// }
// COMPARING SELECTORS -- IMPORTANT FOR ORDERING AND NORMALIZING
else if ((type() >= selector_group && type() <=selector_schema) && else if ((type() >= selector_group && type() <=selector_schema) &&
(rhs.type() >= selector_group && rhs.type() <=selector_schema)) { (rhs.type() >= selector_group && rhs.type() <=selector_schema)) {
...@@ -179,13 +220,15 @@ namespace Sass { ...@@ -179,13 +220,15 @@ namespace Sass {
return token() < rhs.token(); return token() < rhs.token();
} break; } break;
// assumes selectors are normalized by the time they're compared
case selector: case selector:
case attribute_selector: { case simple_selector_sequence:
case attribute_selector:
case functional_pseudo:
case pseudo_negation: {
return lexicographical_compare(begin(), end(), rhs.begin(), rhs.end()); return lexicographical_compare(begin(), end(), rhs.begin(), rhs.end());
} break; } break;
default: { default: {
return false; return false;
} break; } break;
...@@ -340,8 +383,6 @@ namespace Sass { ...@@ -340,8 +383,6 @@ namespace Sass {
return 0; return 0;
} }
extern const char percent_str[] = "%";
extern const char empty_str[] = "";
Token Node_Impl::unit() Token Node_Impl::unit()
{ {
switch (type) switch (type)
......
#define SASS_NODE_INCLUDED #define SASS_NODE
#include <cstring> #include <cstring>
#include <string> #include <string>
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
namespace Sass { namespace Sass {
using namespace std; using namespace std;
// Token type for representing lexed chunks of text
struct Token { struct Token {
const char* begin; const char* begin;
const char* end; const char* end;
...@@ -61,6 +62,7 @@ namespace Sass { ...@@ -61,6 +62,7 @@ namespace Sass {
struct Node_Impl; struct Node_Impl;
// Node type for representing SCSS expression nodes. Really just a handle.
class Node { class Node {
private: private:
friend class Node_Factory; friend class Node_Factory;
...@@ -69,6 +71,9 @@ namespace Sass { ...@@ -69,6 +71,9 @@ namespace Sass {
public: public:
enum Type { enum Type {
none, none,
any,
numeric, // number, numeric_percentage, or numeric_dimension
string_t, // string_constant, identifier, concatenation, schemata
comment, comment,
root, root,
...@@ -98,9 +103,7 @@ namespace Sass { ...@@ -98,9 +103,7 @@ namespace Sass {
rule, rule,
property, property,
nil, list,
comma_list,
space_list,
disjunction, disjunction,
conjunction, conjunction,
...@@ -128,7 +131,6 @@ namespace Sass { ...@@ -128,7 +131,6 @@ namespace Sass {
value, value,
identifier, identifier,
uri, uri,
image_url,
textual_percentage, textual_percentage,
textual_dimension, textual_dimension,
textual_number, textual_number,
...@@ -148,13 +150,15 @@ namespace Sass { ...@@ -148,13 +150,15 @@ namespace Sass {
identifier_schema, identifier_schema,
css_import, css_import,
function,
function_call, function_call,
mixin, mixin,
function, mixin_call,
parameters, parameters,
expansion,
arguments, arguments,
extend_directive,
if_directive, if_directive,
for_through_directive, for_through_directive,
for_to_directive, for_to_directive,
...@@ -175,6 +179,7 @@ namespace Sass { ...@@ -175,6 +179,7 @@ namespace Sass {
Node(Node_Impl* ip = 0); Node(Node_Impl* ip = 0);
Type type() const; Type type() const;
Type type(Type);
bool has_children() const; bool has_children() const;
bool has_statements() const; bool has_statements() const;
...@@ -183,11 +188,14 @@ namespace Sass { ...@@ -183,11 +188,14 @@ namespace Sass {
bool has_backref() const; bool has_backref() const;
bool from_variable() const; bool from_variable() const;
bool& should_eval() const; bool& should_eval() const;
bool& is_unquoted() const; // for strings bool& is_quoted() const;
bool& is_quoted() const; // for identifiers
bool is_numeric() const; bool is_numeric() const;
bool is_string() const; // for all string-like types
bool is_schema() const; // for all interpolated data
bool is_guarded() const; bool is_guarded() const;
bool& has_been_extended() const; bool& has_been_extended() const;
bool is_false() const;
bool& is_comma_separated() const;
string& path() const; string& path() const;
size_t line() const; size_t line() const;
...@@ -198,6 +206,7 @@ namespace Sass { ...@@ -198,6 +206,7 @@ namespace Sass {
Node& back() const; Node& back() const;
Node& operator[](size_t i) const; Node& operator[](size_t i) const;
void pop_back(); void pop_back();
void pop_all();
Node& push_back(Node n); Node& push_back(Node n);
Node& push_front(Node n); Node& push_front(Node n);
Node& operator<<(Node n); Node& operator<<(Node n);
...@@ -214,7 +223,7 @@ namespace Sass { ...@@ -214,7 +223,7 @@ namespace Sass {
Token token() const; Token token() const;
Token unit() const; Token unit() const;
bool is_null_ptr() const { return !ip_; } bool is_null() const { return !ip_; }
bool is(Node n) const { return ip_ == n.ip_; } bool is(Node n) const { return ip_ == n.ip_; }
void flatten(); void flatten();
...@@ -236,6 +245,7 @@ namespace Sass { ...@@ -236,6 +245,7 @@ namespace Sass {
}; };
// The actual implementation object for Nodes; Node handles point at these.
struct Node_Impl { struct Node_Impl {
union value_t { union value_t {
bool boolean; bool boolean;
...@@ -259,9 +269,9 @@ namespace Sass { ...@@ -259,9 +269,9 @@ namespace Sass {
bool has_backref; bool has_backref;
bool from_variable; bool from_variable;
bool should_eval; bool should_eval;
bool is_unquoted;
bool is_quoted; bool is_quoted;
bool has_been_extended; bool has_been_extended;
bool is_comma_separated;
Node_Impl() Node_Impl()
: /* value(value_t()), : /* value(value_t()),
...@@ -276,14 +286,53 @@ namespace Sass { ...@@ -276,14 +286,53 @@ namespace Sass {
has_backref(false), has_backref(false),
from_variable(false), from_variable(false),
should_eval(false), should_eval(false),
is_unquoted(false), // for strings is_quoted(false),
is_quoted(false), // for identifiers -- yeah, it's hacky for now has_been_extended(false),
has_been_extended(false) is_comma_separated(false)
{ } { }
bool is_numeric() bool is_numeric()
{ return type >= Node::number && type <= Node::numeric_dimension; } { return type >= Node::number && type <= Node::numeric_dimension; }
bool is_string()
{
switch (type)
{
case Node::string_t:
case Node::identifier:
case Node::value_schema:
case Node::identifier_schema:
case Node::string_constant:
case Node::string_schema:
case Node::concatenation: {
return true;
} break;
default: {
return false;
} break;
}
return false;
}
bool is_schema()
{
switch (type)
{
case Node::selector_schema:
case Node::value_schema:
case Node::string_schema:
case Node::identifier_schema: {
return true;
} break;
default: {
return false;
} break;
}
return false;
}
size_t size() size_t size()
{ return children.size(); } { return children.size(); }
...@@ -323,7 +372,7 @@ namespace Sass { ...@@ -323,7 +372,7 @@ namespace Sass {
case Node::for_to_directive: case Node::for_to_directive:
case Node::each_directive: case Node::each_directive:
case Node::while_directive: case Node::while_directive:
case Node::expansion: { case Node::mixin_call: {
has_expansions = true; has_expansions = true;
} break; } break;
...@@ -355,7 +404,7 @@ namespace Sass { ...@@ -355,7 +404,7 @@ namespace Sass {
case Node::for_to_directive: case Node::for_to_directive:
case Node::each_directive: case Node::each_directive:
case Node::while_directive: case Node::while_directive:
case Node::expansion: has_expansions = true; break; case Node::mixin_call: has_expansions = true; break;
case Node::backref: has_backref = true; break; case Node::backref: has_backref = true; break;
...@@ -367,6 +416,9 @@ namespace Sass { ...@@ -367,6 +416,9 @@ namespace Sass {
void pop_back() void pop_back()
{ children.pop_back(); } { children.pop_back(); }
void pop_all()
{ for (size_t i = 0, S = size(); i < S; ++i) pop_back(); }
bool& boolean_value() bool& boolean_value()
{ return value.boolean; } { return value.boolean; }
...@@ -382,9 +434,10 @@ namespace Sass { ...@@ -382,9 +434,10 @@ namespace Sass {
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
inline Node::Node(Node_Impl* ip) : ip_(ip) { } inline Node::Node(Node_Impl* ip) : ip_(ip) { }
inline Node::Type Node::type() const { return ip_->type; } inline Node::Type Node::type() const { return ip_->type; }
inline Node::Type Node::type(Type t) { return ip_->type = t; }
inline bool Node::has_children() const { return ip_->has_children; } inline bool Node::has_children() const { return ip_->has_children; }
inline bool Node::has_statements() const { return ip_->has_statements; } inline bool Node::has_statements() const { return ip_->has_statements; }
inline bool Node::has_blocks() const { return ip_->has_blocks; } inline bool Node::has_blocks() const { return ip_->has_blocks; }
...@@ -392,11 +445,14 @@ namespace Sass { ...@@ -392,11 +445,14 @@ namespace Sass {
inline bool Node::has_backref() const { return ip_->has_backref; } inline bool Node::has_backref() const { return ip_->has_backref; }
inline bool Node::from_variable() const { return ip_->from_variable; } inline bool Node::from_variable() const { return ip_->from_variable; }
inline bool& Node::should_eval() const { return ip_->should_eval; } inline bool& Node::should_eval() const { return ip_->should_eval; }
inline bool& Node::is_unquoted() const { return ip_->is_unquoted; }
inline bool& Node::is_quoted() const { return ip_->is_quoted; } inline bool& Node::is_quoted() const { return ip_->is_quoted; }
inline bool Node::is_numeric() const { return ip_->is_numeric(); } inline bool Node::is_numeric() const { return ip_->is_numeric(); }
inline bool Node::is_string() const { return ip_->is_string(); }
inline bool Node::is_schema() const { return ip_->is_schema(); }
inline bool Node::is_guarded() const { return (type() == assignment) && (size() == 3); } inline bool Node::is_guarded() const { return (type() == assignment) && (size() == 3); }
inline bool& Node::has_been_extended() const { return ip_->has_been_extended; } inline bool& Node::has_been_extended() const { return ip_->has_been_extended; }
inline bool Node::is_false() const { return (type() == boolean) && (boolean_value() == false); }
inline bool& Node::is_comma_separated() const { return ip_->is_comma_separated; }
inline string& Node::path() const { return ip_->path; } inline string& Node::path() const { return ip_->path; }
inline size_t Node::line() const { return ip_->line; } inline size_t Node::line() const { return ip_->line; }
...@@ -407,6 +463,7 @@ namespace Sass { ...@@ -407,6 +463,7 @@ namespace Sass {
inline Node& Node::back() const { return ip_->back(); } inline Node& Node::back() const { return ip_->back(); }
inline Node& Node::operator[](size_t i) const { return at(i); } inline Node& Node::operator[](size_t i) const { return at(i); }
inline void Node::pop_back() { ip_->pop_back(); } inline void Node::pop_back() { ip_->pop_back(); }
inline void Node::pop_all() { ip_->pop_all(); }
inline Node& Node::push_back(Node n) inline Node& Node::push_back(Node n)
{ {
ip_->push_back(n); ip_->push_back(n);
......
...@@ -19,6 +19,10 @@ namespace Sass { ...@@ -19,6 +19,10 @@ namespace Sass {
{ {
switch (type()) switch (type())
{ {
case none: {
return "";
} break;
case selector_group: case selector_group:
case media_expression_group: { // really only needed for arg to :not case media_expression_group: { // really only needed for arg to :not
string result(at(0).to_string()); string result(at(0).to_string());
...@@ -116,26 +120,19 @@ namespace Sass { ...@@ -116,26 +120,19 @@ namespace Sass {
return result; return result;
} break; } break;
case comma_list: { case list: {
if (size() == 0) return "";
string result(at(0).to_string()); string result(at(0).to_string());
for (size_t i = 1, S = size(); i < S; ++i) { for (size_t i = 1, S = size(); i < S; ++i) {
if (at(i).type() == nil) continue; if (at(i).is_null()) continue;
result += ", "; if (at(i).type() == list && at(i).size() == 0) continue;
result += at(i).to_string(); result += is_comma_separated() ? ", " : " ";
}
return result;
} break;
case space_list: {
string result(at(0).to_string());
for (size_t i = 1, S = size(); i < S; ++i) {
if (at(i).type() == nil) continue;
result += " ";
result += at(i).to_string(); result += at(i).to_string();
} }
return result; return result;
} break; } break;
// still necessary for unevaluated expressions
case expression: case expression:
case term: { case term: {
string result(at(0).to_string()); string result(at(0).to_string());
...@@ -274,13 +271,13 @@ namespace Sass { ...@@ -274,13 +271,13 @@ namespace Sass {
return result; return result;
} break; } break;
case expansion: { case mixin_call: {
// ignore it // ignore it
return ""; return "";
} break; } break;
case string_constant: { case string_constant: {
if (is_unquoted()) return token().unquote(); if (!is_quoted()) return token().unquote();
else { else {
string result(token().to_string()); string result(token().to_string());
if (result[0] != '"' && result[0] != '\'') return "\"" + result + "\""; if (result[0] != '"' && result[0] != '\'') return "\"" + result + "\"";
...@@ -329,35 +326,22 @@ namespace Sass { ...@@ -329,35 +326,22 @@ namespace Sass {
result += chunk; result += chunk;
} }
} }
if (is_unquoted()) result = result.substr(1, result.length() - 2); if (!is_quoted()) result = result.substr(1, result.length() - 2);
return result; return result;
} break; } break;
case concatenation: { case concatenation: {
string result; string result;
for (size_t i = 0, S = size(); i < S; ++i) { for (size_t i = 0, S = size(); i < S; ++i) {
result += at(i).to_string().substr(1, at(i).token().length()-2); result += at(i).unquote();
} }
// if (inside_of == identifier_schema || inside_of == property) return result; if (!(inside_of == identifier_schema || inside_of == property) && is_quoted()) {
// else return "\"" + result + "\"";
if (!(inside_of == identifier_schema || inside_of == property) && !is_unquoted()) {
result = "\"" + result + "\""; result = "\"" + result + "\"";
} }
return result; return result;
} break; } break;
case warning: { case warning: {
string prefix("WARNING: ");
string indent(" ");
Node contents(at(0));
string result(contents.to_string());
if (contents.type() == string_constant || contents.type() == string_schema) {
result = result.substr(1, result.size()-2); // unquote if it's a single string
}
// These cerrs aren't log lines! They're supposed to be here!
cerr << prefix << result << endl;
cerr << indent << "on line " << at(0).line() << " of " << at(0).path();
cerr << endl << endl;
return ""; return "";
} break; } break;
......
...@@ -27,6 +27,21 @@ namespace Sass { ...@@ -27,6 +27,21 @@ namespace Sass {
return ip_cpy; return ip_cpy;
} }
// returns a deep-copy of its argument, but uses the path and line that are passed in
Node_Impl* Node_Factory::alloc_Node_Impl(string& path, size_t line, 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)(path, line, n);
}
}
return ip_cpy;
}
// for cloning nodes // for cloning nodes
Node Node_Factory::operator()(const Node& n1) Node Node_Factory::operator()(const Node& n1)
{ {
...@@ -34,6 +49,15 @@ namespace Sass { ...@@ -34,6 +49,15 @@ namespace Sass {
return Node(ip_cpy); return Node(ip_cpy);
} }
// for cloning nodes and resetting their path and line-number fields
Node Node_Factory::operator()(string& path, size_t line, const Node& n1)
{
Node_Impl* ip_cpy = alloc_Node_Impl(path, line, n1.ip_); // deep-copy the implementation object
ip_cpy->path = path;
ip_cpy->line = line;
return Node(ip_cpy);
}
// for making leaf nodes out of terminals/tokens // for making leaf nodes out of terminals/tokens
Node Node_Factory::operator()(Node::Type type, string path, size_t line, Token t) Node Node_Factory::operator()(Node::Type type, string path, size_t line, Token t)
{ {
......
#define SASS_NODE_FACTORY
#include <vector> #include <vector>
#ifndef SASS_NODE_INCLUDED #ifndef SASS_NODE
#include "node.hpp" #include "node.hpp"
#endif #endif
...@@ -15,9 +17,11 @@ namespace Sass { ...@@ -15,9 +17,11 @@ namespace Sass {
Node_Impl* alloc_Node_Impl(Node::Type type, string file, size_t line); Node_Impl* alloc_Node_Impl(Node::Type type, string file, size_t line);
// returns a deep-copy of its argument // returns a deep-copy of its argument
Node_Impl* alloc_Node_Impl(Node_Impl* ip); Node_Impl* alloc_Node_Impl(Node_Impl* ip);
Node_Impl* alloc_Node_Impl(string& path, size_t line, Node_Impl* ip);
public: public:
// for cloning nodes // for cloning nodes
Node operator()(const Node& n1); Node operator()(const Node& n1);
Node operator()(string& path, size_t line, const Node& n1);
// for making leaf nodes out of terminals/tokens // for making leaf nodes out of terminals/tokens
Node operator()(Node::Type type, string file, size_t line, Token t); Node operator()(Node::Type type, string file, size_t line, Token t);
// for making boolean values or interior nodes that have children // for making boolean values or interior nodes that have children
......
#define SASS_PRELEXER_INCLUDED #define SASS_PRELEXER
namespace Sass { namespace Sass {
namespace Prelexer { namespace Prelexer {
...@@ -305,6 +305,10 @@ namespace Sass { ...@@ -305,6 +305,10 @@ namespace Sass {
// Match interpolant schemas // Match interpolant schemas
const char* identifier_schema(const char* src); const char* identifier_schema(const char* src);
const char* value_schema(const char* src); const char* value_schema(const char* src);
const char* filename(const char* src);
const char* filename_schema(const char* src);
const char* url_schema(const char* src);
const char* url_value(const char* src);
// Match CSS '@' keywords. // Match CSS '@' keywords.
const char* at_keyword(const char* src); const char* at_keyword(const char* src);
const char* import(const char* src); const char* import(const char* src);
...@@ -354,8 +358,7 @@ namespace Sass { ...@@ -354,8 +358,7 @@ namespace Sass {
// Match CSS uri specifiers. // Match CSS uri specifiers.
const char* uri_prefix(const char* src); const char* uri_prefix(const char* src);
const char* uri(const char* src); const char* uri(const char* src);
// Match SCSS image-url function. const char* url(const char* src);
const char* image_url_prefix(const char* src);
// Match CSS "!important" keyword. // Match CSS "!important" keyword.
const char* important(const char* src); const char* important(const char* src);
// Match Sass "!default" keyword. // Match Sass "!default" keyword.
...@@ -385,11 +388,11 @@ namespace Sass { ...@@ -385,11 +388,11 @@ namespace Sass {
const char* variable(const char* src); const char* variable(const char* src);
// Match Sass boolean keywords. // Match Sass boolean keywords.
const char* true_kwd(const char* src); const char* true_val(const char* src);
const char* false_kwd(const char* src); const char* false_val(const char* src);
const char* and_kwd(const char* src); const char* and_op(const char* src);
const char* or_kwd(const char* src); const char* or_op(const char* src);
const char* not_kwd(const char* src); const char* not_op(const char* src);
const char* eq_op(const char* src); const char* eq_op(const char* src);
const char* neq_op(const char* src); const char* neq_op(const char* src);
const char* gt_op(const char* src); const char* gt_op(const char* src);
...@@ -444,6 +447,5 @@ namespace Sass { ...@@ -444,6 +447,5 @@ namespace Sass {
} }
return counter; return counter;
} }
} }
} }
#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <cstdlib> #include <cstdlib>
#include <unistd.h>
#include <iostream> #include <iostream>
#include "document.hpp" #include "document.hpp"
#include "eval_apply.hpp" #include "eval_apply.hpp"
...@@ -41,13 +46,14 @@ extern "C" { ...@@ -41,13 +46,14 @@ extern "C" {
{ {
using namespace Sass; using namespace Sass;
doc.parse_scss(); doc.parse_scss();
eval(doc.root, expand(doc.root,
doc.context.new_Node(Node::none, doc.path, doc.line, 0), Node(),
doc.context.global_env, doc.context.global_env,
doc.context.function_env, doc.context.function_env,
doc.context.new_Node, doc.context.new_Node,
doc.context); doc.context);
extend_selectors(doc.context.pending_extensions, doc.context.extensions, doc.context.new_Node); // extend_selectors(doc.context.pending_extensions, doc.context.extensions, doc.context.new_Node);
if (doc.context.has_extensions) extend(doc.root, doc.context.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)));
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());
......
#include <set>
#include "selector.hpp"
namespace Sass {
using namespace std;
Node normalize_selector(Node s, Node_Factory& new_Node)
{
switch (s.type())
{
case Node::selector_group: {
Node normalized(new_Node(Node::selector_group, s.path(), s.line(), 1));
set<Node> normalizer;
for (size_t i = 0, S = s.size(); i < S; ++i)
normalizer.insert(normalize_selector(s[i], new_Node));
for (set<Node>::iterator i = normalizer.begin(); i != normalizer.end(); ++i)
normalized << *i;
return normalized;
} break;
case Node::selector: {
Node normalized(new_Node(Node::selector, s.path(), s.line(), s.size()));
for (size_t i = 0, S = s.size(); i < S; ++i)
normalized << normalize_selector(s[i], new_Node);
return normalized;
} break;
case Node::simple_selector_sequence: {
Node normalized(new_Node(Node::simple_selector_sequence, s.path(), s.line(), 1));
set<Node> normalizer;
size_t i = 0;
if (!selector_is_qualifier(s[0])) {
normalized << s[0];
i = 1;
}
for (size_t S = s.size(); i < S; ++i)
normalizer.insert(normalize_selector(s[i], new_Node));
for (set<Node>::iterator i = normalizer.begin(); i != normalizer.end(); ++i)
normalized << *i;
return normalized;
} break;
default: {
return s;
} break;
}
return s;
}
// Remove duplicate selectors from a selector group. Used when extending.
Node remove_duplicate_selectors(Node group, Node_Factory& new_Node)
{
if (group.type() != Node::selector_group) return group;
Node filtered(new_Node(Node::selector_group, group.path(), group.line(), 1));
for (size_t i = 0, S = group.size(); i < S; ++i) {
bool found_dup = false;
for (size_t j = 0; j < filtered.size(); ++j) {
if (group[i] == filtered[j]) {
found_dup = true;
break;
}
}
if (!found_dup) filtered << group[i];
}
return filtered;
}
bool selector_is_qualifier(Node s)
{
switch (s.type())
{
case Node::pseudo:
case Node::pseudo_negation:
case Node::functional_pseudo:
case Node::attribute_selector: {
return true;
} break;
case Node::simple_selector: {
if ((*s.token().begin == '.') || (*s.token().begin == '#')) return true;
} break;
default: {
return false;
} break;
}
return false;
}
// Node selector_is_specialization_of(Node s, Node t)
// {
// }
}
\ No newline at end of file
#ifndef SASS_NODE
#include "node.hpp"
#endif
#ifndef SASS_NODE_FACTORY
#include "node_factory.hpp"
#endif
namespace Sass {
Node normalize_selector(Node s, Node_Factory& new_Node);
Node remove_duplicate_selectors(Node group, Node_Factory& new_Node);
bool selector_is_qualifier(Node s);
}
\ No newline at end of file
#if _MSC_VER >= 1600
#include <unordered_map>
#else
#include <tr1/unordered_map>
#endif
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <tr1/unordered_map>
#include <map> #include <map>
#include <algorithm> #include <algorithm>
#ifndef SASS_NODE_INCLUDED #ifndef SASS_NODE
#include "node.hpp" #include "node.hpp"
#endif #endif
......
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