Skip to content

Commit

Permalink
Improve ie property and expression parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
mgreter committed May 11, 2015
1 parent fb82f0b commit cd18ae8
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 36 deletions.
4 changes: 4 additions & 0 deletions debugger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,10 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
cerr << ind << "Map " << expression;
cerr << " (" << pstate_source_position(node) << ")";
cerr << " [Hashed]" << endl;
// for (auto i : expression->elements()) {
// debug_ast(i.first, ind + " key: ");
// debug_ast(i.second, ind + " val: ");
// }
} else if (dynamic_cast<List*>(node)) {
List* expression = dynamic_cast<List*>(node);
cerr << ind << "List " << expression;
Expand Down
3 changes: 1 addition & 2 deletions eval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1018,8 +1018,7 @@ namespace Sass {
is_rest_argument = false;
is_keyword_argument = true;
}
else
if(val->concrete_type() != Expression::LIST) {
else if(val->concrete_type() != Expression::LIST) {
List* wrapper = new (ctx.mem) List(val->pstate(),
0,
List::COMMA,
Expand Down
32 changes: 15 additions & 17 deletions parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1458,28 +1458,23 @@ namespace Sass {
Token str(lexed);
const char* i = str.begin;
// see if there any interpolants
const char* q;
const char* p = find_first_in_interval< exactly<hash_lbrace> >(str.begin, str.end);
if (!p) {
String_Constant* str_node = new (ctx.mem) String_Constant(pstate, normalize_wspace(string(str.begin, str.end)));
str_node->is_delayed(true);
str_node->quote_mark('*');
return str_node;
}

String_Schema* schema = new (ctx.mem) String_Schema(pstate);
while (i < str.end) {
q = find_first_in_interval< alternatives< exactly<'"'>, exactly<'\''> > >(i, str.end);
p = find_first_in_interval< exactly<hash_lbrace> >(i, str.end);
if (q && (!p || p > q)) {
if (i < q) {
(*schema) << new (ctx.mem) String_Constant(pstate, string(i, q)); // accumulate the preceding segment if it's nonempty
}
(*schema) << new (ctx.mem) String_Constant(pstate, string(q, q+1)); // capture the quote mark separately
i = q+1;
}
else if (p) {
if (p) {
if (i < p) {
(*schema) << new (ctx.mem) String_Constant(pstate, string(i, p)); // accumulate the preceding segment if it's nonempty
String_Constant* part = new (ctx.mem) String_Constant(pstate, normalize_wspace(string(i, p))); // accumulate the preceding segment if it's nonempty
part->is_delayed(true);
part->quote_mark('*'); // avoid unquote in interpolation
(*schema) << part;
}
if (peek < sequence < optional_spaces, exactly<rbrace> > >(p+2)) { position = p+2;
css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
Expand All @@ -1498,7 +1493,12 @@ namespace Sass {
}
}
else { // no interpolants left; add the last segment if nonempty
if (i < str.end) (*schema) << new (ctx.mem) String_Constant(pstate, string(i, str.end));
if (i < str.end) {
String_Constant* part = new (ctx.mem) String_Constant(pstate, normalize_wspace(string(i, str.end)));
part->is_delayed(true);
part->quote_mark('*'); // avoid unquote in interpolation
(*schema) << part;
}
break;
}
}
Expand All @@ -1512,15 +1512,13 @@ namespace Sass {
*kwd_arg << new (ctx.mem) Variable(pstate, Util::normalize_underscores(lexed));
} else {
lex< alternatives< identifier_schema, identifier > >();
*kwd_arg << new (ctx.mem) String_Quoted(pstate, lexed);
*kwd_arg << new (ctx.mem) String_Constant(pstate, lexed);
}
lex< exactly<'='> >();
*kwd_arg << new (ctx.mem) String_Quoted(pstate, lexed);
*kwd_arg << new (ctx.mem) String_Constant(pstate, lexed);
if (peek< variable >()) *kwd_arg << parse_list();
else if (lex< number >()) *kwd_arg << new (ctx.mem) Textual(pstate, Textual::NUMBER, Util::normalize_decimals(lexed));
else if (lex< alternatives< identifier_schema, identifier, number, hexa, hex > >()) {
*kwd_arg << new (ctx.mem) String_Quoted(pstate, lexed);
}
else if (peek < ie_keyword_arg_value >()) { *kwd_arg << parse_list(); }
return kwd_arg;
}

Expand Down
40 changes: 35 additions & 5 deletions prelexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,12 @@ namespace Sass {
{
return sequence<
zero_plus < space >,
delimited_by<slash_star, star_slash, false> >(src);
delimited_by<
slash_star,
star_slash,
false
>
>(src);
}
/* not use anymore - remove?
const char* block_comment_prefix(const char* src) {
Expand Down Expand Up @@ -606,7 +611,7 @@ namespace Sass {
>(src);
}
const char* ie_expression(const char* src) {
return sequence < word<expression_kwd>, delimited_by< '(', ')', true> >(src);
return sequence < word<expression_kwd>, exactly<'('>, skip_over_scopes< exactly<'('>, exactly<')'> > >(src);
}
const char* ie_property(const char* src) {
return alternatives < ie_expression, ie_progid >(src);
Expand All @@ -617,13 +622,38 @@ namespace Sass {
// zero_plus< sequence< optional_css_whitespace, exactly<','>, optional_css_whitespace, alternatives< ie_keyword_arg, value_schema, quoted_string, interpolant, number, identifier, delimited_by<'(', ')', true> > > > >(src);
// }

const char* ie_keyword_arg_property(const char* src) {
return alternatives <
variable,
identifier_schema,
identifier
>(src);
}
const char* ie_keyword_arg_value(const char* src) {
return alternatives <
variable,
identifier_schema,
identifier,
quoted_string,
number,
hexa,
sequence <
exactly < '(' >,
skip_over_scopes <
exactly < '(' >,
exactly < ')' >
>
>
>(src);
}

const char* ie_keyword_arg(const char* src) {
return sequence<
alternatives< variable, identifier_schema, identifier >,
return sequence <
ie_keyword_arg_property,
optional_css_whitespace,
exactly<'='>,
optional_css_whitespace,
alternatives< variable, identifier_schema, identifier, quoted_string, number, hexa >
ie_keyword_arg_value
>(src);
}

Expand Down
20 changes: 17 additions & 3 deletions prelexer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ namespace Sass {
// recursive skip stuff delimited by start/stop
// first start/opener must be consumed already!
template<prelexer start, prelexer stop>
const char* skip_over_scopes(const char* src, const char* end = 0) {
const char* skip_over_scopes(const char* src, const char* end) {

size_t level = 0;
bool in_squote = false;
Expand All @@ -85,8 +85,9 @@ namespace Sass {
}

// find another opener inside?
else if (start(src)) {
++ level; // increase counter
else if (const char* pos = start(src)) {
++ level; // increase stack counter
src = pos - 1; // advance position
}

// look for the closer (maybe final, maybe not)
Expand All @@ -96,6 +97,8 @@ namespace Sass {
// return position at end of stop
// delimiter may be multiple chars
else return final;
// advance position
src = final - 1;
}

// next
Expand All @@ -105,6 +108,15 @@ namespace Sass {
return 0;
}

// skip to delimiter (mx) inside given range
// this will savely skip over all quoted strings
// recursive skip stuff delimited by start/stop
// first start/opener must be consumed already!
template<prelexer start, prelexer stop>
const char* skip_over_scopes(const char* src) {
return skip_over_scopes<start, stop>(src, 0);
}

// Match a sequence of characters delimited by the supplied chars.
template <prelexer start, prelexer stop>
const char* recursive_scopes(const char* src) {
Expand Down Expand Up @@ -296,6 +308,8 @@ namespace Sass {
const char* ie_expression(const char* src);
const char* ie_property(const char* src);
const char* ie_keyword_arg(const char* src);
const char* ie_keyword_arg_value(const char* src);
const char* ie_keyword_arg_property(const char* src);

// match urls
const char* url(const char* src);
Expand Down
12 changes: 3 additions & 9 deletions util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,21 +262,15 @@ namespace Sass {
{
bool ws = false;
bool esc = false;
char inside_str = 0;
string text = "";
for(auto i : str) {
for(const char& i : str) {
if (!esc && i == '\\') {
esc = true;
ws = false;
text += i;
} else if (esc) {
esc = false;
text += i;
} else if (!inside_str && (i == '"' || i == '\'')) {
inside_str = i;
text += i;
} else if (inside_str) {
if (i == inside_str)
inside_str = false;
ws = false;
text += i;
} else if (
i == ' ' ||
Expand Down

0 comments on commit cd18ae8

Please sign in to comment.