sassc 1.10.1 → 1.11.0

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