sassc 2.1.0.pre3 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -0
  3. data/CHANGELOG.md +24 -0
  4. data/Rakefile +2 -4
  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.hpp +12 -0
  81. data/ext/libsass/src/memory/allocator.cpp +48 -0
  82. data/ext/libsass/src/memory/allocator.hpp +138 -0
  83. data/ext/libsass/src/memory/config.hpp +20 -0
  84. data/ext/libsass/src/memory/memory_pool.hpp +186 -0
  85. data/ext/libsass/src/memory/{SharedPtr.cpp → shared_ptr.cpp} +2 -2
  86. data/ext/libsass/src/memory/{SharedPtr.hpp → shared_ptr.hpp} +55 -9
  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 +11 -13
  132. data/lib/sassc/native.rb +9 -7
  133. data/lib/sassc/script.rb +4 -6
  134. data/lib/sassc/version.rb +1 -1
  135. data/test/functions_test.rb +38 -1
  136. data/test/native_test.rb +4 -4
  137. metadata +31 -18
  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
@@ -30,7 +30,7 @@ namespace Sass {
30
30
  throw Exception::InvalidValue({}, *n);
31
31
  }
32
32
  // use values to_string facility
33
- std::string res = n->to_string(opt);
33
+ sass::string res = n->to_string(opt);
34
34
  // output the final token
35
35
  append_token(res, n);
36
36
  }
@@ -77,7 +77,7 @@ namespace Sass {
77
77
  // declare the charset
78
78
  if (output_style() != COMPRESSED)
79
79
  charset = "@charset \"UTF-8\";"
80
- + std::string(opt.linefeed);
80
+ + sass::string(opt.linefeed);
81
81
  else charset = "\xEF\xBB\xBF";
82
82
  // abort search
83
83
  break;
@@ -111,16 +111,18 @@ namespace Sass {
111
111
  }
112
112
  }
113
113
 
114
- void Output::operator()(Ruleset* r)
114
+ void Output::operator()(StyleRule* r)
115
115
  {
116
- Selector_Obj s = r->selector();
117
- Block_Obj b = r->block();
116
+ Block_Obj b = r->block();
117
+ SelectorListObj s = r->selector();
118
+
119
+ if (!s || s->empty()) return;
118
120
 
119
121
  // Filter out rulesets that aren't printable (process its children though)
120
122
  if (!Util::isPrintable(r, output_style())) {
121
123
  for (size_t i = 0, L = b->length(); i < L; ++i) {
122
- const Statement_Obj& stm = b->at(i);
123
- if (Cast<Has_Block>(stm)) {
124
+ const Statement_Obj& stm = b->get(i);
125
+ if (Cast<ParentStatement>(stm)) {
124
126
  if (!Cast<Declaration>(stm)) {
125
127
  stm->perform(this);
126
128
  }
@@ -129,12 +131,14 @@ namespace Sass {
129
131
  return;
130
132
  }
131
133
 
132
- if (output_style() == NESTED) indentation += r->tabs();
134
+ if (output_style() == NESTED) {
135
+ indentation += r->tabs();
136
+ }
133
137
  if (opt.source_comments) {
134
- std::stringstream ss;
138
+ sass::ostream ss;
135
139
  append_indentation();
136
- std::string path(File::abs2rel(r->pstate().path));
137
- ss << "/* line " << r->pstate().line + 1 << ", " << path << " */";
140
+ sass::string path(File::abs2rel(r->pstate().getPath()));
141
+ ss << "/* line " << r->pstate().getLine() << ", " << path << " */";
138
142
  append_string(ss.str());
139
143
  append_optional_linefeed();
140
144
  }
@@ -142,13 +146,13 @@ namespace Sass {
142
146
  if (s) s->perform(this);
143
147
  append_scope_opener(b);
144
148
  for (size_t i = 0, L = b->length(); i < L; ++i) {
145
- Statement_Obj stm = b->at(i);
149
+ Statement_Obj stm = b->get(i);
146
150
  bool bPrintExpression = true;
147
151
  // Check print conditions
148
152
  if (Declaration* dec = Cast<Declaration>(stm)) {
149
- if (String_Constant* valConst = Cast<String_Constant>(dec->value())) {
150
- std::string val(valConst->value());
151
- if (String_Quoted* qstr = Cast<String_Quoted>(valConst)) {
153
+ if (const String_Constant* valConst = Cast<String_Constant>(dec->value())) {
154
+ const sass::string& val = valConst->value();
155
+ if (const String_Quoted* qstr = Cast<const String_Quoted>(valConst)) {
152
156
  if (!qstr->quote_mark() && val.empty()) {
153
157
  bPrintExpression = false;
154
158
  }
@@ -157,7 +161,7 @@ namespace Sass {
157
161
  else if (List* list = Cast<List>(dec->value())) {
158
162
  bool all_invisible = true;
159
163
  for (size_t list_i = 0, list_L = list->length(); list_i < list_L; ++list_i) {
160
- Expression* item = list->at(list_i);
164
+ Expression* item = list->get(list_i);
161
165
  if (!item->is_invisible()) all_invisible = false;
162
166
  }
163
167
  if (all_invisible && !list->is_bracketed()) bPrintExpression = false;
@@ -188,25 +192,25 @@ namespace Sass {
188
192
 
189
193
  append_scope_opener();
190
194
  for (size_t i = 0, L = b->length(); i < L; ++i) {
191
- Statement_Obj stm = b->at(i);
195
+ Statement_Obj stm = b->get(i);
192
196
  stm->perform(this);
193
197
  if (i < L - 1) append_special_linefeed();
194
198
  }
195
199
  append_scope_closer();
196
200
  }
197
201
 
198
- void Output::operator()(Supports_Block* f)
202
+ void Output::operator()(SupportsRule* f)
199
203
  {
200
204
  if (f->is_invisible()) return;
201
205
 
202
- Supports_Condition_Obj c = f->condition();
206
+ SupportsConditionObj c = f->condition();
203
207
  Block_Obj b = f->block();
204
208
 
205
209
  // Filter out feature blocks that aren't printable (process its children though)
206
210
  if (!Util::isPrintable(f, output_style())) {
207
211
  for (size_t i = 0, L = b->length(); i < L; ++i) {
208
- Statement_Obj stm = b->at(i);
209
- if (Cast<Has_Block>(stm)) {
212
+ Statement_Obj stm = b->get(i);
213
+ if (Cast<ParentStatement>(stm)) {
210
214
  stm->perform(this);
211
215
  }
212
216
  }
@@ -221,7 +225,7 @@ namespace Sass {
221
225
  append_scope_opener();
222
226
 
223
227
  for (size_t i = 0, L = b->length(); i < L; ++i) {
224
- Statement_Obj stm = b->at(i);
228
+ Statement_Obj stm = b->get(i);
225
229
  stm->perform(this);
226
230
  if (i < L - 1) append_special_linefeed();
227
231
  }
@@ -232,48 +236,28 @@ namespace Sass {
232
236
 
233
237
  }
234
238
 
235
- void Output::operator()(Media_Block* m)
239
+ void Output::operator()(CssMediaRule* rule)
236
240
  {
237
- if (m->is_invisible()) return;
238
-
239
- Block_Obj b = m->block();
240
-
241
- // Filter out media blocks that aren't printable (process its children though)
242
- if (!Util::isPrintable(m, output_style())) {
243
- for (size_t i = 0, L = b->length(); i < L; ++i) {
244
- Statement_Obj stm = b->at(i);
245
- if (Cast<Has_Block>(stm)) {
246
- stm->perform(this);
247
- }
248
- }
249
- return;
241
+ // Avoid null pointer exception
242
+ if (rule == nullptr) return;
243
+ // Skip empty/invisible rule
244
+ if (rule->isInvisible()) return;
245
+ // Avoid null pointer exception
246
+ if (rule->block() == nullptr) return;
247
+ // Skip empty/invisible rule
248
+ if (rule->block()->isInvisible()) return;
249
+ // Skip if block is empty/invisible
250
+ if (Util::isPrintable(rule, output_style())) {
251
+ // Let inspect do its magic
252
+ Inspect::operator()(rule);
250
253
  }
251
- if (output_style() == NESTED) indentation += m->tabs();
252
- append_indentation();
253
- append_token("@media", m);
254
- append_mandatory_space();
255
- in_media_block = true;
256
- m->media_queries()->perform(this);
257
- in_media_block = false;
258
- append_scope_opener();
259
-
260
- for (size_t i = 0, L = b->length(); i < L; ++i) {
261
- if (b->at(i)) {
262
- Statement_Obj stm = b->at(i);
263
- stm->perform(this);
264
- }
265
- if (i < L - 1) append_special_linefeed();
266
- }
267
-
268
- if (output_style() == NESTED) indentation -= m->tabs();
269
- append_scope_closer();
270
254
  }
271
255
 
272
- void Output::operator()(Directive* a)
256
+ void Output::operator()(AtRule* a)
273
257
  {
274
- std::string kwd = a->keyword();
258
+ sass::string kwd = a->keyword();
275
259
  Selector_Obj s = a->selector();
276
- Expression_Obj v = a->value();
260
+ ExpressionObj v = a->value();
277
261
  Block_Obj b = a->block();
278
262
 
279
263
  append_indentation();
@@ -304,8 +288,8 @@ namespace Sass {
304
288
  bool format = kwd != "@font-face";;
305
289
 
306
290
  for (size_t i = 0, L = b->length(); i < L; ++i) {
307
- Statement_Obj stm = b->at(i);
308
- stm->perform(this);
291
+ Statement_Obj stm = b->get(i);
292
+ if (stm) stm->perform(this);
309
293
  if (i < L - 1 && format) append_special_linefeed();
310
294
  }
311
295
 
@@ -325,10 +309,7 @@ namespace Sass {
325
309
 
326
310
  void Output::operator()(String_Constant* s)
327
311
  {
328
- std::string value(s->value());
329
- if (s->can_compress_whitespace() && output_style() == COMPRESSED) {
330
- value.erase(std::remove_if(value.begin(), value.end(), ::isspace), value.end());
331
- }
312
+ sass::string value(s->value());
332
313
  if (!in_comment && !in_custom_property) {
333
314
  append_token(string_to_output(value), s);
334
315
  } else {
@@ -20,17 +20,17 @@ namespace Sass {
20
20
  virtual ~Output();
21
21
 
22
22
  protected:
23
- std::string charset;
24
- std::vector<AST_Node*> top_nodes;
23
+ sass::string charset;
24
+ sass::vector<AST_Node*> top_nodes;
25
25
 
26
26
  public:
27
27
  OutputBuffer get_buffer(void);
28
28
 
29
29
  virtual void operator()(Map*);
30
- virtual void operator()(Ruleset*);
31
- virtual void operator()(Supports_Block*);
32
- virtual void operator()(Media_Block*);
33
- virtual void operator()(Directive*);
30
+ virtual void operator()(StyleRule*);
31
+ virtual void operator()(SupportsRule*);
32
+ virtual void operator()(CssMediaRule*);
33
+ virtual void operator()(AtRule*);
34
34
  virtual void operator()(Keyframe_Rule*);
35
35
  virtual void operator()(Import*);
36
36
  virtual void operator()(Comment*);
@@ -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
  }