sassc 2.0.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.gitmodules +1 -1
  4. data/.travis.yml +9 -3
  5. data/CHANGELOG.md +36 -0
  6. data/CODE_OF_CONDUCT.md +1 -1
  7. data/README.md +1 -1
  8. data/Rakefile +43 -7
  9. data/ext/depend +4 -0
  10. data/ext/extconf.rb +92 -0
  11. data/ext/libsass/VERSION +1 -0
  12. data/ext/libsass/include/sass/base.h +9 -1
  13. data/ext/libsass/include/sass/context.h +5 -1
  14. data/ext/libsass/src/MurmurHash2.hpp +91 -0
  15. data/ext/libsass/src/ast.cpp +755 -2028
  16. data/ext/libsass/src/ast.hpp +492 -2477
  17. data/ext/libsass/src/{to_c.cpp → ast2c.cpp} +22 -16
  18. data/ext/libsass/src/ast2c.hpp +39 -0
  19. data/ext/libsass/src/ast_def_macros.hpp +70 -10
  20. data/ext/libsass/src/ast_fwd_decl.cpp +5 -3
  21. data/ext/libsass/src/ast_fwd_decl.hpp +107 -296
  22. data/ext/libsass/src/ast_helpers.hpp +292 -0
  23. data/ext/libsass/src/ast_sel_cmp.cpp +396 -0
  24. data/ext/libsass/src/ast_sel_super.cpp +539 -0
  25. data/ext/libsass/src/ast_sel_unify.cpp +275 -0
  26. data/ext/libsass/src/ast_sel_weave.cpp +616 -0
  27. data/ext/libsass/src/ast_selectors.cpp +1043 -0
  28. data/ext/libsass/src/ast_selectors.hpp +522 -0
  29. data/ext/libsass/src/ast_supports.cpp +114 -0
  30. data/ext/libsass/src/ast_supports.hpp +121 -0
  31. data/ext/libsass/src/ast_values.cpp +1154 -0
  32. data/ext/libsass/src/ast_values.hpp +498 -0
  33. data/ext/libsass/src/backtrace.cpp +11 -7
  34. data/ext/libsass/src/backtrace.hpp +5 -5
  35. data/ext/libsass/src/base64vlq.cpp +5 -2
  36. data/ext/libsass/src/base64vlq.hpp +1 -1
  37. data/ext/libsass/src/bind.cpp +35 -34
  38. data/ext/libsass/src/bind.hpp +3 -1
  39. data/ext/libsass/src/c2ast.cpp +64 -0
  40. data/ext/libsass/src/c2ast.hpp +14 -0
  41. data/ext/libsass/src/cencode.c +4 -6
  42. data/ext/libsass/src/check_nesting.cpp +83 -88
  43. data/ext/libsass/src/check_nesting.hpp +39 -34
  44. data/ext/libsass/src/color_maps.cpp +168 -164
  45. data/ext/libsass/src/color_maps.hpp +152 -160
  46. data/ext/libsass/src/constants.cpp +20 -0
  47. data/ext/libsass/src/constants.hpp +19 -0
  48. data/ext/libsass/src/context.cpp +104 -121
  49. data/ext/libsass/src/context.hpp +43 -55
  50. data/ext/libsass/src/cssize.cpp +103 -188
  51. data/ext/libsass/src/cssize.hpp +45 -51
  52. data/ext/libsass/src/dart_helpers.hpp +199 -0
  53. data/ext/libsass/src/debugger.hpp +524 -361
  54. data/ext/libsass/src/emitter.cpp +26 -26
  55. data/ext/libsass/src/emitter.hpp +20 -18
  56. data/ext/libsass/src/environment.cpp +41 -27
  57. data/ext/libsass/src/environment.hpp +33 -22
  58. data/ext/libsass/src/error_handling.cpp +92 -94
  59. data/ext/libsass/src/error_handling.hpp +73 -50
  60. data/ext/libsass/src/eval.cpp +380 -515
  61. data/ext/libsass/src/eval.hpp +64 -57
  62. data/ext/libsass/src/eval_selectors.cpp +75 -0
  63. data/ext/libsass/src/expand.cpp +322 -263
  64. data/ext/libsass/src/expand.hpp +55 -39
  65. data/ext/libsass/src/extender.cpp +1188 -0
  66. data/ext/libsass/src/extender.hpp +399 -0
  67. data/ext/libsass/src/extension.cpp +43 -0
  68. data/ext/libsass/src/extension.hpp +89 -0
  69. data/ext/libsass/src/file.cpp +134 -88
  70. data/ext/libsass/src/file.hpp +28 -37
  71. data/ext/libsass/src/fn_colors.cpp +596 -0
  72. data/ext/libsass/src/fn_colors.hpp +85 -0
  73. data/ext/libsass/src/fn_lists.cpp +285 -0
  74. data/ext/libsass/src/fn_lists.hpp +34 -0
  75. data/ext/libsass/src/fn_maps.cpp +94 -0
  76. data/ext/libsass/src/fn_maps.hpp +30 -0
  77. data/ext/libsass/src/fn_miscs.cpp +244 -0
  78. data/ext/libsass/src/fn_miscs.hpp +40 -0
  79. data/ext/libsass/src/fn_numbers.cpp +227 -0
  80. data/ext/libsass/src/fn_numbers.hpp +45 -0
  81. data/ext/libsass/src/fn_selectors.cpp +205 -0
  82. data/ext/libsass/src/fn_selectors.hpp +35 -0
  83. data/ext/libsass/src/fn_strings.cpp +268 -0
  84. data/ext/libsass/src/fn_strings.hpp +34 -0
  85. data/ext/libsass/src/fn_utils.cpp +158 -0
  86. data/ext/libsass/src/fn_utils.hpp +62 -0
  87. data/ext/libsass/src/inspect.cpp +253 -266
  88. data/ext/libsass/src/inspect.hpp +72 -74
  89. data/ext/libsass/src/json.cpp +2 -2
  90. data/ext/libsass/src/lexer.cpp +25 -84
  91. data/ext/libsass/src/lexer.hpp +5 -16
  92. data/ext/libsass/src/listize.cpp +27 -43
  93. data/ext/libsass/src/listize.hpp +14 -11
  94. data/ext/libsass/src/mapping.hpp +1 -0
  95. data/ext/libsass/src/memory.hpp +12 -0
  96. data/ext/libsass/src/memory/allocator.cpp +48 -0
  97. data/ext/libsass/src/memory/allocator.hpp +138 -0
  98. data/ext/libsass/src/memory/config.hpp +20 -0
  99. data/ext/libsass/src/memory/memory_pool.hpp +186 -0
  100. data/ext/libsass/src/memory/shared_ptr.cpp +33 -0
  101. data/ext/libsass/src/memory/shared_ptr.hpp +332 -0
  102. data/ext/libsass/src/operation.hpp +193 -143
  103. data/ext/libsass/src/operators.cpp +56 -29
  104. data/ext/libsass/src/operators.hpp +11 -11
  105. data/ext/libsass/src/ordered_map.hpp +112 -0
  106. data/ext/libsass/src/output.cpp +59 -75
  107. data/ext/libsass/src/output.hpp +15 -22
  108. data/ext/libsass/src/parser.cpp +662 -818
  109. data/ext/libsass/src/parser.hpp +96 -100
  110. data/ext/libsass/src/parser_selectors.cpp +189 -0
  111. data/ext/libsass/src/permutate.hpp +164 -0
  112. data/ext/libsass/src/plugins.cpp +12 -8
  113. data/ext/libsass/src/plugins.hpp +8 -8
  114. data/ext/libsass/src/position.cpp +10 -26
  115. data/ext/libsass/src/position.hpp +44 -21
  116. data/ext/libsass/src/prelexer.cpp +14 -8
  117. data/ext/libsass/src/prelexer.hpp +9 -9
  118. data/ext/libsass/src/remove_placeholders.cpp +59 -57
  119. data/ext/libsass/src/remove_placeholders.hpp +20 -18
  120. data/ext/libsass/src/sass.cpp +25 -18
  121. data/ext/libsass/src/sass.hpp +22 -14
  122. data/ext/libsass/src/sass2scss.cpp +49 -18
  123. data/ext/libsass/src/sass_context.cpp +104 -132
  124. data/ext/libsass/src/sass_context.hpp +2 -2
  125. data/ext/libsass/src/sass_functions.cpp +7 -4
  126. data/ext/libsass/src/sass_functions.hpp +1 -1
  127. data/ext/libsass/src/sass_values.cpp +26 -21
  128. data/ext/libsass/src/settings.hpp +19 -0
  129. data/ext/libsass/src/source.cpp +69 -0
  130. data/ext/libsass/src/source.hpp +95 -0
  131. data/ext/libsass/src/source_data.hpp +32 -0
  132. data/ext/libsass/src/source_map.cpp +27 -20
  133. data/ext/libsass/src/source_map.hpp +14 -11
  134. data/ext/libsass/src/stylesheet.cpp +22 -0
  135. data/ext/libsass/src/stylesheet.hpp +57 -0
  136. data/ext/libsass/src/to_value.cpp +24 -22
  137. data/ext/libsass/src/to_value.hpp +18 -22
  138. data/ext/libsass/src/units.cpp +28 -22
  139. data/ext/libsass/src/units.hpp +9 -8
  140. data/ext/libsass/src/utf8/checked.h +12 -10
  141. data/ext/libsass/src/utf8/core.h +3 -0
  142. data/ext/libsass/src/utf8_string.cpp +12 -10
  143. data/ext/libsass/src/utf8_string.hpp +7 -6
  144. data/ext/libsass/src/util.cpp +97 -107
  145. data/ext/libsass/src/util.hpp +74 -30
  146. data/ext/libsass/src/util_string.cpp +125 -0
  147. data/ext/libsass/src/util_string.hpp +73 -0
  148. data/ext/libsass/src/values.cpp +33 -24
  149. data/ext/libsass/src/values.hpp +2 -2
  150. data/lib/sassc.rb +24 -0
  151. data/lib/sassc/engine.rb +7 -5
  152. data/lib/sassc/functions_handler.rb +11 -13
  153. data/lib/sassc/native.rb +10 -9
  154. data/lib/sassc/native/native_functions_api.rb +0 -5
  155. data/lib/sassc/script.rb +4 -6
  156. data/lib/sassc/version.rb +1 -1
  157. data/sassc.gemspec +32 -12
  158. data/test/engine_test.rb +32 -2
  159. data/test/functions_test.rb +38 -1
  160. data/test/native_test.rb +4 -4
  161. metadata +95 -109
  162. data/ext/Rakefile +0 -3
  163. data/ext/libsass/.editorconfig +0 -15
  164. data/ext/libsass/.gitattributes +0 -2
  165. data/ext/libsass/.github/CONTRIBUTING.md +0 -65
  166. data/ext/libsass/.github/ISSUE_TEMPLATE.md +0 -54
  167. data/ext/libsass/.gitignore +0 -85
  168. data/ext/libsass/.travis.yml +0 -64
  169. data/ext/libsass/COPYING +0 -25
  170. data/ext/libsass/GNUmakefile.am +0 -88
  171. data/ext/libsass/INSTALL +0 -1
  172. data/ext/libsass/LICENSE +0 -25
  173. data/ext/libsass/Makefile +0 -351
  174. data/ext/libsass/Makefile.conf +0 -55
  175. data/ext/libsass/Readme.md +0 -104
  176. data/ext/libsass/SECURITY.md +0 -10
  177. data/ext/libsass/appveyor.yml +0 -91
  178. data/ext/libsass/configure.ac +0 -138
  179. data/ext/libsass/contrib/libsass.spec +0 -66
  180. data/ext/libsass/docs/README.md +0 -20
  181. data/ext/libsass/docs/api-context-example.md +0 -45
  182. data/ext/libsass/docs/api-context-internal.md +0 -163
  183. data/ext/libsass/docs/api-context.md +0 -295
  184. data/ext/libsass/docs/api-doc.md +0 -215
  185. data/ext/libsass/docs/api-function-example.md +0 -67
  186. data/ext/libsass/docs/api-function-internal.md +0 -8
  187. data/ext/libsass/docs/api-function.md +0 -74
  188. data/ext/libsass/docs/api-importer-example.md +0 -112
  189. data/ext/libsass/docs/api-importer-internal.md +0 -20
  190. data/ext/libsass/docs/api-importer.md +0 -86
  191. data/ext/libsass/docs/api-value-example.md +0 -55
  192. data/ext/libsass/docs/api-value-internal.md +0 -76
  193. data/ext/libsass/docs/api-value.md +0 -154
  194. data/ext/libsass/docs/build-on-darwin.md +0 -27
  195. data/ext/libsass/docs/build-on-gentoo.md +0 -55
  196. data/ext/libsass/docs/build-on-windows.md +0 -139
  197. data/ext/libsass/docs/build-shared-library.md +0 -35
  198. data/ext/libsass/docs/build-with-autotools.md +0 -78
  199. data/ext/libsass/docs/build-with-makefiles.md +0 -68
  200. data/ext/libsass/docs/build-with-mingw.md +0 -107
  201. data/ext/libsass/docs/build-with-visual-studio.md +0 -90
  202. data/ext/libsass/docs/build.md +0 -97
  203. data/ext/libsass/docs/compatibility-plan.md +0 -48
  204. data/ext/libsass/docs/contributing.md +0 -17
  205. data/ext/libsass/docs/custom-functions-internal.md +0 -122
  206. data/ext/libsass/docs/dev-ast-memory.md +0 -223
  207. data/ext/libsass/docs/implementations.md +0 -56
  208. data/ext/libsass/docs/plugins.md +0 -47
  209. data/ext/libsass/docs/setup-environment.md +0 -68
  210. data/ext/libsass/docs/source-map-internals.md +0 -51
  211. data/ext/libsass/docs/trace.md +0 -26
  212. data/ext/libsass/docs/triage.md +0 -17
  213. data/ext/libsass/docs/unicode.md +0 -39
  214. data/ext/libsass/extconf.rb +0 -6
  215. data/ext/libsass/include/sass/version.h.in +0 -12
  216. data/ext/libsass/m4/.gitkeep +0 -0
  217. data/ext/libsass/m4/m4-ax_cxx_compile_stdcxx_11.m4 +0 -167
  218. data/ext/libsass/res/resource.rc +0 -35
  219. data/ext/libsass/script/bootstrap +0 -13
  220. data/ext/libsass/script/branding +0 -10
  221. data/ext/libsass/script/ci-build-libsass +0 -134
  222. data/ext/libsass/script/ci-build-plugin +0 -62
  223. data/ext/libsass/script/ci-install-compiler +0 -6
  224. data/ext/libsass/script/ci-install-deps +0 -20
  225. data/ext/libsass/script/ci-report-coverage +0 -42
  226. data/ext/libsass/script/spec +0 -5
  227. data/ext/libsass/script/tap-driver +0 -652
  228. data/ext/libsass/script/tap-runner +0 -1
  229. data/ext/libsass/script/test-leaks.pl +0 -103
  230. data/ext/libsass/src/GNUmakefile.am +0 -54
  231. data/ext/libsass/src/extend.cpp +0 -2130
  232. data/ext/libsass/src/extend.hpp +0 -86
  233. data/ext/libsass/src/functions.cpp +0 -2234
  234. data/ext/libsass/src/functions.hpp +0 -198
  235. data/ext/libsass/src/memory/SharedPtr.cpp +0 -114
  236. data/ext/libsass/src/memory/SharedPtr.hpp +0 -206
  237. data/ext/libsass/src/node.cpp +0 -319
  238. data/ext/libsass/src/node.hpp +0 -118
  239. data/ext/libsass/src/paths.hpp +0 -71
  240. data/ext/libsass/src/sass_util.cpp +0 -149
  241. data/ext/libsass/src/sass_util.hpp +0 -256
  242. data/ext/libsass/src/subset_map.cpp +0 -55
  243. data/ext/libsass/src/subset_map.hpp +0 -76
  244. data/ext/libsass/src/support/libsass.pc.in +0 -11
  245. data/ext/libsass/src/to_c.hpp +0 -39
  246. data/ext/libsass/test/test_node.cpp +0 -94
  247. data/ext/libsass/test/test_paths.cpp +0 -28
  248. data/ext/libsass/test/test_selector_difference.cpp +0 -25
  249. data/ext/libsass/test/test_specificity.cpp +0 -25
  250. data/ext/libsass/test/test_subset_map.cpp +0 -472
  251. data/ext/libsass/test/test_superselector.cpp +0 -69
  252. data/ext/libsass/test/test_unification.cpp +0 -31
  253. data/ext/libsass/version.sh +0 -10
  254. data/ext/libsass/win/libsass.sln +0 -39
  255. data/ext/libsass/win/libsass.sln.DotSettings +0 -9
  256. data/ext/libsass/win/libsass.targets +0 -118
  257. data/ext/libsass/win/libsass.vcxproj +0 -188
  258. data/ext/libsass/win/libsass.vcxproj.filters +0 -357
  259. data/lib/sassc/native/lib_c.rb +0 -21
  260. data/lib/tasks/libsass.rb +0 -33
@@ -11,13 +11,6 @@
11
11
  namespace Sass {
12
12
  class Context;
13
13
 
14
- // Refactor to make it generic to find linefeed (look behind)
15
- inline bool ends_with(std::string const & value, std::string const & ending)
16
- {
17
- if (ending.size() > value.size()) return false;
18
- return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
19
- }
20
-
21
14
  class Output : public Inspect {
22
15
  protected:
23
16
  using Inspect::operator();
@@ -27,25 +20,25 @@ namespace Sass {
27
20
  virtual ~Output();
28
21
 
29
22
  protected:
30
- std::string charset;
31
- std::vector<AST_Node_Ptr> top_nodes;
23
+ sass::string charset;
24
+ sass::vector<AST_Node*> top_nodes;
32
25
 
33
26
  public:
34
27
  OutputBuffer get_buffer(void);
35
28
 
36
- virtual void operator()(Map_Ptr);
37
- virtual void operator()(Ruleset_Ptr);
38
- virtual void operator()(Supports_Block_Ptr);
39
- virtual void operator()(Media_Block_Ptr);
40
- virtual void operator()(Directive_Ptr);
41
- virtual void operator()(Keyframe_Rule_Ptr);
42
- virtual void operator()(Import_Ptr);
43
- virtual void operator()(Comment_Ptr);
44
- virtual void operator()(Number_Ptr);
45
- virtual void operator()(String_Quoted_Ptr);
46
- virtual void operator()(String_Constant_Ptr);
47
-
48
- void fallback_impl(AST_Node_Ptr n);
29
+ virtual void operator()(Map*);
30
+ virtual void operator()(StyleRule*);
31
+ virtual void operator()(SupportsRule*);
32
+ virtual void operator()(CssMediaRule*);
33
+ virtual void operator()(AtRule*);
34
+ virtual void operator()(Keyframe_Rule*);
35
+ virtual void operator()(Import*);
36
+ virtual void operator()(Comment*);
37
+ virtual void operator()(Number*);
38
+ virtual void operator()(String_Quoted*);
39
+ virtual void operator()(String_Constant*);
40
+
41
+ void fallback_impl(AST_Node* n);
49
42
 
50
43
  };
51
44
 
@@ -1,13 +1,10 @@
1
+ // sass.hpp must go before all system headers to get the
2
+ // __EXTENSIONS__ fix on Solaris.
1
3
  #include "sass.hpp"
4
+
2
5
  #include "parser.hpp"
3
- #include "file.hpp"
4
- #include "inspect.hpp"
5
- #include "constants.hpp"
6
- #include "util.hpp"
7
- #include "prelexer.hpp"
8
6
  #include "color_maps.hpp"
9
- #include "sass/functions.h"
10
- #include "error_handling.hpp"
7
+ #include "util_string.hpp"
11
8
 
12
9
  // Notes about delayed: some ast nodes can have delayed evaluation so
13
10
  // they can preserve their original semantics if needed. This is most
@@ -21,57 +18,46 @@
21
18
  // Another case with delayed values are colors. In compressed mode
22
19
  // only processed values get compressed (other are left as written).
23
20
 
24
- #include <cstdlib>
25
- #include <iostream>
26
- #include <vector>
27
- #include <typeinfo>
28
21
 
29
22
  namespace Sass {
30
23
  using namespace Constants;
31
24
  using namespace Prelexer;
32
25
 
33
- Parser Parser::from_c_str(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source)
34
- {
35
- pstate.offset.column = 0;
36
- pstate.offset.line = 0;
37
- Parser p(ctx, pstate, traces);
38
- p.source = source ? source : beg;
39
- p.position = beg ? beg : p.source;
40
- p.end = p.position + strlen(p.position);
41
- Block_Obj root = SASS_MEMORY_NEW(Block, pstate);
42
- p.block_stack.push_back(root);
43
- root->is_root(true);
44
- return p;
45
- }
46
26
 
47
- Parser Parser::from_c_str(const char* beg, const char* end, Context& ctx, Backtraces traces, ParserState pstate, const char* source)
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)
48
41
  {
49
- pstate.offset.column = 0;
50
- pstate.offset.line = 0;
51
- Parser p(ctx, pstate, traces);
52
- p.source = source ? source : beg;
53
- p.position = beg ? beg : p.source;
54
- p.end = end ? end : p.position + strlen(p.position);
55
42
  Block_Obj root = SASS_MEMORY_NEW(Block, pstate);
56
- p.block_stack.push_back(root);
43
+ stack.push_back(Scope::Root);
44
+ block_stack.push_back(root);
57
45
  root->is_root(true);
58
- return p;
59
46
  }
60
47
 
61
- void Parser::advanceToNextToken() {
48
+ void Parser::advanceToNextToken() {
62
49
  lex < css_comments >(false);
63
50
  // advance to position
64
- pstate += pstate.offset;
51
+ pstate.position += pstate.offset;
65
52
  pstate.offset.column = 0;
66
53
  pstate.offset.line = 0;
67
54
  }
68
55
 
69
- Selector_List_Obj Parser::parse_selector(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source)
56
+ SelectorListObj Parser::parse_selector(SourceData* source, Context& ctx, Backtraces traces, bool allow_parent)
70
57
  {
71
- Parser p = Parser::from_c_str(beg, ctx, traces, pstate, source);
72
- // ToDo: ruby sass errors on parent references
58
+ Parser p(source, ctx, traces, allow_parent);
73
59
  // ToDo: remap the source-map entries somehow
74
- return p.parse_selector_list(false);
60
+ return p.parseSelectorList(false);
75
61
  }
76
62
 
77
63
  bool Parser::peek_newline(const char* start)
@@ -80,18 +66,6 @@ namespace Sass {
80
66
  && ! peek_css<exactly<'{'>>(start);
81
67
  }
82
68
 
83
- Parser Parser::from_token(Token t, Context& ctx, Backtraces traces, ParserState pstate, const char* source)
84
- {
85
- Parser p(ctx, pstate, traces);
86
- p.source = source ? source : t.begin;
87
- p.position = t.begin ? t.begin : p.source;
88
- p.end = t.end ? t.end : p.position + strlen(p.position);
89
- Block_Obj root = SASS_MEMORY_NEW(Block, pstate);
90
- p.block_stack.push_back(root);
91
- root->is_root(true);
92
- return p;
93
- }
94
-
95
69
  /* main entry point to parse root block */
96
70
  Block_Obj Parser::parse()
97
71
  {
@@ -104,7 +78,7 @@ namespace Sass {
104
78
 
105
79
  // report invalid utf8
106
80
  if (it != end) {
107
- pstate += Offset::init(position, it);
81
+ pstate.position += Offset::init(position, it);
108
82
  traces.push_back(Backtrace(pstate));
109
83
  throw Exception::InvalidSass(pstate, traces, "Invalid UTF-8 sequence");
110
84
  }
@@ -115,7 +89,7 @@ namespace Sass {
115
89
  // check seems a bit esoteric but works
116
90
  if (ctx.resources.size() == 1) {
117
91
  // apply headers only on very first include
118
- ctx.apply_custom_headers(root, path, pstate);
92
+ ctx.apply_custom_headers(root, getPath(), pstate);
119
93
  }
120
94
 
121
95
  // parse children nodes
@@ -258,16 +232,23 @@ namespace Sass {
258
232
  else if (lex < kwd_extend >(true)) {
259
233
  Lookahead lookahead = lookahead_for_include(position);
260
234
  if (!lookahead.found) css_error("Invalid CSS", " after ", ": expected selector, was ");
261
- Selector_List_Obj target;
235
+ SelectorListObj target;
262
236
  if (!lookahead.has_interpolants) {
263
- 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);
264
242
  }
265
243
  else {
266
- target = SASS_MEMORY_NEW(Selector_List, pstate);
267
- 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);
268
250
  }
269
251
 
270
- block->append(SASS_MEMORY_NEW(Extension, pstate, target));
271
252
  }
272
253
 
273
254
  // selector may contain interpolations which need delayed evaluation
@@ -280,7 +261,7 @@ namespace Sass {
280
261
  }
281
262
 
282
263
  // parse multiple specific keyword directives
283
- else if (lex < kwd_media >(true)) { block->append(parse_media_block()); }
264
+ else if (lex < kwd_media >(true)) { block->append(parseMediaRule()); }
284
265
  else if (lex < kwd_at_root >(true)) { block->append(parse_at_root_block()); }
285
266
  else if (lex < kwd_include_directive >(true)) { block->append(parse_include_directive()); }
286
267
  else if (lex < kwd_content_directive >(true)) { block->append(parse_content_directive()); }
@@ -291,9 +272,9 @@ namespace Sass {
291
272
  // ignore the @charset directive for now
292
273
  else if (lex< kwd_charset_directive >(true)) { parse_charset_directive(); }
293
274
 
275
+ else if (lex < exactly < else_kwd >>(true)) { error("Invalid CSS: @else must come after @if"); }
276
+
294
277
  // generic at keyword (keep last)
295
- else if (lex< re_special_directive >(true)) { block->append(parse_special_directive()); }
296
- else if (lex< re_prefixed_directive >(true)) { block->append(parse_prefixed_directive()); }
297
278
  else if (lex< at_keyword >(true)) { block->append(parse_directive()); }
298
279
 
299
280
  else if (is_root && stack.back() != Scope::AtRoot /* && block->is_root() */) {
@@ -328,33 +309,33 @@ namespace Sass {
328
309
  Import_Obj Parser::parse_import()
329
310
  {
330
311
  Import_Obj imp = SASS_MEMORY_NEW(Import, pstate);
331
- std::vector<std::pair<std::string,Function_Call_Obj>> to_import;
312
+ sass::vector<std::pair<sass::string,Function_Call_Obj>> to_import;
332
313
  bool first = true;
333
314
  do {
334
315
  while (lex< block_comment >());
335
316
  if (lex< quoted_string >()) {
336
- to_import.push_back(std::pair<std::string,Function_Call_Obj>(std::string(lexed), 0));
317
+ to_import.push_back(std::pair<sass::string,Function_Call_Obj>(sass::string(lexed), {}));
337
318
  }
338
319
  else if (lex< uri_prefix >()) {
339
320
  Arguments_Obj args = SASS_MEMORY_NEW(Arguments, pstate);
340
- Function_Call_Obj result = SASS_MEMORY_NEW(Function_Call, pstate, "url", args);
321
+ Function_Call_Obj result = SASS_MEMORY_NEW(Function_Call, pstate, sass::string("url"), args);
341
322
 
342
323
  if (lex< quoted_string >()) {
343
- Expression_Obj quoted_url = parse_string();
324
+ ExpressionObj quoted_url = parse_string();
344
325
  args->append(SASS_MEMORY_NEW(Argument, quoted_url->pstate(), quoted_url));
345
326
  }
346
327
  else if (String_Obj string_url = parse_url_function_argument()) {
347
328
  args->append(SASS_MEMORY_NEW(Argument, string_url->pstate(), string_url));
348
329
  }
349
330
  else if (peek < skip_over_scopes < exactly < '(' >, exactly < ')' > > >(position)) {
350
- Expression_Obj braced_url = parse_list(); // parse_interpolated_chunk(lexed);
331
+ ExpressionObj braced_url = parse_list(); // parse_interpolated_chunk(lexed);
351
332
  args->append(SASS_MEMORY_NEW(Argument, braced_url->pstate(), braced_url));
352
333
  }
353
334
  else {
354
335
  error("malformed URL");
355
336
  }
356
337
  if (!lex< exactly<')'> >()) error("URI is missing ')'");
357
- 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));
358
339
  }
359
340
  else {
360
341
  if (first) error("@import directive requires a url or quoted path");
@@ -373,9 +354,9 @@ namespace Sass {
373
354
  imp->urls().push_back(location.second);
374
355
  }
375
356
  // check if custom importers want to take over the handling
376
- else if (!ctx.call_importers(unquote(location.first), path, pstate, imp)) {
357
+ else if (!ctx.call_importers(unquote(location.first), getPath(), pstate, imp)) {
377
358
  // nobody wants it, so we do our import
378
- ctx.import_url(imp, location.first, path);
359
+ ctx.import_url(imp, location.first, getPath());
379
360
  }
380
361
  }
381
362
 
@@ -384,12 +365,12 @@ namespace Sass {
384
365
 
385
366
  Definition_Obj Parser::parse_definition(Definition::Type which_type)
386
367
  {
387
- std::string which_str(lexed);
368
+ sass::string which_str(lexed);
388
369
  if (!lex< identifier >()) error("invalid name in " + which_str + " definition");
389
- std::string name(Util::normalize_underscores(lexed));
370
+ sass::string name(Util::normalize_underscores(lexed));
390
371
  if (which_type == Definition::FUNCTION && (name == "and" || name == "or" || name == "not"))
391
372
  { error("Invalid function name \"" + name + "\"."); }
392
- ParserState source_position_of_def = pstate;
373
+ SourceSpan source_position_of_def = pstate;
393
374
  Parameters_Obj params = parse_parameters();
394
375
  if (which_type == Definition::MIXIN) stack.push_back(Scope::Mixin);
395
376
  else stack.push_back(Scope::Function);
@@ -423,9 +404,9 @@ namespace Sass {
423
404
  }
424
405
  while (lex< alternatives < spaces, block_comment > >());
425
406
  lex < variable >();
426
- std::string name(Util::normalize_underscores(lexed));
427
- ParserState pos = pstate;
428
- Expression_Obj val;
407
+ sass::string name(Util::normalize_underscores(lexed));
408
+ SourceSpan pos = pstate;
409
+ ExpressionObj val;
429
410
  bool is_rest = false;
430
411
  while (lex< alternatives < spaces, block_comment > >());
431
412
  if (lex< exactly<':'> >()) { // there's a default value
@@ -469,17 +450,17 @@ namespace Sass {
469
450
  Argument_Obj arg;
470
451
  if (peek_css< sequence < variable, optional_css_comments, exactly<':'> > >()) {
471
452
  lex_css< variable >();
472
- std::string name(Util::normalize_underscores(lexed));
473
- ParserState p = pstate;
453
+ sass::string name(Util::normalize_underscores(lexed));
454
+ SourceSpan p = pstate;
474
455
  lex_css< exactly<':'> >();
475
- Expression_Obj val = parse_space_list();
456
+ ExpressionObj val = parse_space_list();
476
457
  arg = SASS_MEMORY_NEW(Argument, p, val, name);
477
458
  }
478
459
  else {
479
460
  bool is_arglist = false;
480
461
  bool is_keyword = false;
481
- Expression_Obj val = parse_space_list();
482
- List_Ptr l = Cast<List>(val);
462
+ ExpressionObj val = parse_space_list();
463
+ List* l = Cast<List>(val);
483
464
  if (lex_css< exactly< ellipsis > >()) {
484
465
  if (val->concrete_type() == Expression::MAP || (
485
466
  (l != NULL && l->separator() == SASS_HASH)
@@ -493,13 +474,13 @@ namespace Sass {
493
474
 
494
475
  Assignment_Obj Parser::parse_assignment()
495
476
  {
496
- std::string name(Util::normalize_underscores(lexed));
497
- ParserState var_source_position = pstate;
477
+ sass::string name(Util::normalize_underscores(lexed));
478
+ SourceSpan var_source_position = pstate;
498
479
  if (!lex< exactly<':'> >()) error("expected ':' after " + name + " in assignment statement");
499
480
  if (peek_css< alternatives < exactly<';'>, end_of_file > >()) {
500
481
  css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
501
482
  }
502
- Expression_Obj val;
483
+ ExpressionObj val;
503
484
  Lookahead lookahead = lookahead_for_value(position);
504
485
  if (lookahead.has_interpolants && lookahead.found) {
505
486
  val = parse_value_schema(lookahead.found);
@@ -516,7 +497,7 @@ namespace Sass {
516
497
  }
517
498
 
518
499
  // a ruleset connects a selector and a block
519
- Ruleset_Obj Parser::parse_ruleset(Lookahead lookahead)
500
+ StyleRuleObj Parser::parse_ruleset(Lookahead lookahead)
520
501
  {
521
502
  NESTING_GUARD(nestings);
522
503
  // inherit is_root from parent block
@@ -525,12 +506,15 @@ namespace Sass {
525
506
  // make sure to move up the the last position
526
507
  lex < optional_css_whitespace >(false, true);
527
508
  // create the connector object (add parts later)
528
- Ruleset_Obj ruleset = SASS_MEMORY_NEW(Ruleset, pstate);
509
+ StyleRuleObj ruleset = SASS_MEMORY_NEW(StyleRule, pstate);
529
510
  // parse selector static or as schema to be evaluated later
530
- if (lookahead.parsable) ruleset->selector(parse_selector_list(false));
511
+ if (lookahead.parsable) {
512
+ ruleset->selector(parseSelectorList(false));
513
+ }
531
514
  else {
532
- Selector_List_Obj list = SASS_MEMORY_NEW(Selector_List, pstate);
533
- 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);
534
518
  ruleset->selector(list);
535
519
  }
536
520
  // then parse the inner block
@@ -556,21 +540,20 @@ namespace Sass {
556
540
  lex< optional_spaces >();
557
541
  const char* i = position;
558
542
  // selector schema re-uses string schema implementation
559
- String_Schema_Ptr schema = SASS_MEMORY_NEW(String_Schema, pstate);
543
+ String_Schema* schema = SASS_MEMORY_NEW(String_Schema, pstate);
560
544
  // the selector schema is pretty much just a wrapper for the string schema
561
545
  Selector_Schema_Obj selector_schema = SASS_MEMORY_NEW(Selector_Schema, pstate, schema);
562
546
  selector_schema->connect_parent(chroot == false);
563
- selector_schema->media_block(last_media_block);
564
547
 
565
548
  // process until end
566
549
  while (i < end_of_selector) {
567
- // try to parse mutliple interpolants
550
+ // try to parse multiple interpolants
568
551
  if (const char* p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, end_of_selector)) {
569
552
  // accumulate the preceding segment if the position has advanced
570
553
  if (i < p) {
571
- std::string parsed(i, p);
554
+ sass::string parsed(i, p);
572
555
  String_Constant_Obj str = SASS_MEMORY_NEW(String_Constant, pstate, parsed);
573
- pstate += Offset(parsed);
556
+ pstate.position += Offset(parsed);
574
557
  str->update_pstate(pstate);
575
558
  schema->append(str);
576
559
  }
@@ -583,15 +566,16 @@ namespace Sass {
583
566
  css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
584
567
  }
585
568
  // pass inner expression to the parser to resolve nested interpolations
586
- pstate.add(p, p+2);
587
- 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();
588
572
  // set status on the list expression
589
573
  interpolant->is_interpolant(true);
590
574
  // schema->has_interpolants(true);
591
575
  // add to the string schema
592
576
  schema->append(interpolant);
593
577
  // advance parser state
594
- pstate.add(p+2, j);
578
+ pstate.position.add(p+2, j);
595
579
  // advance position
596
580
  i = j;
597
581
  }
@@ -600,9 +584,9 @@ namespace Sass {
600
584
  else {
601
585
  // make sure to add the last bits of the string up to the end (if any)
602
586
  if (i < end_of_selector) {
603
- std::string parsed(i, end_of_selector);
587
+ sass::string parsed(i, end_of_selector);
604
588
  String_Constant_Obj str = SASS_MEMORY_NEW(String_Constant, pstate, parsed);
605
- pstate += Offset(parsed);
589
+ pstate.position += Offset(parsed);
606
590
  str->update_pstate(pstate);
607
591
  i = end_of_selector;
608
592
  schema->append(str);
@@ -619,7 +603,7 @@ namespace Sass {
619
603
  selector_schema->update_pstate(pstate);
620
604
  schema->update_pstate(pstate);
621
605
 
622
- after_token = before_token = pstate;
606
+ after_token = before_token = pstate.position;
623
607
 
624
608
  // return parsed result
625
609
  return selector_schema.detach();
@@ -643,239 +627,49 @@ namespace Sass {
643
627
  // lex identifier into `lexed` var
644
628
  lex_identifier(); // may error out
645
629
  // normalize underscores to hyphens
646
- std::string name(Util::normalize_underscores(lexed));
630
+ sass::string name(Util::normalize_underscores(lexed));
647
631
  // create the initial mixin call object
648
- Mixin_Call_Obj call = SASS_MEMORY_NEW(Mixin_Call, pstate, name, 0, 0);
632
+ Mixin_Call_Obj call = SASS_MEMORY_NEW(Mixin_Call, pstate, name, Arguments_Obj{});
649
633
  // parse mandatory arguments
650
634
  call->arguments(parse_arguments());
635
+ // parse using and optional block parameters
636
+ bool has_parameters = lex< kwd_using >() != nullptr;
637
+
638
+ if (has_parameters) {
639
+ if (!peek< exactly<'('> >()) css_error("Invalid CSS", " after ", ": expected \"(\", was ");
640
+ } else {
641
+ if (peek< exactly<'('> >()) css_error("Invalid CSS", " after ", ": expected \";\", was ");
642
+ }
643
+
644
+ if (has_parameters) call->block_parameters(parse_parameters());
645
+
651
646
  // parse optional block
652
647
  if (peek < exactly <'{'> >()) {
653
648
  call->block(parse_block());
654
649
  }
650
+ else if (has_parameters) {
651
+ css_error("Invalid CSS", " after ", ": expected \"{\", was ");
652
+ }
655
653
  // return ast node
656
654
  return call.detach();
657
655
  }
658
656
  // EO parse_include_directive
659
657
 
660
- // parse a list of complex selectors
661
- // this is the main entry point for most
662
- Selector_List_Obj Parser::parse_selector_list(bool chroot)
663
- {
664
- bool reloop;
665
- bool had_linefeed = false;
666
- NESTING_GUARD(nestings);
667
- Complex_Selector_Obj sel;
668
- Selector_List_Obj group = SASS_MEMORY_NEW(Selector_List, pstate);
669
- group->media_block(last_media_block);
670
-
671
- if (peek_css< alternatives < end_of_file, exactly <'{'>, exactly <','> > >()) {
672
- css_error("Invalid CSS", " after ", ": expected selector, was ");
673
- }
674
-
675
- do {
676
- reloop = false;
677
-
678
- had_linefeed = had_linefeed || peek_newline();
679
-
680
- if (peek_css< alternatives < class_char < selector_list_delims > > >())
681
- break; // in case there are superfluous commas at the end
682
-
683
- // now parse the complex selector
684
- sel = parse_complex_selector(chroot);
685
-
686
- if (!sel) return group.detach();
687
-
688
- sel->has_line_feed(had_linefeed);
689
658
 
690
- had_linefeed = false;
691
-
692
- while (peek_css< exactly<','> >())
693
- {
694
- lex< css_comments >(false);
695
- // consume everything up and including the comma separator
696
- reloop = lex< exactly<','> >() != 0;
697
- // remember line break (also between some commas)
698
- had_linefeed = had_linefeed || peek_newline();
699
- // remember line break (also between some commas)
700
- }
701
- group->append(sel);
702
- }
703
- while (reloop);
704
- while (lex_css< kwd_optional >()) {
705
- group->is_optional(true);
706
- }
707
- // update for end position
708
- group->update_pstate(pstate);
709
- if (sel) sel->last()->has_line_break(false);
710
- return group.detach();
711
- }
712
- // EO parse_selector_list
713
-
714
- // a complex selector combines a compound selector with another
715
- // complex selector, with one of four combinator operations.
716
- // the compound selector (head) is optional, since the combinator
717
- // can come first in the whole selector sequence (like `> DIV').
718
- Complex_Selector_Obj Parser::parse_complex_selector(bool chroot)
719
- {
720
-
721
- NESTING_GUARD(nestings);
722
- String_Obj reference = 0;
723
- lex < block_comment >();
724
- advanceToNextToken();
725
- Complex_Selector_Obj sel = SASS_MEMORY_NEW(Complex_Selector, pstate);
726
-
727
- if (peek < end_of_file >()) return 0;
728
-
729
- // parse the left hand side
730
- Compound_Selector_Obj lhs;
731
- // special case if it starts with combinator ([+~>])
732
- if (!peek_css< class_char < selector_combinator_ops > >()) {
733
- // parse the left hand side
734
- lhs = parse_compound_selector();
735
- }
736
-
737
-
738
- // parse combinator between lhs and rhs
739
- Complex_Selector::Combinator combinator = Complex_Selector::ANCESTOR_OF;
740
- if (lex< exactly<'+'> >()) combinator = Complex_Selector::ADJACENT_TO;
741
- else if (lex< exactly<'~'> >()) combinator = Complex_Selector::PRECEDES;
742
- else if (lex< exactly<'>'> >()) combinator = Complex_Selector::PARENT_OF;
743
- else if (lex< sequence < exactly<'/'>, negate < exactly < '*' > > > >()) {
744
- // comments are allowed, but not spaces?
745
- combinator = Complex_Selector::REFERENCE;
746
- if (!lex < re_reference_combinator >()) return 0;
747
- reference = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
748
- if (!lex < exactly < '/' > >()) return 0; // ToDo: error msg?
749
- }
750
-
751
- if (!lhs && combinator == Complex_Selector::ANCESTOR_OF) return 0;
752
-
753
- // lex < block_comment >();
754
- sel->head(lhs);
755
- sel->combinator(combinator);
756
- sel->media_block(last_media_block);
757
-
758
- if (combinator == Complex_Selector::REFERENCE) sel->reference(reference);
759
- // has linfeed after combinator?
760
- sel->has_line_break(peek_newline());
761
- // sel->has_line_feed(has_line_feed);
762
-
763
- // check if we got the abort condition (ToDo: optimize)
764
- if (!peek_css< class_char < complex_selector_delims > >()) {
765
- // parse next selector in sequence
766
- sel->tail(parse_complex_selector(true));
767
- }
768
-
769
- // add a parent selector if we are not in a root
770
- // also skip adding parent ref if we only have refs
771
- if (!sel->has_parent_ref() && !chroot) {
772
- // create the objects to wrap parent selector reference
773
- Compound_Selector_Obj head = SASS_MEMORY_NEW(Compound_Selector, pstate);
774
- Parent_Selector_Ptr parent = SASS_MEMORY_NEW(Parent_Selector, pstate, false);
775
- parent->media_block(last_media_block);
776
- head->media_block(last_media_block);
777
- // add simple selector
778
- head->append(parent);
779
- // selector may not have any head yet
780
- if (!sel->head()) { sel->head(head); }
781
- // otherwise we need to create a new complex selector and set the old one as its tail
782
- else {
783
- sel = SASS_MEMORY_NEW(Complex_Selector, pstate, Complex_Selector::ANCESTOR_OF, head, sel);
784
- sel->media_block(last_media_block);
785
- }
786
- // peek for linefeed and remember result on head
787
- // if (peek_newline()) head->has_line_break(true);
788
- }
789
-
790
- sel->update_pstate(pstate);
791
- // complex selector
792
- return sel;
793
- }
794
- // EO parse_complex_selector
795
-
796
- // parse one compound selector, which is basically
797
- // a list of simple selectors (directly adjacent)
798
- // lex them exactly (without skipping white-space)
799
- Compound_Selector_Obj Parser::parse_compound_selector()
800
- {
801
- // init an empty compound selector wrapper
802
- Compound_Selector_Obj seq = SASS_MEMORY_NEW(Compound_Selector, pstate);
803
- seq->media_block(last_media_block);
804
-
805
- // skip initial white-space
806
- lex< css_whitespace >();
807
-
808
- // parse list
809
- while (true)
810
- {
811
- // remove all block comments (don't skip white-space)
812
- lex< delimited_by< slash_star, star_slash, false > >(false);
813
- // parse functional
814
- if (match < re_pseudo_selector >())
815
- {
816
- seq->append(parse_simple_selector());
817
- }
818
- // parse parent selector
819
- else if (lex< exactly<'&'> >(false))
820
- {
821
- // this produces a linefeed!?
822
- seq->has_parent_reference(true);
823
- seq->append(SASS_MEMORY_NEW(Parent_Selector, pstate));
824
- // parent selector only allowed at start
825
- // upcoming Sass may allow also trailing
826
- if (seq->length() > 1) {
827
- ParserState state(pstate);
828
- Simple_Selector_Obj cur = (*seq)[seq->length()-1];
829
- Simple_Selector_Obj prev = (*seq)[seq->length()-2];
830
- std::string sel(prev->to_string({ NESTED, 5 }));
831
- std::string found(cur->to_string({ NESTED, 5 }));
832
- if (lex < identifier >()) { found += std::string(lexed); }
833
- error("Invalid CSS after \"" + sel + "\": expected \"{\", was \"" + found + "\"\n\n"
834
- "\"" + found + "\" may only be used at the beginning of a compound selector.", state);
835
- }
836
- }
837
- // parse type selector
838
- else if (lex< re_type_selector >(false))
839
- {
840
- seq->append(SASS_MEMORY_NEW(Element_Selector, pstate, lexed));
841
- }
842
- // peek for abort conditions
843
- else if (peek< spaces >()) break;
844
- else if (peek< end_of_file >()) { break; }
845
- else if (peek_css < class_char < selector_combinator_ops > >()) break;
846
- else if (peek_css < class_char < complex_selector_delims > >()) break;
847
- // otherwise parse another simple selector
848
- else {
849
- Simple_Selector_Obj sel = parse_simple_selector();
850
- if (!sel) return 0;
851
- seq->append(sel);
852
- }
853
- }
854
-
855
- if (seq && !peek_css<alternatives<end_of_file,exactly<'{'>>>()) {
856
- seq->has_line_break(peek_newline());
857
- }
858
-
859
- // EO while true
860
- return seq;
861
-
862
- }
863
- // EO parse_compound_selector
864
-
865
- Simple_Selector_Obj Parser::parse_simple_selector()
659
+ SimpleSelectorObj Parser::parse_simple_selector()
866
660
  {
867
661
  lex < css_comments >(false);
868
662
  if (lex< class_name >()) {
869
- return SASS_MEMORY_NEW(Class_Selector, pstate, lexed);
663
+ return SASS_MEMORY_NEW(ClassSelector, pstate, lexed);
870
664
  }
871
665
  else if (lex< id_name >()) {
872
- return SASS_MEMORY_NEW(Id_Selector, pstate, lexed);
666
+ return SASS_MEMORY_NEW(IDSelector, pstate, lexed);
873
667
  }
874
668
  else if (lex< alternatives < variable, number, static_reference_combinator > >()) {
875
- return SASS_MEMORY_NEW(Element_Selector, pstate, lexed);
669
+ return SASS_MEMORY_NEW(TypeSelector, pstate, lexed);
876
670
  }
877
671
  else if (peek< pseudo_not >()) {
878
- return parse_negated_selector();
672
+ return parse_negated_selector2();
879
673
  }
880
674
  else if (peek< re_pseudo_selector >()) {
881
675
  return parse_pseudo_selector();
@@ -887,86 +681,117 @@ namespace Sass {
887
681
  return parse_attribute_selector();
888
682
  }
889
683
  else if (lex< placeholder >()) {
890
- Placeholder_Selector_Ptr sel = SASS_MEMORY_NEW(Placeholder_Selector, pstate, lexed);
891
- sel->media_block(last_media_block);
892
- return sel;
684
+ return SASS_MEMORY_NEW(PlaceholderSelector, pstate, lexed);
893
685
  }
894
686
  else {
895
687
  css_error("Invalid CSS", " after ", ": expected selector, was ");
896
688
  }
897
689
  // failed
898
- return 0;
690
+ return {};
899
691
  }
900
692
 
901
- Wrapped_Selector_Obj Parser::parse_negated_selector()
693
+ PseudoSelectorObj Parser::parse_negated_selector2()
902
694
  {
903
695
  lex< pseudo_not >();
904
- std::string name(lexed);
905
- ParserState nsource_position = pstate;
906
- Selector_List_Obj negated = parse_selector_list(true);
696
+ sass::string name(lexed);
697
+ SourceSpan nsource_position = pstate;
698
+ SelectorListObj negated = parseSelectorList(true);
907
699
  if (!lex< exactly<')'> >()) {
908
700
  error("negated selector is missing ')'");
909
701
  }
910
702
  name.erase(name.size() - 1);
911
- 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;
912
707
  }
913
708
 
709
+ // Helper to clean binominal string
710
+ bool BothAreSpaces(char lhs, char rhs) { return isspace(lhs) && isspace(rhs); }
711
+
914
712
  // a pseudo selector often starts with one or two colons
915
713
  // it can contain more selectors inside parentheses
916
- Simple_Selector_Obj Parser::parse_pseudo_selector() {
917
- if (lex< sequence<
918
- optional < pseudo_prefix >,
919
- // we keep the space within the name, strange enough
920
- // ToDo: refactor output to schedule the space for it
921
- // or do we really want to keep the real white-space?
922
- sequence< identifier, optional < block_comment >, exactly<'('> >
923
- > >())
924
- {
925
-
926
- std::string name(lexed);
927
- name.erase(name.size() - 1);
928
- 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
+ {
929
729
 
930
- // specially parse static stuff
931
- // ToDo: really everything static?
932
- if (peek_css <
933
- sequence <
934
- alternatives <
935
- static_value,
936
- binomial
937
- >,
938
- optional_css_whitespace,
939
- exactly<')'>
940
- >
941
- >()
942
- ) {
943
- lex_css< alternatives < static_value, binomial > >();
944
- String_Constant_Obj expr = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
945
- if (lex_css< exactly<')'> >()) {
946
- expr->can_compress_whitespace(true);
947
- 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
+ }
948
747
  }
949
- }
950
- else if (Selector_List_Obj wrapped = parse_selector_list(true)) {
951
- if (wrapped && lex_css< exactly<')'> >()) {
952
- 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
+ }
953
772
  }
773
+
954
774
  }
775
+ // EO if pseudo selector
955
776
 
956
- }
957
- // 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
+ }
958
783
 
959
- else if (lex < sequence< optional < pseudo_prefix >, identifier > >()) {
960
- return SASS_MEMORY_NEW(Pseudo_Selector, pstate, lexed);
961
784
  }
962
- else if(lex < pseudo_prefix >()) {
963
- 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 ");
964
788
  }
965
789
 
790
+
966
791
  css_error("Invalid CSS", " after ", ": expected \")\", was ");
967
792
 
968
793
  // unreachable statement
969
- return 0;
794
+ return {};
970
795
  }
971
796
 
972
797
  const char* Parser::re_attr_sensitive_close(const char* src)
@@ -979,25 +804,25 @@ namespace Sass {
979
804
  return sequence < insensitive<'i'>, re_attr_sensitive_close >(src);
980
805
  }
981
806
 
982
- Attribute_Selector_Obj Parser::parse_attribute_selector()
807
+ AttributeSelectorObj Parser::parse_attribute_selector()
983
808
  {
984
- ParserState p = pstate;
809
+ SourceSpan p = pstate;
985
810
  if (!lex_css< attribute_name >()) error("invalid attribute name in attribute selector");
986
- std::string name(lexed);
811
+ sass::string name(lexed);
987
812
  if (lex_css< re_attr_sensitive_close >()) {
988
- return SASS_MEMORY_NEW(Attribute_Selector, p, name, "", 0, 0);
813
+ return SASS_MEMORY_NEW(AttributeSelector, p, name, "", String_Obj{});
989
814
  }
990
815
  else if (lex_css< re_attr_insensitive_close >()) {
991
816
  char modifier = lexed.begin[0];
992
- return SASS_MEMORY_NEW(Attribute_Selector, p, name, "", 0, modifier);
817
+ return SASS_MEMORY_NEW(AttributeSelector, p, name, "", String_Obj{}, modifier);
993
818
  }
994
819
  if (!lex_css< alternatives< exact_match, class_match, dash_match,
995
820
  prefix_match, suffix_match, substring_match > >()) {
996
821
  error("invalid operator in attribute selector for " + name);
997
822
  }
998
- std::string matcher(lexed);
823
+ sass::string matcher(lexed);
999
824
 
1000
- String_Obj value = 0;
825
+ String_Obj value;
1001
826
  if (lex_css< identifier >()) {
1002
827
  value = SASS_MEMORY_NEW(String_Constant, p, lexed);
1003
828
  }
@@ -1009,18 +834,18 @@ namespace Sass {
1009
834
  }
1010
835
 
1011
836
  if (lex_css< re_attr_sensitive_close >()) {
1012
- return SASS_MEMORY_NEW(Attribute_Selector, p, name, matcher, value, 0);
837
+ return SASS_MEMORY_NEW(AttributeSelector, p, name, matcher, value, 0);
1013
838
  }
1014
839
  else if (lex_css< re_attr_insensitive_close >()) {
1015
840
  char modifier = lexed.begin[0];
1016
- return SASS_MEMORY_NEW(Attribute_Selector, p, name, matcher, value, modifier);
841
+ return SASS_MEMORY_NEW(AttributeSelector, p, name, matcher, value, modifier);
1017
842
  }
1018
843
  error("unterminated attribute selector for " + name);
1019
- return NULL; // to satisfy compilers (error must not return)
844
+ return {}; // to satisfy compilers (error must not return)
1020
845
  }
1021
846
 
1022
847
  /* parse block comment and add to block */
1023
- void Parser::parse_block_comments()
848
+ void Parser::parse_block_comments(bool store)
1024
849
  {
1025
850
  Block_Obj block = block_stack.back();
1026
851
 
@@ -1028,7 +853,7 @@ namespace Sass {
1028
853
  bool is_important = lexed.begin[2] == '!';
1029
854
  // flag on second param is to skip loosely over comments
1030
855
  String_Obj contents = parse_interpolated_chunk(lexed, true, false);
1031
- block->append(SASS_MEMORY_NEW(Comment, pstate, contents, is_important));
856
+ if (store) block->append(SASS_MEMORY_NEW(Comment, pstate, contents, is_important));
1032
857
  }
1033
858
  }
1034
859
 
@@ -1036,12 +861,12 @@ namespace Sass {
1036
861
  String_Obj prop;
1037
862
  bool is_custom_property = false;
1038
863
  if (lex< sequence< optional< exactly<'*'> >, identifier_schema > >()) {
1039
- const std::string property(lexed);
864
+ const sass::string property(lexed);
1040
865
  is_custom_property = property.compare(0, 2, "--") == 0;
1041
866
  prop = parse_identifier_schema();
1042
867
  }
1043
868
  else if (lex< sequence< optional< exactly<'*'> >, identifier, zero_plus< block_comment > > >()) {
1044
- const std::string property(lexed);
869
+ const sass::string property(lexed);
1045
870
  is_custom_property = property.compare(0, 2, "--") == 0;
1046
871
  prop = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
1047
872
  }
@@ -1049,7 +874,7 @@ namespace Sass {
1049
874
  css_error("Invalid CSS", " after ", ": expected \"}\", was ");
1050
875
  }
1051
876
  bool is_indented = true;
1052
- const std::string property(lexed);
877
+ const sass::string property(lexed);
1053
878
  if (!lex_css< one_plus< exactly<':'> > >()) error("property \"" + escape_string(property) + "\" must be followed by a ':'");
1054
879
  if (!is_custom_property && match< sequence< optional_css_comments, exactly<';'> > >()) error("style declaration must contain a value");
1055
880
  if (match< sequence< optional_css_comments, exactly<'{'> > >()) is_indented = false; // don't indent if value is empty
@@ -1061,7 +886,7 @@ namespace Sass {
1061
886
  return SASS_MEMORY_NEW(Declaration, prop->pstate(), prop, parse_static_value()/*, lex<kwd_important>()*/);
1062
887
  }
1063
888
  else {
1064
- Expression_Obj value;
889
+ ExpressionObj value;
1065
890
  Lookahead lookahead = lookahead_for_value(position);
1066
891
  if (lookahead.found) {
1067
892
  if (lookahead.has_interpolants) {
@@ -1072,7 +897,7 @@ namespace Sass {
1072
897
  }
1073
898
  else {
1074
899
  value = parse_list(DELAYED);
1075
- if (List_Ptr list = Cast<List>(value)) {
900
+ if (List* list = Cast<List>(value)) {
1076
901
  if (!list->is_bracketed() && list->length() == 0 && !peek< exactly <'{'> >()) {
1077
902
  css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
1078
903
  }
@@ -1086,27 +911,10 @@ namespace Sass {
1086
911
  }
1087
912
  }
1088
913
 
1089
- // parse +/- and return false if negative
1090
- // this is never hit via spec tests
1091
- bool Parser::parse_number_prefix()
1092
- {
1093
- bool positive = true;
1094
- while(true) {
1095
- if (lex < block_comment >()) continue;
1096
- if (lex < number_prefix >()) continue;
1097
- if (lex < exactly < '-' > >()) {
1098
- positive = !positive;
1099
- continue;
1100
- }
1101
- break;
1102
- }
1103
- return positive;
1104
- }
1105
-
1106
- Expression_Obj Parser::parse_map()
914
+ ExpressionObj Parser::parse_map()
1107
915
  {
1108
916
  NESTING_GUARD(nestings);
1109
- Expression_Obj key = parse_list();
917
+ ExpressionObj key = parse_list();
1110
918
  List_Obj map = SASS_MEMORY_NEW(List, pstate, 0, SASS_HASH);
1111
919
 
1112
920
  // it's not a map so return the lexed value as a list value
@@ -1118,7 +926,7 @@ namespace Sass {
1118
926
  css_error("Invalid CSS", " after ", ": expected \")\", was ");
1119
927
  }
1120
928
 
1121
- Expression_Obj value = parse_space_list();
929
+ ExpressionObj value = parse_space_list();
1122
930
 
1123
931
  map->append(key);
1124
932
  map->append(value);
@@ -1140,14 +948,14 @@ namespace Sass {
1140
948
  map->append(value);
1141
949
  }
1142
950
 
1143
- ParserState ps = map->pstate();
1144
- ps.offset = pstate - ps + pstate.offset;
951
+ SourceSpan ps = map->pstate();
952
+ ps.offset = pstate.position - ps.position + pstate.offset;
1145
953
  map->pstate(ps);
1146
954
 
1147
955
  return map;
1148
956
  }
1149
957
 
1150
- Expression_Obj Parser::parse_bracket_list()
958
+ ExpressionObj Parser::parse_bracket_list()
1151
959
  {
1152
960
  NESTING_GUARD(nestings);
1153
961
  // check if we have an empty list
@@ -1161,7 +969,7 @@ namespace Sass {
1161
969
  bool has_paren = peek_css< exactly<'('> >() != NULL;
1162
970
 
1163
971
  // now try to parse a space list
1164
- Expression_Obj list = parse_space_list();
972
+ ExpressionObj list = parse_space_list();
1165
973
  // if it's a singleton, return it (don't wrap it)
1166
974
  if (!peek_css< exactly<','> >(position)) {
1167
975
  List_Obj l = Cast<List>(list);
@@ -1194,14 +1002,14 @@ namespace Sass {
1194
1002
  // parse list returns either a space separated list,
1195
1003
  // a comma separated list or any bare expression found.
1196
1004
  // so to speak: we unwrap items from lists if possible here!
1197
- Expression_Obj Parser::parse_list(bool delayed)
1005
+ ExpressionObj Parser::parse_list(bool delayed)
1198
1006
  {
1199
1007
  NESTING_GUARD(nestings);
1200
1008
  return parse_comma_list(delayed);
1201
1009
  }
1202
1010
 
1203
1011
  // will return singletons unwrapped
1204
- Expression_Obj Parser::parse_comma_list(bool delayed)
1012
+ ExpressionObj Parser::parse_comma_list(bool delayed)
1205
1013
  {
1206
1014
  NESTING_GUARD(nestings);
1207
1015
  // check if we have an empty list
@@ -1213,7 +1021,7 @@ namespace Sass {
1213
1021
  }
1214
1022
 
1215
1023
  // now try to parse a space list
1216
- Expression_Obj list = parse_space_list();
1024
+ ExpressionObj list = parse_space_list();
1217
1025
  // if it's a singleton, return it (don't wrap it)
1218
1026
  if (!peek_css< exactly<','> >(position)) {
1219
1027
  // set_delay doesn't apply to list children
@@ -1241,10 +1049,10 @@ namespace Sass {
1241
1049
  // EO parse_comma_list
1242
1050
 
1243
1051
  // will return singletons unwrapped
1244
- Expression_Obj Parser::parse_space_list()
1052
+ ExpressionObj Parser::parse_space_list()
1245
1053
  {
1246
1054
  NESTING_GUARD(nestings);
1247
- Expression_Obj disj1 = parse_disjunction();
1055
+ ExpressionObj disj1 = parse_disjunction();
1248
1056
  // if it's a singleton, return it (don't wrap it)
1249
1057
  if (peek_css< space_list_terminator >(position)
1250
1058
  ) {
@@ -1266,60 +1074,60 @@ namespace Sass {
1266
1074
  // EO parse_space_list
1267
1075
 
1268
1076
  // parse logical OR operation
1269
- Expression_Obj Parser::parse_disjunction()
1077
+ ExpressionObj Parser::parse_disjunction()
1270
1078
  {
1271
1079
  NESTING_GUARD(nestings);
1272
1080
  advanceToNextToken();
1273
- ParserState state(pstate);
1081
+ SourceSpan state(pstate);
1274
1082
  // parse the left hand side conjunction
1275
- Expression_Obj conj = parse_conjunction();
1083
+ ExpressionObj conj = parse_conjunction();
1276
1084
  // parse multiple right hand sides
1277
- std::vector<Expression_Obj> operands;
1085
+ sass::vector<ExpressionObj> operands;
1278
1086
  while (lex_css< kwd_or >())
1279
1087
  operands.push_back(parse_conjunction());
1280
1088
  // if it's a singleton, return it directly
1281
1089
  if (operands.size() == 0) return conj;
1282
1090
  // fold all operands into one binary expression
1283
- Expression_Obj ex = fold_operands(conj, operands, { Sass_OP::OR });
1284
- 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;
1285
1093
  ex->pstate(state);
1286
1094
  return ex;
1287
1095
  }
1288
1096
  // EO parse_disjunction
1289
1097
 
1290
1098
  // parse logical AND operation
1291
- Expression_Obj Parser::parse_conjunction()
1099
+ ExpressionObj Parser::parse_conjunction()
1292
1100
  {
1293
1101
  NESTING_GUARD(nestings);
1294
1102
  advanceToNextToken();
1295
- ParserState state(pstate);
1103
+ SourceSpan state(pstate);
1296
1104
  // parse the left hand side relation
1297
- Expression_Obj rel = parse_relation();
1105
+ ExpressionObj rel = parse_relation();
1298
1106
  // parse multiple right hand sides
1299
- std::vector<Expression_Obj> operands;
1107
+ sass::vector<ExpressionObj> operands;
1300
1108
  while (lex_css< kwd_and >()) {
1301
1109
  operands.push_back(parse_relation());
1302
1110
  }
1303
1111
  // if it's a singleton, return it directly
1304
1112
  if (operands.size() == 0) return rel;
1305
1113
  // fold all operands into one binary expression
1306
- Expression_Obj ex = fold_operands(rel, operands, { Sass_OP::AND });
1307
- 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;
1308
1116
  ex->pstate(state);
1309
1117
  return ex;
1310
1118
  }
1311
1119
  // EO parse_conjunction
1312
1120
 
1313
1121
  // parse comparison operations
1314
- Expression_Obj Parser::parse_relation()
1122
+ ExpressionObj Parser::parse_relation()
1315
1123
  {
1316
1124
  NESTING_GUARD(nestings);
1317
1125
  advanceToNextToken();
1318
- ParserState state(pstate);
1126
+ SourceSpan state(pstate);
1319
1127
  // parse the left hand side expression
1320
- Expression_Obj lhs = parse_expression();
1321
- std::vector<Expression_Obj> operands;
1322
- std::vector<Operand> operators;
1128
+ ExpressionObj lhs = parse_expression();
1129
+ sass::vector<ExpressionObj> operands;
1130
+ sass::vector<Operand> operators;
1323
1131
  // if it's a singleton, return it (don't wrap it)
1324
1132
  while (peek< alternatives <
1325
1133
  kwd_eq,
@@ -1352,8 +1160,8 @@ namespace Sass {
1352
1160
  // correctly set to zero. After folding we also unwrap
1353
1161
  // single nested items. So we cannot set delay on the
1354
1162
  // returned result here, as we have lost nestings ...
1355
- Expression_Obj ex = fold_operands(lhs, operands, operators);
1356
- state.offset = pstate - state + pstate.offset;
1163
+ ExpressionObj ex = fold_operands(lhs, operands, operators);
1164
+ state.offset = pstate.position - state.position + pstate.offset;
1357
1165
  ex->pstate(state);
1358
1166
  return ex;
1359
1167
  }
@@ -1364,25 +1172,25 @@ namespace Sass {
1364
1172
  // called from parse_for_directive
1365
1173
  // called from parse_media_expression
1366
1174
  // parse addition and subtraction operations
1367
- Expression_Obj Parser::parse_expression()
1175
+ ExpressionObj Parser::parse_expression()
1368
1176
  {
1369
1177
  NESTING_GUARD(nestings);
1370
1178
  advanceToNextToken();
1371
- ParserState state(pstate);
1179
+ SourceSpan state(pstate);
1372
1180
  // parses multiple add and subtract operations
1373
1181
  // NOTE: make sure that identifiers starting with
1374
1182
  // NOTE: dashes do NOT count as subtract operation
1375
- Expression_Obj lhs = parse_operators();
1183
+ ExpressionObj lhs = parse_operators();
1376
1184
  // if it's a singleton, return it (don't wrap it)
1377
1185
  if (!(peek_css< exactly<'+'> >(position) ||
1378
- // 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
1379
1187
  (peek< no_spaces >(position) && peek< sequence< negate< unsigned_number >, exactly<'-'>, negate< space > > >(position)) ||
1380
1188
  (peek< sequence< negate< unsigned_number >, exactly<'-'>, negate< unsigned_number > > >(position))) ||
1381
1189
  peek< sequence < zero_plus < exactly <'-' > >, identifier > >(position))
1382
1190
  { return lhs; }
1383
1191
 
1384
- std::vector<Expression_Obj> operands;
1385
- std::vector<Operand> operators;
1192
+ sass::vector<ExpressionObj> operands;
1193
+ sass::vector<Operand> operators;
1386
1194
  bool left_ws = peek < css_comments >() != NULL;
1387
1195
  while (
1388
1196
  lex_css< exactly<'+'> >() ||
@@ -1401,22 +1209,22 @@ namespace Sass {
1401
1209
  }
1402
1210
 
1403
1211
  if (operands.size() == 0) return lhs;
1404
- Expression_Obj ex = fold_operands(lhs, operands, operators);
1405
- state.offset = pstate - state + pstate.offset;
1212
+ ExpressionObj ex = fold_operands(lhs, operands, operators);
1213
+ state.offset = pstate.position - state.position + pstate.offset;
1406
1214
  ex->pstate(state);
1407
1215
  return ex;
1408
1216
  }
1409
1217
 
1410
1218
  // parse addition and subtraction operations
1411
- Expression_Obj Parser::parse_operators()
1219
+ ExpressionObj Parser::parse_operators()
1412
1220
  {
1413
1221
  NESTING_GUARD(nestings);
1414
1222
  advanceToNextToken();
1415
- ParserState state(pstate);
1416
- Expression_Obj factor = parse_factor();
1223
+ SourceSpan state(pstate);
1224
+ ExpressionObj factor = parse_factor();
1417
1225
  // if it's a singleton, return it (don't wrap it)
1418
- std::vector<Expression_Obj> operands; // factors
1419
- std::vector<Operand> operators; // ops
1226
+ sass::vector<ExpressionObj> operands; // factors
1227
+ sass::vector<Operand> operators; // ops
1420
1228
  // lex operations to apply to lhs
1421
1229
  const char* left_ws = peek < css_comments >();
1422
1230
  while (lex_css< class_char< static_ops > >()) {
@@ -1431,8 +1239,8 @@ namespace Sass {
1431
1239
  left_ws = peek < css_comments >();
1432
1240
  }
1433
1241
  // operands and operators to binary expression
1434
- Expression_Obj ex = fold_operands(factor, operands, operators);
1435
- state.offset = pstate - state + pstate.offset;
1242
+ ExpressionObj ex = fold_operands(factor, operands, operators);
1243
+ state.offset = pstate.position - state.position + pstate.offset;
1436
1244
  ex->pstate(state);
1437
1245
  return ex;
1438
1246
  }
@@ -1441,13 +1249,13 @@ namespace Sass {
1441
1249
 
1442
1250
  // called from parse_operators
1443
1251
  // called from parse_value_schema
1444
- Expression_Obj Parser::parse_factor()
1252
+ ExpressionObj Parser::parse_factor()
1445
1253
  {
1446
1254
  NESTING_GUARD(nestings);
1447
1255
  lex < css_comments >(false);
1448
1256
  if (lex_css< exactly<'('> >()) {
1449
1257
  // parse_map may return a list
1450
- Expression_Obj value = parse_map();
1258
+ ExpressionObj value = parse_map();
1451
1259
  // lex the expected closing parenthesis
1452
1260
  if (!lex_css< exactly<')'> >()) error("unclosed parenthesis");
1453
1261
  // expression can be evaluated
@@ -1455,7 +1263,7 @@ namespace Sass {
1455
1263
  }
1456
1264
  else if (lex_css< exactly<'['> >()) {
1457
1265
  // explicit bracketed
1458
- Expression_Obj value = parse_bracket_list();
1266
+ ExpressionObj value = parse_bracket_list();
1459
1267
  // lex the expected closing square bracket
1460
1268
  if (!lex_css< exactly<']'> >()) error("unclosed squared bracket");
1461
1269
  return value;
@@ -1478,7 +1286,7 @@ namespace Sass {
1478
1286
  }
1479
1287
  else if (lex< identifier_schema >()) {
1480
1288
  String_Obj string = parse_identifier_schema();
1481
- if (String_Schema_Ptr schema = Cast<String_Schema>(string)) {
1289
+ if (String_Schema* schema = Cast<String_Schema>(string)) {
1482
1290
  if (lex < exactly < '(' > >()) {
1483
1291
  schema->append(parse_list());
1484
1292
  lex < exactly < ')' > >();
@@ -1493,38 +1301,31 @@ namespace Sass {
1493
1301
  return parse_function_call();
1494
1302
  }
1495
1303
  else if (lex< exactly<'+'> >()) {
1496
- Unary_Expression_Ptr ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::PLUS, parse_factor());
1304
+ Unary_Expression* ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::PLUS, parse_factor());
1497
1305
  if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
1498
1306
  return ex;
1499
1307
  }
1500
1308
  else if (lex< exactly<'-'> >()) {
1501
- Unary_Expression_Ptr ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::MINUS, parse_factor());
1309
+ Unary_Expression* ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::MINUS, parse_factor());
1502
1310
  if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
1503
1311
  return ex;
1504
1312
  }
1505
1313
  else if (lex< exactly<'/'> >()) {
1506
- Unary_Expression_Ptr ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::SLASH, parse_factor());
1314
+ Unary_Expression* ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::SLASH, parse_factor());
1507
1315
  if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
1508
1316
  return ex;
1509
1317
  }
1510
1318
  else if (lex< sequence< kwd_not > >()) {
1511
- Unary_Expression_Ptr ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::NOT, parse_factor());
1319
+ Unary_Expression* ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::NOT, parse_factor());
1512
1320
  if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
1513
1321
  return ex;
1514
1322
  }
1515
- // this whole branch is never hit via spec tests
1516
- else if (peek < sequence < one_plus < alternatives < css_whitespace, exactly<'-'>, exactly<'+'> > >, number > >()) {
1517
- if (parse_number_prefix()) return parse_value(); // prefix is positive
1518
- Unary_Expression_Ptr ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::MINUS, parse_value());
1519
- if (ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
1520
- return ex;
1521
- }
1522
1323
  else {
1523
1324
  return parse_value();
1524
1325
  }
1525
1326
  }
1526
1327
 
1527
- bool number_has_zero(const std::string& parsed)
1328
+ bool number_has_zero(const sass::string& parsed)
1528
1329
  {
1529
1330
  size_t L = parsed.length();
1530
1331
  return !( (L > 0 && parsed.substr(0, 1) == ".") ||
@@ -1533,9 +1334,9 @@ namespace Sass {
1533
1334
  (L > 2 && parsed.substr(0, 3) == "-0.") );
1534
1335
  }
1535
1336
 
1536
- Number_Ptr Parser::lexed_number(const ParserState& pstate, const std::string& parsed)
1337
+ Number* Parser::lexed_number(const SourceSpan& pstate, const sass::string& parsed)
1537
1338
  {
1538
- Number_Ptr nr = SASS_MEMORY_NEW(Number,
1339
+ Number* nr = SASS_MEMORY_NEW(Number,
1539
1340
  pstate,
1540
1341
  sass_strtod(parsed.c_str()),
1541
1342
  "",
@@ -1545,9 +1346,9 @@ namespace Sass {
1545
1346
  return nr;
1546
1347
  }
1547
1348
 
1548
- Number_Ptr Parser::lexed_percentage(const ParserState& pstate, const std::string& parsed)
1349
+ Number* Parser::lexed_percentage(const SourceSpan& pstate, const sass::string& parsed)
1549
1350
  {
1550
- Number_Ptr nr = SASS_MEMORY_NEW(Number,
1351
+ Number* nr = SASS_MEMORY_NEW(Number,
1551
1352
  pstate,
1552
1353
  sass_strtod(parsed.c_str()),
1553
1354
  "%",
@@ -1557,18 +1358,18 @@ namespace Sass {
1557
1358
  return nr;
1558
1359
  }
1559
1360
 
1560
- Number_Ptr Parser::lexed_dimension(const ParserState& pstate, const std::string& parsed)
1361
+ Number* Parser::lexed_dimension(const SourceSpan& pstate, const sass::string& parsed)
1561
1362
  {
1562
1363
  size_t L = parsed.length();
1563
1364
  size_t num_pos = parsed.find_first_not_of(" \n\r\t");
1564
- if (num_pos == std::string::npos) num_pos = L;
1365
+ if (num_pos == sass::string::npos) num_pos = L;
1565
1366
  size_t unit_pos = parsed.find_first_not_of("-+0123456789.", num_pos);
1566
1367
  if (parsed[unit_pos] == 'e' && is_number(parsed[unit_pos+1]) ) {
1567
1368
  unit_pos = parsed.find_first_not_of("-+0123456789.", ++ unit_pos);
1568
1369
  }
1569
- if (unit_pos == std::string::npos) unit_pos = L;
1570
- const std::string& num = parsed.substr(num_pos, unit_pos - num_pos);
1571
- Number_Ptr nr = SASS_MEMORY_NEW(Number,
1370
+ if (unit_pos == sass::string::npos) unit_pos = L;
1371
+ const sass::string& num = parsed.substr(num_pos, unit_pos - num_pos);
1372
+ Number* nr = SASS_MEMORY_NEW(Number,
1572
1373
  pstate,
1573
1374
  sass_strtod(num.c_str()),
1574
1375
  Token(number(parsed.c_str())),
@@ -1578,19 +1379,19 @@ namespace Sass {
1578
1379
  return nr;
1579
1380
  }
1580
1381
 
1581
- Expression_Ptr Parser::lexed_hex_color(const ParserState& pstate, const std::string& parsed)
1382
+ Value* Parser::lexed_hex_color(const SourceSpan& pstate, const sass::string& parsed)
1582
1383
  {
1583
- Color_Ptr color = NULL;
1384
+ Color_RGBA* color = NULL;
1584
1385
  if (parsed[0] != '#') {
1585
1386
  return SASS_MEMORY_NEW(String_Quoted, pstate, parsed);
1586
1387
  }
1587
1388
  // chop off the '#'
1588
- std::string hext(parsed.substr(1));
1389
+ sass::string hext(parsed.substr(1));
1589
1390
  if (parsed.length() == 4) {
1590
- std::string r(2, parsed[1]);
1591
- std::string g(2, parsed[2]);
1592
- std::string b(2, parsed[3]);
1593
- color = SASS_MEMORY_NEW(Color,
1391
+ sass::string r(2, parsed[1]);
1392
+ sass::string g(2, parsed[2]);
1393
+ sass::string b(2, parsed[3]);
1394
+ color = SASS_MEMORY_NEW(Color_RGBA,
1594
1395
  pstate,
1595
1396
  static_cast<double>(strtol(r.c_str(), NULL, 16)),
1596
1397
  static_cast<double>(strtol(g.c_str(), NULL, 16)),
@@ -1598,11 +1399,24 @@ namespace Sass {
1598
1399
  1, // alpha channel
1599
1400
  parsed);
1600
1401
  }
1402
+ else if (parsed.length() == 5) {
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]);
1407
+ color = SASS_MEMORY_NEW(Color_RGBA,
1408
+ pstate,
1409
+ static_cast<double>(strtol(r.c_str(), NULL, 16)),
1410
+ static_cast<double>(strtol(g.c_str(), NULL, 16)),
1411
+ static_cast<double>(strtol(b.c_str(), NULL, 16)),
1412
+ static_cast<double>(strtol(a.c_str(), NULL, 16)) / 255,
1413
+ parsed);
1414
+ }
1601
1415
  else if (parsed.length() == 7) {
1602
- std::string r(parsed.substr(1,2));
1603
- std::string g(parsed.substr(3,2));
1604
- std::string b(parsed.substr(5,2));
1605
- color = SASS_MEMORY_NEW(Color,
1416
+ sass::string r(parsed.substr(1,2));
1417
+ sass::string g(parsed.substr(3,2));
1418
+ sass::string b(parsed.substr(5,2));
1419
+ color = SASS_MEMORY_NEW(Color_RGBA,
1606
1420
  pstate,
1607
1421
  static_cast<double>(strtol(r.c_str(), NULL, 16)),
1608
1422
  static_cast<double>(strtol(g.c_str(), NULL, 16)),
@@ -1611,11 +1425,11 @@ namespace Sass {
1611
1425
  parsed);
1612
1426
  }
1613
1427
  else if (parsed.length() == 9) {
1614
- std::string r(parsed.substr(1,2));
1615
- std::string g(parsed.substr(3,2));
1616
- std::string b(parsed.substr(5,2));
1617
- std::string a(parsed.substr(7,2));
1618
- color = SASS_MEMORY_NEW(Color,
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));
1432
+ color = SASS_MEMORY_NEW(Color_RGBA,
1619
1433
  pstate,
1620
1434
  static_cast<double>(strtol(r.c_str(), NULL, 16)),
1621
1435
  static_cast<double>(strtol(g.c_str(), NULL, 16)),
@@ -1628,8 +1442,21 @@ namespace Sass {
1628
1442
  return color;
1629
1443
  }
1630
1444
 
1445
+ Value* Parser::color_or_string(const sass::string& lexed) const
1446
+ {
1447
+ if (auto color = name_to_color(lexed)) {
1448
+ auto c = SASS_MEMORY_NEW(Color_RGBA, color);
1449
+ c->is_delayed(true);
1450
+ c->pstate(pstate);
1451
+ c->disp(lexed);
1452
+ return c;
1453
+ } else {
1454
+ return SASS_MEMORY_NEW(String_Constant, pstate, lexed);
1455
+ }
1456
+ }
1457
+
1631
1458
  // parse one value for a list
1632
- Expression_Obj Parser::parse_value()
1459
+ ExpressionObj Parser::parse_value()
1633
1460
  {
1634
1461
  lex< css_comments >(false);
1635
1462
  if (lex< ampersand >())
@@ -1637,7 +1464,7 @@ namespace Sass {
1637
1464
  if (match< ampersand >()) {
1638
1465
  warning("In Sass, \"&&\" means two copies of the parent selector. You probably want to use \"and\" instead.", pstate);
1639
1466
  }
1640
- return SASS_MEMORY_NEW(Parent_Selector, pstate); }
1467
+ return SASS_MEMORY_NEW(Parent_Reference, pstate); }
1641
1468
 
1642
1469
  if (lex< kwd_important >())
1643
1470
  { return SASS_MEMORY_NEW(String_Constant, pstate, "!important"); }
@@ -1670,7 +1497,7 @@ namespace Sass {
1670
1497
  { return SASS_MEMORY_NEW(Null, pstate); }
1671
1498
 
1672
1499
  if (lex< identifier >()) {
1673
- return SASS_MEMORY_NEW(String_Constant, pstate, lexed);
1500
+ return color_or_string(lexed);
1674
1501
  }
1675
1502
 
1676
1503
  if (lex< percentage >())
@@ -1681,17 +1508,7 @@ namespace Sass {
1681
1508
  { return lexed_hex_color(lexed); }
1682
1509
 
1683
1510
  if (lex< hexa >())
1684
- {
1685
- std::string s = lexed.to_string();
1686
-
1687
- deprecated(
1688
- "The value \""+s+"\" is currently parsed as a string, but it will be parsed as a color in",
1689
- "future versions of Sass. Use \"unquote('"+s+"')\" to continue parsing it as a string.",
1690
- true, pstate
1691
- );
1692
-
1693
- return SASS_MEMORY_NEW(String_Quoted, pstate, lexed);
1694
- }
1511
+ { return lexed_hex_color(lexed); }
1695
1512
 
1696
1513
  if (lex< sequence < exactly <'#'>, identifier > >())
1697
1514
  { return SASS_MEMORY_NEW(String_Quoted, pstate, lexed); }
@@ -1710,14 +1527,10 @@ namespace Sass {
1710
1527
  if (lex< variable >())
1711
1528
  { return SASS_MEMORY_NEW(Variable, pstate, Util::normalize_underscores(lexed)); }
1712
1529
 
1713
- // Special case handling for `%` proceeding an interpolant.
1714
- if (lex< sequence< exactly<'%'>, optional< percentage > > >())
1715
- { return SASS_MEMORY_NEW(String_Constant, pstate, lexed); }
1716
-
1717
1530
  css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
1718
1531
 
1719
1532
  // unreachable statement
1720
- return 0;
1533
+ return {};
1721
1534
  }
1722
1535
 
1723
1536
  // this parses interpolation inside other strings
@@ -1730,7 +1543,7 @@ namespace Sass {
1730
1543
  find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, chunk.end);
1731
1544
 
1732
1545
  if (!p) {
1733
- String_Quoted_Ptr 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);
1734
1547
  if (!constant && str_quoted->quote_mark()) str_quoted->quote_mark('*');
1735
1548
  return str_quoted;
1736
1549
  }
@@ -1743,7 +1556,7 @@ namespace Sass {
1743
1556
  if (p) {
1744
1557
  if (i < p) {
1745
1558
  // accumulate the preceding segment if it's nonempty
1746
- 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));
1747
1560
  }
1748
1561
  // we need to skip anything inside strings
1749
1562
  // create a new target in parser/prelexer
@@ -1753,7 +1566,9 @@ namespace Sass {
1753
1566
  const char* j = skip_over_scopes< exactly<hash_lbrace>, exactly<rbrace> >(p + 2, chunk.end); // find the closing brace
1754
1567
  if (j) { --j;
1755
1568
  // parse the interpolant and accumulate it
1756
- 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();
1757
1572
  interp_node->is_interpolant(true);
1758
1573
  schema->append(interp_node);
1759
1574
  i = j;
@@ -1765,7 +1580,7 @@ namespace Sass {
1765
1580
  }
1766
1581
  else { // no interpolants left; add the last segment if nonempty
1767
1582
  // check if we need quotes here (was not sure after merge)
1768
- 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));
1769
1584
  break;
1770
1585
  }
1771
1586
  ++ i;
@@ -1774,74 +1589,66 @@ namespace Sass {
1774
1589
  return schema.detach();
1775
1590
  }
1776
1591
 
1777
- String_Schema_Obj Parser::parse_css_variable_value(bool top_level)
1592
+ String_Schema_Obj Parser::parse_css_variable_value()
1778
1593
  {
1779
1594
  String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
1780
- String_Schema_Obj tok;
1781
- if (!(tok = parse_css_variable_value_token(top_level))) {
1782
- return NULL;
1783
- }
1784
-
1785
- schema->concat(tok);
1786
- while ((tok = parse_css_variable_value_token(top_level))) {
1787
- schema->concat(tok);
1788
- }
1789
-
1790
- return schema.detach();
1791
- }
1792
-
1793
- String_Schema_Obj Parser::parse_css_variable_value_token(bool top_level)
1794
- {
1795
- String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
1796
- if (
1797
- (top_level && lex< css_variable_top_level_value >(false)) ||
1798
- (!top_level && lex< css_variable_value >(false))
1799
- ) {
1800
- Token str(lexed);
1801
- schema->append(SASS_MEMORY_NEW(String_Constant, pstate, str));
1802
- }
1803
- else if (Expression_Obj tok = lex_interpolation()) {
1804
- if (String_Schema_Ptr s = Cast<String_Schema>(tok)) {
1805
- schema->concat(s);
1806
- } else {
1807
- schema->append(tok);
1808
- }
1809
- }
1810
- else if (lex< quoted_string >()) {
1811
- Expression_Obj tok = parse_string();
1812
- if (String_Schema_Ptr s = Cast<String_Schema>(tok)) {
1813
- schema->concat(s);
1814
- } else {
1815
- schema->append(tok);
1816
- }
1817
- }
1818
- else {
1819
- if (peek< alternatives< exactly<'('>, exactly<'['>, exactly<'{'> > >()) {
1820
- if (lex< exactly<'('> >()) {
1821
- schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string("(")));
1822
- if (String_Schema_Obj tok = parse_css_variable_value(false)) schema->concat(tok);
1823
- if (!lex< exactly<')'> >()) css_error("Invalid CSS", " after ", ": expected \")\", was ");
1824
- schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(")")));
1595
+ sass::vector<char> brackets;
1596
+ while (true) {
1597
+ if (
1598
+ (brackets.empty() && lex< css_variable_top_level_value >(false)) ||
1599
+ (!brackets.empty() && lex< css_variable_value >(false))
1600
+ ) {
1601
+ Token str(lexed);
1602
+ schema->append(SASS_MEMORY_NEW(String_Constant, pstate, str));
1603
+ } else if (ExpressionObj tok = lex_interpolation()) {
1604
+ if (String_Schema* s = Cast<String_Schema>(tok)) {
1605
+ if (s->empty()) break;
1606
+ schema->concat(s);
1607
+ } else {
1608
+ schema->append(tok);
1825
1609
  }
1826
- else if (lex< exactly<'['> >()) {
1827
- schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string("[")));
1828
- if (String_Schema_Obj tok = parse_css_variable_value(false)) schema->concat(tok);
1829
- if (!lex< exactly<']'> >()) css_error("Invalid CSS", " after ", ": expected \"]\", was ");
1830
- schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string("]")));
1610
+ } else if (lex< quoted_string >()) {
1611
+ ExpressionObj tok = parse_string();
1612
+ if (tok.isNull()) break;
1613
+ if (String_Schema* s = Cast<String_Schema>(tok)) {
1614
+ if (s->empty()) break;
1615
+ schema->concat(s);
1616
+ } else {
1617
+ schema->append(tok);
1831
1618
  }
1832
- else if (lex< exactly<'{'> >()) {
1833
- schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string("{")));
1834
- if (String_Schema_Obj tok = parse_css_variable_value(false)) schema->concat(tok);
1835
- if (!lex< exactly<'}'> >()) css_error("Invalid CSS", " after ", ": expected \"}\", was ");
1836
- schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string("}")));
1619
+ } else if (lex< alternatives< exactly<'('>, exactly<'['>, exactly<'{'> > >()) {
1620
+ const char opening_bracket = *(position - 1);
1621
+ brackets.push_back(opening_bracket);
1622
+ schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(1, opening_bracket)));
1623
+ } else if (const char *match = peek< alternatives< exactly<')'>, exactly<']'>, exactly<'}'> > >()) {
1624
+ if (brackets.empty()) break;
1625
+ const char closing_bracket = *(match - 1);
1626
+ if (brackets.back() != Util::opening_bracket_for(closing_bracket)) {
1627
+ sass::string message = ": expected \"";
1628
+ message += Util::closing_bracket_for(brackets.back());
1629
+ message += "\", was ";
1630
+ css_error("Invalid CSS", " after ", message);
1837
1631
  }
1632
+ lex< alternatives< exactly<')'>, exactly<']'>, exactly<'}'> > >();
1633
+ schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(1, closing_bracket)));
1634
+ brackets.pop_back();
1635
+ } else {
1636
+ break;
1838
1637
  }
1839
1638
  }
1840
1639
 
1841
- return schema->length() > 0 ? schema.detach() : NULL;
1640
+ if (!brackets.empty()) {
1641
+ sass::string message = ": expected \"";
1642
+ message += Util::closing_bracket_for(brackets.back());
1643
+ message += "\", was ";
1644
+ css_error("Invalid CSS", " after ", message);
1645
+ }
1646
+
1647
+ if (schema->empty()) error("Custom property values may not be empty.");
1648
+ return schema.detach();
1842
1649
  }
1843
1650
 
1844
- String_Constant_Obj Parser::parse_static_value()
1651
+ ValueObj Parser::parse_static_value()
1845
1652
  {
1846
1653
  lex< static_value >();
1847
1654
  Token str(lexed);
@@ -1852,8 +1659,7 @@ namespace Sass {
1852
1659
  --str.end;
1853
1660
  --position;
1854
1661
 
1855
- String_Constant_Ptr str_node = SASS_MEMORY_NEW(String_Constant, pstate, str.time_wspace());
1856
- return str_node;
1662
+ return color_or_string(str.time_wspace());;
1857
1663
  }
1858
1664
 
1859
1665
  String_Obj Parser::parse_string()
@@ -1869,15 +1675,15 @@ namespace Sass {
1869
1675
  // see if there any interpolants
1870
1676
  const char* p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(str.begin, str.end);
1871
1677
  if (!p) {
1872
- 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));
1873
1679
  }
1874
1680
 
1875
- String_Schema_Ptr schema = SASS_MEMORY_NEW(String_Schema, pstate);
1681
+ String_Schema* schema = SASS_MEMORY_NEW(String_Schema, pstate);
1876
1682
  while (i < str.end) {
1877
1683
  p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, str.end);
1878
1684
  if (p) {
1879
1685
  if (i < p) {
1880
- 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
1881
1687
  }
1882
1688
  if (peek < sequence < optional_spaces, exactly<rbrace> > >(p+2)) { position = p+2;
1883
1689
  css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
@@ -1885,7 +1691,9 @@ namespace Sass {
1885
1691
  const char* j = skip_over_scopes< exactly<hash_lbrace>, exactly<rbrace> >(p+2, str.end); // find the closing brace
1886
1692
  if (j) {
1887
1693
  // parse the interpolant and accumulate it
1888
- 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();
1889
1697
  interp_node->is_interpolant(true);
1890
1698
  schema->append(interp_node);
1891
1699
  i = j;
@@ -1897,7 +1705,7 @@ namespace Sass {
1897
1705
  }
1898
1706
  else { // no interpolants left; add the last segment if nonempty
1899
1707
  if (i < str.end) {
1900
- 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)));
1901
1709
  }
1902
1710
  break;
1903
1711
  }
@@ -1907,7 +1715,7 @@ namespace Sass {
1907
1715
 
1908
1716
  String_Obj Parser::parse_ie_keyword_arg()
1909
1717
  {
1910
- String_Schema_Ptr kwd_arg = SASS_MEMORY_NEW(String_Schema, pstate, 3);
1718
+ String_Schema_Obj kwd_arg = SASS_MEMORY_NEW(String_Schema, pstate, 3);
1911
1719
  if (lex< variable >()) {
1912
1720
  kwd_arg->append(SASS_MEMORY_NEW(Variable, pstate, Util::normalize_underscores(lexed)));
1913
1721
  } else {
@@ -1918,7 +1726,7 @@ namespace Sass {
1918
1726
  kwd_arg->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
1919
1727
  if (peek< variable >()) kwd_arg->append(parse_list());
1920
1728
  else if (lex< number >()) {
1921
- std::string parsed(lexed);
1729
+ sass::string parsed(lexed);
1922
1730
  Util::normalize_decimals(parsed);
1923
1731
  kwd_arg->append(lexed_number(parsed));
1924
1732
  }
@@ -1958,11 +1766,11 @@ namespace Sass {
1958
1766
  if (peek< exactly< rbrace > >()) {
1959
1767
  css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
1960
1768
  }
1961
- Expression_Obj ex;
1769
+ ExpressionObj ex;
1962
1770
  if (lex< re_static_expression >()) {
1963
1771
  ex = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
1964
1772
  } else {
1965
- ex = parse_list();
1773
+ ex = parse_list(true);
1966
1774
  }
1967
1775
  ex->is_interpolant(true);
1968
1776
  schema->append(ex);
@@ -1986,7 +1794,7 @@ namespace Sass {
1986
1794
  }
1987
1795
  if (peek < exactly < '-' > >()) break;
1988
1796
  }
1989
- else if (lex< sequence < identifier > >()) {
1797
+ else if (lex< identifier >()) {
1990
1798
  schema->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
1991
1799
  if ((*position == '"' || *position == '\'') || peek < alternatives < alpha > >()) {
1992
1800
  // need_space = true;
@@ -1994,7 +1802,7 @@ namespace Sass {
1994
1802
  }
1995
1803
  // lex (normalized) variable
1996
1804
  else if (lex< variable >()) {
1997
- std::string name(Util::normalize_underscores(lexed));
1805
+ sass::string name(Util::normalize_underscores(lexed));
1998
1806
  schema->append(SASS_MEMORY_NEW(Variable, pstate, name));
1999
1807
  }
2000
1808
  // lex percentage value
@@ -2026,7 +1834,7 @@ namespace Sass {
2026
1834
  ++num_items;
2027
1835
  }
2028
1836
  if (position != stop) {
2029
- 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)));
2030
1838
  position = stop;
2031
1839
  }
2032
1840
  end = ee;
@@ -2042,7 +1850,7 @@ namespace Sass {
2042
1850
  // see if there any interpolants
2043
1851
  const char* p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(id.begin, id.end);
2044
1852
  if (!p) {
2045
- 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));
2046
1854
  }
2047
1855
 
2048
1856
  String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
@@ -2063,7 +1871,9 @@ namespace Sass {
2063
1871
  const char* j = skip_over_scopes< exactly<hash_lbrace>, exactly<rbrace> >(p+2, id.end); // find the closing brace
2064
1872
  if (j) {
2065
1873
  // parse the interpolant and accumulate it
2066
- 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);
2067
1877
  interp_node->is_interpolant(true);
2068
1878
  schema->append(interp_node);
2069
1879
  // schema->has_interpolants(true);
@@ -2090,10 +1900,10 @@ namespace Sass {
2090
1900
  Function_Call_Obj Parser::parse_calc_function()
2091
1901
  {
2092
1902
  lex< identifier >();
2093
- std::string name(lexed);
2094
- ParserState call_pos = pstate;
1903
+ sass::string name(lexed);
1904
+ SourceSpan call_pos = pstate;
2095
1905
  lex< exactly<'('> >();
2096
- ParserState arg_pos = pstate;
1906
+ SourceSpan arg_pos = pstate;
2097
1907
  const char* arg_beg = position;
2098
1908
  parse_list();
2099
1909
  const char* arg_end = position;
@@ -2110,32 +1920,32 @@ namespace Sass {
2110
1920
 
2111
1921
  String_Obj Parser::parse_url_function_string()
2112
1922
  {
2113
- std::string prefix("");
1923
+ sass::string prefix("");
2114
1924
  if (lex< uri_prefix >()) {
2115
- prefix = std::string(lexed);
1925
+ prefix = sass::string(lexed);
2116
1926
  }
2117
1927
 
2118
1928
  lex < optional_spaces >();
2119
1929
  String_Obj url_string = parse_url_function_argument();
2120
1930
 
2121
- std::string suffix("");
1931
+ sass::string suffix("");
2122
1932
  if (lex< real_uri_suffix >()) {
2123
- suffix = std::string(lexed);
1933
+ suffix = sass::string(lexed);
2124
1934
  }
2125
1935
 
2126
- std::string uri("");
1936
+ sass::string uri("");
2127
1937
  if (url_string) {
2128
1938
  uri = url_string->to_string({ NESTED, 5 });
2129
1939
  }
2130
1940
 
2131
- if (String_Schema_Ptr schema = Cast<String_Schema>(url_string)) {
1941
+ if (String_Schema* schema = Cast<String_Schema>(url_string)) {
2132
1942
  String_Schema_Obj res = SASS_MEMORY_NEW(String_Schema, pstate);
2133
1943
  res->append(SASS_MEMORY_NEW(String_Constant, pstate, prefix));
2134
1944
  res->append(schema);
2135
1945
  res->append(SASS_MEMORY_NEW(String_Constant, pstate, suffix));
2136
1946
  return res;
2137
1947
  } else {
2138
- std::string res = prefix + uri + suffix;
1948
+ sass::string res = prefix + uri + suffix;
2139
1949
  return SASS_MEMORY_NEW(String_Constant, pstate, res);
2140
1950
  }
2141
1951
  }
@@ -2144,7 +1954,7 @@ namespace Sass {
2144
1954
  {
2145
1955
  const char* p = position;
2146
1956
 
2147
- std::string uri("");
1957
+ sass::string uri("");
2148
1958
  if (lex< real_uri_value >(false)) {
2149
1959
  uri = lexed.to_string();
2150
1960
  }
@@ -2155,52 +1965,56 @@ namespace Sass {
2155
1965
  while (pp && peek< exactly< hash_lbrace > >(pp)) {
2156
1966
  pp = sequence< interpolant, real_uri_value >(pp);
2157
1967
  }
1968
+ if (!pp) return {};
2158
1969
  position = pp;
2159
1970
  return parse_interpolated_chunk(Token(p, position));
2160
1971
  }
2161
1972
  else if (uri != "") {
2162
- std::string res = Util::rtrim(uri);
1973
+ sass::string res = Util::rtrim(uri);
2163
1974
  return SASS_MEMORY_NEW(String_Constant, pstate, res);
2164
1975
  }
2165
1976
 
2166
- return 0;
1977
+ return {};
2167
1978
  }
2168
1979
 
2169
1980
  Function_Call_Obj Parser::parse_function_call()
2170
1981
  {
2171
1982
  lex< identifier >();
2172
- std::string name(lexed);
1983
+ sass::string name(lexed);
2173
1984
 
2174
1985
  if (Util::normalize_underscores(name) == "content-exists" && stack.back() != Scope::Mixin)
2175
1986
  { error("Cannot call content-exists() except within a mixin."); }
2176
1987
 
2177
- ParserState call_pos = pstate;
1988
+ SourceSpan call_pos = pstate;
2178
1989
  Arguments_Obj args = parse_arguments();
2179
1990
  return SASS_MEMORY_NEW(Function_Call, call_pos, name, args);
2180
1991
  }
2181
1992
 
2182
- Function_Call_Schema_Obj Parser::parse_function_call_schema()
1993
+ Function_Call_Obj Parser::parse_function_call_schema()
2183
1994
  {
2184
1995
  String_Obj name = parse_identifier_schema();
2185
- ParserState source_position_of_call = pstate;
1996
+ SourceSpan source_position_of_call = pstate;
2186
1997
  Arguments_Obj args = parse_arguments();
2187
1998
 
2188
- return SASS_MEMORY_NEW(Function_Call_Schema, source_position_of_call, name, args);
1999
+ return SASS_MEMORY_NEW(Function_Call, source_position_of_call, name, args);
2189
2000
  }
2190
2001
 
2191
2002
  Content_Obj Parser::parse_content_directive()
2192
2003
  {
2193
- return SASS_MEMORY_NEW(Content, pstate);
2004
+ SourceSpan call_pos = pstate;
2005
+ Arguments_Obj args = parse_arguments();
2006
+
2007
+ return SASS_MEMORY_NEW(Content, call_pos, args);
2194
2008
  }
2195
2009
 
2196
2010
  If_Obj Parser::parse_if_directive(bool else_if)
2197
2011
  {
2198
2012
  stack.push_back(Scope::Control);
2199
- ParserState if_source_position = pstate;
2013
+ SourceSpan if_source_position = pstate;
2200
2014
  bool root = block_stack.back()->is_root();
2201
- Expression_Obj predicate = parse_list();
2015
+ ExpressionObj predicate = parse_list();
2202
2016
  Block_Obj block = parse_block(root);
2203
- Block_Obj alternative = NULL;
2017
+ Block_Obj alternative;
2204
2018
 
2205
2019
  // only throw away comment if we parse a case
2206
2020
  // we want all other comments to be parsed
@@ -2215,23 +2029,23 @@ namespace Sass {
2215
2029
  return SASS_MEMORY_NEW(If, if_source_position, predicate, block, alternative);
2216
2030
  }
2217
2031
 
2218
- For_Obj Parser::parse_for_directive()
2032
+ ForRuleObj Parser::parse_for_directive()
2219
2033
  {
2220
2034
  stack.push_back(Scope::Control);
2221
- ParserState for_source_position = pstate;
2035
+ SourceSpan for_source_position = pstate;
2222
2036
  bool root = block_stack.back()->is_root();
2223
2037
  lex_variable();
2224
- std::string var(Util::normalize_underscores(lexed));
2038
+ sass::string var(Util::normalize_underscores(lexed));
2225
2039
  if (!lex< kwd_from >()) error("expected 'from' keyword in @for directive");
2226
- Expression_Obj lower_bound = parse_expression();
2040
+ ExpressionObj lower_bound = parse_expression();
2227
2041
  bool inclusive = false;
2228
2042
  if (lex< kwd_through >()) inclusive = true;
2229
2043
  else if (lex< kwd_to >()) inclusive = false;
2230
2044
  else error("expected 'through' or 'to' keyword in @for directive");
2231
- Expression_Obj upper_bound = parse_expression();
2045
+ ExpressionObj upper_bound = parse_expression();
2232
2046
  Block_Obj body = parse_block(root);
2233
2047
  stack.pop_back();
2234
- 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);
2235
2049
  }
2236
2050
 
2237
2051
  // helper to parse a var token
@@ -2247,7 +2061,7 @@ namespace Sass {
2247
2061
  css_error("Invalid CSS", " after ", ": expected identifier, was ");
2248
2062
  }
2249
2063
  // return object
2250
- return token;
2064
+ return lexed;
2251
2065
  }
2252
2066
  // helper to parse identifier
2253
2067
  Token Parser::lex_identifier()
@@ -2257,15 +2071,15 @@ namespace Sass {
2257
2071
  css_error("Invalid CSS", " after ", ": expected identifier, was ");
2258
2072
  }
2259
2073
  // return object
2260
- return token;
2074
+ return lexed;
2261
2075
  }
2262
2076
 
2263
- Each_Obj Parser::parse_each_directive()
2077
+ EachRuleObj Parser::parse_each_directive()
2264
2078
  {
2265
2079
  stack.push_back(Scope::Control);
2266
- ParserState each_source_position = pstate;
2080
+ SourceSpan each_source_position = pstate;
2267
2081
  bool root = block_stack.back()->is_root();
2268
- std::vector<std::string> vars;
2082
+ sass::vector<sass::string> vars;
2269
2083
  lex_variable();
2270
2084
  vars.push_back(Util::normalize_underscores(lexed));
2271
2085
  while (lex< exactly<','> >()) {
@@ -2273,21 +2087,21 @@ namespace Sass {
2273
2087
  vars.push_back(Util::normalize_underscores(lexed));
2274
2088
  }
2275
2089
  if (!lex< kwd_in >()) error("expected 'in' keyword in @each directive");
2276
- Expression_Obj list = parse_list();
2090
+ ExpressionObj list = parse_list();
2277
2091
  Block_Obj body = parse_block(root);
2278
2092
  stack.pop_back();
2279
- return SASS_MEMORY_NEW(Each, each_source_position, vars, list, body);
2093
+ return SASS_MEMORY_NEW(EachRule, each_source_position, vars, list, body);
2280
2094
  }
2281
2095
 
2282
2096
  // called after parsing `kwd_while_directive`
2283
- While_Obj Parser::parse_while_directive()
2097
+ WhileRuleObj Parser::parse_while_directive()
2284
2098
  {
2285
2099
  stack.push_back(Scope::Control);
2286
2100
  bool root = block_stack.back()->is_root();
2287
2101
  // create the initial while call object
2288
- While_Obj call = SASS_MEMORY_NEW(While, pstate, 0, 0);
2102
+ WhileRuleObj call = SASS_MEMORY_NEW(WhileRule, pstate, ExpressionObj{}, Block_Obj{});
2289
2103
  // parse mandatory predicate
2290
- Expression_Obj predicate = parse_list();
2104
+ ExpressionObj predicate = parse_list();
2291
2105
  List_Obj l = Cast<List>(predicate);
2292
2106
  if (!predicate || (l && !l->length())) {
2293
2107
  css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ", false);
@@ -2301,20 +2115,107 @@ namespace Sass {
2301
2115
  return call.detach();
2302
2116
  }
2303
2117
 
2304
- // EO parse_while_directive
2305
- Media_Block_Obj Parser::parse_media_block()
2118
+
2119
+ sass::vector<CssMediaQuery_Obj> Parser::parseCssMediaQueries()
2306
2120
  {
2307
- stack.push_back(Scope::Media);
2308
- Media_Block_Obj media_block = SASS_MEMORY_NEW(Media_Block, pstate, 0, 0);
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
+ }
2309
2207
 
2310
- media_block->media_queries(parse_media_queries());
2311
2208
 
2312
- Media_Block_Obj prev_media_block = last_media_block;
2313
- last_media_block = media_block;
2314
- media_block->block(parse_css_block());
2315
- 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());
2316
2217
  stack.pop_back();
2317
- return media_block.detach();
2218
+ return rule;
2318
2219
  }
2319
2220
 
2320
2221
  List_Obj Parser::parse_media_queries()
@@ -2327,7 +2228,7 @@ namespace Sass {
2327
2228
  return queries.detach();
2328
2229
  }
2329
2230
 
2330
- // Expression_Ptr Parser::parse_media_query()
2231
+ // Expression* Parser::parse_media_query()
2331
2232
  Media_Query_Obj Parser::parse_media_query()
2332
2233
  {
2333
2234
  advanceToNextToken();
@@ -2335,15 +2236,17 @@ namespace Sass {
2335
2236
  if (lex < kwd_not >()) { media_query->is_negated(true); lex < css_comments >(false); }
2336
2237
  else if (lex < kwd_only >()) { media_query->is_restricted(true); lex < css_comments >(false); }
2337
2238
 
2338
- if (lex < identifier_schema >()) media_query->media_type(parse_identifier_schema());
2339
- 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));
2340
2241
  else media_query->append(parse_media_expression());
2341
2242
 
2342
2243
  while (lex_css < kwd_and >()) media_query->append(parse_media_expression());
2343
2244
  if (lex < identifier_schema >()) {
2344
- String_Schema_Ptr schema = SASS_MEMORY_NEW(String_Schema, pstate);
2345
- schema->append(media_query->media_type());
2346
- 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
+ }
2347
2250
  schema->append(parse_identifier_schema());
2348
2251
  media_query->media_type(schema);
2349
2252
  }
@@ -2354,21 +2257,21 @@ namespace Sass {
2354
2257
  return media_query;
2355
2258
  }
2356
2259
 
2357
- Media_Query_Expression_Obj Parser::parse_media_expression()
2260
+ Media_Query_ExpressionObj Parser::parse_media_expression()
2358
2261
  {
2359
2262
  if (lex < identifier_schema >()) {
2360
2263
  String_Obj ss = parse_identifier_schema();
2361
- return SASS_MEMORY_NEW(Media_Query_Expression, pstate, ss, 0, true);
2264
+ return SASS_MEMORY_NEW(Media_Query_Expression, pstate, ss, ExpressionObj{}, true);
2362
2265
  }
2363
2266
  if (!lex_css< exactly<'('> >()) {
2364
2267
  error("media query expression must begin with '('");
2365
2268
  }
2366
- Expression_Obj feature;
2269
+ ExpressionObj feature;
2367
2270
  if (peek_css< exactly<')'> >()) {
2368
2271
  error("media feature required in media query expression");
2369
2272
  }
2370
2273
  feature = parse_expression();
2371
- Expression_Obj expression = 0;
2274
+ ExpressionObj expression;
2372
2275
  if (lex_css< exactly<':'> >()) {
2373
2276
  expression = parse_list(DELAYED);
2374
2277
  }
@@ -2380,14 +2283,11 @@ namespace Sass {
2380
2283
 
2381
2284
  // lexed after `kwd_supports_directive`
2382
2285
  // these are very similar to media blocks
2383
- Supports_Block_Obj Parser::parse_supports_directive()
2286
+ SupportsRuleObj Parser::parse_supports_directive()
2384
2287
  {
2385
- Supports_Condition_Obj cond = parse_supports_condition();
2386
- if (!cond) {
2387
- css_error("Invalid CSS", " after ", ": expected @supports condition (e.g. (display: flexbox)), was ", false);
2388
- }
2288
+ SupportsConditionObj cond = parse_supports_condition(/*top_level=*/true);
2389
2289
  // create the ast node object for the support queries
2390
- Supports_Block_Obj query = SASS_MEMORY_NEW(Supports_Block, pstate, cond);
2290
+ SupportsRuleObj query = SASS_MEMORY_NEW(SupportsRule, pstate, cond);
2391
2291
  // additional block is mandatory
2392
2292
  // parse inner block
2393
2293
  query->block(parse_block());
@@ -2397,65 +2297,65 @@ namespace Sass {
2397
2297
 
2398
2298
  // parse one query operation
2399
2299
  // may encounter nested queries
2400
- Supports_Condition_Obj Parser::parse_supports_condition()
2300
+ SupportsConditionObj Parser::parse_supports_condition(bool top_level)
2401
2301
  {
2402
2302
  lex < css_whitespace >();
2403
- Supports_Condition_Obj cond;
2303
+ SupportsConditionObj cond;
2404
2304
  if ((cond = parse_supports_negation())) return cond;
2405
- if ((cond = parse_supports_operator())) return cond;
2305
+ if ((cond = parse_supports_operator(top_level))) return cond;
2406
2306
  if ((cond = parse_supports_interpolation())) return cond;
2407
2307
  return cond;
2408
2308
  }
2409
2309
 
2410
- Supports_Condition_Obj Parser::parse_supports_negation()
2310
+ SupportsConditionObj Parser::parse_supports_negation()
2411
2311
  {
2412
- if (!lex < kwd_not >()) return 0;
2413
- Supports_Condition_Obj cond = parse_supports_condition_in_parens();
2414
- return SASS_MEMORY_NEW(Supports_Negation, pstate, cond);
2312
+ if (!lex < kwd_not >()) return {};
2313
+ SupportsConditionObj cond = parse_supports_condition_in_parens(/*parens_required=*/true);
2314
+ return SASS_MEMORY_NEW(SupportsNegation, pstate, cond);
2415
2315
  }
2416
2316
 
2417
- Supports_Condition_Obj Parser::parse_supports_operator()
2317
+ SupportsConditionObj Parser::parse_supports_operator(bool top_level)
2418
2318
  {
2419
- Supports_Condition_Obj cond = parse_supports_condition_in_parens();
2420
- if (cond.isNull()) return 0;
2319
+ SupportsConditionObj cond = parse_supports_condition_in_parens(/*parens_required=*/top_level);
2320
+ if (cond.isNull()) return {};
2421
2321
 
2422
2322
  while (true) {
2423
- Supports_Operator::Operand op = Supports_Operator::OR;
2424
- if (lex < kwd_and >()) { op = Supports_Operator::AND; }
2323
+ SupportsOperation::Operand op = SupportsOperation::OR;
2324
+ if (lex < kwd_and >()) { op = SupportsOperation::AND; }
2425
2325
  else if(!lex < kwd_or >()) { break; }
2426
2326
 
2427
2327
  lex < css_whitespace >();
2428
- Supports_Condition_Obj right = parse_supports_condition_in_parens();
2328
+ SupportsConditionObj right = parse_supports_condition_in_parens(/*parens_required=*/true);
2429
2329
 
2430
- // Supports_Condition_Ptr cc = SASS_MEMORY_NEW(Supports_Condition, *static_cast<Supports_Condition_Ptr>(cond));
2431
- 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);
2432
2332
  }
2433
2333
  return cond;
2434
2334
  }
2435
2335
 
2436
- Supports_Condition_Obj Parser::parse_supports_interpolation()
2336
+ SupportsConditionObj Parser::parse_supports_interpolation()
2437
2337
  {
2438
- if (!lex < interpolant >()) return 0;
2338
+ if (!lex < interpolant >()) return {};
2439
2339
 
2440
2340
  String_Obj interp = parse_interpolated_chunk(lexed);
2441
- if (!interp) return 0;
2341
+ if (!interp) return {};
2442
2342
 
2443
2343
  return SASS_MEMORY_NEW(Supports_Interpolation, pstate, interp);
2444
2344
  }
2445
2345
 
2446
2346
  // TODO: This needs some major work. Although feature conditions
2447
2347
  // look like declarations their semantics differ significantly
2448
- Supports_Condition_Obj Parser::parse_supports_declaration()
2348
+ SupportsConditionObj Parser::parse_supports_declaration()
2449
2349
  {
2450
- Supports_Condition_Ptr cond;
2350
+ SupportsCondition* cond;
2451
2351
  // parse something declaration like
2452
- Expression_Obj feature = parse_expression();
2453
- Expression_Obj expression = 0;
2352
+ ExpressionObj feature = parse_expression();
2353
+ ExpressionObj expression;
2454
2354
  if (lex_css< exactly<':'> >()) {
2455
2355
  expression = parse_list(DELAYED);
2456
2356
  }
2457
2357
  if (!feature || !expression) error("@supports condition expected declaration");
2458
- cond = SASS_MEMORY_NEW(Supports_Declaration,
2358
+ cond = SASS_MEMORY_NEW(SupportsDeclaration,
2459
2359
  feature->pstate(),
2460
2360
  feature,
2461
2361
  expression);
@@ -2463,30 +2363,33 @@ namespace Sass {
2463
2363
  return cond;
2464
2364
  }
2465
2365
 
2466
- Supports_Condition_Obj Parser::parse_supports_condition_in_parens()
2366
+ SupportsConditionObj Parser::parse_supports_condition_in_parens(bool parens_required)
2467
2367
  {
2468
- Supports_Condition_Obj interp = parse_supports_interpolation();
2469
- if (interp != 0) return interp;
2368
+ SupportsConditionObj interp = parse_supports_interpolation();
2369
+ if (interp != nullptr) return interp;
2470
2370
 
2471
- if (!lex < exactly <'('> >()) return 0;
2371
+ if (!lex < exactly <'('> >()) {
2372
+ if (parens_required) {
2373
+ css_error("Invalid CSS", " after ", ": expected @supports condition (e.g. (display: flexbox)), was ", /*trim=*/false);
2374
+ } else {
2375
+ return {};
2376
+ }
2377
+ }
2472
2378
  lex < css_whitespace >();
2473
2379
 
2474
- Supports_Condition_Obj cond = parse_supports_condition();
2475
- if (cond != 0) {
2476
- if (!lex < exactly <')'> >()) error("unclosed parenthesis in @supports declaration");
2477
- } else {
2478
- cond = parse_supports_declaration();
2479
- if (!lex < exactly <')'> >()) error("unclosed parenthesis in @supports declaration");
2480
- }
2380
+ SupportsConditionObj cond = parse_supports_condition(/*top_level=*/false);
2381
+ if (cond.isNull()) cond = parse_supports_declaration();
2382
+ if (!lex < exactly <')'> >()) error("unclosed parenthesis in @supports declaration");
2383
+
2481
2384
  lex < css_whitespace >();
2482
2385
  return cond;
2483
2386
  }
2484
2387
 
2485
- At_Root_Block_Obj Parser::parse_at_root_block()
2388
+ AtRootRuleObj Parser::parse_at_root_block()
2486
2389
  {
2487
2390
  stack.push_back(Scope::AtRoot);
2488
- ParserState at_source_position = pstate;
2489
- Block_Obj body = 0;
2391
+ SourceSpan at_source_position = pstate;
2392
+ Block_Obj body;
2490
2393
  At_Root_Query_Obj expr;
2491
2394
  Lookahead lookahead_result;
2492
2395
  if (lex_css< exactly<'('> >()) {
@@ -2497,11 +2400,11 @@ namespace Sass {
2497
2400
  body = parse_block(true);
2498
2401
  }
2499
2402
  else if ((lookahead_result = lookahead_for_selector(position)).found) {
2500
- Ruleset_Obj r = parse_ruleset(lookahead_result);
2403
+ StyleRuleObj r = parse_ruleset(lookahead_result);
2501
2404
  body = SASS_MEMORY_NEW(Block, r->pstate(), 1, true);
2502
2405
  body->append(r);
2503
2406
  }
2504
- 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);
2505
2408
  if (!expr.isNull()) at_root->expression(expr);
2506
2409
  stack.pop_back();
2507
2410
  return at_root;
@@ -2515,9 +2418,9 @@ namespace Sass {
2515
2418
  css_error("Invalid CSS", " after ", ": expected \"with\" or \"without\", was ");
2516
2419
  }
2517
2420
 
2518
- Expression_Obj feature = parse_list();
2421
+ ExpressionObj feature = parse_list();
2519
2422
  if (!lex_css< exactly<':'> >()) error("style declaration must contain a value");
2520
- Expression_Obj expression = parse_list();
2423
+ ExpressionObj expression = parse_list();
2521
2424
  List_Obj value = SASS_MEMORY_NEW(List, feature->pstate(), 1);
2522
2425
 
2523
2426
  if (expression->concrete_type() == Expression::LIST) {
@@ -2533,71 +2436,9 @@ namespace Sass {
2533
2436
  return cond;
2534
2437
  }
2535
2438
 
2536
- Directive_Obj Parser::parse_special_directive()
2537
- {
2538
- std::string kwd(lexed);
2539
-
2540
- if (lexed == "@else") error("Invalid CSS: @else must come after @if");
2541
-
2542
- // this whole branch is never hit via spec tests
2543
-
2544
- Directive_Ptr at_rule = SASS_MEMORY_NEW(Directive, pstate, kwd);
2545
- Lookahead lookahead = lookahead_for_include(position);
2546
- if (lookahead.found && !lookahead.has_interpolants) {
2547
- at_rule->selector(parse_selector_list(false));
2548
- }
2549
-
2550
- lex < css_comments >(false);
2551
-
2552
- if (lex < static_property >()) {
2553
- at_rule->value(parse_interpolated_chunk(Token(lexed)));
2554
- } else if (!(peek < alternatives < exactly<'{'>, exactly<'}'>, exactly<';'> > >())) {
2555
- at_rule->value(parse_list());
2556
- }
2557
-
2558
- lex < css_comments >(false);
2559
-
2560
- if (peek< exactly<'{'> >()) {
2561
- at_rule->block(parse_block());
2562
- }
2563
-
2564
- return at_rule;
2565
- }
2566
-
2567
- // this whole branch is never hit via spec tests
2568
- Directive_Obj Parser::parse_prefixed_directive()
2439
+ AtRuleObj Parser::parse_directive()
2569
2440
  {
2570
- std::string kwd(lexed);
2571
-
2572
- if (lexed == "@else") error("Invalid CSS: @else must come after @if");
2573
-
2574
- Directive_Obj at_rule = SASS_MEMORY_NEW(Directive, pstate, kwd);
2575
- Lookahead lookahead = lookahead_for_include(position);
2576
- if (lookahead.found && !lookahead.has_interpolants) {
2577
- at_rule->selector(parse_selector_list(false));
2578
- }
2579
-
2580
- lex < css_comments >(false);
2581
-
2582
- if (lex < static_property >()) {
2583
- at_rule->value(parse_interpolated_chunk(Token(lexed)));
2584
- } else if (!(peek < alternatives < exactly<'{'>, exactly<'}'>, exactly<';'> > >())) {
2585
- at_rule->value(parse_list());
2586
- }
2587
-
2588
- lex < css_comments >(false);
2589
-
2590
- if (peek< exactly<'{'> >()) {
2591
- at_rule->block(parse_block());
2592
- }
2593
-
2594
- return at_rule;
2595
- }
2596
-
2597
-
2598
- Directive_Obj Parser::parse_directive()
2599
- {
2600
- Directive_Obj directive = SASS_MEMORY_NEW(Directive, pstate, lexed);
2441
+ AtRuleObj directive = SASS_MEMORY_NEW(AtRule, pstate, lexed);
2601
2442
  String_Schema_Obj val = parse_almost_any_value();
2602
2443
  // strip left and right if they are of type string
2603
2444
  directive->value(val);
@@ -2607,34 +2448,35 @@ namespace Sass {
2607
2448
  return directive;
2608
2449
  }
2609
2450
 
2610
- Expression_Obj Parser::lex_interpolation()
2451
+ ExpressionObj Parser::lex_interpolation()
2611
2452
  {
2612
2453
  if (lex < interpolant >(true) != NULL) {
2613
2454
  return parse_interpolated_chunk(lexed, true);
2614
2455
  }
2615
- return 0;
2456
+ return {};
2616
2457
  }
2617
2458
 
2618
- Expression_Obj Parser::lex_interp_uri()
2459
+ ExpressionObj Parser::lex_interp_uri()
2619
2460
  {
2620
2461
  // create a string schema by lexing optional interpolations
2621
2462
  return lex_interp< re_string_uri_open, re_string_uri_close >();
2622
2463
  }
2623
2464
 
2624
- Expression_Obj Parser::lex_interp_string()
2465
+ ExpressionObj Parser::lex_interp_string()
2625
2466
  {
2626
- Expression_Obj rv;
2467
+ ExpressionObj rv;
2627
2468
  if ((rv = lex_interp< re_string_double_open, re_string_double_close >())) return rv;
2628
2469
  if ((rv = lex_interp< re_string_single_open, re_string_single_close >())) return rv;
2629
2470
  return rv;
2630
2471
  }
2631
2472
 
2632
- Expression_Obj Parser::lex_almost_any_value_chars()
2473
+ ExpressionObj Parser::lex_almost_any_value_chars()
2633
2474
  {
2634
2475
  const char* match =
2635
2476
  lex <
2636
2477
  one_plus <
2637
2478
  alternatives <
2479
+ exactly <'>'>,
2638
2480
  sequence <
2639
2481
  exactly <'\\'>,
2640
2482
  any_char
@@ -2678,30 +2520,32 @@ namespace Sass {
2678
2520
  if (match) {
2679
2521
  return SASS_MEMORY_NEW(String_Constant, pstate, lexed);
2680
2522
  }
2681
- return NULL;
2523
+ return {};
2682
2524
  }
2683
2525
 
2684
- Expression_Obj Parser::lex_almost_any_value_token()
2526
+ ExpressionObj Parser::lex_almost_any_value_token()
2685
2527
  {
2686
- Expression_Obj rv;
2687
- if (*position == 0) return 0;
2528
+ ExpressionObj rv;
2529
+ if (*position == 0) return {};
2688
2530
  if ((rv = lex_almost_any_value_chars())) return rv;
2689
2531
  // if ((rv = lex_block_comment())) return rv;
2690
2532
  // if ((rv = lex_single_line_comment())) return rv;
2691
2533
  if ((rv = lex_interp_string())) return rv;
2692
2534
  if ((rv = lex_interp_uri())) return rv;
2693
2535
  if ((rv = lex_interpolation())) return rv;
2694
- return rv;
2536
+ if (lex< alternatives< hex, hex0 > >())
2537
+ { return lexed_hex_color(lexed); }
2538
+ return rv;
2695
2539
  }
2696
2540
 
2697
2541
  String_Schema_Obj Parser::parse_almost_any_value()
2698
2542
  {
2699
2543
 
2700
2544
  String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
2701
- if (*position == 0) return 0;
2545
+ if (*position == 0) return {};
2702
2546
  lex < spaces >(false);
2703
- Expression_Obj token = lex_almost_any_value_token();
2704
- if (!token) return 0;
2547
+ ExpressionObj token = lex_almost_any_value_token();
2548
+ if (!token) return {};
2705
2549
  schema->append(token);
2706
2550
  if (*position == 0) {
2707
2551
  schema->rtrim();
@@ -2719,7 +2563,7 @@ namespace Sass {
2719
2563
  return schema.detach();
2720
2564
  }
2721
2565
 
2722
- Warning_Obj Parser::parse_warning()
2566
+ WarningRuleObj Parser::parse_warning()
2723
2567
  {
2724
2568
  if (stack.back() != Scope::Root &&
2725
2569
  stack.back() != Scope::Function &&
@@ -2728,10 +2572,10 @@ namespace Sass {
2728
2572
  stack.back() != Scope::Rules) {
2729
2573
  error("Illegal nesting: Only properties may be nested beneath properties.");
2730
2574
  }
2731
- return SASS_MEMORY_NEW(Warning, pstate, parse_list(DELAYED));
2575
+ return SASS_MEMORY_NEW(WarningRule, pstate, parse_list(DELAYED));
2732
2576
  }
2733
2577
 
2734
- Error_Obj Parser::parse_error()
2578
+ ErrorRuleObj Parser::parse_error()
2735
2579
  {
2736
2580
  if (stack.back() != Scope::Root &&
2737
2581
  stack.back() != Scope::Function &&
@@ -2740,10 +2584,10 @@ namespace Sass {
2740
2584
  stack.back() != Scope::Rules) {
2741
2585
  error("Illegal nesting: Only properties may be nested beneath properties.");
2742
2586
  }
2743
- return SASS_MEMORY_NEW(Error, pstate, parse_list(DELAYED));
2587
+ return SASS_MEMORY_NEW(ErrorRule, pstate, parse_list(DELAYED));
2744
2588
  }
2745
2589
 
2746
- Debug_Obj Parser::parse_debug()
2590
+ DebugRuleObj Parser::parse_debug()
2747
2591
  {
2748
2592
  if (stack.back() != Scope::Root &&
2749
2593
  stack.back() != Scope::Function &&
@@ -2752,7 +2596,7 @@ namespace Sass {
2752
2596
  stack.back() != Scope::Rules) {
2753
2597
  error("Illegal nesting: Only properties may be nested beneath properties.");
2754
2598
  }
2755
- return SASS_MEMORY_NEW(Debug, pstate, parse_list(DELAYED));
2599
+ return SASS_MEMORY_NEW(DebugRule, pstate, parse_list(DELAYED));
2756
2600
  }
2757
2601
 
2758
2602
  Return_Obj Parser::parse_return_directive()
@@ -2777,6 +2621,7 @@ namespace Sass {
2777
2621
  >(p)
2778
2622
  ) {
2779
2623
  bool could_be_property = peek< sequence< exactly<'-'>, exactly<'-'> > >(p) != 0;
2624
+ bool could_be_escaped = false;
2780
2625
  while (p < q) {
2781
2626
  // did we have interpolations?
2782
2627
  if (*p == '#' && *(p+1) == '{') {
@@ -2785,9 +2630,10 @@ namespace Sass {
2785
2630
  }
2786
2631
  // A property that's ambiguous with a nested selector is interpreted as a
2787
2632
  // custom property.
2788
- if (*p == ':') {
2633
+ if (*p == ':' && !could_be_escaped) {
2789
2634
  rv.is_custom_property = could_be_property || p+1 == q || peek< space >(p+1);
2790
2635
  }
2636
+ could_be_escaped = *p == '\\';
2791
2637
  ++ p;
2792
2638
  }
2793
2639
  // store anyway }
@@ -2797,7 +2643,7 @@ namespace Sass {
2797
2643
  rv.error = q;
2798
2644
  rv.position = q;
2799
2645
  // check expected opening bracket
2800
- // only after successfull matching
2646
+ // only after successful matching
2801
2647
  if (peek < exactly<'{'> >(q)) rv.found = q;
2802
2648
  // else if (peek < end_of_file >(q)) rv.found = q;
2803
2649
  else if (peek < exactly<'('> >(q)) rv.found = q;
@@ -2905,53 +2751,53 @@ namespace Sass {
2905
2751
  void Parser::read_bom()
2906
2752
  {
2907
2753
  size_t skip = 0;
2908
- std::string encoding;
2754
+ sass::string encoding;
2909
2755
  bool utf_8 = false;
2910
- switch ((unsigned char) source[0]) {
2756
+ switch ((unsigned char)position[0]) {
2911
2757
  case 0xEF:
2912
- skip = check_bom_chars(source, end, utf_8_bom, 3);
2758
+ skip = check_bom_chars(position, end, utf_8_bom, 3);
2913
2759
  encoding = "UTF-8";
2914
2760
  utf_8 = true;
2915
2761
  break;
2916
2762
  case 0xFE:
2917
- skip = check_bom_chars(source, end, utf_16_bom_be, 2);
2763
+ skip = check_bom_chars(position, end, utf_16_bom_be, 2);
2918
2764
  encoding = "UTF-16 (big endian)";
2919
2765
  break;
2920
2766
  case 0xFF:
2921
- skip = check_bom_chars(source, end, utf_16_bom_le, 2);
2922
- 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);
2923
2769
  encoding = (skip == 2 ? "UTF-16 (little endian)" : "UTF-32 (little endian)");
2924
2770
  break;
2925
2771
  case 0x00:
2926
- skip = check_bom_chars(source, end, utf_32_bom_be, 4);
2772
+ skip = check_bom_chars(position, end, utf_32_bom_be, 4);
2927
2773
  encoding = "UTF-32 (big endian)";
2928
2774
  break;
2929
2775
  case 0x2B:
2930
- skip = check_bom_chars(source, end, utf_7_bom_1, 4)
2931
- | check_bom_chars(source, end, utf_7_bom_2, 4)
2932
- | check_bom_chars(source, end, utf_7_bom_3, 4)
2933
- | check_bom_chars(source, end, utf_7_bom_4, 4)
2934
- | 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);
2935
2781
  encoding = "UTF-7";
2936
2782
  break;
2937
2783
  case 0xF7:
2938
- skip = check_bom_chars(source, end, utf_1_bom, 3);
2784
+ skip = check_bom_chars(position, end, utf_1_bom, 3);
2939
2785
  encoding = "UTF-1";
2940
2786
  break;
2941
2787
  case 0xDD:
2942
- skip = check_bom_chars(source, end, utf_ebcdic_bom, 4);
2788
+ skip = check_bom_chars(position, end, utf_ebcdic_bom, 4);
2943
2789
  encoding = "UTF-EBCDIC";
2944
2790
  break;
2945
2791
  case 0x0E:
2946
- skip = check_bom_chars(source, end, scsu_bom, 3);
2792
+ skip = check_bom_chars(position, end, scsu_bom, 3);
2947
2793
  encoding = "SCSU";
2948
2794
  break;
2949
2795
  case 0xFB:
2950
- skip = check_bom_chars(source, end, bocu_1_bom, 3);
2796
+ skip = check_bom_chars(position, end, bocu_1_bom, 3);
2951
2797
  encoding = "BOCU-1";
2952
2798
  break;
2953
2799
  case 0x84:
2954
- skip = check_bom_chars(source, end, gb_18030_bom, 4);
2800
+ skip = check_bom_chars(position, end, gb_18030_bom, 4);
2955
2801
  encoding = "GB-18030";
2956
2802
  break;
2957
2803
  default: break;
@@ -2971,7 +2817,7 @@ namespace Sass {
2971
2817
  }
2972
2818
 
2973
2819
 
2974
- 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)
2975
2821
  {
2976
2822
  for (size_t i = 0, S = operands.size(); i < S; ++i) {
2977
2823
  base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), op, base, operands[i]);
@@ -2979,9 +2825,9 @@ namespace Sass {
2979
2825
  return base;
2980
2826
  }
2981
2827
 
2982
- 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)
2983
2829
  {
2984
- if (String_Schema_Ptr schema = Cast<String_Schema>(base)) {
2830
+ if (String_Schema* schema = Cast<String_Schema>(base)) {
2985
2831
  // return schema;
2986
2832
  if (schema->has_interpolants()) {
2987
2833
  if (i + 1 < operands.size() && (
@@ -2995,7 +2841,7 @@ namespace Sass {
2995
2841
  || (ops[0].operand == Sass_OP::LTE)
2996
2842
  || (ops[0].operand == Sass_OP::GTE)
2997
2843
  )) {
2998
- Expression_Obj rhs = fold_operands(operands[i], operands, ops, i + 1);
2844
+ ExpressionObj rhs = fold_operands(operands[i], operands, ops, i + 1);
2999
2845
  rhs = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[0], schema, rhs);
3000
2846
  return rhs;
3001
2847
  }
@@ -3003,12 +2849,19 @@ namespace Sass {
3003
2849
  }
3004
2850
  }
3005
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
+
3006
2859
  for (size_t S = operands.size(); i < S; ++i) {
3007
- if (String_Schema_Ptr schema = Cast<String_Schema>(operands[i])) {
2860
+ if (String_Schema* schema = Cast<String_Schema>(operands[i])) {
3008
2861
  if (schema->has_interpolants()) {
3009
2862
  if (i + 1 < S) {
3010
2863
  // this whole branch is never hit via spec tests
3011
- Expression_Obj rhs = fold_operands(operands[i+1], operands, ops, i + 2);
2864
+ ExpressionObj rhs = fold_operands(operands[i+1], operands, ops, i + 2);
3012
2865
  rhs = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], schema, rhs);
3013
2866
  base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], base, rhs);
3014
2867
  return base;
@@ -3021,34 +2874,27 @@ namespace Sass {
3021
2874
  } else {
3022
2875
  base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], base, operands[i]);
3023
2876
  }
3024
- Binary_Expression_Ptr b = Cast<Binary_Expression>(base.ptr());
2877
+ Binary_Expression* b = Cast<Binary_Expression>(base.ptr());
3025
2878
  if (b && ops[i].operand == Sass_OP::DIV && b->left()->is_delayed() && b->right()->is_delayed()) {
3026
2879
  base->is_delayed(true);
3027
2880
  }
3028
2881
  }
3029
2882
  // nested binary expression are never to be delayed
3030
- if (Binary_Expression_Ptr b = Cast<Binary_Expression>(base)) {
2883
+ if (Binary_Expression* b = Cast<Binary_Expression>(base)) {
3031
2884
  if (Cast<Binary_Expression>(b->left())) base->set_delayed(false);
3032
2885
  if (Cast<Binary_Expression>(b->right())) base->set_delayed(false);
3033
2886
  }
3034
2887
  return base;
3035
2888
  }
3036
2889
 
3037
- void Parser::error(std::string msg, Position pos)
2890
+ void Parser::error(sass::string msg)
3038
2891
  {
3039
- Position p(pos.line ? pos : before_token);
3040
- ParserState pstate(path, source, p, Offset(0, 0));
3041
2892
  traces.push_back(Backtrace(pstate));
3042
2893
  throw Exception::InvalidSass(pstate, traces, msg);
3043
2894
  }
3044
2895
 
3045
- void Parser::error(std::string msg)
3046
- {
3047
- error(msg, pstate);
3048
- }
3049
-
3050
2896
  // print a css parsing error with actual context information from parsed source
3051
- 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)
3052
2898
  {
3053
2899
  int max_len = 18;
3054
2900
  const char* end = this->end;
@@ -3057,13 +2903,13 @@ namespace Sass {
3057
2903
  if (!pos) pos = position;
3058
2904
 
3059
2905
  const char* last_pos(pos);
3060
- if (last_pos > source) {
3061
- utf8::prior(last_pos, source);
2906
+ if (last_pos > begin) {
2907
+ utf8::prior(last_pos, begin);
3062
2908
  }
3063
2909
  // backup position to last significant char
3064
- while (trim && last_pos > source && last_pos < end) {
3065
- if (!Prelexer::is_space(*last_pos)) break;
3066
- 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);
3067
2913
  }
3068
2914
 
3069
2915
  bool ellipsis_left = false;
@@ -3072,9 +2918,9 @@ namespace Sass {
3072
2918
 
3073
2919
  if (*pos_left) utf8::next(pos_left, end);
3074
2920
  if (*end_left) utf8::next(end_left, end);
3075
- while (pos_left > source) {
2921
+ while (pos_left > begin) {
3076
2922
  if (utf8::distance(pos_left, end_left) >= max_len) {
3077
- utf8::prior(pos_left, source);
2923
+ utf8::prior(pos_left, begin);
3078
2924
  ellipsis_left = *(pos_left) != '\n' &&
3079
2925
  *(pos_left) != '\r';
3080
2926
  utf8::next(pos_left, end);
@@ -3082,13 +2928,13 @@ namespace Sass {
3082
2928
  }
3083
2929
 
3084
2930
  const char* prev = pos_left;
3085
- utf8::prior(prev, source);
2931
+ utf8::prior(prev, begin);
3086
2932
  if (*prev == '\r') break;
3087
2933
  if (*prev == '\n') break;
3088
2934
  pos_left = prev;
3089
2935
  }
3090
- if (pos_left < source) {
3091
- pos_left = source;
2936
+ if (pos_left < begin) {
2937
+ pos_left = begin;
3092
2938
  }
3093
2939
 
3094
2940
  bool ellipsis_right = false;
@@ -3106,14 +2952,12 @@ namespace Sass {
3106
2952
  }
3107
2953
  // if (*end_right == 0) end_right ++;
3108
2954
 
3109
- std::string left(pos_left, end_left);
3110
- std::string right(pos_right, end_right);
2955
+ sass::string left(pos_left, end_left);
2956
+ sass::string right(pos_right, end_right);
3111
2957
  size_t left_subpos = left.size() > 15 ? left.size() - 15 : 0;
3112
2958
  size_t right_subpos = right.size() > 15 ? right.size() - 15 : 0;
3113
2959
  if (left_subpos && ellipsis_left) left = ellipsis + left.substr(left_subpos);
3114
2960
  if (right_subpos && ellipsis_right) right = right.substr(right_subpos) + ellipsis;
3115
- // Hotfix when source is null, probably due to interpolation parsing!?
3116
- if (source == NULL || *source == 0) source = pstate.src;
3117
2961
  // now pass new message to the more generic error function
3118
2962
  error(msg + prefix + quote(left) + middle + quote(right));
3119
2963
  }