@@ -202,7 +202,7 @@ namespace Sass {
202202 if (!lex< identifier >()) throw_syntax_error (" invalid name in @include directive" );
203203 Node name (context.new_Node (Node::identifier, path, line, lexed));
204204 Node args (parse_arguments ());
205- Node the_call (context.new_Node (Node::expansion , path, line, 2 ));
205+ Node the_call (context.new_Node (Node::mixin_call , path, line, 2 ));
206206 the_call << name << args;
207207 return the_call;
208208 }
@@ -215,12 +215,10 @@ namespace Sass {
215215 if (lex< exactly<' (' > >()) {
216216 if (!peek< exactly<' )' > >(position)) {
217217 Node arg (parse_argument (Node::none));
218- arg.should_eval () = true ;
219218 args << arg;
220219 if (arg.type () == Node::assignment) arg_type = Node::assignment;
221220 while (lex< exactly<' ,' > >()) {
222221 Node arg (parse_argument (arg_type));
223- arg.should_eval () = true ;
224222 args << arg;
225223 if (arg.type () == Node::assignment) arg_type = Node::assignment;
226224 }
@@ -239,6 +237,7 @@ namespace Sass {
239237 Node var (context.new_Node (Node::variable, path, line, lexed));
240238 lex< exactly<' :' > >();
241239 Node val (parse_space_list ());
240+ val.should_eval () = true ;
242241 Node assn (context.new_Node (Node::assignment, path, line, 2 ));
243242 assn << var << val;
244243 return assn;
@@ -254,23 +253,14 @@ namespace Sass {
254253 Node var (context.new_Node (Node::variable, path, line, lexed));
255254 lex< exactly<' :' > >();
256255 Node val (parse_space_list ());
256+ val.should_eval () = true ;
257257 Node assn (context.new_Node (Node::assignment, path, line, 2 ));
258258 assn << var << val;
259259 return assn;
260260 }
261- return parse_space_list ();
262- // if (peek< sequence < variable, spaces_and_comments, exactly<':'> > >()) {
263- // lex< variable >();
264- // Node var(context.new_Node(Node::variable, path, line, lexed));
265- // lex< exactly<':'> >();
266- // Node val(parse_space_list());
267- // Node assn(context.new_Node(Node::assignment, path, line, 2));
268- // assn << var << val;
269- // return assn;
270- // }
271- // else {
272- // return parse_space_list();
273- // }
261+ Node val (parse_space_list ());
262+ val.should_eval () = true ;
263+ return val;
274264 }
275265
276266 Node Document::parse_assignment ()
@@ -365,12 +355,15 @@ namespace Sass {
365355 Node seq1 (parse_simple_selector_sequence ());
366356 if (peek< exactly<' ,' > >() ||
367357 peek< exactly<' )' > >() ||
368- peek< exactly<' {' > >()) return seq1;
358+ peek< exactly<' {' > >() ||
359+ peek< exactly<' ;' > >()) return seq1;
369360
370361 Node selector (context.new_Node (Node::selector, path, line, 2 ));
371362 selector << seq1;
372363
373- while (!peek< exactly<' {' > >() && !peek< exactly<' ,' > >()) {
364+ while (!peek< exactly<' {' > >() &&
365+ !peek< exactly<' ,' > >() &&
366+ !peek< exactly<' ;' > >()) {
374367 selector << parse_simple_selector_sequence ();
375368 }
376369 return selector;
@@ -598,11 +591,16 @@ namespace Sass {
598591 semicolon = true ;
599592 }
600593 else if (lex< extend >()) {
601- if (surrounding_ruleset.is_null_ptr ()) throw_syntax_error (" @extend directive may only be used within rules" );
602- Node extendee (parse_simple_selector_sequence ());
603- context.extensions .insert (pair<Node, Node>(extendee, surrounding_ruleset));
604- context.has_extensions = true ;
594+ Node request (context.new_Node (Node::extend_directive, path, line, 1 ));
595+ Selector_Lookahead lookahead = lookahead_for_extension_target (position);
596+
597+ if (!lookahead.found ) throw_syntax_error (" invalid selector for @extend" );
598+
599+ if (lookahead.has_interpolants ) request << parse_selector_schema (lookahead.found );
600+ else request << parse_selector_group ();
601+
605602 semicolon = true ;
603+ block << request;
606604 }
607605 else if (peek< media >()) {
608606 block << parse_media_query (inside_of);
@@ -1016,6 +1014,7 @@ namespace Sass {
10161014 if (lex< interpolant >()) {
10171015 Token insides (Token::make (lexed.begin + 2 , lexed.end - 1 ));
10181016 Node interp_node (Document::make_from_token (context, insides, path, line).parse_list ());
1017+ interp_node.should_eval () = true ;
10191018 schema << interp_node;
10201019 }
10211020 else if (lex< identifier >()) {
@@ -1080,6 +1079,7 @@ namespace Sass {
10801079 else if (lex< interpolant >()) {
10811080 Token insides (Token::make (lexed.begin + 2 , lexed.end - 1 ));
10821081 Node interp_node (Document::make_from_token (context, insides, path, line).parse_list ());
1082+ interp_node.should_eval () = true ;
10831083 schema << interp_node;
10841084 }
10851085 else if (lex< sequence< identifier, exactly<' :' > > >()) {
@@ -1343,5 +1343,56 @@ namespace Sass {
13431343
13441344 return result;
13451345 }
1346+
1347+ Selector_Lookahead Document::lookahead_for_extension_target (const char * start)
1348+ {
1349+ const char * p = start ? start : position;
1350+ const char * q;
1351+ bool saw_interpolant = false ;
1352+
1353+ while ((q = peek< identifier >(p)) ||
1354+ (q = peek< id_name >(p)) ||
1355+ (q = peek< class_name >(p)) ||
1356+ (q = peek< sequence< pseudo_prefix, identifier > >(p)) ||
1357+ (q = peek< string_constant >(p)) ||
1358+ (q = peek< exactly<' *' > >(p)) ||
1359+ (q = peek< exactly<' (' > >(p)) ||
1360+ (q = peek< exactly<' )' > >(p)) ||
1361+ (q = peek< exactly<' [' > >(p)) ||
1362+ (q = peek< exactly<' ]' > >(p)) ||
1363+ (q = peek< exactly<' +' > >(p)) ||
1364+ (q = peek< exactly<' ~' > >(p)) ||
1365+ (q = peek< exactly<' >' > >(p)) ||
1366+ (q = peek< exactly<' ,' > >(p)) ||
1367+ (q = peek< binomial >(p)) ||
1368+ (q = peek< sequence< optional<sign>,
1369+ optional<digits>,
1370+ exactly<' n' > > >(p)) ||
1371+ (q = peek< sequence< optional<sign>,
1372+ digits > >(p)) ||
1373+ (q = peek< number >(p)) ||
1374+ (q = peek< exactly<' &' > >(p)) ||
1375+ (q = peek< alternatives<exact_match,
1376+ class_match,
1377+ dash_match,
1378+ prefix_match,
1379+ suffix_match,
1380+ substring_match> >(p)) ||
1381+ (q = peek< sequence< exactly<' .' >, interpolant > >(p)) ||
1382+ (q = peek< sequence< exactly<' #' >, interpolant > >(p)) ||
1383+ (q = peek< sequence< exactly<' -' >, interpolant > >(p)) ||
1384+ (q = peek< sequence< pseudo_prefix, interpolant > >(p)) ||
1385+ (q = peek< interpolant >(p))) {
1386+ p = q;
1387+ if (*(p - 1 ) == ' }' ) saw_interpolant = true ;
1388+ }
1389+
1390+ Selector_Lookahead result;
1391+ result.found = peek< alternatives< exactly<' ;' >, exactly<' }' > > >(p) ? p : 0 ;
1392+ result.has_interpolants = saw_interpolant;
1393+
1394+ return result;
1395+ }
1396+
13461397
13471398}
0 commit comments