Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 269 lines (238 sloc) 6.951 kB
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
1 #include <sstream>
e476b60 @akhleung Expanded-style output works (with some whitespace hiccups).
akhleung authored
2 #include "node.hpp"
11a8906 @akhleung Moved the less-than node comparison over to the refactored version.
akhleung authored
3 #include "error.hpp"
d3b2584 @akhleung Parsing and echoing works.
akhleung authored
4
cefe1e2 @akhleung Fleshing out the classes for documents, nodes, and tokens.
akhleung authored
5 namespace Sass {
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
6 using namespace std;
594d4b3 @akhleung Moving a node comparison function into the refactored version.
akhleung authored
7
8 // ------------------------------------------------------------------------
9 // Node method implementations
10 // ------------------------------------------------------------------------
11
ca5286a @akhleung Adding/refactoring some helper methods.
akhleung authored
12 void Node::flatten()
13 {
14 if (type() != block && type() != expansion && type() != root) return;
8205182 @akhleung Adding a helpful comment.
akhleung authored
15 // size can change during flattening, so we need to call size() on each pass
242e7be @akhleung Fixing a bug in the refactored 'flatten' function.
akhleung authored
16 for (size_t i = 0; i < size(); ++i) {
ca5286a @akhleung Adding/refactoring some helper methods.
akhleung authored
17 if (at(i).type() == expansion) {
18 Node expn(at(i));
19 if (expn.has_expansions()) expn.flatten();
20 ip_->has_statements |= expn.has_statements();
21 ip_->has_blocks |= expn.has_blocks();
22 ip_->has_expansions |= expn.has_expansions();
23 // leave the expansion node here and skip it during emission
242e7be @akhleung Fixing a bug in the refactored 'flatten' function.
akhleung authored
24 insert(begin() + i + 1, expn.begin(), expn.end());
ca5286a @akhleung Adding/refactoring some helper methods.
akhleung authored
25 }
26 }
27 }
28
594d4b3 @akhleung Moving a node comparison function into the refactored version.
akhleung authored
29 bool Node::operator==(Node rhs) const
30 {
31 Type t = type();
32 if (t != rhs.type()) return false;
33
34 switch (t)
35 {
36 case comma_list:
37 case space_list:
38 case expression:
39 case term:
40 case numeric_color: {
c73a1b9 @akhleung Fixing an error in the node equality function.
akhleung authored
41 if (size() != rhs.size()) return false;
42 for (size_t i = 0, L = size(); i < L; ++i) {
594d4b3 @akhleung Moving a node comparison function into the refactored version.
akhleung authored
43 if (at(i) == rhs[i]) continue;
44 else return false;
45 }
46 return true;
47 } break;
48
49 case variable:
50 case identifier:
51 case uri:
52 case textual_percentage:
53 case textual_dimension:
54 case textual_number:
55 case textual_hex:
56 case string_constant: {
57 return token().unquote() == rhs.token().unquote();
58 } break;
59
60 case number:
61 case numeric_percentage: {
62 return numeric_value() == rhs.numeric_value();
63 } break;
64
65 case numeric_dimension: {
66 if (unit() == rhs.unit()) {
67 return numeric_value() == rhs.numeric_value();
68 }
69 else {
70 return false;
71 }
72 } break;
73
74 case boolean: {
75 return boolean_value() == rhs.boolean_value();
76 } break;
77
78 default: {
79 return true;
80 } break;
81 }
11a8906 @akhleung Moved the less-than node comparison over to the refactored version.
akhleung authored
82 return false;
594d4b3 @akhleung Moving a node comparison function into the refactored version.
akhleung authored
83 }
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
84
6a8b096 @akhleung Merged the other node comparison functions into the refactor.
akhleung authored
85 bool Node::operator!=(Node rhs) const
86 { return !(*this == rhs); }
87
11a8906 @akhleung Moved the less-than node comparison over to the refactored version.
akhleung authored
88 bool Node::operator<(Node rhs) const
89 {
90 Type lhs_type = type();
91 Type rhs_type = rhs.type();
92
f9964c8 @akhleung All warnings gone!
akhleung authored
93 if ((lhs_type == number && rhs_type == number) ||
94 (lhs_type == numeric_percentage && rhs_type == numeric_percentage)) {
11a8906 @akhleung Moved the less-than node comparison over to the refactored version.
akhleung authored
95 return numeric_value() < rhs.numeric_value();
96 }
97 else if (lhs_type == numeric_dimension && rhs_type == numeric_dimension) {
98 if (unit() == rhs.unit()) {
99 return numeric_value() < rhs.numeric_value();
100 }
101 else {
bd84119 @akhleung Re-ordering some arguments.
akhleung authored
102 throw Error(Error::evaluation, path(), line(), "incompatible units");
11a8906 @akhleung Moved the less-than node comparison over to the refactored version.
akhleung authored
103 }
104 }
105 else {
bd84119 @akhleung Re-ordering some arguments.
akhleung authored
106 throw Error(Error::evaluation, path(), line(), "incomparable types");
11a8906 @akhleung Moved the less-than node comparison over to the refactored version.
akhleung authored
107 }
108 }
6a8b096 @akhleung Merged the other node comparison functions into the refactor.
akhleung authored
109
110 bool Node::operator<=(Node rhs) const
111 { return *this < rhs || *this == rhs; }
112
113 bool Node::operator>(Node rhs) const
114 { return !(*this <= rhs); }
115
116 bool Node::operator>=(Node rhs) const
117 { return !(*this < rhs); }
11a8906 @akhleung Moved the less-than node comparison over to the refactored version.
akhleung authored
118
119
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
120 // ------------------------------------------------------------------------
121 // Token method implementations
122 // ------------------------------------------------------------------------
0e87917 @akhleung Clone function for nodes.
akhleung authored
123
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
124 string Token::unquote() const
cb03bb0 @akhleung Working on getting expressions to print out. Next step is evaluation.
akhleung authored
125 {
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
126 string result;
127 const char* p = begin;
128 if (*begin == '\'' || *begin == '"') {
129 ++p;
130 while (p < end) {
131 if (*p == '\\') {
132 switch (*(++p)) {
133 case 'n': result += '\n'; break;
134 case 't': result += '\t'; break;
135 case 'b': result += '\b'; break;
136 case 'r': result += '\r'; break;
137 case 'f': result += '\f'; break;
138 case 'v': result += '\v'; break;
139 case 'a': result += '\a'; break;
140 case '\\': result += '\\'; break;
141 default: result += *p; break;
82811e9 @akhleung Correctly printing out colors with an alpha channel.
akhleung authored
142 }
143 }
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
144 else if (p == end - 1) {
145 return result;
12fcacc @akhleung New node type for hex triples. Modified the emitter to print hex trip…
akhleung authored
146 }
b069370 @akhleung Implemented the "quote" and "unquote" builtins.
akhleung authored
147 else {
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
148 result += *p;
c7f0785 @akhleung Implemented string interpolation.
akhleung authored
149 }
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
150 ++p;
b9cfc22 @akhleung Properly handling selector combinators. Had to account for some subtl…
akhleung authored
151 }
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
152 return result;
153 }
154 else {
155 while (p < end) {
156 result += *(p++);
a5080f4 @akhleung Handling class/id selectors, as well as simple selector sequences con…
akhleung authored
157 }
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
158 return result;
a6ae423 @akhleung Gah, finally got parsing of comma-separated groups of simple selector…
akhleung authored
159 }
160 }
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
161
162 void Token::unquote_to_stream(std::stringstream& buf) const
f3e0a52 @akhleung functionality++; efficiency--; // got nested selector group combinati…
akhleung authored
163 {
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
164 const char* p = begin;
165 if (*begin == '\'' || *begin == '"') {
166 ++p;
167 while (p < end) {
168 if (*p == '\\') {
169 switch (*(++p)) {
170 case 'n': buf << '\n'; break;
171 case 't': buf << '\t'; break;
172 case 'b': buf << '\b'; break;
173 case 'r': buf << '\r'; break;
174 case 'f': buf << '\f'; break;
175 case 'v': buf << '\v'; break;
176 case 'a': buf << '\a'; break;
177 case '\\': buf << '\\'; break;
178 default: buf << *p; break;
f3e0a52 @akhleung functionality++; efficiency--; // got nested selector group combinati…
akhleung authored
179 }
180 }
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
181 else if (p == end - 1) {
182 return;
f3e0a52 @akhleung functionality++; efficiency--; // got nested selector group combinati…
akhleung authored
183 }
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
184 else {
185 buf << *p;
0086b38 @akhleung Cleaning up and correcting the nested-style emitter. Now handles arbi…
akhleung authored
186 }
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
187 ++p;
0086b38 @akhleung Cleaning up and correcting the nested-style emitter. Now handles arbi…
akhleung authored
188 }
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
189 return;
190 }
191 else {
192 while (p < end) {
193 buf << *(p++);
0086b38 @akhleung Cleaning up and correcting the nested-style emitter. Now handles arbi…
akhleung authored
194 }
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
195 return;
f3e0a52 @akhleung functionality++; efficiency--; // got nested selector group combinati…
akhleung authored
196 }
197 }
198
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
199 bool Token::operator<(const Token& rhs) const
f3e0a52 @akhleung functionality++; efficiency--; // got nested selector group combinati…
akhleung authored
200 {
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
201 const char* first1 = begin;
202 const char* last1 = end;
203 const char* first2 = rhs.begin;
204 const char* last2 = rhs.end;
205 while (first1!=last1)
f5dfac9 @akhleung Handling hex arithmetic. Ignoring more janky edge cases. Probably nee…
akhleung authored
206 {
11a8906 @akhleung Moved the less-than node comparison over to the refactored version.
akhleung authored
207 if (first2 == last2 || *first2 < *first1) return false;
208 else if (*first1 < *first2) return true;
209 ++first1; ++first2;
13f0472 @akhleung Getting the nested-style emitter working on basic cases. Still buggy …
akhleung authored
210 }
11a8906 @akhleung Moved the less-than node comparison over to the refactored version.
akhleung authored
211 return (first2 != last2);
13f0472 @akhleung Getting the nested-style emitter working on basic cases. Still buggy …
akhleung authored
212 }
3663a72 @akhleung Working on namespaced properties. Still trying to get them to emit co…
akhleung authored
213
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
214 bool Token::operator==(const Token& rhs) const
215 {
216 if (length() != rhs.length()) return false;
217
218 if ((begin[0] == '"' || begin[0] == '\'') &&
219 (rhs.begin[0] == '"' || rhs.begin[0] == '\''))
220 { return unquote() == rhs.unquote(); }
3663a72 @akhleung Working on namespaced properties. Still trying to get them to emit co…
akhleung authored
221
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
222 const char* p = begin;
223 const char* q = rhs.begin;
224 for (; p < end; ++p, ++q) if (*p != *q) return false;
225 return true;
3663a72 @akhleung Working on namespaced properties. Still trying to get them to emit co…
akhleung authored
226 }
d759699 @akhleung Working on selector combinators. Don't try to compile this.
akhleung authored
227
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
228
229 // ------------------------------------------------------------------------
230 // Node_Impl method implementations
231 // ------------------------------------------------------------------------
232
d12389e @akhleung Simplifying the numeric_value method slightly; no reason to return a …
akhleung authored
233 double Node_Impl::numeric_value()
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
234 {
235 switch (type)
236 {
83a92d8 @akhleung Putting the node type-tag enum back inside the Node class.
akhleung authored
237 case Node::number:
238 case Node::numeric_percentage:
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
239 return value.numeric;
83a92d8 @akhleung Putting the node type-tag enum back inside the Node class.
akhleung authored
240 case Node::numeric_dimension:
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
241 return value.dimension.numeric;
242 default:
243 break;
244 // throw an exception?
245 }
f9964c8 @akhleung All warnings gone!
akhleung authored
246 // if you reach this point, you've got a logic error somewhere
247 return 0;
e476b60 @akhleung Expanded-style output works (with some whitespace hiccups).
akhleung authored
248 }
c54a691 @akhleung Flattening blocks that contain expansion nodes in order to get them t…
akhleung authored
249
594d4b3 @akhleung Moving a node comparison function into the refactored version.
akhleung authored
250 extern const char percent_str[] = "%";
251 extern const char empty_str[] = "";
252 Token Node_Impl::unit()
c54a691 @akhleung Flattening blocks that contain expansion nodes in order to get them t…
akhleung authored
253 {
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
254 switch (type)
255 {
83a92d8 @akhleung Putting the node type-tag enum back inside the Node class.
akhleung authored
256 case Node::numeric_percentage: {
594d4b3 @akhleung Moving a node comparison function into the refactored version.
akhleung authored
257 return Token::make(percent_str);
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
258 } break;
259
83a92d8 @akhleung Putting the node type-tag enum back inside the Node class.
akhleung authored
260 case Node::numeric_dimension: {
594d4b3 @akhleung Moving a node comparison function into the refactored version.
akhleung authored
261 return value.dimension.unit;
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
262 } break;
263
264 default: break;
c54a691 @akhleung Flattening blocks that contain expansion nodes in order to get them t…
akhleung authored
265 }
594d4b3 @akhleung Moving a node comparison function into the refactored version.
akhleung authored
266 return Token::make(empty_str);
c54a691 @akhleung Flattening blocks that contain expansion nodes in order to get them t…
akhleung authored
267 }
e476b60 @akhleung Expanded-style output works (with some whitespace hiccups).
akhleung authored
268
37dbd22 @akhleung More Node reorganization. Pretty clean now. I guess.
akhleung authored
269 }
Something went wrong with that request. Please try again.