sassc 1.10.1 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -2
  3. data/ext/libsass/.github/CONTRIBUTING.md +65 -0
  4. data/ext/libsass/.github/ISSUE_TEMPLATE.md +29 -0
  5. data/ext/libsass/Makefile +8 -3
  6. data/ext/libsass/Makefile.conf +28 -22
  7. data/ext/libsass/Readme.md +14 -7
  8. data/ext/libsass/configure.ac +5 -8
  9. data/ext/libsass/docs/api-context-internal.md +3 -0
  10. data/ext/libsass/docs/api-context.md +7 -0
  11. data/ext/libsass/docs/api-doc.md +4 -0
  12. data/ext/libsass/docs/api-importer.md +2 -0
  13. data/ext/libsass/docs/api-value-example.md +55 -0
  14. data/ext/libsass/docs/api-value.md +49 -22
  15. data/ext/libsass/docs/implementations.md +4 -0
  16. data/ext/libsass/include/sass/base.h +5 -4
  17. data/ext/libsass/include/sass/context.h +3 -0
  18. data/ext/libsass/include/sass/values.h +28 -27
  19. data/ext/libsass/include/sass/version.h +1 -1
  20. data/ext/libsass/include/sass2scss.h +1 -1
  21. data/ext/libsass/script/ci-build-libsass +3 -3
  22. data/ext/libsass/script/ci-install-deps +12 -3
  23. data/ext/libsass/src/ast.cpp +321 -212
  24. data/ext/libsass/src/ast.hpp +273 -165
  25. data/ext/libsass/src/ast_factory.hpp +4 -5
  26. data/ext/libsass/src/ast_fwd_decl.hpp +8 -7
  27. data/ext/libsass/src/bind.cpp +2 -7
  28. data/ext/libsass/src/bind.hpp +0 -1
  29. data/ext/libsass/src/check_nesting.cpp +379 -0
  30. data/ext/libsass/src/check_nesting.hpp +60 -0
  31. data/ext/libsass/src/constants.cpp +7 -6
  32. data/ext/libsass/src/constants.hpp +2 -1
  33. data/ext/libsass/src/context.cpp +7 -1
  34. data/ext/libsass/src/context.hpp +1 -1
  35. data/ext/libsass/src/cssize.cpp +76 -32
  36. data/ext/libsass/src/cssize.hpp +7 -8
  37. data/ext/libsass/src/debugger.hpp +70 -40
  38. data/ext/libsass/src/error_handling.cpp +15 -2
  39. data/ext/libsass/src/error_handling.hpp +19 -0
  40. data/ext/libsass/src/eval.cpp +107 -161
  41. data/ext/libsass/src/eval.hpp +12 -8
  42. data/ext/libsass/src/expand.cpp +81 -74
  43. data/ext/libsass/src/expand.hpp +13 -12
  44. data/ext/libsass/src/extend.cpp +149 -142
  45. data/ext/libsass/src/extend.hpp +10 -3
  46. data/ext/libsass/src/file.cpp +2 -1
  47. data/ext/libsass/src/functions.cpp +96 -59
  48. data/ext/libsass/src/functions.hpp +2 -2
  49. data/ext/libsass/src/inspect.cpp +33 -45
  50. data/ext/libsass/src/inspect.hpp +7 -7
  51. data/ext/libsass/src/json.cpp +17 -5
  52. data/ext/libsass/src/lexer.cpp +3 -3
  53. data/ext/libsass/src/listize.cpp +10 -10
  54. data/ext/libsass/src/listize.hpp +3 -3
  55. data/ext/libsass/src/node.cpp +30 -30
  56. data/ext/libsass/src/node.hpp +13 -13
  57. data/ext/libsass/src/operation.hpp +21 -19
  58. data/ext/libsass/src/output.cpp +48 -103
  59. data/ext/libsass/src/output.hpp +0 -1
  60. data/ext/libsass/src/parser.cpp +161 -133
  61. data/ext/libsass/src/parser.hpp +10 -7
  62. data/ext/libsass/src/remove_placeholders.cpp +6 -6
  63. data/ext/libsass/src/remove_placeholders.hpp +1 -1
  64. data/ext/libsass/src/sass.cpp +21 -0
  65. data/ext/libsass/src/sass.hpp +8 -1
  66. data/ext/libsass/src/sass2scss.cpp +14 -3
  67. data/ext/libsass/src/sass_context.cpp +69 -24
  68. data/ext/libsass/src/sass_context.hpp +3 -0
  69. data/ext/libsass/src/source_map.cpp +22 -10
  70. data/ext/libsass/src/to_value.cpp +2 -2
  71. data/ext/libsass/src/to_value.hpp +1 -1
  72. data/ext/libsass/src/units.hpp +3 -1
  73. data/ext/libsass/src/util.cpp +20 -16
  74. data/ext/libsass/src/util.hpp +2 -1
  75. data/ext/libsass/win/libsass.targets +2 -0
  76. data/ext/libsass/win/libsass.vcxproj.filters +6 -0
  77. data/lib/sassc/engine.rb +5 -0
  78. data/lib/sassc/native/native_functions_api.rb +13 -1
  79. data/lib/sassc/script/value_conversion.rb +11 -1
  80. data/lib/sassc/script/value_conversion/list.rb +23 -0
  81. data/lib/sassc/version.rb +1 -1
  82. data/test/engine_test.rb +18 -2
  83. data/test/functions_test.rb +30 -0
  84. data/test/native_test.rb +1 -1
  85. metadata +8 -3
@@ -17,7 +17,7 @@ namespace Sass {
17
17
  /*
18
18
  There are a lot of stumbling blocks when trying to port the ruby extend code to C++. The biggest is the choice of
19
19
  data type. The ruby code will pretty seamlessly switch types between an Array<SimpleSequence or Op> (libsass'
20
- equivalent is the Complex_Selector) to a Sequence, which contains more metadata about the sequence than just the
20
+ equivalent is the Sequence_Selector) to a Sequence, which contains more metadata about the sequence than just the
21
21
  selector info. They also have the ability to have arbitrary nestings of arrays like [1, [2]], which is hard to
22
22
  implement using Array equivalents in C++ (like the deque or vector). They also have the ability to include nil
23
23
  in the arrays, like [1, nil, 3], which has potential semantic differences than an empty array [1, [], 3]. To be
@@ -26,7 +26,7 @@ namespace Sass {
26
26
  more closely match the ruby code, which is a huge benefit when attempting to implement an complex algorithm like
27
27
  the Extend operator.
28
28
 
29
- Note that the current libsass data model also pairs the combinator with the Complex_Selector that follows it, but
29
+ Note that the current libsass data model also pairs the combinator with the Sequence_Selector that follows it, but
30
30
  ruby sass has no such restriction, so we attempt to create a data structure that can handle them split apart.
31
31
  */
32
32
 
@@ -50,18 +50,18 @@ namespace Sass {
50
50
  bool isNil() const { return mType == NIL; }
51
51
  bool got_line_feed;
52
52
 
53
- Complex_Selector::Combinator combinator() const { return mCombinator; }
53
+ Sequence_Selector::Combinator combinator() const { return mCombinator; }
54
54
 
55
- Complex_Selector* selector() { return mpSelector; }
56
- const Complex_Selector* selector() const { return mpSelector; }
55
+ Sequence_Selector* selector() { return mpSelector; }
56
+ const Sequence_Selector* selector() const { return mpSelector; }
57
57
 
58
58
  NodeDequePtr collection() { return mpCollection; }
59
59
  const NodeDequePtr collection() const { return mpCollection; }
60
60
 
61
- static Node createCombinator(const Complex_Selector::Combinator& combinator);
61
+ static Node createCombinator(const Sequence_Selector::Combinator& combinator);
62
62
 
63
63
  // This method will clone the selector, stripping off the tail and combinator
64
- static Node createSelector(Complex_Selector* pSelector, Context& ctx);
64
+ static Node createSelector(Sequence_Selector* pSelector, Context& ctx);
65
65
 
66
66
  static Node createCollection();
67
67
  static Node createCollection(const NodeDeque& values);
@@ -79,7 +79,7 @@ namespace Sass {
79
79
  COLLECTION FUNCTIONS
80
80
 
81
81
  Most types don't need any helper methods (nil and combinator due to their simplicity and
82
- selector due to the fact that we leverage the non-node selector code on the Complex_Selector
82
+ selector due to the fact that we leverage the non-node selector code on the Sequence_Selector
83
83
  whereever possible). The following methods are intended to be called on Node objects whose
84
84
  type is COLLECTION only.
85
85
  */
@@ -97,21 +97,21 @@ namespace Sass {
97
97
  // Private constructor; Use the static methods (like createCombinator and createSelector)
98
98
  // to instantiate this object. This is more expressive, and it allows us to break apart each
99
99
  // case into separate functions.
100
- Node(const TYPE& type, Complex_Selector::Combinator combinator, Complex_Selector* pSelector, NodeDequePtr& pCollection);
100
+ Node(const TYPE& type, Sequence_Selector::Combinator combinator, Sequence_Selector* pSelector, NodeDequePtr& pCollection);
101
101
 
102
102
  TYPE mType;
103
103
 
104
104
  // TODO: can we union these to save on memory?
105
- Complex_Selector::Combinator mCombinator;
106
- Complex_Selector* mpSelector; // this is an AST_Node, so it will be handled by the Memory_Manager
105
+ Sequence_Selector::Combinator mCombinator;
106
+ Sequence_Selector* mpSelector; // this is an AST_Node, so it will be handled by the Memory_Manager
107
107
  NodeDequePtr mpCollection;
108
108
  };
109
109
 
110
110
  #ifdef DEBUG
111
111
  std::ostream& operator<<(std::ostream& os, const Node& node);
112
112
  #endif
113
- Node complexSelectorToNode(Complex_Selector* pToConvert, Context& ctx);
114
- Complex_Selector* nodeToComplexSelector(const Node& toConvert, Context& ctx);
113
+ Node complexSelectorToNode(Sequence_Selector* pToConvert, Context& ctx);
114
+ Sequence_Selector* nodeToComplexSelector(const Node& toConvert, Context& ctx);
115
115
 
116
116
  bool nodesEqual(const Node& one, const Node& two, bool simpleSelectorOrderDependent);
117
117
 
@@ -13,12 +13,12 @@ namespace Sass {
13
13
  // statements
14
14
  virtual T operator()(Block* x) = 0;
15
15
  virtual T operator()(Ruleset* x) = 0;
16
- virtual T operator()(Propset* x) = 0;
17
16
  virtual T operator()(Bubble* x) = 0;
17
+ virtual T operator()(Trace* x) = 0;
18
18
  virtual T operator()(Supports_Block* x) = 0;
19
19
  virtual T operator()(Media_Block* x) = 0;
20
20
  virtual T operator()(At_Root_Block* x) = 0;
21
- virtual T operator()(Directive* x) = 0;
21
+ virtual T operator()(Directive* x) = 0;
22
22
  virtual T operator()(Keyframe_Rule* x) = 0;
23
23
  virtual T operator()(Declaration* x) = 0;
24
24
  virtual T operator()(Assignment* x) = 0;
@@ -61,7 +61,7 @@ namespace Sass {
61
61
  virtual T operator()(Supports_Interpolation* x) = 0;
62
62
  virtual T operator()(Media_Query* x) = 0;
63
63
  virtual T operator()(Media_Query_Expression* x) = 0;
64
- virtual T operator()(At_Root_Query* x) = 0;
64
+ virtual T operator()(At_Root_Query* x) = 0;
65
65
  virtual T operator()(Null* x) = 0;
66
66
  virtual T operator()(Parent_Selector* x) = 0;
67
67
  // parameters and arguments
@@ -71,15 +71,16 @@ namespace Sass {
71
71
  virtual T operator()(Arguments* x) = 0;
72
72
  // selectors
73
73
  virtual T operator()(Selector_Schema* x) = 0;
74
- virtual T operator()(Selector_Placeholder* x) = 0;
75
- virtual T operator()(Type_Selector* x) = 0;
76
- virtual T operator()(Selector_Qualifier* x) = 0;
74
+ virtual T operator()(Placeholder_Selector* x) = 0;
75
+ virtual T operator()(Element_Selector* x) = 0;
76
+ virtual T operator()(Class_Selector* x) = 0;
77
+ virtual T operator()(Id_Selector* x) = 0;
77
78
  virtual T operator()(Attribute_Selector* x) = 0;
78
79
  virtual T operator()(Pseudo_Selector* x) = 0;
79
80
  virtual T operator()(Wrapped_Selector* x) = 0;
80
- virtual T operator()(Compound_Selector* x) = 0;
81
- virtual T operator()(Complex_Selector* x) = 0;
82
- virtual T operator()(Selector_List* x) = 0;
81
+ virtual T operator()(SimpleSequence_Selector* x)= 0;
82
+ virtual T operator()(Sequence_Selector* x) = 0;
83
+ virtual T operator()(CommaSequence_Selector* x) = 0;
83
84
 
84
85
  template <typename U>
85
86
  T fallback(U x) { return T(); }
@@ -94,12 +95,12 @@ namespace Sass {
94
95
  // statements
95
96
  T operator()(Block* x) { return static_cast<D*>(this)->fallback(x); }
96
97
  T operator()(Ruleset* x) { return static_cast<D*>(this)->fallback(x); }
97
- T operator()(Propset* x) { return static_cast<D*>(this)->fallback(x); }
98
98
  T operator()(Bubble* x) { return static_cast<D*>(this)->fallback(x); }
99
+ T operator()(Trace* x) { return static_cast<D*>(this)->fallback(x); }
99
100
  T operator()(Supports_Block* x) { return static_cast<D*>(this)->fallback(x); }
100
101
  T operator()(Media_Block* x) { return static_cast<D*>(this)->fallback(x); }
101
102
  T operator()(At_Root_Block* x) { return static_cast<D*>(this)->fallback(x); }
102
- T operator()(Directive* x) { return static_cast<D*>(this)->fallback(x); }
103
+ T operator()(Directive* x) { return static_cast<D*>(this)->fallback(x); }
103
104
  T operator()(Keyframe_Rule* x) { return static_cast<D*>(this)->fallback(x); }
104
105
  T operator()(Declaration* x) { return static_cast<D*>(this)->fallback(x); }
105
106
  T operator()(Assignment* x) { return static_cast<D*>(this)->fallback(x); }
@@ -142,7 +143,7 @@ namespace Sass {
142
143
  T operator()(Supports_Interpolation* x) { return static_cast<D*>(this)->fallback(x); }
143
144
  T operator()(Media_Query* x) { return static_cast<D*>(this)->fallback(x); }
144
145
  T operator()(Media_Query_Expression* x) { return static_cast<D*>(this)->fallback(x); }
145
- T operator()(At_Root_Query* x) { return static_cast<D*>(this)->fallback(x); }
146
+ T operator()(At_Root_Query* x) { return static_cast<D*>(this)->fallback(x); }
146
147
  T operator()(Null* x) { return static_cast<D*>(this)->fallback(x); }
147
148
  T operator()(Parent_Selector* x) { return static_cast<D*>(this)->fallback(x); }
148
149
  // parameters and arguments
@@ -152,18 +153,19 @@ namespace Sass {
152
153
  T operator()(Arguments* x) { return static_cast<D*>(this)->fallback(x); }
153
154
  // selectors
154
155
  T operator()(Selector_Schema* x) { return static_cast<D*>(this)->fallback(x); }
155
- T operator()(Selector_Placeholder* x) { return static_cast<D*>(this)->fallback(x); }
156
- T operator()(Type_Selector* x) { return static_cast<D*>(this)->fallback(x); }
157
- T operator()(Selector_Qualifier* x) { return static_cast<D*>(this)->fallback(x); }
156
+ T operator()(Placeholder_Selector* x) { return static_cast<D*>(this)->fallback(x); }
157
+ T operator()(Element_Selector* x) { return static_cast<D*>(this)->fallback(x); }
158
+ T operator()(Class_Selector* x) { return static_cast<D*>(this)->fallback(x); }
159
+ T operator()(Id_Selector* x) { return static_cast<D*>(this)->fallback(x); }
158
160
  T operator()(Attribute_Selector* x) { return static_cast<D*>(this)->fallback(x); }
159
161
  T operator()(Pseudo_Selector* x) { return static_cast<D*>(this)->fallback(x); }
160
162
  T operator()(Wrapped_Selector* x) { return static_cast<D*>(this)->fallback(x); }
161
- T operator()(Compound_Selector* x) { return static_cast<D*>(this)->fallback(x); }
162
- T operator()(Complex_Selector* x) { return static_cast<D*>(this)->fallback(x); }
163
- T operator()(Selector_List* x) { return static_cast<D*>(this)->fallback(x); }
163
+ T operator()(SimpleSequence_Selector* x){ return static_cast<D*>(this)->fallback(x); }
164
+ T operator()(Sequence_Selector* x) { return static_cast<D*>(this)->fallback(x); }
165
+ T operator()(CommaSequence_Selector* x) { return static_cast<D*>(this)->fallback(x); }
164
166
 
165
167
  template <typename U>
166
- T fallback(U x) { return T(); }
168
+ T fallback(U x) { return T(); }
167
169
  };
168
170
 
169
171
  }
@@ -111,77 +111,65 @@ namespace Sass {
111
111
  {
112
112
  Selector* s = r->selector();
113
113
  Block* b = r->block();
114
- bool decls = false;
115
114
 
116
115
  // Filter out rulesets that aren't printable (process its children though)
117
116
  if (!Util::isPrintable(r, output_style())) {
118
117
  for (size_t i = 0, L = b->length(); i < L; ++i) {
119
118
  Statement* stm = (*b)[i];
120
119
  if (dynamic_cast<Has_Block*>(stm)) {
121
- stm->perform(this);
120
+ if (typeid(*stm) != typeid(Declaration)) {
121
+ stm->perform(this);
122
+ }
122
123
  }
123
124
  }
124
125
  return;
125
126
  }
126
127
 
127
- if (b->has_non_hoistable()) {
128
- decls = true;
129
- if (output_style() == NESTED) indentation += r->tabs();
130
- if (opt.source_comments) {
131
- std::stringstream ss;
132
- append_indentation();
133
- ss << "/* line " << r->pstate().line + 1 << ", " << r->pstate().path << " */";
134
- append_string(ss.str());
135
- append_optional_linefeed();
136
- }
137
- s->perform(this);
138
- append_scope_opener(b);
139
- for (size_t i = 0, L = b->length(); i < L; ++i) {
140
- Statement* stm = (*b)[i];
141
- bool bPrintExpression = true;
142
- // Check print conditions
143
- if (typeid(*stm) == typeid(Declaration)) {
144
- Declaration* dec = static_cast<Declaration*>(stm);
145
- if (dec->value()->concrete_type() == Expression::STRING) {
146
- String_Constant* valConst = static_cast<String_Constant*>(dec->value());
147
- std::string val(valConst->value());
148
- if (auto qstr = dynamic_cast<String_Quoted*>(valConst)) {
149
- if (!qstr->quote_mark() && val.empty()) {
150
- bPrintExpression = false;
151
- }
152
- }
153
- }
154
- else if (dec->value()->concrete_type() == Expression::LIST) {
155
- List* list = static_cast<List*>(dec->value());
156
- bool all_invisible = true;
157
- for (size_t list_i = 0, list_L = list->length(); list_i < list_L; ++list_i) {
158
- Expression* item = (*list)[list_i];
159
- if (!item->is_invisible()) all_invisible = false;
128
+ if (output_style() == NESTED) indentation += r->tabs();
129
+ if (opt.source_comments) {
130
+ std::stringstream ss;
131
+ append_indentation();
132
+ std::string path(File::abs2rel(r->pstate().path));
133
+ ss << "/* line " << r->pstate().line + 1 << ", " << path << " */";
134
+ append_string(ss.str());
135
+ append_optional_linefeed();
136
+ }
137
+ s->perform(this);
138
+ append_scope_opener(b);
139
+ for (size_t i = 0, L = b->length(); i < L; ++i) {
140
+ Statement* stm = (*b)[i];
141
+ bool bPrintExpression = true;
142
+ // Check print conditions
143
+ if (typeid(*stm) == typeid(Declaration)) {
144
+ Declaration* dec = static_cast<Declaration*>(stm);
145
+ if (dec->value()->concrete_type() == Expression::STRING) {
146
+ String_Constant* valConst = static_cast<String_Constant*>(dec->value());
147
+ std::string val(valConst->value());
148
+ if (auto qstr = dynamic_cast<String_Quoted*>(valConst)) {
149
+ if (!qstr->quote_mark() && val.empty()) {
150
+ bPrintExpression = false;
160
151
  }
161
- if (all_invisible) bPrintExpression = false;
162
152
  }
163
153
  }
164
- // Print if OK
165
- if (!stm->is_hoistable() && bPrintExpression) {
166
- stm->perform(this);
154
+ else if (dec->value()->concrete_type() == Expression::LIST) {
155
+ List* list = static_cast<List*>(dec->value());
156
+ bool all_invisible = true;
157
+ for (size_t list_i = 0, list_L = list->length(); list_i < list_L; ++list_i) {
158
+ Expression* item = (*list)[list_i];
159
+ if (!item->is_invisible()) all_invisible = false;
160
+ }
161
+ if (all_invisible) bPrintExpression = false;
167
162
  }
168
163
  }
169
- if (output_style() == NESTED) indentation -= r->tabs();
170
- append_scope_closer(b);
171
- }
172
-
173
- if (b->has_hoistable()) {
174
- if (decls) ++indentation;
175
- for (size_t i = 0, L = b->length(); i < L; ++i) {
176
- Statement* stm = (*b)[i];
177
- if (stm->is_hoistable()) {
178
- stm->perform(this);
179
- }
164
+ // Print if OK
165
+ if (bPrintExpression) {
166
+ stm->perform(this);
180
167
  }
181
- if (decls) --indentation;
182
168
  }
183
- }
169
+ if (output_style() == NESTED) indentation -= r->tabs();
170
+ append_scope_closer(b);
184
171
 
172
+ }
185
173
  void Output::operator()(Keyframe_Rule* r)
186
174
  {
187
175
  Block* b = r->block();
@@ -199,19 +187,9 @@ namespace Sass {
199
187
  append_scope_opener();
200
188
  for (size_t i = 0, L = b->length(); i < L; ++i) {
201
189
  Statement* stm = (*b)[i];
202
- if (!stm->is_hoistable()) {
203
- stm->perform(this);
204
- if (i < L - 1) append_special_linefeed();
205
- }
206
- }
207
-
208
- for (size_t i = 0, L = b->length(); i < L; ++i) {
209
- Statement* stm = (*b)[i];
210
- if (stm->is_hoistable()) {
211
- stm->perform(this);
212
- }
190
+ stm->perform(this);
191
+ if (i < L - 1) append_special_linefeed();
213
192
  }
214
-
215
193
  append_scope_closer();
216
194
  }
217
195
 
@@ -240,33 +218,10 @@ namespace Sass {
240
218
  c->perform(this);
241
219
  append_scope_opener();
242
220
 
243
- if (b->has_non_hoistable()) {
244
- // JMA - hoisted, output the non-hoistable in a nested block, followed by the hoistable
245
- append_scope_opener();
246
-
247
- for (size_t i = 0, L = b->length(); i < L; ++i) {
248
- Statement* stm = (*b)[i];
249
- if (!stm->is_hoistable()) {
250
- stm->perform(this);
251
- }
252
- }
253
-
254
- append_scope_closer();
255
-
256
- for (size_t i = 0, L = b->length(); i < L; ++i) {
257
- Statement* stm = (*b)[i];
258
- if (stm->is_hoistable()) {
259
- stm->perform(this);
260
- }
261
- }
262
- }
263
- else {
264
- // JMA - not hoisted, just output in order
265
- for (size_t i = 0, L = b->length(); i < L; ++i) {
266
- Statement* stm = (*b)[i];
267
- stm->perform(this);
268
- if (i < L - 1) append_special_linefeed();
269
- }
221
+ for (size_t i = 0, L = b->length(); i < L; ++i) {
222
+ Statement* stm = (*b)[i];
223
+ stm->perform(this);
224
+ if (i < L - 1) append_special_linefeed();
270
225
  }
271
226
 
272
227
  if (output_style() == NESTED) indentation -= f->tabs();
@@ -346,18 +301,8 @@ namespace Sass {
346
301
 
347
302
  for (size_t i = 0, L = b->length(); i < L; ++i) {
348
303
  Statement* stm = (*b)[i];
349
- if (!stm->is_hoistable()) {
350
- stm->perform(this);
351
- if (i < L - 1 && format) append_special_linefeed();
352
- }
353
- }
354
-
355
- for (size_t i = 0, L = b->length(); i < L; ++i) {
356
- Statement* stm = (*b)[i];
357
- if (stm->is_hoistable()) {
358
- stm->perform(this);
359
- if (i < L - 1 && format) append_special_linefeed();
360
- }
304
+ stm->perform(this);
305
+ if (i < L - 1 && format) append_special_linefeed();
361
306
  }
362
307
 
363
308
  append_scope_closer();
@@ -35,7 +35,6 @@ namespace Sass {
35
35
 
36
36
  virtual void operator()(Map*);
37
37
  virtual void operator()(Ruleset*);
38
- // virtual void operator()(Propset*);
39
38
  virtual void operator()(Supports_Block*);
40
39
  virtual void operator()(Media_Block*);
41
40
  virtual void operator()(Directive*);
@@ -12,6 +12,18 @@
12
12
  #include "sass/functions.h"
13
13
  #include "error_handling.hpp"
14
14
 
15
+ // Notes about delayed: some ast nodes can have delayed evaluation so
16
+ // they can preserve their original semantics if needed. This is most
17
+ // prominently exhibited by the division operation, since it is not
18
+ // only a valid operation, but also a valid css statement (i.e. for
19
+ // fonts, as in `16px/24px`). When parsing lists and expression we
20
+ // unwrap single items from lists and other operations. A nested list
21
+ // must not be delayed, only the items of the first level sometimes
22
+ // are delayed (as with argument lists). To achieve this we need to
23
+ // pass status to the list parser, so this can be set correctly.
24
+ // Another case with delayed values are colors. In compressed mode
25
+ // only processed values get compressed (other are left as written).
26
+
15
27
  #include <typeinfo>
16
28
  #include <tuple>
17
29
 
@@ -21,6 +33,8 @@ namespace Sass {
21
33
 
22
34
  Parser Parser::from_c_str(const char* beg, Context& ctx, ParserState pstate, const char* source)
23
35
  {
36
+ pstate.offset.column = 0;
37
+ pstate.offset.line = 0;
24
38
  Parser p(ctx, pstate);
25
39
  p.source = source ? source : beg;
26
40
  p.position = beg ? beg : p.source;
@@ -33,6 +47,8 @@ namespace Sass {
33
47
 
34
48
  Parser Parser::from_c_str(const char* beg, const char* end, Context& ctx, ParserState pstate, const char* source)
35
49
  {
50
+ pstate.offset.column = 0;
51
+ pstate.offset.line = 0;
36
52
  Parser p(ctx, pstate);
37
53
  p.source = source ? source : beg;
38
54
  p.position = beg ? beg : p.source;
@@ -43,7 +59,15 @@ namespace Sass {
43
59
  return p;
44
60
  }
45
61
 
46
- Selector_List* Parser::parse_selector(const char* beg, Context& ctx, ParserState pstate, const char* source)
62
+ void Parser::advanceToNextToken() {
63
+ lex < css_comments >(false);
64
+ // advance to position
65
+ pstate += pstate.offset;
66
+ pstate.offset.column = 0;
67
+ pstate.offset.line = 0;
68
+ }
69
+
70
+ CommaSequence_Selector* Parser::parse_selector(const char* beg, Context& ctx, ParserState pstate, const char* source)
47
71
  {
48
72
  Parser p = Parser::from_c_str(beg, ctx, pstate, source);
49
73
  // ToDo: ruby sass errors on parent references
@@ -254,7 +278,7 @@ namespace Sass {
254
278
  else if (lex< re_prefixed_directive >(true)) { (*block) << parse_prefixed_directive(); }
255
279
  else if (lex< at_keyword >(true)) { (*block) << parse_directive(); }
256
280
 
257
- else if (block->is_root()) {
281
+ else if (is_root /* && block->is_root() */) {
258
282
  lex< css_whitespace >();
259
283
  if (position >= end) return true;
260
284
  css_error("Invalid CSS", " after ", ": expected 1 selector or at-rule, was ");
@@ -272,7 +296,7 @@ namespace Sass {
272
296
  if (decl->is_indented()) ++ indentation;
273
297
  // parse a propset that rides on the declaration's property
274
298
  stack.push_back(Scope::Properties);
275
- (*block) << SASS_MEMORY_NEW(ctx.mem, Propset, pstate, decl->property(), parse_block());
299
+ decl->block(parse_block());
276
300
  stack.pop_back();
277
301
  if (decl->is_indented()) -- indentation;
278
302
  }
@@ -321,7 +345,7 @@ namespace Sass {
321
345
  first = false;
322
346
  } while (lex_css< exactly<','> >());
323
347
 
324
- if (!peek_css<alternatives<exactly<';'>,end_of_file>>()) {
348
+ if (!peek_css< alternatives< exactly<';'>, exactly<'}'>, end_of_file > >()) {
325
349
  List* media_queries = parse_media_queries();
326
350
  imp->media_queries(media_queries);
327
351
  }
@@ -391,7 +415,6 @@ namespace Sass {
391
415
  if (lex< exactly<':'> >()) { // there's a default value
392
416
  while (lex< block_comment >());
393
417
  val = parse_space_list();
394
- val->is_delayed(false);
395
418
  }
396
419
  else if (lex< exactly< ellipsis > >()) {
397
420
  is_rest = true;
@@ -430,14 +453,12 @@ namespace Sass {
430
453
  ParserState p = pstate;
431
454
  lex_css< exactly<':'> >();
432
455
  Expression* val = parse_space_list();
433
- val->is_delayed(false);
434
456
  arg = SASS_MEMORY_NEW(ctx.mem, Argument, p, val, name);
435
457
  }
436
458
  else {
437
459
  bool is_arglist = false;
438
460
  bool is_keyword = false;
439
461
  Expression* val = parse_space_list();
440
- val->is_delayed(false);
441
462
  List* l = dynamic_cast<List*>(val);
442
463
  if (lex_css< exactly< ellipsis > >()) {
443
464
  if (val->concrete_type() == Expression::MAP || (
@@ -455,6 +476,9 @@ namespace Sass {
455
476
  std::string name(Util::normalize_underscores(lexed));
456
477
  ParserState var_source_position = pstate;
457
478
  if (!lex< exactly<':'> >()) error("expected ':' after " + name + " in assignment statement", pstate);
479
+ if (peek_css< alternatives < exactly<';'>, end_of_file > >()) {
480
+ css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
481
+ }
458
482
  Expression* val;
459
483
  Lookahead lookahead = lookahead_for_value(position);
460
484
  if (lookahead.has_interpolants && lookahead.found) {
@@ -462,7 +486,6 @@ namespace Sass {
462
486
  } else {
463
487
  val = parse_list();
464
488
  }
465
- val->is_delayed(false);
466
489
  bool is_default = false;
467
490
  bool is_global = false;
468
491
  while (peek< alternatives < default_flag, global_flag > >()) {
@@ -587,12 +610,12 @@ namespace Sass {
587
610
 
588
611
  // parse a list of complex selectors
589
612
  // this is the main entry point for most
590
- Selector_List* Parser::parse_selector_list(bool in_root)
613
+ CommaSequence_Selector* Parser::parse_selector_list(bool in_root)
591
614
  {
592
615
  bool reloop = true;
593
616
  bool had_linefeed = false;
594
- Complex_Selector* sel = 0;
595
- Selector_List* group = SASS_MEMORY_NEW(ctx.mem, Selector_List, pstate);
617
+ Sequence_Selector* sel = 0;
618
+ CommaSequence_Selector* group = SASS_MEMORY_NEW(ctx.mem, CommaSequence_Selector, pstate);
596
619
  group->media_block(last_media_block);
597
620
 
598
621
  do {
@@ -639,13 +662,16 @@ namespace Sass {
639
662
  // complex selector, with one of four combinator operations.
640
663
  // the compound selector (head) is optional, since the combinator
641
664
  // can come first in the whole selector sequence (like `> DIV').
642
- Complex_Selector* Parser::parse_complex_selector(bool in_root)
665
+ Sequence_Selector* Parser::parse_complex_selector(bool in_root)
643
666
  {
644
667
 
645
668
  String* reference = 0;
646
669
  lex < block_comment >();
670
+
671
+ Sequence_Selector* sel = SASS_MEMORY_NEW(ctx.mem, Sequence_Selector, pstate);
672
+
647
673
  // parse the left hand side
648
- Compound_Selector* lhs = 0;
674
+ SimpleSequence_Selector* lhs = 0;
649
675
  // special case if it starts with combinator ([+~>])
650
676
  if (!peek_css< class_char < selector_combinator_ops > >()) {
651
677
  // parse the left hand side
@@ -656,28 +682,27 @@ namespace Sass {
656
682
  if (peek < end_of_file >()) return 0;
657
683
 
658
684
  // parse combinator between lhs and rhs
659
- Complex_Selector::Combinator combinator;
660
- if (lex< exactly<'+'> >()) combinator = Complex_Selector::ADJACENT_TO;
661
- else if (lex< exactly<'~'> >()) combinator = Complex_Selector::PRECEDES;
662
- else if (lex< exactly<'>'> >()) combinator = Complex_Selector::PARENT_OF;
685
+ Sequence_Selector::Combinator combinator;
686
+ if (lex< exactly<'+'> >()) combinator = Sequence_Selector::ADJACENT_TO;
687
+ else if (lex< exactly<'~'> >()) combinator = Sequence_Selector::PRECEDES;
688
+ else if (lex< exactly<'>'> >()) combinator = Sequence_Selector::PARENT_OF;
663
689
  else if (lex< sequence < exactly<'/'>, negate < exactly < '*' > > > >()) {
664
690
  // comments are allowed, but not spaces?
665
- combinator = Complex_Selector::REFERENCE;
691
+ combinator = Sequence_Selector::REFERENCE;
666
692
  if (!lex < re_reference_combinator >()) return 0;
667
693
  reference = SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, lexed);
668
694
  if (!lex < exactly < '/' > >()) return 0; // ToDo: error msg?
669
695
  }
670
- else /* if (lex< zero >()) */ combinator = Complex_Selector::ANCESTOR_OF;
696
+ else /* if (lex< zero >()) */ combinator = Sequence_Selector::ANCESTOR_OF;
671
697
 
672
- if (!lhs && combinator == Complex_Selector::ANCESTOR_OF) return 0;
698
+ if (!lhs && combinator == Sequence_Selector::ANCESTOR_OF) return 0;
673
699
 
674
700
  // lex < block_comment >();
675
- // source position of a complex selector points to the combinator
676
- // ToDo: make sure we update pstate for ancestor of (lex < zero >());
677
- Complex_Selector* sel = SASS_MEMORY_NEW(ctx.mem, Complex_Selector, pstate, combinator, lhs);
701
+ sel->head(lhs);
702
+ sel->combinator(combinator);
678
703
  sel->media_block(last_media_block);
679
704
 
680
- if (combinator == Complex_Selector::REFERENCE) sel->reference(reference);
705
+ if (combinator == Sequence_Selector::REFERENCE) sel->reference(reference);
681
706
  // has linfeed after combinator?
682
707
  sel->has_line_break(peek_newline());
683
708
  // sel->has_line_feed(has_line_feed);
@@ -686,20 +711,15 @@ namespace Sass {
686
711
  if (!peek_css< class_char < complex_selector_delims > >()) {
687
712
  // parse next selector in sequence
688
713
  sel->tail(parse_complex_selector(true));
689
- if (sel->tail()) {
690
- // ToDo: move this logic below into tail setter
691
- // if (sel->tail()->has_reference()) sel->has_reference(true);
692
- if (sel->tail()->has_placeholder()) sel->has_placeholder(true);
693
- }
694
714
  }
695
715
 
696
716
  // add a parent selector if we are not in a root
697
717
  // also skip adding parent ref if we only have refs
698
718
  if (!sel->has_parent_ref() && !in_at_root && !in_root) {
699
719
  // create the objects to wrap parent selector reference
700
- Parent_Selector* parent = SASS_MEMORY_NEW(ctx.mem, Parent_Selector, pstate);
720
+ SimpleSequence_Selector* head = SASS_MEMORY_NEW(ctx.mem, SimpleSequence_Selector, pstate);
721
+ Parent_Selector* parent = SASS_MEMORY_NEW(ctx.mem, Parent_Selector, pstate, false);
701
722
  parent->media_block(last_media_block);
702
- Compound_Selector* head = SASS_MEMORY_NEW(ctx.mem, Compound_Selector, pstate);
703
723
  head->media_block(last_media_block);
704
724
  // add simple selector
705
725
  (*head) << parent;
@@ -707,13 +727,15 @@ namespace Sass {
707
727
  if (!sel->head()) { sel->head(head); }
708
728
  // otherwise we need to create a new complex selector and set the old one as its tail
709
729
  else {
710
- sel = SASS_MEMORY_NEW(ctx.mem, Complex_Selector, pstate, Complex_Selector::ANCESTOR_OF, head, sel);
730
+ sel = SASS_MEMORY_NEW(ctx.mem, Sequence_Selector, pstate, Sequence_Selector::ANCESTOR_OF, head, sel);
711
731
  sel->media_block(last_media_block);
712
732
  }
713
733
  // peek for linefeed and remember result on head
714
734
  // if (peek_newline()) head->has_line_break(true);
715
735
  }
716
736
 
737
+ sel->update_pstate(pstate);
738
+
717
739
  // complex selector
718
740
  return sel;
719
741
  }
@@ -722,10 +744,10 @@ namespace Sass {
722
744
  // parse one compound selector, which is basically
723
745
  // a list of simple selectors (directly adjacent)
724
746
  // lex them exactly (without skipping white-space)
725
- Compound_Selector* Parser::parse_compound_selector()
747
+ SimpleSequence_Selector* Parser::parse_compound_selector()
726
748
  {
727
749
  // init an empty compound selector wrapper
728
- Compound_Selector* seq = SASS_MEMORY_NEW(ctx.mem, Compound_Selector, pstate);
750
+ SimpleSequence_Selector* seq = SASS_MEMORY_NEW(ctx.mem, SimpleSequence_Selector, pstate);
729
751
  seq->media_block(last_media_block);
730
752
 
731
753
  // skip initial white-space
@@ -763,7 +785,7 @@ namespace Sass {
763
785
  // parse type selector
764
786
  else if (lex< re_type_selector >(false))
765
787
  {
766
- (*seq) << SASS_MEMORY_NEW(ctx.mem, Type_Selector, pstate, lexed);
788
+ (*seq) << SASS_MEMORY_NEW(ctx.mem, Element_Selector, pstate, lexed);
767
789
  }
768
790
  // peek for abort conditions
769
791
  else if (peek< spaces >()) break;
@@ -791,14 +813,17 @@ namespace Sass {
791
813
  Simple_Selector* Parser::parse_simple_selector()
792
814
  {
793
815
  lex < css_comments >(false);
794
- if (lex< alternatives < id_name, class_name > >()) {
795
- return SASS_MEMORY_NEW(ctx.mem, Selector_Qualifier, pstate, lexed);
816
+ if (lex< class_name >()) {
817
+ return SASS_MEMORY_NEW(ctx.mem, Class_Selector, pstate, lexed);
818
+ }
819
+ else if (lex< id_name >()) {
820
+ return SASS_MEMORY_NEW(ctx.mem, Id_Selector, pstate, lexed);
796
821
  }
797
822
  else if (lex< quoted_string >()) {
798
- return SASS_MEMORY_NEW(ctx.mem, Type_Selector, pstate, unquote(lexed));
823
+ return SASS_MEMORY_NEW(ctx.mem, Element_Selector, pstate, unquote(lexed));
799
824
  }
800
825
  else if (lex< alternatives < variable, number, static_reference_combinator > >()) {
801
- return SASS_MEMORY_NEW(ctx.mem, Type_Selector, pstate, lexed);
826
+ return SASS_MEMORY_NEW(ctx.mem, Element_Selector, pstate, lexed);
802
827
  }
803
828
  else if (peek< pseudo_not >()) {
804
829
  return parse_negated_selector();
@@ -813,7 +838,7 @@ namespace Sass {
813
838
  return parse_attribute_selector();
814
839
  }
815
840
  else if (lex< placeholder >()) {
816
- Selector_Placeholder* sel = SASS_MEMORY_NEW(ctx.mem, Selector_Placeholder, pstate, lexed);
841
+ Placeholder_Selector* sel = SASS_MEMORY_NEW(ctx.mem, Placeholder_Selector, pstate, lexed);
817
842
  sel->media_block(last_media_block);
818
843
  return sel;
819
844
  }
@@ -938,7 +963,6 @@ namespace Sass {
938
963
  }
939
964
  else if (lex< sequence< optional< exactly<'*'> >, identifier, zero_plus< block_comment > > >()) {
940
965
  prop = SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, lexed);
941
- prop->is_delayed(true);
942
966
  }
943
967
  else {
944
968
  css_error("Invalid CSS", " after ", ": expected \"}\", was ");
@@ -959,11 +983,11 @@ namespace Sass {
959
983
  if (lookahead.has_interpolants) {
960
984
  value = parse_value_schema(lookahead.found);
961
985
  } else {
962
- value = parse_list();
986
+ value = parse_list(DELAYED);
963
987
  }
964
988
  }
965
989
  else {
966
- value = parse_list();
990
+ value = parse_list(DELAYED);
967
991
  if (List* list = dynamic_cast<List*>(value)) {
968
992
  if (list->length() == 0 && !peek< exactly <'{'> >()) {
969
993
  css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
@@ -1022,7 +1046,7 @@ namespace Sass {
1022
1046
  if (peek_css< exactly<')'> >(position))
1023
1047
  { break; }
1024
1048
 
1025
- Expression* key = parse_list();
1049
+ Expression* key = parse_space_list();
1026
1050
  if (String_Quoted* str = dynamic_cast<String_Quoted*>(key)) {
1027
1051
  if (!str->quote_mark() && !str->is_delayed()) {
1028
1052
  if (const Color* col = name_to_color(str->value())) {
@@ -1035,7 +1059,7 @@ namespace Sass {
1035
1059
  }
1036
1060
 
1037
1061
  if (!(lex< exactly<':'> >()))
1038
- { error("invalid syntax", pstate); }
1062
+ { css_error("Invalid CSS", " after ", ": expected \":\", was "); }
1039
1063
 
1040
1064
  Expression* value = parse_space_list();
1041
1065
 
@@ -1052,14 +1076,13 @@ namespace Sass {
1052
1076
  // parse list returns either a space separated list,
1053
1077
  // a comma separated list or any bare expression found.
1054
1078
  // so to speak: we unwrap items from lists if possible here!
1055
- Expression* Parser::parse_list()
1079
+ Expression* Parser::parse_list(bool delayed)
1056
1080
  {
1057
- // parse list is relly just an alias
1058
- return parse_comma_list();
1081
+ return parse_comma_list(delayed);
1059
1082
  }
1060
1083
 
1061
1084
  // will return singletons unwrapped
1062
- Expression* Parser::parse_comma_list()
1085
+ Expression* Parser::parse_comma_list(bool delayed)
1063
1086
  {
1064
1087
  // check if we have an empty list
1065
1088
  // return the empty list as such
@@ -1075,12 +1098,20 @@ namespace Sass {
1075
1098
  default_flag,
1076
1099
  global_flag
1077
1100
  > >(position))
1078
- { return SASS_MEMORY_NEW(ctx.mem, List, pstate, 0); }
1101
+ {
1102
+ // return an empty list (nothing to delay)
1103
+ return SASS_MEMORY_NEW(ctx.mem, List, pstate, 0);
1104
+ }
1079
1105
 
1080
1106
  // now try to parse a space list
1081
1107
  Expression* list = parse_space_list();
1082
1108
  // if it's a singleton, return it (don't wrap it)
1083
- if (!peek_css< exactly<','> >(position)) return list;
1109
+ if (!peek_css< exactly<','> >(position)) {
1110
+ // set_delay doesn't apply to list children
1111
+ // so this will only undelay single values
1112
+ if (!delayed) list->set_delayed(false);
1113
+ return list;
1114
+ }
1084
1115
 
1085
1116
  // if we got so far, we actually do have a comma list
1086
1117
  List* comma_list = SASS_MEMORY_NEW(ctx.mem, List, pstate, 2, SASS_COMMA);
@@ -1158,6 +1189,8 @@ namespace Sass {
1158
1189
  // parse logical OR operation
1159
1190
  Expression* Parser::parse_disjunction()
1160
1191
  {
1192
+ advanceToNextToken();
1193
+ ParserState state(pstate);
1161
1194
  // parse the left hand side conjunction
1162
1195
  Expression* conj = parse_conjunction();
1163
1196
  // parse multiple right hand sides
@@ -1167,13 +1200,18 @@ namespace Sass {
1167
1200
  // if it's a singleton, return it directly
1168
1201
  if (operands.size() == 0) return conj;
1169
1202
  // fold all operands into one binary expression
1170
- return fold_operands(conj, operands, { Sass_OP::OR });
1203
+ Expression* ex = fold_operands(conj, operands, { Sass_OP::OR });
1204
+ state.offset = pstate - state + pstate.offset;
1205
+ ex->pstate(state);
1206
+ return ex;
1171
1207
  }
1172
1208
  // EO parse_disjunction
1173
1209
 
1174
1210
  // parse logical AND operation
1175
1211
  Expression* Parser::parse_conjunction()
1176
1212
  {
1213
+ advanceToNextToken();
1214
+ ParserState state(pstate);
1177
1215
  // parse the left hand side relation
1178
1216
  Expression* rel = parse_relation();
1179
1217
  // parse multiple right hand sides
@@ -1183,13 +1221,18 @@ namespace Sass {
1183
1221
  // if it's a singleton, return it directly
1184
1222
  if (operands.size() == 0) return rel;
1185
1223
  // fold all operands into one binary expression
1186
- return fold_operands(rel, operands, { Sass_OP::AND });
1224
+ Expression* ex = fold_operands(rel, operands, { Sass_OP::AND });
1225
+ state.offset = pstate - state + pstate.offset;
1226
+ ex->pstate(state);
1227
+ return ex;
1187
1228
  }
1188
1229
  // EO parse_conjunction
1189
1230
 
1190
1231
  // parse comparison operations
1191
1232
  Expression* Parser::parse_relation()
1192
1233
  {
1234
+ advanceToNextToken();
1235
+ ParserState state(pstate);
1193
1236
  // parse the left hand side expression
1194
1237
  Expression* lhs = parse_expression();
1195
1238
  std::vector<Expression*> operands;
@@ -1222,8 +1265,15 @@ namespace Sass {
1222
1265
  operands.push_back(parse_expression());
1223
1266
  left_ws = peek < css_comments >() != NULL;
1224
1267
  }
1225
- // parse the operator
1226
- return fold_operands(lhs, operands, operators);
1268
+ // we are called recursively for list, so we first
1269
+ // fold inner binary expression which has delayed
1270
+ // correctly set to zero. After folding we also unwrap
1271
+ // single nested items. So we cannot set delay on the
1272
+ // returned result here, as we have lost nestings ...
1273
+ Expression* ex = fold_operands(lhs, operands, operators);
1274
+ state.offset = pstate - state + pstate.offset;
1275
+ ex->pstate(state);
1276
+ return ex;
1227
1277
  }
1228
1278
  // parse_relation
1229
1279
 
@@ -1234,6 +1284,8 @@ namespace Sass {
1234
1284
  // parse addition and subtraction operations
1235
1285
  Expression* Parser::parse_expression()
1236
1286
  {
1287
+ advanceToNextToken();
1288
+ ParserState state(pstate);
1237
1289
  // parses multiple add and subtract operations
1238
1290
  // NOTE: make sure that identifiers starting with
1239
1291
  // NOTE: dashes do NOT count as subtract operation
@@ -1259,7 +1311,6 @@ namespace Sass {
1259
1311
 
1260
1312
  ) {
1261
1313
 
1262
-
1263
1314
  bool right_ws = peek < css_comments >() != NULL;
1264
1315
  operators.push_back({ lexed.to_string() == "+" ? Sass_OP::ADD : Sass_OP::SUB, left_ws, right_ws });
1265
1316
  operands.push_back(parse_operators());
@@ -1267,12 +1318,17 @@ namespace Sass {
1267
1318
  }
1268
1319
 
1269
1320
  if (operands.size() == 0) return lhs;
1270
- return fold_operands(lhs, operands, operators);
1321
+ Expression* ex = fold_operands(lhs, operands, operators);
1322
+ state.offset = pstate - state + pstate.offset;
1323
+ ex->pstate(state);
1324
+ return ex;
1271
1325
  }
1272
1326
 
1273
1327
  // parse addition and subtraction operations
1274
1328
  Expression* Parser::parse_operators()
1275
1329
  {
1330
+ advanceToNextToken();
1331
+ ParserState state(pstate);
1276
1332
  Expression* factor = parse_factor();
1277
1333
  // if it's a singleton, return it (don't wrap it)
1278
1334
  std::vector<Expression*> operands; // factors
@@ -1291,7 +1347,10 @@ namespace Sass {
1291
1347
  left_ws = peek < css_comments >();
1292
1348
  }
1293
1349
  // operands and operators to binary expression
1294
- return fold_operands(factor, operands, operators);
1350
+ Expression* ex = fold_operands(factor, operands, operators);
1351
+ state.offset = pstate - state + pstate.offset;
1352
+ ex->pstate(state);
1353
+ return ex;
1295
1354
  }
1296
1355
  // EO parse_operators
1297
1356
 
@@ -1307,14 +1366,6 @@ namespace Sass {
1307
1366
  // lex the expected closing parenthesis
1308
1367
  if (!lex_css< exactly<')'> >()) error("unclosed parenthesis", pstate);
1309
1368
  // expression can be evaluated
1310
- // make sure wrapped lists and division expressions are non-delayed within parentheses
1311
- if (value->concrete_type() == Expression::LIST) {
1312
- // List* l = static_cast<List*>(value);
1313
- // if (!l->empty()) (*l)[0]->is_delayed(false);
1314
- } else if (typeid(*value) == typeid(Binary_Expression)) {
1315
- Binary_Expression* b = static_cast<Binary_Expression*>(value);
1316
- if (b && b->type() == Sass_OP::DIV) b->set_delayed(false);
1317
- }
1318
1369
  return value;
1319
1370
  }
1320
1371
  // string may be interpolated
@@ -1350,17 +1401,25 @@ namespace Sass {
1350
1401
  return parse_function_call();
1351
1402
  }
1352
1403
  else if (lex< exactly<'+'> >()) {
1353
- return SASS_MEMORY_NEW(ctx.mem, Unary_Expression, pstate, Unary_Expression::PLUS, parse_factor());
1404
+ Unary_Expression* ex = SASS_MEMORY_NEW(ctx.mem, Unary_Expression, pstate, Unary_Expression::PLUS, parse_factor());
1405
+ if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
1406
+ return ex;
1354
1407
  }
1355
1408
  else if (lex< exactly<'-'> >()) {
1356
- return SASS_MEMORY_NEW(ctx.mem, Unary_Expression, pstate, Unary_Expression::MINUS, parse_factor());
1409
+ Unary_Expression* ex = SASS_MEMORY_NEW(ctx.mem, Unary_Expression, pstate, Unary_Expression::MINUS, parse_factor());
1410
+ if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
1411
+ return ex;
1357
1412
  }
1358
1413
  else if (lex< sequence< kwd_not > >()) {
1359
- return SASS_MEMORY_NEW(ctx.mem, Unary_Expression, pstate, Unary_Expression::NOT, parse_factor());
1414
+ Unary_Expression* ex = SASS_MEMORY_NEW(ctx.mem, Unary_Expression, pstate, Unary_Expression::NOT, parse_factor());
1415
+ if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
1416
+ return ex;
1360
1417
  }
1361
1418
  else if (peek < sequence < one_plus < alternatives < css_whitespace, exactly<'-'>, exactly<'+'> > >, number > >()) {
1362
1419
  if (parse_number_prefix()) return parse_value(); // prefix is positive
1363
- return SASS_MEMORY_NEW(ctx.mem, Unary_Expression, pstate, Unary_Expression::MINUS, parse_value());
1420
+ Unary_Expression* ex = SASS_MEMORY_NEW(ctx.mem, Unary_Expression, pstate, Unary_Expression::MINUS, parse_value());;
1421
+ if (ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
1422
+ return ex;
1364
1423
  }
1365
1424
  else {
1366
1425
  return parse_value();
@@ -1455,7 +1514,6 @@ namespace Sass {
1455
1514
  if (!p) {
1456
1515
  String_Quoted* str_quoted = SASS_MEMORY_NEW(ctx.mem, String_Quoted, pstate, std::string(i, chunk.end));
1457
1516
  if (!constant && str_quoted->quote_mark()) str_quoted->quote_mark('*');
1458
- str_quoted->is_delayed(true);
1459
1517
  return str_quoted;
1460
1518
  }
1461
1519
 
@@ -1510,11 +1568,13 @@ namespace Sass {
1510
1568
  {
1511
1569
  lex< static_value >();
1512
1570
  Token str(lexed);
1571
+ // static values always have trailing white-
1572
+ // space and end delimiter (\s*[;]$) included
1573
+ -- pstate.offset.column;
1513
1574
  --str.end;
1514
1575
  --position;
1515
1576
 
1516
1577
  String_Constant* str_node = SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, str.time_wspace());
1517
- str_node->is_delayed(true);
1518
1578
  return str_node;
1519
1579
  }
1520
1580
 
@@ -1720,7 +1780,7 @@ namespace Sass {
1720
1780
  const char* j = skip_over_scopes< exactly<hash_lbrace>, exactly<rbrace> >(p+2, id.end); // find the closing brace
1721
1781
  if (j) {
1722
1782
  // parse the interpolant and accumulate it
1723
- Expression* interp_node = Parser::from_token(Token(p+2, j), ctx, pstate, source).parse_list();
1783
+ Expression* interp_node = Parser::from_token(Token(p+2, j), ctx, pstate, source).parse_list(DELAYED);
1724
1784
  interp_node->is_interpolant(true);
1725
1785
  (*schema) << interp_node;
1726
1786
  // schema->has_interpolants(true);
@@ -1844,16 +1904,6 @@ namespace Sass {
1844
1904
 
1845
1905
  Content* Parser::parse_content_directive()
1846
1906
  {
1847
- bool missing_mixin_parent = true;
1848
- for (auto parent : stack) {
1849
- if (parent == Scope::Mixin) {
1850
- missing_mixin_parent = false;
1851
- break;
1852
- }
1853
- }
1854
- if (missing_mixin_parent) {
1855
- error("@content may only be used within a mixin", pstate);
1856
- }
1857
1907
  return SASS_MEMORY_NEW(ctx.mem, Content, pstate);
1858
1908
  }
1859
1909
 
@@ -1861,9 +1911,9 @@ namespace Sass {
1861
1911
  {
1862
1912
  stack.push_back(Scope::Control);
1863
1913
  ParserState if_source_position = pstate;
1914
+ bool root = block_stack.back()->is_root();
1864
1915
  Expression* predicate = parse_list();
1865
- predicate->is_delayed(false);
1866
- Block* block = parse_block();
1916
+ Block* block = parse_block(root);
1867
1917
  Block* alternative = 0;
1868
1918
 
1869
1919
  // only throw away comment if we parse a case
@@ -1873,7 +1923,7 @@ namespace Sass {
1873
1923
  (*alternative) << parse_if_directive(true);
1874
1924
  }
1875
1925
  else if (lex_css< kwd_else_directive >()) {
1876
- alternative = parse_block();
1926
+ alternative = parse_block(root);
1877
1927
  }
1878
1928
  stack.pop_back();
1879
1929
  return SASS_MEMORY_NEW(ctx.mem, If, if_source_position, predicate, block, alternative);
@@ -1883,18 +1933,17 @@ namespace Sass {
1883
1933
  {
1884
1934
  stack.push_back(Scope::Control);
1885
1935
  ParserState for_source_position = pstate;
1936
+ bool root = block_stack.back()->is_root();
1886
1937
  lex_variable();
1887
1938
  std::string var(Util::normalize_underscores(lexed));
1888
1939
  if (!lex< kwd_from >()) error("expected 'from' keyword in @for directive", pstate);
1889
1940
  Expression* lower_bound = parse_expression();
1890
- lower_bound->is_delayed(false);
1891
1941
  bool inclusive = false;
1892
1942
  if (lex< kwd_through >()) inclusive = true;
1893
1943
  else if (lex< kwd_to >()) inclusive = false;
1894
1944
  else error("expected 'through' or 'to' keyword in @for directive", pstate);
1895
1945
  Expression* upper_bound = parse_expression();
1896
- upper_bound->is_delayed(false);
1897
- Block* body = parse_block();
1946
+ Block* body = parse_block(root);
1898
1947
  stack.pop_back();
1899
1948
  return SASS_MEMORY_NEW(ctx.mem, For, for_source_position, var, lower_bound, upper_bound, body, inclusive);
1900
1949
  }
@@ -1929,6 +1978,7 @@ namespace Sass {
1929
1978
  {
1930
1979
  stack.push_back(Scope::Control);
1931
1980
  ParserState each_source_position = pstate;
1981
+ bool root = block_stack.back()->is_root();
1932
1982
  std::vector<std::string> vars;
1933
1983
  lex_variable();
1934
1984
  vars.push_back(Util::normalize_underscores(lexed));
@@ -1938,14 +1988,7 @@ namespace Sass {
1938
1988
  }
1939
1989
  if (!lex< kwd_in >()) error("expected 'in' keyword in @each directive", pstate);
1940
1990
  Expression* list = parse_list();
1941
- list->is_delayed(false);
1942
- if (list->concrete_type() == Expression::LIST) {
1943
- List* l = static_cast<List*>(list);
1944
- for (size_t i = 0, L = l->length(); i < L; ++i) {
1945
- (*l)[i]->is_delayed(false);
1946
- }
1947
- }
1948
- Block* body = parse_block();
1991
+ Block* body = parse_block(root);
1949
1992
  stack.pop_back();
1950
1993
  return SASS_MEMORY_NEW(ctx.mem, Each, each_source_position, vars, list, body);
1951
1994
  }
@@ -1954,14 +1997,14 @@ namespace Sass {
1954
1997
  While* Parser::parse_while_directive()
1955
1998
  {
1956
1999
  stack.push_back(Scope::Control);
2000
+ bool root = block_stack.back()->is_root();
1957
2001
  // create the initial while call object
1958
2002
  While* call = SASS_MEMORY_NEW(ctx.mem, While, pstate, 0, 0);
1959
2003
  // parse mandatory predicate
1960
2004
  Expression* predicate = parse_list();
1961
- predicate->is_delayed(false);
1962
2005
  call->predicate(predicate);
1963
2006
  // parse mandatory block
1964
- call->block(parse_block());
2007
+ call->block(parse_block(root));
1965
2008
  // return ast node
1966
2009
  stack.pop_back();
1967
2010
  // return ast node
@@ -1985,22 +2028,22 @@ namespace Sass {
1985
2028
 
1986
2029
  List* Parser::parse_media_queries()
1987
2030
  {
2031
+ advanceToNextToken();
1988
2032
  List* media_queries = SASS_MEMORY_NEW(ctx.mem, List, pstate, 0, SASS_COMMA);
1989
2033
  if (!peek_css < exactly <'{'> >()) (*media_queries) << parse_media_query();
1990
2034
  while (lex_css < exactly <','> >()) (*media_queries) << parse_media_query();
2035
+ media_queries->update_pstate(pstate);
1991
2036
  return media_queries;
1992
2037
  }
1993
2038
 
1994
2039
  // Expression* Parser::parse_media_query()
1995
2040
  Media_Query* Parser::parse_media_query()
1996
2041
  {
2042
+ advanceToNextToken();
1997
2043
  Media_Query* media_query = SASS_MEMORY_NEW(ctx.mem, Media_Query, pstate);
2044
+ if (lex < kwd_not >()) { media_query->is_negated(true); lex < css_comments >(false); }
2045
+ else if (lex < kwd_only >()) { media_query->is_restricted(true); lex < css_comments >(false); }
1998
2046
 
1999
- lex < css_comments >(false);
2000
- if (lex < kwd_not >()) media_query->is_negated(true);
2001
- else if (lex < kwd_only >()) media_query->is_restricted(true);
2002
-
2003
- lex < css_comments >(false);
2004
2047
  if (lex < identifier_schema >()) media_query->media_type(parse_identifier_schema());
2005
2048
  else if (lex < identifier >()) media_query->media_type(parse_interpolated_chunk(lexed));
2006
2049
  else (*media_query) << parse_media_expression();
@@ -2014,6 +2057,9 @@ namespace Sass {
2014
2057
  media_query->media_type(schema);
2015
2058
  }
2016
2059
  while (lex_css < kwd_and >()) (*media_query) << parse_media_expression();
2060
+
2061
+ media_query->update_pstate(pstate);
2062
+
2017
2063
  return media_query;
2018
2064
  }
2019
2065
 
@@ -2033,7 +2079,7 @@ namespace Sass {
2033
2079
  feature = parse_expression();
2034
2080
  Expression* expression = 0;
2035
2081
  if (lex_css< exactly<':'> >()) {
2036
- expression = parse_list();
2082
+ expression = parse_list(DELAYED);
2037
2083
  }
2038
2084
  if (!lex_css< exactly<')'> >()) {
2039
2085
  error("unclosed parenthesis in media query expression", pstate);
@@ -2252,13 +2298,9 @@ namespace Sass {
2252
2298
  Directive* directive = SASS_MEMORY_NEW(ctx.mem, Directive, pstate, lexed);
2253
2299
  Expression* val = parse_almost_any_value();
2254
2300
  // strip left and right if they are of type string
2255
- // debug_ast(val);
2256
- // std::cerr << "HAASDASD\n";
2257
2301
  directive->value(val);
2258
2302
  if (peek< exactly<'{'> >()) {
2259
2303
  directive->block(parse_block());
2260
- } else if (!val) {
2261
- css_error("most def");
2262
2304
  }
2263
2305
  return directive;
2264
2306
  }
@@ -2386,7 +2428,7 @@ namespace Sass {
2386
2428
  stack.back() != Scope::Rules) {
2387
2429
  error("Illegal nesting: Only properties may be nested beneath properties.", pstate);
2388
2430
  }
2389
- return SASS_MEMORY_NEW(ctx.mem, Warning, pstate, parse_list());
2431
+ return SASS_MEMORY_NEW(ctx.mem, Warning, pstate, parse_list(DELAYED));
2390
2432
  }
2391
2433
 
2392
2434
  Error* Parser::parse_error()
@@ -2398,7 +2440,7 @@ namespace Sass {
2398
2440
  stack.back() != Scope::Rules) {
2399
2441
  error("Illegal nesting: Only properties may be nested beneath properties.", pstate);
2400
2442
  }
2401
- return SASS_MEMORY_NEW(ctx.mem, Error, pstate, parse_list());
2443
+ return SASS_MEMORY_NEW(ctx.mem, Error, pstate, parse_list(DELAYED));
2402
2444
  }
2403
2445
 
2404
2446
  Debug* Parser::parse_debug()
@@ -2410,7 +2452,7 @@ namespace Sass {
2410
2452
  stack.back() != Scope::Rules) {
2411
2453
  error("Illegal nesting: Only properties may be nested beneath properties.", pstate);
2412
2454
  }
2413
- return SASS_MEMORY_NEW(ctx.mem, Debug, pstate, parse_list());
2455
+ return SASS_MEMORY_NEW(ctx.mem, Debug, pstate, parse_list(DELAYED));
2414
2456
  }
2415
2457
 
2416
2458
  Return* Parser::parse_return_directive()
@@ -2623,22 +2665,13 @@ namespace Sass {
2623
2665
  Expression* Parser::fold_operands(Expression* base, std::vector<Expression*>& operands, Operand op)
2624
2666
  {
2625
2667
  for (size_t i = 0, S = operands.size(); i < S; ++i) {
2626
- base = SASS_MEMORY_NEW(ctx.mem, Binary_Expression, pstate, op, base, operands[i]);
2627
- Binary_Expression* b = static_cast<Binary_Expression*>(base);
2628
- if (op.operand == Sass_OP::DIV && b->left()->is_delayed() && b->right()->is_delayed()) {
2629
- base->is_delayed(true);
2630
- }
2631
- else if (b && b->op().operand != Sass_OP::DIV) {
2632
- b->left()->is_delayed(false);
2633
- b->right()->is_delayed(false);
2634
- }
2668
+ base = SASS_MEMORY_NEW(ctx.mem, Binary_Expression, base->pstate(), op, base, operands[i]);
2635
2669
  }
2636
2670
  return base;
2637
2671
  }
2638
2672
 
2639
2673
  Expression* Parser::fold_operands(Expression* base, std::vector<Expression*>& operands, std::vector<Operand>& ops, size_t i)
2640
2674
  {
2641
-
2642
2675
  if (String_Schema* schema = dynamic_cast<String_Schema*>(base)) {
2643
2676
  // return schema;
2644
2677
  if (schema->has_interpolants()) {
@@ -2653,10 +2686,8 @@ namespace Sass {
2653
2686
  || (ops[0].operand == Sass_OP::LTE)
2654
2687
  || (ops[0].operand == Sass_OP::GTE)
2655
2688
  )) {
2656
- Expression* rhs = fold_operands(operands[0], operands, ops, 1);
2689
+ Expression* rhs = fold_operands(operands[i], operands, ops, i + 1);
2657
2690
  rhs = SASS_MEMORY_NEW(ctx.mem, Binary_Expression, base->pstate(), ops[0], schema, rhs);
2658
- rhs->set_delayed(false);
2659
- rhs->is_delayed(true);
2660
2691
  return rhs;
2661
2692
  }
2662
2693
  // return schema;
@@ -2670,12 +2701,9 @@ namespace Sass {
2670
2701
  Expression* rhs = fold_operands(operands[i+1], operands, ops, i + 2);
2671
2702
  rhs = SASS_MEMORY_NEW(ctx.mem, Binary_Expression, base->pstate(), ops[i], schema, rhs);
2672
2703
  base = SASS_MEMORY_NEW(ctx.mem, Binary_Expression, base->pstate(), ops[i], base, rhs);
2673
- rhs->is_delayed(true);
2674
- base->is_delayed(true);
2675
2704
  return base;
2676
2705
  }
2677
2706
  base = SASS_MEMORY_NEW(ctx.mem, Binary_Expression, base->pstate(), ops[i], base, operands[i]);
2678
- if (ops[i].operand != Sass_OP::DIV) base->is_delayed(true);
2679
2707
  return base;
2680
2708
  } else {
2681
2709
  base = SASS_MEMORY_NEW(ctx.mem, Binary_Expression, base->pstate(), ops[i], base, operands[i]);
@@ -2687,11 +2715,11 @@ namespace Sass {
2687
2715
  if (b && ops[i].operand == Sass_OP::DIV && b->left()->is_delayed() && b->right()->is_delayed()) {
2688
2716
  base->is_delayed(true);
2689
2717
  }
2690
- else if (b) {
2691
- b->left()->is_delayed(false);
2692
- b->right()->is_delayed(false);
2693
- }
2694
-
2718
+ }
2719
+ // nested binary expression are never to be delayed
2720
+ if (Binary_Expression* b = dynamic_cast<Binary_Expression*>(base)) {
2721
+ if (dynamic_cast<Binary_Expression*>(b->left())) base->set_delayed(false);
2722
+ if (dynamic_cast<Binary_Expression*>(b->right())) base->set_delayed(false);
2695
2723
  }
2696
2724
  return base;
2697
2725
  }