sassc 2.2.1 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -0
  3. data/CHANGELOG.md +18 -0
  4. data/Rakefile +1 -3
  5. data/ext/extconf.rb +13 -5
  6. data/ext/libsass/VERSION +1 -1
  7. data/ext/libsass/include/sass/base.h +2 -1
  8. data/ext/libsass/include/sass/context.h +4 -0
  9. data/ext/libsass/src/MurmurHash2.hpp +91 -0
  10. data/ext/libsass/src/ast.cpp +158 -168
  11. data/ext/libsass/src/ast.hpp +389 -230
  12. data/ext/libsass/src/ast_def_macros.hpp +18 -10
  13. data/ext/libsass/src/ast_fwd_decl.cpp +4 -3
  14. data/ext/libsass/src/ast_fwd_decl.hpp +98 -165
  15. data/ext/libsass/src/ast_helpers.hpp +292 -0
  16. data/ext/libsass/src/ast_sel_cmp.cpp +219 -732
  17. data/ext/libsass/src/ast_sel_super.cpp +539 -0
  18. data/ext/libsass/src/ast_sel_unify.cpp +207 -212
  19. data/ext/libsass/src/ast_sel_weave.cpp +616 -0
  20. data/ext/libsass/src/ast_selectors.cpp +594 -1026
  21. data/ext/libsass/src/ast_selectors.hpp +339 -385
  22. data/ext/libsass/src/ast_supports.cpp +36 -52
  23. data/ext/libsass/src/ast_supports.hpp +29 -29
  24. data/ext/libsass/src/ast_values.cpp +271 -84
  25. data/ext/libsass/src/ast_values.hpp +116 -107
  26. data/ext/libsass/src/backtrace.cpp +9 -9
  27. data/ext/libsass/src/backtrace.hpp +5 -5
  28. data/ext/libsass/src/base64vlq.cpp +2 -2
  29. data/ext/libsass/src/base64vlq.hpp +1 -1
  30. data/ext/libsass/src/bind.cpp +18 -18
  31. data/ext/libsass/src/bind.hpp +1 -1
  32. data/ext/libsass/src/c2ast.cpp +3 -3
  33. data/ext/libsass/src/c2ast.hpp +1 -1
  34. data/ext/libsass/src/cencode.c +4 -6
  35. data/ext/libsass/src/check_nesting.cpp +40 -41
  36. data/ext/libsass/src/check_nesting.hpp +6 -2
  37. data/ext/libsass/src/color_maps.cpp +14 -13
  38. data/ext/libsass/src/color_maps.hpp +1 -9
  39. data/ext/libsass/src/constants.cpp +5 -0
  40. data/ext/libsass/src/constants.hpp +6 -0
  41. data/ext/libsass/src/context.cpp +92 -119
  42. data/ext/libsass/src/context.hpp +41 -53
  43. data/ext/libsass/src/cssize.cpp +66 -149
  44. data/ext/libsass/src/cssize.hpp +17 -23
  45. data/ext/libsass/src/dart_helpers.hpp +199 -0
  46. data/ext/libsass/src/debugger.hpp +451 -295
  47. data/ext/libsass/src/emitter.cpp +15 -16
  48. data/ext/libsass/src/emitter.hpp +10 -12
  49. data/ext/libsass/src/environment.cpp +27 -27
  50. data/ext/libsass/src/environment.hpp +29 -24
  51. data/ext/libsass/src/error_handling.cpp +62 -41
  52. data/ext/libsass/src/error_handling.hpp +61 -51
  53. data/ext/libsass/src/eval.cpp +167 -281
  54. data/ext/libsass/src/eval.hpp +27 -29
  55. data/ext/libsass/src/eval_selectors.cpp +75 -0
  56. data/ext/libsass/src/expand.cpp +275 -222
  57. data/ext/libsass/src/expand.hpp +36 -16
  58. data/ext/libsass/src/extender.cpp +1188 -0
  59. data/ext/libsass/src/extender.hpp +399 -0
  60. data/ext/libsass/src/extension.cpp +43 -0
  61. data/ext/libsass/src/extension.hpp +89 -0
  62. data/ext/libsass/src/file.cpp +81 -72
  63. data/ext/libsass/src/file.hpp +28 -37
  64. data/ext/libsass/src/fn_colors.cpp +20 -18
  65. data/ext/libsass/src/fn_lists.cpp +30 -29
  66. data/ext/libsass/src/fn_maps.cpp +3 -3
  67. data/ext/libsass/src/fn_miscs.cpp +34 -46
  68. data/ext/libsass/src/fn_numbers.cpp +20 -13
  69. data/ext/libsass/src/fn_selectors.cpp +98 -128
  70. data/ext/libsass/src/fn_strings.cpp +47 -33
  71. data/ext/libsass/src/fn_utils.cpp +31 -29
  72. data/ext/libsass/src/fn_utils.hpp +17 -11
  73. data/ext/libsass/src/inspect.cpp +186 -148
  74. data/ext/libsass/src/inspect.hpp +31 -29
  75. data/ext/libsass/src/lexer.cpp +20 -82
  76. data/ext/libsass/src/lexer.hpp +5 -16
  77. data/ext/libsass/src/listize.cpp +23 -37
  78. data/ext/libsass/src/listize.hpp +8 -9
  79. data/ext/libsass/src/mapping.hpp +1 -0
  80. data/ext/libsass/src/memory/allocator.cpp +48 -0
  81. data/ext/libsass/src/memory/allocator.hpp +138 -0
  82. data/ext/libsass/src/memory/config.hpp +20 -0
  83. data/ext/libsass/src/memory/memory_pool.hpp +186 -0
  84. data/ext/libsass/src/memory/{SharedPtr.cpp → shared_ptr.cpp} +2 -2
  85. data/ext/libsass/src/memory/{SharedPtr.hpp → shared_ptr.hpp} +55 -9
  86. data/ext/libsass/src/memory.hpp +12 -0
  87. data/ext/libsass/src/operation.hpp +71 -61
  88. data/ext/libsass/src/operators.cpp +19 -18
  89. data/ext/libsass/src/operators.hpp +11 -11
  90. data/ext/libsass/src/ordered_map.hpp +112 -0
  91. data/ext/libsass/src/output.cpp +45 -64
  92. data/ext/libsass/src/output.hpp +6 -6
  93. data/ext/libsass/src/parser.cpp +512 -700
  94. data/ext/libsass/src/parser.hpp +89 -97
  95. data/ext/libsass/src/parser_selectors.cpp +189 -0
  96. data/ext/libsass/src/permutate.hpp +164 -0
  97. data/ext/libsass/src/plugins.cpp +7 -7
  98. data/ext/libsass/src/plugins.hpp +8 -8
  99. data/ext/libsass/src/position.cpp +7 -26
  100. data/ext/libsass/src/position.hpp +44 -21
  101. data/ext/libsass/src/prelexer.cpp +6 -6
  102. data/ext/libsass/src/remove_placeholders.cpp +55 -56
  103. data/ext/libsass/src/remove_placeholders.hpp +21 -18
  104. data/ext/libsass/src/sass.cpp +16 -15
  105. data/ext/libsass/src/sass.hpp +10 -5
  106. data/ext/libsass/src/sass2scss.cpp +4 -4
  107. data/ext/libsass/src/sass_context.cpp +91 -122
  108. data/ext/libsass/src/sass_context.hpp +2 -2
  109. data/ext/libsass/src/sass_functions.cpp +1 -1
  110. data/ext/libsass/src/sass_values.cpp +8 -11
  111. data/ext/libsass/src/settings.hpp +19 -0
  112. data/ext/libsass/src/source.cpp +69 -0
  113. data/ext/libsass/src/source.hpp +95 -0
  114. data/ext/libsass/src/source_data.hpp +32 -0
  115. data/ext/libsass/src/source_map.cpp +22 -18
  116. data/ext/libsass/src/source_map.hpp +12 -9
  117. data/ext/libsass/src/stylesheet.cpp +22 -0
  118. data/ext/libsass/src/stylesheet.hpp +57 -0
  119. data/ext/libsass/src/to_value.cpp +2 -2
  120. data/ext/libsass/src/to_value.hpp +1 -1
  121. data/ext/libsass/src/units.cpp +24 -22
  122. data/ext/libsass/src/units.hpp +8 -8
  123. data/ext/libsass/src/utf8_string.cpp +9 -10
  124. data/ext/libsass/src/utf8_string.hpp +7 -6
  125. data/ext/libsass/src/util.cpp +48 -50
  126. data/ext/libsass/src/util.hpp +20 -21
  127. data/ext/libsass/src/util_string.cpp +111 -61
  128. data/ext/libsass/src/util_string.hpp +62 -8
  129. data/ext/libsass/src/values.cpp +12 -12
  130. data/lib/sassc/engine.rb +5 -3
  131. data/lib/sassc/functions_handler.rb +8 -8
  132. data/lib/sassc/native.rb +4 -6
  133. data/lib/sassc/script.rb +4 -4
  134. data/lib/sassc/version.rb +1 -1
  135. data/test/functions_test.rb +18 -1
  136. data/test/native_test.rb +4 -4
  137. metadata +29 -15
  138. data/ext/libsass/src/extend.cpp +0 -2132
  139. data/ext/libsass/src/extend.hpp +0 -86
  140. data/ext/libsass/src/node.cpp +0 -322
  141. data/ext/libsass/src/node.hpp +0 -118
  142. data/ext/libsass/src/paths.hpp +0 -71
  143. data/ext/libsass/src/sass_util.cpp +0 -152
  144. data/ext/libsass/src/sass_util.hpp +0 -256
  145. data/ext/libsass/src/subset_map.cpp +0 -58
  146. data/ext/libsass/src/subset_map.hpp +0 -76
  147. data/lib/sassc/native/lib_c.rb +0 -21
@@ -3,14 +3,7 @@
3
3
  #include "sass.hpp"
4
4
 
5
5
  #include "parser.hpp"
6
- #include "file.hpp"
7
- #include "inspect.hpp"
8
- #include "constants.hpp"
9
- #include "util.hpp"
10
- #include "prelexer.hpp"
11
6
  #include "color_maps.hpp"
12
- #include "sass/functions.h"
13
- #include "error_handling.hpp"
14
7
  #include "util_string.hpp"
15
8
 
16
9
  // Notes about delayed: some ast nodes can have delayed evaluation so
@@ -25,56 +18,46 @@
25
18
  // Another case with delayed values are colors. In compressed mode
26
19
  // only processed values get compressed (other are left as written).
27
20
 
28
- #include <cstdlib>
29
- #include <iostream>
30
- #include <vector>
31
- #include <typeinfo>
32
21
 
33
22
  namespace Sass {
34
23
  using namespace Constants;
35
24
  using namespace Prelexer;
36
25
 
37
- Parser Parser::from_c_str(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source, bool allow_parent)
38
- {
39
- pstate.offset.column = 0;
40
- pstate.offset.line = 0;
41
- Parser p(ctx, pstate, traces, allow_parent);
42
- p.source = source ? source : beg;
43
- p.position = beg ? beg : p.source;
44
- p.end = p.position + strlen(p.position);
45
- Block_Obj root = SASS_MEMORY_NEW(Block, pstate);
46
- p.block_stack.push_back(root);
47
- root->is_root(true);
48
- return p;
49
- }
50
26
 
51
- Parser Parser::from_c_str(const char* beg, const char* end, Context& ctx, Backtraces traces, ParserState pstate, const char* source, bool allow_parent)
27
+ Parser::Parser(SourceData* source, Context& ctx, Backtraces traces, bool allow_parent) :
28
+ SourceSpan(source),
29
+ ctx(ctx),
30
+ source(source),
31
+ begin(source->begin()),
32
+ position(source->begin()),
33
+ end(source->end()),
34
+ before_token(0, 0),
35
+ after_token(0, 0),
36
+ pstate(source->getSourceSpan()),
37
+ traces(traces),
38
+ indentation(0),
39
+ nestings(0),
40
+ allow_parent(allow_parent)
52
41
  {
53
- pstate.offset.column = 0;
54
- pstate.offset.line = 0;
55
- Parser p(ctx, pstate, traces, allow_parent);
56
- p.source = source ? source : beg;
57
- p.position = beg ? beg : p.source;
58
- p.end = end ? end : p.position + strlen(p.position);
59
42
  Block_Obj root = SASS_MEMORY_NEW(Block, pstate);
60
- p.block_stack.push_back(root);
43
+ stack.push_back(Scope::Root);
44
+ block_stack.push_back(root);
61
45
  root->is_root(true);
62
- return p;
63
46
  }
64
47
 
65
- void Parser::advanceToNextToken() {
48
+ void Parser::advanceToNextToken() {
66
49
  lex < css_comments >(false);
67
50
  // advance to position
68
- pstate += pstate.offset;
51
+ pstate.position += pstate.offset;
69
52
  pstate.offset.column = 0;
70
53
  pstate.offset.line = 0;
71
54
  }
72
55
 
73
- Selector_List_Obj Parser::parse_selector(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source, bool allow_parent)
56
+ SelectorListObj Parser::parse_selector(SourceData* source, Context& ctx, Backtraces traces, bool allow_parent)
74
57
  {
75
- Parser p = Parser::from_c_str(beg, ctx, traces, pstate, source, allow_parent);
58
+ Parser p(source, ctx, traces, allow_parent);
76
59
  // ToDo: remap the source-map entries somehow
77
- return p.parse_selector_list(false);
60
+ return p.parseSelectorList(false);
78
61
  }
79
62
 
80
63
  bool Parser::peek_newline(const char* start)
@@ -83,18 +66,6 @@ namespace Sass {
83
66
  && ! peek_css<exactly<'{'>>(start);
84
67
  }
85
68
 
86
- Parser Parser::from_token(Token t, Context& ctx, Backtraces traces, ParserState pstate, const char* source)
87
- {
88
- Parser p(ctx, pstate, traces);
89
- p.source = source ? source : t.begin;
90
- p.position = t.begin ? t.begin : p.source;
91
- p.end = t.end ? t.end : p.position + strlen(p.position);
92
- Block_Obj root = SASS_MEMORY_NEW(Block, pstate);
93
- p.block_stack.push_back(root);
94
- root->is_root(true);
95
- return p;
96
- }
97
-
98
69
  /* main entry point to parse root block */
99
70
  Block_Obj Parser::parse()
100
71
  {
@@ -107,7 +78,7 @@ namespace Sass {
107
78
 
108
79
  // report invalid utf8
109
80
  if (it != end) {
110
- pstate += Offset::init(position, it);
81
+ pstate.position += Offset::init(position, it);
111
82
  traces.push_back(Backtrace(pstate));
112
83
  throw Exception::InvalidSass(pstate, traces, "Invalid UTF-8 sequence");
113
84
  }
@@ -118,7 +89,7 @@ namespace Sass {
118
89
  // check seems a bit esoteric but works
119
90
  if (ctx.resources.size() == 1) {
120
91
  // apply headers only on very first include
121
- ctx.apply_custom_headers(root, path, pstate);
92
+ ctx.apply_custom_headers(root, getPath(), pstate);
122
93
  }
123
94
 
124
95
  // parse children nodes
@@ -261,16 +232,23 @@ namespace Sass {
261
232
  else if (lex < kwd_extend >(true)) {
262
233
  Lookahead lookahead = lookahead_for_include(position);
263
234
  if (!lookahead.found) css_error("Invalid CSS", " after ", ": expected selector, was ");
264
- Selector_List_Obj target;
235
+ SelectorListObj target;
265
236
  if (!lookahead.has_interpolants) {
266
- target = parse_selector_list(true);
237
+ LOCAL_FLAG(allow_parent, false);
238
+ auto selector = parseSelectorList(true);
239
+ auto extender = SASS_MEMORY_NEW(ExtendRule, pstate, selector);
240
+ extender->isOptional(selector && selector->is_optional());
241
+ block->append(extender);
267
242
  }
268
243
  else {
269
- target = SASS_MEMORY_NEW(Selector_List, pstate);
270
- target->schema(parse_selector_schema(lookahead.found, true));
244
+ LOCAL_FLAG(allow_parent, false);
245
+ auto selector = parse_selector_schema(lookahead.found, true);
246
+ auto extender = SASS_MEMORY_NEW(ExtendRule, pstate, selector);
247
+ // A schema is not optional yet, check once it is evaluated
248
+ // extender->isOptional(selector && selector->is_optional());
249
+ block->append(extender);
271
250
  }
272
251
 
273
- block->append(SASS_MEMORY_NEW(Extension, pstate, target));
274
252
  }
275
253
 
276
254
  // selector may contain interpolations which need delayed evaluation
@@ -283,7 +261,7 @@ namespace Sass {
283
261
  }
284
262
 
285
263
  // parse multiple specific keyword directives
286
- else if (lex < kwd_media >(true)) { block->append(parse_media_block()); }
264
+ else if (lex < kwd_media >(true)) { block->append(parseMediaRule()); }
287
265
  else if (lex < kwd_at_root >(true)) { block->append(parse_at_root_block()); }
288
266
  else if (lex < kwd_include_directive >(true)) { block->append(parse_include_directive()); }
289
267
  else if (lex < kwd_content_directive >(true)) { block->append(parse_content_directive()); }
@@ -294,9 +272,9 @@ namespace Sass {
294
272
  // ignore the @charset directive for now
295
273
  else if (lex< kwd_charset_directive >(true)) { parse_charset_directive(); }
296
274
 
275
+ else if (lex < exactly < else_kwd >>(true)) { error("Invalid CSS: @else must come after @if"); }
276
+
297
277
  // generic at keyword (keep last)
298
- else if (lex< re_special_directive >(true)) { block->append(parse_special_directive()); }
299
- else if (lex< re_prefixed_directive >(true)) { block->append(parse_prefixed_directive()); }
300
278
  else if (lex< at_keyword >(true)) { block->append(parse_directive()); }
301
279
 
302
280
  else if (is_root && stack.back() != Scope::AtRoot /* && block->is_root() */) {
@@ -331,33 +309,33 @@ namespace Sass {
331
309
  Import_Obj Parser::parse_import()
332
310
  {
333
311
  Import_Obj imp = SASS_MEMORY_NEW(Import, pstate);
334
- std::vector<std::pair<std::string,Function_Call_Obj>> to_import;
312
+ sass::vector<std::pair<sass::string,Function_Call_Obj>> to_import;
335
313
  bool first = true;
336
314
  do {
337
315
  while (lex< block_comment >());
338
316
  if (lex< quoted_string >()) {
339
- to_import.push_back(std::pair<std::string,Function_Call_Obj>(std::string(lexed), {}));
317
+ to_import.push_back(std::pair<sass::string,Function_Call_Obj>(sass::string(lexed), {}));
340
318
  }
341
319
  else if (lex< uri_prefix >()) {
342
320
  Arguments_Obj args = SASS_MEMORY_NEW(Arguments, pstate);
343
- Function_Call_Obj result = SASS_MEMORY_NEW(Function_Call, pstate, std::string("url"), args);
321
+ Function_Call_Obj result = SASS_MEMORY_NEW(Function_Call, pstate, sass::string("url"), args);
344
322
 
345
323
  if (lex< quoted_string >()) {
346
- Expression_Obj quoted_url = parse_string();
324
+ ExpressionObj quoted_url = parse_string();
347
325
  args->append(SASS_MEMORY_NEW(Argument, quoted_url->pstate(), quoted_url));
348
326
  }
349
327
  else if (String_Obj string_url = parse_url_function_argument()) {
350
328
  args->append(SASS_MEMORY_NEW(Argument, string_url->pstate(), string_url));
351
329
  }
352
330
  else if (peek < skip_over_scopes < exactly < '(' >, exactly < ')' > > >(position)) {
353
- Expression_Obj braced_url = parse_list(); // parse_interpolated_chunk(lexed);
331
+ ExpressionObj braced_url = parse_list(); // parse_interpolated_chunk(lexed);
354
332
  args->append(SASS_MEMORY_NEW(Argument, braced_url->pstate(), braced_url));
355
333
  }
356
334
  else {
357
335
  error("malformed URL");
358
336
  }
359
337
  if (!lex< exactly<')'> >()) error("URI is missing ')'");
360
- to_import.push_back(std::pair<std::string, Function_Call_Obj>("", result));
338
+ to_import.push_back(std::pair<sass::string, Function_Call_Obj>("", result));
361
339
  }
362
340
  else {
363
341
  if (first) error("@import directive requires a url or quoted path");
@@ -376,9 +354,9 @@ namespace Sass {
376
354
  imp->urls().push_back(location.second);
377
355
  }
378
356
  // check if custom importers want to take over the handling
379
- else if (!ctx.call_importers(unquote(location.first), path, pstate, imp)) {
357
+ else if (!ctx.call_importers(unquote(location.first), getPath(), pstate, imp)) {
380
358
  // nobody wants it, so we do our import
381
- ctx.import_url(imp, location.first, path);
359
+ ctx.import_url(imp, location.first, getPath());
382
360
  }
383
361
  }
384
362
 
@@ -387,12 +365,12 @@ namespace Sass {
387
365
 
388
366
  Definition_Obj Parser::parse_definition(Definition::Type which_type)
389
367
  {
390
- std::string which_str(lexed);
368
+ sass::string which_str(lexed);
391
369
  if (!lex< identifier >()) error("invalid name in " + which_str + " definition");
392
- std::string name(Util::normalize_underscores(lexed));
370
+ sass::string name(Util::normalize_underscores(lexed));
393
371
  if (which_type == Definition::FUNCTION && (name == "and" || name == "or" || name == "not"))
394
372
  { error("Invalid function name \"" + name + "\"."); }
395
- ParserState source_position_of_def = pstate;
373
+ SourceSpan source_position_of_def = pstate;
396
374
  Parameters_Obj params = parse_parameters();
397
375
  if (which_type == Definition::MIXIN) stack.push_back(Scope::Mixin);
398
376
  else stack.push_back(Scope::Function);
@@ -426,9 +404,9 @@ namespace Sass {
426
404
  }
427
405
  while (lex< alternatives < spaces, block_comment > >());
428
406
  lex < variable >();
429
- std::string name(Util::normalize_underscores(lexed));
430
- ParserState pos = pstate;
431
- Expression_Obj val;
407
+ sass::string name(Util::normalize_underscores(lexed));
408
+ SourceSpan pos = pstate;
409
+ ExpressionObj val;
432
410
  bool is_rest = false;
433
411
  while (lex< alternatives < spaces, block_comment > >());
434
412
  if (lex< exactly<':'> >()) { // there's a default value
@@ -472,16 +450,16 @@ namespace Sass {
472
450
  Argument_Obj arg;
473
451
  if (peek_css< sequence < variable, optional_css_comments, exactly<':'> > >()) {
474
452
  lex_css< variable >();
475
- std::string name(Util::normalize_underscores(lexed));
476
- ParserState p = pstate;
453
+ sass::string name(Util::normalize_underscores(lexed));
454
+ SourceSpan p = pstate;
477
455
  lex_css< exactly<':'> >();
478
- Expression_Obj val = parse_space_list();
456
+ ExpressionObj val = parse_space_list();
479
457
  arg = SASS_MEMORY_NEW(Argument, p, val, name);
480
458
  }
481
459
  else {
482
460
  bool is_arglist = false;
483
461
  bool is_keyword = false;
484
- Expression_Obj val = parse_space_list();
462
+ ExpressionObj val = parse_space_list();
485
463
  List* l = Cast<List>(val);
486
464
  if (lex_css< exactly< ellipsis > >()) {
487
465
  if (val->concrete_type() == Expression::MAP || (
@@ -496,13 +474,13 @@ namespace Sass {
496
474
 
497
475
  Assignment_Obj Parser::parse_assignment()
498
476
  {
499
- std::string name(Util::normalize_underscores(lexed));
500
- ParserState var_source_position = pstate;
477
+ sass::string name(Util::normalize_underscores(lexed));
478
+ SourceSpan var_source_position = pstate;
501
479
  if (!lex< exactly<':'> >()) error("expected ':' after " + name + " in assignment statement");
502
480
  if (peek_css< alternatives < exactly<';'>, end_of_file > >()) {
503
481
  css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
504
482
  }
505
- Expression_Obj val;
483
+ ExpressionObj val;
506
484
  Lookahead lookahead = lookahead_for_value(position);
507
485
  if (lookahead.has_interpolants && lookahead.found) {
508
486
  val = parse_value_schema(lookahead.found);
@@ -519,7 +497,7 @@ namespace Sass {
519
497
  }
520
498
 
521
499
  // a ruleset connects a selector and a block
522
- Ruleset_Obj Parser::parse_ruleset(Lookahead lookahead)
500
+ StyleRuleObj Parser::parse_ruleset(Lookahead lookahead)
523
501
  {
524
502
  NESTING_GUARD(nestings);
525
503
  // inherit is_root from parent block
@@ -528,12 +506,15 @@ namespace Sass {
528
506
  // make sure to move up the the last position
529
507
  lex < optional_css_whitespace >(false, true);
530
508
  // create the connector object (add parts later)
531
- Ruleset_Obj ruleset = SASS_MEMORY_NEW(Ruleset, pstate);
509
+ StyleRuleObj ruleset = SASS_MEMORY_NEW(StyleRule, pstate);
532
510
  // parse selector static or as schema to be evaluated later
533
- if (lookahead.parsable) ruleset->selector(parse_selector_list(false));
511
+ if (lookahead.parsable) {
512
+ ruleset->selector(parseSelectorList(false));
513
+ }
534
514
  else {
535
- Selector_List_Obj list = SASS_MEMORY_NEW(Selector_List, pstate);
536
- list->schema(parse_selector_schema(lookahead.position, false));
515
+ SelectorListObj list = SASS_MEMORY_NEW(SelectorList, pstate);
516
+ auto sc = parse_selector_schema(lookahead.position, false);
517
+ ruleset->schema(sc);
537
518
  ruleset->selector(list);
538
519
  }
539
520
  // then parse the inner block
@@ -563,17 +544,16 @@ namespace Sass {
563
544
  // the selector schema is pretty much just a wrapper for the string schema
564
545
  Selector_Schema_Obj selector_schema = SASS_MEMORY_NEW(Selector_Schema, pstate, schema);
565
546
  selector_schema->connect_parent(chroot == false);
566
- selector_schema->media_block(last_media_block);
567
547
 
568
548
  // process until end
569
549
  while (i < end_of_selector) {
570
- // try to parse mutliple interpolants
550
+ // try to parse multiple interpolants
571
551
  if (const char* p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, end_of_selector)) {
572
552
  // accumulate the preceding segment if the position has advanced
573
553
  if (i < p) {
574
- std::string parsed(i, p);
554
+ sass::string parsed(i, p);
575
555
  String_Constant_Obj str = SASS_MEMORY_NEW(String_Constant, pstate, parsed);
576
- pstate += Offset(parsed);
556
+ pstate.position += Offset(parsed);
577
557
  str->update_pstate(pstate);
578
558
  schema->append(str);
579
559
  }
@@ -586,15 +566,16 @@ namespace Sass {
586
566
  css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
587
567
  }
588
568
  // pass inner expression to the parser to resolve nested interpolations
589
- pstate.add(p, p+2);
590
- Expression_Obj interpolant = Parser::from_c_str(p+2, j, ctx, traces, pstate).parse_list();
569
+ LocalOption<const char*> partEnd(end, j);
570
+ LocalOption<const char*> partBeg(position, p + 2);
571
+ ExpressionObj interpolant = parse_list();
591
572
  // set status on the list expression
592
573
  interpolant->is_interpolant(true);
593
574
  // schema->has_interpolants(true);
594
575
  // add to the string schema
595
576
  schema->append(interpolant);
596
577
  // advance parser state
597
- pstate.add(p+2, j);
578
+ pstate.position.add(p+2, j);
598
579
  // advance position
599
580
  i = j;
600
581
  }
@@ -603,9 +584,9 @@ namespace Sass {
603
584
  else {
604
585
  // make sure to add the last bits of the string up to the end (if any)
605
586
  if (i < end_of_selector) {
606
- std::string parsed(i, end_of_selector);
587
+ sass::string parsed(i, end_of_selector);
607
588
  String_Constant_Obj str = SASS_MEMORY_NEW(String_Constant, pstate, parsed);
608
- pstate += Offset(parsed);
589
+ pstate.position += Offset(parsed);
609
590
  str->update_pstate(pstate);
610
591
  i = end_of_selector;
611
592
  schema->append(str);
@@ -622,7 +603,7 @@ namespace Sass {
622
603
  selector_schema->update_pstate(pstate);
623
604
  schema->update_pstate(pstate);
624
605
 
625
- after_token = before_token = pstate;
606
+ after_token = before_token = pstate.position;
626
607
 
627
608
  // return parsed result
628
609
  return selector_schema.detach();
@@ -646,9 +627,9 @@ namespace Sass {
646
627
  // lex identifier into `lexed` var
647
628
  lex_identifier(); // may error out
648
629
  // normalize underscores to hyphens
649
- std::string name(Util::normalize_underscores(lexed));
630
+ sass::string name(Util::normalize_underscores(lexed));
650
631
  // create the initial mixin call object
651
- Mixin_Call_Obj call = SASS_MEMORY_NEW(Mixin_Call, pstate, name, {}, {}, {});
632
+ Mixin_Call_Obj call = SASS_MEMORY_NEW(Mixin_Call, pstate, name, Arguments_Obj{});
652
633
  // parse mandatory arguments
653
634
  call->arguments(parse_arguments());
654
635
  // parse using and optional block parameters
@@ -674,226 +655,21 @@ namespace Sass {
674
655
  }
675
656
  // EO parse_include_directive
676
657
 
677
- // parse a list of complex selectors
678
- // this is the main entry point for most
679
- Selector_List_Obj Parser::parse_selector_list(bool chroot)
680
- {
681
- bool reloop;
682
- bool had_linefeed = false;
683
- NESTING_GUARD(nestings);
684
- Complex_Selector_Obj sel;
685
- Selector_List_Obj group = SASS_MEMORY_NEW(Selector_List, pstate);
686
- group->media_block(last_media_block);
687
-
688
- if (peek_css< alternatives < end_of_file, exactly <'{'>, exactly <','> > >()) {
689
- css_error("Invalid CSS", " after ", ": expected selector, was ");
690
- }
691
-
692
- do {
693
- reloop = false;
694
-
695
- had_linefeed = had_linefeed || peek_newline();
696
-
697
- if (peek_css< alternatives < class_char < selector_list_delims > > >())
698
- break; // in case there are superfluous commas at the end
699
-
700
- // now parse the complex selector
701
- sel = parse_complex_selector(chroot);
702
-
703
- if (!sel) return group.detach();
704
-
705
- sel->has_line_feed(had_linefeed);
706
-
707
- had_linefeed = false;
708
-
709
- while (peek_css< exactly<','> >())
710
- {
711
- lex< css_comments >(false);
712
- // consume everything up and including the comma separator
713
- reloop = lex< exactly<','> >() != 0;
714
- // remember line break (also between some commas)
715
- had_linefeed = had_linefeed || peek_newline();
716
- // remember line break (also between some commas)
717
- }
718
- group->append(sel);
719
- }
720
- while (reloop);
721
- while (lex_css< kwd_optional >()) {
722
- group->is_optional(true);
723
- }
724
- // update for end position
725
- group->update_pstate(pstate);
726
- if (sel) sel->mutable_last()->has_line_break(false);
727
- return group.detach();
728
- }
729
- // EO parse_selector_list
730
-
731
- // a complex selector combines a compound selector with another
732
- // complex selector, with one of four combinator operations.
733
- // the compound selector (head) is optional, since the combinator
734
- // can come first in the whole selector sequence (like `> DIV').
735
- Complex_Selector_Obj Parser::parse_complex_selector(bool chroot)
736
- {
737
-
738
- NESTING_GUARD(nestings);
739
- String_Obj reference;
740
- lex < block_comment >();
741
- advanceToNextToken();
742
- Complex_Selector_Obj sel = SASS_MEMORY_NEW(Complex_Selector, pstate);
743
-
744
- if (peek < end_of_file >()) return {};
745
-
746
- // parse the left hand side
747
- Compound_Selector_Obj lhs;
748
- // special case if it starts with combinator ([+~>])
749
- if (!peek_css< class_char < selector_combinator_ops > >()) {
750
- // parse the left hand side
751
- lhs = parse_compound_selector();
752
- }
753
-
754
-
755
- // parse combinator between lhs and rhs
756
- Complex_Selector::Combinator combinator = Complex_Selector::ANCESTOR_OF;
757
- if (lex< exactly<'+'> >()) combinator = Complex_Selector::ADJACENT_TO;
758
- else if (lex< exactly<'~'> >()) combinator = Complex_Selector::PRECEDES;
759
- else if (lex< exactly<'>'> >()) combinator = Complex_Selector::PARENT_OF;
760
- else if (lex< sequence < exactly<'/'>, negate < exactly < '*' > > > >()) {
761
- // comments are allowed, but not spaces?
762
- combinator = Complex_Selector::REFERENCE;
763
- if (!lex < re_reference_combinator >()) return {};
764
- reference = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
765
- if (!lex < exactly < '/' > >()) return {}; // ToDo: error msg?
766
- }
767
-
768
- if (!lhs && combinator == Complex_Selector::ANCESTOR_OF) return {};
769
-
770
- // lex < block_comment >();
771
- sel->head(lhs);
772
- sel->combinator(combinator);
773
- sel->media_block(last_media_block);
774
-
775
- if (combinator == Complex_Selector::REFERENCE) sel->reference(reference);
776
- // has linfeed after combinator?
777
- sel->has_line_break(peek_newline());
778
- // sel->has_line_feed(has_line_feed);
779
-
780
- // check if we got the abort condition (ToDo: optimize)
781
- if (!peek_css< class_char < complex_selector_delims > >()) {
782
- // parse next selector in sequence
783
- sel->tail(parse_complex_selector(true));
784
- }
785
-
786
- // add a parent selector if we are not in a root
787
- // also skip adding parent ref if we only have refs
788
- if (!sel->has_parent_ref() && !chroot) {
789
- // create the objects to wrap parent selector reference
790
- Compound_Selector_Obj head = SASS_MEMORY_NEW(Compound_Selector, pstate);
791
- Parent_Selector* parent = SASS_MEMORY_NEW(Parent_Selector, pstate, false);
792
- parent->media_block(last_media_block);
793
- head->media_block(last_media_block);
794
- // add simple selector
795
- head->append(parent);
796
- // selector may not have any head yet
797
- if (!sel->head()) { sel->head(head); }
798
- // otherwise we need to create a new complex selector and set the old one as its tail
799
- else {
800
- sel = SASS_MEMORY_NEW(Complex_Selector, pstate, Complex_Selector::ANCESTOR_OF, head, sel);
801
- sel->media_block(last_media_block);
802
- }
803
- // peek for linefeed and remember result on head
804
- // if (peek_newline()) head->has_line_break(true);
805
- }
806
-
807
- sel->update_pstate(pstate);
808
- // complex selector
809
- return sel;
810
- }
811
- // EO parse_complex_selector
812
-
813
- // parse one compound selector, which is basically
814
- // a list of simple selectors (directly adjacent)
815
- // lex them exactly (without skipping white-space)
816
- Compound_Selector_Obj Parser::parse_compound_selector()
817
- {
818
- // init an empty compound selector wrapper
819
- Compound_Selector_Obj seq = SASS_MEMORY_NEW(Compound_Selector, pstate);
820
- seq->media_block(last_media_block);
821
-
822
- // skip initial white-space
823
- lex< css_whitespace >();
824
658
 
825
- // parse list
826
- while (true)
827
- {
828
- // remove all block comments (don't skip white-space)
829
- lex< delimited_by< slash_star, star_slash, false > >(false);
830
- // parse functional
831
- if (match < re_pseudo_selector >())
832
- {
833
- seq->append(parse_simple_selector());
834
- }
835
- // parse parent selector
836
- else if (lex< exactly<'&'> >(false))
837
- {
838
- if (!allow_parent) error("Parent selectors aren't allowed here.");
839
- // this produces a linefeed!?
840
- seq->has_parent_reference(true);
841
- seq->append(SASS_MEMORY_NEW(Parent_Selector, pstate));
842
- // parent selector only allowed at start
843
- // upcoming Sass may allow also trailing
844
- if (seq->length() > 1) {
845
- ParserState state(pstate);
846
- Simple_Selector_Obj cur = (*seq)[seq->length()-1];
847
- Simple_Selector_Obj prev = (*seq)[seq->length()-2];
848
- std::string sel(prev->to_string({ NESTED, 5 }));
849
- std::string found(cur->to_string({ NESTED, 5 }));
850
- if (lex < identifier >()) { found += std::string(lexed); }
851
- error("Invalid CSS after \"" + sel + "\": expected \"{\", was \"" + found + "\"\n\n"
852
- "\"" + found + "\" may only be used at the beginning of a compound selector.", state);
853
- }
854
- }
855
- // parse type selector
856
- else if (lex< re_type_selector >(false))
857
- {
858
- seq->append(SASS_MEMORY_NEW(Type_Selector, pstate, lexed));
859
- }
860
- // peek for abort conditions
861
- else if (peek< spaces >()) break;
862
- else if (peek< end_of_file >()) { break; }
863
- else if (peek_css < class_char < selector_combinator_ops > >()) break;
864
- else if (peek_css < class_char < complex_selector_delims > >()) break;
865
- // otherwise parse another simple selector
866
- else {
867
- Simple_Selector_Obj sel = parse_simple_selector();
868
- if (!sel) return {};
869
- seq->append(sel);
870
- }
871
- }
872
-
873
- if (seq && !peek_css<alternatives<end_of_file,exactly<'{'>>>()) {
874
- seq->has_line_break(peek_newline());
875
- }
876
-
877
- // EO while true
878
- return seq;
879
-
880
- }
881
- // EO parse_compound_selector
882
-
883
- Simple_Selector_Obj Parser::parse_simple_selector()
659
+ SimpleSelectorObj Parser::parse_simple_selector()
884
660
  {
885
661
  lex < css_comments >(false);
886
662
  if (lex< class_name >()) {
887
- return SASS_MEMORY_NEW(Class_Selector, pstate, lexed);
663
+ return SASS_MEMORY_NEW(ClassSelector, pstate, lexed);
888
664
  }
889
665
  else if (lex< id_name >()) {
890
- return SASS_MEMORY_NEW(Id_Selector, pstate, lexed);
666
+ return SASS_MEMORY_NEW(IDSelector, pstate, lexed);
891
667
  }
892
668
  else if (lex< alternatives < variable, number, static_reference_combinator > >()) {
893
- return SASS_MEMORY_NEW(Type_Selector, pstate, lexed);
669
+ return SASS_MEMORY_NEW(TypeSelector, pstate, lexed);
894
670
  }
895
671
  else if (peek< pseudo_not >()) {
896
- return parse_negated_selector();
672
+ return parse_negated_selector2();
897
673
  }
898
674
  else if (peek< re_pseudo_selector >()) {
899
675
  return parse_pseudo_selector();
@@ -905,9 +681,7 @@ namespace Sass {
905
681
  return parse_attribute_selector();
906
682
  }
907
683
  else if (lex< placeholder >()) {
908
- Placeholder_Selector* sel = SASS_MEMORY_NEW(Placeholder_Selector, pstate, lexed);
909
- sel->media_block(last_media_block);
910
- return sel;
684
+ return SASS_MEMORY_NEW(PlaceholderSelector, pstate, lexed);
911
685
  }
912
686
  else {
913
687
  css_error("Invalid CSS", " after ", ": expected selector, was ");
@@ -916,71 +690,104 @@ namespace Sass {
916
690
  return {};
917
691
  }
918
692
 
919
- Wrapped_Selector_Obj Parser::parse_negated_selector()
693
+ PseudoSelectorObj Parser::parse_negated_selector2()
920
694
  {
921
695
  lex< pseudo_not >();
922
- std::string name(lexed);
923
- ParserState nsource_position = pstate;
924
- Selector_List_Obj negated = parse_selector_list(true);
696
+ sass::string name(lexed);
697
+ SourceSpan nsource_position = pstate;
698
+ SelectorListObj negated = parseSelectorList(true);
925
699
  if (!lex< exactly<')'> >()) {
926
700
  error("negated selector is missing ')'");
927
701
  }
928
702
  name.erase(name.size() - 1);
929
- return SASS_MEMORY_NEW(Wrapped_Selector, nsource_position, name, negated);
703
+
704
+ PseudoSelector* sel = SASS_MEMORY_NEW(PseudoSelector, nsource_position, name.substr(1));
705
+ sel->selector(negated);
706
+ return sel;
930
707
  }
931
708
 
709
+ // Helper to clean binominal string
710
+ bool BothAreSpaces(char lhs, char rhs) { return isspace(lhs) && isspace(rhs); }
711
+
932
712
  // a pseudo selector often starts with one or two colons
933
713
  // it can contain more selectors inside parentheses
934
- Simple_Selector_Obj Parser::parse_pseudo_selector() {
935
- if (lex< sequence<
936
- pseudo_prefix,
937
- // we keep the space within the name, strange enough
938
- // ToDo: refactor output to schedule the space for it
939
- // or do we really want to keep the real white-space?
940
- sequence< identifier, optional < block_comment >, exactly<'('> >
941
- > >())
942
- {
943
-
944
- std::string name(lexed);
945
- name.erase(name.size() - 1);
946
- ParserState p = pstate;
714
+ SimpleSelectorObj Parser::parse_pseudo_selector() {
715
+
716
+ // Lex one or two colon characters
717
+ if (lex<pseudo_prefix>()) {
718
+ sass::string colons(lexed);
719
+ // Check if it is a pseudo element
720
+ bool element = colons.size() == 2;
721
+
722
+ if (lex< sequence<
723
+ // we keep the space within the name, strange enough
724
+ // ToDo: refactor output to schedule the space for it
725
+ // or do we really want to keep the real white-space?
726
+ sequence< identifier, optional < block_comment >, exactly<'('> >
727
+ > >())
728
+ {
947
729
 
948
- // specially parse static stuff
949
- // ToDo: really everything static?
950
- if (peek_css <
951
- sequence <
952
- alternatives <
953
- static_value,
954
- binomial
955
- >,
956
- optional_css_whitespace,
957
- exactly<')'>
958
- >
959
- >()
960
- ) {
961
- lex_css< alternatives < static_value, binomial > >();
962
- String_Constant_Obj expr = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
963
- if (lex_css< exactly<')'> >()) {
964
- expr->can_compress_whitespace(true);
965
- return SASS_MEMORY_NEW(Pseudo_Selector, p, name, expr);
730
+ sass::string name(lexed);
731
+ name.erase(name.size() - 1);
732
+ SourceSpan p = pstate;
733
+
734
+ // specially parse nth-child pseudo selectors
735
+ if (lex_css < sequence < binomial, word_boundary >>()) {
736
+ sass::string parsed(lexed); // always compacting binominals (as dart-sass)
737
+ parsed.erase(std::unique(parsed.begin(), parsed.end(), BothAreSpaces), parsed.end());
738
+ String_Constant_Obj arg = SASS_MEMORY_NEW(String_Constant, pstate, parsed);
739
+ PseudoSelector* pseudo = SASS_MEMORY_NEW(PseudoSelector, p, name, element);
740
+ if (lex < sequence < css_whitespace, insensitive < of_kwd >>>(false)) {
741
+ pseudo->selector(parseSelectorList(true));
742
+ }
743
+ pseudo->argument(arg);
744
+ if (lex_css< exactly<')'> >()) {
745
+ return pseudo;
746
+ }
966
747
  }
967
- }
968
- else if (Selector_List_Obj wrapped = parse_selector_list(true)) {
969
- if (wrapped && lex_css< exactly<')'> >()) {
970
- return SASS_MEMORY_NEW(Wrapped_Selector, p, name, wrapped);
748
+ else {
749
+ if (peek_css< exactly<')'>>() && Util::equalsLiteral("nth-", name.substr(0, 4))) {
750
+ css_error("Invalid CSS", " after ", ": expected An+B expression, was ");
751
+ }
752
+
753
+ sass::string unvendored = Util::unvendor(name);
754
+
755
+ if (unvendored == "not" || unvendored == "matches" || unvendored == "current" || unvendored == "any" || unvendored == "has" || unvendored == "host" || unvendored == "host-context" || unvendored == "slotted") {
756
+ if (SelectorListObj wrapped = parseSelectorList(true)) {
757
+ if (wrapped && lex_css< exactly<')'> >()) {
758
+ PseudoSelector* pseudo = SASS_MEMORY_NEW(PseudoSelector, p, name, element);
759
+ pseudo->selector(wrapped);
760
+ return pseudo;
761
+ }
762
+ }
763
+ } else {
764
+ String_Schema_Obj arg = parse_css_variable_value();
765
+ PseudoSelector* pseudo = SASS_MEMORY_NEW(PseudoSelector, p, name, element);
766
+ pseudo->argument(arg);
767
+
768
+ if (lex_css< exactly<')'> >()) {
769
+ return pseudo;
770
+ }
771
+ }
971
772
  }
773
+
972
774
  }
775
+ // EO if pseudo selector
973
776
 
974
- }
975
- // EO if pseudo selector
777
+ else if (lex < sequence< optional < pseudo_prefix >, identifier > >()) {
778
+ return SASS_MEMORY_NEW(PseudoSelector, pstate, lexed, element);
779
+ }
780
+ else if (lex < pseudo_prefix >()) {
781
+ css_error("Invalid CSS", " after ", ": expected pseudoclass or pseudoelement, was ");
782
+ }
976
783
 
977
- else if (lex < sequence< optional < pseudo_prefix >, identifier > >()) {
978
- return SASS_MEMORY_NEW(Pseudo_Selector, pstate, lexed);
979
784
  }
980
- else if(lex < pseudo_prefix >()) {
981
- css_error("Invalid CSS", " after ", ": expected pseudoclass or pseudoelement, was ");
785
+ else {
786
+ lex < identifier >(); // needed for error message?
787
+ css_error("Invalid CSS", " after ", ": expected selector, was ");
982
788
  }
983
789
 
790
+
984
791
  css_error("Invalid CSS", " after ", ": expected \")\", was ");
985
792
 
986
793
  // unreachable statement
@@ -997,23 +804,23 @@ namespace Sass {
997
804
  return sequence < insensitive<'i'>, re_attr_sensitive_close >(src);
998
805
  }
999
806
 
1000
- Attribute_Selector_Obj Parser::parse_attribute_selector()
807
+ AttributeSelectorObj Parser::parse_attribute_selector()
1001
808
  {
1002
- ParserState p = pstate;
809
+ SourceSpan p = pstate;
1003
810
  if (!lex_css< attribute_name >()) error("invalid attribute name in attribute selector");
1004
- std::string name(lexed);
811
+ sass::string name(lexed);
1005
812
  if (lex_css< re_attr_sensitive_close >()) {
1006
- return SASS_MEMORY_NEW(Attribute_Selector, p, name, "", {}, {});
813
+ return SASS_MEMORY_NEW(AttributeSelector, p, name, "", String_Obj{});
1007
814
  }
1008
815
  else if (lex_css< re_attr_insensitive_close >()) {
1009
816
  char modifier = lexed.begin[0];
1010
- return SASS_MEMORY_NEW(Attribute_Selector, p, name, "", {}, modifier);
817
+ return SASS_MEMORY_NEW(AttributeSelector, p, name, "", String_Obj{}, modifier);
1011
818
  }
1012
819
  if (!lex_css< alternatives< exact_match, class_match, dash_match,
1013
820
  prefix_match, suffix_match, substring_match > >()) {
1014
821
  error("invalid operator in attribute selector for " + name);
1015
822
  }
1016
- std::string matcher(lexed);
823
+ sass::string matcher(lexed);
1017
824
 
1018
825
  String_Obj value;
1019
826
  if (lex_css< identifier >()) {
@@ -1027,18 +834,18 @@ namespace Sass {
1027
834
  }
1028
835
 
1029
836
  if (lex_css< re_attr_sensitive_close >()) {
1030
- return SASS_MEMORY_NEW(Attribute_Selector, p, name, matcher, value, 0);
837
+ return SASS_MEMORY_NEW(AttributeSelector, p, name, matcher, value, 0);
1031
838
  }
1032
839
  else if (lex_css< re_attr_insensitive_close >()) {
1033
840
  char modifier = lexed.begin[0];
1034
- return SASS_MEMORY_NEW(Attribute_Selector, p, name, matcher, value, modifier);
841
+ return SASS_MEMORY_NEW(AttributeSelector, p, name, matcher, value, modifier);
1035
842
  }
1036
843
  error("unterminated attribute selector for " + name);
1037
844
  return {}; // to satisfy compilers (error must not return)
1038
845
  }
1039
846
 
1040
847
  /* parse block comment and add to block */
1041
- void Parser::parse_block_comments()
848
+ void Parser::parse_block_comments(bool store)
1042
849
  {
1043
850
  Block_Obj block = block_stack.back();
1044
851
 
@@ -1046,7 +853,7 @@ namespace Sass {
1046
853
  bool is_important = lexed.begin[2] == '!';
1047
854
  // flag on second param is to skip loosely over comments
1048
855
  String_Obj contents = parse_interpolated_chunk(lexed, true, false);
1049
- block->append(SASS_MEMORY_NEW(Comment, pstate, contents, is_important));
856
+ if (store) block->append(SASS_MEMORY_NEW(Comment, pstate, contents, is_important));
1050
857
  }
1051
858
  }
1052
859
 
@@ -1054,12 +861,12 @@ namespace Sass {
1054
861
  String_Obj prop;
1055
862
  bool is_custom_property = false;
1056
863
  if (lex< sequence< optional< exactly<'*'> >, identifier_schema > >()) {
1057
- const std::string property(lexed);
864
+ const sass::string property(lexed);
1058
865
  is_custom_property = property.compare(0, 2, "--") == 0;
1059
866
  prop = parse_identifier_schema();
1060
867
  }
1061
868
  else if (lex< sequence< optional< exactly<'*'> >, identifier, zero_plus< block_comment > > >()) {
1062
- const std::string property(lexed);
869
+ const sass::string property(lexed);
1063
870
  is_custom_property = property.compare(0, 2, "--") == 0;
1064
871
  prop = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
1065
872
  }
@@ -1067,7 +874,7 @@ namespace Sass {
1067
874
  css_error("Invalid CSS", " after ", ": expected \"}\", was ");
1068
875
  }
1069
876
  bool is_indented = true;
1070
- const std::string property(lexed);
877
+ const sass::string property(lexed);
1071
878
  if (!lex_css< one_plus< exactly<':'> > >()) error("property \"" + escape_string(property) + "\" must be followed by a ':'");
1072
879
  if (!is_custom_property && match< sequence< optional_css_comments, exactly<';'> > >()) error("style declaration must contain a value");
1073
880
  if (match< sequence< optional_css_comments, exactly<'{'> > >()) is_indented = false; // don't indent if value is empty
@@ -1079,7 +886,7 @@ namespace Sass {
1079
886
  return SASS_MEMORY_NEW(Declaration, prop->pstate(), prop, parse_static_value()/*, lex<kwd_important>()*/);
1080
887
  }
1081
888
  else {
1082
- Expression_Obj value;
889
+ ExpressionObj value;
1083
890
  Lookahead lookahead = lookahead_for_value(position);
1084
891
  if (lookahead.found) {
1085
892
  if (lookahead.has_interpolants) {
@@ -1104,27 +911,10 @@ namespace Sass {
1104
911
  }
1105
912
  }
1106
913
 
1107
- // parse +/- and return false if negative
1108
- // this is never hit via spec tests
1109
- bool Parser::parse_number_prefix()
1110
- {
1111
- bool positive = true;
1112
- while(true) {
1113
- if (lex < block_comment >()) continue;
1114
- if (lex < number_prefix >()) continue;
1115
- if (lex < exactly < '-' > >()) {
1116
- positive = !positive;
1117
- continue;
1118
- }
1119
- break;
1120
- }
1121
- return positive;
1122
- }
1123
-
1124
- Expression_Obj Parser::parse_map()
914
+ ExpressionObj Parser::parse_map()
1125
915
  {
1126
916
  NESTING_GUARD(nestings);
1127
- Expression_Obj key = parse_list();
917
+ ExpressionObj key = parse_list();
1128
918
  List_Obj map = SASS_MEMORY_NEW(List, pstate, 0, SASS_HASH);
1129
919
 
1130
920
  // it's not a map so return the lexed value as a list value
@@ -1136,7 +926,7 @@ namespace Sass {
1136
926
  css_error("Invalid CSS", " after ", ": expected \")\", was ");
1137
927
  }
1138
928
 
1139
- Expression_Obj value = parse_space_list();
929
+ ExpressionObj value = parse_space_list();
1140
930
 
1141
931
  map->append(key);
1142
932
  map->append(value);
@@ -1158,14 +948,14 @@ namespace Sass {
1158
948
  map->append(value);
1159
949
  }
1160
950
 
1161
- ParserState ps = map->pstate();
1162
- ps.offset = pstate - ps + pstate.offset;
951
+ SourceSpan ps = map->pstate();
952
+ ps.offset = pstate.position - ps.position + pstate.offset;
1163
953
  map->pstate(ps);
1164
954
 
1165
955
  return map;
1166
956
  }
1167
957
 
1168
- Expression_Obj Parser::parse_bracket_list()
958
+ ExpressionObj Parser::parse_bracket_list()
1169
959
  {
1170
960
  NESTING_GUARD(nestings);
1171
961
  // check if we have an empty list
@@ -1179,7 +969,7 @@ namespace Sass {
1179
969
  bool has_paren = peek_css< exactly<'('> >() != NULL;
1180
970
 
1181
971
  // now try to parse a space list
1182
- Expression_Obj list = parse_space_list();
972
+ ExpressionObj list = parse_space_list();
1183
973
  // if it's a singleton, return it (don't wrap it)
1184
974
  if (!peek_css< exactly<','> >(position)) {
1185
975
  List_Obj l = Cast<List>(list);
@@ -1212,14 +1002,14 @@ namespace Sass {
1212
1002
  // parse list returns either a space separated list,
1213
1003
  // a comma separated list or any bare expression found.
1214
1004
  // so to speak: we unwrap items from lists if possible here!
1215
- Expression_Obj Parser::parse_list(bool delayed)
1005
+ ExpressionObj Parser::parse_list(bool delayed)
1216
1006
  {
1217
1007
  NESTING_GUARD(nestings);
1218
1008
  return parse_comma_list(delayed);
1219
1009
  }
1220
1010
 
1221
1011
  // will return singletons unwrapped
1222
- Expression_Obj Parser::parse_comma_list(bool delayed)
1012
+ ExpressionObj Parser::parse_comma_list(bool delayed)
1223
1013
  {
1224
1014
  NESTING_GUARD(nestings);
1225
1015
  // check if we have an empty list
@@ -1231,7 +1021,7 @@ namespace Sass {
1231
1021
  }
1232
1022
 
1233
1023
  // now try to parse a space list
1234
- Expression_Obj list = parse_space_list();
1024
+ ExpressionObj list = parse_space_list();
1235
1025
  // if it's a singleton, return it (don't wrap it)
1236
1026
  if (!peek_css< exactly<','> >(position)) {
1237
1027
  // set_delay doesn't apply to list children
@@ -1259,10 +1049,10 @@ namespace Sass {
1259
1049
  // EO parse_comma_list
1260
1050
 
1261
1051
  // will return singletons unwrapped
1262
- Expression_Obj Parser::parse_space_list()
1052
+ ExpressionObj Parser::parse_space_list()
1263
1053
  {
1264
1054
  NESTING_GUARD(nestings);
1265
- Expression_Obj disj1 = parse_disjunction();
1055
+ ExpressionObj disj1 = parse_disjunction();
1266
1056
  // if it's a singleton, return it (don't wrap it)
1267
1057
  if (peek_css< space_list_terminator >(position)
1268
1058
  ) {
@@ -1284,60 +1074,60 @@ namespace Sass {
1284
1074
  // EO parse_space_list
1285
1075
 
1286
1076
  // parse logical OR operation
1287
- Expression_Obj Parser::parse_disjunction()
1077
+ ExpressionObj Parser::parse_disjunction()
1288
1078
  {
1289
1079
  NESTING_GUARD(nestings);
1290
1080
  advanceToNextToken();
1291
- ParserState state(pstate);
1081
+ SourceSpan state(pstate);
1292
1082
  // parse the left hand side conjunction
1293
- Expression_Obj conj = parse_conjunction();
1083
+ ExpressionObj conj = parse_conjunction();
1294
1084
  // parse multiple right hand sides
1295
- std::vector<Expression_Obj> operands;
1085
+ sass::vector<ExpressionObj> operands;
1296
1086
  while (lex_css< kwd_or >())
1297
1087
  operands.push_back(parse_conjunction());
1298
1088
  // if it's a singleton, return it directly
1299
1089
  if (operands.size() == 0) return conj;
1300
1090
  // fold all operands into one binary expression
1301
- Expression_Obj ex = fold_operands(conj, operands, { Sass_OP::OR });
1302
- state.offset = pstate - state + pstate.offset;
1091
+ ExpressionObj ex = fold_operands(conj, operands, { Sass_OP::OR });
1092
+ state.offset = pstate.position - state.position + pstate.offset;
1303
1093
  ex->pstate(state);
1304
1094
  return ex;
1305
1095
  }
1306
1096
  // EO parse_disjunction
1307
1097
 
1308
1098
  // parse logical AND operation
1309
- Expression_Obj Parser::parse_conjunction()
1099
+ ExpressionObj Parser::parse_conjunction()
1310
1100
  {
1311
1101
  NESTING_GUARD(nestings);
1312
1102
  advanceToNextToken();
1313
- ParserState state(pstate);
1103
+ SourceSpan state(pstate);
1314
1104
  // parse the left hand side relation
1315
- Expression_Obj rel = parse_relation();
1105
+ ExpressionObj rel = parse_relation();
1316
1106
  // parse multiple right hand sides
1317
- std::vector<Expression_Obj> operands;
1107
+ sass::vector<ExpressionObj> operands;
1318
1108
  while (lex_css< kwd_and >()) {
1319
1109
  operands.push_back(parse_relation());
1320
1110
  }
1321
1111
  // if it's a singleton, return it directly
1322
1112
  if (operands.size() == 0) return rel;
1323
1113
  // fold all operands into one binary expression
1324
- Expression_Obj ex = fold_operands(rel, operands, { Sass_OP::AND });
1325
- state.offset = pstate - state + pstate.offset;
1114
+ ExpressionObj ex = fold_operands(rel, operands, { Sass_OP::AND });
1115
+ state.offset = pstate.position - state.position + pstate.offset;
1326
1116
  ex->pstate(state);
1327
1117
  return ex;
1328
1118
  }
1329
1119
  // EO parse_conjunction
1330
1120
 
1331
1121
  // parse comparison operations
1332
- Expression_Obj Parser::parse_relation()
1122
+ ExpressionObj Parser::parse_relation()
1333
1123
  {
1334
1124
  NESTING_GUARD(nestings);
1335
1125
  advanceToNextToken();
1336
- ParserState state(pstate);
1126
+ SourceSpan state(pstate);
1337
1127
  // parse the left hand side expression
1338
- Expression_Obj lhs = parse_expression();
1339
- std::vector<Expression_Obj> operands;
1340
- std::vector<Operand> operators;
1128
+ ExpressionObj lhs = parse_expression();
1129
+ sass::vector<ExpressionObj> operands;
1130
+ sass::vector<Operand> operators;
1341
1131
  // if it's a singleton, return it (don't wrap it)
1342
1132
  while (peek< alternatives <
1343
1133
  kwd_eq,
@@ -1370,8 +1160,8 @@ namespace Sass {
1370
1160
  // correctly set to zero. After folding we also unwrap
1371
1161
  // single nested items. So we cannot set delay on the
1372
1162
  // returned result here, as we have lost nestings ...
1373
- Expression_Obj ex = fold_operands(lhs, operands, operators);
1374
- state.offset = pstate - state + pstate.offset;
1163
+ ExpressionObj ex = fold_operands(lhs, operands, operators);
1164
+ state.offset = pstate.position - state.position + pstate.offset;
1375
1165
  ex->pstate(state);
1376
1166
  return ex;
1377
1167
  }
@@ -1382,25 +1172,25 @@ namespace Sass {
1382
1172
  // called from parse_for_directive
1383
1173
  // called from parse_media_expression
1384
1174
  // parse addition and subtraction operations
1385
- Expression_Obj Parser::parse_expression()
1175
+ ExpressionObj Parser::parse_expression()
1386
1176
  {
1387
1177
  NESTING_GUARD(nestings);
1388
1178
  advanceToNextToken();
1389
- ParserState state(pstate);
1179
+ SourceSpan state(pstate);
1390
1180
  // parses multiple add and subtract operations
1391
1181
  // NOTE: make sure that identifiers starting with
1392
1182
  // NOTE: dashes do NOT count as subtract operation
1393
- Expression_Obj lhs = parse_operators();
1183
+ ExpressionObj lhs = parse_operators();
1394
1184
  // if it's a singleton, return it (don't wrap it)
1395
1185
  if (!(peek_css< exactly<'+'> >(position) ||
1396
- // condition is a bit misterious, but some combinations should not be counted as operations
1186
+ // condition is a bit mysterious, but some combinations should not be counted as operations
1397
1187
  (peek< no_spaces >(position) && peek< sequence< negate< unsigned_number >, exactly<'-'>, negate< space > > >(position)) ||
1398
1188
  (peek< sequence< negate< unsigned_number >, exactly<'-'>, negate< unsigned_number > > >(position))) ||
1399
1189
  peek< sequence < zero_plus < exactly <'-' > >, identifier > >(position))
1400
1190
  { return lhs; }
1401
1191
 
1402
- std::vector<Expression_Obj> operands;
1403
- std::vector<Operand> operators;
1192
+ sass::vector<ExpressionObj> operands;
1193
+ sass::vector<Operand> operators;
1404
1194
  bool left_ws = peek < css_comments >() != NULL;
1405
1195
  while (
1406
1196
  lex_css< exactly<'+'> >() ||
@@ -1419,22 +1209,22 @@ namespace Sass {
1419
1209
  }
1420
1210
 
1421
1211
  if (operands.size() == 0) return lhs;
1422
- Expression_Obj ex = fold_operands(lhs, operands, operators);
1423
- state.offset = pstate - state + pstate.offset;
1212
+ ExpressionObj ex = fold_operands(lhs, operands, operators);
1213
+ state.offset = pstate.position - state.position + pstate.offset;
1424
1214
  ex->pstate(state);
1425
1215
  return ex;
1426
1216
  }
1427
1217
 
1428
1218
  // parse addition and subtraction operations
1429
- Expression_Obj Parser::parse_operators()
1219
+ ExpressionObj Parser::parse_operators()
1430
1220
  {
1431
1221
  NESTING_GUARD(nestings);
1432
1222
  advanceToNextToken();
1433
- ParserState state(pstate);
1434
- Expression_Obj factor = parse_factor();
1223
+ SourceSpan state(pstate);
1224
+ ExpressionObj factor = parse_factor();
1435
1225
  // if it's a singleton, return it (don't wrap it)
1436
- std::vector<Expression_Obj> operands; // factors
1437
- std::vector<Operand> operators; // ops
1226
+ sass::vector<ExpressionObj> operands; // factors
1227
+ sass::vector<Operand> operators; // ops
1438
1228
  // lex operations to apply to lhs
1439
1229
  const char* left_ws = peek < css_comments >();
1440
1230
  while (lex_css< class_char< static_ops > >()) {
@@ -1449,8 +1239,8 @@ namespace Sass {
1449
1239
  left_ws = peek < css_comments >();
1450
1240
  }
1451
1241
  // operands and operators to binary expression
1452
- Expression_Obj ex = fold_operands(factor, operands, operators);
1453
- state.offset = pstate - state + pstate.offset;
1242
+ ExpressionObj ex = fold_operands(factor, operands, operators);
1243
+ state.offset = pstate.position - state.position + pstate.offset;
1454
1244
  ex->pstate(state);
1455
1245
  return ex;
1456
1246
  }
@@ -1459,13 +1249,13 @@ namespace Sass {
1459
1249
 
1460
1250
  // called from parse_operators
1461
1251
  // called from parse_value_schema
1462
- Expression_Obj Parser::parse_factor()
1252
+ ExpressionObj Parser::parse_factor()
1463
1253
  {
1464
1254
  NESTING_GUARD(nestings);
1465
1255
  lex < css_comments >(false);
1466
1256
  if (lex_css< exactly<'('> >()) {
1467
1257
  // parse_map may return a list
1468
- Expression_Obj value = parse_map();
1258
+ ExpressionObj value = parse_map();
1469
1259
  // lex the expected closing parenthesis
1470
1260
  if (!lex_css< exactly<')'> >()) error("unclosed parenthesis");
1471
1261
  // expression can be evaluated
@@ -1473,7 +1263,7 @@ namespace Sass {
1473
1263
  }
1474
1264
  else if (lex_css< exactly<'['> >()) {
1475
1265
  // explicit bracketed
1476
- Expression_Obj value = parse_bracket_list();
1266
+ ExpressionObj value = parse_bracket_list();
1477
1267
  // lex the expected closing square bracket
1478
1268
  if (!lex_css< exactly<']'> >()) error("unclosed squared bracket");
1479
1269
  return value;
@@ -1530,19 +1320,12 @@ namespace Sass {
1530
1320
  if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
1531
1321
  return ex;
1532
1322
  }
1533
- // this whole branch is never hit via spec tests
1534
- else if (peek < sequence < one_plus < alternatives < css_whitespace, exactly<'-'>, exactly<'+'> > >, number > >()) {
1535
- if (parse_number_prefix()) return parse_value(); // prefix is positive
1536
- Unary_Expression* ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::MINUS, parse_value());
1537
- if (ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
1538
- return ex;
1539
- }
1540
1323
  else {
1541
1324
  return parse_value();
1542
1325
  }
1543
1326
  }
1544
1327
 
1545
- bool number_has_zero(const std::string& parsed)
1328
+ bool number_has_zero(const sass::string& parsed)
1546
1329
  {
1547
1330
  size_t L = parsed.length();
1548
1331
  return !( (L > 0 && parsed.substr(0, 1) == ".") ||
@@ -1551,7 +1334,7 @@ namespace Sass {
1551
1334
  (L > 2 && parsed.substr(0, 3) == "-0.") );
1552
1335
  }
1553
1336
 
1554
- Number* Parser::lexed_number(const ParserState& pstate, const std::string& parsed)
1337
+ Number* Parser::lexed_number(const SourceSpan& pstate, const sass::string& parsed)
1555
1338
  {
1556
1339
  Number* nr = SASS_MEMORY_NEW(Number,
1557
1340
  pstate,
@@ -1563,7 +1346,7 @@ namespace Sass {
1563
1346
  return nr;
1564
1347
  }
1565
1348
 
1566
- Number* Parser::lexed_percentage(const ParserState& pstate, const std::string& parsed)
1349
+ Number* Parser::lexed_percentage(const SourceSpan& pstate, const sass::string& parsed)
1567
1350
  {
1568
1351
  Number* nr = SASS_MEMORY_NEW(Number,
1569
1352
  pstate,
@@ -1575,17 +1358,17 @@ namespace Sass {
1575
1358
  return nr;
1576
1359
  }
1577
1360
 
1578
- Number* Parser::lexed_dimension(const ParserState& pstate, const std::string& parsed)
1361
+ Number* Parser::lexed_dimension(const SourceSpan& pstate, const sass::string& parsed)
1579
1362
  {
1580
1363
  size_t L = parsed.length();
1581
1364
  size_t num_pos = parsed.find_first_not_of(" \n\r\t");
1582
- if (num_pos == std::string::npos) num_pos = L;
1365
+ if (num_pos == sass::string::npos) num_pos = L;
1583
1366
  size_t unit_pos = parsed.find_first_not_of("-+0123456789.", num_pos);
1584
1367
  if (parsed[unit_pos] == 'e' && is_number(parsed[unit_pos+1]) ) {
1585
1368
  unit_pos = parsed.find_first_not_of("-+0123456789.", ++ unit_pos);
1586
1369
  }
1587
- if (unit_pos == std::string::npos) unit_pos = L;
1588
- const std::string& num = parsed.substr(num_pos, unit_pos - num_pos);
1370
+ if (unit_pos == sass::string::npos) unit_pos = L;
1371
+ const sass::string& num = parsed.substr(num_pos, unit_pos - num_pos);
1589
1372
  Number* nr = SASS_MEMORY_NEW(Number,
1590
1373
  pstate,
1591
1374
  sass_strtod(num.c_str()),
@@ -1596,18 +1379,18 @@ namespace Sass {
1596
1379
  return nr;
1597
1380
  }
1598
1381
 
1599
- Value* Parser::lexed_hex_color(const ParserState& pstate, const std::string& parsed)
1382
+ Value* Parser::lexed_hex_color(const SourceSpan& pstate, const sass::string& parsed)
1600
1383
  {
1601
1384
  Color_RGBA* color = NULL;
1602
1385
  if (parsed[0] != '#') {
1603
1386
  return SASS_MEMORY_NEW(String_Quoted, pstate, parsed);
1604
1387
  }
1605
1388
  // chop off the '#'
1606
- std::string hext(parsed.substr(1));
1389
+ sass::string hext(parsed.substr(1));
1607
1390
  if (parsed.length() == 4) {
1608
- std::string r(2, parsed[1]);
1609
- std::string g(2, parsed[2]);
1610
- std::string b(2, parsed[3]);
1391
+ sass::string r(2, parsed[1]);
1392
+ sass::string g(2, parsed[2]);
1393
+ sass::string b(2, parsed[3]);
1611
1394
  color = SASS_MEMORY_NEW(Color_RGBA,
1612
1395
  pstate,
1613
1396
  static_cast<double>(strtol(r.c_str(), NULL, 16)),
@@ -1617,10 +1400,10 @@ namespace Sass {
1617
1400
  parsed);
1618
1401
  }
1619
1402
  else if (parsed.length() == 5) {
1620
- std::string r(2, parsed[1]);
1621
- std::string g(2, parsed[2]);
1622
- std::string b(2, parsed[3]);
1623
- std::string a(2, parsed[4]);
1403
+ sass::string r(2, parsed[1]);
1404
+ sass::string g(2, parsed[2]);
1405
+ sass::string b(2, parsed[3]);
1406
+ sass::string a(2, parsed[4]);
1624
1407
  color = SASS_MEMORY_NEW(Color_RGBA,
1625
1408
  pstate,
1626
1409
  static_cast<double>(strtol(r.c_str(), NULL, 16)),
@@ -1630,9 +1413,9 @@ namespace Sass {
1630
1413
  parsed);
1631
1414
  }
1632
1415
  else if (parsed.length() == 7) {
1633
- std::string r(parsed.substr(1,2));
1634
- std::string g(parsed.substr(3,2));
1635
- std::string b(parsed.substr(5,2));
1416
+ sass::string r(parsed.substr(1,2));
1417
+ sass::string g(parsed.substr(3,2));
1418
+ sass::string b(parsed.substr(5,2));
1636
1419
  color = SASS_MEMORY_NEW(Color_RGBA,
1637
1420
  pstate,
1638
1421
  static_cast<double>(strtol(r.c_str(), NULL, 16)),
@@ -1642,10 +1425,10 @@ namespace Sass {
1642
1425
  parsed);
1643
1426
  }
1644
1427
  else if (parsed.length() == 9) {
1645
- std::string r(parsed.substr(1,2));
1646
- std::string g(parsed.substr(3,2));
1647
- std::string b(parsed.substr(5,2));
1648
- std::string a(parsed.substr(7,2));
1428
+ sass::string r(parsed.substr(1,2));
1429
+ sass::string g(parsed.substr(3,2));
1430
+ sass::string b(parsed.substr(5,2));
1431
+ sass::string a(parsed.substr(7,2));
1649
1432
  color = SASS_MEMORY_NEW(Color_RGBA,
1650
1433
  pstate,
1651
1434
  static_cast<double>(strtol(r.c_str(), NULL, 16)),
@@ -1659,7 +1442,7 @@ namespace Sass {
1659
1442
  return color;
1660
1443
  }
1661
1444
 
1662
- Value* Parser::color_or_string(const std::string& lexed) const
1445
+ Value* Parser::color_or_string(const sass::string& lexed) const
1663
1446
  {
1664
1447
  if (auto color = name_to_color(lexed)) {
1665
1448
  auto c = SASS_MEMORY_NEW(Color_RGBA, color);
@@ -1673,7 +1456,7 @@ namespace Sass {
1673
1456
  }
1674
1457
 
1675
1458
  // parse one value for a list
1676
- Expression_Obj Parser::parse_value()
1459
+ ExpressionObj Parser::parse_value()
1677
1460
  {
1678
1461
  lex< css_comments >(false);
1679
1462
  if (lex< ampersand >())
@@ -1760,7 +1543,7 @@ namespace Sass {
1760
1543
  find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, chunk.end);
1761
1544
 
1762
1545
  if (!p) {
1763
- String_Quoted* str_quoted = SASS_MEMORY_NEW(String_Quoted, pstate, std::string(i, chunk.end), 0, false, false, true, css);
1546
+ String_Quoted* str_quoted = SASS_MEMORY_NEW(String_Quoted, pstate, sass::string(i, chunk.end), 0, false, false, true, css);
1764
1547
  if (!constant && str_quoted->quote_mark()) str_quoted->quote_mark('*');
1765
1548
  return str_quoted;
1766
1549
  }
@@ -1773,7 +1556,7 @@ namespace Sass {
1773
1556
  if (p) {
1774
1557
  if (i < p) {
1775
1558
  // accumulate the preceding segment if it's nonempty
1776
- schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(i, p), css));
1559
+ schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(i, p), css));
1777
1560
  }
1778
1561
  // we need to skip anything inside strings
1779
1562
  // create a new target in parser/prelexer
@@ -1783,7 +1566,9 @@ namespace Sass {
1783
1566
  const char* j = skip_over_scopes< exactly<hash_lbrace>, exactly<rbrace> >(p + 2, chunk.end); // find the closing brace
1784
1567
  if (j) { --j;
1785
1568
  // parse the interpolant and accumulate it
1786
- Expression_Obj interp_node = Parser::from_token(Token(p+2, j), ctx, traces, pstate, source).parse_list();
1569
+ LocalOption<const char*> partEnd(end, j);
1570
+ LocalOption<const char*> partBeg(position, p + 2);
1571
+ ExpressionObj interp_node = parse_list();
1787
1572
  interp_node->is_interpolant(true);
1788
1573
  schema->append(interp_node);
1789
1574
  i = j;
@@ -1795,7 +1580,7 @@ namespace Sass {
1795
1580
  }
1796
1581
  else { // no interpolants left; add the last segment if nonempty
1797
1582
  // check if we need quotes here (was not sure after merge)
1798
- if (i < chunk.end) schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(i, chunk.end), css));
1583
+ if (i < chunk.end) schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(i, chunk.end), css));
1799
1584
  break;
1800
1585
  }
1801
1586
  ++ i;
@@ -1807,7 +1592,7 @@ namespace Sass {
1807
1592
  String_Schema_Obj Parser::parse_css_variable_value()
1808
1593
  {
1809
1594
  String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
1810
- std::vector<char> brackets;
1595
+ sass::vector<char> brackets;
1811
1596
  while (true) {
1812
1597
  if (
1813
1598
  (brackets.empty() && lex< css_variable_top_level_value >(false)) ||
@@ -1815,7 +1600,7 @@ namespace Sass {
1815
1600
  ) {
1816
1601
  Token str(lexed);
1817
1602
  schema->append(SASS_MEMORY_NEW(String_Constant, pstate, str));
1818
- } else if (Expression_Obj tok = lex_interpolation()) {
1603
+ } else if (ExpressionObj tok = lex_interpolation()) {
1819
1604
  if (String_Schema* s = Cast<String_Schema>(tok)) {
1820
1605
  if (s->empty()) break;
1821
1606
  schema->concat(s);
@@ -1823,7 +1608,7 @@ namespace Sass {
1823
1608
  schema->append(tok);
1824
1609
  }
1825
1610
  } else if (lex< quoted_string >()) {
1826
- Expression_Obj tok = parse_string();
1611
+ ExpressionObj tok = parse_string();
1827
1612
  if (tok.isNull()) break;
1828
1613
  if (String_Schema* s = Cast<String_Schema>(tok)) {
1829
1614
  if (s->empty()) break;
@@ -1834,18 +1619,18 @@ namespace Sass {
1834
1619
  } else if (lex< alternatives< exactly<'('>, exactly<'['>, exactly<'{'> > >()) {
1835
1620
  const char opening_bracket = *(position - 1);
1836
1621
  brackets.push_back(opening_bracket);
1837
- schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(1, opening_bracket)));
1622
+ schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(1, opening_bracket)));
1838
1623
  } else if (const char *match = peek< alternatives< exactly<')'>, exactly<']'>, exactly<'}'> > >()) {
1839
1624
  if (brackets.empty()) break;
1840
1625
  const char closing_bracket = *(match - 1);
1841
1626
  if (brackets.back() != Util::opening_bracket_for(closing_bracket)) {
1842
- std::string message = ": expected \"";
1627
+ sass::string message = ": expected \"";
1843
1628
  message += Util::closing_bracket_for(brackets.back());
1844
1629
  message += "\", was ";
1845
1630
  css_error("Invalid CSS", " after ", message);
1846
1631
  }
1847
1632
  lex< alternatives< exactly<')'>, exactly<']'>, exactly<'}'> > >();
1848
- schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(1, closing_bracket)));
1633
+ schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(1, closing_bracket)));
1849
1634
  brackets.pop_back();
1850
1635
  } else {
1851
1636
  break;
@@ -1853,7 +1638,7 @@ namespace Sass {
1853
1638
  }
1854
1639
 
1855
1640
  if (!brackets.empty()) {
1856
- std::string message = ": expected \"";
1641
+ sass::string message = ": expected \"";
1857
1642
  message += Util::closing_bracket_for(brackets.back());
1858
1643
  message += "\", was ";
1859
1644
  css_error("Invalid CSS", " after ", message);
@@ -1863,7 +1648,7 @@ namespace Sass {
1863
1648
  return schema.detach();
1864
1649
  }
1865
1650
 
1866
- Value_Obj Parser::parse_static_value()
1651
+ ValueObj Parser::parse_static_value()
1867
1652
  {
1868
1653
  lex< static_value >();
1869
1654
  Token str(lexed);
@@ -1890,7 +1675,7 @@ namespace Sass {
1890
1675
  // see if there any interpolants
1891
1676
  const char* p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(str.begin, str.end);
1892
1677
  if (!p) {
1893
- return SASS_MEMORY_NEW(String_Quoted, pstate, std::string(str.begin, str.end));
1678
+ return SASS_MEMORY_NEW(String_Quoted, pstate, sass::string(str.begin, str.end));
1894
1679
  }
1895
1680
 
1896
1681
  String_Schema* schema = SASS_MEMORY_NEW(String_Schema, pstate);
@@ -1898,7 +1683,7 @@ namespace Sass {
1898
1683
  p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, str.end);
1899
1684
  if (p) {
1900
1685
  if (i < p) {
1901
- schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(i, p))); // accumulate the preceding segment if it's nonempty
1686
+ schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(i, p))); // accumulate the preceding segment if it's nonempty
1902
1687
  }
1903
1688
  if (peek < sequence < optional_spaces, exactly<rbrace> > >(p+2)) { position = p+2;
1904
1689
  css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
@@ -1906,7 +1691,9 @@ namespace Sass {
1906
1691
  const char* j = skip_over_scopes< exactly<hash_lbrace>, exactly<rbrace> >(p+2, str.end); // find the closing brace
1907
1692
  if (j) {
1908
1693
  // parse the interpolant and accumulate it
1909
- Expression_Obj interp_node = Parser::from_token(Token(p+2, j), ctx, traces, pstate, source).parse_list();
1694
+ LocalOption<const char*> partEnd(end, j);
1695
+ LocalOption<const char*> partBeg(position, p + 2);
1696
+ ExpressionObj interp_node = parse_list();
1910
1697
  interp_node->is_interpolant(true);
1911
1698
  schema->append(interp_node);
1912
1699
  i = j;
@@ -1918,7 +1705,7 @@ namespace Sass {
1918
1705
  }
1919
1706
  else { // no interpolants left; add the last segment if nonempty
1920
1707
  if (i < str.end) {
1921
- schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(i, str.end)));
1708
+ schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(i, str.end)));
1922
1709
  }
1923
1710
  break;
1924
1711
  }
@@ -1939,7 +1726,7 @@ namespace Sass {
1939
1726
  kwd_arg->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
1940
1727
  if (peek< variable >()) kwd_arg->append(parse_list());
1941
1728
  else if (lex< number >()) {
1942
- std::string parsed(lexed);
1729
+ sass::string parsed(lexed);
1943
1730
  Util::normalize_decimals(parsed);
1944
1731
  kwd_arg->append(lexed_number(parsed));
1945
1732
  }
@@ -1979,7 +1766,7 @@ namespace Sass {
1979
1766
  if (peek< exactly< rbrace > >()) {
1980
1767
  css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
1981
1768
  }
1982
- Expression_Obj ex;
1769
+ ExpressionObj ex;
1983
1770
  if (lex< re_static_expression >()) {
1984
1771
  ex = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
1985
1772
  } else {
@@ -2015,7 +1802,7 @@ namespace Sass {
2015
1802
  }
2016
1803
  // lex (normalized) variable
2017
1804
  else if (lex< variable >()) {
2018
- std::string name(Util::normalize_underscores(lexed));
1805
+ sass::string name(Util::normalize_underscores(lexed));
2019
1806
  schema->append(SASS_MEMORY_NEW(Variable, pstate, name));
2020
1807
  }
2021
1808
  // lex percentage value
@@ -2047,7 +1834,7 @@ namespace Sass {
2047
1834
  ++num_items;
2048
1835
  }
2049
1836
  if (position != stop) {
2050
- schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(position, stop)));
1837
+ schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(position, stop)));
2051
1838
  position = stop;
2052
1839
  }
2053
1840
  end = ee;
@@ -2063,7 +1850,7 @@ namespace Sass {
2063
1850
  // see if there any interpolants
2064
1851
  const char* p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(id.begin, id.end);
2065
1852
  if (!p) {
2066
- return SASS_MEMORY_NEW(String_Constant, pstate, std::string(id.begin, id.end));
1853
+ return SASS_MEMORY_NEW(String_Constant, pstate, sass::string(id.begin, id.end));
2067
1854
  }
2068
1855
 
2069
1856
  String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
@@ -2084,7 +1871,9 @@ namespace Sass {
2084
1871
  const char* j = skip_over_scopes< exactly<hash_lbrace>, exactly<rbrace> >(p+2, id.end); // find the closing brace
2085
1872
  if (j) {
2086
1873
  // parse the interpolant and accumulate it
2087
- Expression_Obj interp_node = Parser::from_token(Token(p+2, j), ctx, traces, pstate, source).parse_list(DELAYED);
1874
+ LocalOption<const char*> partEnd(end, j);
1875
+ LocalOption<const char*> partBeg(position, p + 2);
1876
+ ExpressionObj interp_node = parse_list(DELAYED);
2088
1877
  interp_node->is_interpolant(true);
2089
1878
  schema->append(interp_node);
2090
1879
  // schema->has_interpolants(true);
@@ -2111,10 +1900,10 @@ namespace Sass {
2111
1900
  Function_Call_Obj Parser::parse_calc_function()
2112
1901
  {
2113
1902
  lex< identifier >();
2114
- std::string name(lexed);
2115
- ParserState call_pos = pstate;
1903
+ sass::string name(lexed);
1904
+ SourceSpan call_pos = pstate;
2116
1905
  lex< exactly<'('> >();
2117
- ParserState arg_pos = pstate;
1906
+ SourceSpan arg_pos = pstate;
2118
1907
  const char* arg_beg = position;
2119
1908
  parse_list();
2120
1909
  const char* arg_end = position;
@@ -2131,20 +1920,20 @@ namespace Sass {
2131
1920
 
2132
1921
  String_Obj Parser::parse_url_function_string()
2133
1922
  {
2134
- std::string prefix("");
1923
+ sass::string prefix("");
2135
1924
  if (lex< uri_prefix >()) {
2136
- prefix = std::string(lexed);
1925
+ prefix = sass::string(lexed);
2137
1926
  }
2138
1927
 
2139
1928
  lex < optional_spaces >();
2140
1929
  String_Obj url_string = parse_url_function_argument();
2141
1930
 
2142
- std::string suffix("");
1931
+ sass::string suffix("");
2143
1932
  if (lex< real_uri_suffix >()) {
2144
- suffix = std::string(lexed);
1933
+ suffix = sass::string(lexed);
2145
1934
  }
2146
1935
 
2147
- std::string uri("");
1936
+ sass::string uri("");
2148
1937
  if (url_string) {
2149
1938
  uri = url_string->to_string({ NESTED, 5 });
2150
1939
  }
@@ -2156,7 +1945,7 @@ namespace Sass {
2156
1945
  res->append(SASS_MEMORY_NEW(String_Constant, pstate, suffix));
2157
1946
  return res;
2158
1947
  } else {
2159
- std::string res = prefix + uri + suffix;
1948
+ sass::string res = prefix + uri + suffix;
2160
1949
  return SASS_MEMORY_NEW(String_Constant, pstate, res);
2161
1950
  }
2162
1951
  }
@@ -2165,7 +1954,7 @@ namespace Sass {
2165
1954
  {
2166
1955
  const char* p = position;
2167
1956
 
2168
- std::string uri("");
1957
+ sass::string uri("");
2169
1958
  if (lex< real_uri_value >(false)) {
2170
1959
  uri = lexed.to_string();
2171
1960
  }
@@ -2181,7 +1970,7 @@ namespace Sass {
2181
1970
  return parse_interpolated_chunk(Token(p, position));
2182
1971
  }
2183
1972
  else if (uri != "") {
2184
- std::string res = Util::rtrim(uri);
1973
+ sass::string res = Util::rtrim(uri);
2185
1974
  return SASS_MEMORY_NEW(String_Constant, pstate, res);
2186
1975
  }
2187
1976
 
@@ -2191,12 +1980,12 @@ namespace Sass {
2191
1980
  Function_Call_Obj Parser::parse_function_call()
2192
1981
  {
2193
1982
  lex< identifier >();
2194
- std::string name(lexed);
1983
+ sass::string name(lexed);
2195
1984
 
2196
1985
  if (Util::normalize_underscores(name) == "content-exists" && stack.back() != Scope::Mixin)
2197
1986
  { error("Cannot call content-exists() except within a mixin."); }
2198
1987
 
2199
- ParserState call_pos = pstate;
1988
+ SourceSpan call_pos = pstate;
2200
1989
  Arguments_Obj args = parse_arguments();
2201
1990
  return SASS_MEMORY_NEW(Function_Call, call_pos, name, args);
2202
1991
  }
@@ -2204,7 +1993,7 @@ namespace Sass {
2204
1993
  Function_Call_Obj Parser::parse_function_call_schema()
2205
1994
  {
2206
1995
  String_Obj name = parse_identifier_schema();
2207
- ParserState source_position_of_call = pstate;
1996
+ SourceSpan source_position_of_call = pstate;
2208
1997
  Arguments_Obj args = parse_arguments();
2209
1998
 
2210
1999
  return SASS_MEMORY_NEW(Function_Call, source_position_of_call, name, args);
@@ -2212,7 +2001,7 @@ namespace Sass {
2212
2001
 
2213
2002
  Content_Obj Parser::parse_content_directive()
2214
2003
  {
2215
- ParserState call_pos = pstate;
2004
+ SourceSpan call_pos = pstate;
2216
2005
  Arguments_Obj args = parse_arguments();
2217
2006
 
2218
2007
  return SASS_MEMORY_NEW(Content, call_pos, args);
@@ -2221,9 +2010,9 @@ namespace Sass {
2221
2010
  If_Obj Parser::parse_if_directive(bool else_if)
2222
2011
  {
2223
2012
  stack.push_back(Scope::Control);
2224
- ParserState if_source_position = pstate;
2013
+ SourceSpan if_source_position = pstate;
2225
2014
  bool root = block_stack.back()->is_root();
2226
- Expression_Obj predicate = parse_list();
2015
+ ExpressionObj predicate = parse_list();
2227
2016
  Block_Obj block = parse_block(root);
2228
2017
  Block_Obj alternative;
2229
2018
 
@@ -2240,23 +2029,23 @@ namespace Sass {
2240
2029
  return SASS_MEMORY_NEW(If, if_source_position, predicate, block, alternative);
2241
2030
  }
2242
2031
 
2243
- For_Obj Parser::parse_for_directive()
2032
+ ForRuleObj Parser::parse_for_directive()
2244
2033
  {
2245
2034
  stack.push_back(Scope::Control);
2246
- ParserState for_source_position = pstate;
2035
+ SourceSpan for_source_position = pstate;
2247
2036
  bool root = block_stack.back()->is_root();
2248
2037
  lex_variable();
2249
- std::string var(Util::normalize_underscores(lexed));
2038
+ sass::string var(Util::normalize_underscores(lexed));
2250
2039
  if (!lex< kwd_from >()) error("expected 'from' keyword in @for directive");
2251
- Expression_Obj lower_bound = parse_expression();
2040
+ ExpressionObj lower_bound = parse_expression();
2252
2041
  bool inclusive = false;
2253
2042
  if (lex< kwd_through >()) inclusive = true;
2254
2043
  else if (lex< kwd_to >()) inclusive = false;
2255
2044
  else error("expected 'through' or 'to' keyword in @for directive");
2256
- Expression_Obj upper_bound = parse_expression();
2045
+ ExpressionObj upper_bound = parse_expression();
2257
2046
  Block_Obj body = parse_block(root);
2258
2047
  stack.pop_back();
2259
- return SASS_MEMORY_NEW(For, for_source_position, var, lower_bound, upper_bound, body, inclusive);
2048
+ return SASS_MEMORY_NEW(ForRule, for_source_position, var, lower_bound, upper_bound, body, inclusive);
2260
2049
  }
2261
2050
 
2262
2051
  // helper to parse a var token
@@ -2272,7 +2061,7 @@ namespace Sass {
2272
2061
  css_error("Invalid CSS", " after ", ": expected identifier, was ");
2273
2062
  }
2274
2063
  // return object
2275
- return token;
2064
+ return lexed;
2276
2065
  }
2277
2066
  // helper to parse identifier
2278
2067
  Token Parser::lex_identifier()
@@ -2282,15 +2071,15 @@ namespace Sass {
2282
2071
  css_error("Invalid CSS", " after ", ": expected identifier, was ");
2283
2072
  }
2284
2073
  // return object
2285
- return token;
2074
+ return lexed;
2286
2075
  }
2287
2076
 
2288
- Each_Obj Parser::parse_each_directive()
2077
+ EachRuleObj Parser::parse_each_directive()
2289
2078
  {
2290
2079
  stack.push_back(Scope::Control);
2291
- ParserState each_source_position = pstate;
2080
+ SourceSpan each_source_position = pstate;
2292
2081
  bool root = block_stack.back()->is_root();
2293
- std::vector<std::string> vars;
2082
+ sass::vector<sass::string> vars;
2294
2083
  lex_variable();
2295
2084
  vars.push_back(Util::normalize_underscores(lexed));
2296
2085
  while (lex< exactly<','> >()) {
@@ -2298,21 +2087,21 @@ namespace Sass {
2298
2087
  vars.push_back(Util::normalize_underscores(lexed));
2299
2088
  }
2300
2089
  if (!lex< kwd_in >()) error("expected 'in' keyword in @each directive");
2301
- Expression_Obj list = parse_list();
2090
+ ExpressionObj list = parse_list();
2302
2091
  Block_Obj body = parse_block(root);
2303
2092
  stack.pop_back();
2304
- return SASS_MEMORY_NEW(Each, each_source_position, vars, list, body);
2093
+ return SASS_MEMORY_NEW(EachRule, each_source_position, vars, list, body);
2305
2094
  }
2306
2095
 
2307
2096
  // called after parsing `kwd_while_directive`
2308
- While_Obj Parser::parse_while_directive()
2097
+ WhileRuleObj Parser::parse_while_directive()
2309
2098
  {
2310
2099
  stack.push_back(Scope::Control);
2311
2100
  bool root = block_stack.back()->is_root();
2312
2101
  // create the initial while call object
2313
- While_Obj call = SASS_MEMORY_NEW(While, pstate, {}, {});
2102
+ WhileRuleObj call = SASS_MEMORY_NEW(WhileRule, pstate, ExpressionObj{}, Block_Obj{});
2314
2103
  // parse mandatory predicate
2315
- Expression_Obj predicate = parse_list();
2104
+ ExpressionObj predicate = parse_list();
2316
2105
  List_Obj l = Cast<List>(predicate);
2317
2106
  if (!predicate || (l && !l->length())) {
2318
2107
  css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ", false);
@@ -2326,20 +2115,107 @@ namespace Sass {
2326
2115
  return call.detach();
2327
2116
  }
2328
2117
 
2329
- // EO parse_while_directive
2330
- Media_Block_Obj Parser::parse_media_block()
2118
+
2119
+ sass::vector<CssMediaQuery_Obj> Parser::parseCssMediaQueries()
2331
2120
  {
2332
- stack.push_back(Scope::Media);
2333
- Media_Block_Obj media_block = SASS_MEMORY_NEW(Media_Block, pstate, {}, {});
2121
+ sass::vector<CssMediaQuery_Obj> result;
2122
+ do {
2123
+ if (auto query = parseCssMediaQuery()) {
2124
+ result.push_back(query);
2125
+ }
2126
+ } while (lex<exactly<','>>());
2127
+ return result;
2128
+ }
2129
+
2130
+ sass::string Parser::parseIdentifier()
2131
+ {
2132
+ if (lex < identifier >(false)) {
2133
+ return sass::string(lexed);
2134
+ }
2135
+ return sass::string();
2136
+ }
2137
+
2138
+ CssMediaQuery_Obj Parser::parseCssMediaQuery()
2139
+ {
2140
+ CssMediaQuery_Obj result = SASS_MEMORY_NEW(CssMediaQuery, pstate);
2141
+ lex<css_comments>(false);
2142
+
2143
+ // Check if any tokens are to parse
2144
+ if (!peek_css<exactly<'('>>()) {
2145
+
2146
+ sass::string token1(parseIdentifier());
2147
+ lex<css_comments>(false);
2148
+
2149
+ if (token1.empty()) {
2150
+ return {};
2151
+ }
2152
+
2153
+ sass::string token2(parseIdentifier());
2154
+ lex<css_comments>(false);
2155
+
2156
+ if (Util::equalsLiteral("and", token2)) {
2157
+ result->type(token1);
2158
+ }
2159
+ else {
2160
+ if (token2.empty()) {
2161
+ result->type(token1);
2162
+ }
2163
+ else {
2164
+ result->modifier(token1);
2165
+ result->type(token2);
2166
+ }
2167
+
2168
+ if (lex < kwd_and >()) {
2169
+ lex<css_comments>(false);
2170
+ }
2171
+ else {
2172
+ return result;
2173
+ }
2174
+
2175
+ }
2176
+
2177
+ }
2178
+
2179
+ sass::vector<sass::string> queries;
2180
+
2181
+ do {
2182
+ lex<css_comments>(false);
2183
+
2184
+ if (lex<exactly<'('>>()) {
2185
+ // In dart sass parser returns a pure string
2186
+ if (lex < skip_over_scopes < exactly < '(' >, exactly < ')' > > >()) {
2187
+ sass::string decl("(" + sass::string(lexed));
2188
+ queries.push_back(decl);
2189
+ }
2190
+ // Should be: parseDeclarationValue;
2191
+ if (!lex<exactly<')'>>()) {
2192
+ // Should we throw an error here?
2193
+ }
2194
+ }
2195
+ } while (lex < kwd_and >());
2196
+
2197
+ result->features(queries);
2198
+
2199
+ if (result->features().empty()) {
2200
+ if (result->type().empty()) {
2201
+ return {};
2202
+ }
2203
+ }
2204
+
2205
+ return result;
2206
+ }
2334
2207
 
2335
- media_block->media_queries(parse_media_queries());
2336
2208
 
2337
- Media_Block_Obj prev_media_block = last_media_block;
2338
- last_media_block = media_block;
2339
- media_block->block(parse_css_block());
2340
- last_media_block = prev_media_block;
2209
+ // EO parse_while_directive
2210
+ MediaRule_Obj Parser::parseMediaRule()
2211
+ {
2212
+ MediaRule_Obj rule = SASS_MEMORY_NEW(MediaRule, pstate);
2213
+ stack.push_back(Scope::Media);
2214
+ rule->schema(parse_media_queries());
2215
+ parse_block_comments(false);
2216
+ rule->block(parse_css_block());
2341
2217
  stack.pop_back();
2342
- return media_block.detach();
2218
+ return rule;
2343
2219
  }
2344
2220
 
2345
2221
  List_Obj Parser::parse_media_queries()
@@ -2360,15 +2236,17 @@ namespace Sass {
2360
2236
  if (lex < kwd_not >()) { media_query->is_negated(true); lex < css_comments >(false); }
2361
2237
  else if (lex < kwd_only >()) { media_query->is_restricted(true); lex < css_comments >(false); }
2362
2238
 
2363
- if (lex < identifier_schema >()) media_query->media_type(parse_identifier_schema());
2364
- else if (lex < identifier >()) media_query->media_type(parse_interpolated_chunk(lexed));
2239
+ if (lex < identifier_schema >()) media_query->media_type(parse_identifier_schema());
2240
+ else if (lex < identifier >()) media_query->media_type(parse_interpolated_chunk(lexed));
2365
2241
  else media_query->append(parse_media_expression());
2366
2242
 
2367
2243
  while (lex_css < kwd_and >()) media_query->append(parse_media_expression());
2368
2244
  if (lex < identifier_schema >()) {
2369
- String_Schema* schema = SASS_MEMORY_NEW(String_Schema, pstate);
2370
- schema->append(media_query->media_type());
2371
- schema->append(SASS_MEMORY_NEW(String_Constant, pstate, " "));
2245
+ String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
2246
+ if (media_query->media_type()) {
2247
+ schema->append(media_query->media_type());
2248
+ schema->append(SASS_MEMORY_NEW(String_Constant, pstate, " "));
2249
+ }
2372
2250
  schema->append(parse_identifier_schema());
2373
2251
  media_query->media_type(schema);
2374
2252
  }
@@ -2379,21 +2257,21 @@ namespace Sass {
2379
2257
  return media_query;
2380
2258
  }
2381
2259
 
2382
- Media_Query_Expression_Obj Parser::parse_media_expression()
2260
+ Media_Query_ExpressionObj Parser::parse_media_expression()
2383
2261
  {
2384
2262
  if (lex < identifier_schema >()) {
2385
2263
  String_Obj ss = parse_identifier_schema();
2386
- return SASS_MEMORY_NEW(Media_Query_Expression, pstate, ss, {}, true);
2264
+ return SASS_MEMORY_NEW(Media_Query_Expression, pstate, ss, ExpressionObj{}, true);
2387
2265
  }
2388
2266
  if (!lex_css< exactly<'('> >()) {
2389
2267
  error("media query expression must begin with '('");
2390
2268
  }
2391
- Expression_Obj feature;
2269
+ ExpressionObj feature;
2392
2270
  if (peek_css< exactly<')'> >()) {
2393
2271
  error("media feature required in media query expression");
2394
2272
  }
2395
2273
  feature = parse_expression();
2396
- Expression_Obj expression;
2274
+ ExpressionObj expression;
2397
2275
  if (lex_css< exactly<':'> >()) {
2398
2276
  expression = parse_list(DELAYED);
2399
2277
  }
@@ -2405,11 +2283,11 @@ namespace Sass {
2405
2283
 
2406
2284
  // lexed after `kwd_supports_directive`
2407
2285
  // these are very similar to media blocks
2408
- Supports_Block_Obj Parser::parse_supports_directive()
2286
+ SupportsRuleObj Parser::parse_supports_directive()
2409
2287
  {
2410
- Supports_Condition_Obj cond = parse_supports_condition(/*top_level=*/true);
2288
+ SupportsConditionObj cond = parse_supports_condition(/*top_level=*/true);
2411
2289
  // create the ast node object for the support queries
2412
- Supports_Block_Obj query = SASS_MEMORY_NEW(Supports_Block, pstate, cond);
2290
+ SupportsRuleObj query = SASS_MEMORY_NEW(SupportsRule, pstate, cond);
2413
2291
  // additional block is mandatory
2414
2292
  // parse inner block
2415
2293
  query->block(parse_block());
@@ -2419,43 +2297,43 @@ namespace Sass {
2419
2297
 
2420
2298
  // parse one query operation
2421
2299
  // may encounter nested queries
2422
- Supports_Condition_Obj Parser::parse_supports_condition(bool top_level)
2300
+ SupportsConditionObj Parser::parse_supports_condition(bool top_level)
2423
2301
  {
2424
2302
  lex < css_whitespace >();
2425
- Supports_Condition_Obj cond;
2303
+ SupportsConditionObj cond;
2426
2304
  if ((cond = parse_supports_negation())) return cond;
2427
2305
  if ((cond = parse_supports_operator(top_level))) return cond;
2428
2306
  if ((cond = parse_supports_interpolation())) return cond;
2429
2307
  return cond;
2430
2308
  }
2431
2309
 
2432
- Supports_Condition_Obj Parser::parse_supports_negation()
2310
+ SupportsConditionObj Parser::parse_supports_negation()
2433
2311
  {
2434
2312
  if (!lex < kwd_not >()) return {};
2435
- Supports_Condition_Obj cond = parse_supports_condition_in_parens(/*parens_required=*/true);
2436
- return SASS_MEMORY_NEW(Supports_Negation, pstate, cond);
2313
+ SupportsConditionObj cond = parse_supports_condition_in_parens(/*parens_required=*/true);
2314
+ return SASS_MEMORY_NEW(SupportsNegation, pstate, cond);
2437
2315
  }
2438
2316
 
2439
- Supports_Condition_Obj Parser::parse_supports_operator(bool top_level)
2317
+ SupportsConditionObj Parser::parse_supports_operator(bool top_level)
2440
2318
  {
2441
- Supports_Condition_Obj cond = parse_supports_condition_in_parens(/*parens_required=*/top_level);
2319
+ SupportsConditionObj cond = parse_supports_condition_in_parens(/*parens_required=*/top_level);
2442
2320
  if (cond.isNull()) return {};
2443
2321
 
2444
2322
  while (true) {
2445
- Supports_Operator::Operand op = Supports_Operator::OR;
2446
- if (lex < kwd_and >()) { op = Supports_Operator::AND; }
2323
+ SupportsOperation::Operand op = SupportsOperation::OR;
2324
+ if (lex < kwd_and >()) { op = SupportsOperation::AND; }
2447
2325
  else if(!lex < kwd_or >()) { break; }
2448
2326
 
2449
2327
  lex < css_whitespace >();
2450
- Supports_Condition_Obj right = parse_supports_condition_in_parens(/*parens_required=*/true);
2328
+ SupportsConditionObj right = parse_supports_condition_in_parens(/*parens_required=*/true);
2451
2329
 
2452
- // Supports_Condition* cc = SASS_MEMORY_NEW(Supports_Condition, *static_cast<Supports_Condition*>(cond));
2453
- cond = SASS_MEMORY_NEW(Supports_Operator, pstate, cond, right, op);
2330
+ // SupportsCondition* cc = SASS_MEMORY_NEW(SupportsCondition, *static_cast<SupportsCondition*>(cond));
2331
+ cond = SASS_MEMORY_NEW(SupportsOperation, pstate, cond, right, op);
2454
2332
  }
2455
2333
  return cond;
2456
2334
  }
2457
2335
 
2458
- Supports_Condition_Obj Parser::parse_supports_interpolation()
2336
+ SupportsConditionObj Parser::parse_supports_interpolation()
2459
2337
  {
2460
2338
  if (!lex < interpolant >()) return {};
2461
2339
 
@@ -2467,17 +2345,17 @@ namespace Sass {
2467
2345
 
2468
2346
  // TODO: This needs some major work. Although feature conditions
2469
2347
  // look like declarations their semantics differ significantly
2470
- Supports_Condition_Obj Parser::parse_supports_declaration()
2348
+ SupportsConditionObj Parser::parse_supports_declaration()
2471
2349
  {
2472
- Supports_Condition* cond;
2350
+ SupportsCondition* cond;
2473
2351
  // parse something declaration like
2474
- Expression_Obj feature = parse_expression();
2475
- Expression_Obj expression;
2352
+ ExpressionObj feature = parse_expression();
2353
+ ExpressionObj expression;
2476
2354
  if (lex_css< exactly<':'> >()) {
2477
2355
  expression = parse_list(DELAYED);
2478
2356
  }
2479
2357
  if (!feature || !expression) error("@supports condition expected declaration");
2480
- cond = SASS_MEMORY_NEW(Supports_Declaration,
2358
+ cond = SASS_MEMORY_NEW(SupportsDeclaration,
2481
2359
  feature->pstate(),
2482
2360
  feature,
2483
2361
  expression);
@@ -2485,9 +2363,9 @@ namespace Sass {
2485
2363
  return cond;
2486
2364
  }
2487
2365
 
2488
- Supports_Condition_Obj Parser::parse_supports_condition_in_parens(bool parens_required)
2366
+ SupportsConditionObj Parser::parse_supports_condition_in_parens(bool parens_required)
2489
2367
  {
2490
- Supports_Condition_Obj interp = parse_supports_interpolation();
2368
+ SupportsConditionObj interp = parse_supports_interpolation();
2491
2369
  if (interp != nullptr) return interp;
2492
2370
 
2493
2371
  if (!lex < exactly <'('> >()) {
@@ -2499,7 +2377,7 @@ namespace Sass {
2499
2377
  }
2500
2378
  lex < css_whitespace >();
2501
2379
 
2502
- Supports_Condition_Obj cond = parse_supports_condition(/*top_level=*/false);
2380
+ SupportsConditionObj cond = parse_supports_condition(/*top_level=*/false);
2503
2381
  if (cond.isNull()) cond = parse_supports_declaration();
2504
2382
  if (!lex < exactly <')'> >()) error("unclosed parenthesis in @supports declaration");
2505
2383
 
@@ -2507,10 +2385,10 @@ namespace Sass {
2507
2385
  return cond;
2508
2386
  }
2509
2387
 
2510
- At_Root_Block_Obj Parser::parse_at_root_block()
2388
+ AtRootRuleObj Parser::parse_at_root_block()
2511
2389
  {
2512
2390
  stack.push_back(Scope::AtRoot);
2513
- ParserState at_source_position = pstate;
2391
+ SourceSpan at_source_position = pstate;
2514
2392
  Block_Obj body;
2515
2393
  At_Root_Query_Obj expr;
2516
2394
  Lookahead lookahead_result;
@@ -2522,11 +2400,11 @@ namespace Sass {
2522
2400
  body = parse_block(true);
2523
2401
  }
2524
2402
  else if ((lookahead_result = lookahead_for_selector(position)).found) {
2525
- Ruleset_Obj r = parse_ruleset(lookahead_result);
2403
+ StyleRuleObj r = parse_ruleset(lookahead_result);
2526
2404
  body = SASS_MEMORY_NEW(Block, r->pstate(), 1, true);
2527
2405
  body->append(r);
2528
2406
  }
2529
- At_Root_Block_Obj at_root = SASS_MEMORY_NEW(At_Root_Block, at_source_position, body);
2407
+ AtRootRuleObj at_root = SASS_MEMORY_NEW(AtRootRule, at_source_position, body);
2530
2408
  if (!expr.isNull()) at_root->expression(expr);
2531
2409
  stack.pop_back();
2532
2410
  return at_root;
@@ -2540,9 +2418,9 @@ namespace Sass {
2540
2418
  css_error("Invalid CSS", " after ", ": expected \"with\" or \"without\", was ");
2541
2419
  }
2542
2420
 
2543
- Expression_Obj feature = parse_list();
2421
+ ExpressionObj feature = parse_list();
2544
2422
  if (!lex_css< exactly<':'> >()) error("style declaration must contain a value");
2545
- Expression_Obj expression = parse_list();
2423
+ ExpressionObj expression = parse_list();
2546
2424
  List_Obj value = SASS_MEMORY_NEW(List, feature->pstate(), 1);
2547
2425
 
2548
2426
  if (expression->concrete_type() == Expression::LIST) {
@@ -2558,71 +2436,9 @@ namespace Sass {
2558
2436
  return cond;
2559
2437
  }
2560
2438
 
2561
- Directive_Obj Parser::parse_special_directive()
2562
- {
2563
- std::string kwd(lexed);
2564
-
2565
- if (lexed == "@else") error("Invalid CSS: @else must come after @if");
2566
-
2567
- // this whole branch is never hit via spec tests
2568
-
2569
- Directive* at_rule = SASS_MEMORY_NEW(Directive, pstate, kwd);
2570
- Lookahead lookahead = lookahead_for_include(position);
2571
- if (lookahead.found && !lookahead.has_interpolants) {
2572
- at_rule->selector(parse_selector_list(false));
2573
- }
2574
-
2575
- lex < css_comments >(false);
2576
-
2577
- if (lex < static_property >()) {
2578
- at_rule->value(parse_interpolated_chunk(Token(lexed)));
2579
- } else if (!(peek < alternatives < exactly<'{'>, exactly<'}'>, exactly<';'> > >())) {
2580
- at_rule->value(parse_list());
2581
- }
2582
-
2583
- lex < css_comments >(false);
2584
-
2585
- if (peek< exactly<'{'> >()) {
2586
- at_rule->block(parse_block());
2587
- }
2588
-
2589
- return at_rule;
2590
- }
2591
-
2592
- // this whole branch is never hit via spec tests
2593
- Directive_Obj Parser::parse_prefixed_directive()
2439
+ AtRuleObj Parser::parse_directive()
2594
2440
  {
2595
- std::string kwd(lexed);
2596
-
2597
- if (lexed == "@else") error("Invalid CSS: @else must come after @if");
2598
-
2599
- Directive_Obj at_rule = SASS_MEMORY_NEW(Directive, pstate, kwd);
2600
- Lookahead lookahead = lookahead_for_include(position);
2601
- if (lookahead.found && !lookahead.has_interpolants) {
2602
- at_rule->selector(parse_selector_list(false));
2603
- }
2604
-
2605
- lex < css_comments >(false);
2606
-
2607
- if (lex < static_property >()) {
2608
- at_rule->value(parse_interpolated_chunk(Token(lexed)));
2609
- } else if (!(peek < alternatives < exactly<'{'>, exactly<'}'>, exactly<';'> > >())) {
2610
- at_rule->value(parse_list());
2611
- }
2612
-
2613
- lex < css_comments >(false);
2614
-
2615
- if (peek< exactly<'{'> >()) {
2616
- at_rule->block(parse_block());
2617
- }
2618
-
2619
- return at_rule;
2620
- }
2621
-
2622
-
2623
- Directive_Obj Parser::parse_directive()
2624
- {
2625
- Directive_Obj directive = SASS_MEMORY_NEW(Directive, pstate, lexed);
2441
+ AtRuleObj directive = SASS_MEMORY_NEW(AtRule, pstate, lexed);
2626
2442
  String_Schema_Obj val = parse_almost_any_value();
2627
2443
  // strip left and right if they are of type string
2628
2444
  directive->value(val);
@@ -2632,7 +2448,7 @@ namespace Sass {
2632
2448
  return directive;
2633
2449
  }
2634
2450
 
2635
- Expression_Obj Parser::lex_interpolation()
2451
+ ExpressionObj Parser::lex_interpolation()
2636
2452
  {
2637
2453
  if (lex < interpolant >(true) != NULL) {
2638
2454
  return parse_interpolated_chunk(lexed, true);
@@ -2640,26 +2456,27 @@ namespace Sass {
2640
2456
  return {};
2641
2457
  }
2642
2458
 
2643
- Expression_Obj Parser::lex_interp_uri()
2459
+ ExpressionObj Parser::lex_interp_uri()
2644
2460
  {
2645
2461
  // create a string schema by lexing optional interpolations
2646
2462
  return lex_interp< re_string_uri_open, re_string_uri_close >();
2647
2463
  }
2648
2464
 
2649
- Expression_Obj Parser::lex_interp_string()
2465
+ ExpressionObj Parser::lex_interp_string()
2650
2466
  {
2651
- Expression_Obj rv;
2467
+ ExpressionObj rv;
2652
2468
  if ((rv = lex_interp< re_string_double_open, re_string_double_close >())) return rv;
2653
2469
  if ((rv = lex_interp< re_string_single_open, re_string_single_close >())) return rv;
2654
2470
  return rv;
2655
2471
  }
2656
2472
 
2657
- Expression_Obj Parser::lex_almost_any_value_chars()
2473
+ ExpressionObj Parser::lex_almost_any_value_chars()
2658
2474
  {
2659
2475
  const char* match =
2660
2476
  lex <
2661
2477
  one_plus <
2662
2478
  alternatives <
2479
+ exactly <'>'>,
2663
2480
  sequence <
2664
2481
  exactly <'\\'>,
2665
2482
  any_char
@@ -2706,9 +2523,9 @@ namespace Sass {
2706
2523
  return {};
2707
2524
  }
2708
2525
 
2709
- Expression_Obj Parser::lex_almost_any_value_token()
2526
+ ExpressionObj Parser::lex_almost_any_value_token()
2710
2527
  {
2711
- Expression_Obj rv;
2528
+ ExpressionObj rv;
2712
2529
  if (*position == 0) return {};
2713
2530
  if ((rv = lex_almost_any_value_chars())) return rv;
2714
2531
  // if ((rv = lex_block_comment())) return rv;
@@ -2727,7 +2544,7 @@ namespace Sass {
2727
2544
  String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
2728
2545
  if (*position == 0) return {};
2729
2546
  lex < spaces >(false);
2730
- Expression_Obj token = lex_almost_any_value_token();
2547
+ ExpressionObj token = lex_almost_any_value_token();
2731
2548
  if (!token) return {};
2732
2549
  schema->append(token);
2733
2550
  if (*position == 0) {
@@ -2746,7 +2563,7 @@ namespace Sass {
2746
2563
  return schema.detach();
2747
2564
  }
2748
2565
 
2749
- Warning_Obj Parser::parse_warning()
2566
+ WarningRuleObj Parser::parse_warning()
2750
2567
  {
2751
2568
  if (stack.back() != Scope::Root &&
2752
2569
  stack.back() != Scope::Function &&
@@ -2755,10 +2572,10 @@ namespace Sass {
2755
2572
  stack.back() != Scope::Rules) {
2756
2573
  error("Illegal nesting: Only properties may be nested beneath properties.");
2757
2574
  }
2758
- return SASS_MEMORY_NEW(Warning, pstate, parse_list(DELAYED));
2575
+ return SASS_MEMORY_NEW(WarningRule, pstate, parse_list(DELAYED));
2759
2576
  }
2760
2577
 
2761
- Error_Obj Parser::parse_error()
2578
+ ErrorRuleObj Parser::parse_error()
2762
2579
  {
2763
2580
  if (stack.back() != Scope::Root &&
2764
2581
  stack.back() != Scope::Function &&
@@ -2767,10 +2584,10 @@ namespace Sass {
2767
2584
  stack.back() != Scope::Rules) {
2768
2585
  error("Illegal nesting: Only properties may be nested beneath properties.");
2769
2586
  }
2770
- return SASS_MEMORY_NEW(Error, pstate, parse_list(DELAYED));
2587
+ return SASS_MEMORY_NEW(ErrorRule, pstate, parse_list(DELAYED));
2771
2588
  }
2772
2589
 
2773
- Debug_Obj Parser::parse_debug()
2590
+ DebugRuleObj Parser::parse_debug()
2774
2591
  {
2775
2592
  if (stack.back() != Scope::Root &&
2776
2593
  stack.back() != Scope::Function &&
@@ -2779,7 +2596,7 @@ namespace Sass {
2779
2596
  stack.back() != Scope::Rules) {
2780
2597
  error("Illegal nesting: Only properties may be nested beneath properties.");
2781
2598
  }
2782
- return SASS_MEMORY_NEW(Debug, pstate, parse_list(DELAYED));
2599
+ return SASS_MEMORY_NEW(DebugRule, pstate, parse_list(DELAYED));
2783
2600
  }
2784
2601
 
2785
2602
  Return_Obj Parser::parse_return_directive()
@@ -2826,7 +2643,7 @@ namespace Sass {
2826
2643
  rv.error = q;
2827
2644
  rv.position = q;
2828
2645
  // check expected opening bracket
2829
- // only after successfull matching
2646
+ // only after successful matching
2830
2647
  if (peek < exactly<'{'> >(q)) rv.found = q;
2831
2648
  // else if (peek < end_of_file >(q)) rv.found = q;
2832
2649
  else if (peek < exactly<'('> >(q)) rv.found = q;
@@ -2934,53 +2751,53 @@ namespace Sass {
2934
2751
  void Parser::read_bom()
2935
2752
  {
2936
2753
  size_t skip = 0;
2937
- std::string encoding;
2754
+ sass::string encoding;
2938
2755
  bool utf_8 = false;
2939
- switch ((unsigned char) source[0]) {
2756
+ switch ((unsigned char)position[0]) {
2940
2757
  case 0xEF:
2941
- skip = check_bom_chars(source, end, utf_8_bom, 3);
2758
+ skip = check_bom_chars(position, end, utf_8_bom, 3);
2942
2759
  encoding = "UTF-8";
2943
2760
  utf_8 = true;
2944
2761
  break;
2945
2762
  case 0xFE:
2946
- skip = check_bom_chars(source, end, utf_16_bom_be, 2);
2763
+ skip = check_bom_chars(position, end, utf_16_bom_be, 2);
2947
2764
  encoding = "UTF-16 (big endian)";
2948
2765
  break;
2949
2766
  case 0xFF:
2950
- skip = check_bom_chars(source, end, utf_16_bom_le, 2);
2951
- skip += (skip ? check_bom_chars(source, end, utf_32_bom_le, 4) : 0);
2767
+ skip = check_bom_chars(position, end, utf_16_bom_le, 2);
2768
+ skip += (skip ? check_bom_chars(position, end, utf_32_bom_le, 4) : 0);
2952
2769
  encoding = (skip == 2 ? "UTF-16 (little endian)" : "UTF-32 (little endian)");
2953
2770
  break;
2954
2771
  case 0x00:
2955
- skip = check_bom_chars(source, end, utf_32_bom_be, 4);
2772
+ skip = check_bom_chars(position, end, utf_32_bom_be, 4);
2956
2773
  encoding = "UTF-32 (big endian)";
2957
2774
  break;
2958
2775
  case 0x2B:
2959
- skip = check_bom_chars(source, end, utf_7_bom_1, 4)
2960
- | check_bom_chars(source, end, utf_7_bom_2, 4)
2961
- | check_bom_chars(source, end, utf_7_bom_3, 4)
2962
- | check_bom_chars(source, end, utf_7_bom_4, 4)
2963
- | check_bom_chars(source, end, utf_7_bom_5, 5);
2776
+ skip = check_bom_chars(position, end, utf_7_bom_1, 4)
2777
+ | check_bom_chars(position, end, utf_7_bom_2, 4)
2778
+ | check_bom_chars(position, end, utf_7_bom_3, 4)
2779
+ | check_bom_chars(position, end, utf_7_bom_4, 4)
2780
+ | check_bom_chars(position, end, utf_7_bom_5, 5);
2964
2781
  encoding = "UTF-7";
2965
2782
  break;
2966
2783
  case 0xF7:
2967
- skip = check_bom_chars(source, end, utf_1_bom, 3);
2784
+ skip = check_bom_chars(position, end, utf_1_bom, 3);
2968
2785
  encoding = "UTF-1";
2969
2786
  break;
2970
2787
  case 0xDD:
2971
- skip = check_bom_chars(source, end, utf_ebcdic_bom, 4);
2788
+ skip = check_bom_chars(position, end, utf_ebcdic_bom, 4);
2972
2789
  encoding = "UTF-EBCDIC";
2973
2790
  break;
2974
2791
  case 0x0E:
2975
- skip = check_bom_chars(source, end, scsu_bom, 3);
2792
+ skip = check_bom_chars(position, end, scsu_bom, 3);
2976
2793
  encoding = "SCSU";
2977
2794
  break;
2978
2795
  case 0xFB:
2979
- skip = check_bom_chars(source, end, bocu_1_bom, 3);
2796
+ skip = check_bom_chars(position, end, bocu_1_bom, 3);
2980
2797
  encoding = "BOCU-1";
2981
2798
  break;
2982
2799
  case 0x84:
2983
- skip = check_bom_chars(source, end, gb_18030_bom, 4);
2800
+ skip = check_bom_chars(position, end, gb_18030_bom, 4);
2984
2801
  encoding = "GB-18030";
2985
2802
  break;
2986
2803
  default: break;
@@ -3000,7 +2817,7 @@ namespace Sass {
3000
2817
  }
3001
2818
 
3002
2819
 
3003
- Expression_Obj Parser::fold_operands(Expression_Obj base, std::vector<Expression_Obj>& operands, Operand op)
2820
+ ExpressionObj Parser::fold_operands(ExpressionObj base, sass::vector<ExpressionObj>& operands, Operand op)
3004
2821
  {
3005
2822
  for (size_t i = 0, S = operands.size(); i < S; ++i) {
3006
2823
  base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), op, base, operands[i]);
@@ -3008,7 +2825,7 @@ namespace Sass {
3008
2825
  return base;
3009
2826
  }
3010
2827
 
3011
- Expression_Obj Parser::fold_operands(Expression_Obj base, std::vector<Expression_Obj>& operands, std::vector<Operand>& ops, size_t i)
2828
+ ExpressionObj Parser::fold_operands(ExpressionObj base, sass::vector<ExpressionObj>& operands, sass::vector<Operand>& ops, size_t i)
3012
2829
  {
3013
2830
  if (String_Schema* schema = Cast<String_Schema>(base)) {
3014
2831
  // return schema;
@@ -3024,7 +2841,7 @@ namespace Sass {
3024
2841
  || (ops[0].operand == Sass_OP::LTE)
3025
2842
  || (ops[0].operand == Sass_OP::GTE)
3026
2843
  )) {
3027
- Expression_Obj rhs = fold_operands(operands[i], operands, ops, i + 1);
2844
+ ExpressionObj rhs = fold_operands(operands[i], operands, ops, i + 1);
3028
2845
  rhs = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[0], schema, rhs);
3029
2846
  return rhs;
3030
2847
  }
@@ -3032,12 +2849,19 @@ namespace Sass {
3032
2849
  }
3033
2850
  }
3034
2851
 
2852
+ if (operands.size() > Constants::MaxCallStack) {
2853
+ // XXX: this is never hit via spec tests
2854
+ sass::ostream stm;
2855
+ stm << "Stack depth exceeded max of " << Constants::MaxCallStack;
2856
+ error(stm.str());
2857
+ }
2858
+
3035
2859
  for (size_t S = operands.size(); i < S; ++i) {
3036
2860
  if (String_Schema* schema = Cast<String_Schema>(operands[i])) {
3037
2861
  if (schema->has_interpolants()) {
3038
2862
  if (i + 1 < S) {
3039
2863
  // this whole branch is never hit via spec tests
3040
- Expression_Obj rhs = fold_operands(operands[i+1], operands, ops, i + 2);
2864
+ ExpressionObj rhs = fold_operands(operands[i+1], operands, ops, i + 2);
3041
2865
  rhs = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], schema, rhs);
3042
2866
  base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], base, rhs);
3043
2867
  return base;
@@ -3063,24 +2887,14 @@ namespace Sass {
3063
2887
  return base;
3064
2888
  }
3065
2889
 
3066
- void Parser::error(std::string msg, Position pos)
2890
+ void Parser::error(sass::string msg)
3067
2891
  {
3068
- Position p(pos.line ? pos : before_token);
3069
- ParserState pstate(path, source, p, Offset(0, 0));
3070
- // `pstate.src` may not outlive stack unwind so we must copy it.
3071
- char *src_copy = sass_copy_c_string(pstate.src);
3072
- pstate.src = src_copy;
3073
2892
  traces.push_back(Backtrace(pstate));
3074
- throw Exception::InvalidSass(pstate, traces, msg, src_copy);
3075
- }
3076
-
3077
- void Parser::error(std::string msg)
3078
- {
3079
- error(msg, pstate);
2893
+ throw Exception::InvalidSass(pstate, traces, msg);
3080
2894
  }
3081
2895
 
3082
2896
  // print a css parsing error with actual context information from parsed source
3083
- void Parser::css_error(const std::string& msg, const std::string& prefix, const std::string& middle, const bool trim)
2897
+ void Parser::css_error(const sass::string& msg, const sass::string& prefix, const sass::string& middle, const bool trim)
3084
2898
  {
3085
2899
  int max_len = 18;
3086
2900
  const char* end = this->end;
@@ -3089,13 +2903,13 @@ namespace Sass {
3089
2903
  if (!pos) pos = position;
3090
2904
 
3091
2905
  const char* last_pos(pos);
3092
- if (last_pos > source) {
3093
- utf8::prior(last_pos, source);
2906
+ if (last_pos > begin) {
2907
+ utf8::prior(last_pos, begin);
3094
2908
  }
3095
2909
  // backup position to last significant char
3096
- while (trim && last_pos > source && last_pos < end) {
3097
- if (!Prelexer::is_space(*last_pos)) break;
3098
- utf8::prior(last_pos, source);
2910
+ while (trim && last_pos > begin&& last_pos < end) {
2911
+ if (!Util::ascii_isspace(static_cast<unsigned char>(*last_pos))) break;
2912
+ utf8::prior(last_pos, begin);
3099
2913
  }
3100
2914
 
3101
2915
  bool ellipsis_left = false;
@@ -3104,9 +2918,9 @@ namespace Sass {
3104
2918
 
3105
2919
  if (*pos_left) utf8::next(pos_left, end);
3106
2920
  if (*end_left) utf8::next(end_left, end);
3107
- while (pos_left > source) {
2921
+ while (pos_left > begin) {
3108
2922
  if (utf8::distance(pos_left, end_left) >= max_len) {
3109
- utf8::prior(pos_left, source);
2923
+ utf8::prior(pos_left, begin);
3110
2924
  ellipsis_left = *(pos_left) != '\n' &&
3111
2925
  *(pos_left) != '\r';
3112
2926
  utf8::next(pos_left, end);
@@ -3114,13 +2928,13 @@ namespace Sass {
3114
2928
  }
3115
2929
 
3116
2930
  const char* prev = pos_left;
3117
- utf8::prior(prev, source);
2931
+ utf8::prior(prev, begin);
3118
2932
  if (*prev == '\r') break;
3119
2933
  if (*prev == '\n') break;
3120
2934
  pos_left = prev;
3121
2935
  }
3122
- if (pos_left < source) {
3123
- pos_left = source;
2936
+ if (pos_left < begin) {
2937
+ pos_left = begin;
3124
2938
  }
3125
2939
 
3126
2940
  bool ellipsis_right = false;
@@ -3138,14 +2952,12 @@ namespace Sass {
3138
2952
  }
3139
2953
  // if (*end_right == 0) end_right ++;
3140
2954
 
3141
- std::string left(pos_left, end_left);
3142
- std::string right(pos_right, end_right);
2955
+ sass::string left(pos_left, end_left);
2956
+ sass::string right(pos_right, end_right);
3143
2957
  size_t left_subpos = left.size() > 15 ? left.size() - 15 : 0;
3144
2958
  size_t right_subpos = right.size() > 15 ? right.size() - 15 : 0;
3145
2959
  if (left_subpos && ellipsis_left) left = ellipsis + left.substr(left_subpos);
3146
2960
  if (right_subpos && ellipsis_right) right = right.substr(right_subpos) + ellipsis;
3147
- // Hotfix when source is null, probably due to interpolation parsing!?
3148
- if (source == NULL || *source == 0) source = pstate.src;
3149
2961
  // now pass new message to the more generic error function
3150
2962
  error(msg + prefix + quote(left) + middle + quote(right));
3151
2963
  }