Commit a087ed82 by Andrew Nesbitt

Updated libsass, closes #52

parent 119743ae
...@@ -41,6 +41,17 @@ namespace Sass { ...@@ -41,6 +41,17 @@ namespace Sass {
return ss.str(); return ss.str();
} }
size_t depth()
{
size_t d = 0;
Backtrace* p = parent;
while (p) {
++d;
p = p->parent;
}
return d-1;
}
}; };
} }
\ No newline at end of file
...@@ -86,6 +86,7 @@ namespace Sass { ...@@ -86,6 +86,7 @@ namespace Sass {
extern const char rparen[] = ")"; extern const char rparen[] = ")";
extern const char sign_chars[] = "-+"; extern const char sign_chars[] = "-+";
extern const char hyphen[] = "-"; extern const char hyphen[] = "-";
extern const char ellipsis[] = "...";
// type names // type names
extern const char numeric_name[] = "numeric value"; extern const char numeric_name[] = "numeric value";
...@@ -96,6 +97,7 @@ namespace Sass { ...@@ -96,6 +97,7 @@ namespace Sass {
extern const char bool_name[] = "bool"; extern const char bool_name[] = "bool";
extern const char color_name[] = "color"; extern const char color_name[] = "color";
extern const char list_name[] = "list"; extern const char list_name[] = "list";
extern const char arglist_name[] = "arglist";
} }
} }
\ No newline at end of file
...@@ -86,6 +86,7 @@ namespace Sass { ...@@ -86,6 +86,7 @@ namespace Sass {
extern const char rparen[]; extern const char rparen[];
extern const char sign_chars[]; extern const char sign_chars[];
extern const char hyphen[]; extern const char hyphen[];
extern const char ellipsis[];
// type names // type names
extern const char numeric_name[]; extern const char numeric_name[];
...@@ -96,5 +97,6 @@ namespace Sass { ...@@ -96,5 +97,6 @@ namespace Sass {
extern const char bool_name[]; extern const char bool_name[];
extern const char color_name[]; extern const char color_name[];
extern const char list_name[]; extern const char list_name[];
extern const char arglist_name[];
} }
} }
\ No newline at end of file
...@@ -177,23 +177,32 @@ namespace Sass { ...@@ -177,23 +177,32 @@ namespace Sass {
Node::Type param_type = Node::none; Node::Type param_type = Node::none;
if (lex< exactly<'('> >()) { if (lex< exactly<'('> >()) {
if (peek< variable >()) { if (peek< variable >()) {
Node param(parse_parameter(param_type)); do {
if (param.type() == Node::assignment) param_type = Node::assignment;
params << param;
while (lex< exactly<','> >()) {
if (!peek< variable >()) throw_syntax_error("expected a variable name (e.g. $x) for the parameter list for " + name.to_string()); if (!peek< variable >()) throw_syntax_error("expected a variable name (e.g. $x) for the parameter list for " + name.to_string());
Node param(parse_parameter(param_type)); Node param(parse_parameter(param_type));
if (param.type() == Node::assignment) param_type = Node::assignment; if (param.type() == Node::assignment) param_type = Node::assignment;
params << param; params << param;
if (param.type() == Node::rest) {
param_type = Node::rest;
break;
}
} while (lex< exactly<','> >());
if (!lex< exactly<')'> >()) {
if (params.back().type() == Node::rest && peek< exactly<','> >()) {
throw_syntax_error("variable-length parameter must appear last in a parameter list");
}
else {
throw_syntax_error("parameter list for " + name.to_string() + " requires a ')'");
}
} }
if (!lex< exactly<')'> >()) throw_syntax_error("parameter list for " + name.to_string() + " requires a ')'");
} }
else if (!lex< exactly<')'> >()) throw_syntax_error("expected a variable name (e.g. $x) or ')' for the parameter list for " + name.to_string()); else if (!lex< exactly<')'> >()) throw_syntax_error("expected a variable name (e.g. $x) or ')' for the parameter list for " + name.to_string());
} }
return params; return params;
} }
Node Document::parse_parameter(Node::Type param_type) { Node Document::parse_parameter(Node::Type param_type)
{
lex< variable >(); lex< variable >();
Node var(context.new_Node(Node::variable, path, line, lexed)); Node var(context.new_Node(Node::variable, path, line, lexed));
if (param_type == Node::assignment) { if (param_type == Node::assignment) {
...@@ -213,6 +222,9 @@ namespace Sass { ...@@ -213,6 +222,9 @@ namespace Sass {
par_and_val << var << val; par_and_val << var << val;
return par_and_val; return par_and_val;
} }
else if (lex< exactly< ellipsis > >()) {
return context.new_Node(Node::rest, var.path(), var.line(), var.token());
}
return var; return var;
} }
...@@ -241,16 +253,26 @@ namespace Sass { ...@@ -241,16 +253,26 @@ namespace Sass {
Node::Type arg_type = Node::none; Node::Type arg_type = Node::none;
if (lex< exactly<'('> >()) { if (lex< exactly<'('> >()) {
if (!peek< exactly<')'> >(position)) { if (!peek< exactly<')'> >(position)) {
Node arg(parse_argument(Node::none)); do {
args << arg;
if (arg.type() == Node::assignment) arg_type = Node::assignment;
while (lex< exactly<','> >()) {
Node arg(parse_argument(arg_type)); Node arg(parse_argument(arg_type));
args << arg; args << arg;
if (arg.type() == Node::assignment) arg_type = Node::assignment; if (arg.type() == Node::assignment) {
arg_type = Node::assignment;
}
else if (arg.type() == Node::rest) {
arg_type = Node::rest;
break;
}
} while (lex< exactly<','> >());
}
if (!lex< exactly<')'> >()) {
if (args.back().is_arglist() && peek< exactly<','> >()) {
throw_syntax_error("variable-length argument must appear last in an argument list");
}
else {
throw_syntax_error("improperly terminated argument list for " + name.to_string());
} }
} }
if (!lex< exactly<')'> >()) throw_syntax_error("improperly terminated argument list for " + name.to_string());
} }
return args; return args;
} }
...@@ -274,8 +296,8 @@ namespace Sass { ...@@ -274,8 +296,8 @@ namespace Sass {
} }
} }
// otherwise accept either, and let the caller set the arg_type flag // otherwise accept either, and let the caller set the arg_type flag
if (arg_type == Node::none && else if (arg_type == Node::none &&
peek< sequence < variable, spaces_and_comments, exactly<':'> > >()) { peek< sequence < variable, spaces_and_comments, exactly<':'> > >()) {
lex< variable >(); lex< variable >();
Node var(context.new_Node(Node::variable, path, line, lexed)); Node var(context.new_Node(Node::variable, path, line, lexed));
lex< exactly<':'> >(); lex< exactly<':'> >();
...@@ -285,8 +307,18 @@ namespace Sass { ...@@ -285,8 +307,18 @@ namespace Sass {
assn << var << val; assn << var << val;
return assn; return assn;
} }
// else if (arg_type == Node::none &&
// peek< sequence < variable, spaces_and_comments, exactly< ellipsis > > >()) {
// lex< variable >();
// lex< exactly< ellipsis > >();
// return context.new_Node(Node::rest, path, line, lexed);
// }
Node val(parse_space_list()); Node val(parse_space_list());
val.should_eval() = true; val.should_eval() = true;
if (lex< exactly< ellipsis > >()) {
val.is_arglist() = true;
val.is_splat() = true;
}
return val; return val;
} }
...@@ -711,7 +743,8 @@ namespace Sass { ...@@ -711,7 +743,8 @@ namespace Sass {
if (peek< exactly<';'> >(position) || if (peek< exactly<';'> >(position) ||
peek< exactly<'}'> >(position) || peek< exactly<'}'> >(position) ||
peek< exactly<'{'> >(position) || peek< exactly<'{'> >(position) ||
peek< exactly<')'> >(position)) peek< exactly<')'> >(position) ||
peek< exactly<ellipsis> >(position))
{ return context.new_Node(Node::list, path, line, 0); } { return context.new_Node(Node::list, path, line, 0); }
Node list1(parse_space_list()); Node list1(parse_space_list());
// if it's a singleton, return it directly; don't wrap it // if it's a singleton, return it directly; don't wrap it
...@@ -741,6 +774,7 @@ namespace Sass { ...@@ -741,6 +774,7 @@ namespace Sass {
peek< exactly<'{'> >(position) || peek< exactly<'{'> >(position) ||
peek< exactly<')'> >(position) || peek< exactly<')'> >(position) ||
peek< exactly<','> >(position) || peek< exactly<','> >(position) ||
peek< exactly<ellipsis> >(position) ||
peek< default_flag >(position)) peek< default_flag >(position))
{ return disj1; } { return disj1; }
...@@ -753,6 +787,7 @@ namespace Sass { ...@@ -753,6 +787,7 @@ namespace Sass {
peek< exactly<'{'> >(position) || peek< exactly<'{'> >(position) ||
peek< exactly<')'> >(position) || peek< exactly<')'> >(position) ||
peek< exactly<','> >(position) || peek< exactly<','> >(position) ||
peek< exactly<ellipsis> >(position) ||
peek< default_flag >(position))) peek< default_flag >(position)))
{ {
Node disj(parse_disjunction()); Node disj(parse_disjunction());
......
...@@ -1049,7 +1049,13 @@ namespace Sass { ...@@ -1049,7 +1049,13 @@ namespace Sass {
type_name = Token::make(color_name); type_name = Token::make(color_name);
} break; } break;
case Node::list: { case Node::list: {
type_name = Token::make(list_name); // cerr << val.to_string() << endl;
// cerr << val.is_arglist() << endl;
// throw (42);
if (val.is_arglist())
type_name = Token::make(arglist_name);
else
type_name = Token::make(list_name);
} break; } break;
default: { default: {
type_name = Token::make(string_name); type_name = Token::make(string_name);
......
...@@ -158,6 +158,7 @@ namespace Sass { ...@@ -158,6 +158,7 @@ namespace Sass {
mixin_content, mixin_content,
parameters, parameters,
arguments, arguments,
rest,
extend_directive, extend_directive,
...@@ -199,6 +200,8 @@ namespace Sass { ...@@ -199,6 +200,8 @@ namespace Sass {
bool& has_been_extended() const; bool& has_been_extended() const;
bool is_false() const; bool is_false() const;
bool& is_comma_separated() const; bool& is_comma_separated() const;
bool& is_arglist() const;
bool& is_splat() const;
string& path() const; string& path() const;
size_t line() const; size_t line() const;
...@@ -240,7 +243,7 @@ namespace Sass { ...@@ -240,7 +243,7 @@ namespace Sass {
bool operator>(Node rhs) const; bool operator>(Node rhs) const;
bool operator>=(Node rhs) const; bool operator>=(Node rhs) const;
string to_string(Type inside_of = none, const string space = " ") const; string to_string(Type inside_of = none, const string space = " ", const bool in_media_feature = false) const;
void emit_nested_css(stringstream& buf, size_t depth, bool at_toplevel = false, bool in_media_query = false, bool source_comments = false); void emit_nested_css(stringstream& buf, size_t depth, bool at_toplevel = false, bool in_media_query = false, bool source_comments = false);
void emit_propset(stringstream& buf, size_t depth, const string& prefix, const bool compressed = false); void emit_propset(stringstream& buf, size_t depth, const string& prefix, const bool compressed = false);
void echo(stringstream& buf, size_t depth = 0); void echo(stringstream& buf, size_t depth = 0);
...@@ -277,6 +280,8 @@ namespace Sass { ...@@ -277,6 +280,8 @@ namespace Sass {
bool is_quoted; bool is_quoted;
bool has_been_extended; bool has_been_extended;
bool is_comma_separated; bool is_comma_separated;
bool is_arglist;
bool is_splat;
Node_Impl() Node_Impl()
: /* value(value_t()), : /* value(value_t()),
...@@ -294,7 +299,9 @@ namespace Sass { ...@@ -294,7 +299,9 @@ namespace Sass {
should_eval(false), should_eval(false),
is_quoted(false), is_quoted(false),
has_been_extended(false), has_been_extended(false),
is_comma_separated(false) is_comma_separated(false),
is_arglist(false),
is_splat(false)
{ } { }
bool is_numeric() bool is_numeric()
...@@ -467,6 +474,8 @@ namespace Sass { ...@@ -467,6 +474,8 @@ namespace Sass {
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_false() const { return (type() == boolean) && (boolean_value() == false); }
inline bool& Node::is_comma_separated() const { return ip_->is_comma_separated; } inline bool& Node::is_comma_separated() const { return ip_->is_comma_separated; }
inline bool& Node::is_arglist() const { return ip_->is_arglist; }
inline bool& Node::is_splat() const { return ip_->is_splat; }
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; }
......
...@@ -15,7 +15,7 @@ using std::endl; ...@@ -15,7 +15,7 @@ using std::endl;
namespace Sass { namespace Sass {
string Node::to_string(Type inside_of, const string space) const string Node::to_string(Type inside_of, const string space, const bool in_media_feature) const
{ {
if (is_null()) return ""; if (is_null()) return "";
switch (type()) switch (type())
...@@ -39,22 +39,27 @@ namespace Sass { ...@@ -39,22 +39,27 @@ namespace Sass {
string result; string result;
if (at(0).type() == rule) { if (at(0).type() == rule) {
result += "("; result += "(";
result += at(0).to_string(none, space); result += at(0).to_string(none, space, true);
result += ")"; result += ")";
} }
else { else {
result += at(0).to_string(none, space); string tmp = at(0).to_string(none, space);
result += tmp;
if (tmp == "and" && space == "") result += " ";
} }
for (size_t i = 1, S = size(); i < S; ++i) { for (size_t i = 1, S = size(); i < S; ++i) {
if (at(i).type() == rule) { if (at(i).type() == rule) {
result += space; result += space;
result += "("; result += "(";
result += at(i).to_string(none, space); result += at(i).to_string(none, space, true);
result += ")"; result += ")";
} }
else { else {
result += " "; result += " ";
result += at(i).to_string(none, space); // result += at(i).to_string(none, space);
string tmp = at(i).to_string(none, space);
result += tmp;
if (tmp == "and" && space == "") result += " ";
} }
} }
return result; return result;
...@@ -125,6 +130,7 @@ namespace Sass { ...@@ -125,6 +130,7 @@ namespace Sass {
string result(at(0).to_string(property, space)); string result(at(0).to_string(property, space));
result += ":"; result += ":";
result += space; result += space;
if (space == "" && in_media_feature) result += " ";
result += at(1).to_string(none, space); result += at(1).to_string(none, space);
return result; return result;
} break; } break;
......
This diff was suppressed by a .gitattributes entry.
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