Commit 5c16dd51 by Aaron Leung

Parsing and evaluating arbitrary directives.

parent 60e53749
...@@ -166,6 +166,7 @@ namespace Sass { ...@@ -166,6 +166,7 @@ namespace Sass {
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);
Node parse_while_directive(Node surrounding_ruleset, Node::Type inside_of = Node::none); Node parse_while_directive(Node surrounding_ruleset, Node::Type inside_of = Node::none);
Node parse_directive(Node surrounding_ruleset, Node::Type inside_of = Node::none);
Node parse_media_query(Node::Type inside_of = Node::none); Node parse_media_query(Node::Type inside_of = Node::none);
Node parse_media_expression(); Node parse_media_expression();
Node parse_warning(); Node parse_warning();
......
...@@ -58,6 +58,13 @@ namespace Sass { ...@@ -58,6 +58,13 @@ namespace Sass {
root << parse_warning(); root << parse_warning();
if (!lex< exactly<';'> >()) throw_syntax_error("top-level @warn directive must be terminated by ';'"); if (!lex< exactly<';'> >()) throw_syntax_error("top-level @warn directive must be terminated by ';'");
} }
else if (peek< directive >()) {
Node dir(parse_directive(Node(), Node::none));
if (dir.type() == Node::blockless_directive) {
if (!lex< exactly<';'> >()) throw_syntax_error("top-level blockless directive must be terminated by ';'");
}
root << dir;
}
else if (peek< spaces >() || peek< block_comment >() || peek< line_comment >()) { else if (peek< spaces >() || peek< block_comment >() || peek< line_comment >()) {
lex< spaces_and_comments >(); lex< spaces_and_comments >();
continue; continue;
...@@ -553,6 +560,11 @@ namespace Sass { ...@@ -553,6 +560,11 @@ namespace Sass {
else if (peek< media >()) { else if (peek< media >()) {
block << parse_media_query(inside_of); block << parse_media_query(inside_of);
} }
else if (peek< directive >()) {
Node dir(parse_directive(surrounding_ruleset, inside_of));
if (dir.type() == Node::blockless_directive) semicolon = true;
block << dir;
}
else if (!peek< exactly<';'> >()) { else if (!peek< exactly<';'> >()) {
Node rule(parse_rule()); Node rule(parse_rule());
// check for lbrace; if it's there, we have a namespace property with a value // check for lbrace; if it's there, we have a namespace property with a value
...@@ -1055,6 +1067,17 @@ namespace Sass { ...@@ -1055,6 +1067,17 @@ namespace Sass {
return loop; return loop;
} }
Node Document::parse_directive(Node surrounding_ruleset, Node::Type inside_of)
{
lex< directive >();
Node dir_name(context.new_Node(Node::blockless_directive, path, line, lexed));
if (!peek< exactly<'{'> >()) return dir_name;
Node block(parse_block(surrounding_ruleset, inside_of));
Node dir(context.new_Node(Node::block_directive, path, line, 2));
dir << dir_name << block;
return dir;
}
Node Document::parse_media_query(Node::Type inside_of) Node Document::parse_media_query(Node::Type inside_of)
{ {
lex< media >(); lex< media >();
......
...@@ -407,6 +407,12 @@ namespace Sass { ...@@ -407,6 +407,12 @@ namespace Sass {
} }
} break; } break;
case Node::block_directive: {
// TO DO: eval the directive name for interpolants
eval(expr[1], new_Node(Node::none, expr.path(), expr.line(), 0), env, f_env, new_Node, ctx);
return expr;
} break;
case Node::warning: { case Node::warning: {
expr[0] = eval(expr[0], prefix, env, f_env, new_Node, ctx); expr[0] = eval(expr[0], prefix, env, f_env, new_Node, ctx);
return expr; return expr;
......
...@@ -164,6 +164,9 @@ namespace Sass { ...@@ -164,6 +164,9 @@ namespace Sass {
warning, warning,
block_directive,
blockless_directive,
variable, variable,
assignment assignment
}; };
...@@ -297,21 +300,31 @@ namespace Sass { ...@@ -297,21 +300,31 @@ namespace Sass {
case Node::css_import: case Node::css_import:
case Node::rule: case Node::rule:
case Node::propset: case Node::propset:
case Node::warning: has_statements = true; break; case Node::warning:
case Node::block_directive:
case Node::blockless_directive: {
has_statements = true;
} break;
case Node::media_query: case Node::media_query:
case Node::ruleset: has_blocks = true; break; case Node::ruleset: {
has_blocks = true;
} break;
case Node::if_directive: case Node::if_directive:
case Node::for_through_directive: case Node::for_through_directive:
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::expansion: {
has_expansions = true;
} break;
case Node::backref: has_backref = true; break; case Node::backref: {
has_backref = true;
} break;
default: break; default: break;
} }
if (n.has_backref()) has_backref = true; if (n.has_backref()) has_backref = true;
} }
......
...@@ -185,6 +185,10 @@ namespace Sass { ...@@ -185,6 +185,10 @@ namespace Sass {
return exactly<warn_kwd>(src); return exactly<warn_kwd>(src);
} }
const char* directive(const char* src) {
return sequence< exactly<'@'>, identifier >(src);
}
// Match CSS type selectors // Match CSS type selectors
const char* namespace_prefix(const char* src) { const char* namespace_prefix(const char* src) {
return sequence< optional< alternatives< identifier, exactly<'*'> > >, return sequence< optional< alternatives< identifier, exactly<'*'> > >,
......
...@@ -331,6 +331,8 @@ namespace Sass { ...@@ -331,6 +331,8 @@ namespace Sass {
const char* warn(const char* src); const char* warn(const char* src);
const char* directive(const char* src);
// Match CSS type selectors // Match CSS type selectors
const char* namespace_prefix(const char* src); const char* namespace_prefix(const char* src);
const char* type_selector(const char* src); const char* type_selector(const char* src);
......
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