sassc 2.0.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
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
  }