sassc 2.0.1 → 2.1.0.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.gitmodules +1 -1
  4. data/.travis.yml +7 -3
  5. data/CHANGELOG.md +3 -0
  6. data/CODE_OF_CONDUCT.md +1 -1
  7. data/README.md +1 -1
  8. data/Rakefile +23 -8
  9. data/ext/extconf.rb +39 -0
  10. data/ext/libsass/.gitignore +1 -0
  11. data/ext/libsass/GNUmakefile.am +23 -39
  12. data/ext/libsass/Makefile +56 -91
  13. data/ext/libsass/Makefile.conf +16 -2
  14. data/ext/libsass/configure.ac +8 -12
  15. data/ext/libsass/include/sass/base.h +1 -0
  16. data/ext/libsass/include/sass/context.h +1 -1
  17. data/ext/libsass/src/GNUmakefile.am +1 -5
  18. data/ext/libsass/src/ast.cpp +747 -2010
  19. data/ext/libsass/src/ast.hpp +239 -2383
  20. data/ext/libsass/src/{to_c.cpp → ast2c.cpp} +22 -16
  21. data/ext/libsass/src/ast2c.hpp +39 -0
  22. data/ext/libsass/src/ast_def_macros.hpp +62 -10
  23. data/ext/libsass/src/ast_fwd_decl.cpp +1 -0
  24. data/ext/libsass/src/ast_fwd_decl.hpp +43 -165
  25. data/ext/libsass/src/ast_sel_cmp.cpp +909 -0
  26. data/ext/libsass/src/ast_sel_unify.cpp +280 -0
  27. data/ext/libsass/src/ast_selectors.cpp +1475 -0
  28. data/ext/libsass/src/ast_selectors.hpp +568 -0
  29. data/ext/libsass/src/ast_supports.cpp +130 -0
  30. data/ext/libsass/src/ast_supports.hpp +121 -0
  31. data/ext/libsass/src/ast_values.cpp +967 -0
  32. data/ext/libsass/src/ast_values.hpp +489 -0
  33. data/ext/libsass/src/backtrace.cpp +4 -0
  34. data/ext/libsass/src/base64vlq.cpp +3 -0
  35. data/ext/libsass/src/bind.cpp +18 -17
  36. data/ext/libsass/src/bind.hpp +3 -1
  37. data/ext/libsass/src/c2ast.cpp +64 -0
  38. data/ext/libsass/src/c2ast.hpp +14 -0
  39. data/ext/libsass/src/cencode.c +2 -2
  40. data/ext/libsass/src/check_nesting.cpp +52 -56
  41. data/ext/libsass/src/check_nesting.hpp +35 -34
  42. data/ext/libsass/src/color_maps.cpp +156 -153
  43. data/ext/libsass/src/color_maps.hpp +152 -152
  44. data/ext/libsass/src/constants.cpp +15 -0
  45. data/ext/libsass/src/constants.hpp +13 -0
  46. data/ext/libsass/src/context.cpp +24 -14
  47. data/ext/libsass/src/context.hpp +6 -6
  48. data/ext/libsass/src/cssize.cpp +69 -71
  49. data/ext/libsass/src/cssize.hpp +50 -50
  50. data/ext/libsass/src/debugger.hpp +117 -110
  51. data/ext/libsass/src/emitter.cpp +13 -12
  52. data/ext/libsass/src/emitter.hpp +13 -9
  53. data/ext/libsass/src/environment.cpp +15 -1
  54. data/ext/libsass/src/environment.hpp +6 -0
  55. data/ext/libsass/src/error_handling.cpp +36 -59
  56. data/ext/libsass/src/error_handling.hpp +29 -16
  57. data/ext/libsass/src/eval.cpp +302 -323
  58. data/ext/libsass/src/eval.hpp +64 -55
  59. data/ext/libsass/src/expand.cpp +94 -88
  60. data/ext/libsass/src/expand.hpp +33 -37
  61. data/ext/libsass/src/extend.cpp +38 -36
  62. data/ext/libsass/src/extend.hpp +15 -15
  63. data/ext/libsass/src/file.cpp +34 -2
  64. data/ext/libsass/src/fn_colors.cpp +594 -0
  65. data/ext/libsass/src/fn_colors.hpp +85 -0
  66. data/ext/libsass/src/fn_lists.cpp +284 -0
  67. data/ext/libsass/src/fn_lists.hpp +34 -0
  68. data/ext/libsass/src/fn_maps.cpp +94 -0
  69. data/ext/libsass/src/fn_maps.hpp +30 -0
  70. data/ext/libsass/src/fn_miscs.cpp +256 -0
  71. data/ext/libsass/src/fn_miscs.hpp +40 -0
  72. data/ext/libsass/src/fn_numbers.cpp +220 -0
  73. data/ext/libsass/src/fn_numbers.hpp +45 -0
  74. data/ext/libsass/src/fn_selectors.cpp +235 -0
  75. data/ext/libsass/src/fn_selectors.hpp +35 -0
  76. data/ext/libsass/src/fn_strings.cpp +254 -0
  77. data/ext/libsass/src/fn_strings.hpp +34 -0
  78. data/ext/libsass/src/fn_utils.cpp +156 -0
  79. data/ext/libsass/src/fn_utils.hpp +56 -0
  80. data/ext/libsass/src/inspect.cpp +101 -152
  81. data/ext/libsass/src/inspect.hpp +69 -73
  82. data/ext/libsass/src/json.cpp +2 -2
  83. data/ext/libsass/src/lexer.cpp +6 -3
  84. data/ext/libsass/src/listize.cpp +9 -11
  85. data/ext/libsass/src/listize.hpp +11 -7
  86. data/ext/libsass/src/memory/SharedPtr.cpp +2 -83
  87. data/ext/libsass/src/memory/SharedPtr.hpp +127 -143
  88. data/ext/libsass/src/node.cpp +13 -10
  89. data/ext/libsass/src/node.hpp +3 -3
  90. data/ext/libsass/src/operation.hpp +184 -144
  91. data/ext/libsass/src/operators.cpp +43 -17
  92. data/ext/libsass/src/operators.hpp +5 -5
  93. data/ext/libsass/src/output.cpp +21 -18
  94. data/ext/libsass/src/output.hpp +14 -21
  95. data/ext/libsass/src/parser.cpp +215 -183
  96. data/ext/libsass/src/parser.hpp +28 -24
  97. data/ext/libsass/src/plugins.cpp +5 -1
  98. data/ext/libsass/src/position.cpp +3 -0
  99. data/ext/libsass/src/prelexer.cpp +9 -3
  100. data/ext/libsass/src/prelexer.hpp +9 -9
  101. data/ext/libsass/src/remove_placeholders.cpp +14 -11
  102. data/ext/libsass/src/remove_placeholders.hpp +8 -9
  103. data/ext/libsass/src/sass.cpp +9 -3
  104. data/ext/libsass/src/sass.hpp +12 -9
  105. data/ext/libsass/src/sass2scss.cpp +45 -14
  106. data/ext/libsass/src/sass_context.cpp +18 -15
  107. data/ext/libsass/src/sass_functions.cpp +6 -3
  108. data/ext/libsass/src/sass_functions.hpp +1 -1
  109. data/ext/libsass/src/sass_util.cpp +3 -0
  110. data/ext/libsass/src/sass_values.cpp +21 -13
  111. data/ext/libsass/src/source_map.cpp +5 -2
  112. data/ext/libsass/src/source_map.hpp +2 -2
  113. data/ext/libsass/src/subset_map.cpp +4 -1
  114. data/ext/libsass/src/to_value.cpp +23 -21
  115. data/ext/libsass/src/to_value.hpp +18 -22
  116. data/ext/libsass/src/units.cpp +4 -0
  117. data/ext/libsass/src/units.hpp +1 -0
  118. data/ext/libsass/src/utf8/checked.h +12 -10
  119. data/ext/libsass/src/utf8/core.h +3 -0
  120. data/ext/libsass/src/utf8_string.cpp +3 -0
  121. data/ext/libsass/src/util.cpp +67 -75
  122. data/ext/libsass/src/util.hpp +64 -19
  123. data/ext/libsass/src/util_string.cpp +75 -0
  124. data/ext/libsass/src/util_string.hpp +19 -0
  125. data/ext/libsass/src/values.cpp +22 -13
  126. data/ext/libsass/src/values.hpp +2 -2
  127. data/ext/libsass/win/libsass.targets +30 -4
  128. data/ext/libsass/win/libsass.vcxproj.filters +82 -4
  129. data/lib/sassc.rb +24 -0
  130. data/lib/sassc/engine.rb +2 -2
  131. data/lib/sassc/native.rb +8 -1
  132. data/lib/sassc/version.rb +1 -1
  133. data/sassc.gemspec +19 -11
  134. data/test/engine_test.rb +26 -1
  135. data/test/native_test.rb +1 -1
  136. metadata +66 -72
  137. data/ext/Rakefile +0 -3
  138. data/ext/libsass/.github/CONTRIBUTING.md +0 -65
  139. data/ext/libsass/.github/ISSUE_TEMPLATE.md +0 -54
  140. data/ext/libsass/.travis.yml +0 -64
  141. data/ext/libsass/Readme.md +0 -104
  142. data/ext/libsass/SECURITY.md +0 -10
  143. data/ext/libsass/appveyor.yml +0 -91
  144. data/ext/libsass/docs/README.md +0 -20
  145. data/ext/libsass/docs/api-context-example.md +0 -45
  146. data/ext/libsass/docs/api-context-internal.md +0 -163
  147. data/ext/libsass/docs/api-context.md +0 -295
  148. data/ext/libsass/docs/api-doc.md +0 -215
  149. data/ext/libsass/docs/api-function-example.md +0 -67
  150. data/ext/libsass/docs/api-function-internal.md +0 -8
  151. data/ext/libsass/docs/api-function.md +0 -74
  152. data/ext/libsass/docs/api-importer-example.md +0 -112
  153. data/ext/libsass/docs/api-importer-internal.md +0 -20
  154. data/ext/libsass/docs/api-importer.md +0 -86
  155. data/ext/libsass/docs/api-value-example.md +0 -55
  156. data/ext/libsass/docs/api-value-internal.md +0 -76
  157. data/ext/libsass/docs/api-value.md +0 -154
  158. data/ext/libsass/docs/build-on-darwin.md +0 -27
  159. data/ext/libsass/docs/build-on-gentoo.md +0 -55
  160. data/ext/libsass/docs/build-on-windows.md +0 -139
  161. data/ext/libsass/docs/build-shared-library.md +0 -35
  162. data/ext/libsass/docs/build-with-autotools.md +0 -78
  163. data/ext/libsass/docs/build-with-makefiles.md +0 -68
  164. data/ext/libsass/docs/build-with-mingw.md +0 -107
  165. data/ext/libsass/docs/build-with-visual-studio.md +0 -90
  166. data/ext/libsass/docs/build.md +0 -97
  167. data/ext/libsass/docs/compatibility-plan.md +0 -48
  168. data/ext/libsass/docs/contributing.md +0 -17
  169. data/ext/libsass/docs/custom-functions-internal.md +0 -122
  170. data/ext/libsass/docs/dev-ast-memory.md +0 -223
  171. data/ext/libsass/docs/implementations.md +0 -56
  172. data/ext/libsass/docs/plugins.md +0 -47
  173. data/ext/libsass/docs/setup-environment.md +0 -68
  174. data/ext/libsass/docs/source-map-internals.md +0 -51
  175. data/ext/libsass/docs/trace.md +0 -26
  176. data/ext/libsass/docs/triage.md +0 -17
  177. data/ext/libsass/docs/unicode.md +0 -39
  178. data/ext/libsass/extconf.rb +0 -6
  179. data/ext/libsass/script/bootstrap +0 -13
  180. data/ext/libsass/script/branding +0 -10
  181. data/ext/libsass/script/ci-build-libsass +0 -134
  182. data/ext/libsass/script/ci-build-plugin +0 -62
  183. data/ext/libsass/script/ci-install-compiler +0 -6
  184. data/ext/libsass/script/ci-install-deps +0 -20
  185. data/ext/libsass/script/ci-report-coverage +0 -42
  186. data/ext/libsass/script/spec +0 -5
  187. data/ext/libsass/script/tap-driver +0 -652
  188. data/ext/libsass/script/tap-runner +0 -1
  189. data/ext/libsass/script/test-leaks.pl +0 -103
  190. data/ext/libsass/src/functions.cpp +0 -2234
  191. data/ext/libsass/src/functions.hpp +0 -198
  192. data/ext/libsass/src/to_c.hpp +0 -39
  193. data/ext/libsass/test/test_node.cpp +0 -94
  194. data/ext/libsass/test/test_paths.cpp +0 -28
  195. data/ext/libsass/test/test_selector_difference.cpp +0 -25
  196. data/ext/libsass/test/test_specificity.cpp +0 -25
  197. data/ext/libsass/test/test_subset_map.cpp +0 -472
  198. data/ext/libsass/test/test_superselector.cpp +0 -69
  199. data/ext/libsass/test/test_unification.cpp +0 -31
  200. data/lib/tasks/libsass.rb +0 -33
@@ -1,4 +1,7 @@
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 "operators.hpp"
3
6
 
4
7
  namespace Sass {
@@ -54,13 +57,24 @@ namespace Sass {
54
57
  bool lte(Expression_Obj lhs, Expression_Obj rhs) { return cmp(lhs, rhs, Sass_OP::LTE) || eq(lhs, rhs); }
55
58
  bool gte(Expression_Obj lhs, Expression_Obj rhs) { return !cmp(lhs, rhs, Sass_OP::GTE) || eq(lhs, rhs); }
56
59
 
60
+ /* colour math deprecation warning */
61
+ void op_color_deprecation(enum Sass_OP op, std::string lsh, std::string rhs, const ParserState& pstate)
62
+ {
63
+ deprecated(
64
+ "The operation `" + lsh + " " + sass_op_to_name(op) + " " + rhs +
65
+ "` is deprecated and will be an error in future versions.",
66
+ "Consider using Sass's color functions instead.\n"
67
+ "https://sass-lang.com/documentation/Sass/Script/Functions.html#other_color_functions",
68
+ /*with_column=*/false, pstate);
69
+ }
70
+
57
71
  /* static function, throws OperationError, has no traces but optional pstate for returned value */
58
- Value_Ptr op_strings(Sass::Operand operand, Value& lhs, Value& rhs, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed)
72
+ Value* op_strings(Sass::Operand operand, Value& lhs, Value& rhs, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed)
59
73
  {
60
74
  enum Sass_OP op = operand.operand;
61
75
 
62
- String_Quoted_Ptr lqstr = Cast<String_Quoted>(&lhs);
63
- String_Quoted_Ptr rqstr = Cast<String_Quoted>(&rhs);
76
+ String_Quoted* lqstr = Cast<String_Quoted>(&lhs);
77
+ String_Quoted* rqstr = Cast<String_Quoted>(&rhs);
64
78
 
65
79
  std::string lstr(lqstr ? lqstr->value() : lhs.to_string(opt));
66
80
  std::string rstr(rqstr ? rqstr->value() : rhs.to_string(opt));
@@ -104,16 +118,21 @@ namespace Sass {
104
118
  return SASS_MEMORY_NEW(String_Constant, pstate, lstr + sep + rstr);
105
119
  }
106
120
 
121
+ /* ToDo: allow to operate also with hsla colors */
107
122
  /* static function, throws OperationError, has no traces but optional pstate for returned value */
108
- Value_Ptr op_colors(enum Sass_OP op, const Color& lhs, const Color& rhs, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed)
123
+ Value* op_colors(enum Sass_OP op, const Color_RGBA& lhs, const Color_RGBA& rhs, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed)
109
124
  {
125
+
110
126
  if (lhs.a() != rhs.a()) {
111
127
  throw Exception::AlphaChannelsNotEqual(&lhs, &rhs, op);
112
128
  }
113
- if (op == Sass_OP::DIV && (!rhs.r() || !rhs.g() || !rhs.b())) {
129
+ if ((op == Sass_OP::DIV || op == Sass_OP::MOD) && (!rhs.r() || !rhs.g() || !rhs.b())) {
114
130
  throw Exception::ZeroDivisionError(lhs, rhs);
115
131
  }
116
- return SASS_MEMORY_NEW(Color,
132
+
133
+ op_color_deprecation(op, lhs.to_string(), rhs.to_string(), pstate);
134
+
135
+ return SASS_MEMORY_NEW(Color_RGBA,
117
136
  pstate,
118
137
  ops[op](lhs.r(), rhs.r()),
119
138
  ops[op](lhs.g(), rhs.g()),
@@ -122,20 +141,20 @@ namespace Sass {
122
141
  }
123
142
 
124
143
  /* static function, throws OperationError, has no traces but optional pstate for returned value */
125
- Value_Ptr op_numbers(enum Sass_OP op, const Number& lhs, const Number& rhs, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed)
144
+ Value* op_numbers(enum Sass_OP op, const Number& lhs, const Number& rhs, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed)
126
145
  {
127
146
  double lval = lhs.value();
128
147
  double rval = rhs.value();
129
148
 
149
+ if (op == Sass_OP::MOD && rval == 0) {
150
+ return SASS_MEMORY_NEW(String_Quoted, pstate, "NaN");
151
+ }
152
+
130
153
  if (op == Sass_OP::DIV && rval == 0) {
131
154
  std::string result(lval ? "Infinity" : "NaN");
132
155
  return SASS_MEMORY_NEW(String_Quoted, pstate, result);
133
156
  }
134
157
 
135
- if (op == Sass_OP::MOD && rval == 0) {
136
- throw Exception::ZeroDivisionError(lhs, rhs);
137
- }
138
-
139
158
  size_t l_n_units = lhs.numerators.size();
140
159
  size_t l_d_units = lhs.numerators.size();
141
160
  size_t r_n_units = rhs.denominators.size();
@@ -145,7 +164,7 @@ namespace Sass {
145
164
  if (l_n_units + l_d_units <= 1 && r_n_units + r_d_units <= 1) {
146
165
  if (lhs.numerators == rhs.numerators) {
147
166
  if (lhs.denominators == rhs.denominators) {
148
- Number_Ptr v = SASS_MEMORY_COPY(&lhs);
167
+ Number* v = SASS_MEMORY_COPY(&lhs);
149
168
  v->value(ops[op](lval, rval));
150
169
  return v;
151
170
  }
@@ -192,13 +211,15 @@ namespace Sass {
192
211
  }
193
212
 
194
213
  /* static function, throws OperationError, has no traces but optional pstate for returned value */
195
- Value_Ptr op_number_color(enum Sass_OP op, const Number& lhs, const Color& rhs, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed)
214
+ Value* op_number_color(enum Sass_OP op, const Number& lhs, const Color_RGBA& rhs, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed)
196
215
  {
197
216
  double lval = lhs.value();
217
+
198
218
  switch (op) {
199
219
  case Sass_OP::ADD:
200
220
  case Sass_OP::MUL: {
201
- return SASS_MEMORY_NEW(Color,
221
+ op_color_deprecation(op, lhs.to_string(), rhs.to_string(opt), pstate);
222
+ return SASS_MEMORY_NEW(Color_RGBA,
202
223
  pstate,
203
224
  ops[op](lval, rhs.r()),
204
225
  ops[op](lval, rhs.g()),
@@ -208,6 +229,7 @@ namespace Sass {
208
229
  case Sass_OP::SUB:
209
230
  case Sass_OP::DIV: {
210
231
  std::string color(rhs.to_string(opt));
232
+ op_color_deprecation(op, lhs.to_string(), color, pstate);
211
233
  return SASS_MEMORY_NEW(String_Quoted,
212
234
  pstate,
213
235
  lhs.to_string(opt)
@@ -220,14 +242,18 @@ namespace Sass {
220
242
  }
221
243
 
222
244
  /* static function, throws OperationError, has no traces but optional pstate for returned value */
223
- Value_Ptr op_color_number(enum Sass_OP op, const Color& lhs, const Number& rhs, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed)
245
+ Value* op_color_number(enum Sass_OP op, const Color_RGBA& lhs, const Number& rhs, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed)
224
246
  {
225
247
  double rval = rhs.value();
226
- if (op == Sass_OP::DIV && rval == 0) {
248
+
249
+ if ((op == Sass_OP::DIV || op == Sass_OP::DIV) && rval == 0) {
227
250
  // comparison of Fixnum with Float failed?
228
251
  throw Exception::ZeroDivisionError(lhs, rhs);
229
252
  }
230
- return SASS_MEMORY_NEW(Color,
253
+
254
+ op_color_deprecation(op, lhs.to_string(), rhs.to_string(), pstate);
255
+
256
+ return SASS_MEMORY_NEW(Color_RGBA,
231
257
  pstate,
232
258
  ops[op](lhs.r(), rval),
233
259
  ops[op](lhs.g(), rval),
@@ -17,11 +17,11 @@ namespace Sass {
17
17
  bool lte(Expression_Obj, Expression_Obj);
18
18
  bool gte(Expression_Obj, Expression_Obj);
19
19
  // arithmetic for all the combinations that matter
20
- Value_Ptr op_strings(Sass::Operand, Value&, Value&, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed = false);
21
- Value_Ptr op_colors(enum Sass_OP, const Color&, const Color&, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed = false);
22
- Value_Ptr op_numbers(enum Sass_OP, const Number&, const Number&, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed = false);
23
- Value_Ptr op_number_color(enum Sass_OP, const Number&, const Color&, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed = false);
24
- Value_Ptr op_color_number(enum Sass_OP, const Color&, const Number&, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed = false);
20
+ Value* op_strings(Sass::Operand, Value&, Value&, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed = false);
21
+ Value* op_colors(enum Sass_OP, const Color_RGBA&, const Color_RGBA&, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed = false);
22
+ Value* op_numbers(enum Sass_OP, const Number&, const Number&, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed = false);
23
+ Value* op_number_color(enum Sass_OP, const Number&, const Color_RGBA&, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed = false);
24
+ Value* op_color_number(enum Sass_OP, const Color_RGBA&, const Number&, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed = false);
25
25
 
26
26
  };
27
27
 
@@ -1,6 +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 "ast.hpp"
3
6
  #include "output.hpp"
7
+ #include "util.hpp"
4
8
 
5
9
  namespace Sass {
6
10
 
@@ -12,12 +16,12 @@ namespace Sass {
12
16
 
13
17
  Output::~Output() { }
14
18
 
15
- void Output::fallback_impl(AST_Node_Ptr n)
19
+ void Output::fallback_impl(AST_Node* n)
16
20
  {
17
21
  return n->perform(this);
18
22
  }
19
23
 
20
- void Output::operator()(Number_Ptr n)
24
+ void Output::operator()(Number* n)
21
25
  {
22
26
  // check for a valid unit here
23
27
  // includes result for reporting
@@ -31,12 +35,12 @@ namespace Sass {
31
35
  append_token(res, n);
32
36
  }
33
37
 
34
- void Output::operator()(Import_Ptr imp)
38
+ void Output::operator()(Import* imp)
35
39
  {
36
40
  top_nodes.push_back(imp);
37
41
  }
38
42
 
39
- void Output::operator()(Map_Ptr m)
43
+ void Output::operator()(Map* m)
40
44
  {
41
45
  // should be handle in check_expression
42
46
  throw Exception::InvalidValue({}, *m);
@@ -86,9 +90,8 @@ namespace Sass {
86
90
 
87
91
  }
88
92
 
89
- void Output::operator()(Comment_Ptr c)
93
+ void Output::operator()(Comment* c)
90
94
  {
91
- std::string txt = c->text()->to_string(opt);
92
95
  // if (indentation && txt == "/**/") return;
93
96
  bool important = c->is_important();
94
97
  if (output_style() != COMPRESSED || important) {
@@ -108,7 +111,7 @@ namespace Sass {
108
111
  }
109
112
  }
110
113
 
111
- void Output::operator()(Ruleset_Ptr r)
114
+ void Output::operator()(Ruleset* r)
112
115
  {
113
116
  Selector_Obj s = r->selector();
114
117
  Block_Obj b = r->block();
@@ -142,19 +145,19 @@ namespace Sass {
142
145
  Statement_Obj stm = b->at(i);
143
146
  bool bPrintExpression = true;
144
147
  // Check print conditions
145
- if (Declaration_Ptr dec = Cast<Declaration>(stm)) {
146
- if (String_Constant_Ptr valConst = Cast<String_Constant>(dec->value())) {
148
+ if (Declaration* dec = Cast<Declaration>(stm)) {
149
+ if (String_Constant* valConst = Cast<String_Constant>(dec->value())) {
147
150
  std::string val(valConst->value());
148
- if (String_Quoted_Ptr qstr = Cast<String_Quoted>(valConst)) {
151
+ if (String_Quoted* qstr = Cast<String_Quoted>(valConst)) {
149
152
  if (!qstr->quote_mark() && val.empty()) {
150
153
  bPrintExpression = false;
151
154
  }
152
155
  }
153
156
  }
154
- else if (List_Ptr list = Cast<List>(dec->value())) {
157
+ else if (List* list = Cast<List>(dec->value())) {
155
158
  bool all_invisible = true;
156
159
  for (size_t list_i = 0, list_L = list->length(); list_i < list_L; ++list_i) {
157
- Expression_Ptr item = list->at(list_i);
160
+ Expression* item = list->at(list_i);
158
161
  if (!item->is_invisible()) all_invisible = false;
159
162
  }
160
163
  if (all_invisible && !list->is_bracketed()) bPrintExpression = false;
@@ -169,7 +172,7 @@ namespace Sass {
169
172
  append_scope_closer(b);
170
173
 
171
174
  }
172
- void Output::operator()(Keyframe_Rule_Ptr r)
175
+ void Output::operator()(Keyframe_Rule* r)
173
176
  {
174
177
  Block_Obj b = r->block();
175
178
  Selector_Obj v = r->name();
@@ -192,7 +195,7 @@ namespace Sass {
192
195
  append_scope_closer();
193
196
  }
194
197
 
195
- void Output::operator()(Supports_Block_Ptr f)
198
+ void Output::operator()(Supports_Block* f)
196
199
  {
197
200
  if (f->is_invisible()) return;
198
201
 
@@ -229,7 +232,7 @@ namespace Sass {
229
232
 
230
233
  }
231
234
 
232
- void Output::operator()(Media_Block_Ptr m)
235
+ void Output::operator()(Media_Block* m)
233
236
  {
234
237
  if (m->is_invisible()) return;
235
238
 
@@ -266,7 +269,7 @@ namespace Sass {
266
269
  append_scope_closer();
267
270
  }
268
271
 
269
- void Output::operator()(Directive_Ptr a)
272
+ void Output::operator()(Directive* a)
270
273
  {
271
274
  std::string kwd = a->keyword();
272
275
  Selector_Obj s = a->selector();
@@ -309,7 +312,7 @@ namespace Sass {
309
312
  append_scope_closer();
310
313
  }
311
314
 
312
- void Output::operator()(String_Quoted_Ptr s)
315
+ void Output::operator()(String_Quoted* s)
313
316
  {
314
317
  if (s->quote_mark()) {
315
318
  append_token(quote(s->value(), s->quote_mark()), s);
@@ -320,7 +323,7 @@ namespace Sass {
320
323
  }
321
324
  }
322
325
 
323
- void Output::operator()(String_Constant_Ptr s)
326
+ void Output::operator()(String_Constant* s)
324
327
  {
325
328
  std::string value(s->value());
326
329
  if (s->can_compress_whitespace() && output_style() == COMPRESSED) {
@@ -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();
@@ -28,24 +21,24 @@ namespace Sass {
28
21
 
29
22
  protected:
30
23
  std::string charset;
31
- std::vector<AST_Node_Ptr> top_nodes;
24
+ std::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()(Ruleset*);
31
+ virtual void operator()(Supports_Block*);
32
+ virtual void operator()(Media_Block*);
33
+ virtual void operator()(Directive*);
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,4 +1,7 @@
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
6
  #include "file.hpp"
4
7
  #include "inspect.hpp"
@@ -8,6 +11,7 @@
8
11
  #include "color_maps.hpp"
9
12
  #include "sass/functions.h"
10
13
  #include "error_handling.hpp"
14
+ #include "util_string.hpp"
11
15
 
12
16
  // Notes about delayed: some ast nodes can have delayed evaluation so
13
17
  // they can preserve their original semantics if needed. This is most
@@ -30,11 +34,11 @@ namespace Sass {
30
34
  using namespace Constants;
31
35
  using namespace Prelexer;
32
36
 
33
- Parser Parser::from_c_str(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source)
37
+ Parser Parser::from_c_str(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source, bool allow_parent)
34
38
  {
35
39
  pstate.offset.column = 0;
36
40
  pstate.offset.line = 0;
37
- Parser p(ctx, pstate, traces);
41
+ Parser p(ctx, pstate, traces, allow_parent);
38
42
  p.source = source ? source : beg;
39
43
  p.position = beg ? beg : p.source;
40
44
  p.end = p.position + strlen(p.position);
@@ -44,11 +48,11 @@ namespace Sass {
44
48
  return p;
45
49
  }
46
50
 
47
- Parser Parser::from_c_str(const char* beg, const char* end, Context& ctx, Backtraces traces, ParserState pstate, const char* source)
51
+ Parser Parser::from_c_str(const char* beg, const char* end, Context& ctx, Backtraces traces, ParserState pstate, const char* source, bool allow_parent)
48
52
  {
49
53
  pstate.offset.column = 0;
50
54
  pstate.offset.line = 0;
51
- Parser p(ctx, pstate, traces);
55
+ Parser p(ctx, pstate, traces, allow_parent);
52
56
  p.source = source ? source : beg;
53
57
  p.position = beg ? beg : p.source;
54
58
  p.end = end ? end : p.position + strlen(p.position);
@@ -66,10 +70,9 @@ namespace Sass {
66
70
  pstate.offset.line = 0;
67
71
  }
68
72
 
69
- Selector_List_Obj Parser::parse_selector(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source)
73
+ Selector_List_Obj Parser::parse_selector(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source, bool allow_parent)
70
74
  {
71
- Parser p = Parser::from_c_str(beg, ctx, traces, pstate, source);
72
- // ToDo: ruby sass errors on parent references
75
+ Parser p = Parser::from_c_str(beg, ctx, traces, pstate, source, allow_parent);
73
76
  // ToDo: remap the source-map entries somehow
74
77
  return p.parse_selector_list(false);
75
78
  }
@@ -333,11 +336,11 @@ namespace Sass {
333
336
  do {
334
337
  while (lex< block_comment >());
335
338
  if (lex< quoted_string >()) {
336
- to_import.push_back(std::pair<std::string,Function_Call_Obj>(std::string(lexed), 0));
339
+ to_import.push_back(std::pair<std::string,Function_Call_Obj>(std::string(lexed), {}));
337
340
  }
338
341
  else if (lex< uri_prefix >()) {
339
342
  Arguments_Obj args = SASS_MEMORY_NEW(Arguments, pstate);
340
- Function_Call_Obj result = SASS_MEMORY_NEW(Function_Call, pstate, "url", args);
343
+ Function_Call_Obj result = SASS_MEMORY_NEW(Function_Call, pstate, std::string("url"), args);
341
344
 
342
345
  if (lex< quoted_string >()) {
343
346
  Expression_Obj quoted_url = parse_string();
@@ -479,7 +482,7 @@ namespace Sass {
479
482
  bool is_arglist = false;
480
483
  bool is_keyword = false;
481
484
  Expression_Obj val = parse_space_list();
482
- List_Ptr l = Cast<List>(val);
485
+ List* l = Cast<List>(val);
483
486
  if (lex_css< exactly< ellipsis > >()) {
484
487
  if (val->concrete_type() == Expression::MAP || (
485
488
  (l != NULL && l->separator() == SASS_HASH)
@@ -556,7 +559,7 @@ namespace Sass {
556
559
  lex< optional_spaces >();
557
560
  const char* i = position;
558
561
  // selector schema re-uses string schema implementation
559
- String_Schema_Ptr schema = SASS_MEMORY_NEW(String_Schema, pstate);
562
+ String_Schema* schema = SASS_MEMORY_NEW(String_Schema, pstate);
560
563
  // the selector schema is pretty much just a wrapper for the string schema
561
564
  Selector_Schema_Obj selector_schema = SASS_MEMORY_NEW(Selector_Schema, pstate, schema);
562
565
  selector_schema->connect_parent(chroot == false);
@@ -645,13 +648,27 @@ namespace Sass {
645
648
  // normalize underscores to hyphens
646
649
  std::string name(Util::normalize_underscores(lexed));
647
650
  // create the initial mixin call object
648
- Mixin_Call_Obj call = SASS_MEMORY_NEW(Mixin_Call, pstate, name, 0, 0);
651
+ Mixin_Call_Obj call = SASS_MEMORY_NEW(Mixin_Call, pstate, name, {}, {}, {});
649
652
  // parse mandatory arguments
650
653
  call->arguments(parse_arguments());
654
+ // parse using and optional block parameters
655
+ bool has_parameters = lex< kwd_using >() != nullptr;
656
+
657
+ if (has_parameters) {
658
+ if (!peek< exactly<'('> >()) css_error("Invalid CSS", " after ", ": expected \"(\", was ");
659
+ } else {
660
+ if (peek< exactly<'('> >()) css_error("Invalid CSS", " after ", ": expected \";\", was ");
661
+ }
662
+
663
+ if (has_parameters) call->block_parameters(parse_parameters());
664
+
651
665
  // parse optional block
652
666
  if (peek < exactly <'{'> >()) {
653
667
  call->block(parse_block());
654
668
  }
669
+ else if (has_parameters) {
670
+ css_error("Invalid CSS", " after ", ": expected \"{\", was ");
671
+ }
655
672
  // return ast node
656
673
  return call.detach();
657
674
  }
@@ -706,7 +723,7 @@ namespace Sass {
706
723
  }
707
724
  // update for end position
708
725
  group->update_pstate(pstate);
709
- if (sel) sel->last()->has_line_break(false);
726
+ if (sel) sel->mutable_last()->has_line_break(false);
710
727
  return group.detach();
711
728
  }
712
729
  // EO parse_selector_list
@@ -719,12 +736,12 @@ namespace Sass {
719
736
  {
720
737
 
721
738
  NESTING_GUARD(nestings);
722
- String_Obj reference = 0;
739
+ String_Obj reference;
723
740
  lex < block_comment >();
724
741
  advanceToNextToken();
725
742
  Complex_Selector_Obj sel = SASS_MEMORY_NEW(Complex_Selector, pstate);
726
743
 
727
- if (peek < end_of_file >()) return 0;
744
+ if (peek < end_of_file >()) return {};
728
745
 
729
746
  // parse the left hand side
730
747
  Compound_Selector_Obj lhs;
@@ -743,12 +760,12 @@ namespace Sass {
743
760
  else if (lex< sequence < exactly<'/'>, negate < exactly < '*' > > > >()) {
744
761
  // comments are allowed, but not spaces?
745
762
  combinator = Complex_Selector::REFERENCE;
746
- if (!lex < re_reference_combinator >()) return 0;
763
+ if (!lex < re_reference_combinator >()) return {};
747
764
  reference = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
748
- if (!lex < exactly < '/' > >()) return 0; // ToDo: error msg?
765
+ if (!lex < exactly < '/' > >()) return {}; // ToDo: error msg?
749
766
  }
750
767
 
751
- if (!lhs && combinator == Complex_Selector::ANCESTOR_OF) return 0;
768
+ if (!lhs && combinator == Complex_Selector::ANCESTOR_OF) return {};
752
769
 
753
770
  // lex < block_comment >();
754
771
  sel->head(lhs);
@@ -771,7 +788,7 @@ namespace Sass {
771
788
  if (!sel->has_parent_ref() && !chroot) {
772
789
  // create the objects to wrap parent selector reference
773
790
  Compound_Selector_Obj head = SASS_MEMORY_NEW(Compound_Selector, pstate);
774
- Parent_Selector_Ptr parent = SASS_MEMORY_NEW(Parent_Selector, pstate, false);
791
+ Parent_Selector* parent = SASS_MEMORY_NEW(Parent_Selector, pstate, false);
775
792
  parent->media_block(last_media_block);
776
793
  head->media_block(last_media_block);
777
794
  // add simple selector
@@ -818,6 +835,7 @@ namespace Sass {
818
835
  // parse parent selector
819
836
  else if (lex< exactly<'&'> >(false))
820
837
  {
838
+ if (!allow_parent) error("Parent selectors aren't allowed here.");
821
839
  // this produces a linefeed!?
822
840
  seq->has_parent_reference(true);
823
841
  seq->append(SASS_MEMORY_NEW(Parent_Selector, pstate));
@@ -837,7 +855,7 @@ namespace Sass {
837
855
  // parse type selector
838
856
  else if (lex< re_type_selector >(false))
839
857
  {
840
- seq->append(SASS_MEMORY_NEW(Element_Selector, pstate, lexed));
858
+ seq->append(SASS_MEMORY_NEW(Type_Selector, pstate, lexed));
841
859
  }
842
860
  // peek for abort conditions
843
861
  else if (peek< spaces >()) break;
@@ -847,7 +865,7 @@ namespace Sass {
847
865
  // otherwise parse another simple selector
848
866
  else {
849
867
  Simple_Selector_Obj sel = parse_simple_selector();
850
- if (!sel) return 0;
868
+ if (!sel) return {};
851
869
  seq->append(sel);
852
870
  }
853
871
  }
@@ -872,7 +890,7 @@ namespace Sass {
872
890
  return SASS_MEMORY_NEW(Id_Selector, pstate, lexed);
873
891
  }
874
892
  else if (lex< alternatives < variable, number, static_reference_combinator > >()) {
875
- return SASS_MEMORY_NEW(Element_Selector, pstate, lexed);
893
+ return SASS_MEMORY_NEW(Type_Selector, pstate, lexed);
876
894
  }
877
895
  else if (peek< pseudo_not >()) {
878
896
  return parse_negated_selector();
@@ -887,7 +905,7 @@ namespace Sass {
887
905
  return parse_attribute_selector();
888
906
  }
889
907
  else if (lex< placeholder >()) {
890
- Placeholder_Selector_Ptr sel = SASS_MEMORY_NEW(Placeholder_Selector, pstate, lexed);
908
+ Placeholder_Selector* sel = SASS_MEMORY_NEW(Placeholder_Selector, pstate, lexed);
891
909
  sel->media_block(last_media_block);
892
910
  return sel;
893
911
  }
@@ -895,7 +913,7 @@ namespace Sass {
895
913
  css_error("Invalid CSS", " after ", ": expected selector, was ");
896
914
  }
897
915
  // failed
898
- return 0;
916
+ return {};
899
917
  }
900
918
 
901
919
  Wrapped_Selector_Obj Parser::parse_negated_selector()
@@ -915,7 +933,7 @@ namespace Sass {
915
933
  // it can contain more selectors inside parentheses
916
934
  Simple_Selector_Obj Parser::parse_pseudo_selector() {
917
935
  if (lex< sequence<
918
- optional < pseudo_prefix >,
936
+ pseudo_prefix,
919
937
  // we keep the space within the name, strange enough
920
938
  // ToDo: refactor output to schedule the space for it
921
939
  // or do we really want to keep the real white-space?
@@ -966,7 +984,7 @@ namespace Sass {
966
984
  css_error("Invalid CSS", " after ", ": expected \")\", was ");
967
985
 
968
986
  // unreachable statement
969
- return 0;
987
+ return {};
970
988
  }
971
989
 
972
990
  const char* Parser::re_attr_sensitive_close(const char* src)
@@ -985,11 +1003,11 @@ namespace Sass {
985
1003
  if (!lex_css< attribute_name >()) error("invalid attribute name in attribute selector");
986
1004
  std::string name(lexed);
987
1005
  if (lex_css< re_attr_sensitive_close >()) {
988
- return SASS_MEMORY_NEW(Attribute_Selector, p, name, "", 0, 0);
1006
+ return SASS_MEMORY_NEW(Attribute_Selector, p, name, "", {}, {});
989
1007
  }
990
1008
  else if (lex_css< re_attr_insensitive_close >()) {
991
1009
  char modifier = lexed.begin[0];
992
- return SASS_MEMORY_NEW(Attribute_Selector, p, name, "", 0, modifier);
1010
+ return SASS_MEMORY_NEW(Attribute_Selector, p, name, "", {}, modifier);
993
1011
  }
994
1012
  if (!lex_css< alternatives< exact_match, class_match, dash_match,
995
1013
  prefix_match, suffix_match, substring_match > >()) {
@@ -997,7 +1015,7 @@ namespace Sass {
997
1015
  }
998
1016
  std::string matcher(lexed);
999
1017
 
1000
- String_Obj value = 0;
1018
+ String_Obj value;
1001
1019
  if (lex_css< identifier >()) {
1002
1020
  value = SASS_MEMORY_NEW(String_Constant, p, lexed);
1003
1021
  }
@@ -1016,7 +1034,7 @@ namespace Sass {
1016
1034
  return SASS_MEMORY_NEW(Attribute_Selector, p, name, matcher, value, modifier);
1017
1035
  }
1018
1036
  error("unterminated attribute selector for " + name);
1019
- return NULL; // to satisfy compilers (error must not return)
1037
+ return {}; // to satisfy compilers (error must not return)
1020
1038
  }
1021
1039
 
1022
1040
  /* parse block comment and add to block */
@@ -1072,7 +1090,7 @@ namespace Sass {
1072
1090
  }
1073
1091
  else {
1074
1092
  value = parse_list(DELAYED);
1075
- if (List_Ptr list = Cast<List>(value)) {
1093
+ if (List* list = Cast<List>(value)) {
1076
1094
  if (!list->is_bracketed() && list->length() == 0 && !peek< exactly <'{'> >()) {
1077
1095
  css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
1078
1096
  }
@@ -1478,7 +1496,7 @@ namespace Sass {
1478
1496
  }
1479
1497
  else if (lex< identifier_schema >()) {
1480
1498
  String_Obj string = parse_identifier_schema();
1481
- if (String_Schema_Ptr schema = Cast<String_Schema>(string)) {
1499
+ if (String_Schema* schema = Cast<String_Schema>(string)) {
1482
1500
  if (lex < exactly < '(' > >()) {
1483
1501
  schema->append(parse_list());
1484
1502
  lex < exactly < ')' > >();
@@ -1493,29 +1511,29 @@ namespace Sass {
1493
1511
  return parse_function_call();
1494
1512
  }
1495
1513
  else if (lex< exactly<'+'> >()) {
1496
- Unary_Expression_Ptr ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::PLUS, parse_factor());
1514
+ Unary_Expression* ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::PLUS, parse_factor());
1497
1515
  if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
1498
1516
  return ex;
1499
1517
  }
1500
1518
  else if (lex< exactly<'-'> >()) {
1501
- Unary_Expression_Ptr ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::MINUS, parse_factor());
1519
+ Unary_Expression* ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::MINUS, parse_factor());
1502
1520
  if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
1503
1521
  return ex;
1504
1522
  }
1505
1523
  else if (lex< exactly<'/'> >()) {
1506
- Unary_Expression_Ptr ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::SLASH, parse_factor());
1524
+ Unary_Expression* ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::SLASH, parse_factor());
1507
1525
  if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
1508
1526
  return ex;
1509
1527
  }
1510
1528
  else if (lex< sequence< kwd_not > >()) {
1511
- Unary_Expression_Ptr ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::NOT, parse_factor());
1529
+ Unary_Expression* ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::NOT, parse_factor());
1512
1530
  if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
1513
1531
  return ex;
1514
1532
  }
1515
1533
  // this whole branch is never hit via spec tests
1516
1534
  else if (peek < sequence < one_plus < alternatives < css_whitespace, exactly<'-'>, exactly<'+'> > >, number > >()) {
1517
1535
  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());
1536
+ Unary_Expression* ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::MINUS, parse_value());
1519
1537
  if (ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
1520
1538
  return ex;
1521
1539
  }
@@ -1533,9 +1551,9 @@ namespace Sass {
1533
1551
  (L > 2 && parsed.substr(0, 3) == "-0.") );
1534
1552
  }
1535
1553
 
1536
- Number_Ptr Parser::lexed_number(const ParserState& pstate, const std::string& parsed)
1554
+ Number* Parser::lexed_number(const ParserState& pstate, const std::string& parsed)
1537
1555
  {
1538
- Number_Ptr nr = SASS_MEMORY_NEW(Number,
1556
+ Number* nr = SASS_MEMORY_NEW(Number,
1539
1557
  pstate,
1540
1558
  sass_strtod(parsed.c_str()),
1541
1559
  "",
@@ -1545,9 +1563,9 @@ namespace Sass {
1545
1563
  return nr;
1546
1564
  }
1547
1565
 
1548
- Number_Ptr Parser::lexed_percentage(const ParserState& pstate, const std::string& parsed)
1566
+ Number* Parser::lexed_percentage(const ParserState& pstate, const std::string& parsed)
1549
1567
  {
1550
- Number_Ptr nr = SASS_MEMORY_NEW(Number,
1568
+ Number* nr = SASS_MEMORY_NEW(Number,
1551
1569
  pstate,
1552
1570
  sass_strtod(parsed.c_str()),
1553
1571
  "%",
@@ -1557,7 +1575,7 @@ namespace Sass {
1557
1575
  return nr;
1558
1576
  }
1559
1577
 
1560
- Number_Ptr Parser::lexed_dimension(const ParserState& pstate, const std::string& parsed)
1578
+ Number* Parser::lexed_dimension(const ParserState& pstate, const std::string& parsed)
1561
1579
  {
1562
1580
  size_t L = parsed.length();
1563
1581
  size_t num_pos = parsed.find_first_not_of(" \n\r\t");
@@ -1568,7 +1586,7 @@ namespace Sass {
1568
1586
  }
1569
1587
  if (unit_pos == std::string::npos) unit_pos = L;
1570
1588
  const std::string& num = parsed.substr(num_pos, unit_pos - num_pos);
1571
- Number_Ptr nr = SASS_MEMORY_NEW(Number,
1589
+ Number* nr = SASS_MEMORY_NEW(Number,
1572
1590
  pstate,
1573
1591
  sass_strtod(num.c_str()),
1574
1592
  Token(number(parsed.c_str())),
@@ -1578,9 +1596,9 @@ namespace Sass {
1578
1596
  return nr;
1579
1597
  }
1580
1598
 
1581
- Expression_Ptr Parser::lexed_hex_color(const ParserState& pstate, const std::string& parsed)
1599
+ Value* Parser::lexed_hex_color(const ParserState& pstate, const std::string& parsed)
1582
1600
  {
1583
- Color_Ptr color = NULL;
1601
+ Color_RGBA* color = NULL;
1584
1602
  if (parsed[0] != '#') {
1585
1603
  return SASS_MEMORY_NEW(String_Quoted, pstate, parsed);
1586
1604
  }
@@ -1590,7 +1608,7 @@ namespace Sass {
1590
1608
  std::string r(2, parsed[1]);
1591
1609
  std::string g(2, parsed[2]);
1592
1610
  std::string b(2, parsed[3]);
1593
- color = SASS_MEMORY_NEW(Color,
1611
+ color = SASS_MEMORY_NEW(Color_RGBA,
1594
1612
  pstate,
1595
1613
  static_cast<double>(strtol(r.c_str(), NULL, 16)),
1596
1614
  static_cast<double>(strtol(g.c_str(), NULL, 16)),
@@ -1598,11 +1616,24 @@ namespace Sass {
1598
1616
  1, // alpha channel
1599
1617
  parsed);
1600
1618
  }
1619
+ else if (parsed.length() == 5) {
1620
+ std::string r(2, parsed[1]);
1621
+ std::string g(2, parsed[2]);
1622
+ std::string b(2, parsed[3]);
1623
+ std::string a(2, parsed[4]);
1624
+ color = SASS_MEMORY_NEW(Color_RGBA,
1625
+ pstate,
1626
+ static_cast<double>(strtol(r.c_str(), NULL, 16)),
1627
+ static_cast<double>(strtol(g.c_str(), NULL, 16)),
1628
+ static_cast<double>(strtol(b.c_str(), NULL, 16)),
1629
+ static_cast<double>(strtol(a.c_str(), NULL, 16)) / 255,
1630
+ parsed);
1631
+ }
1601
1632
  else if (parsed.length() == 7) {
1602
1633
  std::string r(parsed.substr(1,2));
1603
1634
  std::string g(parsed.substr(3,2));
1604
1635
  std::string b(parsed.substr(5,2));
1605
- color = SASS_MEMORY_NEW(Color,
1636
+ color = SASS_MEMORY_NEW(Color_RGBA,
1606
1637
  pstate,
1607
1638
  static_cast<double>(strtol(r.c_str(), NULL, 16)),
1608
1639
  static_cast<double>(strtol(g.c_str(), NULL, 16)),
@@ -1615,7 +1646,7 @@ namespace Sass {
1615
1646
  std::string g(parsed.substr(3,2));
1616
1647
  std::string b(parsed.substr(5,2));
1617
1648
  std::string a(parsed.substr(7,2));
1618
- color = SASS_MEMORY_NEW(Color,
1649
+ color = SASS_MEMORY_NEW(Color_RGBA,
1619
1650
  pstate,
1620
1651
  static_cast<double>(strtol(r.c_str(), NULL, 16)),
1621
1652
  static_cast<double>(strtol(g.c_str(), NULL, 16)),
@@ -1628,6 +1659,19 @@ namespace Sass {
1628
1659
  return color;
1629
1660
  }
1630
1661
 
1662
+ Value* Parser::color_or_string(const std::string& lexed) const
1663
+ {
1664
+ if (auto color = name_to_color(lexed)) {
1665
+ auto c = SASS_MEMORY_NEW(Color_RGBA, color);
1666
+ c->is_delayed(true);
1667
+ c->pstate(pstate);
1668
+ c->disp(lexed);
1669
+ return c;
1670
+ } else {
1671
+ return SASS_MEMORY_NEW(String_Constant, pstate, lexed);
1672
+ }
1673
+ }
1674
+
1631
1675
  // parse one value for a list
1632
1676
  Expression_Obj Parser::parse_value()
1633
1677
  {
@@ -1637,7 +1681,7 @@ namespace Sass {
1637
1681
  if (match< ampersand >()) {
1638
1682
  warning("In Sass, \"&&\" means two copies of the parent selector. You probably want to use \"and\" instead.", pstate);
1639
1683
  }
1640
- return SASS_MEMORY_NEW(Parent_Selector, pstate); }
1684
+ return SASS_MEMORY_NEW(Parent_Reference, pstate); }
1641
1685
 
1642
1686
  if (lex< kwd_important >())
1643
1687
  { return SASS_MEMORY_NEW(String_Constant, pstate, "!important"); }
@@ -1670,7 +1714,7 @@ namespace Sass {
1670
1714
  { return SASS_MEMORY_NEW(Null, pstate); }
1671
1715
 
1672
1716
  if (lex< identifier >()) {
1673
- return SASS_MEMORY_NEW(String_Constant, pstate, lexed);
1717
+ return color_or_string(lexed);
1674
1718
  }
1675
1719
 
1676
1720
  if (lex< percentage >())
@@ -1681,17 +1725,7 @@ namespace Sass {
1681
1725
  { return lexed_hex_color(lexed); }
1682
1726
 
1683
1727
  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
- }
1728
+ { return lexed_hex_color(lexed); }
1695
1729
 
1696
1730
  if (lex< sequence < exactly <'#'>, identifier > >())
1697
1731
  { return SASS_MEMORY_NEW(String_Quoted, pstate, lexed); }
@@ -1710,14 +1744,10 @@ namespace Sass {
1710
1744
  if (lex< variable >())
1711
1745
  { return SASS_MEMORY_NEW(Variable, pstate, Util::normalize_underscores(lexed)); }
1712
1746
 
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
1747
  css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
1718
1748
 
1719
1749
  // unreachable statement
1720
- return 0;
1750
+ return {};
1721
1751
  }
1722
1752
 
1723
1753
  // this parses interpolation inside other strings
@@ -1730,7 +1760,7 @@ namespace Sass {
1730
1760
  find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, chunk.end);
1731
1761
 
1732
1762
  if (!p) {
1733
- String_Quoted_Ptr str_quoted = SASS_MEMORY_NEW(String_Quoted, pstate, std::string(i, chunk.end), 0, false, false, true, css);
1763
+ String_Quoted* str_quoted = SASS_MEMORY_NEW(String_Quoted, pstate, std::string(i, chunk.end), 0, false, false, true, css);
1734
1764
  if (!constant && str_quoted->quote_mark()) str_quoted->quote_mark('*');
1735
1765
  return str_quoted;
1736
1766
  }
@@ -1774,74 +1804,66 @@ namespace Sass {
1774
1804
  return schema.detach();
1775
1805
  }
1776
1806
 
1777
- String_Schema_Obj Parser::parse_css_variable_value(bool top_level)
1807
+ String_Schema_Obj Parser::parse_css_variable_value()
1778
1808
  {
1779
1809
  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(")")));
1810
+ std::vector<char> brackets;
1811
+ while (true) {
1812
+ if (
1813
+ (brackets.empty() && lex< css_variable_top_level_value >(false)) ||
1814
+ (!brackets.empty() && lex< css_variable_value >(false))
1815
+ ) {
1816
+ Token str(lexed);
1817
+ schema->append(SASS_MEMORY_NEW(String_Constant, pstate, str));
1818
+ } else if (Expression_Obj tok = lex_interpolation()) {
1819
+ if (String_Schema* s = Cast<String_Schema>(tok)) {
1820
+ if (s->empty()) break;
1821
+ schema->concat(s);
1822
+ } else {
1823
+ schema->append(tok);
1825
1824
  }
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("]")));
1825
+ } else if (lex< quoted_string >()) {
1826
+ Expression_Obj tok = parse_string();
1827
+ if (tok.isNull()) break;
1828
+ if (String_Schema* s = Cast<String_Schema>(tok)) {
1829
+ if (s->empty()) break;
1830
+ schema->concat(s);
1831
+ } else {
1832
+ schema->append(tok);
1831
1833
  }
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("}")));
1834
+ } else if (lex< alternatives< exactly<'('>, exactly<'['>, exactly<'{'> > >()) {
1835
+ const char opening_bracket = *(position - 1);
1836
+ brackets.push_back(opening_bracket);
1837
+ schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(1, opening_bracket)));
1838
+ } else if (const char *match = peek< alternatives< exactly<')'>, exactly<']'>, exactly<'}'> > >()) {
1839
+ if (brackets.empty()) break;
1840
+ const char closing_bracket = *(match - 1);
1841
+ if (brackets.back() != Util::opening_bracket_for(closing_bracket)) {
1842
+ std::string message = ": expected \"";
1843
+ message += Util::closing_bracket_for(brackets.back());
1844
+ message += "\", was ";
1845
+ css_error("Invalid CSS", " after ", message);
1837
1846
  }
1847
+ lex< alternatives< exactly<')'>, exactly<']'>, exactly<'}'> > >();
1848
+ schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(1, closing_bracket)));
1849
+ brackets.pop_back();
1850
+ } else {
1851
+ break;
1838
1852
  }
1839
1853
  }
1840
1854
 
1841
- return schema->length() > 0 ? schema.detach() : NULL;
1855
+ if (!brackets.empty()) {
1856
+ std::string message = ": expected \"";
1857
+ message += Util::closing_bracket_for(brackets.back());
1858
+ message += "\", was ";
1859
+ css_error("Invalid CSS", " after ", message);
1860
+ }
1861
+
1862
+ if (schema->empty()) error("Custom property values may not be empty.");
1863
+ return schema.detach();
1842
1864
  }
1843
1865
 
1844
- String_Constant_Obj Parser::parse_static_value()
1866
+ Value_Obj Parser::parse_static_value()
1845
1867
  {
1846
1868
  lex< static_value >();
1847
1869
  Token str(lexed);
@@ -1852,8 +1874,7 @@ namespace Sass {
1852
1874
  --str.end;
1853
1875
  --position;
1854
1876
 
1855
- String_Constant_Ptr str_node = SASS_MEMORY_NEW(String_Constant, pstate, str.time_wspace());
1856
- return str_node;
1877
+ return color_or_string(str.time_wspace());;
1857
1878
  }
1858
1879
 
1859
1880
  String_Obj Parser::parse_string()
@@ -1872,7 +1893,7 @@ namespace Sass {
1872
1893
  return SASS_MEMORY_NEW(String_Quoted, pstate, std::string(str.begin, str.end));
1873
1894
  }
1874
1895
 
1875
- String_Schema_Ptr schema = SASS_MEMORY_NEW(String_Schema, pstate);
1896
+ String_Schema* schema = SASS_MEMORY_NEW(String_Schema, pstate);
1876
1897
  while (i < str.end) {
1877
1898
  p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, str.end);
1878
1899
  if (p) {
@@ -1907,7 +1928,7 @@ namespace Sass {
1907
1928
 
1908
1929
  String_Obj Parser::parse_ie_keyword_arg()
1909
1930
  {
1910
- String_Schema_Ptr kwd_arg = SASS_MEMORY_NEW(String_Schema, pstate, 3);
1931
+ String_Schema_Obj kwd_arg = SASS_MEMORY_NEW(String_Schema, pstate, 3);
1911
1932
  if (lex< variable >()) {
1912
1933
  kwd_arg->append(SASS_MEMORY_NEW(Variable, pstate, Util::normalize_underscores(lexed)));
1913
1934
  } else {
@@ -1962,7 +1983,7 @@ namespace Sass {
1962
1983
  if (lex< re_static_expression >()) {
1963
1984
  ex = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
1964
1985
  } else {
1965
- ex = parse_list();
1986
+ ex = parse_list(true);
1966
1987
  }
1967
1988
  ex->is_interpolant(true);
1968
1989
  schema->append(ex);
@@ -1986,7 +2007,7 @@ namespace Sass {
1986
2007
  }
1987
2008
  if (peek < exactly < '-' > >()) break;
1988
2009
  }
1989
- else if (lex< sequence < identifier > >()) {
2010
+ else if (lex< identifier >()) {
1990
2011
  schema->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
1991
2012
  if ((*position == '"' || *position == '\'') || peek < alternatives < alpha > >()) {
1992
2013
  // need_space = true;
@@ -2128,7 +2149,7 @@ namespace Sass {
2128
2149
  uri = url_string->to_string({ NESTED, 5 });
2129
2150
  }
2130
2151
 
2131
- if (String_Schema_Ptr schema = Cast<String_Schema>(url_string)) {
2152
+ if (String_Schema* schema = Cast<String_Schema>(url_string)) {
2132
2153
  String_Schema_Obj res = SASS_MEMORY_NEW(String_Schema, pstate);
2133
2154
  res->append(SASS_MEMORY_NEW(String_Constant, pstate, prefix));
2134
2155
  res->append(schema);
@@ -2155,6 +2176,7 @@ namespace Sass {
2155
2176
  while (pp && peek< exactly< hash_lbrace > >(pp)) {
2156
2177
  pp = sequence< interpolant, real_uri_value >(pp);
2157
2178
  }
2179
+ if (!pp) return {};
2158
2180
  position = pp;
2159
2181
  return parse_interpolated_chunk(Token(p, position));
2160
2182
  }
@@ -2163,7 +2185,7 @@ namespace Sass {
2163
2185
  return SASS_MEMORY_NEW(String_Constant, pstate, res);
2164
2186
  }
2165
2187
 
2166
- return 0;
2188
+ return {};
2167
2189
  }
2168
2190
 
2169
2191
  Function_Call_Obj Parser::parse_function_call()
@@ -2179,18 +2201,21 @@ namespace Sass {
2179
2201
  return SASS_MEMORY_NEW(Function_Call, call_pos, name, args);
2180
2202
  }
2181
2203
 
2182
- Function_Call_Schema_Obj Parser::parse_function_call_schema()
2204
+ Function_Call_Obj Parser::parse_function_call_schema()
2183
2205
  {
2184
2206
  String_Obj name = parse_identifier_schema();
2185
2207
  ParserState source_position_of_call = pstate;
2186
2208
  Arguments_Obj args = parse_arguments();
2187
2209
 
2188
- return SASS_MEMORY_NEW(Function_Call_Schema, source_position_of_call, name, args);
2210
+ return SASS_MEMORY_NEW(Function_Call, source_position_of_call, name, args);
2189
2211
  }
2190
2212
 
2191
2213
  Content_Obj Parser::parse_content_directive()
2192
2214
  {
2193
- return SASS_MEMORY_NEW(Content, pstate);
2215
+ ParserState call_pos = pstate;
2216
+ Arguments_Obj args = parse_arguments();
2217
+
2218
+ return SASS_MEMORY_NEW(Content, call_pos, args);
2194
2219
  }
2195
2220
 
2196
2221
  If_Obj Parser::parse_if_directive(bool else_if)
@@ -2200,7 +2225,7 @@ namespace Sass {
2200
2225
  bool root = block_stack.back()->is_root();
2201
2226
  Expression_Obj predicate = parse_list();
2202
2227
  Block_Obj block = parse_block(root);
2203
- Block_Obj alternative = NULL;
2228
+ Block_Obj alternative;
2204
2229
 
2205
2230
  // only throw away comment if we parse a case
2206
2231
  // we want all other comments to be parsed
@@ -2285,7 +2310,7 @@ namespace Sass {
2285
2310
  stack.push_back(Scope::Control);
2286
2311
  bool root = block_stack.back()->is_root();
2287
2312
  // create the initial while call object
2288
- While_Obj call = SASS_MEMORY_NEW(While, pstate, 0, 0);
2313
+ While_Obj call = SASS_MEMORY_NEW(While, pstate, {}, {});
2289
2314
  // parse mandatory predicate
2290
2315
  Expression_Obj predicate = parse_list();
2291
2316
  List_Obj l = Cast<List>(predicate);
@@ -2305,7 +2330,7 @@ namespace Sass {
2305
2330
  Media_Block_Obj Parser::parse_media_block()
2306
2331
  {
2307
2332
  stack.push_back(Scope::Media);
2308
- Media_Block_Obj media_block = SASS_MEMORY_NEW(Media_Block, pstate, 0, 0);
2333
+ Media_Block_Obj media_block = SASS_MEMORY_NEW(Media_Block, pstate, {}, {});
2309
2334
 
2310
2335
  media_block->media_queries(parse_media_queries());
2311
2336
 
@@ -2327,7 +2352,7 @@ namespace Sass {
2327
2352
  return queries.detach();
2328
2353
  }
2329
2354
 
2330
- // Expression_Ptr Parser::parse_media_query()
2355
+ // Expression* Parser::parse_media_query()
2331
2356
  Media_Query_Obj Parser::parse_media_query()
2332
2357
  {
2333
2358
  advanceToNextToken();
@@ -2341,7 +2366,7 @@ namespace Sass {
2341
2366
 
2342
2367
  while (lex_css < kwd_and >()) media_query->append(parse_media_expression());
2343
2368
  if (lex < identifier_schema >()) {
2344
- String_Schema_Ptr schema = SASS_MEMORY_NEW(String_Schema, pstate);
2369
+ String_Schema* schema = SASS_MEMORY_NEW(String_Schema, pstate);
2345
2370
  schema->append(media_query->media_type());
2346
2371
  schema->append(SASS_MEMORY_NEW(String_Constant, pstate, " "));
2347
2372
  schema->append(parse_identifier_schema());
@@ -2358,7 +2383,7 @@ namespace Sass {
2358
2383
  {
2359
2384
  if (lex < identifier_schema >()) {
2360
2385
  String_Obj ss = parse_identifier_schema();
2361
- return SASS_MEMORY_NEW(Media_Query_Expression, pstate, ss, 0, true);
2386
+ return SASS_MEMORY_NEW(Media_Query_Expression, pstate, ss, {}, true);
2362
2387
  }
2363
2388
  if (!lex_css< exactly<'('> >()) {
2364
2389
  error("media query expression must begin with '('");
@@ -2368,7 +2393,7 @@ namespace Sass {
2368
2393
  error("media feature required in media query expression");
2369
2394
  }
2370
2395
  feature = parse_expression();
2371
- Expression_Obj expression = 0;
2396
+ Expression_Obj expression;
2372
2397
  if (lex_css< exactly<':'> >()) {
2373
2398
  expression = parse_list(DELAYED);
2374
2399
  }
@@ -2382,10 +2407,7 @@ namespace Sass {
2382
2407
  // these are very similar to media blocks
2383
2408
  Supports_Block_Obj Parser::parse_supports_directive()
2384
2409
  {
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
- }
2410
+ Supports_Condition_Obj cond = parse_supports_condition(/*top_level=*/true);
2389
2411
  // create the ast node object for the support queries
2390
2412
  Supports_Block_Obj query = SASS_MEMORY_NEW(Supports_Block, pstate, cond);
2391
2413
  // additional block is mandatory
@@ -2397,27 +2419,27 @@ namespace Sass {
2397
2419
 
2398
2420
  // parse one query operation
2399
2421
  // may encounter nested queries
2400
- Supports_Condition_Obj Parser::parse_supports_condition()
2422
+ Supports_Condition_Obj Parser::parse_supports_condition(bool top_level)
2401
2423
  {
2402
2424
  lex < css_whitespace >();
2403
2425
  Supports_Condition_Obj cond;
2404
2426
  if ((cond = parse_supports_negation())) return cond;
2405
- if ((cond = parse_supports_operator())) return cond;
2427
+ if ((cond = parse_supports_operator(top_level))) return cond;
2406
2428
  if ((cond = parse_supports_interpolation())) return cond;
2407
2429
  return cond;
2408
2430
  }
2409
2431
 
2410
2432
  Supports_Condition_Obj Parser::parse_supports_negation()
2411
2433
  {
2412
- if (!lex < kwd_not >()) return 0;
2413
- Supports_Condition_Obj cond = parse_supports_condition_in_parens();
2434
+ if (!lex < kwd_not >()) return {};
2435
+ Supports_Condition_Obj cond = parse_supports_condition_in_parens(/*parens_required=*/true);
2414
2436
  return SASS_MEMORY_NEW(Supports_Negation, pstate, cond);
2415
2437
  }
2416
2438
 
2417
- Supports_Condition_Obj Parser::parse_supports_operator()
2439
+ Supports_Condition_Obj Parser::parse_supports_operator(bool top_level)
2418
2440
  {
2419
- Supports_Condition_Obj cond = parse_supports_condition_in_parens();
2420
- if (cond.isNull()) return 0;
2441
+ Supports_Condition_Obj cond = parse_supports_condition_in_parens(/*parens_required=*/top_level);
2442
+ if (cond.isNull()) return {};
2421
2443
 
2422
2444
  while (true) {
2423
2445
  Supports_Operator::Operand op = Supports_Operator::OR;
@@ -2425,9 +2447,9 @@ namespace Sass {
2425
2447
  else if(!lex < kwd_or >()) { break; }
2426
2448
 
2427
2449
  lex < css_whitespace >();
2428
- Supports_Condition_Obj right = parse_supports_condition_in_parens();
2450
+ Supports_Condition_Obj right = parse_supports_condition_in_parens(/*parens_required=*/true);
2429
2451
 
2430
- // Supports_Condition_Ptr cc = SASS_MEMORY_NEW(Supports_Condition, *static_cast<Supports_Condition_Ptr>(cond));
2452
+ // Supports_Condition* cc = SASS_MEMORY_NEW(Supports_Condition, *static_cast<Supports_Condition*>(cond));
2431
2453
  cond = SASS_MEMORY_NEW(Supports_Operator, pstate, cond, right, op);
2432
2454
  }
2433
2455
  return cond;
@@ -2435,10 +2457,10 @@ namespace Sass {
2435
2457
 
2436
2458
  Supports_Condition_Obj Parser::parse_supports_interpolation()
2437
2459
  {
2438
- if (!lex < interpolant >()) return 0;
2460
+ if (!lex < interpolant >()) return {};
2439
2461
 
2440
2462
  String_Obj interp = parse_interpolated_chunk(lexed);
2441
- if (!interp) return 0;
2463
+ if (!interp) return {};
2442
2464
 
2443
2465
  return SASS_MEMORY_NEW(Supports_Interpolation, pstate, interp);
2444
2466
  }
@@ -2447,10 +2469,10 @@ namespace Sass {
2447
2469
  // look like declarations their semantics differ significantly
2448
2470
  Supports_Condition_Obj Parser::parse_supports_declaration()
2449
2471
  {
2450
- Supports_Condition_Ptr cond;
2472
+ Supports_Condition* cond;
2451
2473
  // parse something declaration like
2452
2474
  Expression_Obj feature = parse_expression();
2453
- Expression_Obj expression = 0;
2475
+ Expression_Obj expression;
2454
2476
  if (lex_css< exactly<':'> >()) {
2455
2477
  expression = parse_list(DELAYED);
2456
2478
  }
@@ -2463,21 +2485,24 @@ namespace Sass {
2463
2485
  return cond;
2464
2486
  }
2465
2487
 
2466
- Supports_Condition_Obj Parser::parse_supports_condition_in_parens()
2488
+ Supports_Condition_Obj Parser::parse_supports_condition_in_parens(bool parens_required)
2467
2489
  {
2468
2490
  Supports_Condition_Obj interp = parse_supports_interpolation();
2469
2491
  if (interp != 0) return interp;
2470
2492
 
2471
- if (!lex < exactly <'('> >()) return 0;
2493
+ if (!lex < exactly <'('> >()) {
2494
+ if (parens_required) {
2495
+ css_error("Invalid CSS", " after ", ": expected @supports condition (e.g. (display: flexbox)), was ", /*trim=*/false);
2496
+ } else {
2497
+ return {};
2498
+ }
2499
+ }
2472
2500
  lex < css_whitespace >();
2473
2501
 
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
- }
2502
+ Supports_Condition_Obj cond = parse_supports_condition(/*top_level=*/false);
2503
+ if (cond.isNull()) cond = parse_supports_declaration();
2504
+ if (!lex < exactly <')'> >()) error("unclosed parenthesis in @supports declaration");
2505
+
2481
2506
  lex < css_whitespace >();
2482
2507
  return cond;
2483
2508
  }
@@ -2486,7 +2511,7 @@ namespace Sass {
2486
2511
  {
2487
2512
  stack.push_back(Scope::AtRoot);
2488
2513
  ParserState at_source_position = pstate;
2489
- Block_Obj body = 0;
2514
+ Block_Obj body;
2490
2515
  At_Root_Query_Obj expr;
2491
2516
  Lookahead lookahead_result;
2492
2517
  if (lex_css< exactly<'('> >()) {
@@ -2541,7 +2566,7 @@ namespace Sass {
2541
2566
 
2542
2567
  // this whole branch is never hit via spec tests
2543
2568
 
2544
- Directive_Ptr at_rule = SASS_MEMORY_NEW(Directive, pstate, kwd);
2569
+ Directive* at_rule = SASS_MEMORY_NEW(Directive, pstate, kwd);
2545
2570
  Lookahead lookahead = lookahead_for_include(position);
2546
2571
  if (lookahead.found && !lookahead.has_interpolants) {
2547
2572
  at_rule->selector(parse_selector_list(false));
@@ -2612,7 +2637,7 @@ namespace Sass {
2612
2637
  if (lex < interpolant >(true) != NULL) {
2613
2638
  return parse_interpolated_chunk(lexed, true);
2614
2639
  }
2615
- return 0;
2640
+ return {};
2616
2641
  }
2617
2642
 
2618
2643
  Expression_Obj Parser::lex_interp_uri()
@@ -2678,30 +2703,32 @@ namespace Sass {
2678
2703
  if (match) {
2679
2704
  return SASS_MEMORY_NEW(String_Constant, pstate, lexed);
2680
2705
  }
2681
- return NULL;
2706
+ return {};
2682
2707
  }
2683
2708
 
2684
2709
  Expression_Obj Parser::lex_almost_any_value_token()
2685
2710
  {
2686
2711
  Expression_Obj rv;
2687
- if (*position == 0) return 0;
2712
+ if (*position == 0) return {};
2688
2713
  if ((rv = lex_almost_any_value_chars())) return rv;
2689
2714
  // if ((rv = lex_block_comment())) return rv;
2690
2715
  // if ((rv = lex_single_line_comment())) return rv;
2691
2716
  if ((rv = lex_interp_string())) return rv;
2692
2717
  if ((rv = lex_interp_uri())) return rv;
2693
2718
  if ((rv = lex_interpolation())) return rv;
2694
- return rv;
2719
+ if (lex< alternatives< hex, hex0 > >())
2720
+ { return lexed_hex_color(lexed); }
2721
+ return rv;
2695
2722
  }
2696
2723
 
2697
2724
  String_Schema_Obj Parser::parse_almost_any_value()
2698
2725
  {
2699
2726
 
2700
2727
  String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
2701
- if (*position == 0) return 0;
2728
+ if (*position == 0) return {};
2702
2729
  lex < spaces >(false);
2703
2730
  Expression_Obj token = lex_almost_any_value_token();
2704
- if (!token) return 0;
2731
+ if (!token) return {};
2705
2732
  schema->append(token);
2706
2733
  if (*position == 0) {
2707
2734
  schema->rtrim();
@@ -2777,6 +2804,7 @@ namespace Sass {
2777
2804
  >(p)
2778
2805
  ) {
2779
2806
  bool could_be_property = peek< sequence< exactly<'-'>, exactly<'-'> > >(p) != 0;
2807
+ bool could_be_escaped = false;
2780
2808
  while (p < q) {
2781
2809
  // did we have interpolations?
2782
2810
  if (*p == '#' && *(p+1) == '{') {
@@ -2785,9 +2813,10 @@ namespace Sass {
2785
2813
  }
2786
2814
  // A property that's ambiguous with a nested selector is interpreted as a
2787
2815
  // custom property.
2788
- if (*p == ':') {
2816
+ if (*p == ':' && !could_be_escaped) {
2789
2817
  rv.is_custom_property = could_be_property || p+1 == q || peek< space >(p+1);
2790
2818
  }
2819
+ could_be_escaped = *p == '\\';
2791
2820
  ++ p;
2792
2821
  }
2793
2822
  // store anyway }
@@ -2981,7 +3010,7 @@ namespace Sass {
2981
3010
 
2982
3011
  Expression_Obj Parser::fold_operands(Expression_Obj base, std::vector<Expression_Obj>& operands, std::vector<Operand>& ops, size_t i)
2983
3012
  {
2984
- if (String_Schema_Ptr schema = Cast<String_Schema>(base)) {
3013
+ if (String_Schema* schema = Cast<String_Schema>(base)) {
2985
3014
  // return schema;
2986
3015
  if (schema->has_interpolants()) {
2987
3016
  if (i + 1 < operands.size() && (
@@ -3004,7 +3033,7 @@ namespace Sass {
3004
3033
  }
3005
3034
 
3006
3035
  for (size_t S = operands.size(); i < S; ++i) {
3007
- if (String_Schema_Ptr schema = Cast<String_Schema>(operands[i])) {
3036
+ if (String_Schema* schema = Cast<String_Schema>(operands[i])) {
3008
3037
  if (schema->has_interpolants()) {
3009
3038
  if (i + 1 < S) {
3010
3039
  // this whole branch is never hit via spec tests
@@ -3021,13 +3050,13 @@ namespace Sass {
3021
3050
  } else {
3022
3051
  base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], base, operands[i]);
3023
3052
  }
3024
- Binary_Expression_Ptr b = Cast<Binary_Expression>(base.ptr());
3053
+ Binary_Expression* b = Cast<Binary_Expression>(base.ptr());
3025
3054
  if (b && ops[i].operand == Sass_OP::DIV && b->left()->is_delayed() && b->right()->is_delayed()) {
3026
3055
  base->is_delayed(true);
3027
3056
  }
3028
3057
  }
3029
3058
  // nested binary expression are never to be delayed
3030
- if (Binary_Expression_Ptr b = Cast<Binary_Expression>(base)) {
3059
+ if (Binary_Expression* b = Cast<Binary_Expression>(base)) {
3031
3060
  if (Cast<Binary_Expression>(b->left())) base->set_delayed(false);
3032
3061
  if (Cast<Binary_Expression>(b->right())) base->set_delayed(false);
3033
3062
  }
@@ -3038,8 +3067,11 @@ namespace Sass {
3038
3067
  {
3039
3068
  Position p(pos.line ? pos : before_token);
3040
3069
  ParserState pstate(path, source, p, Offset(0, 0));
3070
+ // `pstate.src` may not outlive stack unwind so we must copy it.
3071
+ char *src_copy = sass_copy_c_string(pstate.src);
3072
+ pstate.src = src_copy;
3041
3073
  traces.push_back(Backtrace(pstate));
3042
- throw Exception::InvalidSass(pstate, traces, msg);
3074
+ throw Exception::InvalidSass(pstate, traces, msg, src_copy);
3043
3075
  }
3044
3076
 
3045
3077
  void Parser::error(std::string msg)