Commit f0f9eab1 by Aaron Leung

Merge branch 'master' into func_resolver

Conflicts:
	functions.cpp
parents eb153df1 d5875e5e
......@@ -153,7 +153,7 @@ namespace Sass {
"yellowgreen",
// sentinel value
0
}
};
const double color_values[] =
{
......@@ -306,6 +306,6 @@ namespace Sass {
0x9a, 0xcd, 0x32,
// sentinel value
0xfff
}
};
}
\ No newline at end of file
#include "context.hpp"
#include <cstring>
#include <iostream>
#include <unistd.h>
#include "prelexer.hpp"
#include "color_names.hpp"
using std::cerr; using std::endl;
namespace Sass {
......@@ -40,19 +42,28 @@ namespace Sass {
// }
}
Context::Context(const char* paths_str)
Context::Context(const char* paths_str, const char* img_path_str)
: global_env(Environment()),
function_env(map<string, Function>()),
extensions(multimap<Node, Node>()),
pending_extensions(vector<pair<Node, Node> >()),
source_refs(vector<char*>()),
include_paths(vector<string>()),
color_names_to_values(map<string, Node>()),
color_values_to_names(map<Node, string>()),
new_Node(Node_Factory()),
image_path(0),
ref_count(0),
has_extensions(false)
{
register_functions();
collect_include_paths(paths_str);
setup_color_map();
string path_string(img_path_str ? img_path_str : "");
path_string = "'" + path_string + "/'";
image_path = new char[path_string.length() + 1];
std::strcpy(image_path, path_string.c_str());
}
Context::~Context()
......@@ -60,7 +71,7 @@ namespace Sass {
for (size_t i = 0; i < source_refs.size(); ++i) {
delete[] source_refs[i];
}
delete[] image_path;
new_Node.free();
// cerr << "Deallocated " << i << " source string(s)." << endl;
}
......@@ -148,6 +159,23 @@ namespace Sass {
register_function(comparable_descriptor, comparable);
// Boolean Functions
register_function(not_descriptor, not_impl);
register_function(if_descriptor, if_impl);
}
void Context::setup_color_map()
{
size_t i = 0;
while (color_names[i]) {
string name(color_names[i]);
Node value(new_Node("[COLOR TABLE]", 0,
color_values[i*3],
color_values[i*3+1],
color_values[i*3+2],
1));
color_names_to_values[name] = value;
color_values_to_names[value] = name;
++i;
}
}
}
......@@ -47,20 +47,24 @@ namespace Sass {
vector<pair<Node, Node> > pending_extensions;
vector<char*> source_refs; // all the source c-strings
vector<string> include_paths;
map<string, Node> color_names_to_values;
map<Node, string> color_values_to_names;
Node_Factory new_Node;
char* image_path;
size_t ref_count;
string sass_path;
string css_path;
// string sass_path;
// string css_path;
bool has_extensions;
void collect_include_paths(const char* paths_str);
Context(const char* paths_str = 0);
Context(const char* paths_str = 0, const char* img_path_str = 0);
~Context();
void register_function(Function_Descriptor d, Primitive ip);
void register_function(Function_Descriptor d, Primitive ip, size_t arity);
void register_overload_stub(string name);
void register_functions();
void setup_color_map();
};
}
......@@ -5,6 +5,7 @@
#include "error.hpp"
#include <iostream>
#include <sstream>
#include <sys/stat.h>
namespace Sass {
......@@ -30,28 +31,28 @@ namespace Sass {
{
std::FILE *f;
const char* path_str = path.c_str();
f = std::fopen(path_str, "rb");
if (!f) {
string path_with_extension(path + ".scss");
f = std::fopen(path_with_extension.c_str(), "rb");
if (!f) {
const char* file_name_str = Prelexer::folders(path_str);
string path_with_underscore(Token::make(path_str, file_name_str).to_string() +
struct stat st;
string tmp;
if (stat(path_str, &st) == -1 || S_ISDIR(st.st_mode)) {
tmp = path + ".scss";
path_str = tmp.c_str();
if (stat(path_str, &st) == -1 || S_ISDIR(st.st_mode)) {
const char *full_path_str = path.c_str();
const char *file_name_str = Prelexer::folders(full_path_str);
tmp = Token::make(full_path_str, file_name_str).to_string() +
"_" +
Token::make(file_name_str).to_string());
f = std::fopen(path_with_underscore.c_str(), "rb");
if (!f) {
string path_with_underscore_and_extension(path_with_underscore + ".scss");
f = std::fopen(path_with_underscore_and_extension.c_str(), "rb");
if (!f) throw path;
string(file_name_str);
path_str = tmp.c_str();
if (stat(path_str, &st) == -1 || S_ISDIR(st.st_mode)) {
tmp = tmp + ".scss";
path_str = tmp.c_str();
if (stat(path_str, &st) == -1 || S_ISDIR(st.st_mode))
throw path;
}
}
}
if (std::fseek(f, 0, SEEK_END)) throw path;
int status = std::ftell(f);
if (status < 0) throw path;
size_t len = status;
std::rewind(f);
f = std::fopen(path_str, "rb");
size_t len = st.st_size;
char* source = new char[len + 1];
size_t bytes_read = std::fread(source, sizeof(char), len, f);
if (bytes_read != len) {
......@@ -61,6 +62,8 @@ namespace Sass {
source[len] = '\0';
char* end = source + len;
if (std::fclose(f)) throw path;
const char *file_name_str = Prelexer::folders(path_str);
string include_path(path_str, file_name_str - path_str);
Document doc(ctx);
doc.path = path;
......@@ -72,6 +75,9 @@ namespace Sass {
doc.end = end;
doc.position = source;
doc.context.source_refs.push_back(source);
if (!include_path.empty()) {
doc.context.include_paths.push_back(include_path);
}
return doc;
}
......@@ -136,7 +142,8 @@ namespace Sass {
// trim trailing whitespace
if (!retval.empty()) {
size_t newlines = 0;
for (size_t i = retval.length() - 1; i >= 0; --i) {
size_t i = retval.length();
while (i--) {
if (retval[i] == '\n') {
++newlines;
continue;
......
......@@ -101,17 +101,16 @@ namespace Sass {
if (!lex< string_constant >()) throw_syntax_error("@import directive requires a url or quoted path");
// TO DO: BETTER PATH HANDLING
string import_path(lexed.unquote());
const char* curr_path_start = path.c_str();
const char* curr_path_end = folders(curr_path_start);
string current_path(curr_path_start, curr_path_end - curr_path_start);
for (vector<string>::iterator path = context.include_paths.begin(); path < context.include_paths.end(); ++path) {
try {
Document importee(Document::make_from_file(context, current_path + import_path));
Document importee(Document::make_from_file(context, *path + import_path));
importee.parse_scss();
return importee.root;
}
catch (string& path) {
throw_read_error("error reading file \"" + path + "\"");
}
}
throw_read_error("error reading file \"" + import_path + "\"");
// unreached statement
return Node();
}
......@@ -814,14 +813,26 @@ namespace Sass {
const char* value = position;
const char* rparen = find_first< exactly<')'> >(position);
if (!rparen) throw_syntax_error("URI is missing ')'");
Token contents(Token::make(value, rparen));
Token content_tok(Token::make(value, rparen));
Node content_node(context.new_Node(Node::string_constant, path, line, content_tok));
// lex< string_constant >();
Node result(context.new_Node(Node::uri, path, line, contents));
Node result(context.new_Node(Node::uri, path, line, 1));
result << content_node;
position = rparen;
lex< exactly<')'> >();
return result;
}
if (lex< image_url_prefix >())
{
Node url(parse_value());
if (!lex< exactly<')'> >()) throw_syntax_error("call to image-url is missing ')'");
Node the_call(context.new_Node(Node::image_url, path, line, 1));
the_call << url;
the_call.should_eval() = true;
return the_call;
}
if (peek< functional >())
{ return parse_function_call(); }
......
......@@ -2,6 +2,7 @@
#include "eval_apply.hpp"
#include "document.hpp"
#include "error.hpp"
#include <cctype>
#include <iostream>
#include <sstream>
#include <cstdlib>
......@@ -19,7 +20,7 @@ namespace Sass {
// Evaluate the parse tree in-place (mostly). Most nodes will be left alone.
Node eval(Node expr, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx)
Node eval(Node expr, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool function_name)
{
switch (expr.type())
{
......@@ -288,11 +289,21 @@ namespace Sass {
return env[expr.token()];
} break;
case Node::image_url: {
Node base(eval(expr[0], prefix, env, f_env, new_Node, ctx));
Node prefix(new_Node(Node::identifier, base.path(), base.line(), Token::make(ctx.image_path)));
Node fullpath(new_Node(Node::concatenation, base.path(), base.line(), 2));
Node url(new_Node(Node::uri, base.path(), base.line(), 1));
fullpath << prefix << base;
url << fullpath;
return url;
} break;
case Node::function_call: {
// TO DO: default-constructed Function should be a generic callback (maybe)
// eval the function name in case it's interpolated
expr[0] = eval(expr[0], prefix, env, f_env, new_Node, ctx);
expr[0] = eval(expr[0], prefix, env, f_env, new_Node, ctx, true);
string name(expr[0].to_string());
if (!f_env.count(name)) {
// no definition available; just pass it through (with evaluated args)
......@@ -338,6 +349,17 @@ namespace Sass {
}
} break;
case Node::identifier: {
string id_str(expr.to_string());
to_lowercase(id_str);
if (!function_name && ctx.color_names_to_values.count(id_str)) {
return ctx.color_names_to_values[id_str];
}
else {
return expr;
}
} break;
case Node::string_schema:
case Node::value_schema:
case Node::identifier_schema: {
......@@ -1258,4 +1280,7 @@ namespace Sass {
Node selector_butlast(Node sel, Node_Factory& new_Node)
{ return selector_but(sel, new_Node, 0, 1); }
void to_lowercase(string& s)
{ for (size_t i = 0, L = s.length(); i < L; ++i) s[i] = tolower(s[i]); }
}
......@@ -11,7 +11,7 @@
namespace Sass {
using std::map;
Node eval(Node expr, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx);
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 accumulate(Node::Type op, Node acc, Node rhs, Node_Factory& new_Node);
double operate(Node::Type op, double lhs, double rhs);
......@@ -29,4 +29,5 @@ namespace Sass {
Node selector_butfirst(Node sel, Node_Factory& new_Node);
Node selector_butlast(Node sel, Node_Factory& new_Node);
void to_lowercase(string& s);
}
\ No newline at end of file
......@@ -199,6 +199,9 @@ namespace Sass {
extern Function_Descriptor not_descriptor;
Node not_impl(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor if_descriptor;
Node if_impl(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
}
}
......@@ -128,6 +128,7 @@ namespace Sass {
value,
identifier,
uri,
image_url,
textual_percentage,
textual_dimension,
textual_number,
......@@ -182,8 +183,8 @@ namespace Sass {
bool has_backref() const;
bool from_variable() const;
bool& should_eval() const;
bool& is_unquoted() const;
bool& is_quoted() const;
bool& is_unquoted() const; // for strings
bool& is_quoted() const; // for identifiers
bool is_numeric() const;
bool is_guarded() const;
bool& has_been_extended() const;
......
......@@ -268,7 +268,8 @@ namespace Sass {
case uri: {
string result("url(");
result += token().to_string();
// result += token().to_string();
result += at(0).to_string();
result += ")";
return result;
} break;
......
......@@ -278,6 +278,11 @@ namespace Sass {
optional<spaces>,
exactly<')'> >(src);
}
// Match SCSS image-url function
extern const char image_url_kwd[] = "image-url(";
const char* image_url_prefix(const char* src) {
return exactly<image_url_kwd>(src);
}
// Match CSS "!important" keyword.
extern const char important_kwd[] = "important";
const char* important(const char* src) {
......
......@@ -354,6 +354,8 @@ namespace Sass {
// Match CSS uri specifiers.
const char* uri_prefix(const char* src);
const char* uri(const char* src);
// Match SCSS image-url function.
const char* image_url_prefix(const char* src);
// Match CSS "!important" keyword.
const char* important(const char* src);
// Match Sass "!default" keyword.
......
......@@ -58,7 +58,8 @@ extern "C" {
{
using namespace Sass;
try {
Context cpp_ctx(c_ctx->options.include_paths);
Context cpp_ctx(c_ctx->options.include_paths, c_ctx->options.image_path);
// cpp_ctx.image_path = c_ctx->options.image_path;
// 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);
......@@ -93,8 +94,11 @@ extern "C" {
{
using namespace Sass;
try {
Context cpp_ctx(c_ctx->options.include_paths);
Context cpp_ctx(c_ctx->options.include_paths, c_ctx->options.image_path);
// Document doc(c_ctx->input_path, 0, cpp_ctx);
// string path_string(c_ctx->options.image_path);
// path_string = "'" + path_string + "/";
// cpp_ctx.image_path = c_ctx->options.image_path;
Document doc(Document::make_from_file(cpp_ctx, string(c_ctx->input_path)));
// cerr << "MADE A DOC AND CONTEXT OBJ" << endl;
// cerr << "REGISTRY: " << doc.context.registry.size() << endl;
......
......@@ -10,6 +10,7 @@ extern "C" {
struct sass_options {
int output_style;
char* include_paths;
char* image_path;
};
struct sass_context {
......
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