Skip to content

Commit e00aec6

Browse files
committed
Fix interpolation edge case in value parsing
Fixes #442
1 parent 8ca8816 commit e00aec6

File tree

3 files changed

+33
-5
lines changed

3 files changed

+33
-5
lines changed

parser.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,13 @@ namespace Sass {
415415
string name(Util::normalize_underscores(lexed));
416416
ParserState var_source_position = pstate;
417417
if (!lex< exactly<':'> >()) error("expected ':' after " + name + " in assignment statement", pstate);
418-
Expression* val = parse_list();
418+
Expression* val;
419+
Selector_Lookahead lookahead = lookahead_for_value(position);
420+
if (lookahead.has_interpolants && lookahead.found) {
421+
val = parse_value_schema(lookahead.found);
422+
} else {
423+
val = parse_list();
424+
}
419425
val->is_delayed(false);
420426
bool is_default = false;
421427
bool is_global = false;
@@ -1553,12 +1559,18 @@ namespace Sass {
15531559
else if (lex< hex >()) {
15541560
(*schema) << new (ctx.mem) Textual(pstate, Textual::HEX, unquote(lexed));
15551561
}
1562+
else if (lex < exactly < '-' > >()) {
1563+
(*schema) << new (ctx.mem) String_Constant(pstate, lexed);
1564+
}
15561565
else if (lex< quoted_string >()) {
15571566
(*schema) << new (ctx.mem) String_Quoted(pstate, lexed);
15581567
}
15591568
else if (lex< variable >()) {
15601569
(*schema) << new (ctx.mem) Variable(pstate, Util::normalize_underscores(lexed));
15611570
}
1571+
else if (peek< parenthese_scope >()) {
1572+
(*schema) << parse_factor();
1573+
}
15621574
else {
15631575
error("error parsing interpolated value", pstate);
15641576
}
@@ -2160,23 +2172,24 @@ namespace Sass {
21602172
(q = peek< percentage >(p)) ||
21612173
(q = peek< dimension >(p)) ||
21622174
(q = peek< quoted_string >(p)) ||
2163-
(q = peek< variable >(p)) ||
2175+
(q = peek< variable >(p)) ||
21642176
(q = peek< exactly<'*'> >(p)) ||
21652177
(q = peek< exactly<'+'> >(p)) ||
21662178
(q = peek< exactly<'~'> >(p)) ||
21672179
(q = peek< exactly<'>'> >(p)) ||
21682180
(q = peek< exactly<','> >(p)) ||
2181+
(q = peek< sequence<parenthese_scope, interpolant>>(p)) ||
21692182
(saw_stuff && (q = peek< exactly<'-'> >(p))) ||
21702183
(q = peek< binomial >(p)) ||
21712184
(q = peek< block_comment >(p)) ||
21722185
(q = peek< sequence< optional<sign>,
21732186
zero_plus<digit>,
21742187
exactly<'n'> > >(p)) ||
21752188
(q = peek< sequence< optional<sign>,
2176-
one_plus<digit> > >(p)) ||
2189+
one_plus<digit> > >(p)) ||
21772190
(q = peek< number >(p)) ||
21782191
(q = peek< sequence< exactly<'&'>,
2179-
identifier_alnums > >(p)) ||
2192+
identifier_alnums > >(p)) ||
21802193
(q = peek< exactly<'&'> >(p)) ||
21812194
(q = peek< exactly<'%'> >(p)) ||
21822195
(q = peek< sequence< exactly<'.'>, interpolant > >(p)) ||

prelexer.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,5 +759,16 @@ namespace Sass {
759759
alternatives< exactly<';'>, exactly<'}'> >
760760
>(src);
761761
}
762+
763+
const char* parenthese_scope(const char* src) {
764+
return sequence <
765+
exactly < '(' >,
766+
skip_over_scopes <
767+
exactly < '(' >,
768+
exactly < ')' >
769+
>
770+
>(src);
771+
}
772+
762773
}
763774
}

prelexer.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ namespace Sass {
8686

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

@@ -108,6 +108,10 @@ namespace Sass {
108108
return 0;
109109
}
110110

111+
// skip to a skip delimited by parentheses
112+
// uses smart `skip_over_scopes` internally
113+
const char* parenthese_scope(const char* src);
114+
111115
// skip to delimiter (mx) inside given range
112116
// this will savely skip over all quoted strings
113117
// recursive skip stuff delimited by start/stop

0 commit comments

Comments
 (0)