sassc 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.gitmodules +3 -0
  4. data/.travis.yml +9 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +24 -0
  8. data/Rakefile +21 -0
  9. data/ext/libsass/.editorconfig +15 -0
  10. data/ext/libsass/.gitattributes +2 -0
  11. data/ext/libsass/.gitignore +61 -0
  12. data/ext/libsass/.travis.yml +38 -0
  13. data/ext/libsass/COPYING +25 -0
  14. data/ext/libsass/INSTALL +1 -0
  15. data/ext/libsass/LICENSE +25 -0
  16. data/ext/libsass/Makefile +223 -0
  17. data/ext/libsass/Makefile.am +145 -0
  18. data/ext/libsass/Readme.md +93 -0
  19. data/ext/libsass/appveyor.yml +76 -0
  20. data/ext/libsass/ast.cpp +581 -0
  21. data/ext/libsass/ast.hpp +1949 -0
  22. data/ext/libsass/ast_def_macros.hpp +16 -0
  23. data/ext/libsass/ast_factory.hpp +87 -0
  24. data/ext/libsass/ast_fwd_decl.hpp +72 -0
  25. data/ext/libsass/b64/cencode.h +32 -0
  26. data/ext/libsass/b64/encode.h +77 -0
  27. data/ext/libsass/backtrace.hpp +81 -0
  28. data/ext/libsass/base64vlq.cpp +43 -0
  29. data/ext/libsass/base64vlq.hpp +28 -0
  30. data/ext/libsass/bind.cpp +187 -0
  31. data/ext/libsass/bind.hpp +18 -0
  32. data/ext/libsass/cencode.c +102 -0
  33. data/ext/libsass/color_names.hpp +324 -0
  34. data/ext/libsass/configure.ac +130 -0
  35. data/ext/libsass/constants.cpp +144 -0
  36. data/ext/libsass/constants.hpp +145 -0
  37. data/ext/libsass/context.cpp +507 -0
  38. data/ext/libsass/context.hpp +150 -0
  39. data/ext/libsass/contextualize.cpp +157 -0
  40. data/ext/libsass/contextualize.hpp +65 -0
  41. data/ext/libsass/copy_c_str.cpp +13 -0
  42. data/ext/libsass/copy_c_str.hpp +5 -0
  43. data/ext/libsass/debug.hpp +39 -0
  44. data/ext/libsass/environment.hpp +75 -0
  45. data/ext/libsass/error_handling.cpp +28 -0
  46. data/ext/libsass/error_handling.hpp +28 -0
  47. data/ext/libsass/eval.cpp +1149 -0
  48. data/ext/libsass/eval.hpp +80 -0
  49. data/ext/libsass/expand.cpp +430 -0
  50. data/ext/libsass/expand.hpp +77 -0
  51. data/ext/libsass/extconf.rb +6 -0
  52. data/ext/libsass/extend.cpp +1962 -0
  53. data/ext/libsass/extend.hpp +50 -0
  54. data/ext/libsass/file.cpp +291 -0
  55. data/ext/libsass/file.hpp +18 -0
  56. data/ext/libsass/functions.cpp +1565 -0
  57. data/ext/libsass/functions.hpp +187 -0
  58. data/ext/libsass/inspect.cpp +727 -0
  59. data/ext/libsass/inspect.hpp +108 -0
  60. data/ext/libsass/json.cpp +1411 -0
  61. data/ext/libsass/json.hpp +117 -0
  62. data/ext/libsass/kwd_arg_macros.hpp +23 -0
  63. data/ext/libsass/m4/.gitkeep +0 -0
  64. data/ext/libsass/mapping.hpp +17 -0
  65. data/ext/libsass/memory_manager.hpp +54 -0
  66. data/ext/libsass/node.cpp +251 -0
  67. data/ext/libsass/node.hpp +122 -0
  68. data/ext/libsass/operation.hpp +153 -0
  69. data/ext/libsass/output_compressed.cpp +401 -0
  70. data/ext/libsass/output_compressed.hpp +95 -0
  71. data/ext/libsass/output_nested.cpp +364 -0
  72. data/ext/libsass/output_nested.hpp +108 -0
  73. data/ext/libsass/parser.cpp +2016 -0
  74. data/ext/libsass/parser.hpp +264 -0
  75. data/ext/libsass/paths.hpp +69 -0
  76. data/ext/libsass/position.hpp +22 -0
  77. data/ext/libsass/posix/getopt.c +562 -0
  78. data/ext/libsass/posix/getopt.h +95 -0
  79. data/ext/libsass/prelexer.cpp +688 -0
  80. data/ext/libsass/prelexer.hpp +513 -0
  81. data/ext/libsass/remove_placeholders.cpp +59 -0
  82. data/ext/libsass/remove_placeholders.hpp +43 -0
  83. data/ext/libsass/res/resource.rc +35 -0
  84. data/ext/libsass/sass.cpp +33 -0
  85. data/ext/libsass/sass.h +60 -0
  86. data/ext/libsass/sass2scss.cpp +834 -0
  87. data/ext/libsass/sass2scss.h +110 -0
  88. data/ext/libsass/sass_context.cpp +709 -0
  89. data/ext/libsass/sass_context.h +120 -0
  90. data/ext/libsass/sass_functions.cpp +137 -0
  91. data/ext/libsass/sass_functions.h +90 -0
  92. data/ext/libsass/sass_interface.cpp +277 -0
  93. data/ext/libsass/sass_interface.h +97 -0
  94. data/ext/libsass/sass_util.cpp +136 -0
  95. data/ext/libsass/sass_util.hpp +259 -0
  96. data/ext/libsass/sass_values.cpp +337 -0
  97. data/ext/libsass/sass_values.h +124 -0
  98. data/ext/libsass/script/bootstrap +10 -0
  99. data/ext/libsass/script/branding +10 -0
  100. data/ext/libsass/script/ci-build-libsass +72 -0
  101. data/ext/libsass/script/ci-install-compiler +4 -0
  102. data/ext/libsass/script/ci-install-deps +19 -0
  103. data/ext/libsass/script/ci-report-coverage +25 -0
  104. data/ext/libsass/script/coveralls-debug +32 -0
  105. data/ext/libsass/script/spec +5 -0
  106. data/ext/libsass/script/tap-driver +652 -0
  107. data/ext/libsass/script/tap-runner +1 -0
  108. data/ext/libsass/source_map.cpp +133 -0
  109. data/ext/libsass/source_map.hpp +46 -0
  110. data/ext/libsass/subset_map.hpp +145 -0
  111. data/ext/libsass/support/libsass.pc.in +11 -0
  112. data/ext/libsass/test-driver +127 -0
  113. data/ext/libsass/test/test_node.cpp +98 -0
  114. data/ext/libsass/test/test_paths.cpp +29 -0
  115. data/ext/libsass/test/test_selector_difference.cpp +28 -0
  116. data/ext/libsass/test/test_specificity.cpp +28 -0
  117. data/ext/libsass/test/test_subset_map.cpp +472 -0
  118. data/ext/libsass/test/test_superselector.cpp +71 -0
  119. data/ext/libsass/test/test_unification.cpp +33 -0
  120. data/ext/libsass/to_c.cpp +61 -0
  121. data/ext/libsass/to_c.hpp +44 -0
  122. data/ext/libsass/to_string.cpp +29 -0
  123. data/ext/libsass/to_string.hpp +32 -0
  124. data/ext/libsass/token.hpp +32 -0
  125. data/ext/libsass/units.cpp +54 -0
  126. data/ext/libsass/units.hpp +10 -0
  127. data/ext/libsass/utf8.h +34 -0
  128. data/ext/libsass/utf8/checked.h +327 -0
  129. data/ext/libsass/utf8/core.h +329 -0
  130. data/ext/libsass/utf8/unchecked.h +228 -0
  131. data/ext/libsass/utf8_string.cpp +102 -0
  132. data/ext/libsass/utf8_string.hpp +36 -0
  133. data/ext/libsass/util.cpp +189 -0
  134. data/ext/libsass/util.hpp +26 -0
  135. data/ext/libsass/win/libsass.filters +291 -0
  136. data/ext/libsass/win/libsass.sln +28 -0
  137. data/ext/libsass/win/libsass.vcxproj +255 -0
  138. data/lib/sassc.rb +6 -0
  139. data/lib/sassc/engine.rb +13 -0
  140. data/lib/sassc/native.rb +44 -0
  141. data/lib/sassc/native/native_context_api.rb +140 -0
  142. data/lib/sassc/native/native_functions_api.rb +41 -0
  143. data/lib/sassc/native/sass_input_style.rb +11 -0
  144. data/lib/sassc/native/sass_output_style.rb +10 -0
  145. data/lib/sassc/native/sass_value.rb +95 -0
  146. data/lib/sassc/native/string_list.rb +8 -0
  147. data/lib/sassc/version.rb +3 -0
  148. data/sassc.gemspec +43 -0
  149. data/test/smoke_test.rb +171 -0
  150. data/test/test_helper.rb +4 -0
  151. metadata +281 -0
@@ -0,0 +1,117 @@
1
+ /*
2
+ Copyright (C) 2011 Joseph A. Adams (joeyadams3.14159@gmail.com)
3
+ All rights reserved.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
22
+ */
23
+
24
+ #ifndef CCAN_JSON_H
25
+ #define CCAN_JSON_H
26
+
27
+ #include <stdbool.h>
28
+ #include <stddef.h>
29
+
30
+ typedef enum {
31
+ JSON_NULL,
32
+ JSON_BOOL,
33
+ JSON_STRING,
34
+ JSON_NUMBER,
35
+ JSON_ARRAY,
36
+ JSON_OBJECT,
37
+ } JsonTag;
38
+
39
+ typedef struct JsonNode JsonNode;
40
+
41
+ struct JsonNode
42
+ {
43
+ /* only if parent is an object or array (NULL otherwise) */
44
+ JsonNode *parent;
45
+ JsonNode *prev, *next;
46
+
47
+ /* only if parent is an object (NULL otherwise) */
48
+ char *key; /* Must be valid UTF-8. */
49
+
50
+ JsonTag tag;
51
+ union {
52
+ /* JSON_BOOL */
53
+ bool bool_;
54
+
55
+ /* JSON_STRING */
56
+ char *string_; /* Must be valid UTF-8. */
57
+
58
+ /* JSON_NUMBER */
59
+ double number_;
60
+
61
+ /* JSON_ARRAY */
62
+ /* JSON_OBJECT */
63
+ struct {
64
+ JsonNode *head, *tail;
65
+ } children;
66
+ };
67
+ };
68
+
69
+ /*** Encoding, decoding, and validation ***/
70
+
71
+ JsonNode *json_decode (const char *json);
72
+ char *json_encode (const JsonNode *node);
73
+ char *json_encode_string (const char *str);
74
+ char *json_stringify (const JsonNode *node, const char *space);
75
+ void json_delete (JsonNode *node);
76
+
77
+ bool json_validate (const char *json);
78
+
79
+ /*** Lookup and traversal ***/
80
+
81
+ JsonNode *json_find_element (JsonNode *array, int index);
82
+ JsonNode *json_find_member (JsonNode *object, const char *key);
83
+
84
+ JsonNode *json_first_child (const JsonNode *node);
85
+
86
+ #define json_foreach(i, object_or_array) \
87
+ for ((i) = json_first_child(object_or_array); \
88
+ (i) != NULL; \
89
+ (i) = (i)->next)
90
+
91
+ /*** Construction and manipulation ***/
92
+
93
+ JsonNode *json_mknull(void);
94
+ JsonNode *json_mkbool(bool b);
95
+ JsonNode *json_mkstring(const char *s);
96
+ JsonNode *json_mknumber(double n);
97
+ JsonNode *json_mkarray(void);
98
+ JsonNode *json_mkobject(void);
99
+
100
+ void json_append_element(JsonNode *array, JsonNode *element);
101
+ void json_prepend_element(JsonNode *array, JsonNode *element);
102
+ void json_append_member(JsonNode *object, const char *key, JsonNode *value);
103
+ void json_prepend_member(JsonNode *object, const char *key, JsonNode *value);
104
+
105
+ void json_remove_from_parent(JsonNode *node);
106
+
107
+ /*** Debugging ***/
108
+
109
+ /*
110
+ * Look for structure and encoding problems in a JsonNode or its descendents.
111
+ *
112
+ * If a problem is detected, return false, writing a description of the problem
113
+ * to errmsg (unless errmsg is NULL).
114
+ */
115
+ bool json_check(const JsonNode *node, char errmsg[256]);
116
+
117
+ #endif
@@ -0,0 +1,23 @@
1
+ // Example usage:
2
+ // KWD_ARG_SET(Args) {
3
+ // KWD_ARG(Args, string, foo);
4
+ // KWD_ARG(Args, int, bar);
5
+ // ...
6
+ // };
7
+ //
8
+ // ... and later ...
9
+ //
10
+ // something(Args().foo("hey").bar(3));
11
+
12
+ #define KWD_ARG_SET(set_name) class set_name
13
+
14
+ #define KWD_ARG(set_name, type, name) \
15
+ private: \
16
+ type name##_; \
17
+ public: \
18
+ set_name& name(type name##__) { \
19
+ name##_ = name##__; \
20
+ return *this; \
21
+ } \
22
+ type name() { return name##_; } \
23
+ private:
File without changes
@@ -0,0 +1,17 @@
1
+ #define SASS_MAPPING
2
+
3
+ #ifndef SASS_POSITION
4
+ #include "position.hpp"
5
+ #endif
6
+
7
+ namespace Sass {
8
+
9
+ struct Mapping {
10
+ Position original_position;
11
+ Position generated_position;
12
+
13
+ Mapping(const Position& original_position, const Position& generated_position)
14
+ : original_position(original_position), generated_position(generated_position) { }
15
+ };
16
+
17
+ }
@@ -0,0 +1,54 @@
1
+ #define SASS_MEMORY_MANAGER
2
+
3
+ #include <vector>
4
+ #include <iostream>
5
+ using namespace std;
6
+
7
+ namespace Sass {
8
+ /////////////////////////////////////////////////////////////////////////////
9
+ // A class for tracking allocations of AST_Node objects. The intended usage
10
+ // is something like: Some_Node* n = new (mem_mgr) Some_Node(...);
11
+ // Then, at the end of the program, the memory manager will delete all of the
12
+ // allocated nodes that have been passed to it.
13
+ // In the future, this class may implement a custom allocator.
14
+ /////////////////////////////////////////////////////////////////////////////
15
+ template <typename T>
16
+ class Memory_Manager {
17
+ vector<T*> nodes;
18
+
19
+ public:
20
+ Memory_Manager(size_t size = 0) : nodes(vector<T*>())
21
+ { nodes.reserve(size); }
22
+
23
+ ~Memory_Manager()
24
+ {
25
+ for (size_t i = 0, S = nodes.size(); i < S; ++i) {
26
+ // cout << "deleting " << typeid(*nodes[i]).name() << endl;
27
+ delete nodes[i];
28
+ }
29
+ }
30
+
31
+ T* operator()(T* np)
32
+ {
33
+ nodes.push_back(np);
34
+ // cout << "registering " << typeid(*np).name() << endl;
35
+ return np;
36
+ }
37
+
38
+ void remove(T* np)
39
+ {
40
+ nodes.erase(find(nodes.begin(), nodes.end(), np));
41
+ }
42
+ };
43
+ }
44
+
45
+ template <typename T>
46
+ inline void* operator new(size_t size, Sass::Memory_Manager<T>& mem_mgr)
47
+ { return mem_mgr(static_cast<T*>(operator new(size))); }
48
+
49
+ template <typename T>
50
+ inline void operator delete(void *np, Sass::Memory_Manager<T>& mem_mgr)
51
+ {
52
+ mem_mgr.remove(reinterpret_cast<T*>(np));
53
+ operator delete(np);
54
+ }
@@ -0,0 +1,251 @@
1
+ #include "node.hpp"
2
+ #include "to_string.hpp"
3
+ #include "context.hpp"
4
+ #include "parser.hpp"
5
+
6
+ namespace Sass {
7
+
8
+
9
+ Node Node::createCombinator(const Complex_Selector::Combinator& combinator) {
10
+ NodeDequePtr null;
11
+ return Node(COMBINATOR, combinator, NULL /*pSelector*/, null /*pCollection*/);
12
+ }
13
+
14
+
15
+ Node Node::createSelector(Complex_Selector* pSelector, Context& ctx) {
16
+ NodeDequePtr null;
17
+
18
+ Complex_Selector* pStripped = pSelector->clone(ctx);
19
+ pStripped->tail(NULL);
20
+ pStripped->combinator(Complex_Selector::ANCESTOR_OF);
21
+
22
+ return Node(SELECTOR, Complex_Selector::ANCESTOR_OF, pStripped, null /*pCollection*/);
23
+ }
24
+
25
+
26
+ Node Node::createCollection() {
27
+ NodeDequePtr pEmptyCollection = make_shared<NodeDeque>();
28
+ return Node(COLLECTION, Complex_Selector::ANCESTOR_OF, NULL /*pSelector*/, pEmptyCollection);
29
+ }
30
+
31
+
32
+ Node Node::createCollection(const NodeDeque& values) {
33
+ NodeDequePtr pShallowCopiedCollection = make_shared<NodeDeque>(values);
34
+ return Node(COLLECTION, Complex_Selector::ANCESTOR_OF, NULL /*pSelector*/, pShallowCopiedCollection);
35
+ }
36
+
37
+
38
+ Node Node::createNil() {
39
+ NodeDequePtr null;
40
+ return Node(NIL, Complex_Selector::ANCESTOR_OF, NULL /*pSelector*/, null /*pCollection*/);
41
+ }
42
+
43
+
44
+ Node::Node(const TYPE& type, Complex_Selector::Combinator combinator, Complex_Selector* pSelector, NodeDequePtr& pCollection) :
45
+ mType(type),
46
+ mCombinator(combinator),
47
+ mpSelector(pSelector),
48
+ mpCollection(pCollection) {}
49
+
50
+
51
+ Node Node::clone(Context& ctx) const {
52
+ NodeDequePtr pNewCollection = make_shared<NodeDeque>();
53
+ if (mpCollection) {
54
+ for (NodeDeque::iterator iter = mpCollection->begin(), iterEnd = mpCollection->end(); iter != iterEnd; iter++) {
55
+ Node& toClone = *iter;
56
+ pNewCollection->push_back(toClone.clone(ctx));
57
+ }
58
+ }
59
+
60
+ return Node(mType, mCombinator, mpSelector ? mpSelector->clone(ctx) : NULL, pNewCollection);
61
+ }
62
+
63
+
64
+ bool Node::contains(const Node& potentialChild, bool simpleSelectorOrderDependent) const {
65
+ bool found = false;
66
+
67
+ for (NodeDeque::iterator iter = mpCollection->begin(), iterEnd = mpCollection->end(); iter != iterEnd; iter++) {
68
+ Node& toTest = *iter;
69
+
70
+ if (nodesEqual(toTest, potentialChild, simpleSelectorOrderDependent)) {
71
+ found = true;
72
+ break;
73
+ }
74
+ }
75
+
76
+ return found;
77
+ }
78
+
79
+
80
+ bool Node::operator==(const Node& rhs) const {
81
+ return nodesEqual(*this, rhs, true /*simpleSelectorOrderDependent*/);
82
+ }
83
+
84
+
85
+ bool nodesEqual(const Node& lhs, const Node& rhs, bool simpleSelectorOrderDependent) {
86
+ if (lhs.type() != rhs.type()) {
87
+ return false;
88
+ }
89
+
90
+ if (lhs.isCombinator()) {
91
+
92
+ return lhs.combinator() == rhs.combinator();
93
+
94
+ } else if (lhs.isNil()) {
95
+
96
+ return true; // no state to check
97
+
98
+ } else if (lhs.isSelector()){
99
+
100
+ return selectors_equal(*lhs.selector(), *rhs.selector(), simpleSelectorOrderDependent);
101
+
102
+ } else if (lhs.isCollection()) {
103
+
104
+ if (lhs.collection()->size() != rhs.collection()->size()) {
105
+ return false;
106
+ }
107
+
108
+ for (NodeDeque::iterator lhsIter = lhs.collection()->begin(), lhsIterEnd = lhs.collection()->end(),
109
+ rhsIter = rhs.collection()->begin(); lhsIter != lhsIterEnd; lhsIter++, rhsIter++) {
110
+
111
+ if (!nodesEqual(*lhsIter, *rhsIter, simpleSelectorOrderDependent)) {
112
+ return false;
113
+ }
114
+
115
+ }
116
+
117
+ return true;
118
+
119
+ }
120
+
121
+ // We shouldn't get here.
122
+ throw "Comparing unknown node types. A new type was probably added and this method wasn't implemented for it.";
123
+ }
124
+
125
+
126
+ void Node::plus(Node& rhs) {
127
+ if (!this->isCollection() || !rhs.isCollection()) {
128
+ throw "Both the current node and rhs must be collections.";
129
+ }
130
+ this->collection()->insert(this->collection()->end(), rhs.collection()->begin(), rhs.collection()->end());
131
+ }
132
+
133
+
134
+ ostream& operator<<(ostream& os, const Node& node) {
135
+
136
+ if (node.isCombinator()) {
137
+
138
+ switch (node.combinator()) {
139
+ case Complex_Selector::ANCESTOR_OF: os << "\" \""; break;
140
+ case Complex_Selector::PARENT_OF: os << "\">\""; break;
141
+ case Complex_Selector::PRECEDES: os << "\"~\""; break;
142
+ case Complex_Selector::ADJACENT_TO: os << "\"+\""; break;
143
+ }
144
+
145
+ } else if (node.isNil()) {
146
+
147
+ os << "nil";
148
+
149
+ } else if (node.isSelector()){
150
+
151
+ To_String to_string;
152
+ os << node.selector()->head()->perform(&to_string);
153
+
154
+ } else if (node.isCollection()) {
155
+
156
+ os << "[";
157
+
158
+ for (NodeDeque::iterator iter = node.collection()->begin(), iterBegin = node.collection()->begin(), iterEnd = node.collection()->end(); iter != iterEnd; iter++) {
159
+ if (iter != iterBegin) {
160
+ os << ", ";
161
+ }
162
+
163
+ os << (*iter);
164
+ }
165
+
166
+ os << "]";
167
+
168
+ }
169
+
170
+ return os;
171
+
172
+ }
173
+
174
+
175
+ Node complexSelectorToNode(Complex_Selector* pToConvert, Context& ctx) {
176
+ if (pToConvert == NULL) {
177
+ return Node::createNil();
178
+ }
179
+
180
+ Node node = Node::createCollection();
181
+
182
+ while (pToConvert) {
183
+
184
+ // the first Complex_Selector may contain a dummy head pointer, skip it.
185
+ if (pToConvert->head() != NULL && !pToConvert->head()->is_empty_reference()) {
186
+ node.collection()->push_back(Node::createSelector(pToConvert, ctx));
187
+ }
188
+
189
+ if (pToConvert->combinator() != Complex_Selector::ANCESTOR_OF) {
190
+ node.collection()->push_back(Node::createCombinator(pToConvert->combinator()));
191
+ }
192
+
193
+ pToConvert = pToConvert->tail();
194
+ }
195
+
196
+ return node;
197
+ }
198
+
199
+
200
+ Complex_Selector* nodeToComplexSelector(const Node& toConvert, Context& ctx) {
201
+ if (toConvert.isNil()) {
202
+ return NULL;
203
+ }
204
+
205
+
206
+ if (!toConvert.isCollection()) {
207
+ throw "The node to convert to a Complex_Selector* must be a collection type or nil.";
208
+ }
209
+
210
+
211
+ NodeDeque& childNodes = *toConvert.collection();
212
+
213
+ string noPath("");
214
+ Position noPosition;
215
+ Complex_Selector* pFirst = new (ctx.mem) Complex_Selector(noPath, noPosition, Complex_Selector::ANCESTOR_OF, NULL, NULL);
216
+ Complex_Selector* pCurrent = pFirst;
217
+
218
+ for (NodeDeque::iterator childIter = childNodes.begin(), childIterEnd = childNodes.end(); childIter != childIterEnd; childIter++) {
219
+
220
+ Node& child = *childIter;
221
+
222
+ if (child.isSelector()) {
223
+ pCurrent->tail(child.selector()->clone(ctx)); // JMA - need to clone the selector, because they can end up getting shared across Node collections, and can result in an infinite loop during the call to parentSuperselector()
224
+ pCurrent = pCurrent->tail();
225
+ } else if (child.isCombinator()) {
226
+ pCurrent->combinator(child.combinator());
227
+
228
+ // if the next node is also a combinator, create another Complex_Selector to hold it so it doesn't replace the current combinator
229
+ if (childIter+1 != childIterEnd) {
230
+ Node& nextNode = *(childIter+1);
231
+ if (nextNode.isCombinator()) {
232
+ pCurrent->tail(new (ctx.mem) Complex_Selector(noPath, noPosition, Complex_Selector::ANCESTOR_OF, NULL, NULL));
233
+ pCurrent = pCurrent->tail();
234
+ }
235
+ }
236
+ } else {
237
+ throw "The node to convert's children must be only combinators or selectors.";
238
+ }
239
+ }
240
+
241
+ // Put the dummy Compound_Selector in the first position, for consistency with the rest of libsass
242
+ Compound_Selector* fakeHead = new (ctx.mem) Compound_Selector(noPath, noPosition, 1);
243
+ Selector_Reference* selectorRef = new (ctx.mem) Selector_Reference(noPath, noPosition, NULL);
244
+ fakeHead->elements().push_back(selectorRef);
245
+ pFirst->head(fakeHead);
246
+
247
+ return pFirst;
248
+ }
249
+
250
+
251
+ }