Commit 4b86ac98 by Dean Mao

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

parents ba80ff04 b3e8d772
#define SASS_COLOR_NAMES_INCLUDED
namespace Sass {
const char* color_names[] =
{
"aliceblue",
"antiquewhite",
"aqua",
"aquamarine",
"azure",
"beige",
"bisque",
"black",
"blanchedalmond",
"blue",
"blueviolet",
"brown",
"burlywood",
"cadetblue",
"chartreuse",
"chocolate",
"coral",
"cornflowerblue",
"cornsilk",
"crimson",
"cyan",
"darkblue",
"darkcyan",
"darkgoldenrod",
"darkgray",
"darkgrey",
"darkgreen",
"darkkhaki",
"darkmagenta",
"darkolivegreen",
"darkorange",
"darkorchid",
"darkred",
"darksalmon",
"darkseagreen",
"darkslateblue",
"darkslategray",
"darkslategrey",
"darkturquoise",
"darkviolet",
"deeppink",
"deepskyblue",
"dimgray",
"dimgrey",
"dodgerblue",
"firebrick",
"floralwhite",
"forestgreen",
"fuchsia",
"gainsboro",
"ghostwhite",
"gold",
"goldenrod",
"gray",
"grey",
"green",
"greenyellow",
"honeydew",
"hotpink",
"indianred",
"indigo",
"ivory",
"khaki",
"lavender",
"lavenderblush",
"lawngreen",
"lemonchiffon",
"lightblue",
"lightcoral",
"lightcyan",
"lightgoldenrodyellow",
"lightgray",
"lightgrey",
"lightgreen",
"lightpink",
"lightsalmon",
"lightseagreen",
"lightskyblue",
"lightslategray",
"lightslategrey",
"lightsteelblue",
"lightyellow",
"lime",
"limegreen",
"linen",
"magenta",
"maroon",
"mediumaquamarine",
"mediumblue",
"mediumorchid",
"mediumpurple",
"mediumseagreen",
"mediumslateblue",
"mediumspringgreen",
"mediumturquoise",
"mediumvioletred",
"midnightblue",
"mintcream",
"mistyrose",
"moccasin",
"navajowhite",
"navy",
"oldlace",
"olive",
"olivedrab",
"orange",
"orangered",
"orchid",
"palegoldenrod",
"palegreen",
"paleturquoise",
"palevioletred",
"papayawhip",
"peachpuff",
"peru",
"pink",
"plum",
"powderblue",
"purple",
"red",
"rosybrown",
"royalblue",
"saddlebrown",
"salmon",
"sandybrown",
"seagreen",
"seashell",
"sienna",
"silver",
"skyblue",
"slateblue",
"slategray",
"slategrey",
"snow",
"springgreen",
"steelblue",
"tan",
"teal",
"thistle",
"tomato",
"turquoise",
"violet",
"wheat",
"white",
"whitesmoke",
"yellow",
"yellowgreen",
// sentinel value
0
};
const double color_values[] =
{
0xf0, 0xf8, 0xff,
0xfa, 0xeb, 0xd7,
0x00, 0xff, 0xff,
0x7f, 0xff, 0xd4,
0xf0, 0xff, 0xff,
0xf5, 0xf5, 0xdc,
0xff, 0xe4, 0xc4,
0x00, 0x00, 0x00,
0xff, 0xeb, 0xcd,
0x00, 0x00, 0xff,
0x8a, 0x2b, 0xe2,
0xa5, 0x2a, 0x2a,
0xde, 0xb8, 0x87,
0x5f, 0x9e, 0xa0,
0x7f, 0xff, 0x00,
0xd2, 0x69, 0x1e,
0xff, 0x7f, 0x50,
0x64, 0x95, 0xed,
0xff, 0xf8, 0xdc,
0xdc, 0x14, 0x3c,
0x00, 0xff, 0xff,
0x00, 0x00, 0x8b,
0x00, 0x8b, 0x8b,
0xb8, 0x86, 0x0b,
0xa9, 0xa9, 0xa9,
0xa9, 0xa9, 0xa9,
0x00, 0x64, 0x00,
0xbd, 0xb7, 0x6b,
0x8b, 0x00, 0x8b,
0x55, 0x6b, 0x2f,
0xff, 0x8c, 0x00,
0x99, 0x32, 0xcc,
0x8b, 0x00, 0x00,
0xe9, 0x96, 0x7a,
0x8f, 0xbc, 0x8f,
0x48, 0x3d, 0x8b,
0x2f, 0x4f, 0x4f,
0x2f, 0x4f, 0x4f,
0x00, 0xce, 0xd1,
0x94, 0x00, 0xd3,
0xff, 0x14, 0x93,
0x00, 0xbf, 0xff,
0x69, 0x69, 0x69,
0x69, 0x69, 0x69,
0x1e, 0x90, 0xff,
0xb2, 0x22, 0x22,
0xff, 0xfa, 0xf0,
0x22, 0x8b, 0x22,
0xff, 0x00, 0xff,
0xdc, 0xdc, 0xdc,
0xf8, 0xf8, 0xff,
0xff, 0xd7, 0x00,
0xda, 0xa5, 0x20,
0x80, 0x80, 0x80,
0x80, 0x80, 0x80,
0x00, 0x80, 0x00,
0xad, 0xff, 0x2f,
0xf0, 0xff, 0xf0,
0xff, 0x69, 0xb4,
0xcd, 0x5c, 0x5c,
0x4b, 0x00, 0x82,
0xff, 0xff, 0xf0,
0xf0, 0xe6, 0x8c,
0xe6, 0xe6, 0xfa,
0xff, 0xf0, 0xf5,
0x7c, 0xfc, 0x00,
0xff, 0xfa, 0xcd,
0xad, 0xd8, 0xe6,
0xf0, 0x80, 0x80,
0xe0, 0xff, 0xff,
0xfa, 0xfa, 0xd2,
0xd3, 0xd3, 0xd3,
0xd3, 0xd3, 0xd3,
0x90, 0xee, 0x90,
0xff, 0xb6, 0xc1,
0xff, 0xa0, 0x7a,
0x20, 0xb2, 0xaa,
0x87, 0xce, 0xfa,
0x77, 0x88, 0x99,
0x77, 0x88, 0x99,
0xb0, 0xc4, 0xde,
0xff, 0xff, 0xe0,
0x00, 0xff, 0x00,
0x32, 0xcd, 0x32,
0xfa, 0xf0, 0xe6,
0xff, 0x00, 0xff,
0x80, 0x00, 0x00,
0x66, 0xcd, 0xaa,
0x00, 0x00, 0xcd,
0xba, 0x55, 0xd3,
0x93, 0x70, 0xd8,
0x3c, 0xb3, 0x71,
0x7b, 0x68, 0xee,
0x00, 0xfa, 0x9a,
0x48, 0xd1, 0xcc,
0xc7, 0x15, 0x85,
0x19, 0x19, 0x70,
0xf5, 0xff, 0xfa,
0xff, 0xe4, 0xe1,
0xff, 0xe4, 0xb5,
0xff, 0xde, 0xad,
0x00, 0x00, 0x80,
0xfd, 0xf5, 0xe6,
0x80, 0x80, 0x00,
0x6b, 0x8e, 0x23,
0xff, 0xa5, 0x00,
0xff, 0x45, 0x00,
0xda, 0x70, 0xd6,
0xee, 0xe8, 0xaa,
0x98, 0xfb, 0x98,
0xaf, 0xee, 0xee,
0xd8, 0x70, 0x93,
0xff, 0xef, 0xd5,
0xff, 0xda, 0xb9,
0xcd, 0x85, 0x3f,
0xff, 0xc0, 0xcb,
0xdd, 0xa0, 0xdd,
0xb0, 0xe0, 0xe6,
0x80, 0x00, 0x80,
0xff, 0x00, 0x00,
0xbc, 0x8f, 0x8f,
0x41, 0x69, 0xe1,
0x8b, 0x45, 0x13,
0xfa, 0x80, 0x72,
0xf4, 0xa4, 0x60,
0x2e, 0x8b, 0x57,
0xff, 0xf5, 0xee,
0xa0, 0x52, 0x2d,
0xc0, 0xc0, 0xc0,
0x87, 0xce, 0xeb,
0x6a, 0x5a, 0xcd,
0x70, 0x80, 0x90,
0x70, 0x80, 0x90,
0xff, 0xfa, 0xfa,
0x00, 0xff, 0x7f,
0x46, 0x82, 0xb4,
0xd2, 0xb4, 0x8c,
0x00, 0x80, 0x80,
0xd8, 0xbf, 0xd8,
0xff, 0x63, 0x47,
0x40, 0xe0, 0xd0,
0xee, 0x82, 0xee,
0xf5, 0xde, 0xb3,
0xff, 0xff, 0xff,
0xf5, 0xf5, 0xf5,
0xff, 0xff, 0x00,
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<pair<string, size_t>, Function>()),
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);
path_string = "'" + path_string + "/'";
image_path = new char[path_string.length() + 1];
std::strcpy(image_path, path_string.c_str());
}
Context::~Context()
......@@ -60,21 +71,28 @@ 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;
}
inline void Context::register_function(Function_Descriptor d, Primitive ip)
{
Function f(d, ip);
function_env[pair<string, size_t>(f.name, f.parameters.size())] = f;
Function f(d, ip, new_Node);
// function_env[pair<string, size_t>(f.name, f.parameters.size())] = f;
function_env[f.name] = f;
}
inline void Context::register_function(Function_Descriptor d, Primitive ip, size_t arity)
{
Function f(d, ip);
function_env[pair<string, size_t>(f.name, arity)] = f;
Function f(d, ip, new_Node);
// function_env[pair<string, size_t>(f.name, arity)] = f;
function_env[f.name] = f;
}
inline void Context::register_overload_stub(string name)
{
function_env[name] = Function(name, true);
}
void Context::register_functions()
......@@ -82,11 +100,13 @@ namespace Sass {
using namespace Functions;
// RGB Functions
register_function(rgb_descriptor, rgb);
register_overload_stub("rgba");
register_function(rgba_4_descriptor, rgba_4);
register_function(rgba_2_descriptor, rgba_2);
register_function(red_descriptor, red);
register_function(green_descriptor, green);
register_function(blue_descriptor, blue);
register_overload_stub("mix");
register_function(mix_2_descriptor, mix_2);
register_function(mix_3_descriptor, mix_3);
// HSL Functions
......@@ -112,10 +132,13 @@ namespace Sass {
// List Functions
register_function(length_descriptor, length);
register_function(nth_descriptor, nth);
register_overload_stub("join");
register_function(join_2_descriptor, join_2);
register_function(join_3_descriptor, join_3);
register_overload_stub("append");
register_function(append_2_descriptor, append_2);
register_function(append_3_descriptor, append_3);
register_overload_stub("compact");
register_function(compact_1_descriptor, compact);
register_function(compact_2_descriptor, compact);
register_function(compact_3_descriptor, compact);
......@@ -126,6 +149,8 @@ namespace Sass {
register_function(compact_8_descriptor, compact);
register_function(compact_9_descriptor, compact);
register_function(compact_10_descriptor, compact);
register_function(compact_11_descriptor, compact);
register_function(compact_12_descriptor, compact);
// Introspection Functions
register_function(type_of_descriptor, type_of);
register_function(unit_descriptor, unit);
......@@ -135,4 +160,20 @@ namespace Sass {
register_function(not_descriptor, not_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;
}
}
}
......@@ -42,24 +42,29 @@ namespace Sass {
struct Context {
Environment global_env;
map<pair<string, size_t>, Function> function_env;
map<string, Function> function_env;
multimap<Node, Node> extensions;
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();
};
}
AliceBlue #F0F8FF
AntiqueWhite #FAEBD7
Aqua #00FFFF
Aquamarine #7FFFD4
Azure #F0FFFF
Beige #F5F5DC
Bisque #FFE4C4
Black #000000
BlanchedAlmond #FFEBCD
Blue #0000FF
BlueViolet #8A2BE2
Brown #A52A2A
BurlyWood #DEB887
CadetBlue #5F9EA0
Chartreuse #7FFF00
Chocolate #D2691E
Coral #FF7F50
CornflowerBlue #6495ED
Cornsilk #FFF8DC
Crimson #DC143C
Cyan #00FFFF
DarkBlue #00008B
DarkCyan #008B8B
DarkGoldenRod #B8860B
DarkGray #A9A9A9
DarkGrey #A9A9A9
DarkGreen #006400
DarkKhaki #BDB76B
DarkMagenta #8B008B
DarkOliveGreen #556B2F
Darkorange #FF8C00
DarkOrchid #9932CC
DarkRed #8B0000
DarkSalmon #E9967A
DarkSeaGreen #8FBC8F
DarkSlateBlue #483D8B
DarkSlateGray #2F4F4F
DarkSlateGrey #2F4F4F
DarkTurquoise #00CED1
DarkViolet #9400D3
DeepPink #FF1493
DeepSkyBlue #00BFFF
DimGray #696969
DimGrey #696969
DodgerBlue #1E90FF
FireBrick #B22222
FloralWhite #FFFAF0
ForestGreen #228B22
Fuchsia #FF00FF
Gainsboro #DCDCDC
GhostWhite #F8F8FF
Gold #FFD700
GoldenRod #DAA520
Gray #808080
Grey #808080
Green #008000
GreenYellow #ADFF2F
HoneyDew #F0FFF0
HotPink #FF69B4
IndianRed #CD5C5C
Indigo #4B0082
Ivory #FFFFF0
Khaki #F0E68C
Lavender #E6E6FA
LavenderBlush #FFF0F5
LawnGreen #7CFC00
LemonChiffon #FFFACD
LightBlue #ADD8E6
LightCoral #F08080
LightCyan #E0FFFF
LightGoldenRodYellow #FAFAD2
LightGray #D3D3D3
LightGrey #D3D3D3
LightGreen #90EE90
LightPink #FFB6C1
LightSalmon #FFA07A
LightSeaGreen #20B2AA
LightSkyBlue #87CEFA
LightSlateGray #778899
LightSlateGrey #778899
LightSteelBlue #B0C4DE
LightYellow #FFFFE0
Lime #00FF00
LimeGreen #32CD32
Linen #FAF0E6
Magenta #FF00FF
Maroon #800000
MediumAquaMarine #66CDAA
MediumBlue #0000CD
MediumOrchid #BA55D3
MediumPurple #9370D8
MediumSeaGreen #3CB371
MediumSlateBlue #7B68EE
MediumSpringGreen #00FA9A
MediumTurquoise #48D1CC
MediumVioletRed #C71585
MidnightBlue #191970
MintCream #F5FFFA
MistyRose #FFE4E1
Moccasin #FFE4B5
NavajoWhite #FFDEAD
Navy #000080
OldLace #FDF5E6
Olive #808000
OliveDrab #6B8E23
Orange #FFA500
OrangeRed #FF4500
Orchid #DA70D6
PaleGoldenRod #EEE8AA
PaleGreen #98FB98
PaleTurquoise #AFEEEE
PaleVioletRed #D87093
PapayaWhip #FFEFD5
PeachPuff #FFDAB9
Peru #CD853F
Pink #FFC0CB
Plum #DDA0DD
PowderBlue #B0E0E6
Purple #800080
Red #FF0000
RosyBrown #BC8F8F
RoyalBlue #4169E1
SaddleBrown #8B4513
Salmon #FA8072
SandyBrown #F4A460
SeaGreen #2E8B57
SeaShell #FFF5EE
Sienna #A0522D
Silver #C0C0C0
SkyBlue #87CEEB
SlateBlue #6A5ACD
SlateGray #708090
SlateGrey #708090
Snow #FFFAFA
SpringGreen #00FF7F
SteelBlue #4682B4
Tan #D2B48C
Teal #008080
Thistle #D8BFD8
Tomato #FF6347
Turquoise #40E0D0
Violet #EE82EE
Wheat #F5DEB3
White #FFFFFF
WhiteSmoke #F5F5F5
Yellow #FFFF00
YellowGreen #9ACD32
\ No newline at end of file
......@@ -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();
}
......@@ -523,6 +522,7 @@ namespace Sass {
else if (lex < return_directive >()) {
Node ret_expr(context.new_Node(Node::return_directive, path, line, 1));
ret_expr << parse_list();
ret_expr.should_eval() = true;
block << ret_expr;
semicolon = true;
}
......@@ -813,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<pair<string, size_t>, 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())
{
......@@ -29,7 +30,7 @@ namespace Sass {
} break;
case Node::function: {
f_env[pair<string, size_t>(expr[0].to_string(), expr[1].size())] = Function(expr);
f_env[expr[0].to_string()] = Function(expr);
return expr;
} break;
......@@ -288,12 +289,24 @@ 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);
pair<string, size_t> sig(expr[0].to_string(), expr[1].size());
if (!f_env.count(sig)) {
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)
Node args(expr[1]);
for (size_t i = 0, S = args.size(); i < S; ++i) {
args[i] = eval(args[i], prefix, env, f_env, new_Node, ctx);
......@@ -301,7 +314,16 @@ namespace Sass {
return expr;
}
else {
return apply_function(f_env[sig], expr[1], prefix, env, f_env, new_Node, ctx);
// check to see if the function is primitive/built-in
Function f(f_env[name]);
if (f.overloaded) {
stringstream s;
s << name << " " << expr[1].size();
string resolved_name(s.str());
if (!f_env.count(resolved_name)) throw_eval_error("wrong number of arguments to " + name, expr.path(), expr.line());
f = f_env[resolved_name];
}
return apply_function(f, expr[1], prefix, env, f_env, new_Node, ctx);
}
} break;
......@@ -327,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: {
......@@ -582,7 +615,7 @@ namespace Sass {
// environment to the current one, then copy the body and eval in the new
// environment.
Node apply_mixin(Node mixin, const Node args, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool dynamic_scope)
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)
{
Node params(mixin[1]);
Node body(new_Node(mixin[2])); // clone the body
......@@ -650,7 +683,7 @@ namespace Sass {
// Apply a function -- bind the arguments and pass them to the underlying
// primitive function implementation, then return its value.
Node apply_function(const Function& f, const Node args, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& ctx)
Node apply_function(const Function& f, const Node args, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx)
{
if (f.primitive) {
map<Token, Node> bindings;
......@@ -663,7 +696,7 @@ namespace Sass {
}
else {
// TO DO: ensure (j < f.parameters.size())
bindings[f.parameters[j]] = eval(args[i], prefix, env, f_env, new_Node, ctx);
bindings[f.parameters[j].token()] = eval(args[i], prefix, env, f_env, new_Node, ctx);
++j;
}
}
......@@ -827,7 +860,13 @@ namespace Sass {
} break;
case Node::return_directive: {
return eval(stm[0], Node(), bindings, ctx.function_env, new_Node, ctx);
Node retval(eval(stm[0], Node(), bindings, ctx.function_env, new_Node, ctx));
if (retval.type() == Node::comma_list || retval.type() == Node::space_list) {
for (size_t i = 0, S = retval.size(); i < S; ++i) {
retval[i] = eval(retval[i], Node(), bindings, ctx.function_env, new_Node, ctx);
}
}
return retval;
} break;
default: {
......@@ -1177,11 +1216,9 @@ namespace Sass {
default: {
// something
cerr << "pux!" << endl;
} break;
}
}
cerr << "blux!" << endl;
return Node();
}
......@@ -1243,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,13 +11,13 @@
namespace Sass {
using std::map;
Node eval(Node expr, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& 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);
Node apply_mixin(Node mixin, const Node args, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool dynamic_scope = false);
Node apply_function(const Function& f, const Node args, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& ctx);
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 expand_selector(Node sel, Node pre, Node_Factory& new_Node);
Node expand_backref(Node sel, Node pre);
void extend_selectors(vector<pair<Node, Node> >&, multimap<Node, Node>&, Node_Factory&);
......@@ -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
......@@ -23,10 +23,10 @@ namespace Sass {
Function_Descriptor rgb_descriptor =
{ "rgb", "$red", "$green", "$blue", 0 };
Node rgb(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node r(bindings[parameters[0]]);
Node g(bindings[parameters[1]]);
Node b(bindings[parameters[2]]);
Node rgb(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node r(bindings[parameters[0].token()]);
Node g(bindings[parameters[1].token()]);
Node b(bindings[parameters[2].token()]);
if (!(r.type() == Node::number && g.type() == Node::number && b.type() == Node::number)) {
throw_eval_error("arguments for rgb must be numbers", r.path(), r.line());
}
......@@ -34,12 +34,12 @@ namespace Sass {
}
Function_Descriptor rgba_4_descriptor =
{ "rgba", "$red", "$green", "$blue", "$alpha", 0 };
Node rgba_4(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node r(bindings[parameters[0]]);
Node g(bindings[parameters[1]]);
Node b(bindings[parameters[2]]);
Node a(bindings[parameters[3]]);
{ "rgba 4", "$red", "$green", "$blue", "$alpha", 0 };
Node rgba_4(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node r(bindings[parameters[0].token()]);
Node g(bindings[parameters[1].token()]);
Node b(bindings[parameters[2].token()]);
Node a(bindings[parameters[3].token()]);
if (!(r.type() == Node::number && g.type() == Node::number && b.type() == Node::number && a.type() == Node::number)) {
throw_eval_error("arguments for rgba must be numbers", r.path(), r.line());
}
......@@ -47,37 +47,37 @@ namespace Sass {
}
Function_Descriptor rgba_2_descriptor =
{ "rgba", "$color", "$alpha", 0 };
Node rgba_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0]]);
{ "rgba 2", "$color", "$alpha", 0 };
Node rgba_2(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0].token()]);
Node r(color[0]);
Node g(color[1]);
Node b(color[2]);
Node a(bindings[parameters[1]]);
Node a(bindings[parameters[1].token()]);
if (color.type() != Node::numeric_color || a.type() != Node::number) throw_eval_error("arguments to rgba must be a color and a number", color.path(), color.line());
return new_Node(color.path(), color.line(), r.numeric_value(), g.numeric_value(), b.numeric_value(), a.numeric_value());
}
Function_Descriptor red_descriptor =
{ "red", "$color", 0 };
Node red(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0]]);
Node red(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0].token()]);
if (color.type() != Node::numeric_color) throw_eval_error("argument to red must be a color", color.path(), color.line());
return color[0];
}
Function_Descriptor green_descriptor =
{ "green", "$color", 0 };
Node green(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0]]);
Node green(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0].token()]);
if (color.type() != Node::numeric_color) throw_eval_error("argument to green must be a color", color.path(), color.line());
return color[1];
}
Function_Descriptor blue_descriptor =
{ "blue", "$color", 0 };
Node blue(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0]]);
Node blue(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0].token()]);
if (color.type() != Node::numeric_color) throw_eval_error("argument to blue must be a color", color.path(), color.line());
return color[2];
}
......@@ -104,20 +104,20 @@ namespace Sass {
}
Function_Descriptor mix_2_descriptor =
{ "mix", "$color1", "$color2", 0 };
Node mix_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
return mix_impl(bindings[parameters[0]], bindings[parameters[1]], 50, new_Node);
{ "mix 2", "$color1", "$color2", 0 };
Node mix_2(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
return mix_impl(bindings[parameters[0].token()], bindings[parameters[1].token()], 50, new_Node);
}
Function_Descriptor mix_3_descriptor =
{ "mix", "$color1", "$color2", "$weight", 0 };
Node mix_3(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node percentage(bindings[parameters[2]]);
{ "mix 3", "$color1", "$color2", "$weight", 0 };
Node mix_3(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node percentage(bindings[parameters[2].token()]);
if (!(percentage.type() == Node::number || percentage.type() == Node::numeric_percentage || percentage.type() == Node::numeric_dimension)) {
throw_eval_error("third argument to mix must be numeric", percentage.path(), percentage.line());
}
return mix_impl(bindings[parameters[0]],
bindings[parameters[1]],
return mix_impl(bindings[parameters[0].token()],
bindings[parameters[1].token()],
percentage.numeric_value(),
new_Node);
}
......@@ -151,42 +151,42 @@ namespace Sass {
Function_Descriptor hsla_descriptor =
{ "hsla", "$hue", "$saturation", "$lightness", "$alpha", 0 };
Node hsla(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
if (!(bindings[parameters[0]].is_numeric() &&
bindings[parameters[1]].is_numeric() &&
bindings[parameters[2]].is_numeric() &&
bindings[parameters[3]].is_numeric())) {
throw_eval_error("arguments to hsla must be numeric", bindings[parameters[0]].path(), bindings[parameters[0]].line());
}
double h = bindings[parameters[0]].numeric_value();
double s = bindings[parameters[1]].numeric_value();
double l = bindings[parameters[2]].numeric_value();
double a = bindings[parameters[3]].numeric_value();
Node hsla(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
if (!(bindings[parameters[0].token()].is_numeric() &&
bindings[parameters[1].token()].is_numeric() &&
bindings[parameters[2].token()].is_numeric() &&
bindings[parameters[3].token()].is_numeric())) {
throw_eval_error("arguments to hsla must be numeric", bindings[parameters[0].token()].path(), bindings[parameters[0].token()].line());
}
double h = bindings[parameters[0].token()].numeric_value();
double s = bindings[parameters[1].token()].numeric_value();
double l = bindings[parameters[2].token()].numeric_value();
double a = bindings[parameters[3].token()].numeric_value();
Node color(hsla_impl(h, s, l, a, new_Node));
// color.line() = bindings[parameters[0]].line();
// color.line() = bindings[parameters[0].token()].line();
return color;
}
Function_Descriptor hsl_descriptor =
{ "hsl", "$hue", "$saturation", "$lightness", 0 };
Node hsl(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
if (!(bindings[parameters[0]].is_numeric() &&
bindings[parameters[1]].is_numeric() &&
bindings[parameters[2]].is_numeric())) {
throw_eval_error("arguments to hsl must be numeric", bindings[parameters[0]].path(), bindings[parameters[0]].line());
}
double h = bindings[parameters[0]].numeric_value();
double s = bindings[parameters[1]].numeric_value();
double l = bindings[parameters[2]].numeric_value();
Node hsl(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
if (!(bindings[parameters[0].token()].is_numeric() &&
bindings[parameters[1].token()].is_numeric() &&
bindings[parameters[2].token()].is_numeric())) {
throw_eval_error("arguments to hsl must be numeric", bindings[parameters[0].token()].path(), bindings[parameters[0].token()].line());
}
double h = bindings[parameters[0].token()].numeric_value();
double s = bindings[parameters[1].token()].numeric_value();
double l = bindings[parameters[2].token()].numeric_value();
Node color(hsla_impl(h, s, l, 1, new_Node));
// color.line() = bindings[parameters[0]].line();
// color.line() = bindings[parameters[0].token()].line();
return color;
}
Function_Descriptor invert_descriptor =
{ "invert", "$color", 0 };
Node invert(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node orig(bindings[parameters[0]]);
Node invert(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node orig(bindings[parameters[0].token()]);
if (orig.type() != Node::numeric_color) throw_eval_error("argument to invert must be a color", orig.path(), orig.line());
return new_Node(orig.path(), orig.line(),
255 - orig[0].numeric_value(),
......@@ -201,8 +201,8 @@ namespace Sass {
{ "alpha", "$color", 0 };
Function_Descriptor opacity_descriptor =
{ "opacity", "$color", 0 };
Node alpha(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0]]);
Node alpha(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0].token()]);
if (color.type() != Node::numeric_color) throw_eval_error("argument to alpha must be a color", color.path(), color.line());
return color[3];
}
......@@ -211,9 +211,9 @@ namespace Sass {
{ "opacify", "$color", "$amount", 0 };
Function_Descriptor fade_in_descriptor =
{ "fade_in", "$color", "$amount", 0 };
Node opacify(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0]]);
Node delta(bindings[parameters[1]]);
Node opacify(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0].token()]);
Node delta(bindings[parameters[1].token()]);
if (color.type() != Node::numeric_color || !delta.is_numeric()) {
throw_eval_error("arguments to opacify/fade_in must be a color and a numeric value", color.path(), color.line());
}
......@@ -231,9 +231,9 @@ namespace Sass {
{ "transparentize", "$color", "$amount", 0 };
Function_Descriptor fade_out_descriptor =
{ "fade_out", "$color", "$amount", 0 };
Node transparentize(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0]]);
Node delta(bindings[parameters[1]]);
Node transparentize(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0].token()]);
Node delta(bindings[parameters[1].token()]);
if (color.type() != Node::numeric_color || !delta.is_numeric()) {
throw_eval_error("arguments to transparentize/fade_out must be a color and a numeric value", color.path(), color.line());
}
......@@ -251,8 +251,8 @@ namespace Sass {
Function_Descriptor unquote_descriptor =
{ "unquote", "$string", 0 };
Node unquote(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node cpy(new_Node(bindings[parameters[0]]));
Node unquote(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node cpy(new_Node(bindings[parameters[0].token()]));
// if (cpy.type() != Node::string_constant /* && cpy.type() != Node::concatenation */) {
// throw_eval_error("argument to unquote must be a string", cpy.path(), cpy.line());
// }
......@@ -263,8 +263,8 @@ namespace Sass {
Function_Descriptor quote_descriptor =
{ "quote", "$string", 0 };
Node quote(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node orig(bindings[parameters[0]]);
Node quote(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node orig(bindings[parameters[0].token()]);
switch (orig.type())
{
default: {
......@@ -289,8 +289,8 @@ namespace Sass {
Function_Descriptor percentage_descriptor =
{ "percentage", "$value", 0 };
Node percentage(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node orig(bindings[parameters[0]]);
Node percentage(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node orig(bindings[parameters[0].token()]);
if (orig.type() != Node::number) {
throw_eval_error("argument to percentage must be a unitless number", orig.path(), orig.line());
}
......@@ -299,8 +299,8 @@ namespace Sass {
Function_Descriptor round_descriptor =
{ "round", "$value", 0 };
Node round(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node orig(bindings[parameters[0]]);
Node round(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node orig(bindings[parameters[0].token()]);
switch (orig.type())
{
case Node::numeric_dimension: {
......@@ -329,8 +329,8 @@ namespace Sass {
Function_Descriptor ceil_descriptor =
{ "ceil", "$value", 0 };
Node ceil(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node orig(bindings[parameters[0]]);
Node ceil(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node orig(bindings[parameters[0].token()]);
switch (orig.type())
{
case Node::numeric_dimension: {
......@@ -359,8 +359,8 @@ namespace Sass {
Function_Descriptor floor_descriptor =
{ "floor", "$value", 0 };
Node floor(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node orig(bindings[parameters[0]]);
Node floor(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node orig(bindings[parameters[0].token()]);
switch (orig.type())
{
case Node::numeric_dimension: {
......@@ -389,8 +389,8 @@ namespace Sass {
Function_Descriptor abs_descriptor =
{ "abs", "$value", 0 };
Node abs(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node orig(bindings[parameters[0]]);
Node abs(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node orig(bindings[parameters[0].token()]);
switch (orig.type())
{
case Node::numeric_dimension: {
......@@ -421,8 +421,8 @@ namespace Sass {
Function_Descriptor length_descriptor =
{ "length", "$list", 0 };
Node length(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node arg(bindings[parameters[0]]);
Node length(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node arg(bindings[parameters[0].token()]);
switch (arg.type())
{
case Node::space_list:
......@@ -445,9 +445,9 @@ namespace Sass {
Function_Descriptor nth_descriptor =
{ "nth", "$list", "$n", 0 };
Node nth(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node l(bindings[parameters[0]]);
Node n(bindings[parameters[1]]);
Node nth(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node l(bindings[parameters[0].token()]);
Node n(bindings[parameters[1].token()]);
if (n.type() != Node::number) {
throw_eval_error("second argument to nth must be a number", n.path(), n.line());
}
......@@ -466,13 +466,13 @@ namespace Sass {
}
extern const char separator_kwd[] = "$separator";
Node join_impl(const vector<Token>& parameters, map<Token, Node>& bindings, bool has_sep, Node_Factory& new_Node) {
Node join_impl(const Node parameters, map<Token, Node>& bindings, bool has_sep, Node_Factory& new_Node) {
// if the args aren't lists, turn them into singleton lists
Node l1(bindings[parameters[0]]);
Node l1(bindings[parameters[0].token()]);
if (l1.type() != Node::space_list && l1.type() != Node::comma_list && l1.type() != Node::nil) {
l1 = new_Node(Node::space_list, l1.path(), l1.line(), 1) << l1;
}
Node l2(bindings[parameters[1]]);
Node l2(bindings[parameters[1].token()]);
if (l2.type() != Node::space_list && l2.type() != Node::comma_list && l2.type() != Node::nil) {
l2 = new_Node(Node::space_list, l2.path(), l2.line(), 1) << l2;
}
......@@ -487,7 +487,7 @@ namespace Sass {
// figure out the result type in advance
Node::Type rtype = Node::space_list;
if (has_sep) {
string sep(bindings[parameters[2]].token().unquote());
string sep(bindings[parameters[2].token()].token().unquote());
if (sep == "comma") rtype = Node::comma_list;
else if (sep == "space") rtype = Node::space_list;
else if (sep == "auto") rtype = l1.type();
......@@ -505,19 +505,19 @@ namespace Sass {
}
Function_Descriptor join_2_descriptor =
{ "join", "$list1", "$list2", 0 };
Node join_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
{ "join 2", "$list1", "$list2", 0 };
Node join_2(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
return join_impl(parameters, bindings, false, new_Node);
}
Function_Descriptor join_3_descriptor =
{ "join", "$list1", "$list2", "$separator", 0 };
Node join_3(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
{ "join 3", "$list1", "$list2", "$separator", 0 };
Node join_3(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
return join_impl(parameters, bindings, true, new_Node);
}
Node append_impl(const vector<Token>& parameters, map<Token, Node>& bindings, bool has_sep, Node_Factory& new_Node) {
Node list(bindings[parameters[0]]);
Node append_impl(const Node parameters, map<Token, Node>& bindings, bool has_sep, Node_Factory& new_Node) {
Node list(bindings[parameters[0].token()]);
switch (list.type())
{
case Node::space_list:
......@@ -532,7 +532,7 @@ namespace Sass {
}
Node::Type sep_type = list.type();
if (has_sep) {
string sep_string = bindings[parameters[2]].token().unquote();
string sep_string = bindings[parameters[2].token()].token().unquote();
if (sep_string == "comma") sep_type = Node::comma_list;
else if (sep_string == "space") sep_type = Node::space_list;
else if (sep_string == "auto") sep_type = list.type();
......@@ -540,27 +540,27 @@ namespace Sass {
}
Node new_list(new_Node(sep_type, list.path(), list.line(), list.size() + 1));
new_list += list;
new_list << bindings[parameters[1]];
new_list << bindings[parameters[1].token()];
return new_list;
}
Function_Descriptor append_2_descriptor =
{ "append", "$list", "$val", 0 };
Node append_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
{ "append 2", "$list", "$val", 0 };
Node append_2(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
return append_impl(parameters, bindings, false, new_Node);
}
Function_Descriptor append_3_descriptor =
{ "append", "$list", "$val", "$separator", 0 };
Node append_3(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
{ "append 3", "$list", "$val", "$separator", 0 };
Node append_3(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
return append_impl(parameters, bindings, true, new_Node);
}
Node compact(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node compact(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
size_t num_args = bindings.size();
Node::Type sep_type = Node::comma_list;
Node list;
Node arg1(bindings[parameters[0]]);
Node arg1(bindings[parameters[0].token()]);
if (num_args == 1 && (arg1.type() == Node::space_list ||
arg1.type() == Node::comma_list ||
arg1.type() == Node::nil)) {
......@@ -570,7 +570,7 @@ namespace Sass {
else {
list = new_Node(sep_type, arg1.path(), arg1.line(), num_args);
for (size_t i = 0; i < num_args; ++i) {
list << bindings[parameters[i]];
list << bindings[parameters[i].token()];
}
}
Node new_list(new_Node(list.type(), list.path(), list.line(), 0));
......@@ -583,30 +583,37 @@ namespace Sass {
}
Function_Descriptor compact_1_descriptor =
{ "compact", "$arg1", 0 };
{ "compact 1", "$arg1", 0 };
Function_Descriptor compact_2_descriptor =
{ "compact", "$arg1", "$arg2", 0 };
{ "compact 2", "$arg1", "$arg2", 0 };
Function_Descriptor compact_3_descriptor =
{ "compact", "$arg1", "$arg2", "$arg3", 0 };
{ "compact 3", "$arg1", "$arg2", "$arg3", 0 };
Function_Descriptor compact_4_descriptor =
{ "compact", "$arg1", "$arg2", "$arg3", "$arg4", 0 };
{ "compact 4", "$arg1", "$arg2", "$arg3", "$arg4", 0 };
Function_Descriptor compact_5_descriptor =
{ "compact", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5", 0 };
{ "compact 5", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5", 0 };
Function_Descriptor compact_6_descriptor =
{ "compact", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5",
{ "compact 6", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5",
"$arg6", 0 };
Function_Descriptor compact_7_descriptor =
{ "compact", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5",
{ "compact 7", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5",
"$arg6", "$arg7", 0 };
Function_Descriptor compact_8_descriptor =
{ "compact", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5",
{ "compact 8", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5",
"$arg6", "$arg7", "$arg8", 0 };
Function_Descriptor compact_9_descriptor =
{ "compact", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5",
{ "compact 9", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5",
"$arg6", "$arg7", "$arg8", "$arg9", 0 };
Function_Descriptor compact_10_descriptor =
{ "compact", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5",
{ "compact 10", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5",
"$arg6", "$arg7", "$arg8", "$arg9", "$arg10", 0 };
Function_Descriptor compact_11_descriptor =
{ "compact 11", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5", "$arg6",
"$arg7", "$arg8", "$arg9", "$arg10", "$arg11", 0 };
Function_Descriptor compact_12_descriptor =
{ "compact 12", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5", "arg6",
"$arg7", "$arg8", "$arg9", "$arg10", "$arg11", "$arg12", 0 };
// Introspection Functions /////////////////////////////////////////////
......@@ -619,8 +626,8 @@ namespace Sass {
Function_Descriptor type_of_descriptor =
{ "type-of", "$value", 0 };
Node type_of(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node val(bindings[parameters[0]]);
Node type_of(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node val(bindings[parameters[0].token()]);
Token type_name;
switch (val.type())
{
......@@ -658,8 +665,8 @@ namespace Sass {
Function_Descriptor unit_descriptor =
{ "unit", "$number", 0 };
Node unit(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node val(bindings[parameters[0]]);
Node unit(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node val(bindings[parameters[0].token()]);
switch (val.type())
{
case Node::number: {
......@@ -684,8 +691,8 @@ namespace Sass {
Function_Descriptor unitless_descriptor =
{ "unitless", "$number", 0 };
Node unitless(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node val(bindings[parameters[0]]);
Node unitless(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node val(bindings[parameters[0].token()]);
switch (val.type())
{
case Node::number: {
......@@ -707,9 +714,9 @@ namespace Sass {
Function_Descriptor comparable_descriptor =
{ "comparable", "$number_1", "$number_2", 0 };
Node comparable(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node n1(bindings[parameters[0]]);
Node n2(bindings[parameters[1]]);
Node comparable(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node n1(bindings[parameters[0].token()]);
Node n2(bindings[parameters[1].token()]);
Node::Type t1 = n1.type();
Node::Type t2 = n2.type();
if ((t1 == Node::number && n2.is_numeric()) ||
......@@ -742,8 +749,8 @@ namespace Sass {
// Boolean Functions ///////////////////////////////////////////////////
Function_Descriptor not_descriptor =
{ "not", "value", 0 };
Node not_impl(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node val(bindings[parameters[0]]);
Node not_impl(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node val(bindings[parameters[0].token()]);
if (val.type() == Node::boolean && val.boolean_value() == false) {
return new_Node(Node::boolean, val.path(), val.line(), true);
}
......
......@@ -8,41 +8,52 @@
namespace Sass {
using std::map;
typedef Node (*Primitive)(const vector<Token>&, map<Token, Node>&, Node_Factory& new_Node);
typedef Node (*Primitive)(const Node, map<Token, Node>&, Node_Factory& new_Node);
typedef const char* str;
typedef str Function_Descriptor[];
struct Function {
string name;
vector<Token> parameters;
// vector<Token> parameters;
Node parameters;
Node definition;
Primitive primitive;
bool overloaded;
Function()
{ /* TO DO: set up the generic callback here */ }
Function(Node def)
: name(def[0].to_string()),
parameters(vector<Token>()),
parameters(def[1]),
definition(def),
primitive(0)
primitive(0),
overloaded(false)
{ }
Function(Function_Descriptor d, Primitive ip)
// Stub for overloaded primitives
Function(string name, bool overloaded = true)
: name(name),
parameters(Node()),
definition(Node()),
primitive(0),
overloaded(overloaded)
{ }
Function(Function_Descriptor d, Primitive ip, Node_Factory& new_Node)
: name(d[0]),
parameters(vector<Token>()),
parameters(new_Node(Node::parameters, "[PRIMITIVE FUNCTIONS]", 0, 0)),
definition(Node()),
primitive(ip)
primitive(ip),
overloaded(false)
{
size_t len = 0;
while (d[len+1]) ++len;
parameters.reserve(len);
for (size_t i = 0; i < len; ++i) {
const char* p = d[i+1];
Token name(Token::make(p, p + std::strlen(p)));
parameters.push_back(name);
parameters.push_back(new_Node(Node::variable, "[PRIMITIVE FUNCTIONS]", 0, Token::make(p, p + std::strlen(p))));
}
}
......@@ -59,98 +70,98 @@ namespace Sass {
// RGB Functions ///////////////////////////////////////////////////////
extern Function_Descriptor rgb_descriptor;
Node rgb(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node rgb(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor rgba_4_descriptor;
Node rgba_4(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node rgba_4(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor rgba_2_descriptor;
Node rgba_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node rgba_2(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor red_descriptor;
Node red(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node red(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor green_descriptor;
Node green(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node green(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor blue_descriptor;
Node blue(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node blue(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor mix_2_descriptor;
Node mix_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node mix_2(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor mix_3_descriptor;
Node mix_3(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node mix_3(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// HSL Functions ///////////////////////////////////////////////////////
extern Function_Descriptor hsla_descriptor;
Node hsla(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node hsla(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor hsl_descriptor;
Node hsl(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node hsl(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor invert_descriptor;
Node invert(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node invert(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Opacity Functions ///////////////////////////////////////////////////
extern Function_Descriptor alpha_descriptor;
extern Function_Descriptor opacity_descriptor;
Node alpha(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node alpha(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor opacify_descriptor;
extern Function_Descriptor fade_in_descriptor;
Node opacify(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node opacify(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor transparentize_descriptor;
extern Function_Descriptor fade_out_descriptor;
Node transparentize(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node transparentize(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// String Functions ////////////////////////////////////////////////////
extern Function_Descriptor unquote_descriptor;
Node unquote(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node unquote(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor quote_descriptor;
Node quote(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node quote(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Number Functions ////////////////////////////////////////////////////
extern Function_Descriptor percentage_descriptor;
Node percentage(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node percentage(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor round_descriptor;
Node round(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node round(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor ceil_descriptor;
Node ceil(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node ceil(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor floor_descriptor;
Node floor(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node floor(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor abs_descriptor;
Node abs(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node abs(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// List Functions //////////////////////////////////////////////////////
extern Function_Descriptor length_descriptor;
Node length(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node length(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor nth_descriptor;
Node nth(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node nth(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor join_2_descriptor;
Node join_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node join_2(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor join_3_descriptor;
Node join_3(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node join_3(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor append_2_descriptor;
Node append_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node append_2(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor append_3_descriptor;
Node append_3(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node append_3(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor compact_1_descriptor;
extern Function_Descriptor compact_2_descriptor;
......@@ -162,26 +173,28 @@ namespace Sass {
extern Function_Descriptor compact_8_descriptor;
extern Function_Descriptor compact_9_descriptor;
extern Function_Descriptor compact_10_descriptor;
Node compact(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor compact_11_descriptor;
extern Function_Descriptor compact_12_descriptor;
Node compact(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Introspection Functions /////////////////////////////////////////////
extern Function_Descriptor type_of_descriptor;
Node type_of(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node type_of(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor unit_descriptor;
Node unit(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node unit(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor unitless_descriptor;
Node unitless(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node unitless(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor comparable_descriptor;
Node comparable(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node comparable(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Boolean Functions ///////////////////////////////////////////////////
extern Function_Descriptor not_descriptor;
Node not_impl(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
Node not_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,
......
......@@ -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;
......
......@@ -12,6 +12,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