Skip to content

Commit 8ca8816

Browse files
committed
Merge pull request #1194 from mgreter/bugfix/issue_1188
Improve ie property and expression parsing
2 parents 1a3c30d + cd18ae8 commit 8ca8816

File tree

6 files changed

+75
-36
lines changed

6 files changed

+75
-36
lines changed

debugger.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,10 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
452452
cerr << ind << "Map " << expression;
453453
cerr << " (" << pstate_source_position(node) << ")";
454454
cerr << " [Hashed]" << endl;
455+
// for (auto i : expression->elements()) {
456+
// debug_ast(i.first, ind + " key: ");
457+
// debug_ast(i.second, ind + " val: ");
458+
// }
455459
} else if (dynamic_cast<List*>(node)) {
456460
List* expression = dynamic_cast<List*>(node);
457461
cerr << ind << "List " << expression;

eval.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,8 +1018,7 @@ namespace Sass {
10181018
is_rest_argument = false;
10191019
is_keyword_argument = true;
10201020
}
1021-
else
1022-
if(val->concrete_type() != Expression::LIST) {
1021+
else if(val->concrete_type() != Expression::LIST) {
10231022
List* wrapper = new (ctx.mem) List(val->pstate(),
10241023
0,
10251024
List::COMMA,

parser.cpp

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,28 +1449,23 @@ namespace Sass {
14491449
Token str(lexed);
14501450
const char* i = str.begin;
14511451
// see if there any interpolants
1452-
const char* q;
14531452
const char* p = find_first_in_interval< exactly<hash_lbrace> >(str.begin, str.end);
14541453
if (!p) {
14551454
String_Constant* str_node = new (ctx.mem) String_Constant(pstate, normalize_wspace(string(str.begin, str.end)));
14561455
str_node->is_delayed(true);
1456+
str_node->quote_mark('*');
14571457
return str_node;
14581458
}
14591459

14601460
String_Schema* schema = new (ctx.mem) String_Schema(pstate);
14611461
while (i < str.end) {
1462-
q = find_first_in_interval< alternatives< exactly<'"'>, exactly<'\''> > >(i, str.end);
14631462
p = find_first_in_interval< exactly<hash_lbrace> >(i, str.end);
1464-
if (q && (!p || p > q)) {
1465-
if (i < q) {
1466-
(*schema) << new (ctx.mem) String_Constant(pstate, string(i, q)); // accumulate the preceding segment if it's nonempty
1467-
}
1468-
(*schema) << new (ctx.mem) String_Constant(pstate, string(q, q+1)); // capture the quote mark separately
1469-
i = q+1;
1470-
}
1471-
else if (p) {
1463+
if (p) {
14721464
if (i < p) {
1473-
(*schema) << new (ctx.mem) String_Constant(pstate, string(i, p)); // accumulate the preceding segment if it's nonempty
1465+
String_Constant* part = new (ctx.mem) String_Constant(pstate, normalize_wspace(string(i, p))); // accumulate the preceding segment if it's nonempty
1466+
part->is_delayed(true);
1467+
part->quote_mark('*'); // avoid unquote in interpolation
1468+
(*schema) << part;
14741469
}
14751470
if (peek < sequence < optional_spaces, exactly<rbrace> > >(p+2)) { position = p+2;
14761471
css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
@@ -1489,7 +1484,12 @@ namespace Sass {
14891484
}
14901485
}
14911486
else { // no interpolants left; add the last segment if nonempty
1492-
if (i < str.end) (*schema) << new (ctx.mem) String_Constant(pstate, string(i, str.end));
1487+
if (i < str.end) {
1488+
String_Constant* part = new (ctx.mem) String_Constant(pstate, normalize_wspace(string(i, str.end)));
1489+
part->is_delayed(true);
1490+
part->quote_mark('*'); // avoid unquote in interpolation
1491+
(*schema) << part;
1492+
}
14931493
break;
14941494
}
14951495
}
@@ -1503,15 +1503,13 @@ namespace Sass {
15031503
*kwd_arg << new (ctx.mem) Variable(pstate, Util::normalize_underscores(lexed));
15041504
} else {
15051505
lex< alternatives< identifier_schema, identifier > >();
1506-
*kwd_arg << new (ctx.mem) String_Quoted(pstate, lexed);
1506+
*kwd_arg << new (ctx.mem) String_Constant(pstate, lexed);
15071507
}
15081508
lex< exactly<'='> >();
1509-
*kwd_arg << new (ctx.mem) String_Quoted(pstate, lexed);
1509+
*kwd_arg << new (ctx.mem) String_Constant(pstate, lexed);
15101510
if (peek< variable >()) *kwd_arg << parse_list();
15111511
else if (lex< number >()) *kwd_arg << new (ctx.mem) Textual(pstate, Textual::NUMBER, Util::normalize_decimals(lexed));
1512-
else if (lex< alternatives< identifier_schema, identifier, number, hexa, hex > >()) {
1513-
*kwd_arg << new (ctx.mem) String_Quoted(pstate, lexed);
1514-
}
1512+
else if (peek < ie_keyword_arg_value >()) { *kwd_arg << parse_list(); }
15151513
return kwd_arg;
15161514
}
15171515

prelexer.cpp

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,12 @@ namespace Sass {
3434
{
3535
return sequence<
3636
zero_plus < space >,
37-
delimited_by<slash_star, star_slash, false> >(src);
37+
delimited_by<
38+
slash_star,
39+
star_slash,
40+
false
41+
>
42+
>(src);
3843
}
3944
/* not use anymore - remove?
4045
const char* block_comment_prefix(const char* src) {
@@ -606,7 +611,7 @@ namespace Sass {
606611
>(src);
607612
}
608613
const char* ie_expression(const char* src) {
609-
return sequence < word<expression_kwd>, delimited_by< '(', ')', true> >(src);
614+
return sequence < word<expression_kwd>, exactly<'('>, skip_over_scopes< exactly<'('>, exactly<')'> > >(src);
610615
}
611616
const char* ie_property(const char* src) {
612617
return alternatives < ie_expression, ie_progid >(src);
@@ -617,13 +622,38 @@ namespace Sass {
617622
// 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);
618623
// }
619624

625+
const char* ie_keyword_arg_property(const char* src) {
626+
return alternatives <
627+
variable,
628+
identifier_schema,
629+
identifier
630+
>(src);
631+
}
632+
const char* ie_keyword_arg_value(const char* src) {
633+
return alternatives <
634+
variable,
635+
identifier_schema,
636+
identifier,
637+
quoted_string,
638+
number,
639+
hexa,
640+
sequence <
641+
exactly < '(' >,
642+
skip_over_scopes <
643+
exactly < '(' >,
644+
exactly < ')' >
645+
>
646+
>
647+
>(src);
648+
}
649+
620650
const char* ie_keyword_arg(const char* src) {
621-
return sequence<
622-
alternatives< variable, identifier_schema, identifier >,
651+
return sequence <
652+
ie_keyword_arg_property,
623653
optional_css_whitespace,
624654
exactly<'='>,
625655
optional_css_whitespace,
626-
alternatives< variable, identifier_schema, identifier, quoted_string, number, hexa >
656+
ie_keyword_arg_value
627657
>(src);
628658
}
629659

prelexer.hpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ namespace Sass {
5858
// recursive skip stuff delimited by start/stop
5959
// first start/opener must be consumed already!
6060
template<prelexer start, prelexer stop>
61-
const char* skip_over_scopes(const char* src, const char* end = 0) {
61+
const char* skip_over_scopes(const char* src, const char* end) {
6262

6363
size_t level = 0;
6464
bool in_squote = false;
@@ -85,8 +85,9 @@ namespace Sass {
8585
}
8686

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

9293
// look for the closer (maybe final, maybe not)
@@ -96,6 +97,8 @@ namespace Sass {
9697
// return position at end of stop
9798
// delimiter may be multiple chars
9899
else return final;
100+
// advance position
101+
src = final - 1;
99102
}
100103

101104
// next
@@ -105,6 +108,15 @@ namespace Sass {
105108
return 0;
106109
}
107110

111+
// skip to delimiter (mx) inside given range
112+
// this will savely skip over all quoted strings
113+
// recursive skip stuff delimited by start/stop
114+
// first start/opener must be consumed already!
115+
template<prelexer start, prelexer stop>
116+
const char* skip_over_scopes(const char* src) {
117+
return skip_over_scopes<start, stop>(src, 0);
118+
}
119+
108120
// Match a sequence of characters delimited by the supplied chars.
109121
template <prelexer start, prelexer stop>
110122
const char* recursive_scopes(const char* src) {
@@ -296,6 +308,8 @@ namespace Sass {
296308
const char* ie_expression(const char* src);
297309
const char* ie_property(const char* src);
298310
const char* ie_keyword_arg(const char* src);
311+
const char* ie_keyword_arg_value(const char* src);
312+
const char* ie_keyword_arg_property(const char* src);
299313

300314
// match urls
301315
const char* url(const char* src);

util.cpp

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -262,21 +262,15 @@ namespace Sass {
262262
{
263263
bool ws = false;
264264
bool esc = false;
265-
char inside_str = 0;
266265
string text = "";
267-
for(auto i : str) {
266+
for(const char& i : str) {
268267
if (!esc && i == '\\') {
269268
esc = true;
269+
ws = false;
270270
text += i;
271271
} else if (esc) {
272272
esc = false;
273-
text += i;
274-
} else if (!inside_str && (i == '"' || i == '\'')) {
275-
inside_str = i;
276-
text += i;
277-
} else if (inside_str) {
278-
if (i == inside_str)
279-
inside_str = false;
273+
ws = false;
280274
text += i;
281275
} else if (
282276
i == ' ' ||

0 commit comments

Comments
 (0)