Initial commit
[yaffs-website] / node_modules / node-sass / src / libsass / src / parser.cpp
1 #include "sass.hpp"
2 #include "parser.hpp"
3 #include "file.hpp"
4 #include "inspect.hpp"
5 #include "constants.hpp"
6 #include "util.hpp"
7 #include "prelexer.hpp"
8 #include "color_maps.hpp"
9 #include "sass/functions.h"
10 #include "error_handling.hpp"
11
12 // Notes about delayed: some ast nodes can have delayed evaluation so
13 // they can preserve their original semantics if needed. This is most
14 // prominently exhibited by the division operation, since it is not
15 // only a valid operation, but also a valid css statement (i.e. for
16 // fonts, as in `16px/24px`). When parsing lists and expression we
17 // unwrap single items from lists and other operations. A nested list
18 // must not be delayed, only the items of the first level sometimes
19 // are delayed (as with argument lists). To achieve this we need to
20 // pass status to the list parser, so this can be set correctly.
21 // Another case with delayed values are colors. In compressed mode
22 // only processed values get compressed (other are left as written).
23
24 #include <cstdlib>
25 #include <iostream>
26 #include <vector>
27 #include <typeinfo>
28
29 namespace Sass {
30   using namespace Constants;
31   using namespace Prelexer;
32
33   Parser Parser::from_c_str(const char* beg, Context& ctx, ParserState pstate, const char* source)
34   {
35     pstate.offset.column = 0;
36     pstate.offset.line = 0;
37     Parser p(ctx, pstate);
38     p.source   = source ? source : beg;
39     p.position = beg ? beg : p.source;
40     p.end      = p.position + strlen(p.position);
41     Block_Obj root = SASS_MEMORY_NEW(Block, pstate);
42     p.block_stack.push_back(root);
43     root->is_root(true);
44     return p;
45   }
46
47   Parser Parser::from_c_str(const char* beg, const char* end, Context& ctx, ParserState pstate, const char* source)
48   {
49     pstate.offset.column = 0;
50     pstate.offset.line = 0;
51     Parser p(ctx, pstate);
52     p.source   = source ? source : beg;
53     p.position = beg ? beg : p.source;
54     p.end      = end ? end : p.position + strlen(p.position);
55     Block_Obj root = SASS_MEMORY_NEW(Block, pstate);
56     p.block_stack.push_back(root);
57     root->is_root(true);
58     return p;
59   }
60
61    void Parser::advanceToNextToken() {
62       lex < css_comments >(false);
63       // advance to position
64       pstate += pstate.offset;
65       pstate.offset.column = 0;
66       pstate.offset.line = 0;
67     }
68
69   Selector_List_Obj Parser::parse_selector(const char* beg, Context& ctx, ParserState pstate, const char* source)
70   {
71     Parser p = Parser::from_c_str(beg, ctx, pstate, source);
72     // ToDo: ruby sass errors on parent references
73     // ToDo: remap the source-map entries somehow
74     return p.parse_selector_list(false);
75   }
76
77   bool Parser::peek_newline(const char* start)
78   {
79     return peek_linefeed(start ? start : position)
80            && ! peek_css<exactly<'{'>>(start);
81   }
82
83   Parser Parser::from_token(Token t, Context& ctx, ParserState pstate, const char* source)
84   {
85     Parser p(ctx, pstate);
86     p.source   = source ? source : t.begin;
87     p.position = t.begin ? t.begin : p.source;
88     p.end      = t.end ? t.end : p.position + strlen(p.position);
89     Block_Obj root = SASS_MEMORY_NEW(Block, pstate);
90     p.block_stack.push_back(root);
91     root->is_root(true);
92     return p;
93   }
94
95   /* main entry point to parse root block */
96   Block_Obj Parser::parse()
97   {
98
99     // consume unicode BOM
100     read_bom();
101
102     // create a block AST node to hold children
103     Block_Obj root = SASS_MEMORY_NEW(Block, pstate, 0, true);
104
105     // check seems a bit esoteric but works
106     if (ctx.resources.size() == 1) {
107       // apply headers only on very first include
108       ctx.apply_custom_headers(root, path, pstate);
109     }
110
111     // parse children nodes
112     block_stack.push_back(root);
113     parse_block_nodes(true);
114     block_stack.pop_back();
115
116     // update final position
117     root->update_pstate(pstate);
118
119     if (position != end) {
120       css_error("Invalid CSS", " after ", ": expected selector or at-rule, was ");
121     }
122
123     return root;
124   }
125
126
127   // convenience function for block parsing
128   // will create a new block ad-hoc for you
129   // this is the base block parsing function
130   Block_Obj Parser::parse_css_block(bool is_root)
131   {
132
133     // parse comments before block
134     // lex < optional_css_comments >();
135
136     // lex mandatory opener or error out
137     if (!lex_css < exactly<'{'> >()) {
138       css_error("Invalid CSS", " after ", ": expected \"{\", was ");
139     }
140     // create new block and push to the selector stack
141     Block_Obj block = SASS_MEMORY_NEW(Block, pstate, 0, is_root);
142     block_stack.push_back(block);
143
144     if (!parse_block_nodes(is_root)) css_error("Invalid CSS", " after ", ": expected \"}\", was ");
145
146     if (!lex_css < exactly<'}'> >()) {
147       css_error("Invalid CSS", " after ", ": expected \"}\", was ");
148     }
149
150     // update for end position
151     // this seems to be done somewhere else
152     // but that fixed selector schema issue
153     // block->update_pstate(pstate);
154
155     // parse comments after block
156     // lex < optional_css_comments >();
157
158     block_stack.pop_back();
159
160     return block;
161   }
162
163   // convenience function for block parsing
164   // will create a new block ad-hoc for you
165   // also updates the `in_at_root` flag
166   Block_Obj Parser::parse_block(bool is_root)
167   {
168     return parse_css_block(is_root);
169   }
170
171   // the main block parsing function
172   // parses stuff between `{` and `}`
173   bool Parser::parse_block_nodes(bool is_root)
174   {
175
176     // loop until end of string
177     while (position < end) {
178
179       // we should be able to refactor this
180       parse_block_comments();
181       lex < css_whitespace >();
182
183       if (lex < exactly<';'> >()) continue;
184       if (peek < end_of_file >()) return true;
185       if (peek < exactly<'}'> >()) return true;
186
187       if (parse_block_node(is_root)) continue;
188
189       parse_block_comments();
190
191       if (lex_css < exactly<';'> >()) continue;
192       if (peek_css < end_of_file >()) return true;
193       if (peek_css < exactly<'}'> >()) return true;
194
195       // illegal sass
196       return false;
197     }
198     // return success
199     return true;
200   }
201
202   // parser for a single node in a block
203   // semicolons must be lexed beforehand
204   bool Parser::parse_block_node(bool is_root) {
205
206     Block_Obj block = block_stack.back();
207
208     parse_block_comments();
209
210     // throw away white-space
211     // includes line comments
212     lex < css_whitespace >();
213
214     Lookahead lookahead_result;
215
216     // also parse block comments
217
218     // first parse everything that is allowed in functions
219     if (lex < variable >(true)) { block->append(parse_assignment()); }
220     else if (lex < kwd_err >(true)) { block->append(parse_error()); }
221     else if (lex < kwd_dbg >(true)) { block->append(parse_debug()); }
222     else if (lex < kwd_warn >(true)) { block->append(parse_warning()); }
223     else if (lex < kwd_if_directive >(true)) { block->append(parse_if_directive()); }
224     else if (lex < kwd_for_directive >(true)) { block->append(parse_for_directive()); }
225     else if (lex < kwd_each_directive >(true)) { block->append(parse_each_directive()); }
226     else if (lex < kwd_while_directive >(true)) { block->append(parse_while_directive()); }
227     else if (lex < kwd_return_directive >(true)) { block->append(parse_return_directive()); }
228
229     // parse imports to process later
230     else if (lex < kwd_import >(true)) {
231       Scope parent = stack.empty() ? Scope::Rules : stack.back();
232       if (parent != Scope::Function && parent != Scope::Root && parent != Scope::Rules && parent != Scope::Media) {
233         if (! peek_css< uri_prefix >(position)) { // this seems to go in ruby sass 3.4.20
234           error("Import directives may not be used within control directives or mixins.", pstate);
235         }
236       }
237       // this puts the parsed doc into sheets
238       // import stub will fetch this in expand
239       Import_Obj imp = parse_import();
240       // if it is a url, we only add the statement
241       if (!imp->urls().empty()) block->append(imp);
242       // process all resources now (add Import_Stub nodes)
243       for (size_t i = 0, S = imp->incs().size(); i < S; ++i) {
244         block->append(SASS_MEMORY_NEW(Import_Stub, pstate, imp->incs()[i]));
245       }
246     }
247
248     else if (lex < kwd_extend >(true)) {
249       Lookahead lookahead = lookahead_for_include(position);
250       if (!lookahead.found) css_error("Invalid CSS", " after ", ": expected selector, was ");
251       Selector_List_Obj target;
252       if (!lookahead.has_interpolants) {
253         target = parse_selector_list(true);
254       }
255       else {
256         target = SASS_MEMORY_NEW(Selector_List, pstate);
257         target->schema(parse_selector_schema(lookahead.found, true));
258       }
259
260       block->append(SASS_MEMORY_NEW(Extension, pstate, target));
261     }
262
263     // selector may contain interpolations which need delayed evaluation
264     else if (!(lookahead_result = lookahead_for_selector(position)).error)
265     { block->append(parse_ruleset(lookahead_result)); }
266
267     // parse multiple specific keyword directives
268     else if (lex < kwd_media >(true)) { block->append(parse_media_block()); }
269     else if (lex < kwd_at_root >(true)) { block->append(parse_at_root_block()); }
270     else if (lex < kwd_include_directive >(true)) { block->append(parse_include_directive()); }
271     else if (lex < kwd_content_directive >(true)) { block->append(parse_content_directive()); }
272     else if (lex < kwd_supports_directive >(true)) { block->append(parse_supports_directive()); }
273     else if (lex < kwd_mixin >(true)) { block->append(parse_definition(Definition::MIXIN)); }
274     else if (lex < kwd_function >(true)) { block->append(parse_definition(Definition::FUNCTION)); }
275
276     // ignore the @charset directive for now
277     else if (lex< kwd_charset_directive >(true)) { parse_charset_directive(); }
278
279     // generic at keyword (keep last)
280     else if (lex< re_special_directive >(true)) { block->append(parse_special_directive()); }
281     else if (lex< re_prefixed_directive >(true)) { block->append(parse_prefixed_directive()); }
282     else if (lex< at_keyword >(true)) { block->append(parse_directive()); }
283
284     else if (is_root /* && block->is_root() */) {
285       lex< css_whitespace >();
286       if (position >= end) return true;
287       css_error("Invalid CSS", " after ", ": expected 1 selector or at-rule, was ");
288     }
289     // parse a declaration
290     else
291     {
292       // ToDo: how does it handle parse errors?
293       // maybe we are expected to parse something?
294       Declaration_Obj decl = parse_declaration();
295       decl->tabs(indentation);
296       block->append(decl);
297       // maybe we have a "sub-block"
298       if (peek< exactly<'{'> >()) {
299         if (decl->is_indented()) ++ indentation;
300         // parse a propset that rides on the declaration's property
301         stack.push_back(Scope::Properties);
302         decl->block(parse_block());
303         stack.pop_back();
304         if (decl->is_indented()) -- indentation;
305       }
306     }
307     // something matched
308     return true;
309   }
310   // EO parse_block_nodes
311
312   // parse imports inside the
313   Import_Obj Parser::parse_import()
314   {
315     Import_Obj imp = SASS_MEMORY_NEW(Import, pstate);
316     std::vector<std::pair<std::string,Function_Call_Obj>> to_import;
317     bool first = true;
318     do {
319       while (lex< block_comment >());
320       if (lex< quoted_string >()) {
321         to_import.push_back(std::pair<std::string,Function_Call_Obj>(std::string(lexed), 0));
322       }
323       else if (lex< uri_prefix >()) {
324         Arguments_Obj args = SASS_MEMORY_NEW(Arguments, pstate);
325         Function_Call_Obj result = SASS_MEMORY_NEW(Function_Call, pstate, "url", args);
326
327         if (lex< quoted_string >()) {
328           Expression_Obj the_url = parse_string();
329           args->append(SASS_MEMORY_NEW(Argument, the_url->pstate(), the_url));
330         }
331         else if (String_Obj the_url = parse_url_function_argument()) {
332           args->append(SASS_MEMORY_NEW(Argument, the_url->pstate(), the_url));
333         }
334         else if (peek < skip_over_scopes < exactly < '(' >, exactly < ')' > > >(position)) {
335           Expression_Obj the_url = parse_list(); // parse_interpolated_chunk(lexed);
336           args->append(SASS_MEMORY_NEW(Argument, the_url->pstate(), the_url));
337         }
338         else {
339           error("malformed URL", pstate);
340         }
341         if (!lex< exactly<')'> >()) error("URI is missing ')'", pstate);
342         to_import.push_back(std::pair<std::string, Function_Call_Obj>("", result));
343       }
344       else {
345         if (first) error("@import directive requires a url or quoted path", pstate);
346         else error("expecting another url or quoted path in @import list", pstate);
347       }
348       first = false;
349     } while (lex_css< exactly<','> >());
350
351     if (!peek_css< alternatives< exactly<';'>, exactly<'}'>, end_of_file > >()) {
352       List_Obj import_queries = parse_media_queries();
353       imp->import_queries(import_queries);
354     }
355
356     for(auto location : to_import) {
357       if (location.second) {
358         imp->urls().push_back(location.second);
359       }
360       // check if custom importers want to take over the handling
361       else if (!ctx.call_importers(unquote(location.first), path, pstate, imp)) {
362         // nobody wants it, so we do our import
363         ctx.import_url(imp, location.first, path);
364       }
365     }
366
367     return imp;
368   }
369
370   Definition_Obj Parser::parse_definition(Definition::Type which_type)
371   {
372     std::string which_str(lexed);
373     if (!lex< identifier >()) error("invalid name in " + which_str + " definition", pstate);
374     std::string name(Util::normalize_underscores(lexed));
375     if (which_type == Definition::FUNCTION && (name == "and" || name == "or" || name == "not"))
376     { error("Invalid function name \"" + name + "\".", pstate); }
377     ParserState source_position_of_def = pstate;
378     Parameters_Obj params = parse_parameters();
379     if (which_type == Definition::MIXIN) stack.push_back(Scope::Mixin);
380     else stack.push_back(Scope::Function);
381     Block_Obj body = parse_block();
382     stack.pop_back();
383     return SASS_MEMORY_NEW(Definition, source_position_of_def, name, params, body, which_type);
384   }
385
386   Parameters_Obj Parser::parse_parameters()
387   {
388     std::string name(lexed);
389     Position position = after_token;
390     Parameters_Obj params = SASS_MEMORY_NEW(Parameters, pstate);
391     if (lex_css< exactly<'('> >()) {
392       // if there's anything there at all
393       if (!peek_css< exactly<')'> >()) {
394         do params->append(parse_parameter());
395         while (lex_css< exactly<','> >());
396       }
397       if (!lex_css< exactly<')'> >()) error("expected a variable name (e.g. $x) or ')' for the parameter list for " + name, position);
398     }
399     return params;
400   }
401
402   Parameter_Obj Parser::parse_parameter()
403   {
404     while (lex< alternatives < spaces, block_comment > >());
405     lex < variable >();
406     std::string name(Util::normalize_underscores(lexed));
407     ParserState pos = pstate;
408     Expression_Obj val;
409     bool is_rest = false;
410     while (lex< alternatives < spaces, block_comment > >());
411     if (lex< exactly<':'> >()) { // there's a default value
412       while (lex< block_comment >());
413       val = parse_space_list();
414     }
415     else if (lex< exactly< ellipsis > >()) {
416       is_rest = true;
417     }
418     return SASS_MEMORY_NEW(Parameter, pos, name, val, is_rest);
419   }
420
421   Arguments_Obj Parser::parse_arguments()
422   {
423     std::string name(lexed);
424     Position position = after_token;
425     Arguments_Obj args = SASS_MEMORY_NEW(Arguments, pstate);
426     if (lex_css< exactly<'('> >()) {
427       // if there's anything there at all
428       if (!peek_css< exactly<')'> >()) {
429         do args->append(parse_argument());
430         while (lex_css< exactly<','> >());
431       }
432       if (!lex_css< exactly<')'> >()) error("expected a variable name (e.g. $x) or ')' for the parameter list for " + name, position);
433     }
434     return args;
435   }
436
437   Argument_Obj Parser::parse_argument()
438   {
439     if (peek_css< sequence < exactly< hash_lbrace >, exactly< rbrace > > >()) {
440       position += 2;
441       css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
442     }
443
444     Argument_Obj arg;
445     if (peek_css< sequence < variable, optional_css_comments, exactly<':'> > >()) {
446       lex_css< variable >();
447       std::string name(Util::normalize_underscores(lexed));
448       ParserState p = pstate;
449       lex_css< exactly<':'> >();
450       Expression_Obj val = parse_space_list();
451       arg = SASS_MEMORY_NEW(Argument, p, val, name);
452     }
453     else {
454       bool is_arglist = false;
455       bool is_keyword = false;
456       Expression_Obj val = parse_space_list();
457       List_Ptr l = Cast<List>(val);
458       if (lex_css< exactly< ellipsis > >()) {
459         if (val->concrete_type() == Expression::MAP || (
460            (l != NULL && l->separator() == SASS_HASH)
461         )) is_keyword = true;
462         else is_arglist = true;
463       }
464       arg = SASS_MEMORY_NEW(Argument, pstate, val, "", is_arglist, is_keyword);
465     }
466     return arg;
467   }
468
469   Assignment_Obj Parser::parse_assignment()
470   {
471     std::string name(Util::normalize_underscores(lexed));
472     ParserState var_source_position = pstate;
473     if (!lex< exactly<':'> >()) error("expected ':' after " + name + " in assignment statement", pstate);
474     if (peek_css< alternatives < exactly<';'>, end_of_file > >()) {
475       css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
476     }
477     Expression_Obj val;
478     Lookahead lookahead = lookahead_for_value(position);
479     if (lookahead.has_interpolants && lookahead.found) {
480       val = parse_value_schema(lookahead.found);
481     } else {
482       val = parse_list();
483     }
484     bool is_default = false;
485     bool is_global = false;
486     while (peek< alternatives < default_flag, global_flag > >()) {
487       if (lex< default_flag >()) is_default = true;
488       else if (lex< global_flag >()) is_global = true;
489     }
490     return SASS_MEMORY_NEW(Assignment, var_source_position, name, val, is_default, is_global);
491   }
492
493   // a ruleset connects a selector and a block
494   Ruleset_Obj Parser::parse_ruleset(Lookahead lookahead)
495   {
496     // inherit is_root from parent block
497     Block_Obj parent = block_stack.back();
498     bool is_root = parent && parent->is_root();
499     // make sure to move up the the last position
500     lex < optional_css_whitespace >(false, true);
501     // create the connector object (add parts later)
502     Ruleset_Obj ruleset = SASS_MEMORY_NEW(Ruleset, pstate);
503     // parse selector static or as schema to be evaluated later
504     if (lookahead.parsable) ruleset->selector(parse_selector_list(false));
505     else {
506       Selector_List_Obj list = SASS_MEMORY_NEW(Selector_List, pstate);
507       list->schema(parse_selector_schema(lookahead.found, false));
508       ruleset->selector(list);
509     }
510     // then parse the inner block
511     stack.push_back(Scope::Rules);
512     ruleset->block(parse_block());
513     stack.pop_back();
514     // update for end position
515     ruleset->update_pstate(pstate);
516     ruleset->block()->update_pstate(pstate);
517     // need this info for sanity checks
518     ruleset->is_root(is_root);
519     // return AST Node
520     return ruleset;
521   }
522
523   // parse a selector schema that will be evaluated in the eval stage
524   // uses a string schema internally to do the actual schema handling
525   // in the eval stage we will be re-parse it into an actual selector
526   Selector_Schema_Obj Parser::parse_selector_schema(const char* end_of_selector, bool chroot)
527   {
528     // move up to the start
529     lex< optional_spaces >();
530     const char* i = position;
531     // selector schema re-uses string schema implementation
532     String_Schema_Ptr schema = SASS_MEMORY_NEW(String_Schema, pstate);
533     // the selector schema is pretty much just a wrapper for the string schema
534     Selector_Schema_Ptr selector_schema = SASS_MEMORY_NEW(Selector_Schema, pstate, schema);
535     selector_schema->connect_parent(chroot == false);
536     selector_schema->media_block(last_media_block);
537
538     // process until end
539     while (i < end_of_selector) {
540       // try to parse mutliple interpolants
541       if (const char* p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, end_of_selector)) {
542         // accumulate the preceding segment if the position has advanced
543         if (i < p) {
544           std::string parsed(i, p);
545           String_Constant_Obj str = SASS_MEMORY_NEW(String_Constant, pstate, parsed);
546           pstate += Offset(parsed);
547           str->update_pstate(pstate);
548           schema->append(str);
549         }
550
551         // check if the interpolation only contains white-space (error out)
552         if (peek < sequence < optional_spaces, exactly<rbrace> > >(p+2)) { position = p+2;
553           css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
554         }
555         // skip over all nested inner interpolations up to our own delimiter
556         const char* j = skip_over_scopes< exactly<hash_lbrace>, exactly<rbrace> >(p + 2, end_of_selector);
557         // pass inner expression to the parser to resolve nested interpolations
558         pstate.add(p, p+2);
559         Expression_Obj interpolant = Parser::from_c_str(p+2, j, ctx, pstate).parse_list();
560         // set status on the list expression
561         interpolant->is_interpolant(true);
562         // schema->has_interpolants(true);
563         // add to the string schema
564         schema->append(interpolant);
565         // advance parser state
566         pstate.add(p+2, j);
567         // advance position
568         i = j;
569       }
570       // no more interpolants have been found
571       // add the last segment if there is one
572       else {
573         // make sure to add the last bits of the string up to the end (if any)
574         if (i < end_of_selector) {
575           std::string parsed(i, end_of_selector);
576           String_Constant_Obj str = SASS_MEMORY_NEW(String_Constant, pstate, parsed);
577           pstate += Offset(parsed);
578           str->update_pstate(pstate);
579           i = end_of_selector;
580           schema->append(str);
581         }
582         // exit loop
583       }
584     }
585     // EO until eos
586
587     // update position
588     position = i;
589
590     // update for end position
591     selector_schema->update_pstate(pstate);
592     schema->update_pstate(pstate);
593
594     after_token = before_token = pstate;
595
596     // return parsed result
597     return selector_schema;
598   }
599   // EO parse_selector_schema
600
601   void Parser::parse_charset_directive()
602   {
603     lex <
604       sequence <
605         quoted_string,
606         optional_spaces,
607         exactly <';'>
608       >
609     >();
610   }
611
612   // called after parsing `kwd_include_directive`
613   Mixin_Call_Obj Parser::parse_include_directive()
614   {
615     // lex identifier into `lexed` var
616     lex_identifier(); // may error out
617     // normalize underscores to hyphens
618     std::string name(Util::normalize_underscores(lexed));
619     // create the initial mixin call object
620     Mixin_Call_Obj call = SASS_MEMORY_NEW(Mixin_Call, pstate, name, 0, 0);
621     // parse mandatory arguments
622     call->arguments(parse_arguments());
623     // parse optional block
624     if (peek < exactly <'{'> >()) {
625       call->block(parse_block());
626     }
627     // return ast node
628     return call.detach();
629   }
630   // EO parse_include_directive
631
632   // parse a list of complex selectors
633   // this is the main entry point for most
634   Selector_List_Obj Parser::parse_selector_list(bool chroot)
635   {
636     bool reloop = true;
637     bool had_linefeed = false;
638     Complex_Selector_Obj sel;
639     Selector_List_Obj group = SASS_MEMORY_NEW(Selector_List, pstate);
640     group->media_block(last_media_block);
641
642     if (peek_css< alternatives < end_of_file, exactly <'{'> > >()) {
643       css_error("Invalid CSS", " after ", ": expected selector, was ");
644     }
645
646     do {
647       reloop = false;
648
649       had_linefeed = had_linefeed || peek_newline();
650
651       if (peek_css< alternatives < class_char < selector_list_delims > > >())
652         break; // in case there are superfluous commas at the end
653
654       // now parse the complex selector
655       sel = parse_complex_selector(chroot);
656
657       if (!sel) return group.detach();
658
659       sel->has_line_feed(had_linefeed);
660
661       had_linefeed = false;
662
663       while (peek_css< exactly<','> >())
664       {
665         lex< css_comments >(false);
666         // consume everything up and including the comma separator
667         reloop = lex< exactly<','> >() != 0;
668         // remember line break (also between some commas)
669         had_linefeed = had_linefeed || peek_newline();
670         // remember line break (also between some commas)
671       }
672       group->append(sel);
673     }
674     while (reloop);
675     while (lex_css< kwd_optional >()) {
676       group->is_optional(true);
677     }
678     // update for end position
679     group->update_pstate(pstate);
680     if (sel) sel->last()->has_line_break(false);
681     return group.detach();
682   }
683   // EO parse_selector_list
684
685   // a complex selector combines a compound selector with another
686   // complex selector, with one of four combinator operations.
687   // the compound selector (head) is optional, since the combinator
688   // can come first in the whole selector sequence (like `> DIV').
689   Complex_Selector_Obj Parser::parse_complex_selector(bool chroot)
690   {
691
692     String_Ptr reference = 0;
693     lex < block_comment >();
694     advanceToNextToken();
695     Complex_Selector_Obj sel = SASS_MEMORY_NEW(Complex_Selector, pstate);
696
697     if (peek < end_of_file >()) return 0;
698
699     // parse the left hand side
700     Compound_Selector_Obj lhs;
701     // special case if it starts with combinator ([+~>])
702     if (!peek_css< class_char < selector_combinator_ops > >()) {
703       // parse the left hand side
704       lhs = parse_compound_selector();
705     }
706
707
708     // parse combinator between lhs and rhs
709     Complex_Selector::Combinator combinator = Complex_Selector::ANCESTOR_OF;
710     if      (lex< exactly<'+'> >()) combinator = Complex_Selector::ADJACENT_TO;
711     else if (lex< exactly<'~'> >()) combinator = Complex_Selector::PRECEDES;
712     else if (lex< exactly<'>'> >()) combinator = Complex_Selector::PARENT_OF;
713     else if (lex< sequence < exactly<'/'>, negate < exactly < '*' > > > >()) {
714       // comments are allowed, but not spaces?
715       combinator = Complex_Selector::REFERENCE;
716       if (!lex < re_reference_combinator >()) return 0;
717       reference = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
718       if (!lex < exactly < '/' > >()) return 0; // ToDo: error msg?
719     }
720
721     if (!lhs && combinator == Complex_Selector::ANCESTOR_OF) return 0;
722
723     // lex < block_comment >();
724     sel->head(lhs);
725     sel->combinator(combinator);
726     sel->media_block(last_media_block);
727
728     if (combinator == Complex_Selector::REFERENCE) sel->reference(reference);
729     // has linfeed after combinator?
730     sel->has_line_break(peek_newline());
731     // sel->has_line_feed(has_line_feed);
732
733     // check if we got the abort condition (ToDo: optimize)
734     if (!peek_css< class_char < complex_selector_delims > >()) {
735       // parse next selector in sequence
736       sel->tail(parse_complex_selector(true));
737     }
738
739     // add a parent selector if we are not in a root
740     // also skip adding parent ref if we only have refs
741     if (!sel->has_parent_ref() && !chroot) {
742       // create the objects to wrap parent selector reference
743       Compound_Selector_Obj head = SASS_MEMORY_NEW(Compound_Selector, pstate);
744       Parent_Selector_Ptr parent = SASS_MEMORY_NEW(Parent_Selector, pstate, false);
745       parent->media_block(last_media_block);
746       head->media_block(last_media_block);
747       // add simple selector
748       head->append(parent);
749       // selector may not have any head yet
750       if (!sel->head()) { sel->head(head); }
751       // otherwise we need to create a new complex selector and set the old one as its tail
752       else {
753         sel = SASS_MEMORY_NEW(Complex_Selector, pstate, Complex_Selector::ANCESTOR_OF, head, sel);
754         sel->media_block(last_media_block);
755       }
756       // peek for linefeed and remember result on head
757       // if (peek_newline()) head->has_line_break(true);
758     }
759
760     sel->update_pstate(pstate);
761     // complex selector
762     return sel;
763   }
764   // EO parse_complex_selector
765
766   // parse one compound selector, which is basically
767   // a list of simple selectors (directly adjacent)
768   // lex them exactly (without skipping white-space)
769   Compound_Selector_Obj Parser::parse_compound_selector()
770   {
771     // init an empty compound selector wrapper
772     Compound_Selector_Obj seq = SASS_MEMORY_NEW(Compound_Selector, pstate);
773     seq->media_block(last_media_block);
774
775     // skip initial white-space
776     lex< css_whitespace >();
777
778     // parse list
779     while (true)
780     {
781       // remove all block comments (don't skip white-space)
782       lex< delimited_by< slash_star, star_slash, false > >(false);
783       // parse functional
784       if (match < re_pseudo_selector >())
785       {
786         seq->append(parse_simple_selector());
787       }
788       // parse parent selector
789       else if (lex< exactly<'&'> >(false))
790       {
791         // this produces a linefeed!?
792         seq->has_parent_reference(true);
793         seq->append(SASS_MEMORY_NEW(Parent_Selector, pstate));
794         // parent selector only allowed at start
795         // upcoming Sass may allow also trailing
796         if (seq->length() > 1) {
797           ParserState state(pstate);
798           Simple_Selector_Obj cur = (*seq)[seq->length()-1];
799           Simple_Selector_Obj prev = (*seq)[seq->length()-2];
800           std::string sel(prev->to_string({ NESTED, 5 }));
801           std::string found(cur->to_string({ NESTED, 5 }));
802           if (lex < identifier >()) { found += std::string(lexed); }
803           error("Invalid CSS after \"" + sel + "\": expected \"{\", was \"" + found + "\"\n\n"
804             "\"" + found + "\" may only be used at the beginning of a compound selector.", state);
805         }
806       }
807       // parse type selector
808       else if (lex< re_type_selector >(false))
809       {
810         seq->append(SASS_MEMORY_NEW(Element_Selector, pstate, lexed));
811       }
812       // peek for abort conditions
813       else if (peek< spaces >()) break;
814       else if (peek< end_of_file >()) { break; }
815       else if (peek_css < class_char < selector_combinator_ops > >()) break;
816       else if (peek_css < class_char < complex_selector_delims > >()) break;
817       // otherwise parse another simple selector
818       else {
819         Simple_Selector_Obj sel = parse_simple_selector();
820         if (!sel) return 0;
821         seq->append(sel);
822       }
823     }
824
825     if (seq && !peek_css<alternatives<end_of_file,exactly<'{'>>>()) {
826       seq->has_line_break(peek_newline());
827     }
828
829     // EO while true
830     return seq;
831
832   }
833   // EO parse_compound_selector
834
835   Simple_Selector_Obj Parser::parse_simple_selector()
836   {
837     lex < css_comments >(false);
838     if (lex< class_name >()) {
839       return SASS_MEMORY_NEW(Class_Selector, pstate, lexed);
840     }
841     else if (lex< id_name >()) {
842       return SASS_MEMORY_NEW(Id_Selector, pstate, lexed);
843     }
844     else if (lex< quoted_string >()) {
845       return SASS_MEMORY_NEW(Element_Selector, pstate, unquote(lexed));
846     }
847     else if (lex< alternatives < variable, number, static_reference_combinator > >()) {
848       return SASS_MEMORY_NEW(Element_Selector, pstate, lexed);
849     }
850     else if (peek< pseudo_not >()) {
851       return parse_negated_selector();
852     }
853     else if (peek< re_pseudo_selector >()) {
854       return parse_pseudo_selector();
855     }
856     else if (peek< exactly<':'> >()) {
857       return parse_pseudo_selector();
858     }
859     else if (lex < exactly<'['> >()) {
860       return parse_attribute_selector();
861     }
862     else if (lex< placeholder >()) {
863       Placeholder_Selector_Ptr sel = SASS_MEMORY_NEW(Placeholder_Selector, pstate, lexed);
864       sel->media_block(last_media_block);
865       return sel;
866     }
867     // failed
868     return 0;
869   }
870
871   Wrapped_Selector_Obj Parser::parse_negated_selector()
872   {
873     lex< pseudo_not >();
874     std::string name(lexed);
875     ParserState nsource_position = pstate;
876     Selector_List_Obj negated = parse_selector_list(true);
877     if (!lex< exactly<')'> >()) {
878       error("negated selector is missing ')'", pstate);
879     }
880     name.erase(name.size() - 1);
881     return SASS_MEMORY_NEW(Wrapped_Selector, nsource_position, name, negated);
882   }
883
884   // a pseudo selector often starts with one or two colons
885   // it can contain more selectors inside parentheses
886   Simple_Selector_Obj Parser::parse_pseudo_selector() {
887     if (lex< sequence<
888           optional < pseudo_prefix >,
889           // we keep the space within the name, strange enough
890           // ToDo: refactor output to schedule the space for it
891           // or do we really want to keep the real white-space?
892           sequence< identifier, optional < block_comment >, exactly<'('> >
893         > >())
894     {
895
896       std::string name(lexed);
897       name.erase(name.size() - 1);
898       ParserState p = pstate;
899
900       // specially parse static stuff
901       // ToDo: really everything static?
902       if (peek_css <
903             sequence <
904               alternatives <
905                 static_value,
906                 binomial
907               >,
908               optional_css_whitespace,
909               exactly<')'>
910             >
911           >()
912       ) {
913         lex_css< alternatives < static_value, binomial > >();
914         String_Constant_Ptr expr = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
915         if (expr && lex_css< exactly<')'> >()) {
916           expr->can_compress_whitespace(true);
917           return SASS_MEMORY_NEW(Pseudo_Selector, p, name, expr);
918         }
919       }
920       else if (Selector_List_Obj wrapped = parse_selector_list(true)) {
921         if (wrapped && lex_css< exactly<')'> >()) {
922           return SASS_MEMORY_NEW(Wrapped_Selector, p, name, wrapped);
923         }
924       }
925
926     }
927     // EO if pseudo selector
928
929     else if (lex < sequence< optional < pseudo_prefix >, identifier > >()) {
930       return SASS_MEMORY_NEW(Pseudo_Selector, pstate, lexed);
931     }
932     else if(lex < pseudo_prefix >()) {
933       css_error("Invalid CSS", " after ", ": expected pseudoclass or pseudoelement, was ");
934     }
935
936     css_error("Invalid CSS", " after ", ": expected \")\", was ");
937
938     // unreachable statement
939     return 0;
940   }
941
942   Attribute_Selector_Obj Parser::parse_attribute_selector()
943   {
944     ParserState p = pstate;
945     if (!lex_css< attribute_name >()) error("invalid attribute name in attribute selector", pstate);
946     std::string name(lexed);
947     if (lex_css< alternatives < exactly<']'>, exactly<'/'> > >()) return SASS_MEMORY_NEW(Attribute_Selector, p, name, "", 0);
948     if (!lex_css< alternatives< exact_match, class_match, dash_match,
949                                 prefix_match, suffix_match, substring_match > >()) {
950       error("invalid operator in attribute selector for " + name, pstate);
951     }
952     std::string matcher(lexed);
953
954     String_Obj value = 0;
955     if (lex_css< identifier >()) {
956       value = SASS_MEMORY_NEW(String_Constant, p, lexed);
957     }
958     else if (lex_css< quoted_string >()) {
959       value = parse_interpolated_chunk(lexed, true); // needed!
960     }
961     else {
962       error("expected a string constant or identifier in attribute selector for " + name, pstate);
963     }
964
965     if (!lex_css< alternatives < exactly<']'>, exactly<'/'> > >()) error("unterminated attribute selector for " + name, pstate);
966     return SASS_MEMORY_NEW(Attribute_Selector, p, name, matcher, value);
967   }
968
969   /* parse block comment and add to block */
970   void Parser::parse_block_comments()
971   {
972     Block_Obj block = block_stack.back();
973
974     while (lex< block_comment >()) {
975       bool is_important = lexed.begin[2] == '!';
976       // flag on second param is to skip loosely over comments
977       String_Obj contents = parse_interpolated_chunk(lexed, true);
978       block->append(SASS_MEMORY_NEW(Comment, pstate, contents, is_important));
979     }
980   }
981
982   Declaration_Obj Parser::parse_declaration() {
983     String_Obj prop;
984     if (lex< sequence< optional< exactly<'*'> >, identifier_schema > >()) {
985       prop = parse_identifier_schema();
986     }
987     else if (lex< sequence< optional< exactly<'*'> >, identifier, zero_plus< block_comment > > >()) {
988       prop = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
989     }
990     else {
991       css_error("Invalid CSS", " after ", ": expected \"}\", was ");
992     }
993     bool is_indented = true;
994     const std::string property(lexed);
995     if (!lex_css< one_plus< exactly<':'> > >()) error("property \"" + property + "\" must be followed by a ':'", pstate);
996     lex < css_comments >(false);
997     if (peek_css< exactly<';'> >()) error("style declaration must contain a value", pstate);
998     if (peek_css< exactly<'{'> >()) is_indented = false; // don't indent if value is empty
999     if (peek_css< static_value >()) {
1000       return SASS_MEMORY_NEW(Declaration, prop->pstate(), prop, parse_static_value()/*, lex<kwd_important>()*/);
1001     }
1002     else {
1003       Expression_Obj value;
1004       Lookahead lookahead = lookahead_for_value(position);
1005       if (lookahead.found) {
1006         if (lookahead.has_interpolants) {
1007           value = parse_value_schema(lookahead.found);
1008         } else {
1009           value = parse_list(DELAYED);
1010         }
1011       }
1012       else {
1013         value = parse_list(DELAYED);
1014         if (List_Ptr list = Cast<List>(value)) {
1015           if (!list->is_bracketed() && list->length() == 0 && !peek< exactly <'{'> >()) {
1016             css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
1017           }
1018         }
1019       }
1020       lex < css_comments >(false);
1021       Declaration_Obj decl = SASS_MEMORY_NEW(Declaration, prop->pstate(), prop, value/*, lex<kwd_important>()*/);
1022       decl->is_indented(is_indented);
1023       decl->update_pstate(pstate);
1024       return decl;
1025     }
1026   }
1027
1028   // parse +/- and return false if negative
1029   // this is never hit via spec tests
1030   bool Parser::parse_number_prefix()
1031   {
1032     bool positive = true;
1033     while(true) {
1034       if (lex < block_comment >()) continue;
1035       if (lex < number_prefix >()) continue;
1036       if (lex < exactly < '-' > >()) {
1037         positive = !positive;
1038         continue;
1039       }
1040       break;
1041     }
1042     return positive;
1043   }
1044
1045   Expression_Obj Parser::parse_map()
1046   {
1047     Expression_Obj key = parse_list();
1048     List_Obj map = SASS_MEMORY_NEW(List, pstate, 0, SASS_HASH);
1049
1050     // it's not a map so return the lexed value as a list value
1051     if (!lex_css< exactly<':'> >())
1052     { return key; }
1053
1054     Expression_Obj value = parse_space_list();
1055
1056     map->append(key);
1057     map->append(value);
1058
1059     while (lex_css< exactly<','> >())
1060     {
1061       // allow trailing commas - #495
1062       if (peek_css< exactly<')'> >(position))
1063       { break; }
1064
1065       Expression_Obj key = parse_space_list();
1066
1067       if (!(lex< exactly<':'> >()))
1068       { css_error("Invalid CSS", " after ", ": expected \":\", was "); }
1069
1070       Expression_Obj value = parse_space_list();
1071
1072       map->append(key);
1073       map->append(value);
1074     }
1075
1076     ParserState ps = map->pstate();
1077     ps.offset = pstate - ps + pstate.offset;
1078     map->pstate(ps);
1079
1080     return map;
1081   }
1082
1083   Expression_Obj Parser::parse_bracket_list()
1084   {
1085     // check if we have an empty list
1086     // return the empty list as such
1087     if (peek_css< list_terminator >(position))
1088     {
1089       // return an empty list (nothing to delay)
1090       return SASS_MEMORY_NEW(List, pstate, 0, SASS_SPACE, false, true);
1091     }
1092
1093     bool has_paren = peek_css< exactly<'('> >() != NULL;
1094
1095     // now try to parse a space list
1096     Expression_Obj list = parse_space_list();
1097     // if it's a singleton, return it (don't wrap it)
1098     if (!peek_css< exactly<','> >(position)) {
1099       List_Obj l = Cast<List>(list);
1100       if (!l || l->is_bracketed() || has_paren) {
1101         List_Obj bracketed_list = SASS_MEMORY_NEW(List, pstate, 1, SASS_SPACE, false, true);
1102         bracketed_list->append(list);
1103         return bracketed_list;
1104       }
1105       l->is_bracketed(true);
1106       return l;
1107     }
1108
1109     // if we got so far, we actually do have a comma list
1110     List_Obj bracketed_list = SASS_MEMORY_NEW(List, pstate, 2, SASS_COMMA, false, true);
1111     // wrap the first expression
1112     bracketed_list->append(list);
1113
1114     while (lex_css< exactly<','> >())
1115     {
1116       // check for abort condition
1117       if (peek_css< list_terminator >(position)
1118       ) { break; }
1119       // otherwise add another expression
1120       bracketed_list->append(parse_space_list());
1121     }
1122     // return the list
1123     return bracketed_list;
1124   }
1125
1126   // parse list returns either a space separated list,
1127   // a comma separated list or any bare expression found.
1128   // so to speak: we unwrap items from lists if possible here!
1129   Expression_Obj Parser::parse_list(bool delayed)
1130   {
1131     return parse_comma_list(delayed);
1132   }
1133
1134   // will return singletons unwrapped
1135   Expression_Obj Parser::parse_comma_list(bool delayed)
1136   {
1137     // check if we have an empty list
1138     // return the empty list as such
1139     if (peek_css< list_terminator >(position))
1140     {
1141       // return an empty list (nothing to delay)
1142       return SASS_MEMORY_NEW(List, pstate, 0);
1143     }
1144
1145     // now try to parse a space list
1146     Expression_Obj list = parse_space_list();
1147     // if it's a singleton, return it (don't wrap it)
1148     if (!peek_css< exactly<','> >(position)) {
1149       // set_delay doesn't apply to list children
1150       // so this will only undelay single values
1151       if (!delayed) list->set_delayed(false);
1152       return list;
1153     }
1154
1155     // if we got so far, we actually do have a comma list
1156     List_Obj comma_list = SASS_MEMORY_NEW(List, pstate, 2, SASS_COMMA);
1157     // wrap the first expression
1158     comma_list->append(list);
1159
1160     while (lex_css< exactly<','> >())
1161     {
1162       // check for abort condition
1163       if (peek_css< list_terminator >(position)
1164       ) { break; }
1165       // otherwise add another expression
1166       comma_list->append(parse_space_list());
1167     }
1168     // return the list
1169     return comma_list;
1170   }
1171   // EO parse_comma_list
1172
1173   // will return singletons unwrapped
1174   Expression_Obj Parser::parse_space_list()
1175   {
1176     Expression_Obj disj1 = parse_disjunction();
1177     // if it's a singleton, return it (don't wrap it)
1178     if (peek_css< space_list_terminator >(position)
1179     ) {
1180       return disj1; }
1181
1182     List_Obj space_list = SASS_MEMORY_NEW(List, pstate, 2, SASS_SPACE);
1183     space_list->append(disj1);
1184
1185     while (
1186       !(peek_css< space_list_terminator >(position)) &&
1187       peek_css< optional_css_whitespace >() != end
1188     ) {
1189       // the space is parsed implicitly?
1190       space_list->append(parse_disjunction());
1191     }
1192     // return the list
1193     return space_list;
1194   }
1195   // EO parse_space_list
1196
1197   // parse logical OR operation
1198   Expression_Obj Parser::parse_disjunction()
1199   {
1200     advanceToNextToken();
1201     ParserState state(pstate);
1202     // parse the left hand side conjunction
1203     Expression_Obj conj = parse_conjunction();
1204     // parse multiple right hand sides
1205     std::vector<Expression_Obj> operands;
1206     while (lex_css< kwd_or >())
1207       operands.push_back(parse_conjunction());
1208     // if it's a singleton, return it directly
1209     if (operands.size() == 0) return conj;
1210     // fold all operands into one binary expression
1211     Expression_Obj ex = fold_operands(conj, operands, { Sass_OP::OR });
1212     state.offset = pstate - state + pstate.offset;
1213     ex->pstate(state);
1214     return ex;
1215   }
1216   // EO parse_disjunction
1217
1218   // parse logical AND operation
1219   Expression_Obj Parser::parse_conjunction()
1220   {
1221     advanceToNextToken();
1222     ParserState state(pstate);
1223     // parse the left hand side relation
1224     Expression_Obj rel = parse_relation();
1225     // parse multiple right hand sides
1226     std::vector<Expression_Obj> operands;
1227     while (lex_css< kwd_and >()) {
1228       operands.push_back(parse_relation());
1229     }
1230     // if it's a singleton, return it directly
1231     if (operands.size() == 0) return rel;
1232     // fold all operands into one binary expression
1233     Expression_Obj ex = fold_operands(rel, operands, { Sass_OP::AND });
1234     state.offset = pstate - state + pstate.offset;
1235     ex->pstate(state);
1236     return ex;
1237   }
1238   // EO parse_conjunction
1239
1240   // parse comparison operations
1241   Expression_Obj Parser::parse_relation()
1242   {
1243     advanceToNextToken();
1244     ParserState state(pstate);
1245     // parse the left hand side expression
1246     Expression_Obj lhs = parse_expression();
1247     std::vector<Expression_Obj> operands;
1248     std::vector<Operand> operators;
1249     // if it's a singleton, return it (don't wrap it)
1250     while (peek< alternatives <
1251             kwd_eq,
1252             kwd_neq,
1253             kwd_gte,
1254             kwd_gt,
1255             kwd_lte,
1256             kwd_lt
1257           > >(position))
1258     {
1259       // is directly adjancent to expression?
1260       bool left_ws = peek < css_comments >() != NULL;
1261       // parse the operator
1262       enum Sass_OP op
1263       = lex<kwd_eq>()  ? Sass_OP::EQ
1264       : lex<kwd_neq>() ? Sass_OP::NEQ
1265       : lex<kwd_gte>() ? Sass_OP::GTE
1266       : lex<kwd_lte>() ? Sass_OP::LTE
1267       : lex<kwd_gt>()  ? Sass_OP::GT
1268       : lex<kwd_lt>()  ? Sass_OP::LT
1269       // we checked the possibilities on top of fn
1270       :                  Sass_OP::EQ;
1271       // is directly adjacent to expression?
1272       bool right_ws = peek < css_comments >() != NULL;
1273       operators.push_back({ op, left_ws, right_ws });
1274       operands.push_back(parse_expression());
1275       left_ws = peek < css_comments >() != NULL;
1276     }
1277     // we are called recursively for list, so we first
1278     // fold inner binary expression which has delayed
1279     // correctly set to zero. After folding we also unwrap
1280     // single nested items. So we cannot set delay on the
1281     // returned result here, as we have lost nestings ...
1282     Expression_Obj ex = fold_operands(lhs, operands, operators);
1283     state.offset = pstate - state + pstate.offset;
1284     ex->pstate(state);
1285     return ex;
1286   }
1287   // parse_relation
1288
1289   // parse expression valid for operations
1290   // called from parse_relation
1291   // called from parse_for_directive
1292   // called from parse_media_expression
1293   // parse addition and subtraction operations
1294   Expression_Obj Parser::parse_expression()
1295   {
1296     advanceToNextToken();
1297     ParserState state(pstate);
1298     // parses multiple add and subtract operations
1299     // NOTE: make sure that identifiers starting with
1300     // NOTE: dashes do NOT count as subtract operation
1301     Expression_Obj lhs = parse_operators();
1302     // if it's a singleton, return it (don't wrap it)
1303     if (!(peek_css< exactly<'+'> >(position) ||
1304           // condition is a bit misterious, but some combinations should not be counted as operations
1305           (peek< no_spaces >(position) && peek< sequence< negate< unsigned_number >, exactly<'-'>, negate< space > > >(position)) ||
1306           (peek< sequence< negate< unsigned_number >, exactly<'-'>, negate< unsigned_number > > >(position))) ||
1307           peek< sequence < zero_plus < exactly <'-' > >, identifier > >(position))
1308     { return lhs; }
1309
1310     std::vector<Expression_Obj> operands;
1311     std::vector<Operand> operators;
1312     bool left_ws = peek < css_comments >() != NULL;
1313     while (
1314       lex_css< exactly<'+'> >() ||
1315
1316       (
1317       ! peek_css< sequence < zero_plus < exactly <'-' > >, identifier > >(position)
1318       && lex_css< sequence< negate< digit >, exactly<'-'> > >()
1319       )
1320
1321     ) {
1322
1323       bool right_ws = peek < css_comments >() != NULL;
1324       operators.push_back({ lexed.to_string() == "+" ? Sass_OP::ADD : Sass_OP::SUB, left_ws, right_ws });
1325       operands.push_back(parse_operators());
1326       left_ws = peek < css_comments >() != NULL;
1327     }
1328
1329     if (operands.size() == 0) return lhs;
1330     Expression_Obj ex = fold_operands(lhs, operands, operators);
1331     state.offset = pstate - state + pstate.offset;
1332     ex->pstate(state);
1333     return ex;
1334   }
1335
1336   // parse addition and subtraction operations
1337   Expression_Obj Parser::parse_operators()
1338   {
1339     advanceToNextToken();
1340     ParserState state(pstate);
1341     Expression_Obj factor = parse_factor();
1342     // if it's a singleton, return it (don't wrap it)
1343     std::vector<Expression_Obj> operands; // factors
1344     std::vector<Operand> operators; // ops
1345     // lex operations to apply to lhs
1346     const char* left_ws = peek < css_comments >();
1347     while (lex_css< class_char< static_ops > >()) {
1348       const char* right_ws = peek < css_comments >();
1349       switch(*lexed.begin) {
1350         case '*': operators.push_back({ Sass_OP::MUL, left_ws != 0, right_ws != 0 }); break;
1351         case '/': operators.push_back({ Sass_OP::DIV, left_ws != 0, right_ws != 0 }); break;
1352         case '%': operators.push_back({ Sass_OP::MOD, left_ws != 0, right_ws != 0 }); break;
1353         default: throw std::runtime_error("unknown static op parsed"); break;
1354       }
1355       operands.push_back(parse_factor());
1356       left_ws = peek < css_comments >();
1357     }
1358     // operands and operators to binary expression
1359     Expression_Obj ex = fold_operands(factor, operands, operators);
1360     state.offset = pstate - state + pstate.offset;
1361     ex->pstate(state);
1362     return ex;
1363   }
1364   // EO parse_operators
1365
1366
1367   // called from parse_operators
1368   // called from parse_value_schema
1369   Expression_Obj Parser::parse_factor()
1370   {
1371     lex < css_comments >(false);
1372     if (lex_css< exactly<'('> >()) {
1373       // parse_map may return a list
1374       Expression_Obj value = parse_map();
1375       // lex the expected closing parenthesis
1376       if (!lex_css< exactly<')'> >()) error("unclosed parenthesis", pstate);
1377       // expression can be evaluated
1378       return value;
1379     }
1380     else if (lex_css< exactly<'['> >()) {
1381       // explicit bracketed
1382       Expression_Obj value = parse_bracket_list();
1383       // lex the expected closing square bracket
1384       if (!lex_css< exactly<']'> >()) error("unclosed squared bracket", pstate);
1385       return value;
1386     }
1387     // string may be interpolated
1388     // if (lex< quoted_string >()) {
1389     //   return &parse_string();
1390     // }
1391     else if (peek< ie_property >()) {
1392       return parse_ie_property();
1393     }
1394     else if (peek< ie_keyword_arg >()) {
1395       return parse_ie_keyword_arg();
1396     }
1397     else if (peek< sequence < calc_fn_call, exactly <'('> > >()) {
1398       return parse_calc_function();
1399     }
1400     else if (lex < functional_schema >()) {
1401       return parse_function_call_schema();
1402     }
1403     else if (lex< identifier_schema >()) {
1404       String_Obj string = parse_identifier_schema();
1405       if (String_Schema_Ptr schema = Cast<String_Schema>(string)) {
1406         if (lex < exactly < '(' > >()) {
1407           schema->append(parse_list());
1408           lex < exactly < ')' > >();
1409         }
1410       }
1411       return string;
1412     }
1413     else if (peek< sequence< uri_prefix, W, real_uri_value > >()) {
1414       return parse_url_function_string();
1415     }
1416     else if (peek< re_functional >()) {
1417       return parse_function_call();
1418     }
1419     else if (lex< exactly<'+'> >()) {
1420       Unary_Expression_Ptr ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::PLUS, parse_factor());
1421       if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
1422       return ex;
1423     }
1424     else if (lex< exactly<'-'> >()) {
1425       Unary_Expression_Ptr ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::MINUS, parse_factor());
1426       if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
1427       return ex;
1428     }
1429     else if (lex< sequence< kwd_not > >()) {
1430       Unary_Expression_Ptr ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::NOT, parse_factor());
1431       if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
1432       return ex;
1433     }
1434     // this whole branch is never hit via spec tests
1435     else if (peek < sequence < one_plus < alternatives < css_whitespace, exactly<'-'>, exactly<'+'> > >, number > >()) {
1436       if (parse_number_prefix()) return parse_value(); // prefix is positive
1437       Unary_Expression_Ptr ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::MINUS, parse_value());
1438       if (ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
1439       return ex;
1440     }
1441     else {
1442       return parse_value();
1443     }
1444   }
1445
1446   // parse one value for a list
1447   Expression_Obj Parser::parse_value()
1448   {
1449     lex< css_comments >(false);
1450     if (lex< ampersand >())
1451     {
1452       return SASS_MEMORY_NEW(Parent_Selector, pstate); }
1453
1454     if (lex< kwd_important >())
1455     { return SASS_MEMORY_NEW(String_Constant, pstate, "!important"); }
1456
1457     // parse `10%4px` into separated items and not a schema
1458     if (lex< sequence < percentage, lookahead < number > > >())
1459     { return SASS_MEMORY_NEW(Textual, pstate, Textual::PERCENTAGE, lexed); }
1460
1461     if (lex< sequence < number, lookahead< sequence < op, number > > > >())
1462     { return SASS_MEMORY_NEW(Textual, pstate, Textual::NUMBER, lexed); }
1463
1464     // string may be interpolated
1465     if (lex< sequence < quoted_string, lookahead < exactly <'-'> > > >())
1466     { return parse_string(); }
1467
1468     if (const char* stop = peek< value_schema >())
1469     { return parse_value_schema(stop); }
1470
1471     // string may be interpolated
1472     if (lex< quoted_string >())
1473     { return parse_string(); }
1474
1475     if (lex< kwd_true >())
1476     { return SASS_MEMORY_NEW(Boolean, pstate, true); }
1477
1478     if (lex< kwd_false >())
1479     { return SASS_MEMORY_NEW(Boolean, pstate, false); }
1480
1481     if (lex< kwd_null >())
1482     { return SASS_MEMORY_NEW(Null, pstate); }
1483
1484     if (lex< identifier >()) {
1485       return SASS_MEMORY_NEW(String_Constant, pstate, lexed);
1486     }
1487
1488     if (lex< percentage >())
1489     { return SASS_MEMORY_NEW(Textual, pstate, Textual::PERCENTAGE, lexed); }
1490
1491     // match hex number first because 0x000 looks like a number followed by an identifier
1492     if (lex< sequence < alternatives< hex, hex0 >, negate < exactly<'-'> > > >())
1493     { return SASS_MEMORY_NEW(Textual, pstate, Textual::HEX, lexed); }
1494
1495     if (lex< sequence < exactly <'#'>, identifier > >())
1496     { return SASS_MEMORY_NEW(String_Quoted, pstate, lexed); }
1497
1498     // also handle the 10em- foo special case
1499     // alternatives < exactly < '.' >, .. > -- `1.5em-.75em` is split into a list, not a binary expression
1500     if (lex< sequence< dimension, optional< sequence< exactly<'-'>, lookahead< alternatives < space > > > > > >())
1501     { return SASS_MEMORY_NEW(Textual, pstate, Textual::DIMENSION, lexed); }
1502
1503     if (lex< sequence< static_component, one_plus< strict_identifier > > >())
1504     { return SASS_MEMORY_NEW(String_Constant, pstate, lexed); }
1505
1506     if (lex< number >())
1507     { return SASS_MEMORY_NEW(Textual, pstate, Textual::NUMBER, lexed); }
1508
1509     if (lex< variable >())
1510     { return SASS_MEMORY_NEW(Variable, pstate, Util::normalize_underscores(lexed)); }
1511
1512     // Special case handling for `%` proceeding an interpolant.
1513     if (lex< sequence< exactly<'%'>, optional< percentage > > >())
1514     { return SASS_MEMORY_NEW(String_Constant, pstate, lexed); }
1515
1516     css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
1517
1518     // unreachable statement
1519     return 0;
1520   }
1521
1522   // this parses interpolation inside other strings
1523   // means the result should later be quoted again
1524   String_Obj Parser::parse_interpolated_chunk(Token chunk, bool constant)
1525   {
1526     const char* i = chunk.begin;
1527     // see if there any interpolants
1528     const char* p = constant ? find_first_in_interval< exactly<hash_lbrace> >(i, chunk.end) :
1529                     find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, chunk.end);
1530
1531     if (!p) {
1532       String_Quoted_Ptr str_quoted = SASS_MEMORY_NEW(String_Quoted, pstate, std::string(i, chunk.end));
1533       if (!constant && str_quoted->quote_mark()) str_quoted->quote_mark('*');
1534       return str_quoted;
1535     }
1536
1537     String_Schema_Ptr schema = SASS_MEMORY_NEW(String_Schema, pstate);
1538     schema->is_interpolant(true);
1539     while (i < chunk.end) {
1540       p = constant ? find_first_in_interval< exactly<hash_lbrace> >(i, chunk.end) :
1541           find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, chunk.end);
1542       if (p) {
1543         if (i < p) {
1544           // accumulate the preceding segment if it's nonempty
1545           schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(i, p)));
1546         }
1547         // we need to skip anything inside strings
1548         // create a new target in parser/prelexer
1549         if (peek < sequence < optional_spaces, exactly<rbrace> > >(p+2)) { position = p+2;
1550           css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
1551         }
1552         const char* j = skip_over_scopes< exactly<hash_lbrace>, exactly<rbrace> >(p + 2, chunk.end); // find the closing brace
1553         if (j) { --j;
1554           // parse the interpolant and accumulate it
1555           Expression_Obj interp_node = Parser::from_token(Token(p+2, j), ctx, pstate, source).parse_list();
1556           interp_node->is_interpolant(true);
1557           schema->append(interp_node);
1558           i = j;
1559         }
1560         else {
1561           // throw an error if the interpolant is unterminated
1562           error("unterminated interpolant inside string constant " + chunk.to_string(), pstate);
1563         }
1564       }
1565       else { // no interpolants left; add the last segment if nonempty
1566         // check if we need quotes here (was not sure after merge)
1567         if (i < chunk.end) schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(i, chunk.end)));
1568         break;
1569       }
1570       ++ i;
1571     }
1572
1573     return schema;
1574   }
1575
1576   String_Constant_Obj Parser::parse_static_value()
1577   {
1578     lex< static_value >();
1579     Token str(lexed);
1580     // static values always have trailing white-
1581     // space and end delimiter (\s*[;]$) included
1582     -- pstate.offset.column;
1583     --str.end;
1584     --position;
1585
1586     String_Constant_Ptr str_node = SASS_MEMORY_NEW(String_Constant, pstate, str.time_wspace());
1587     return str_node;
1588   }
1589
1590   String_Obj Parser::parse_string()
1591   {
1592     return parse_interpolated_chunk(Token(lexed));
1593   }
1594
1595   String_Obj Parser::parse_ie_property()
1596   {
1597     lex< ie_property >();
1598     Token str(lexed);
1599     const char* i = str.begin;
1600     // see if there any interpolants
1601     const char* p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(str.begin, str.end);
1602     if (!p) {
1603       return SASS_MEMORY_NEW(String_Quoted, pstate, std::string(str.begin, str.end));
1604     }
1605
1606     String_Schema_Ptr schema = SASS_MEMORY_NEW(String_Schema, pstate);
1607     while (i < str.end) {
1608       p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, str.end);
1609       if (p) {
1610         if (i < p) {
1611           schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(i, p))); // accumulate the preceding segment if it's nonempty
1612         }
1613         if (peek < sequence < optional_spaces, exactly<rbrace> > >(p+2)) { position = p+2;
1614           css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
1615         }
1616         const char* j = skip_over_scopes< exactly<hash_lbrace>, exactly<rbrace> >(p+2, str.end); // find the closing brace
1617         if (j) {
1618           // parse the interpolant and accumulate it
1619           Expression_Obj interp_node = Parser::from_token(Token(p+2, j), ctx, pstate, source).parse_list();
1620           interp_node->is_interpolant(true);
1621           schema->append(interp_node);
1622           i = j;
1623         }
1624         else {
1625           // throw an error if the interpolant is unterminated
1626           error("unterminated interpolant inside IE function " + str.to_string(), pstate);
1627         }
1628       }
1629       else { // no interpolants left; add the last segment if nonempty
1630         if (i < str.end) {
1631           schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(i, str.end)));
1632         }
1633         break;
1634       }
1635     }
1636     return schema;
1637   }
1638
1639   String_Obj Parser::parse_ie_keyword_arg()
1640   {
1641     String_Schema_Ptr kwd_arg = SASS_MEMORY_NEW(String_Schema, pstate, 3);
1642     if (lex< variable >()) {
1643       kwd_arg->append(SASS_MEMORY_NEW(Variable, pstate, Util::normalize_underscores(lexed)));
1644     } else {
1645       lex< alternatives< identifier_schema, identifier > >();
1646       kwd_arg->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
1647     }
1648     lex< exactly<'='> >();
1649     kwd_arg->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
1650     if (peek< variable >()) kwd_arg->append(parse_list());
1651     else if (lex< number >()) kwd_arg->append(SASS_MEMORY_NEW(Textual, pstate, Textual::NUMBER, Util::normalize_decimals(lexed)));
1652     else if (peek < ie_keyword_arg_value >()) { kwd_arg->append(parse_list()); }
1653     return kwd_arg;
1654   }
1655
1656   String_Schema_Obj Parser::parse_value_schema(const char* stop)
1657   {
1658     // initialize the string schema object to add tokens
1659     String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
1660
1661     if (peek<exactly<'}'>>()) {
1662       css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
1663     }
1664
1665     const char* e = 0;
1666     const char* ee = end;
1667     end = stop;
1668     size_t num_items = 0;
1669     bool need_space = false;
1670     while (position < stop) {
1671       // parse space between tokens
1672       if (lex< spaces >() && num_items) {
1673         need_space = true;
1674       }
1675       if (need_space) {
1676         need_space = false;
1677         // schema->append(SASS_MEMORY_NEW(String_Constant, pstate, " "));
1678       }
1679       if ((e = peek< re_functional >()) && e < stop) {
1680         schema->append(parse_function_call());
1681       }
1682       // lex an interpolant /#{...}/
1683       else if (lex< exactly < hash_lbrace > >()) {
1684         // Try to lex static expression first
1685         if (peek< exactly< rbrace > >()) {
1686           css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
1687         }
1688         Expression_Obj ex = 0;
1689         if (lex< re_static_expression >()) {
1690           ex = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
1691         } else {
1692           ex = parse_list();
1693         }
1694         ex->is_interpolant(true);
1695         schema->append(ex);
1696         if (!lex < exactly < rbrace > >()) {
1697           css_error("Invalid CSS", " after ", ": expected \"}\", was ");
1698         }
1699       }
1700       // lex some string constants or other valid token
1701       // Note: [-+] chars are left over from i.e. `#{3}+3`
1702       else if (lex< alternatives < exactly<'%'>, exactly < '-' >, exactly < '+' > > >()) {
1703         schema->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
1704       }
1705       // lex a quoted string
1706       else if (lex< quoted_string >()) {
1707         // need_space = true;
1708         // if (schema->length()) schema->append(SASS_MEMORY_NEW(String_Constant, pstate, " "));
1709         // else need_space = true;
1710         schema->append(parse_string());
1711         if ((*position == '"' || *position == '\'') || peek < alternatives < alpha > >()) {
1712           // need_space = true;
1713         }
1714         if (peek < exactly < '-' > >()) break;
1715       }
1716       else if (lex< sequence < identifier > >()) {
1717         schema->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
1718         if ((*position == '"' || *position == '\'') || peek < alternatives < alpha > >()) {
1719            // need_space = true;
1720         }
1721       }
1722       // lex (normalized) variable
1723       else if (lex< variable >()) {
1724         std::string name(Util::normalize_underscores(lexed));
1725         schema->append(SASS_MEMORY_NEW(Variable, pstate, name));
1726       }
1727       // lex percentage value
1728       else if (lex< percentage >()) {
1729         schema->append(SASS_MEMORY_NEW(Textual, pstate, Textual::PERCENTAGE, lexed));
1730       }
1731       // lex dimension value
1732       else if (lex< dimension >()) {
1733         schema->append(SASS_MEMORY_NEW(Textual, pstate, Textual::DIMENSION, lexed));
1734       }
1735       // lex number value
1736       else if (lex< number >()) {
1737         schema->append( SASS_MEMORY_NEW(Textual, pstate, Textual::NUMBER, lexed));
1738       }
1739       // lex hex color value
1740       else if (lex< sequence < hex, negate < exactly < '-' > > > >()) {
1741         schema->append(SASS_MEMORY_NEW(Textual, pstate, Textual::HEX, lexed));
1742       }
1743       else if (lex< sequence < exactly <'#'>, identifier > >()) {
1744         schema->append(SASS_MEMORY_NEW(String_Quoted, pstate, lexed));
1745       }
1746       // lex a value in parentheses
1747       else if (peek< parenthese_scope >()) {
1748         schema->append(parse_factor());
1749       }
1750       else {
1751         break;
1752       }
1753       ++num_items;
1754     }
1755     if (position != stop) {
1756       schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(position, stop)));
1757       position = stop;
1758     }
1759     end = ee;
1760     return schema;
1761   }
1762
1763   // this parses interpolation outside other strings
1764   // means the result must not be quoted again later
1765   String_Obj Parser::parse_identifier_schema()
1766   {
1767     Token id(lexed);
1768     const char* i = id.begin;
1769     // see if there any interpolants
1770     const char* p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(id.begin, id.end);
1771     if (!p) {
1772       return SASS_MEMORY_NEW(String_Constant, pstate, std::string(id.begin, id.end));
1773     }
1774
1775     String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
1776     while (i < id.end) {
1777       p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, id.end);
1778       if (p) {
1779         if (i < p) {
1780           // accumulate the preceding segment if it's nonempty
1781           const char* o = position; position = i;
1782           schema->append(parse_value_schema(p));
1783           position = o;
1784         }
1785         // we need to skip anything inside strings
1786         // create a new target in parser/prelexer
1787         if (peek < sequence < optional_spaces, exactly<rbrace> > >(p+2)) { position = p;
1788           css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
1789         }
1790         const char* j = skip_over_scopes< exactly<hash_lbrace>, exactly<rbrace> >(p+2, id.end); // find the closing brace
1791         if (j) {
1792           // parse the interpolant and accumulate it
1793           Expression_Obj interp_node = Parser::from_token(Token(p+2, j), ctx, pstate, source).parse_list(DELAYED);
1794           interp_node->is_interpolant(true);
1795           schema->append(interp_node);
1796           // schema->has_interpolants(true);
1797           i = j;
1798         }
1799         else {
1800           // throw an error if the interpolant is unterminated
1801           error("unterminated interpolant inside interpolated identifier " + id.to_string(), pstate);
1802         }
1803       }
1804       else { // no interpolants left; add the last segment if nonempty
1805         if (i < end) {
1806           const char* o = position; position = i;
1807           schema->append(parse_value_schema(id.end));
1808           position = o;
1809         }
1810         break;
1811       }
1812     }
1813     return schema ? schema.detach() : 0;
1814   }
1815
1816   // calc functions should preserve arguments
1817   Function_Call_Obj Parser::parse_calc_function()
1818   {
1819     lex< identifier >();
1820     std::string name(lexed);
1821     ParserState call_pos = pstate;
1822     lex< exactly<'('> >();
1823     ParserState arg_pos = pstate;
1824     const char* arg_beg = position;
1825     parse_list();
1826     const char* arg_end = position;
1827     lex< skip_over_scopes <
1828           exactly < '(' >,
1829           exactly < ')' >
1830         > >();
1831
1832     Argument_Obj arg = SASS_MEMORY_NEW(Argument, arg_pos, parse_interpolated_chunk(Token(arg_beg, arg_end)));
1833     Arguments_Obj args = SASS_MEMORY_NEW(Arguments, arg_pos);
1834     args->append(arg);
1835     return SASS_MEMORY_NEW(Function_Call, call_pos, name, args);
1836   }
1837
1838   String_Obj Parser::parse_url_function_string()
1839   {
1840     std::string prefix("");
1841     if (lex< uri_prefix >()) {
1842       prefix = std::string(lexed);
1843     }
1844
1845     lex < optional_spaces >();
1846     String_Obj url_string = parse_url_function_argument();
1847
1848     std::string suffix("");
1849     if (lex< real_uri_suffix >()) {
1850       suffix = std::string(lexed);
1851     }
1852
1853     std::string uri("");
1854     if (url_string) {
1855       uri = url_string->to_string({ NESTED, 5 });
1856     }
1857
1858     if (String_Schema_Ptr schema = Cast<String_Schema>(url_string)) {
1859       String_Schema_Obj res = SASS_MEMORY_NEW(String_Schema, pstate);
1860       res->append(SASS_MEMORY_NEW(String_Constant, pstate, prefix));
1861       res->append(schema);
1862       res->append(SASS_MEMORY_NEW(String_Constant, pstate, suffix));
1863       return res;
1864     } else {
1865       std::string res = prefix + uri + suffix;
1866       return SASS_MEMORY_NEW(String_Constant, pstate, res);
1867     }
1868   }
1869
1870   String_Obj Parser::parse_url_function_argument()
1871   {
1872     const char* p = position;
1873
1874     std::string uri("");
1875     if (lex< real_uri_value >(false)) {
1876       uri = lexed.to_string();
1877     }
1878
1879     if (peek< exactly< hash_lbrace > >()) {
1880       const char* pp = position;
1881       // TODO: error checking for unclosed interpolants
1882       while (pp && peek< exactly< hash_lbrace > >(pp)) {
1883         pp = sequence< interpolant, real_uri_value >(pp);
1884       }
1885       position = pp;
1886       return parse_interpolated_chunk(Token(p, position));
1887     }
1888     else if (uri != "") {
1889       std::string res = Util::rtrim(uri);
1890       return SASS_MEMORY_NEW(String_Constant, pstate, res);
1891     }
1892
1893     return 0;
1894   }
1895
1896   Function_Call_Obj Parser::parse_function_call()
1897   {
1898     lex< identifier >();
1899     std::string name(lexed);
1900
1901     ParserState call_pos = pstate;
1902     Arguments_Obj args = parse_arguments();
1903     return SASS_MEMORY_NEW(Function_Call, call_pos, name, args);
1904   }
1905
1906   Function_Call_Schema_Obj Parser::parse_function_call_schema()
1907   {
1908     String_Obj name = parse_identifier_schema();
1909     ParserState source_position_of_call = pstate;
1910     Arguments_Obj args = parse_arguments();
1911
1912     return SASS_MEMORY_NEW(Function_Call_Schema, source_position_of_call, name, args);
1913   }
1914
1915   Content_Obj Parser::parse_content_directive()
1916   {
1917     return SASS_MEMORY_NEW(Content, pstate);
1918   }
1919
1920   If_Obj Parser::parse_if_directive(bool else_if)
1921   {
1922     stack.push_back(Scope::Control);
1923     ParserState if_source_position = pstate;
1924     bool root = block_stack.back()->is_root();
1925     Expression_Obj predicate = parse_list();
1926     Block_Obj block = parse_block(root);
1927     Block_Obj alternative = NULL;
1928
1929     // only throw away comment if we parse a case
1930     // we want all other comments to be parsed
1931     if (lex_css< elseif_directive >()) {
1932       alternative = SASS_MEMORY_NEW(Block, pstate);
1933       alternative->append(parse_if_directive(true));
1934     }
1935     else if (lex_css< kwd_else_directive >()) {
1936       alternative = parse_block(root);
1937     }
1938     stack.pop_back();
1939     return SASS_MEMORY_NEW(If, if_source_position, predicate, block, alternative);
1940   }
1941
1942   For_Obj Parser::parse_for_directive()
1943   {
1944     stack.push_back(Scope::Control);
1945     ParserState for_source_position = pstate;
1946     bool root = block_stack.back()->is_root();
1947     lex_variable();
1948     std::string var(Util::normalize_underscores(lexed));
1949     if (!lex< kwd_from >()) error("expected 'from' keyword in @for directive", pstate);
1950     Expression_Obj lower_bound = parse_expression();
1951     bool inclusive = false;
1952     if (lex< kwd_through >()) inclusive = true;
1953     else if (lex< kwd_to >()) inclusive = false;
1954     else                  error("expected 'through' or 'to' keyword in @for directive", pstate);
1955     Expression_Obj upper_bound = parse_expression();
1956     Block_Obj body = parse_block(root);
1957     stack.pop_back();
1958     return SASS_MEMORY_NEW(For, for_source_position, var, lower_bound, upper_bound, body, inclusive);
1959   }
1960
1961   // helper to parse a var token
1962   Token Parser::lex_variable()
1963   {
1964     // peek for dollar sign first
1965     if (!peek< exactly <'$'> >()) {
1966       css_error("Invalid CSS", " after ", ": expected \"$\", was ");
1967     }
1968     // we expect a simple identifier as the call name
1969     if (!lex< sequence < exactly <'$'>, identifier > >()) {
1970       lex< exactly <'$'> >(); // move pstate and position up
1971       css_error("Invalid CSS", " after ", ": expected identifier, was ");
1972     }
1973     // return object
1974     return token;
1975   }
1976   // helper to parse identifier
1977   Token Parser::lex_identifier()
1978   {
1979     // we expect a simple identifier as the call name
1980     if (!lex< identifier >()) { // ToDo: pstate wrong?
1981       css_error("Invalid CSS", " after ", ": expected identifier, was ");
1982     }
1983     // return object
1984     return token;
1985   }
1986
1987   Each_Obj Parser::parse_each_directive()
1988   {
1989     stack.push_back(Scope::Control);
1990     ParserState each_source_position = pstate;
1991     bool root = block_stack.back()->is_root();
1992     std::vector<std::string> vars;
1993     lex_variable();
1994     vars.push_back(Util::normalize_underscores(lexed));
1995     while (lex< exactly<','> >()) {
1996       if (!lex< variable >()) error("@each directive requires an iteration variable", pstate);
1997       vars.push_back(Util::normalize_underscores(lexed));
1998     }
1999     if (!lex< kwd_in >()) error("expected 'in' keyword in @each directive", pstate);
2000     Expression_Obj list = parse_list();
2001     Block_Obj body = parse_block(root);
2002     stack.pop_back();
2003     return SASS_MEMORY_NEW(Each, each_source_position, vars, list, body);
2004   }
2005
2006   // called after parsing `kwd_while_directive`
2007   While_Obj Parser::parse_while_directive()
2008   {
2009     stack.push_back(Scope::Control);
2010     bool root = block_stack.back()->is_root();
2011     // create the initial while call object
2012     While_Obj call = SASS_MEMORY_NEW(While, pstate, 0, 0);
2013     // parse mandatory predicate
2014     Expression_Obj predicate = parse_list();
2015     call->predicate(predicate);
2016     // parse mandatory block
2017     call->block(parse_block(root));
2018     // return ast node
2019     stack.pop_back();
2020     // return ast node
2021     return call.detach();
2022   }
2023
2024   // EO parse_while_directive
2025   Media_Block_Obj Parser::parse_media_block()
2026   {
2027     stack.push_back(Scope::Media);
2028     Media_Block_Obj media_block = SASS_MEMORY_NEW(Media_Block, pstate, 0, 0);
2029
2030     media_block->media_queries(parse_media_queries());
2031
2032     Media_Block_Obj prev_media_block = last_media_block;
2033     last_media_block = media_block;
2034     media_block->block(parse_css_block());
2035     last_media_block = prev_media_block;
2036     stack.pop_back();
2037     return media_block.detach();
2038   }
2039
2040   List_Obj Parser::parse_media_queries()
2041   {
2042     advanceToNextToken();
2043     List_Obj queries = SASS_MEMORY_NEW(List, pstate, 0, SASS_COMMA);
2044     if (!peek_css < exactly <'{'> >()) queries->append(parse_media_query());
2045     while (lex_css < exactly <','> >()) queries->append(parse_media_query());
2046     queries->update_pstate(pstate);
2047     return queries.detach();
2048   }
2049
2050   // Expression_Ptr Parser::parse_media_query()
2051   Media_Query_Obj Parser::parse_media_query()
2052   {
2053     advanceToNextToken();
2054     Media_Query_Obj media_query = SASS_MEMORY_NEW(Media_Query, pstate);
2055     if (lex < kwd_not >()) { media_query->is_negated(true); lex < css_comments >(false); }
2056     else if (lex < kwd_only >()) { media_query->is_restricted(true); lex < css_comments >(false); }
2057
2058     if (lex < identifier_schema >())  media_query->media_type(parse_identifier_schema());
2059     else if (lex < identifier >())    media_query->media_type(parse_interpolated_chunk(lexed));
2060     else                             media_query->append(parse_media_expression());
2061
2062     while (lex_css < kwd_and >()) media_query->append(parse_media_expression());
2063     if (lex < identifier_schema >()) {
2064       String_Schema_Ptr schema = SASS_MEMORY_NEW(String_Schema, pstate);
2065       schema->append(media_query->media_type());
2066       schema->append(SASS_MEMORY_NEW(String_Constant, pstate, " "));
2067       schema->append(parse_identifier_schema());
2068       media_query->media_type(schema);
2069     }
2070     while (lex_css < kwd_and >()) media_query->append(parse_media_expression());
2071
2072     media_query->update_pstate(pstate);
2073
2074     return media_query;
2075   }
2076
2077   Media_Query_Expression_Obj Parser::parse_media_expression()
2078   {
2079     if (lex < identifier_schema >()) {
2080       String_Obj ss = parse_identifier_schema();
2081       return SASS_MEMORY_NEW(Media_Query_Expression, pstate, ss, 0, true);
2082     }
2083     if (!lex_css< exactly<'('> >()) {
2084       error("media query expression must begin with '('", pstate);
2085     }
2086     Expression_Obj feature = 0;
2087     if (peek_css< exactly<')'> >()) {
2088       error("media feature required in media query expression", pstate);
2089     }
2090     feature = parse_expression();
2091     Expression_Obj expression = 0;
2092     if (lex_css< exactly<':'> >()) {
2093       expression = parse_list(DELAYED);
2094     }
2095     if (!lex_css< exactly<')'> >()) {
2096       error("unclosed parenthesis in media query expression", pstate);
2097     }
2098     return SASS_MEMORY_NEW(Media_Query_Expression, feature->pstate(), feature, expression);
2099   }
2100
2101   // lexed after `kwd_supports_directive`
2102   // these are very similar to media blocks
2103   Supports_Block_Obj Parser::parse_supports_directive()
2104   {
2105     Supports_Condition_Obj cond = parse_supports_condition();
2106     // create the ast node object for the support queries
2107     Supports_Block_Obj query = SASS_MEMORY_NEW(Supports_Block, pstate, cond);
2108     // additional block is mandatory
2109     // parse inner block
2110     query->block(parse_block());
2111     // return ast node
2112     return query;
2113   }
2114
2115   // parse one query operation
2116   // may encounter nested queries
2117   Supports_Condition_Obj Parser::parse_supports_condition()
2118   {
2119     lex < css_whitespace >();
2120     Supports_Condition_Obj cond = 0;
2121     if ((cond = parse_supports_negation())) return cond;
2122     if ((cond = parse_supports_operator())) return cond;
2123     if ((cond = parse_supports_interpolation())) return cond;
2124     return cond;
2125   }
2126
2127   Supports_Condition_Obj Parser::parse_supports_negation()
2128   {
2129     if (!lex < kwd_not >()) return 0;
2130     Supports_Condition_Obj cond = parse_supports_condition_in_parens();
2131     return SASS_MEMORY_NEW(Supports_Negation, pstate, cond);
2132   }
2133
2134   Supports_Condition_Obj Parser::parse_supports_operator()
2135   {
2136     Supports_Condition_Obj cond = parse_supports_condition_in_parens();
2137     if (cond.isNull()) return 0;
2138
2139     while (true) {
2140       Supports_Operator::Operand op = Supports_Operator::OR;
2141       if (lex < kwd_and >()) { op = Supports_Operator::AND; }
2142       else if(!lex < kwd_or >()) { break; }
2143
2144       lex < css_whitespace >();
2145       Supports_Condition_Obj right = parse_supports_condition_in_parens();
2146
2147       // Supports_Condition_Ptr cc = SASS_MEMORY_NEW(Supports_Condition, *static_cast<Supports_Condition_Ptr>(cond));
2148       cond = SASS_MEMORY_NEW(Supports_Operator, pstate, cond, right, op);
2149     }
2150     return cond;
2151   }
2152
2153   Supports_Condition_Obj Parser::parse_supports_interpolation()
2154   {
2155     if (!lex < interpolant >()) return 0;
2156
2157     String_Obj interp = parse_interpolated_chunk(lexed);
2158     if (!interp) return 0;
2159
2160     return SASS_MEMORY_NEW(Supports_Interpolation, pstate, interp);
2161   }
2162
2163   // TODO: This needs some major work. Although feature conditions
2164   // look like declarations their semantics differ significantly
2165   Supports_Condition_Obj Parser::parse_supports_declaration()
2166   {
2167     Supports_Condition_Ptr cond = 0;
2168     // parse something declaration like
2169     Declaration_Obj declaration = parse_declaration();
2170     if (!declaration) error("@supports condition expected declaration", pstate);
2171     cond = SASS_MEMORY_NEW(Supports_Declaration,
2172                      declaration->pstate(),
2173                      declaration->property(),
2174                      declaration->value());
2175     // ToDo: maybe we need an additional error condition?
2176     return cond;
2177   }
2178
2179   Supports_Condition_Obj Parser::parse_supports_condition_in_parens()
2180   {
2181     Supports_Condition_Obj interp = parse_supports_interpolation();
2182     if (interp != 0) return interp;
2183
2184     if (!lex < exactly <'('> >()) return 0;
2185     lex < css_whitespace >();
2186
2187     Supports_Condition_Obj cond = parse_supports_condition();
2188     if (cond != 0) {
2189       if (!lex < exactly <')'> >()) error("unclosed parenthesis in @supports declaration", pstate);
2190     } else {
2191       cond = parse_supports_declaration();
2192       if (!lex < exactly <')'> >()) error("unclosed parenthesis in @supports declaration", pstate);
2193     }
2194     lex < css_whitespace >();
2195     return cond;
2196   }
2197
2198   At_Root_Block_Obj Parser::parse_at_root_block()
2199   {
2200     ParserState at_source_position = pstate;
2201     Block_Obj body = 0;
2202     At_Root_Query_Obj expr;
2203     Lookahead lookahead_result;
2204     if (lex_css< exactly<'('> >()) {
2205       expr = parse_at_root_query();
2206     }
2207     if (peek_css < exactly<'{'> >()) {
2208       lex <optional_spaces>();
2209       body = parse_block(true);
2210     }
2211     else if ((lookahead_result = lookahead_for_selector(position)).found) {
2212       Ruleset_Obj r = parse_ruleset(lookahead_result);
2213       body = SASS_MEMORY_NEW(Block, r->pstate(), 1, true);
2214       body->append(r);
2215     }
2216     At_Root_Block_Obj at_root = SASS_MEMORY_NEW(At_Root_Block, at_source_position, body);
2217     if (!expr.isNull()) at_root->expression(expr);
2218     return at_root;
2219   }
2220
2221   At_Root_Query_Obj Parser::parse_at_root_query()
2222   {
2223     if (peek< exactly<')'> >()) error("at-root feature required in at-root expression", pstate);
2224
2225     if (!peek< alternatives< kwd_with_directive, kwd_without_directive > >()) {
2226       css_error("Invalid CSS", " after ", ": expected \"with\" or \"without\", was ");
2227     }
2228
2229     Expression_Obj feature = parse_list();
2230     if (!lex_css< exactly<':'> >()) error("style declaration must contain a value", pstate);
2231     Expression_Obj expression = parse_list();
2232     List_Obj value = SASS_MEMORY_NEW(List, feature->pstate(), 1);
2233
2234     if (expression->concrete_type() == Expression::LIST) {
2235         value = Cast<List>(expression);
2236     }
2237     else value->append(expression);
2238
2239     At_Root_Query_Obj cond = SASS_MEMORY_NEW(At_Root_Query,
2240                                           value->pstate(),
2241                                           feature,
2242                                           value);
2243     if (!lex_css< exactly<')'> >()) error("unclosed parenthesis in @at-root expression", pstate);
2244     return cond;
2245   }
2246
2247   Directive_Obj Parser::parse_special_directive()
2248   {
2249     std::string kwd(lexed);
2250
2251     if (lexed == "@else") error("Invalid CSS: @else must come after @if", pstate);
2252
2253     // this whole branch is never hit via spec tests
2254
2255     Directive_Ptr at_rule = SASS_MEMORY_NEW(Directive, pstate, kwd);
2256     Lookahead lookahead = lookahead_for_include(position);
2257     if (lookahead.found && !lookahead.has_interpolants) {
2258       at_rule->selector(parse_selector_list(false));
2259     }
2260
2261     lex < css_comments >(false);
2262
2263     if (lex < static_property >()) {
2264       at_rule->value(parse_interpolated_chunk(Token(lexed)));
2265     } else if (!(peek < alternatives < exactly<'{'>, exactly<'}'>, exactly<';'> > >())) {
2266       at_rule->value(parse_list());
2267     }
2268
2269     lex < css_comments >(false);
2270
2271     if (peek< exactly<'{'> >()) {
2272       at_rule->block(parse_block());
2273     }
2274
2275     return at_rule;
2276   }
2277
2278   // this whole branch is never hit via spec tests
2279   Directive_Obj Parser::parse_prefixed_directive()
2280   {
2281     std::string kwd(lexed);
2282
2283     if (lexed == "@else") error("Invalid CSS: @else must come after @if", pstate);
2284
2285     Directive_Obj at_rule = SASS_MEMORY_NEW(Directive, pstate, kwd);
2286     Lookahead lookahead = lookahead_for_include(position);
2287     if (lookahead.found && !lookahead.has_interpolants) {
2288       at_rule->selector(parse_selector_list(false));
2289     }
2290
2291     lex < css_comments >(false);
2292
2293     if (lex < static_property >()) {
2294       at_rule->value(parse_interpolated_chunk(Token(lexed)));
2295     } else if (!(peek < alternatives < exactly<'{'>, exactly<'}'>, exactly<';'> > >())) {
2296       at_rule->value(parse_list());
2297     }
2298
2299     lex < css_comments >(false);
2300
2301     if (peek< exactly<'{'> >()) {
2302       at_rule->block(parse_block());
2303     }
2304
2305     return at_rule;
2306   }
2307
2308
2309   Directive_Obj Parser::parse_directive()
2310   {
2311     Directive_Obj directive = SASS_MEMORY_NEW(Directive, pstate, lexed);
2312     String_Schema_Obj val = parse_almost_any_value();
2313     // strip left and right if they are of type string
2314     directive->value(val);
2315     if (peek< exactly<'{'> >()) {
2316       directive->block(parse_block());
2317     }
2318     return directive;
2319   }
2320
2321   Expression_Obj Parser::lex_interpolation()
2322   {
2323     if (lex < interpolant >(true) != NULL) {
2324       return parse_interpolated_chunk(lexed, true);
2325     }
2326     return 0;
2327   }
2328
2329   Expression_Obj Parser::lex_interp_uri()
2330   {
2331     // create a string schema by lexing optional interpolations
2332     return lex_interp< re_string_uri_open, re_string_uri_close >();
2333   }
2334
2335   Expression_Obj Parser::lex_interp_string()
2336   {
2337     Expression_Obj rv = 0;
2338     if ((rv = lex_interp< re_string_double_open, re_string_double_close >())) return rv;
2339     if ((rv = lex_interp< re_string_single_open, re_string_single_close >())) return rv;
2340     return rv;
2341   }
2342
2343   Expression_Obj Parser::lex_almost_any_value_chars()
2344   {
2345     const char* match =
2346     lex <
2347       one_plus <
2348         alternatives <
2349           sequence <
2350             exactly <'\\'>,
2351             any_char
2352           >,
2353           sequence <
2354             negate <
2355               sequence <
2356                 exactly < url_kwd >,
2357                 exactly <'('>
2358               >
2359             >,
2360             neg_class_char <
2361               almost_any_value_class
2362             >
2363           >,
2364           sequence <
2365             exactly <'/'>,
2366             negate <
2367               alternatives <
2368                 exactly <'/'>,
2369                 exactly <'*'>
2370               >
2371             >
2372           >,
2373           sequence <
2374             exactly <'\\'>,
2375             exactly <'#'>,
2376             negate <
2377               exactly <'{'>
2378             >
2379           >,
2380           sequence <
2381             exactly <'!'>,
2382             negate <
2383               alpha
2384             >
2385           >
2386         >
2387       >
2388     >(false);
2389     if (match) {
2390       return SASS_MEMORY_NEW(String_Constant, pstate, lexed);
2391     }
2392     return NULL;
2393   }
2394
2395   Expression_Obj Parser::lex_almost_any_value_token()
2396   {
2397     Expression_Obj rv = 0;
2398     if (*position == 0) return 0;
2399     if ((rv = lex_almost_any_value_chars())) return rv;
2400     // if ((rv = lex_block_comment())) return rv;
2401     // if ((rv = lex_single_line_comment())) return rv;
2402     if ((rv = lex_interp_string())) return rv;
2403     if ((rv = lex_interp_uri())) return rv;
2404     if ((rv = lex_interpolation())) return rv;
2405     return rv;
2406   }
2407
2408   String_Schema_Obj Parser::parse_almost_any_value()
2409   {
2410
2411     String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
2412     if (*position == 0) return 0;
2413     lex < spaces >(false);
2414     Expression_Obj token = lex_almost_any_value_token();
2415     if (!token) return 0;
2416     schema->append(token);
2417     if (*position == 0) {
2418       schema->rtrim();
2419       return schema.detach();
2420     }
2421
2422     while ((token = lex_almost_any_value_token())) {
2423       schema->append(token);
2424     }
2425
2426     lex < css_whitespace >();
2427
2428     schema->rtrim();
2429
2430     return schema.detach();
2431   }
2432
2433   Warning_Obj Parser::parse_warning()
2434   {
2435     if (stack.back() != Scope::Root &&
2436         stack.back() != Scope::Function &&
2437         stack.back() != Scope::Mixin &&
2438         stack.back() != Scope::Control &&
2439         stack.back() != Scope::Rules) {
2440       error("Illegal nesting: Only properties may be nested beneath properties.", pstate);
2441     }
2442     return SASS_MEMORY_NEW(Warning, pstate, parse_list(DELAYED));
2443   }
2444
2445   Error_Obj Parser::parse_error()
2446   {
2447     if (stack.back() != Scope::Root &&
2448         stack.back() != Scope::Function &&
2449         stack.back() != Scope::Mixin &&
2450         stack.back() != Scope::Control &&
2451         stack.back() != Scope::Rules) {
2452       error("Illegal nesting: Only properties may be nested beneath properties.", pstate);
2453     }
2454     return SASS_MEMORY_NEW(Error, pstate, parse_list(DELAYED));
2455   }
2456
2457   Debug_Obj Parser::parse_debug()
2458   {
2459     if (stack.back() != Scope::Root &&
2460         stack.back() != Scope::Function &&
2461         stack.back() != Scope::Mixin &&
2462         stack.back() != Scope::Control &&
2463         stack.back() != Scope::Rules) {
2464       error("Illegal nesting: Only properties may be nested beneath properties.", pstate);
2465     }
2466     return SASS_MEMORY_NEW(Debug, pstate, parse_list(DELAYED));
2467   }
2468
2469   Return_Obj Parser::parse_return_directive()
2470   {
2471     // check that we do not have an empty list (ToDo: check if we got all cases)
2472     if (peek_css < alternatives < exactly < ';' >, exactly < '}' >, end_of_file > >())
2473     { css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was "); }
2474     return SASS_MEMORY_NEW(Return, pstate, parse_list());
2475   }
2476
2477   Lookahead Parser::lookahead_for_selector(const char* start)
2478   {
2479     // init result struct
2480     Lookahead rv = Lookahead();
2481     // get start position
2482     const char* p = start ? start : position;
2483     // match in one big "regex"
2484     rv.error = p;
2485     if (const char* q =
2486       peek <
2487         re_selector_list
2488       >(p)
2489     ) {
2490       while (p < q) {
2491         // did we have interpolations?
2492         if (*p == '#' && *(p+1) == '{') {
2493           rv.has_interpolants = true;
2494           p = q; break;
2495         }
2496         ++ p;
2497       }
2498       // store anyway  }
2499
2500
2501       // ToDo: remove
2502       rv.error = q;
2503       rv.position = q;
2504       // check expected opening bracket
2505       // only after successfull matching
2506       if (peek < exactly<'{'> >(q)) rv.found = q;
2507       // else if (peek < end_of_file >(q)) rv.found = q;
2508       else if (peek < exactly<'('> >(q)) rv.found = q;
2509       // else if (peek < exactly<';'> >(q)) rv.found = q;
2510       // else if (peek < exactly<'}'> >(q)) rv.found = q;
2511       if (rv.found || *p == 0) rv.error = 0;
2512     }
2513
2514     rv.parsable = ! rv.has_interpolants;
2515
2516     // return result
2517     return rv;
2518
2519   }
2520   // EO lookahead_for_selector
2521
2522   // used in parse_block_nodes and parse_special_directive
2523   // ToDo: actual usage is still not really clear to me?
2524   Lookahead Parser::lookahead_for_include(const char* start)
2525   {
2526     // we actually just lookahead for a selector
2527     Lookahead rv = lookahead_for_selector(start);
2528     // but the "found" rules are different
2529     if (const char* p = rv.position) {
2530       // check for additional abort condition
2531       if (peek < exactly<';'> >(p)) rv.found = p;
2532       else if (peek < exactly<'}'> >(p)) rv.found = p;
2533     }
2534     // return result
2535     return rv;
2536   }
2537   // EO lookahead_for_include
2538
2539   // look ahead for a token with interpolation in it
2540   // we mostly use the result if there is an interpolation
2541   // everything that passes here gets parsed as one schema
2542   // meaning it will not be parsed as a space separated list
2543   Lookahead Parser::lookahead_for_value(const char* start)
2544   {
2545     // init result struct
2546     Lookahead rv = Lookahead();
2547     // get start position
2548     const char* p = start ? start : position;
2549     // match in one big "regex"
2550     if (const char* q =
2551       peek <
2552         non_greedy <
2553           alternatives <
2554             // consume whitespace
2555             block_comment, // spaces,
2556             // main tokens
2557             sequence <
2558               interpolant,
2559               optional <
2560                 quoted_string
2561               >
2562             >,
2563             identifier,
2564             variable,
2565             // issue #442
2566             sequence <
2567               parenthese_scope,
2568               interpolant,
2569               optional <
2570                 quoted_string
2571               >
2572             >
2573           >,
2574           sequence <
2575             // optional_spaces,
2576             alternatives <
2577               // end_of_file,
2578               exactly<'{'>,
2579               exactly<'}'>,
2580               exactly<';'>
2581             >
2582           >
2583         >
2584       >(p)
2585     ) {
2586       if (p == q) return rv;
2587       while (p < q) {
2588         // did we have interpolations?
2589         if (*p == '#' && *(p+1) == '{') {
2590           rv.has_interpolants = true;
2591           p = q; break;
2592         }
2593         ++ p;
2594       }
2595       // store anyway
2596       // ToDo: remove
2597       rv.position = q;
2598       // check expected opening bracket
2599       // only after successful matching
2600       if (peek < exactly<'{'> >(q)) rv.found = q;
2601       else if (peek < exactly<';'> >(q)) rv.found = q;
2602       else if (peek < exactly<'}'> >(q)) rv.found = q;
2603     }
2604
2605     // return result
2606     return rv;
2607   }
2608   // EO lookahead_for_value
2609
2610   void Parser::read_bom()
2611   {
2612     size_t skip = 0;
2613     std::string encoding;
2614     bool utf_8 = false;
2615     switch ((unsigned char) source[0]) {
2616     case 0xEF:
2617       skip = check_bom_chars(source, end, utf_8_bom, 3);
2618       encoding = "UTF-8";
2619       utf_8 = true;
2620       break;
2621     case 0xFE:
2622       skip = check_bom_chars(source, end, utf_16_bom_be, 2);
2623       encoding = "UTF-16 (big endian)";
2624       break;
2625     case 0xFF:
2626       skip = check_bom_chars(source, end, utf_16_bom_le, 2);
2627       skip += (skip ? check_bom_chars(source, end, utf_32_bom_le, 4) : 0);
2628       encoding = (skip == 2 ? "UTF-16 (little endian)" : "UTF-32 (little endian)");
2629       break;
2630     case 0x00:
2631       skip = check_bom_chars(source, end, utf_32_bom_be, 4);
2632       encoding = "UTF-32 (big endian)";
2633       break;
2634     case 0x2B:
2635       skip = check_bom_chars(source, end, utf_7_bom_1, 4)
2636            | check_bom_chars(source, end, utf_7_bom_2, 4)
2637            | check_bom_chars(source, end, utf_7_bom_3, 4)
2638            | check_bom_chars(source, end, utf_7_bom_4, 4)
2639            | check_bom_chars(source, end, utf_7_bom_5, 5);
2640       encoding = "UTF-7";
2641       break;
2642     case 0xF7:
2643       skip = check_bom_chars(source, end, utf_1_bom, 3);
2644       encoding = "UTF-1";
2645       break;
2646     case 0xDD:
2647       skip = check_bom_chars(source, end, utf_ebcdic_bom, 4);
2648       encoding = "UTF-EBCDIC";
2649       break;
2650     case 0x0E:
2651       skip = check_bom_chars(source, end, scsu_bom, 3);
2652       encoding = "SCSU";
2653       break;
2654     case 0xFB:
2655       skip = check_bom_chars(source, end, bocu_1_bom, 3);
2656       encoding = "BOCU-1";
2657       break;
2658     case 0x84:
2659       skip = check_bom_chars(source, end, gb_18030_bom, 4);
2660       encoding = "GB-18030";
2661       break;
2662     }
2663     if (skip > 0 && !utf_8) error("only UTF-8 documents are currently supported; your document appears to be " + encoding, pstate);
2664     position += skip;
2665   }
2666
2667   size_t check_bom_chars(const char* src, const char *end, const unsigned char* bom, size_t len)
2668   {
2669     size_t skip = 0;
2670     if (src + len > end) return 0;
2671     for (size_t i = 0; i < len; ++i, ++skip) {
2672       if ((unsigned char) src[i] != bom[i]) return 0;
2673     }
2674     return skip;
2675   }
2676
2677
2678   Expression_Obj Parser::fold_operands(Expression_Obj base, std::vector<Expression_Obj>& operands, Operand op)
2679   {
2680     for (size_t i = 0, S = operands.size(); i < S; ++i) {
2681       base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), op, base, operands[i]);
2682     }
2683     return base;
2684   }
2685
2686   Expression_Obj Parser::fold_operands(Expression_Obj base, std::vector<Expression_Obj>& operands, std::vector<Operand>& ops, size_t i)
2687   {
2688     if (String_Schema_Ptr schema = Cast<String_Schema>(base)) {
2689       // return schema;
2690       if (schema->has_interpolants()) {
2691         if (i + 1 < operands.size() && (
2692              (ops[0].operand == Sass_OP::EQ)
2693           || (ops[0].operand == Sass_OP::ADD)
2694           || (ops[0].operand == Sass_OP::DIV)
2695           || (ops[0].operand == Sass_OP::MUL)
2696           || (ops[0].operand == Sass_OP::NEQ)
2697           || (ops[0].operand == Sass_OP::LT)
2698           || (ops[0].operand == Sass_OP::GT)
2699           || (ops[0].operand == Sass_OP::LTE)
2700           || (ops[0].operand == Sass_OP::GTE)
2701         )) {
2702           Expression_Obj rhs = fold_operands(operands[i], operands, ops, i + 1);
2703           rhs = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[0], schema, rhs);
2704           return rhs;
2705         }
2706         // return schema;
2707       }
2708     }
2709
2710     for (size_t S = operands.size(); i < S; ++i) {
2711       if (String_Schema_Ptr schema = Cast<String_Schema>(operands[i])) {
2712         if (schema->has_interpolants()) {
2713           if (i + 1 < S) {
2714             // this whole branch is never hit via spec tests
2715             Expression_Obj rhs = fold_operands(operands[i+1], operands, ops, i + 2);
2716             rhs = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], schema, rhs);
2717             base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], base, rhs);
2718             return base;
2719           }
2720           base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], base, operands[i]);
2721           return base;
2722         } else {
2723           base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], base, operands[i]);
2724         }
2725       } else {
2726         base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], base, operands[i]);
2727       }
2728       Binary_Expression_Ptr b = Cast<Binary_Expression>(base.ptr());
2729       if (b && ops[i].operand == Sass_OP::DIV && b->left()->is_delayed() && b->right()->is_delayed()) {
2730         base->is_delayed(true);
2731       }
2732     }
2733     // nested binary expression are never to be delayed
2734     if (Binary_Expression_Ptr b = Cast<Binary_Expression>(base)) {
2735       if (Cast<Binary_Expression>(b->left())) base->set_delayed(false);
2736       if (Cast<Binary_Expression>(b->right())) base->set_delayed(false);
2737     }
2738     return base;
2739   }
2740
2741   void Parser::error(std::string msg, Position pos)
2742   {
2743     throw Exception::InvalidSass(ParserState(path, source, pos.line ? pos : before_token, Offset(0, 0)), msg);
2744   }
2745
2746   // print a css parsing error with actual context information from parsed source
2747   void Parser::css_error(const std::string& msg, const std::string& prefix, const std::string& middle)
2748   {
2749     int max_len = 18;
2750     const char* end = this->end;
2751     while (*end != 0) ++ end;
2752     const char* pos = peek < optional_spaces >();
2753
2754     const char* last_pos(pos);
2755     if (last_pos > source) {
2756       utf8::prior(last_pos, source);
2757     }
2758     // backup position to last significant char
2759     while (last_pos > source && last_pos < end) {
2760       if (!Prelexer::is_space(*last_pos)) break;
2761       utf8::prior(last_pos, source);
2762     }
2763
2764     bool ellipsis_left = false;
2765     const char* pos_left(last_pos);
2766     const char* end_left(last_pos);
2767
2768     if (*pos_left) utf8::next(pos_left, end);
2769     if (*end_left) utf8::next(end_left, end);
2770     while (pos_left > source) {
2771       if (utf8::distance(pos_left, end_left) >= max_len) {
2772         utf8::prior(pos_left, source);
2773         ellipsis_left = *(pos_left) != '\n' &&
2774                         *(pos_left) != '\r';
2775         utf8::next(pos_left, end);
2776         break;
2777       }
2778
2779       const char* prev = pos_left;
2780       utf8::prior(prev, source);
2781       if (*prev == '\r') break;
2782       if (*prev == '\n') break;
2783       pos_left = prev;
2784     }
2785     if (pos_left < source) {
2786       pos_left = source;
2787     }
2788
2789     bool ellipsis_right = false;
2790     const char* end_right(pos);
2791     const char* pos_right(pos);
2792     while (end_right < end) {
2793       if (utf8::distance(pos_right, end_right) > max_len) {
2794         ellipsis_left = *(pos_right) != '\n' &&
2795                         *(pos_right) != '\r';
2796         break;
2797       }
2798       if (*end_right == '\r') break;
2799       if (*end_right == '\n') break;
2800       utf8::next(end_right, end);
2801     }
2802     // if (*end_right == 0) end_right ++;
2803
2804     std::string left(pos_left, end_left);
2805     std::string right(pos_right, end_right);
2806     size_t left_subpos = left.size() > 15 ? left.size() - 15 : 0;
2807     size_t right_subpos = right.size() > 15 ? right.size() - 15 : 0;
2808     if (left_subpos && ellipsis_left) left = ellipsis + left.substr(left_subpos);
2809     if (right_subpos && ellipsis_right) right = right.substr(right_subpos) + ellipsis;
2810     // now pass new message to the more generic error function
2811     error(msg + prefix + quote(left) + middle + quote(right), pstate);
2812   }
2813
2814 }