sassc 2.2.1 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/CHANGELOG.md +13 -0
  4. data/Rakefile +1 -3
  5. data/ext/extconf.rb +13 -5
  6. data/ext/libsass/VERSION +1 -1
  7. data/ext/libsass/include/sass/base.h +2 -1
  8. data/ext/libsass/include/sass/context.h +1 -0
  9. data/ext/libsass/src/ast.cpp +49 -59
  10. data/ext/libsass/src/ast.hpp +263 -102
  11. data/ext/libsass/src/ast_def_macros.hpp +8 -0
  12. data/ext/libsass/src/ast_fwd_decl.cpp +2 -1
  13. data/ext/libsass/src/ast_fwd_decl.hpp +40 -116
  14. data/ext/libsass/src/ast_helpers.hpp +292 -0
  15. data/ext/libsass/src/ast_sel_cmp.cpp +209 -722
  16. data/ext/libsass/src/ast_sel_super.cpp +539 -0
  17. data/ext/libsass/src/ast_sel_unify.cpp +207 -212
  18. data/ext/libsass/src/ast_sel_weave.cpp +616 -0
  19. data/ext/libsass/src/ast_selectors.cpp +559 -1001
  20. data/ext/libsass/src/ast_selectors.hpp +311 -367
  21. data/ext/libsass/src/ast_supports.cpp +1 -17
  22. data/ext/libsass/src/ast_values.cpp +216 -29
  23. data/ext/libsass/src/ast_values.hpp +42 -33
  24. data/ext/libsass/src/bind.cpp +1 -1
  25. data/ext/libsass/src/cencode.c +4 -6
  26. data/ext/libsass/src/check_nesting.cpp +5 -6
  27. data/ext/libsass/src/check_nesting.hpp +4 -0
  28. data/ext/libsass/src/color_maps.cpp +11 -10
  29. data/ext/libsass/src/color_maps.hpp +0 -8
  30. data/ext/libsass/src/constants.cpp +5 -0
  31. data/ext/libsass/src/constants.hpp +6 -0
  32. data/ext/libsass/src/context.cpp +30 -60
  33. data/ext/libsass/src/context.hpp +8 -20
  34. data/ext/libsass/src/cssize.cpp +36 -120
  35. data/ext/libsass/src/cssize.hpp +4 -10
  36. data/ext/libsass/src/dart_helpers.hpp +199 -0
  37. data/ext/libsass/src/debugger.hpp +364 -207
  38. data/ext/libsass/src/emitter.cpp +3 -4
  39. data/ext/libsass/src/emitter.hpp +0 -2
  40. data/ext/libsass/src/environment.hpp +5 -0
  41. data/ext/libsass/src/error_handling.cpp +21 -0
  42. data/ext/libsass/src/error_handling.hpp +25 -3
  43. data/ext/libsass/src/eval.cpp +33 -153
  44. data/ext/libsass/src/eval.hpp +11 -13
  45. data/ext/libsass/src/eval_selectors.cpp +75 -0
  46. data/ext/libsass/src/expand.cpp +214 -167
  47. data/ext/libsass/src/expand.hpp +26 -6
  48. data/ext/libsass/src/extender.cpp +1186 -0
  49. data/ext/libsass/src/extender.hpp +399 -0
  50. data/ext/libsass/src/extension.cpp +43 -0
  51. data/ext/libsass/src/extension.hpp +89 -0
  52. data/ext/libsass/src/file.cpp +15 -14
  53. data/ext/libsass/src/file.hpp +5 -12
  54. data/ext/libsass/src/fn_colors.cpp +12 -10
  55. data/ext/libsass/src/fn_lists.cpp +12 -11
  56. data/ext/libsass/src/fn_miscs.cpp +22 -34
  57. data/ext/libsass/src/fn_numbers.cpp +13 -6
  58. data/ext/libsass/src/fn_selectors.cpp +94 -124
  59. data/ext/libsass/src/fn_strings.cpp +16 -14
  60. data/ext/libsass/src/fn_utils.cpp +5 -6
  61. data/ext/libsass/src/fn_utils.hpp +9 -3
  62. data/ext/libsass/src/inspect.cpp +154 -117
  63. data/ext/libsass/src/inspect.hpp +10 -8
  64. data/ext/libsass/src/lexer.cpp +17 -81
  65. data/ext/libsass/src/lexer.hpp +5 -16
  66. data/ext/libsass/src/listize.cpp +22 -36
  67. data/ext/libsass/src/listize.hpp +8 -9
  68. data/ext/libsass/src/memory/SharedPtr.hpp +39 -5
  69. data/ext/libsass/src/operation.hpp +27 -17
  70. data/ext/libsass/src/operators.cpp +1 -0
  71. data/ext/libsass/src/ordered_map.hpp +112 -0
  72. data/ext/libsass/src/output.cpp +30 -49
  73. data/ext/libsass/src/output.hpp +1 -1
  74. data/ext/libsass/src/parser.cpp +211 -381
  75. data/ext/libsass/src/parser.hpp +17 -15
  76. data/ext/libsass/src/parser_selectors.cpp +189 -0
  77. data/ext/libsass/src/permutate.hpp +140 -0
  78. data/ext/libsass/src/position.hpp +1 -1
  79. data/ext/libsass/src/prelexer.cpp +6 -6
  80. data/ext/libsass/src/remove_placeholders.cpp +55 -56
  81. data/ext/libsass/src/remove_placeholders.hpp +21 -18
  82. data/ext/libsass/src/sass.hpp +1 -0
  83. data/ext/libsass/src/sass2scss.cpp +4 -4
  84. data/ext/libsass/src/sass_context.cpp +42 -91
  85. data/ext/libsass/src/sass_context.hpp +2 -2
  86. data/ext/libsass/src/sass_functions.cpp +1 -1
  87. data/ext/libsass/src/sass_values.cpp +0 -1
  88. data/ext/libsass/src/stylesheet.cpp +22 -0
  89. data/ext/libsass/src/stylesheet.hpp +57 -0
  90. data/ext/libsass/src/to_value.cpp +2 -2
  91. data/ext/libsass/src/to_value.hpp +1 -1
  92. data/ext/libsass/src/units.cpp +5 -3
  93. data/ext/libsass/src/util.cpp +10 -12
  94. data/ext/libsass/src/util.hpp +2 -3
  95. data/ext/libsass/src/util_string.cpp +111 -61
  96. data/ext/libsass/src/util_string.hpp +61 -8
  97. data/lib/sassc/engine.rb +5 -3
  98. data/lib/sassc/functions_handler.rb +8 -8
  99. data/lib/sassc/native.rb +1 -1
  100. data/lib/sassc/script.rb +4 -4
  101. data/lib/sassc/version.rb +1 -1
  102. data/test/functions_test.rb +18 -1
  103. data/test/native_test.rb +1 -1
  104. metadata +17 -12
  105. data/ext/libsass/src/extend.cpp +0 -2132
  106. data/ext/libsass/src/extend.hpp +0 -86
  107. data/ext/libsass/src/node.cpp +0 -322
  108. data/ext/libsass/src/node.hpp +0 -118
  109. data/ext/libsass/src/paths.hpp +0 -71
  110. data/ext/libsass/src/sass_util.cpp +0 -152
  111. data/ext/libsass/src/sass_util.hpp +0 -256
  112. data/ext/libsass/src/subset_map.cpp +0 -58
  113. data/ext/libsass/src/subset_map.hpp +0 -76
@@ -1,86 +0,0 @@
1
- #ifndef SASS_EXTEND_H
2
- #define SASS_EXTEND_H
3
-
4
- #include <string>
5
- #include <set>
6
-
7
- #include "ast.hpp"
8
- #include "node.hpp"
9
- #include "eval.hpp"
10
- #include "operation.hpp"
11
- #include "subset_map.hpp"
12
- #include "ast_fwd_decl.hpp"
13
-
14
- namespace Sass {
15
-
16
- Node subweave(Node& one, Node& two);
17
-
18
- class Extend : public Operation_CRTP<void, Extend> {
19
-
20
- Subset_Map& subset_map;
21
- Eval* eval;
22
-
23
- private:
24
-
25
- std::unordered_map<
26
- Selector_List_Obj, // key
27
- Selector_List_Obj, // value
28
- HashNodes, // hasher
29
- CompareNodes // compare
30
- > memoizeList;
31
-
32
- std::unordered_map<
33
- Complex_Selector_Obj, // key
34
- Node, // value
35
- HashNodes, // hasher
36
- CompareNodes // compare
37
- > memoizeComplex;
38
-
39
- /* this turned out to be too much overhead
40
- re-evaluate once we store an ast selector
41
- std::unordered_map<
42
- Compound_Selector_Obj, // key
43
- Node, // value
44
- HashNodes, // hasher
45
- CompareNodes // compare
46
- > memoizeCompound;
47
- */
48
-
49
- void extendObjectWithSelectorAndBlock(Ruleset* pObject);
50
- Node extendComplexSelector(Complex_Selector* sel, CompoundSelectorSet& seen, bool isReplace, bool isOriginal);
51
- Node extendCompoundSelector(Compound_Selector* sel, CompoundSelectorSet& seen, bool isReplace);
52
- bool complexSelectorHasExtension(Complex_Selector* selector, CompoundSelectorSet& seen);
53
- Node trim(Node& seqses, bool isReplace);
54
- Node weave(Node& path);
55
-
56
- public:
57
- void setEval(Eval& eval);
58
- Selector_List* extendSelectorList(Selector_List_Obj pSelectorList, bool isReplace, bool& extendedSomething, CompoundSelectorSet& seen);
59
- Selector_List* extendSelectorList(Selector_List_Obj pSelectorList, bool isReplace = false) {
60
- bool extendedSomething = false;
61
- CompoundSelectorSet seen;
62
- return extendSelectorList(pSelectorList, isReplace, extendedSomething, seen);
63
- }
64
- Selector_List* extendSelectorList(Selector_List_Obj pSelectorList, CompoundSelectorSet& seen) {
65
- bool isReplace = false;
66
- bool extendedSomething = false;
67
- return extendSelectorList(pSelectorList, isReplace, extendedSomething, seen);
68
- }
69
- Extend(Subset_Map&);
70
- ~Extend() { }
71
-
72
- void operator()(Block*);
73
- void operator()(Ruleset*);
74
- void operator()(Supports_Block*);
75
- void operator()(Media_Block*);
76
- void operator()(Directive*);
77
-
78
- // ignore missed types
79
- template <typename U>
80
- void fallback(U x) {}
81
-
82
- };
83
-
84
- }
85
-
86
- #endif
@@ -1,322 +0,0 @@
1
- // sass.hpp must go before all system headers to get the
2
- // __EXTENSIONS__ fix on Solaris.
3
- #include "sass.hpp"
4
-
5
- #include <vector>
6
-
7
- #include "node.hpp"
8
- #include "context.hpp"
9
- #include "parser.hpp"
10
-
11
- namespace Sass {
12
-
13
-
14
- Node Node::createCombinator(const Complex_Selector::Combinator& combinator) {
15
- NodeDequePtr null;
16
- return Node(COMBINATOR, combinator, NULL /*pSelector*/, null /*pCollection*/);
17
- }
18
-
19
-
20
- Node Node::createSelector(const Complex_Selector& pSelector) {
21
- NodeDequePtr null;
22
-
23
- Complex_Selector* pStripped = SASS_MEMORY_COPY(&pSelector);
24
- pStripped->tail({});
25
- pStripped->combinator(Complex_Selector::ANCESTOR_OF);
26
-
27
- Node n(SELECTOR, Complex_Selector::ANCESTOR_OF, pStripped, null /*pCollection*/);
28
- n.got_line_feed = pSelector.has_line_feed();
29
- return n;
30
- }
31
-
32
-
33
- Node Node::createCollection() {
34
- NodeDequePtr pEmptyCollection = std::make_shared<NodeDeque>();
35
- return Node(COLLECTION, Complex_Selector::ANCESTOR_OF, NULL /*pSelector*/, pEmptyCollection);
36
- }
37
-
38
-
39
- Node Node::createCollection(const NodeDeque& values) {
40
- NodeDequePtr pShallowCopiedCollection = std::make_shared<NodeDeque>(values);
41
- return Node(COLLECTION, Complex_Selector::ANCESTOR_OF, NULL /*pSelector*/, pShallowCopiedCollection);
42
- }
43
-
44
-
45
- Node Node::createNil() {
46
- NodeDequePtr null;
47
- return Node(NIL, Complex_Selector::ANCESTOR_OF, NULL /*pSelector*/, null /*pCollection*/);
48
- }
49
-
50
-
51
- Node::Node(const TYPE& type, Complex_Selector::Combinator combinator, Complex_Selector* pSelector, NodeDequePtr& pCollection)
52
- : got_line_feed(false), mType(type), mCombinator(combinator), mpSelector(pSelector), mpCollection(pCollection)
53
- { if (pSelector) got_line_feed = pSelector->has_line_feed(); }
54
-
55
-
56
- Node Node::klone() const {
57
- NodeDequePtr pNewCollection = std::make_shared<NodeDeque>();
58
- if (mpCollection) {
59
- for (NodeDeque::iterator iter = mpCollection->begin(), iterEnd = mpCollection->end(); iter != iterEnd; iter++) {
60
- Node& toClone = *iter;
61
- pNewCollection->push_back(toClone.klone());
62
- }
63
- }
64
-
65
- Node n(mType, mCombinator, mpSelector ? SASS_MEMORY_COPY(mpSelector) : NULL, pNewCollection);
66
- n.got_line_feed = got_line_feed;
67
- return n;
68
- }
69
-
70
-
71
- bool Node::contains(const Node& potentialChild) const {
72
- bool found = false;
73
-
74
- for (NodeDeque::iterator iter = mpCollection->begin(), iterEnd = mpCollection->end(); iter != iterEnd; iter++) {
75
- Node& toTest = *iter;
76
-
77
- if (toTest == potentialChild) {
78
- found = true;
79
- break;
80
- }
81
- }
82
-
83
- return found;
84
- }
85
-
86
-
87
- bool Node::operator==(const Node& rhs) const {
88
- if (this->type() != rhs.type()) {
89
- return false;
90
- }
91
-
92
- if (this->isCombinator()) {
93
-
94
- return this->combinator() == rhs.combinator();
95
-
96
- } else if (this->isNil()) {
97
-
98
- return true; // no state to check
99
-
100
- } else if (this->isSelector()){
101
-
102
- return *this->selector() == *rhs.selector();
103
-
104
- } else if (this->isCollection()) {
105
-
106
- if (this->collection()->size() != rhs.collection()->size()) {
107
- return false;
108
- }
109
-
110
- for (NodeDeque::iterator lhsIter = this->collection()->begin(), lhsIterEnd = this->collection()->end(),
111
- rhsIter = rhs.collection()->begin(); lhsIter != lhsIterEnd; lhsIter++, rhsIter++) {
112
-
113
- if (*lhsIter != *rhsIter) {
114
- return false;
115
- }
116
-
117
- }
118
-
119
- return true;
120
-
121
- }
122
-
123
- // We shouldn't get here.
124
- throw "Comparing unknown node types. A new type was probably added and this method wasn't implemented for it.";
125
- }
126
-
127
-
128
- void Node::plus(Node& rhs) {
129
- if (!this->isCollection() || !rhs.isCollection()) {
130
- throw "Both the current node and rhs must be collections.";
131
- }
132
- this->collection()->insert(this->collection()->end(), rhs.collection()->begin(), rhs.collection()->end());
133
- }
134
-
135
- #ifdef DEBUG
136
- std::ostream& operator<<(std::ostream& os, const Node& node) {
137
-
138
- if (node.isCombinator()) {
139
-
140
- switch (node.combinator()) {
141
- case Complex_Selector::ANCESTOR_OF: os << "\" \""; break;
142
- case Complex_Selector::PARENT_OF: os << "\">\""; break;
143
- case Complex_Selector::PRECEDES: os << "\"~\""; break;
144
- case Complex_Selector::ADJACENT_TO: os << "\"+\""; break;
145
- case Complex_Selector::REFERENCE: os << "\"/\""; break;
146
- }
147
-
148
- } else if (node.isNil()) {
149
-
150
- os << "nil";
151
-
152
- } else if (node.isSelector()){
153
-
154
- os << node.selector()->head()->to_string();
155
-
156
- } else if (node.isCollection()) {
157
-
158
- os << "[";
159
-
160
- for (NodeDeque::iterator iter = node.collection()->begin(), iterBegin = node.collection()->begin(), iterEnd = node.collection()->end(); iter != iterEnd; iter++) {
161
- if (iter != iterBegin) {
162
- os << ", ";
163
- }
164
-
165
- os << (*iter);
166
- }
167
-
168
- os << "]";
169
-
170
- }
171
-
172
- return os;
173
-
174
- }
175
- #endif
176
-
177
-
178
- Node complexSelectorToNode(Complex_Selector* pToConvert) {
179
- if (pToConvert == NULL) {
180
- return Node::createNil();
181
- }
182
- Node node = Node::createCollection();
183
- node.got_line_feed = pToConvert->has_line_feed();
184
- bool has_lf = pToConvert->has_line_feed();
185
-
186
- // unwrap the selector from parent ref
187
- if (pToConvert->head() && pToConvert->head()->has_parent_ref()) {
188
- Complex_Selector_Obj tail = pToConvert->tail();
189
- if (tail) tail->has_line_feed(pToConvert->has_line_feed());
190
- pToConvert = tail;
191
- }
192
-
193
- while (pToConvert) {
194
-
195
- bool empty_parent_ref = pToConvert->head() && pToConvert->head()->is_empty_reference();
196
-
197
- // the first Complex_Selector may contain a dummy head pointer, skip it.
198
- if (pToConvert->head() && !empty_parent_ref) {
199
- node.collection()->push_back(Node::createSelector(*pToConvert));
200
- if (has_lf) node.collection()->back().got_line_feed = has_lf;
201
- if (pToConvert->head() || empty_parent_ref) {
202
- if (pToConvert->tail()) {
203
- pToConvert->tail()->has_line_feed(pToConvert->has_line_feed());
204
- }
205
- }
206
- has_lf = false;
207
- }
208
-
209
- if (pToConvert->combinator() != Complex_Selector::ANCESTOR_OF) {
210
- node.collection()->push_back(Node::createCombinator(pToConvert->combinator()));
211
- if (has_lf) node.collection()->back().got_line_feed = has_lf;
212
- has_lf = false;
213
- }
214
-
215
- if (pToConvert && empty_parent_ref && pToConvert->tail()) {
216
- // pToConvert->tail()->has_line_feed(pToConvert->has_line_feed());
217
- }
218
-
219
- pToConvert = pToConvert->tail();
220
- }
221
-
222
- return node;
223
- }
224
-
225
-
226
- Complex_Selector* nodeToComplexSelector(const Node& toConvert) {
227
- if (toConvert.isNil()) {
228
- return NULL;
229
- }
230
-
231
-
232
- if (!toConvert.isCollection()) {
233
- throw "The node to convert to a Complex_Selector* must be a collection type or nil.";
234
- }
235
-
236
-
237
- NodeDeque& childNodes = *toConvert.collection();
238
-
239
- std::string noPath("");
240
- Complex_Selector_Obj pFirst = SASS_MEMORY_NEW(Complex_Selector, ParserState("[NODE]"), Complex_Selector::ANCESTOR_OF, {}, {});
241
-
242
- Complex_Selector_Obj pCurrent = pFirst;
243
-
244
- if (toConvert.isSelector()) pFirst->has_line_feed(toConvert.got_line_feed);
245
- if (toConvert.isCombinator()) pFirst->has_line_feed(toConvert.got_line_feed);
246
-
247
- for (NodeDeque::iterator childIter = childNodes.begin(), childIterEnd = childNodes.end(); childIter != childIterEnd; childIter++) {
248
-
249
- Node& child = *childIter;
250
-
251
- if (child.isSelector()) {
252
- // JMA - need to clone the selector, because they can end up getting shared across Node
253
- // collections, and can result in an infinite loop during the call to parentSuperselector()
254
- pCurrent->tail(SASS_MEMORY_COPY(child.selector()));
255
- // if (child.got_line_feed) pCurrent->has_line_feed(child.got_line_feed);
256
- pCurrent = pCurrent->tail();
257
- } else if (child.isCombinator()) {
258
- pCurrent->combinator(child.combinator());
259
- if (child.got_line_feed) pCurrent->has_line_feed(child.got_line_feed);
260
-
261
- // if the next node is also a combinator, create another Complex_Selector to hold it so it doesn't replace the current combinator
262
- if (childIter+1 != childIterEnd) {
263
- Node& nextNode = *(childIter+1);
264
- if (nextNode.isCombinator()) {
265
- pCurrent->tail(SASS_MEMORY_NEW(Complex_Selector, ParserState("[NODE]"), Complex_Selector::ANCESTOR_OF, {}, {}));
266
- if (nextNode.got_line_feed) pCurrent->tail()->has_line_feed(nextNode.got_line_feed);
267
- pCurrent = pCurrent->tail();
268
- }
269
- }
270
- } else {
271
- throw "The node to convert's children must be only combinators or selectors.";
272
- }
273
- }
274
-
275
- // Put the dummy Compound_Selector in the first position, for consistency with the rest of libsass
276
- Compound_Selector* fakeHead = SASS_MEMORY_NEW(Compound_Selector, ParserState("[NODE]"), 1);
277
- Parent_Selector* selectorRef = SASS_MEMORY_NEW(Parent_Selector, ParserState("[NODE]"));
278
- fakeHead->elements().push_back(selectorRef);
279
- if (toConvert.got_line_feed) pFirst->has_line_feed(toConvert.got_line_feed);
280
- // pFirst->has_line_feed(pFirst->has_line_feed() || pFirst->tail()->has_line_feed() || toConvert.got_line_feed);
281
- pFirst->head(fakeHead);
282
- return SASS_MEMORY_COPY(pFirst);
283
- }
284
-
285
- // A very naive trim function, which removes duplicates in a node
286
- // This is only used in Complex_Selector::unify_with for now, may need modifications to fit other needs
287
- Node Node::naiveTrim(Node& seqses) {
288
-
289
- std::vector<Node*> res;
290
- std::vector<Complex_Selector_Obj> known;
291
-
292
- NodeDeque::reverse_iterator seqsesIter = seqses.collection()->rbegin(),
293
- seqsesIterEnd = seqses.collection()->rend();
294
-
295
- for (; seqsesIter != seqsesIterEnd; ++seqsesIter)
296
- {
297
- Node& seqs1 = *seqsesIter;
298
- if( seqs1.isSelector() ) {
299
- Complex_Selector_Obj sel = seqs1.selector();
300
- std::vector<Complex_Selector_Obj>::iterator it;
301
- bool found = false;
302
- for (it = known.begin(); it != known.end(); ++it) {
303
- if (**it == *sel) { found = true; break; }
304
- }
305
- if( !found ) {
306
- known.push_back(seqs1.selector());
307
- res.push_back(&seqs1);
308
- }
309
- } else {
310
- res.push_back(&seqs1);
311
- }
312
- }
313
-
314
- Node result = Node::createCollection();
315
-
316
- for (size_t i = res.size() - 1; i != std::string::npos; --i) {
317
- result.collection()->push_back(*res[i]);
318
- }
319
-
320
- return result;
321
- }
322
- }
@@ -1,118 +0,0 @@
1
- #ifndef SASS_NODE_H
2
- #define SASS_NODE_H
3
-
4
- #include <deque>
5
- #include <memory>
6
-
7
- #include "ast.hpp"
8
-
9
-
10
- namespace Sass {
11
-
12
-
13
-
14
-
15
- class Context;
16
-
17
- /*
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
- 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
21
- selector info. They also have the ability to have arbitrary nestings of arrays like [1, [2]], which is hard to
22
- implement using Array equivalents in C++ (like the deque or vector). They also have the ability to include nil
23
- in the arrays, like [1, nil, 3], which has potential semantic differences than an empty array [1, [], 3]. To be
24
- able to represent all of these as unique cases, we need to create a tree of variant objects. The tree nature allows
25
- the inconsistent nesting levels. The variant nature (while making some of the C++ code uglier) allows the code to
26
- more closely match the ruby code, which is a huge benefit when attempting to implement an complex algorithm like
27
- the Extend operator.
28
-
29
- Note that the current libsass data model also pairs the combinator with the Complex_Selector that follows it, but
30
- ruby sass has no such restriction, so we attempt to create a data structure that can handle them split apart.
31
- */
32
-
33
- class Node;
34
- typedef std::deque<Node> NodeDeque;
35
- typedef std::shared_ptr<NodeDeque> NodeDequePtr;
36
-
37
- class Node {
38
- public:
39
- enum TYPE {
40
- SELECTOR,
41
- COMBINATOR,
42
- COLLECTION,
43
- NIL
44
- };
45
-
46
- TYPE type() const { return mType; }
47
- bool isCombinator() const { return mType == COMBINATOR; }
48
- bool isSelector() const { return mType == SELECTOR; }
49
- bool isCollection() const { return mType == COLLECTION; }
50
- bool isNil() const { return mType == NIL; }
51
- bool got_line_feed;
52
-
53
- Complex_Selector::Combinator combinator() const { return mCombinator; }
54
-
55
- Complex_Selector_Obj selector() { return mpSelector; }
56
- Complex_Selector_Obj selector() const { return mpSelector; }
57
-
58
- NodeDequePtr collection() { return mpCollection; }
59
- const NodeDequePtr collection() const { return mpCollection; }
60
-
61
- static Node createCombinator(const Complex_Selector::Combinator& combinator);
62
-
63
- // This method will klone the selector, stripping off the tail and combinator
64
- static Node createSelector(const Complex_Selector& pSelector);
65
-
66
- static Node createCollection();
67
- static Node createCollection(const NodeDeque& values);
68
-
69
- static Node createNil();
70
- static Node naiveTrim(Node& seqses);
71
-
72
- Node klone() const;
73
-
74
- bool operator==(const Node& rhs) const;
75
- inline bool operator!=(const Node& rhs) const { return !(*this == rhs); }
76
-
77
-
78
- /*
79
- COLLECTION FUNCTIONS
80
-
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
83
- whereever possible). The following methods are intended to be called on Node objects whose
84
- type is COLLECTION only.
85
- */
86
-
87
- // rhs and this must be node collections. Shallow copy the nodes from rhs to the end of this.
88
- // This function DOES NOT remove the nodes from rhs.
89
- void plus(Node& rhs);
90
-
91
- // potentialChild must be a node collection of selectors/combinators. this must be a collection
92
- // of collections of nodes/combinators. This method checks if potentialChild is a child of this
93
- // Node.
94
- bool contains(const Node& potentialChild) const;
95
-
96
- private:
97
- // Private constructor; Use the static methods (like createCombinator and createSelector)
98
- // to instantiate this object. This is more expressive, and it allows us to break apart each
99
- // case into separate functions.
100
- Node(const TYPE& type, Complex_Selector::Combinator combinator, Complex_Selector* pSelector, NodeDequePtr& pCollection);
101
-
102
- TYPE mType;
103
-
104
- // TODO: can we union these to save on memory?
105
- Complex_Selector::Combinator mCombinator;
106
- Complex_Selector_Obj mpSelector;
107
- NodeDequePtr mpCollection;
108
- };
109
-
110
- #ifdef DEBUG
111
- std::ostream& operator<<(std::ostream& os, const Node& node);
112
- #endif
113
- Node complexSelectorToNode(Complex_Selector* pToConvert);
114
- Complex_Selector* nodeToComplexSelector(const Node& toConvert);
115
-
116
- }
117
-
118
- #endif