ext/libsass/src/parser.cpp in sassc-1.8.4 vs ext/libsass/src/parser.cpp in sassc-1.8.5
- old
+ new
@@ -198,11 +198,11 @@
else if (lex < kwd_while_directive >(true)) { (*block) << parse_while_directive(); }
else if (lex < kwd_return_directive >(true)) { (*block) << parse_return_directive(); }
// abort if we are in function context and have nothing parsed yet
else if (stack.back() == Scope::Function) {
- error("Functions can only contain variable declarations and control directives", pstate);
+ error("Functions can only contain variable declarations and control directives.", pstate);
}
// parse imports to process later
else if (lex < kwd_import >(true)) {
Scope parent = stack.empty() ? Scope::Rules : stack.back();
@@ -219,12 +219,11 @@
(*block) << SASS_MEMORY_NEW(ctx.mem, Import_Stub, pstate, imp->incs()[i]);
}
}
else if (lex < kwd_extend >(true)) {
- Scope parent = stack.empty() ? Scope::Rules : stack.back();
- if (parent == Scope::Root) {
+ if (block->is_root()) {
error("Extend directives may only be used within rules.", pstate);
}
Lookahead lookahead = lookahead_for_include(position);
if (!lookahead.found) css_error("Invalid CSS", " after ", ": expected selector, was ");
@@ -288,16 +287,11 @@
std::vector<std::pair<std::string,Function_Call*>> to_import;
bool first = true;
do {
while (lex< block_comment >());
if (lex< quoted_string >()) {
- if (!ctx.call_importers(unquote(std::string(lexed)), path, pstate, imp))
- {
- // push single file import
- // import_single_file(imp, lexed);
- to_import.push_back(std::pair<std::string,Function_Call*>(std::string(lexed), 0));
- }
+ to_import.push_back(std::pair<std::string,Function_Call*>(std::string(lexed), 0));
}
else if (lex< uri_prefix >()) {
Arguments* args = SASS_MEMORY_NEW(ctx.mem, Arguments, pstate);
Function_Call* result = SASS_MEMORY_NEW(ctx.mem, Function_Call, pstate, "url", args);
@@ -331,11 +325,11 @@
}
for(auto location : to_import) {
if (location.second) {
imp->urls().push_back(location.second);
- } else {
+ } else if (!ctx.call_importers(unquote(location.first), path, pstate, imp)) {
ctx.import_url(imp, location.first, path);
}
}
return imp;
@@ -343,11 +337,16 @@
Definition* Parser::parse_definition(Definition::Type which_type)
{
Scope parent = stack.empty() ? Scope::Rules : stack.back();
if (parent != Scope::Root && parent != Scope::Rules && parent != Scope::Function) {
- error("Functions may not be defined within control directives or other mixins.", pstate);
+ if (which_type == Definition::FUNCTION) {
+ error("Functions may not be defined within control directives or other mixins.", pstate);
+ } else {
+ error("Mixins may not be defined within control directives or other mixins.", pstate);
+ }
+
}
std::string which_str(lexed);
if (!lex< identifier >()) error("invalid name in " + which_str + " definition", pstate);
std::string name(Util::normalize_underscores(lexed));
if (which_type == Definition::FUNCTION && (name == "and" || name == "or" || name == "not"))
@@ -613,11 +612,11 @@
had_linefeed = false;
while (peek_css< exactly<','> >())
{
lex< css_comments >(false);
- // consume everything up and including the comma speparator
+ // consume everything up and including the comma separator
reloop = lex< exactly<','> >() != 0;
// remember line break (also between some commas)
had_linefeed = had_linefeed || peek_newline();
// remember line break (also between some commas)
}
@@ -717,11 +716,11 @@
return sel;
}
// EO parse_complex_selector
// parse one compound selector, which is basically
- // a list of simple selectors (directly adjancent)
+ // a list of simple selectors (directly adjacent)
// lex them exactly (without skipping white-space)
Compound_Selector* Parser::parse_compound_selector()
{
// init an empty compound selector wrapper
Compound_Selector* seq = SASS_MEMORY_NEW(ctx.mem, Compound_Selector, pstate);
@@ -745,11 +744,11 @@
{
// this produces a linefeed!?
seq->has_parent_reference(true);
(*seq) << SASS_MEMORY_NEW(ctx.mem, Parent_Selector, pstate);
// parent selector only allowed at start
- // upcoming sass may allow also trailing
+ // upcoming Sass may allow also trailing
if (seq->length() > 1) {
ParserState state(pstate);
Simple_Selector* cur = (*seq)[seq->length()-1];
Simple_Selector* prev = (*seq)[seq->length()-2];
std::string sel(prev->to_string({ NESTED, 5 }));
@@ -832,11 +831,11 @@
name.erase(name.size() - 1);
return SASS_MEMORY_NEW(ctx.mem, Wrapped_Selector, nsource_position, name, negated);
}
// a pseudo selector often starts with one or two colons
- // it can contain more selectors inside parantheses
+ // it can contain more selectors inside parentheses
Simple_Selector* Parser::parse_pseudo_selector() {
if (lex< sequence<
optional < pseudo_prefix >,
// we keep the space within the name, strange enough
// ToDo: refactor output to schedule the space for it
@@ -1211,13 +1210,13 @@
: lex<kwd_neq>() ? Sass_OP::NEQ
: lex<kwd_gte>() ? Sass_OP::GTE
: lex<kwd_lte>() ? Sass_OP::LTE
: lex<kwd_gt>() ? Sass_OP::GT
: lex<kwd_lt>() ? Sass_OP::LT
- // we checked the possibilites on top of fn
+ // we checked the possibilities on top of fn
: Sass_OP::EQ;
- // is directly adjancent to expression?
+ // is directly adjacent to expression?
bool right_ws = peek < css_comments >() != NULL;
operators.push_back({ op, left_ws, right_ws });
operands.push_back(parse_expression());
left_ws = peek < css_comments >() != NULL;
}
@@ -1236,11 +1235,10 @@
// parses multiple add and subtract operations
// NOTE: make sure that identifiers starting with
// NOTE: dashes do NOT count as subtract operation
Expression* lhs = parse_operators();
// if it's a singleton, return it (don't wrap it)
- // if it's a singleton, return it (don't wrap it)
if (!(peek_css< exactly<'+'> >(position) ||
// condition is a bit misterious, but some combinations should not be counted as operations
(peek< no_spaces >(position) && peek< sequence< negate< unsigned_number >, exactly<'-'>, negate< space > > >(position)) ||
(peek< sequence< negate< unsigned_number >, exactly<'-'>, negate< unsigned_number > > >(position))) ||
peek< sequence < zero_plus < exactly <'-' > >, identifier > >(position))
@@ -1306,11 +1304,10 @@
Expression* value = parse_map();
// lex the expected closing parenthesis
if (!lex_css< exactly<')'> >()) error("unclosed parenthesis", pstate);
// expression can be evaluated
// make sure wrapped lists and division expressions are non-delayed within parentheses
- // make sure wrapped lists and division expressions are non-delayed within parentheses
if (value->concrete_type() == Expression::LIST) {
// List* l = static_cast<List*>(value);
// if (!l->empty()) (*l)[0]->is_delayed(false);
} else if (typeid(*value) == typeid(Binary_Expression)) {
Binary_Expression* b = static_cast<Binary_Expression*>(value);
@@ -1414,11 +1411,11 @@
}
if (lex< percentage >())
{ return SASS_MEMORY_NEW(ctx.mem, Textual, pstate, Textual::PERCENTAGE, lexed); }
- // match hex number first because 0x000 looks like a number followed by an indentifier
+ // match hex number first because 0x000 looks like a number followed by an identifier
if (lex< sequence < alternatives< hex, hex0 >, negate < exactly<'-'> > > >())
{ return SASS_MEMORY_NEW(ctx.mem, Textual, pstate, Textual::HEX, lexed); }
if (lex< sequence < exactly <'#'>, identifier > >())
{ return SASS_MEMORY_NEW(ctx.mem, String_Quoted, pstate, lexed); }
@@ -1596,20 +1593,22 @@
if (peek<exactly<'}'>>()) {
css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
}
const char* e = 0;
+ const char* ee = end;
+ end = stop;
size_t num_items = 0;
bool need_space = false;
while (position < stop) {
// parse space between tokens
if (lex< spaces >() && num_items) {
need_space = true;
}
if (need_space) {
need_space = false;
- (*schema) << SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, " ");
+ // (*schema) << SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, " ");
}
if ((e = peek< re_functional >()) && e < stop) {
(*schema) << parse_function_call();
}
// lex an interpolant /#{...}/
@@ -1628,27 +1627,30 @@
(*schema) << ex;
// ToDo: no error check here?
lex < exactly < rbrace > >();
}
// lex some string constants or other valid token
- // Note: [-+] chars are left over from ie. `#{3}+3`
+ // Note: [-+] chars are left over from i.e. `#{3}+3`
else if (lex< alternatives < exactly<'%'>, exactly < '-' >, exactly < '+' > > >()) {
(*schema) << SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, lexed);
}
- else if (lex< sequence < identifier > >()) {
- (*schema) << SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, lexed);
+ // lex a quoted string
+ else if (lex< quoted_string >()) {
+ // need_space = true;
+ // if (schema->length()) (*schema) << SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, " ");
+ // else need_space = true;
+ (*schema) << parse_string();
if ((*position == '"' || *position == '\'') || peek < alternatives < alpha > >()) {
- need_space = true;
+ // need_space = true;
}
+ if (peek < exactly < '-' > >()) break;
}
- // lex a quoted string
- else if (lex< quoted_string >()) {
- (*schema) << SASS_MEMORY_NEW(ctx.mem, String_Quoted, pstate, lexed, '"');
+ else if (lex< sequence < identifier > >()) {
+ (*schema) << SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, lexed);
if ((*position == '"' || *position == '\'') || peek < alternatives < alpha > >()) {
- need_space = true;
+ // need_space = true;
}
- if (peek < exactly < '-' > >()) return schema;
}
// lex (normalized) variable
else if (lex< variable >()) {
std::string name(Util::normalize_underscores(lexed));
(*schema) << SASS_MEMORY_NEW(ctx.mem, Variable, pstate, name);
@@ -1675,14 +1677,19 @@
// lex a value in parentheses
else if (peek< parenthese_scope >()) {
(*schema) << parse_factor();
}
else {
- return schema;
+ break;
}
++num_items;
}
+ if (position != stop) {
+ (*schema) << SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, std::string(position, stop));
+ position = stop;
+ }
+ end = ee;
return schema;
}
// this parses interpolation outside other strings
// means the result must not be quoted again later
@@ -1771,18 +1778,23 @@
std::string suffix("");
if (lex< real_uri_suffix >()) {
suffix = std::string(lexed);
}
+ std::string uri("");
+ if (url_string) {
+ uri = url_string->to_string({ NESTED, 5 });
+ }
+
if (String_Schema* schema = dynamic_cast<String_Schema*>(url_string)) {
String_Schema* res = SASS_MEMORY_NEW(ctx.mem, String_Schema, pstate);
(*res) << SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, prefix);
(*res) += schema;
(*res) << SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, suffix);
return res;
} else {
- std::string res = prefix + url_string->to_string({ NESTED, 5 }) + suffix;
+ std::string res = prefix + uri + suffix;
return SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, res);
}
}
String* Parser::parse_url_function_argument()
@@ -1892,22 +1904,22 @@
{
// peek for dollar sign first
if (!peek< exactly <'$'> >()) {
css_error("Invalid CSS", " after ", ": expected \"$\", was ");
}
- // we expect a simple identfier as the call name
+ // we expect a simple identifier as the call name
if (!lex< sequence < exactly <'$'>, identifier > >()) {
lex< exactly <'$'> >(); // move pstate and position up
css_error("Invalid CSS", " after ", ": expected identifier, was ");
}
// return object
return token;
}
// helper to parse identifier
Token Parser::lex_identifier()
{
- // we expect a simple identfier as the call name
+ // we expect a simple identifier as the call name
if (!lex< identifier >()) { // ToDo: pstate wrong?
css_error("Invalid CSS", " after ", ": expected identifier, was ");
}
// return object
return token;
@@ -2090,11 +2102,11 @@
return SASS_MEMORY_NEW(ctx.mem, Supports_Interpolation, pstate, interp);
}
// TODO: This needs some major work. Although feature conditions
- // look like declarations their semantics differ siginificantly
+ // look like declarations their semantics differ significantly
Supports_Condition* Parser::parse_supports_declaration()
{
Supports_Condition* cond = 0;
// parse something declaration like
Declaration* declaration = parse_declaration();
@@ -2130,11 +2142,10 @@
{
ParserState at_source_position = pstate;
Block* body = 0;
At_Root_Expression* expr = 0;
Lookahead lookahead_result;
- // stack.push_back(Scope::Root);
LOCAL_FLAG(in_at_root, true);
if (lex< exactly<'('> >()) {
expr = parse_at_root_expression();
}
if (peek < exactly<'{'> >()) {
@@ -2145,11 +2156,10 @@
body = SASS_MEMORY_NEW(ctx.mem, Block, r->pstate(), 1, true);
*body << r;
}
At_Root_Block* at_root = SASS_MEMORY_NEW(ctx.mem, At_Root_Block, at_source_position, body);
if (expr) at_root->expression(expr);
- // stack.pop_back();
return at_root;
}
At_Root_Expression* Parser::parse_at_root_expression()
{
@@ -2257,11 +2267,11 @@
// match in one big "regex"
rv.error = p;
if (const char* q =
peek <
alternatives <
- // partial bem selector
+ // partial BEM selector
sequence <
ampersand,
one_plus <
exactly < '-' >
>,
@@ -2298,11 +2308,11 @@
// class match
exactly <'.'>,
// single or double colon
optional < pseudo_prefix >
>,
- // accept hypens in token
+ // accept hyphens in token
one_plus < sequence <
// can start with hyphens
zero_plus < exactly<'-'> >,
// now the main token
alternatives <
@@ -2387,23 +2397,31 @@
if (const char* q =
peek <
non_greedy <
alternatives <
// consume whitespace
- block_comment, spaces,
+ block_comment, // spaces,
// main tokens
- interpolant,
+ sequence <
+ interpolant,
+ optional <
+ quoted_string
+ >
+ >,
identifier,
variable,
// issue #442
sequence <
parenthese_scope,
- interpolant
+ interpolant,
+ optional <
+ quoted_string
+ >
>
>,
sequence <
- optional_spaces,
+ // optional_spaces,
alternatives <
exactly<'{'>,
exactly<'}'>,
exactly<';'>
>
@@ -2422,10 +2440,10 @@
}
// store anyway
// ToDo: remove
rv.position = q;
// check expected opening bracket
- // only after successfull matching
+ // only after successful matching
if (peek < exactly<'{'> >(q)) rv.found = q;
else if (peek < exactly<';'> >(q)) rv.found = q;
else if (peek < exactly<'}'> >(q)) rv.found = q;
}