sassc 1.11.1 → 1.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +2 -2
- data/README.md +3 -2
- data/ext/libsass/Makefile.conf +2 -1
- data/ext/libsass/appveyor.yml +10 -5
- data/ext/libsass/docs/dev-ast-memory.md +223 -0
- data/ext/libsass/include/sass/base.h +2 -0
- data/ext/libsass/script/bootstrap +7 -4
- data/ext/libsass/script/ci-build-libsass +3 -3
- data/ext/libsass/script/ci-install-compiler +2 -0
- data/ext/libsass/script/ci-report-coverage +2 -1
- data/ext/libsass/script/test-leaks.pl +103 -0
- data/ext/libsass/src/ast.cpp +621 -495
- data/ext/libsass/src/ast.hpp +801 -367
- data/ext/libsass/src/ast_def_macros.hpp +5 -5
- data/ext/libsass/src/ast_fwd_decl.hpp +312 -14
- data/ext/libsass/src/bind.cpp +54 -51
- data/ext/libsass/src/bind.hpp +3 -7
- data/ext/libsass/src/check_nesting.cpp +117 -120
- data/ext/libsass/src/check_nesting.hpp +38 -34
- data/ext/libsass/src/color_maps.cpp +3 -3
- data/ext/libsass/src/color_maps.hpp +3 -3
- data/ext/libsass/src/context.cpp +33 -34
- data/ext/libsass/src/context.hpp +12 -14
- data/ext/libsass/src/cssize.cpp +200 -228
- data/ext/libsass/src/cssize.hpp +49 -49
- data/ext/libsass/src/debugger.hpp +260 -241
- data/ext/libsass/src/emitter.cpp +6 -6
- data/ext/libsass/src/emitter.hpp +7 -7
- data/ext/libsass/src/environment.cpp +2 -2
- data/ext/libsass/src/environment.hpp +0 -2
- data/ext/libsass/src/error_handling.cpp +5 -5
- data/ext/libsass/src/error_handling.hpp +12 -12
- data/ext/libsass/src/eval.cpp +412 -401
- data/ext/libsass/src/eval.hpp +61 -62
- data/ext/libsass/src/expand.cpp +223 -204
- data/ext/libsass/src/expand.hpp +42 -42
- data/ext/libsass/src/extend.cpp +198 -201
- data/ext/libsass/src/extend.hpp +12 -14
- data/ext/libsass/src/file.hpp +4 -5
- data/ext/libsass/src/functions.cpp +413 -418
- data/ext/libsass/src/functions.hpp +7 -10
- data/ext/libsass/src/inspect.cpp +115 -109
- data/ext/libsass/src/inspect.hpp +69 -69
- data/ext/libsass/src/listize.cpp +31 -33
- data/ext/libsass/src/listize.hpp +8 -10
- data/ext/libsass/src/memory/SharedPtr.cpp +116 -0
- data/ext/libsass/src/memory/SharedPtr.hpp +202 -0
- data/ext/libsass/src/node.cpp +45 -43
- data/ext/libsass/src/node.hpp +15 -15
- data/ext/libsass/src/operation.hpp +136 -136
- data/ext/libsass/src/output.cpp +48 -49
- data/ext/libsass/src/output.hpp +14 -14
- data/ext/libsass/src/parser.cpp +530 -554
- data/ext/libsass/src/parser.hpp +91 -96
- data/ext/libsass/src/prelexer.cpp +13 -10
- data/ext/libsass/src/remove_placeholders.cpp +25 -21
- data/ext/libsass/src/remove_placeholders.hpp +7 -7
- data/ext/libsass/src/sass2scss.cpp +2 -1
- data/ext/libsass/src/sass_context.cpp +125 -107
- data/ext/libsass/src/sass_context.hpp +1 -1
- data/ext/libsass/src/sass_util.hpp +5 -5
- data/ext/libsass/src/sass_values.cpp +27 -27
- data/ext/libsass/src/source_map.cpp +2 -2
- data/ext/libsass/src/source_map.hpp +2 -2
- data/ext/libsass/src/subset_map.cpp +57 -0
- data/ext/libsass/src/subset_map.hpp +8 -76
- data/ext/libsass/src/to_c.cpp +13 -13
- data/ext/libsass/src/to_c.hpp +14 -14
- data/ext/libsass/src/to_value.cpp +20 -20
- data/ext/libsass/src/to_value.hpp +20 -21
- data/ext/libsass/src/util.cpp +55 -88
- data/ext/libsass/src/util.hpp +9 -13
- data/ext/libsass/src/values.cpp +27 -26
- data/ext/libsass/src/values.hpp +2 -2
- data/ext/libsass/test/test_subset_map.cpp +69 -69
- data/ext/libsass/win/libsass.targets +3 -2
- data/ext/libsass/win/libsass.vcxproj.filters +9 -6
- data/lib/sassc/version.rb +1 -1
- data/sassc.gemspec +0 -1
- data/test/native_test.rb +1 -1
- metadata +7 -5
- data/ext/libsass/src/ast_factory.hpp +0 -92
- data/ext/libsass/src/memory_manager.cpp +0 -77
- data/ext/libsass/src/memory_manager.hpp +0 -48
data/ext/libsass/src/output.cpp
CHANGED
@@ -12,12 +12,12 @@ namespace Sass {
|
|
12
12
|
|
13
13
|
Output::~Output() { }
|
14
14
|
|
15
|
-
void Output::fallback_impl(
|
15
|
+
void Output::fallback_impl(AST_Node_Ptr n)
|
16
16
|
{
|
17
17
|
return n->perform(this);
|
18
18
|
}
|
19
19
|
|
20
|
-
void Output::operator()(
|
20
|
+
void Output::operator()(Number_Ptr n)
|
21
21
|
{
|
22
22
|
// use values to_string facility
|
23
23
|
std::string res = n->to_string(opt);
|
@@ -30,12 +30,12 @@ namespace Sass {
|
|
30
30
|
append_token(res, n);
|
31
31
|
}
|
32
32
|
|
33
|
-
void Output::operator()(
|
33
|
+
void Output::operator()(Import_Ptr imp)
|
34
34
|
{
|
35
35
|
top_nodes.push_back(imp);
|
36
36
|
}
|
37
37
|
|
38
|
-
void Output::operator()(
|
38
|
+
void Output::operator()(Map_Ptr m)
|
39
39
|
{
|
40
40
|
std::string dbg(m->to_string(opt));
|
41
41
|
error(dbg + " isn't a valid CSS value.", m->pstate());
|
@@ -85,7 +85,7 @@ namespace Sass {
|
|
85
85
|
|
86
86
|
}
|
87
87
|
|
88
|
-
void Output::operator()(
|
88
|
+
void Output::operator()(Comment_Ptr c)
|
89
89
|
{
|
90
90
|
std::string txt = c->text()->to_string(opt);
|
91
91
|
// if (indentation && txt == "/**/") return;
|
@@ -107,17 +107,17 @@ namespace Sass {
|
|
107
107
|
}
|
108
108
|
}
|
109
109
|
|
110
|
-
void Output::operator()(
|
110
|
+
void Output::operator()(Ruleset_Ptr r)
|
111
111
|
{
|
112
|
-
|
113
|
-
|
112
|
+
Selector_Obj s = r->selector();
|
113
|
+
Block_Obj b = r->block();
|
114
114
|
|
115
115
|
// Filter out rulesets that aren't printable (process its children though)
|
116
116
|
if (!Util::isPrintable(r, output_style())) {
|
117
117
|
for (size_t i = 0, L = b->length(); i < L; ++i) {
|
118
|
-
|
119
|
-
if (dynamic_cast<
|
120
|
-
if (
|
118
|
+
const Statement_Obj& stm = b->at(i);
|
119
|
+
if (dynamic_cast<Has_Block_Ptr>(&stm)) {
|
120
|
+
if (!dynamic_cast<Declaration_Ptr>(&stm)) {
|
121
121
|
stm->perform(this);
|
122
122
|
}
|
123
123
|
}
|
@@ -134,28 +134,25 @@ namespace Sass {
|
|
134
134
|
append_string(ss.str());
|
135
135
|
append_optional_linefeed();
|
136
136
|
}
|
137
|
-
s->perform(this);
|
138
|
-
append_scope_opener(b);
|
137
|
+
if (s) s->perform(this);
|
138
|
+
append_scope_opener(&b);
|
139
139
|
for (size_t i = 0, L = b->length(); i < L; ++i) {
|
140
|
-
|
140
|
+
Statement_Obj stm = b->at(i);
|
141
141
|
bool bPrintExpression = true;
|
142
142
|
// Check print conditions
|
143
|
-
if (
|
144
|
-
|
145
|
-
if (dec->value()->concrete_type() == Expression::STRING) {
|
146
|
-
String_Constant* valConst = static_cast<String_Constant*>(dec->value());
|
143
|
+
if (Declaration_Ptr dec = SASS_MEMORY_CAST(Declaration, stm)) {
|
144
|
+
if (String_Constant_Ptr valConst = SASS_MEMORY_CAST(String_Constant, dec->value())) {
|
147
145
|
std::string val(valConst->value());
|
148
|
-
if (
|
146
|
+
if (String_Quoted_Ptr qstr = SASS_MEMORY_CAST_PTR(String_Quoted, valConst)) {
|
149
147
|
if (!qstr->quote_mark() && val.empty()) {
|
150
148
|
bPrintExpression = false;
|
151
149
|
}
|
152
150
|
}
|
153
151
|
}
|
154
|
-
else if (dec->value()
|
155
|
-
List* list = static_cast<List*>(dec->value());
|
152
|
+
else if (List_Ptr list = SASS_MEMORY_CAST(List, dec->value())) {
|
156
153
|
bool all_invisible = true;
|
157
154
|
for (size_t list_i = 0, list_L = list->length(); list_i < list_L; ++list_i) {
|
158
|
-
|
155
|
+
Expression_Ptr item = &list->at(list_i);
|
159
156
|
if (!item->is_invisible()) all_invisible = false;
|
160
157
|
}
|
161
158
|
if (all_invisible) bPrintExpression = false;
|
@@ -167,15 +164,15 @@ namespace Sass {
|
|
167
164
|
}
|
168
165
|
}
|
169
166
|
if (output_style() == NESTED) indentation -= r->tabs();
|
170
|
-
append_scope_closer(b);
|
167
|
+
append_scope_closer(&b);
|
171
168
|
|
172
169
|
}
|
173
|
-
void Output::operator()(
|
170
|
+
void Output::operator()(Keyframe_Rule_Ptr r)
|
174
171
|
{
|
175
|
-
|
176
|
-
|
172
|
+
Block_Obj b = r->block();
|
173
|
+
Selector_Obj v = r->name();
|
177
174
|
|
178
|
-
if (v) {
|
175
|
+
if (&v) {
|
179
176
|
v->perform(this);
|
180
177
|
}
|
181
178
|
|
@@ -186,25 +183,25 @@ namespace Sass {
|
|
186
183
|
|
187
184
|
append_scope_opener();
|
188
185
|
for (size_t i = 0, L = b->length(); i < L; ++i) {
|
189
|
-
|
186
|
+
Statement_Obj stm = b->at(i);
|
190
187
|
stm->perform(this);
|
191
188
|
if (i < L - 1) append_special_linefeed();
|
192
189
|
}
|
193
190
|
append_scope_closer();
|
194
191
|
}
|
195
192
|
|
196
|
-
void Output::operator()(
|
193
|
+
void Output::operator()(Supports_Block_Ptr f)
|
197
194
|
{
|
198
195
|
if (f->is_invisible()) return;
|
199
196
|
|
200
|
-
|
201
|
-
|
197
|
+
Supports_Condition_Obj c = f->condition();
|
198
|
+
Block_Obj b = f->block();
|
202
199
|
|
203
200
|
// Filter out feature blocks that aren't printable (process its children though)
|
204
201
|
if (!Util::isPrintable(f, output_style())) {
|
205
202
|
for (size_t i = 0, L = b->length(); i < L; ++i) {
|
206
|
-
|
207
|
-
if (dynamic_cast<
|
203
|
+
Statement_Obj stm = b->at(i);
|
204
|
+
if (dynamic_cast<Has_Block_Ptr>(&stm)) {
|
208
205
|
stm->perform(this);
|
209
206
|
}
|
210
207
|
}
|
@@ -219,7 +216,7 @@ namespace Sass {
|
|
219
216
|
append_scope_opener();
|
220
217
|
|
221
218
|
for (size_t i = 0, L = b->length(); i < L; ++i) {
|
222
|
-
|
219
|
+
Statement_Obj stm = b->at(i);
|
223
220
|
stm->perform(this);
|
224
221
|
if (i < L - 1) append_special_linefeed();
|
225
222
|
}
|
@@ -230,18 +227,17 @@ namespace Sass {
|
|
230
227
|
|
231
228
|
}
|
232
229
|
|
233
|
-
void Output::operator()(
|
230
|
+
void Output::operator()(Media_Block_Ptr m)
|
234
231
|
{
|
235
232
|
if (m->is_invisible()) return;
|
236
233
|
|
237
|
-
|
238
|
-
Block* b = m->block();
|
234
|
+
Block_Obj b = m->block();
|
239
235
|
|
240
236
|
// Filter out media blocks that aren't printable (process its children though)
|
241
237
|
if (!Util::isPrintable(m, output_style())) {
|
242
238
|
for (size_t i = 0, L = b->length(); i < L; ++i) {
|
243
|
-
|
244
|
-
if (dynamic_cast<
|
239
|
+
Statement_Obj stm = b->at(i);
|
240
|
+
if (dynamic_cast<Has_Block_Ptr>(&stm)) {
|
245
241
|
stm->perform(this);
|
246
242
|
}
|
247
243
|
}
|
@@ -252,12 +248,15 @@ namespace Sass {
|
|
252
248
|
append_token("@media", m);
|
253
249
|
append_mandatory_space();
|
254
250
|
in_media_block = true;
|
255
|
-
|
251
|
+
m->media_queries()->perform(this);
|
256
252
|
in_media_block = false;
|
257
253
|
append_scope_opener();
|
258
254
|
|
259
255
|
for (size_t i = 0, L = b->length(); i < L; ++i) {
|
260
|
-
if ((
|
256
|
+
if (b->at(i)) {
|
257
|
+
Statement_Obj stm = b->at(i);
|
258
|
+
stm->perform(this);
|
259
|
+
}
|
261
260
|
if (i < L - 1) append_special_linefeed();
|
262
261
|
}
|
263
262
|
|
@@ -265,12 +264,12 @@ namespace Sass {
|
|
265
264
|
append_scope_closer();
|
266
265
|
}
|
267
266
|
|
268
|
-
void Output::operator()(
|
267
|
+
void Output::operator()(Directive_Ptr a)
|
269
268
|
{
|
270
269
|
std::string kwd = a->keyword();
|
271
|
-
|
272
|
-
|
273
|
-
|
270
|
+
Selector_Obj s = a->selector();
|
271
|
+
Expression_Obj v = a->value();
|
272
|
+
Block_Obj b = a->block();
|
274
273
|
|
275
274
|
append_indentation();
|
276
275
|
append_token(kwd, a);
|
@@ -283,7 +282,7 @@ namespace Sass {
|
|
283
282
|
if (v) {
|
284
283
|
append_mandatory_space();
|
285
284
|
// ruby sass bug? should use options?
|
286
|
-
append_token(v->to_string(/* opt */), v);
|
285
|
+
append_token(v->to_string(/* opt */), &v);
|
287
286
|
}
|
288
287
|
if (!b) {
|
289
288
|
append_delimiter();
|
@@ -300,7 +299,7 @@ namespace Sass {
|
|
300
299
|
bool format = kwd != "@font-face";;
|
301
300
|
|
302
301
|
for (size_t i = 0, L = b->length(); i < L; ++i) {
|
303
|
-
|
302
|
+
Statement_Obj stm = b->at(i);
|
304
303
|
stm->perform(this);
|
305
304
|
if (i < L - 1 && format) append_special_linefeed();
|
306
305
|
}
|
@@ -308,7 +307,7 @@ namespace Sass {
|
|
308
307
|
append_scope_closer();
|
309
308
|
}
|
310
309
|
|
311
|
-
void Output::operator()(
|
310
|
+
void Output::operator()(String_Quoted_Ptr s)
|
312
311
|
{
|
313
312
|
if (s->quote_mark()) {
|
314
313
|
append_token(quote(s->value(), s->quote_mark()), s);
|
@@ -319,7 +318,7 @@ namespace Sass {
|
|
319
318
|
}
|
320
319
|
}
|
321
320
|
|
322
|
-
void Output::operator()(
|
321
|
+
void Output::operator()(String_Constant_Ptr s)
|
323
322
|
{
|
324
323
|
std::string value(s->value());
|
325
324
|
if (s->can_compress_whitespace() && output_style() == COMPRESSED) {
|
data/ext/libsass/src/output.hpp
CHANGED
@@ -28,24 +28,24 @@ namespace Sass {
|
|
28
28
|
|
29
29
|
protected:
|
30
30
|
std::string charset;
|
31
|
-
std::vector<
|
31
|
+
std::vector<AST_Node_Ptr> top_nodes;
|
32
32
|
|
33
33
|
public:
|
34
34
|
OutputBuffer get_buffer(void);
|
35
35
|
|
36
|
-
virtual void operator()(
|
37
|
-
virtual void operator()(
|
38
|
-
virtual void operator()(
|
39
|
-
virtual void operator()(
|
40
|
-
virtual void operator()(
|
41
|
-
virtual void operator()(
|
42
|
-
virtual void operator()(
|
43
|
-
virtual void operator()(
|
44
|
-
virtual void operator()(
|
45
|
-
virtual void operator()(
|
46
|
-
virtual void operator()(
|
47
|
-
|
48
|
-
void fallback_impl(
|
36
|
+
virtual void operator()(Map_Ptr);
|
37
|
+
virtual void operator()(Ruleset_Ptr);
|
38
|
+
virtual void operator()(Supports_Block_Ptr);
|
39
|
+
virtual void operator()(Media_Block_Ptr);
|
40
|
+
virtual void operator()(Directive_Ptr);
|
41
|
+
virtual void operator()(Keyframe_Rule_Ptr);
|
42
|
+
virtual void operator()(Import_Ptr);
|
43
|
+
virtual void operator()(Comment_Ptr);
|
44
|
+
virtual void operator()(Number_Ptr);
|
45
|
+
virtual void operator()(String_Quoted_Ptr);
|
46
|
+
virtual void operator()(String_Constant_Ptr);
|
47
|
+
|
48
|
+
void fallback_impl(AST_Node_Ptr n);
|
49
49
|
|
50
50
|
};
|
51
51
|
|
data/ext/libsass/src/parser.cpp
CHANGED
@@ -39,7 +39,7 @@ namespace Sass {
|
|
39
39
|
p.source = source ? source : beg;
|
40
40
|
p.position = beg ? beg : p.source;
|
41
41
|
p.end = p.position + strlen(p.position);
|
42
|
-
|
42
|
+
Block_Obj root = SASS_MEMORY_NEW(Block, pstate);
|
43
43
|
p.block_stack.push_back(root);
|
44
44
|
root->is_root(true);
|
45
45
|
return p;
|
@@ -53,7 +53,7 @@ namespace Sass {
|
|
53
53
|
p.source = source ? source : beg;
|
54
54
|
p.position = beg ? beg : p.source;
|
55
55
|
p.end = end ? end : p.position + strlen(p.position);
|
56
|
-
|
56
|
+
Block_Obj root = SASS_MEMORY_NEW(Block, pstate);
|
57
57
|
p.block_stack.push_back(root);
|
58
58
|
root->is_root(true);
|
59
59
|
return p;
|
@@ -67,7 +67,7 @@ namespace Sass {
|
|
67
67
|
pstate.offset.line = 0;
|
68
68
|
}
|
69
69
|
|
70
|
-
|
70
|
+
Selector_List_Obj Parser::parse_selector(const char* beg, Context& ctx, ParserState pstate, const char* source)
|
71
71
|
{
|
72
72
|
Parser p = Parser::from_c_str(beg, ctx, pstate, source);
|
73
73
|
// ToDo: ruby sass errors on parent references
|
@@ -87,23 +87,23 @@ namespace Sass {
|
|
87
87
|
p.source = source ? source : t.begin;
|
88
88
|
p.position = t.begin ? t.begin : p.source;
|
89
89
|
p.end = t.end ? t.end : p.position + strlen(p.position);
|
90
|
-
|
90
|
+
Block_Obj root = SASS_MEMORY_NEW(Block, pstate);
|
91
91
|
p.block_stack.push_back(root);
|
92
92
|
root->is_root(true);
|
93
93
|
return p;
|
94
94
|
}
|
95
95
|
|
96
96
|
/* main entry point to parse root block */
|
97
|
-
|
97
|
+
Block_Obj Parser::parse()
|
98
98
|
{
|
99
99
|
bool is_root = false;
|
100
|
-
|
100
|
+
Block_Obj root = SASS_MEMORY_NEW(Block, pstate, 0, true);
|
101
101
|
read_bom();
|
102
102
|
|
103
103
|
// custom headers
|
104
104
|
if (ctx.resources.size() == 1) {
|
105
105
|
is_root = true;
|
106
|
-
ctx.apply_custom_headers(root, path, pstate);
|
106
|
+
ctx.apply_custom_headers(&root, path, pstate);
|
107
107
|
}
|
108
108
|
|
109
109
|
block_stack.push_back(root);
|
@@ -124,7 +124,7 @@ namespace Sass {
|
|
124
124
|
// convenience function for block parsing
|
125
125
|
// will create a new block ad-hoc for you
|
126
126
|
// this is the base block parsing function
|
127
|
-
|
127
|
+
Block_Obj Parser::parse_css_block(bool is_root)
|
128
128
|
{
|
129
129
|
|
130
130
|
// parse comments before block
|
@@ -135,30 +135,32 @@ namespace Sass {
|
|
135
135
|
css_error("Invalid CSS", " after ", ": expected \"{\", was ");
|
136
136
|
}
|
137
137
|
// create new block and push to the selector stack
|
138
|
-
|
138
|
+
Block_Obj block = SASS_MEMORY_NEW(Block, pstate, 0, is_root);
|
139
139
|
block_stack.push_back(block);
|
140
140
|
|
141
|
-
if (!parse_block_nodes()) css_error("Invalid CSS", " after ", ": expected \"}\", was ")
|
141
|
+
if (!parse_block_nodes()) css_error("Invalid CSS", " after ", ": expected \"}\", was ");
|
142
142
|
|
143
143
|
if (!lex_css < exactly<'}'> >()) {
|
144
144
|
css_error("Invalid CSS", " after ", ": expected \"}\", was ");
|
145
145
|
}
|
146
146
|
|
147
147
|
// update for end position
|
148
|
-
|
148
|
+
// this seems to be done somewhere else
|
149
|
+
// but that fixed selector schema issue
|
150
|
+
// block->update_pstate(pstate);
|
149
151
|
|
150
152
|
// parse comments after block
|
151
153
|
// lex < optional_css_comments >();
|
152
154
|
|
153
155
|
block_stack.pop_back();
|
154
156
|
|
155
|
-
return block;
|
157
|
+
return █
|
156
158
|
}
|
157
159
|
|
158
160
|
// convenience function for block parsing
|
159
161
|
// will create a new block ad-hoc for you
|
160
162
|
// also updates the `in_at_root` flag
|
161
|
-
|
163
|
+
Block_Obj Parser::parse_block(bool is_root)
|
162
164
|
{
|
163
165
|
LOCAL_FLAG(in_at_root, is_root);
|
164
166
|
return parse_css_block(is_root);
|
@@ -199,7 +201,7 @@ namespace Sass {
|
|
199
201
|
// semicolons must be lexed beforehand
|
200
202
|
bool Parser::parse_block_node(bool is_root) {
|
201
203
|
|
202
|
-
|
204
|
+
Block_Obj block = block_stack.back();
|
203
205
|
|
204
206
|
parse_block_comments();
|
205
207
|
|
@@ -212,20 +214,15 @@ namespace Sass {
|
|
212
214
|
// also parse block comments
|
213
215
|
|
214
216
|
// first parse everything that is allowed in functions
|
215
|
-
if (lex < variable >(true)) { (
|
216
|
-
else if (lex < kwd_err >(true)) { (
|
217
|
-
else if (lex < kwd_dbg >(true)) { (
|
218
|
-
else if (lex < kwd_warn >(true)) { (
|
219
|
-
else if (lex < kwd_if_directive >(true)) { (
|
220
|
-
else if (lex < kwd_for_directive >(true)) { (
|
221
|
-
else if (lex < kwd_each_directive >(true)) { (
|
222
|
-
else if (lex < kwd_while_directive >(true)) { (
|
223
|
-
else if (lex < kwd_return_directive >(true)) { (
|
224
|
-
|
225
|
-
// abort if we are in function context and have nothing parsed yet
|
226
|
-
else if (stack.back() == Scope::Function) {
|
227
|
-
error("Functions can only contain variable declarations and control directives.", pstate);
|
228
|
-
}
|
217
|
+
if (lex < variable >(true)) { block->append(&parse_assignment()); }
|
218
|
+
else if (lex < kwd_err >(true)) { block->append(&parse_error()); }
|
219
|
+
else if (lex < kwd_dbg >(true)) { block->append(&parse_debug()); }
|
220
|
+
else if (lex < kwd_warn >(true)) { block->append(&parse_warning()); }
|
221
|
+
else if (lex < kwd_if_directive >(true)) { block->append(&parse_if_directive()); }
|
222
|
+
else if (lex < kwd_for_directive >(true)) { block->append(&parse_for_directive()); }
|
223
|
+
else if (lex < kwd_each_directive >(true)) { block->append(&parse_each_directive()); }
|
224
|
+
else if (lex < kwd_while_directive >(true)) { block->append(&parse_while_directive()); }
|
225
|
+
else if (lex < kwd_return_directive >(true)) { block->append(&parse_return_directive()); }
|
229
226
|
|
230
227
|
// parse imports to process later
|
231
228
|
else if (lex < kwd_import >(true)) {
|
@@ -235,48 +232,44 @@ namespace Sass {
|
|
235
232
|
error("Import directives may not be used within control directives or mixins.", pstate);
|
236
233
|
}
|
237
234
|
}
|
238
|
-
|
235
|
+
Import_Obj imp = parse_import();
|
239
236
|
// if it is a url, we only add the statement
|
240
|
-
if (!imp->urls().empty()) (
|
237
|
+
if (!imp->urls().empty()) block->append(&imp);
|
241
238
|
// process all resources now (add Import_Stub nodes)
|
242
239
|
for (size_t i = 0, S = imp->incs().size(); i < S; ++i) {
|
243
|
-
(
|
240
|
+
block->append(SASS_MEMORY_NEW(Import_Stub, pstate, imp->incs()[i]));
|
244
241
|
}
|
245
242
|
}
|
246
243
|
|
247
244
|
else if (lex < kwd_extend >(true)) {
|
248
|
-
if (block->is_root()) {
|
249
|
-
error("Extend directives may only be used within rules.", pstate);
|
250
|
-
}
|
251
|
-
|
252
245
|
Lookahead lookahead = lookahead_for_include(position);
|
253
246
|
if (!lookahead.found) css_error("Invalid CSS", " after ", ": expected selector, was ");
|
254
|
-
|
255
|
-
if (lookahead.has_interpolants) target = parse_selector_schema(lookahead.found);
|
256
|
-
else target = parse_selector_list(true);
|
257
|
-
(
|
247
|
+
Selector_Obj target;
|
248
|
+
if (lookahead.has_interpolants) target = &parse_selector_schema(lookahead.found);
|
249
|
+
else target = &parse_selector_list(true);
|
250
|
+
block->append(SASS_MEMORY_NEW(Extension, pstate, &target));
|
258
251
|
}
|
259
252
|
|
260
253
|
// selector may contain interpolations which need delayed evaluation
|
261
254
|
else if (!(lookahead_result = lookahead_for_selector(position)).error)
|
262
|
-
{ (
|
255
|
+
{ block->append(&parse_ruleset(lookahead_result, is_root)); }
|
263
256
|
|
264
257
|
// parse multiple specific keyword directives
|
265
|
-
else if (lex < kwd_media >(true)) { (
|
266
|
-
else if (lex < kwd_at_root >(true)) { (
|
267
|
-
else if (lex < kwd_include_directive >(true)) { (
|
268
|
-
else if (lex < kwd_content_directive >(true)) { (
|
269
|
-
else if (lex < kwd_supports_directive >(true)) { (
|
270
|
-
else if (lex < kwd_mixin >(true)) { (
|
271
|
-
else if (lex < kwd_function >(true)) { (
|
258
|
+
else if (lex < kwd_media >(true)) { block->append(&parse_media_block()); }
|
259
|
+
else if (lex < kwd_at_root >(true)) { block->append(&parse_at_root_block()); }
|
260
|
+
else if (lex < kwd_include_directive >(true)) { block->append(&parse_include_directive()); }
|
261
|
+
else if (lex < kwd_content_directive >(true)) { block->append(&parse_content_directive()); }
|
262
|
+
else if (lex < kwd_supports_directive >(true)) { block->append(&parse_supports_directive()); }
|
263
|
+
else if (lex < kwd_mixin >(true)) { block->append(&parse_definition(Definition::MIXIN)); }
|
264
|
+
else if (lex < kwd_function >(true)) { block->append(&parse_definition(Definition::FUNCTION)); }
|
272
265
|
|
273
266
|
// ignore the @charset directive for now
|
274
267
|
else if (lex< kwd_charset_directive >(true)) { parse_charset_directive(); }
|
275
268
|
|
276
269
|
// generic at keyword (keep last)
|
277
|
-
else if (lex< re_special_directive >(true)) { (
|
278
|
-
else if (lex< re_prefixed_directive >(true)) { (
|
279
|
-
else if (lex< at_keyword >(true)) { (
|
270
|
+
else if (lex< re_special_directive >(true)) { block->append(&parse_special_directive()); }
|
271
|
+
else if (lex< re_prefixed_directive >(true)) { block->append(&parse_prefixed_directive()); }
|
272
|
+
else if (lex< at_keyword >(true)) { block->append(&parse_directive()); }
|
280
273
|
|
281
274
|
else if (is_root /* && block->is_root() */) {
|
282
275
|
lex< css_whitespace >();
|
@@ -288,9 +281,9 @@ namespace Sass {
|
|
288
281
|
{
|
289
282
|
// ToDo: how does it handle parse errors?
|
290
283
|
// maybe we are expected to parse something?
|
291
|
-
|
284
|
+
Declaration_Obj decl = parse_declaration();
|
292
285
|
decl->tabs(indentation);
|
293
|
-
(
|
286
|
+
block->append(&decl);
|
294
287
|
// maybe we have a "sub-block"
|
295
288
|
if (peek< exactly<'{'> >()) {
|
296
289
|
if (decl->is_indented()) ++ indentation;
|
@@ -307,36 +300,36 @@ namespace Sass {
|
|
307
300
|
// EO parse_block_nodes
|
308
301
|
|
309
302
|
// parse imports inside the
|
310
|
-
|
303
|
+
Import_Obj Parser::parse_import()
|
311
304
|
{
|
312
|
-
|
313
|
-
std::vector<std::pair<std::string,
|
305
|
+
Import_Obj imp = SASS_MEMORY_NEW(Import, pstate);
|
306
|
+
std::vector<std::pair<std::string,Function_Call_Obj>> to_import;
|
314
307
|
bool first = true;
|
315
308
|
do {
|
316
309
|
while (lex< block_comment >());
|
317
310
|
if (lex< quoted_string >()) {
|
318
|
-
to_import.push_back(std::pair<std::string,
|
311
|
+
to_import.push_back(std::pair<std::string,Function_Call_Obj>(std::string(lexed), 0));
|
319
312
|
}
|
320
313
|
else if (lex< uri_prefix >()) {
|
321
|
-
|
322
|
-
|
314
|
+
Arguments_Obj args = SASS_MEMORY_NEW(Arguments, pstate);
|
315
|
+
Function_Call_Obj result = SASS_MEMORY_NEW(Function_Call, pstate, "url", &args);
|
323
316
|
|
324
317
|
if (lex< quoted_string >()) {
|
325
|
-
|
326
|
-
|
318
|
+
Expression_Obj the_url = &parse_string();
|
319
|
+
args->append(SASS_MEMORY_NEW(Argument, the_url->pstate(), &the_url));
|
327
320
|
}
|
328
|
-
else if (
|
329
|
-
|
321
|
+
else if (String_Obj the_url = parse_url_function_argument()) {
|
322
|
+
args->append(SASS_MEMORY_NEW(Argument, the_url->pstate(), &the_url));
|
330
323
|
}
|
331
324
|
else if (peek < skip_over_scopes < exactly < '(' >, exactly < ')' > > >(position)) {
|
332
|
-
|
333
|
-
|
325
|
+
Expression_Obj the_url = parse_list(); // parse_interpolated_chunk(lexed);
|
326
|
+
args->append(SASS_MEMORY_NEW(Argument, the_url->pstate(), &the_url));
|
334
327
|
}
|
335
328
|
else {
|
336
329
|
error("malformed URL", pstate);
|
337
330
|
}
|
338
331
|
if (!lex< exactly<')'> >()) error("URI is missing ')'", pstate);
|
339
|
-
to_import.push_back(std::pair<std::string,
|
332
|
+
to_import.push_back(std::pair<std::string, Function_Call_Obj>("", &result));
|
340
333
|
}
|
341
334
|
else {
|
342
335
|
if (first) error("@import directive requires a url or quoted path", pstate);
|
@@ -346,56 +339,46 @@ namespace Sass {
|
|
346
339
|
} while (lex_css< exactly<','> >());
|
347
340
|
|
348
341
|
if (!peek_css< alternatives< exactly<';'>, exactly<'}'>, end_of_file > >()) {
|
349
|
-
|
350
|
-
imp->
|
342
|
+
List_Obj import_queries = parse_media_queries();
|
343
|
+
imp->import_queries(import_queries);
|
351
344
|
}
|
352
345
|
|
353
346
|
for(auto location : to_import) {
|
354
347
|
if (location.second) {
|
355
|
-
imp->urls().push_back(location.second);
|
356
|
-
} else if (!ctx.call_importers(unquote(location.first), path, pstate, imp)) {
|
357
|
-
ctx.import_url(imp, location.first, path);
|
348
|
+
imp->urls().push_back(&location.second);
|
349
|
+
} else if (!ctx.call_importers(unquote(location.first), path, pstate, &imp)) {
|
350
|
+
ctx.import_url(&imp, location.first, path);
|
358
351
|
}
|
359
352
|
}
|
360
353
|
|
361
354
|
return imp;
|
362
355
|
}
|
363
356
|
|
364
|
-
|
357
|
+
Definition_Obj Parser::parse_definition(Definition::Type which_type)
|
365
358
|
{
|
366
|
-
Scope parent = stack.empty() ? Scope::Rules : stack.back();
|
367
|
-
if (parent != Scope::Root && parent != Scope::Rules && parent != Scope::Function) {
|
368
|
-
if (which_type == Definition::FUNCTION) {
|
369
|
-
error("Functions may not be defined within control directives or other mixins.", pstate);
|
370
|
-
} else {
|
371
|
-
error("Mixins may not be defined within control directives or other mixins.", pstate);
|
372
|
-
}
|
373
|
-
|
374
|
-
}
|
375
359
|
std::string which_str(lexed);
|
376
360
|
if (!lex< identifier >()) error("invalid name in " + which_str + " definition", pstate);
|
377
361
|
std::string name(Util::normalize_underscores(lexed));
|
378
362
|
if (which_type == Definition::FUNCTION && (name == "and" || name == "or" || name == "not"))
|
379
363
|
{ error("Invalid function name \"" + name + "\".", pstate); }
|
380
364
|
ParserState source_position_of_def = pstate;
|
381
|
-
|
365
|
+
Parameters_Obj params = parse_parameters();
|
382
366
|
if (which_type == Definition::MIXIN) stack.push_back(Scope::Mixin);
|
383
367
|
else stack.push_back(Scope::Function);
|
384
|
-
|
368
|
+
Block_Obj body = parse_block();
|
385
369
|
stack.pop_back();
|
386
|
-
|
387
|
-
return def;
|
370
|
+
return SASS_MEMORY_NEW(Definition, source_position_of_def, name, ¶ms, &body, which_type);
|
388
371
|
}
|
389
372
|
|
390
|
-
|
373
|
+
Parameters_Obj Parser::parse_parameters()
|
391
374
|
{
|
392
375
|
std::string name(lexed);
|
393
376
|
Position position = after_token;
|
394
|
-
|
377
|
+
Parameters_Obj params = SASS_MEMORY_NEW(Parameters, pstate);
|
395
378
|
if (lex_css< exactly<'('> >()) {
|
396
379
|
// if there's anything there at all
|
397
380
|
if (!peek_css< exactly<')'> >()) {
|
398
|
-
do (
|
381
|
+
do params->append(&parse_parameter());
|
399
382
|
while (lex_css< exactly<','> >());
|
400
383
|
}
|
401
384
|
if (!lex_css< exactly<')'> >()) error("expected a variable name (e.g. $x) or ')' for the parameter list for " + name, position);
|
@@ -403,13 +386,13 @@ namespace Sass {
|
|
403
386
|
return params;
|
404
387
|
}
|
405
388
|
|
406
|
-
|
389
|
+
Parameter_Obj Parser::parse_parameter()
|
407
390
|
{
|
408
391
|
while (lex< alternatives < spaces, block_comment > >());
|
409
392
|
lex < variable >();
|
410
393
|
std::string name(Util::normalize_underscores(lexed));
|
411
394
|
ParserState pos = pstate;
|
412
|
-
|
395
|
+
Expression_Obj val;
|
413
396
|
bool is_rest = false;
|
414
397
|
while (lex< alternatives < spaces, block_comment > >());
|
415
398
|
if (lex< exactly<':'> >()) { // there's a default value
|
@@ -419,19 +402,18 @@ namespace Sass {
|
|
419
402
|
else if (lex< exactly< ellipsis > >()) {
|
420
403
|
is_rest = true;
|
421
404
|
}
|
422
|
-
|
423
|
-
return p;
|
405
|
+
return SASS_MEMORY_NEW(Parameter, pos, name, &val, is_rest);
|
424
406
|
}
|
425
407
|
|
426
|
-
|
408
|
+
Arguments_Obj Parser::parse_arguments()
|
427
409
|
{
|
428
410
|
std::string name(lexed);
|
429
411
|
Position position = after_token;
|
430
|
-
|
412
|
+
Arguments_Obj args = SASS_MEMORY_NEW(Arguments, pstate);
|
431
413
|
if (lex_css< exactly<'('> >()) {
|
432
414
|
// if there's anything there at all
|
433
415
|
if (!peek_css< exactly<')'> >()) {
|
434
|
-
do (
|
416
|
+
do args->append(&parse_argument());
|
435
417
|
while (lex_css< exactly<','> >());
|
436
418
|
}
|
437
419
|
if (!lex_css< exactly<')'> >()) error("expected a variable name (e.g. $x) or ')' for the parameter list for " + name, position);
|
@@ -439,39 +421,39 @@ namespace Sass {
|
|
439
421
|
return args;
|
440
422
|
}
|
441
423
|
|
442
|
-
|
424
|
+
Argument_Obj Parser::parse_argument()
|
443
425
|
{
|
444
426
|
if (peek_css< sequence < exactly< hash_lbrace >, exactly< rbrace > > >()) {
|
445
427
|
position += 2;
|
446
428
|
css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
|
447
429
|
}
|
448
430
|
|
449
|
-
|
431
|
+
Argument_Obj arg;
|
450
432
|
if (peek_css< sequence < variable, optional_css_comments, exactly<':'> > >()) {
|
451
433
|
lex_css< variable >();
|
452
434
|
std::string name(Util::normalize_underscores(lexed));
|
453
435
|
ParserState p = pstate;
|
454
436
|
lex_css< exactly<':'> >();
|
455
|
-
|
456
|
-
arg = SASS_MEMORY_NEW(
|
437
|
+
Expression_Obj val = parse_space_list();
|
438
|
+
arg = SASS_MEMORY_NEW(Argument, p, val, name);
|
457
439
|
}
|
458
440
|
else {
|
459
441
|
bool is_arglist = false;
|
460
442
|
bool is_keyword = false;
|
461
|
-
|
462
|
-
|
443
|
+
Expression_Obj val = parse_space_list();
|
444
|
+
List_Ptr l = SASS_MEMORY_CAST(List, val);
|
463
445
|
if (lex_css< exactly< ellipsis > >()) {
|
464
446
|
if (val->concrete_type() == Expression::MAP || (
|
465
447
|
(l != NULL && l->separator() == SASS_HASH)
|
466
448
|
)) is_keyword = true;
|
467
449
|
else is_arglist = true;
|
468
450
|
}
|
469
|
-
arg = SASS_MEMORY_NEW(
|
451
|
+
arg = SASS_MEMORY_NEW(Argument, pstate, val, "", is_arglist, is_keyword);
|
470
452
|
}
|
471
453
|
return arg;
|
472
454
|
}
|
473
455
|
|
474
|
-
|
456
|
+
Assignment_Obj Parser::parse_assignment()
|
475
457
|
{
|
476
458
|
std::string name(Util::normalize_underscores(lexed));
|
477
459
|
ParserState var_source_position = pstate;
|
@@ -479,10 +461,10 @@ namespace Sass {
|
|
479
461
|
if (peek_css< alternatives < exactly<';'>, end_of_file > >()) {
|
480
462
|
css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
|
481
463
|
}
|
482
|
-
|
464
|
+
Expression_Obj val;
|
483
465
|
Lookahead lookahead = lookahead_for_value(position);
|
484
466
|
if (lookahead.has_interpolants && lookahead.found) {
|
485
|
-
val = parse_value_schema(lookahead.found);
|
467
|
+
val = &parse_value_schema(lookahead.found);
|
486
468
|
} else {
|
487
469
|
val = parse_list();
|
488
470
|
}
|
@@ -492,26 +474,26 @@ namespace Sass {
|
|
492
474
|
if (lex< default_flag >()) is_default = true;
|
493
475
|
else if (lex< global_flag >()) is_global = true;
|
494
476
|
}
|
495
|
-
|
496
|
-
return var;
|
477
|
+
return SASS_MEMORY_NEW(Assignment, var_source_position, name, val, is_default, is_global);
|
497
478
|
}
|
498
479
|
|
499
480
|
// a ruleset connects a selector and a block
|
500
|
-
|
481
|
+
Ruleset_Obj Parser::parse_ruleset(Lookahead lookahead, bool is_root)
|
501
482
|
{
|
502
483
|
// make sure to move up the the last position
|
503
484
|
lex < optional_css_whitespace >(false, true);
|
504
485
|
// create the connector object (add parts later)
|
505
|
-
|
486
|
+
Ruleset_Obj ruleset = SASS_MEMORY_NEW(Ruleset, pstate);
|
506
487
|
// parse selector static or as schema to be evaluated later
|
507
|
-
if (lookahead.parsable) ruleset->selector(parse_selector_list(is_root));
|
508
|
-
else ruleset->selector(parse_selector_schema(lookahead.found));
|
488
|
+
if (lookahead.parsable) ruleset->selector(&parse_selector_list(is_root));
|
489
|
+
else ruleset->selector(&parse_selector_schema(lookahead.found));
|
509
490
|
// then parse the inner block
|
510
491
|
stack.push_back(Scope::Rules);
|
511
492
|
ruleset->block(parse_block());
|
512
493
|
stack.pop_back();
|
513
494
|
// update for end position
|
514
495
|
ruleset->update_pstate(pstate);
|
496
|
+
ruleset->block()->update_pstate(pstate);
|
515
497
|
// inherit is_root from parent block
|
516
498
|
// need this info for sanity checks
|
517
499
|
ruleset->is_root(is_root);
|
@@ -522,15 +504,15 @@ namespace Sass {
|
|
522
504
|
// parse a selector schema that will be evaluated in the eval stage
|
523
505
|
// uses a string schema internally to do the actual schema handling
|
524
506
|
// in the eval stage we will be re-parse it into an actual selector
|
525
|
-
|
507
|
+
Selector_Schema_Obj Parser::parse_selector_schema(const char* end_of_selector)
|
526
508
|
{
|
527
509
|
// move up to the start
|
528
510
|
lex< optional_spaces >();
|
529
511
|
const char* i = position;
|
530
512
|
// selector schema re-uses string schema implementation
|
531
|
-
|
513
|
+
String_Schema_Ptr schema = SASS_MEMORY_NEW(String_Schema, pstate);
|
532
514
|
// the selector schema is pretty much just a wrapper for the string schema
|
533
|
-
|
515
|
+
Selector_Schema_Ptr selector_schema = SASS_MEMORY_NEW(Selector_Schema, pstate, schema);
|
534
516
|
selector_schema->media_block(last_media_block);
|
535
517
|
|
536
518
|
// process until end
|
@@ -538,7 +520,14 @@ namespace Sass {
|
|
538
520
|
// try to parse mutliple interpolants
|
539
521
|
if (const char* p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, end_of_selector)) {
|
540
522
|
// accumulate the preceding segment if the position has advanced
|
541
|
-
if (i < p)
|
523
|
+
if (i < p) {
|
524
|
+
std::string parsed(i, p);
|
525
|
+
String_Constant_Obj str = SASS_MEMORY_NEW(String_Constant, pstate, parsed);
|
526
|
+
pstate += Offset(parsed);
|
527
|
+
str->update_pstate(pstate);
|
528
|
+
schema->append(&str);
|
529
|
+
}
|
530
|
+
|
542
531
|
// check if the interpolation only contains white-space (error out)
|
543
532
|
if (peek < sequence < optional_spaces, exactly<rbrace> > >(p+2)) { position = p+2;
|
544
533
|
css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
|
@@ -546,12 +535,15 @@ namespace Sass {
|
|
546
535
|
// skip over all nested inner interpolations up to our own delimiter
|
547
536
|
const char* j = skip_over_scopes< exactly<hash_lbrace>, exactly<rbrace> >(p + 2, end_of_selector);
|
548
537
|
// pass inner expression to the parser to resolve nested interpolations
|
549
|
-
|
538
|
+
pstate.add(p, p+2);
|
539
|
+
Expression_Obj interpolant = Parser::from_c_str(p+2, j, ctx, pstate).parse_list();
|
550
540
|
// set status on the list expression
|
551
541
|
interpolant->is_interpolant(true);
|
552
542
|
// schema->has_interpolants(true);
|
553
543
|
// add to the string schema
|
554
|
-
(
|
544
|
+
schema->append(&interpolant);
|
545
|
+
// advance parser state
|
546
|
+
pstate.add(p+2, j);
|
555
547
|
// advance position
|
556
548
|
i = j;
|
557
549
|
}
|
@@ -559,9 +551,15 @@ namespace Sass {
|
|
559
551
|
// add the last segment if there is one
|
560
552
|
else {
|
561
553
|
// make sure to add the last bits of the string up to the end (if any)
|
562
|
-
if (i < end_of_selector)
|
554
|
+
if (i < end_of_selector) {
|
555
|
+
std::string parsed(i, end_of_selector);
|
556
|
+
String_Constant_Obj str = SASS_MEMORY_NEW(String_Constant, pstate, parsed);
|
557
|
+
pstate += Offset(parsed);
|
558
|
+
str->update_pstate(pstate);
|
559
|
+
i = end_of_selector;
|
560
|
+
schema->append(&str);
|
561
|
+
}
|
563
562
|
// exit loop
|
564
|
-
i = end_of_selector;
|
565
563
|
}
|
566
564
|
}
|
567
565
|
// EO until eos
|
@@ -571,6 +569,9 @@ namespace Sass {
|
|
571
569
|
|
572
570
|
// update for end position
|
573
571
|
selector_schema->update_pstate(pstate);
|
572
|
+
schema->update_pstate(pstate);
|
573
|
+
|
574
|
+
after_token = before_token = pstate;
|
574
575
|
|
575
576
|
// return parsed result
|
576
577
|
return selector_schema;
|
@@ -589,14 +590,14 @@ namespace Sass {
|
|
589
590
|
}
|
590
591
|
|
591
592
|
// called after parsing `kwd_include_directive`
|
592
|
-
|
593
|
+
Mixin_Call_Obj Parser::parse_include_directive()
|
593
594
|
{
|
594
595
|
// lex identifier into `lexed` var
|
595
596
|
lex_identifier(); // may error out
|
596
597
|
// normalize underscores to hyphens
|
597
598
|
std::string name(Util::normalize_underscores(lexed));
|
598
599
|
// create the initial mixin call object
|
599
|
-
|
600
|
+
Mixin_Call_Obj call = SASS_MEMORY_NEW(Mixin_Call, pstate, name, 0, 0);
|
600
601
|
// parse mandatory arguments
|
601
602
|
call->arguments(parse_arguments());
|
602
603
|
// parse optional block
|
@@ -604,20 +605,19 @@ namespace Sass {
|
|
604
605
|
call->block(parse_block());
|
605
606
|
}
|
606
607
|
// return ast node
|
607
|
-
return call;
|
608
|
+
return call.detach();
|
608
609
|
}
|
609
610
|
// EO parse_include_directive
|
610
611
|
|
611
612
|
// parse a list of complex selectors
|
612
613
|
// this is the main entry point for most
|
613
|
-
|
614
|
+
Selector_List_Obj Parser::parse_selector_list(bool in_root)
|
614
615
|
{
|
615
616
|
bool reloop = true;
|
616
617
|
bool had_linefeed = false;
|
617
|
-
|
618
|
-
|
618
|
+
Complex_Selector_Obj sel;
|
619
|
+
Selector_List_Obj group = SASS_MEMORY_NEW(Selector_List, pstate);
|
619
620
|
group->media_block(last_media_block);
|
620
|
-
|
621
621
|
do {
|
622
622
|
reloop = false;
|
623
623
|
|
@@ -630,7 +630,7 @@ namespace Sass {
|
|
630
630
|
// now parse the complex selector
|
631
631
|
sel = parse_complex_selector(in_root);
|
632
632
|
|
633
|
-
if (!sel) return group;
|
633
|
+
if (!sel) return group.detach();
|
634
634
|
|
635
635
|
sel->has_line_feed(had_linefeed);
|
636
636
|
|
@@ -645,7 +645,7 @@ namespace Sass {
|
|
645
645
|
had_linefeed = had_linefeed || peek_newline();
|
646
646
|
// remember line break (also between some commas)
|
647
647
|
}
|
648
|
-
(
|
648
|
+
group->append(sel);
|
649
649
|
}
|
650
650
|
while (reloop);
|
651
651
|
while (lex_css< kwd_optional >()) {
|
@@ -654,7 +654,7 @@ namespace Sass {
|
|
654
654
|
// update for end position
|
655
655
|
group->update_pstate(pstate);
|
656
656
|
if (sel) sel->last()->has_line_break(false);
|
657
|
-
return group;
|
657
|
+
return group.detach();
|
658
658
|
}
|
659
659
|
// EO parse_selector_list
|
660
660
|
|
@@ -662,16 +662,16 @@ namespace Sass {
|
|
662
662
|
// complex selector, with one of four combinator operations.
|
663
663
|
// the compound selector (head) is optional, since the combinator
|
664
664
|
// can come first in the whole selector sequence (like `> DIV').
|
665
|
-
|
665
|
+
Complex_Selector_Obj Parser::parse_complex_selector(bool in_root)
|
666
666
|
{
|
667
667
|
|
668
|
-
|
668
|
+
String_Ptr reference = 0;
|
669
669
|
lex < block_comment >();
|
670
|
-
|
671
|
-
|
670
|
+
advanceToNextToken();
|
671
|
+
Complex_Selector_Obj sel = SASS_MEMORY_NEW(Complex_Selector, pstate);
|
672
672
|
|
673
673
|
// parse the left hand side
|
674
|
-
|
674
|
+
Compound_Selector_Obj lhs;
|
675
675
|
// special case if it starts with combinator ([+~>])
|
676
676
|
if (!peek_css< class_char < selector_combinator_ops > >()) {
|
677
677
|
// parse the left hand side
|
@@ -682,27 +682,27 @@ namespace Sass {
|
|
682
682
|
if (peek < end_of_file >()) return 0;
|
683
683
|
|
684
684
|
// parse combinator between lhs and rhs
|
685
|
-
|
686
|
-
if (lex< exactly<'+'> >()) combinator =
|
687
|
-
else if (lex< exactly<'~'> >()) combinator =
|
688
|
-
else if (lex< exactly<'>'> >()) combinator =
|
685
|
+
Complex_Selector::Combinator combinator;
|
686
|
+
if (lex< exactly<'+'> >()) combinator = Complex_Selector::ADJACENT_TO;
|
687
|
+
else if (lex< exactly<'~'> >()) combinator = Complex_Selector::PRECEDES;
|
688
|
+
else if (lex< exactly<'>'> >()) combinator = Complex_Selector::PARENT_OF;
|
689
689
|
else if (lex< sequence < exactly<'/'>, negate < exactly < '*' > > > >()) {
|
690
690
|
// comments are allowed, but not spaces?
|
691
|
-
combinator =
|
691
|
+
combinator = Complex_Selector::REFERENCE;
|
692
692
|
if (!lex < re_reference_combinator >()) return 0;
|
693
|
-
reference = SASS_MEMORY_NEW(
|
693
|
+
reference = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
|
694
694
|
if (!lex < exactly < '/' > >()) return 0; // ToDo: error msg?
|
695
695
|
}
|
696
|
-
else /* if (lex< zero >()) */ combinator =
|
696
|
+
else /* if (lex< zero >()) */ combinator = Complex_Selector::ANCESTOR_OF;
|
697
697
|
|
698
|
-
if (!lhs && combinator ==
|
698
|
+
if (!lhs && combinator == Complex_Selector::ANCESTOR_OF) return 0;
|
699
699
|
|
700
700
|
// lex < block_comment >();
|
701
701
|
sel->head(lhs);
|
702
702
|
sel->combinator(combinator);
|
703
703
|
sel->media_block(last_media_block);
|
704
704
|
|
705
|
-
if (combinator ==
|
705
|
+
if (combinator == Complex_Selector::REFERENCE) sel->reference(reference);
|
706
706
|
// has linfeed after combinator?
|
707
707
|
sel->has_line_break(peek_newline());
|
708
708
|
// sel->has_line_feed(has_line_feed);
|
@@ -717,17 +717,17 @@ namespace Sass {
|
|
717
717
|
// also skip adding parent ref if we only have refs
|
718
718
|
if (!sel->has_parent_ref() && !in_at_root && !in_root) {
|
719
719
|
// create the objects to wrap parent selector reference
|
720
|
-
|
721
|
-
|
720
|
+
Compound_Selector_Obj head = SASS_MEMORY_NEW(Compound_Selector, pstate);
|
721
|
+
Parent_Selector_Ptr parent = SASS_MEMORY_NEW(Parent_Selector, pstate, false);
|
722
722
|
parent->media_block(last_media_block);
|
723
723
|
head->media_block(last_media_block);
|
724
724
|
// add simple selector
|
725
|
-
(
|
725
|
+
head->append(parent);
|
726
726
|
// selector may not have any head yet
|
727
727
|
if (!sel->head()) { sel->head(head); }
|
728
728
|
// otherwise we need to create a new complex selector and set the old one as its tail
|
729
729
|
else {
|
730
|
-
sel = SASS_MEMORY_NEW(
|
730
|
+
sel = SASS_MEMORY_NEW(Complex_Selector, pstate, Complex_Selector::ANCESTOR_OF, head, sel);
|
731
731
|
sel->media_block(last_media_block);
|
732
732
|
}
|
733
733
|
// peek for linefeed and remember result on head
|
@@ -735,7 +735,6 @@ namespace Sass {
|
|
735
735
|
}
|
736
736
|
|
737
737
|
sel->update_pstate(pstate);
|
738
|
-
|
739
738
|
// complex selector
|
740
739
|
return sel;
|
741
740
|
}
|
@@ -744,10 +743,10 @@ namespace Sass {
|
|
744
743
|
// parse one compound selector, which is basically
|
745
744
|
// a list of simple selectors (directly adjacent)
|
746
745
|
// lex them exactly (without skipping white-space)
|
747
|
-
|
746
|
+
Compound_Selector_Obj Parser::parse_compound_selector()
|
748
747
|
{
|
749
748
|
// init an empty compound selector wrapper
|
750
|
-
|
749
|
+
Compound_Selector_Obj seq = SASS_MEMORY_NEW(Compound_Selector, pstate);
|
751
750
|
seq->media_block(last_media_block);
|
752
751
|
|
753
752
|
// skip initial white-space
|
@@ -761,20 +760,20 @@ namespace Sass {
|
|
761
760
|
// parse functional
|
762
761
|
if (match < re_pseudo_selector >())
|
763
762
|
{
|
764
|
-
(
|
763
|
+
seq->append(&parse_simple_selector());
|
765
764
|
}
|
766
765
|
// parse parent selector
|
767
766
|
else if (lex< exactly<'&'> >(false))
|
768
767
|
{
|
769
768
|
// this produces a linefeed!?
|
770
769
|
seq->has_parent_reference(true);
|
771
|
-
(
|
770
|
+
seq->append(SASS_MEMORY_NEW(Parent_Selector, pstate));
|
772
771
|
// parent selector only allowed at start
|
773
772
|
// upcoming Sass may allow also trailing
|
774
773
|
if (seq->length() > 1) {
|
775
774
|
ParserState state(pstate);
|
776
|
-
|
777
|
-
|
775
|
+
Simple_Selector_Obj cur = (*seq)[seq->length()-1];
|
776
|
+
Simple_Selector_Obj prev = (*seq)[seq->length()-2];
|
778
777
|
std::string sel(prev->to_string({ NESTED, 5 }));
|
779
778
|
std::string found(cur->to_string({ NESTED, 5 }));
|
780
779
|
if (lex < identifier >()) { found += std::string(lexed); }
|
@@ -785,7 +784,7 @@ namespace Sass {
|
|
785
784
|
// parse type selector
|
786
785
|
else if (lex< re_type_selector >(false))
|
787
786
|
{
|
788
|
-
(
|
787
|
+
seq->append(SASS_MEMORY_NEW(Element_Selector, pstate, lexed));
|
789
788
|
}
|
790
789
|
// peek for abort conditions
|
791
790
|
else if (peek< spaces >()) break;
|
@@ -794,9 +793,9 @@ namespace Sass {
|
|
794
793
|
else if (peek_css < class_char < complex_selector_delims > >()) break;
|
795
794
|
// otherwise parse another simple selector
|
796
795
|
else {
|
797
|
-
|
796
|
+
Simple_Selector_Obj sel = parse_simple_selector();
|
798
797
|
if (!sel) return 0;
|
799
|
-
(
|
798
|
+
seq->append(&sel);
|
800
799
|
}
|
801
800
|
}
|
802
801
|
|
@@ -810,35 +809,35 @@ namespace Sass {
|
|
810
809
|
}
|
811
810
|
// EO parse_compound_selector
|
812
811
|
|
813
|
-
|
812
|
+
Simple_Selector_Obj Parser::parse_simple_selector()
|
814
813
|
{
|
815
814
|
lex < css_comments >(false);
|
816
815
|
if (lex< class_name >()) {
|
817
|
-
return SASS_MEMORY_NEW(
|
816
|
+
return SASS_MEMORY_NEW(Class_Selector, pstate, lexed);
|
818
817
|
}
|
819
818
|
else if (lex< id_name >()) {
|
820
|
-
return SASS_MEMORY_NEW(
|
819
|
+
return SASS_MEMORY_NEW(Id_Selector, pstate, lexed);
|
821
820
|
}
|
822
821
|
else if (lex< quoted_string >()) {
|
823
|
-
return SASS_MEMORY_NEW(
|
822
|
+
return SASS_MEMORY_NEW(Element_Selector, pstate, unquote(lexed));
|
824
823
|
}
|
825
824
|
else if (lex< alternatives < variable, number, static_reference_combinator > >()) {
|
826
|
-
return SASS_MEMORY_NEW(
|
825
|
+
return SASS_MEMORY_NEW(Element_Selector, pstate, lexed);
|
827
826
|
}
|
828
827
|
else if (peek< pseudo_not >()) {
|
829
|
-
return parse_negated_selector();
|
828
|
+
return &parse_negated_selector();
|
830
829
|
}
|
831
830
|
else if (peek< re_pseudo_selector >()) {
|
832
|
-
return parse_pseudo_selector();
|
831
|
+
return &parse_pseudo_selector();
|
833
832
|
}
|
834
833
|
else if (peek< exactly<':'> >()) {
|
835
|
-
return parse_pseudo_selector();
|
834
|
+
return &parse_pseudo_selector();
|
836
835
|
}
|
837
836
|
else if (lex < exactly<'['> >()) {
|
838
|
-
return parse_attribute_selector();
|
837
|
+
return &parse_attribute_selector();
|
839
838
|
}
|
840
839
|
else if (lex< placeholder >()) {
|
841
|
-
|
840
|
+
Placeholder_Selector_Ptr sel = SASS_MEMORY_NEW(Placeholder_Selector, pstate, lexed);
|
842
841
|
sel->media_block(last_media_block);
|
843
842
|
return sel;
|
844
843
|
}
|
@@ -846,22 +845,22 @@ namespace Sass {
|
|
846
845
|
return 0;
|
847
846
|
}
|
848
847
|
|
849
|
-
|
848
|
+
Wrapped_Selector_Obj Parser::parse_negated_selector()
|
850
849
|
{
|
851
850
|
lex< pseudo_not >();
|
852
851
|
std::string name(lexed);
|
853
852
|
ParserState nsource_position = pstate;
|
854
|
-
|
853
|
+
Selector_List_Obj negated = parse_selector_list(true);
|
855
854
|
if (!lex< exactly<')'> >()) {
|
856
855
|
error("negated selector is missing ')'", pstate);
|
857
856
|
}
|
858
857
|
name.erase(name.size() - 1);
|
859
|
-
return SASS_MEMORY_NEW(
|
858
|
+
return SASS_MEMORY_NEW(Wrapped_Selector, nsource_position, name, &negated);
|
860
859
|
}
|
861
860
|
|
862
861
|
// a pseudo selector often starts with one or two colons
|
863
862
|
// it can contain more selectors inside parentheses
|
864
|
-
|
863
|
+
Simple_Selector_Obj Parser::parse_pseudo_selector() {
|
865
864
|
if (lex< sequence<
|
866
865
|
optional < pseudo_prefix >,
|
867
866
|
// we keep the space within the name, strange enough
|
@@ -889,15 +888,15 @@ namespace Sass {
|
|
889
888
|
>()
|
890
889
|
) {
|
891
890
|
lex_css< alternatives < static_value, binomial > >();
|
892
|
-
|
891
|
+
String_Constant_Ptr expr = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
|
893
892
|
if (expr && lex_css< exactly<')'> >()) {
|
894
893
|
expr->can_compress_whitespace(true);
|
895
|
-
return SASS_MEMORY_NEW(
|
894
|
+
return SASS_MEMORY_NEW(Pseudo_Selector, p, name, expr);
|
896
895
|
}
|
897
896
|
}
|
898
|
-
else if (
|
897
|
+
else if (Selector_List_Obj wrapped = parse_selector_list(true)) {
|
899
898
|
if (wrapped && lex_css< exactly<')'> >()) {
|
900
|
-
return SASS_MEMORY_NEW(
|
899
|
+
return SASS_MEMORY_NEW(Wrapped_Selector, p, name, &wrapped);
|
901
900
|
}
|
902
901
|
}
|
903
902
|
|
@@ -905,7 +904,7 @@ namespace Sass {
|
|
905
904
|
// EO if pseudo selector
|
906
905
|
|
907
906
|
else if (lex < sequence< optional < pseudo_prefix >, identifier > >()) {
|
908
|
-
return SASS_MEMORY_NEW(
|
907
|
+
return SASS_MEMORY_NEW(Pseudo_Selector, pstate, lexed);
|
909
908
|
}
|
910
909
|
else if(lex < pseudo_prefix >()) {
|
911
910
|
css_error("Invalid CSS", " after ", ": expected pseudoclass or pseudoelement, was ");
|
@@ -917,52 +916,53 @@ namespace Sass {
|
|
917
916
|
return 0;
|
918
917
|
}
|
919
918
|
|
920
|
-
|
919
|
+
Attribute_Selector_Obj Parser::parse_attribute_selector()
|
921
920
|
{
|
922
921
|
ParserState p = pstate;
|
923
922
|
if (!lex_css< attribute_name >()) error("invalid attribute name in attribute selector", pstate);
|
924
923
|
std::string name(lexed);
|
925
|
-
if (lex_css< alternatives < exactly<']'>, exactly<'/'> > >()) return SASS_MEMORY_NEW(
|
924
|
+
if (lex_css< alternatives < exactly<']'>, exactly<'/'> > >()) return SASS_MEMORY_NEW(Attribute_Selector, p, name, "", 0);
|
926
925
|
if (!lex_css< alternatives< exact_match, class_match, dash_match,
|
927
926
|
prefix_match, suffix_match, substring_match > >()) {
|
928
927
|
error("invalid operator in attribute selector for " + name, pstate);
|
929
928
|
}
|
930
929
|
std::string matcher(lexed);
|
931
930
|
|
932
|
-
|
931
|
+
String_Obj value = 0;
|
933
932
|
if (lex_css< identifier >()) {
|
934
|
-
value = SASS_MEMORY_NEW(
|
933
|
+
value = SASS_MEMORY_NEW(String_Constant, p, lexed);
|
935
934
|
}
|
936
935
|
else if (lex_css< quoted_string >()) {
|
937
|
-
value = parse_interpolated_chunk(lexed, true); // needed!
|
936
|
+
value = &parse_interpolated_chunk(lexed, true); // needed!
|
938
937
|
}
|
939
938
|
else {
|
940
939
|
error("expected a string constant or identifier in attribute selector for " + name, pstate);
|
941
940
|
}
|
942
941
|
|
943
942
|
if (!lex_css< alternatives < exactly<']'>, exactly<'/'> > >()) error("unterminated attribute selector for " + name, pstate);
|
944
|
-
return SASS_MEMORY_NEW(
|
943
|
+
return SASS_MEMORY_NEW(Attribute_Selector, p, name, matcher, value);
|
945
944
|
}
|
946
945
|
|
947
946
|
/* parse block comment and add to block */
|
948
947
|
void Parser::parse_block_comments()
|
949
948
|
{
|
950
|
-
|
949
|
+
Block_Obj block = block_stack.back();
|
950
|
+
|
951
951
|
while (lex< block_comment >()) {
|
952
952
|
bool is_important = lexed.begin[2] == '!';
|
953
953
|
// flag on second param is to skip loosely over comments
|
954
|
-
|
955
|
-
(
|
954
|
+
String_Obj contents = parse_interpolated_chunk(lexed, true);
|
955
|
+
block->append(SASS_MEMORY_NEW(Comment, pstate, contents, is_important));
|
956
956
|
}
|
957
957
|
}
|
958
958
|
|
959
|
-
|
960
|
-
|
959
|
+
Declaration_Obj Parser::parse_declaration() {
|
960
|
+
String_Obj prop;
|
961
961
|
if (lex< sequence< optional< exactly<'*'> >, identifier_schema > >()) {
|
962
962
|
prop = parse_identifier_schema();
|
963
963
|
}
|
964
964
|
else if (lex< sequence< optional< exactly<'*'> >, identifier, zero_plus< block_comment > > >()) {
|
965
|
-
prop = SASS_MEMORY_NEW(
|
965
|
+
prop = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
|
966
966
|
}
|
967
967
|
else {
|
968
968
|
css_error("Invalid CSS", " after ", ": expected \"}\", was ");
|
@@ -974,29 +974,30 @@ namespace Sass {
|
|
974
974
|
if (peek_css< exactly<';'> >()) error("style declaration must contain a value", pstate);
|
975
975
|
if (peek_css< exactly<'{'> >()) is_indented = false; // don't indent if value is empty
|
976
976
|
if (peek_css< static_value >()) {
|
977
|
-
return SASS_MEMORY_NEW(
|
977
|
+
return SASS_MEMORY_NEW(Declaration, prop->pstate(), prop, &parse_static_value()/*, lex<kwd_important>()*/);
|
978
978
|
}
|
979
979
|
else {
|
980
|
-
|
980
|
+
Expression_Obj value;
|
981
981
|
Lookahead lookahead = lookahead_for_value(position);
|
982
982
|
if (lookahead.found) {
|
983
983
|
if (lookahead.has_interpolants) {
|
984
|
-
value = parse_value_schema(lookahead.found);
|
984
|
+
value = &parse_value_schema(lookahead.found);
|
985
985
|
} else {
|
986
|
-
value = parse_list(DELAYED);
|
986
|
+
value = &parse_list(DELAYED);
|
987
987
|
}
|
988
988
|
}
|
989
989
|
else {
|
990
|
-
value = parse_list(DELAYED);
|
991
|
-
if (
|
990
|
+
value = &parse_list(DELAYED);
|
991
|
+
if (List_Ptr list = SASS_MEMORY_CAST(List, value)) {
|
992
992
|
if (list->length() == 0 && !peek< exactly <'{'> >()) {
|
993
993
|
css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
|
994
994
|
}
|
995
995
|
}
|
996
996
|
}
|
997
997
|
lex < css_comments >(false);
|
998
|
-
|
998
|
+
Declaration_Obj decl = SASS_MEMORY_NEW(Declaration, prop->pstate(), prop, value/*, lex<kwd_important>()*/);
|
999
999
|
decl->is_indented(is_indented);
|
1000
|
+
decl->update_pstate(pstate);
|
1000
1001
|
return decl;
|
1001
1002
|
}
|
1002
1003
|
}
|
@@ -1017,28 +1018,19 @@ namespace Sass {
|
|
1017
1018
|
return positive;
|
1018
1019
|
}
|
1019
1020
|
|
1020
|
-
|
1021
|
+
Expression_Obj Parser::parse_map()
|
1021
1022
|
{
|
1022
|
-
|
1023
|
-
|
1024
|
-
if (String_Quoted* str = dynamic_cast<String_Quoted*>(key)) {
|
1025
|
-
if (!str->quote_mark() && !str->is_delayed()) {
|
1026
|
-
if (const Color* col = name_to_color(str->value())) {
|
1027
|
-
Color* c = SASS_MEMORY_NEW(ctx.mem, Color, *col);
|
1028
|
-
c->pstate(str->pstate());
|
1029
|
-
c->disp(str->value());
|
1030
|
-
key = c;
|
1031
|
-
}
|
1032
|
-
}
|
1033
|
-
}
|
1023
|
+
Expression_Obj key = parse_list();
|
1024
|
+
List_Obj map = SASS_MEMORY_NEW(List, pstate, 0, SASS_HASH);
|
1034
1025
|
|
1035
1026
|
// it's not a map so return the lexed value as a list value
|
1036
1027
|
if (!lex_css< exactly<':'> >())
|
1037
1028
|
{ return key; }
|
1038
1029
|
|
1039
|
-
|
1030
|
+
Expression_Obj value = parse_space_list();
|
1040
1031
|
|
1041
|
-
(
|
1032
|
+
map->append(key);
|
1033
|
+
map->append(value);
|
1042
1034
|
|
1043
1035
|
while (lex_css< exactly<','> >())
|
1044
1036
|
{
|
@@ -1046,43 +1038,34 @@ namespace Sass {
|
|
1046
1038
|
if (peek_css< exactly<')'> >(position))
|
1047
1039
|
{ break; }
|
1048
1040
|
|
1049
|
-
|
1050
|
-
if (String_Quoted* str = dynamic_cast<String_Quoted*>(key)) {
|
1051
|
-
if (!str->quote_mark() && !str->is_delayed()) {
|
1052
|
-
if (const Color* col = name_to_color(str->value())) {
|
1053
|
-
Color* c = SASS_MEMORY_NEW(ctx.mem, Color, *col);
|
1054
|
-
c->pstate(str->pstate());
|
1055
|
-
c->disp(str->value());
|
1056
|
-
key = c;
|
1057
|
-
}
|
1058
|
-
}
|
1059
|
-
}
|
1041
|
+
Expression_Obj key = parse_space_list();
|
1060
1042
|
|
1061
1043
|
if (!(lex< exactly<':'> >()))
|
1062
1044
|
{ css_error("Invalid CSS", " after ", ": expected \":\", was "); }
|
1063
1045
|
|
1064
|
-
|
1046
|
+
Expression_Obj value = parse_space_list();
|
1065
1047
|
|
1066
|
-
(
|
1048
|
+
map->append(key);
|
1049
|
+
map->append(value);
|
1067
1050
|
}
|
1068
1051
|
|
1069
1052
|
ParserState ps = map->pstate();
|
1070
1053
|
ps.offset = pstate - ps + pstate.offset;
|
1071
1054
|
map->pstate(ps);
|
1072
1055
|
|
1073
|
-
return map;
|
1056
|
+
return ↦
|
1074
1057
|
}
|
1075
1058
|
|
1076
1059
|
// parse list returns either a space separated list,
|
1077
1060
|
// a comma separated list or any bare expression found.
|
1078
1061
|
// so to speak: we unwrap items from lists if possible here!
|
1079
|
-
|
1062
|
+
Expression_Obj Parser::parse_list(bool delayed)
|
1080
1063
|
{
|
1081
1064
|
return parse_comma_list(delayed);
|
1082
1065
|
}
|
1083
1066
|
|
1084
1067
|
// will return singletons unwrapped
|
1085
|
-
|
1068
|
+
Expression_Obj Parser::parse_comma_list(bool delayed)
|
1086
1069
|
{
|
1087
1070
|
// check if we have an empty list
|
1088
1071
|
// return the empty list as such
|
@@ -1100,11 +1083,11 @@ namespace Sass {
|
|
1100
1083
|
> >(position))
|
1101
1084
|
{
|
1102
1085
|
// return an empty list (nothing to delay)
|
1103
|
-
return SASS_MEMORY_NEW(
|
1086
|
+
return SASS_MEMORY_NEW(List, pstate, 0);
|
1104
1087
|
}
|
1105
1088
|
|
1106
1089
|
// now try to parse a space list
|
1107
|
-
|
1090
|
+
Expression_Obj list = parse_space_list();
|
1108
1091
|
// if it's a singleton, return it (don't wrap it)
|
1109
1092
|
if (!peek_css< exactly<','> >(position)) {
|
1110
1093
|
// set_delay doesn't apply to list children
|
@@ -1114,9 +1097,9 @@ namespace Sass {
|
|
1114
1097
|
}
|
1115
1098
|
|
1116
1099
|
// if we got so far, we actually do have a comma list
|
1117
|
-
|
1100
|
+
List_Obj comma_list = SASS_MEMORY_NEW(List, pstate, 2, SASS_COMMA);
|
1118
1101
|
// wrap the first expression
|
1119
|
-
(
|
1102
|
+
comma_list->append(list);
|
1120
1103
|
|
1121
1104
|
while (lex_css< exactly<','> >())
|
1122
1105
|
{
|
@@ -1134,17 +1117,17 @@ namespace Sass {
|
|
1134
1117
|
> >(position)
|
1135
1118
|
) { break; }
|
1136
1119
|
// otherwise add another expression
|
1137
|
-
(
|
1120
|
+
comma_list->append(parse_space_list());
|
1138
1121
|
}
|
1139
1122
|
// return the list
|
1140
|
-
return comma_list;
|
1123
|
+
return &comma_list;
|
1141
1124
|
}
|
1142
1125
|
// EO parse_comma_list
|
1143
1126
|
|
1144
1127
|
// will return singletons unwrapped
|
1145
|
-
|
1128
|
+
Expression_Obj Parser::parse_space_list()
|
1146
1129
|
{
|
1147
|
-
|
1130
|
+
Expression_Obj disj1 = parse_disjunction();
|
1148
1131
|
// if it's a singleton, return it (don't wrap it)
|
1149
1132
|
if (peek_css< alternatives <
|
1150
1133
|
// exactly<'!'>,
|
@@ -1161,8 +1144,8 @@ namespace Sass {
|
|
1161
1144
|
> >(position)
|
1162
1145
|
) { return disj1; }
|
1163
1146
|
|
1164
|
-
|
1165
|
-
(
|
1147
|
+
List_Obj space_list = SASS_MEMORY_NEW(List, pstate, 2, SASS_SPACE);
|
1148
|
+
space_list->append(disj1);
|
1166
1149
|
|
1167
1150
|
while (!(peek_css< alternatives <
|
1168
1151
|
// exactly<'!'>,
|
@@ -1179,28 +1162,28 @@ namespace Sass {
|
|
1179
1162
|
> >(position)) && peek_css< optional_css_whitespace >() != end
|
1180
1163
|
) {
|
1181
1164
|
// the space is parsed implicitly?
|
1182
|
-
(
|
1165
|
+
space_list->append(parse_disjunction());
|
1183
1166
|
}
|
1184
1167
|
// return the list
|
1185
|
-
return space_list;
|
1168
|
+
return &space_list;
|
1186
1169
|
}
|
1187
1170
|
// EO parse_space_list
|
1188
1171
|
|
1189
1172
|
// parse logical OR operation
|
1190
|
-
|
1173
|
+
Expression_Obj Parser::parse_disjunction()
|
1191
1174
|
{
|
1192
1175
|
advanceToNextToken();
|
1193
1176
|
ParserState state(pstate);
|
1194
1177
|
// parse the left hand side conjunction
|
1195
|
-
|
1178
|
+
Expression_Obj conj = parse_conjunction();
|
1196
1179
|
// parse multiple right hand sides
|
1197
|
-
std::vector<
|
1180
|
+
std::vector<Expression_Obj> operands;
|
1198
1181
|
while (lex_css< kwd_or >())
|
1199
1182
|
operands.push_back(parse_conjunction());
|
1200
1183
|
// if it's a singleton, return it directly
|
1201
1184
|
if (operands.size() == 0) return conj;
|
1202
1185
|
// fold all operands into one binary expression
|
1203
|
-
|
1186
|
+
Expression_Obj ex = fold_operands(conj, operands, { Sass_OP::OR });
|
1204
1187
|
state.offset = pstate - state + pstate.offset;
|
1205
1188
|
ex->pstate(state);
|
1206
1189
|
return ex;
|
@@ -1208,20 +1191,21 @@ namespace Sass {
|
|
1208
1191
|
// EO parse_disjunction
|
1209
1192
|
|
1210
1193
|
// parse logical AND operation
|
1211
|
-
|
1194
|
+
Expression_Obj Parser::parse_conjunction()
|
1212
1195
|
{
|
1213
1196
|
advanceToNextToken();
|
1214
1197
|
ParserState state(pstate);
|
1215
1198
|
// parse the left hand side relation
|
1216
|
-
|
1199
|
+
Expression_Obj rel = parse_relation();
|
1217
1200
|
// parse multiple right hand sides
|
1218
|
-
std::vector<
|
1219
|
-
while (lex_css< kwd_and >())
|
1220
|
-
operands.push_back(parse_relation());
|
1201
|
+
std::vector<Expression_Obj> operands;
|
1202
|
+
while (lex_css< kwd_and >()) {
|
1203
|
+
operands.push_back(&parse_relation());
|
1204
|
+
}
|
1221
1205
|
// if it's a singleton, return it directly
|
1222
1206
|
if (operands.size() == 0) return rel;
|
1223
1207
|
// fold all operands into one binary expression
|
1224
|
-
|
1208
|
+
Expression_Obj ex = fold_operands(rel, operands, { Sass_OP::AND });
|
1225
1209
|
state.offset = pstate - state + pstate.offset;
|
1226
1210
|
ex->pstate(state);
|
1227
1211
|
return ex;
|
@@ -1229,13 +1213,13 @@ namespace Sass {
|
|
1229
1213
|
// EO parse_conjunction
|
1230
1214
|
|
1231
1215
|
// parse comparison operations
|
1232
|
-
|
1216
|
+
Expression_Obj Parser::parse_relation()
|
1233
1217
|
{
|
1234
1218
|
advanceToNextToken();
|
1235
1219
|
ParserState state(pstate);
|
1236
1220
|
// parse the left hand side expression
|
1237
|
-
|
1238
|
-
std::vector<
|
1221
|
+
Expression_Obj lhs = parse_expression();
|
1222
|
+
std::vector<Expression_Obj> operands;
|
1239
1223
|
std::vector<Operand> operators;
|
1240
1224
|
// if it's a singleton, return it (don't wrap it)
|
1241
1225
|
while (peek< alternatives <
|
@@ -1262,7 +1246,7 @@ namespace Sass {
|
|
1262
1246
|
// is directly adjacent to expression?
|
1263
1247
|
bool right_ws = peek < css_comments >() != NULL;
|
1264
1248
|
operators.push_back({ op, left_ws, right_ws });
|
1265
|
-
operands.push_back(parse_expression());
|
1249
|
+
operands.push_back(&parse_expression());
|
1266
1250
|
left_ws = peek < css_comments >() != NULL;
|
1267
1251
|
}
|
1268
1252
|
// we are called recursively for list, so we first
|
@@ -1270,7 +1254,7 @@ namespace Sass {
|
|
1270
1254
|
// correctly set to zero. After folding we also unwrap
|
1271
1255
|
// single nested items. So we cannot set delay on the
|
1272
1256
|
// returned result here, as we have lost nestings ...
|
1273
|
-
|
1257
|
+
Expression_Obj ex = fold_operands(lhs, operands, operators);
|
1274
1258
|
state.offset = pstate - state + pstate.offset;
|
1275
1259
|
ex->pstate(state);
|
1276
1260
|
return ex;
|
@@ -1282,14 +1266,14 @@ namespace Sass {
|
|
1282
1266
|
// called from parse_for_directive
|
1283
1267
|
// called from parse_media_expression
|
1284
1268
|
// parse addition and subtraction operations
|
1285
|
-
|
1269
|
+
Expression_Obj Parser::parse_expression()
|
1286
1270
|
{
|
1287
1271
|
advanceToNextToken();
|
1288
1272
|
ParserState state(pstate);
|
1289
1273
|
// parses multiple add and subtract operations
|
1290
1274
|
// NOTE: make sure that identifiers starting with
|
1291
1275
|
// NOTE: dashes do NOT count as subtract operation
|
1292
|
-
|
1276
|
+
Expression_Obj lhs = parse_operators();
|
1293
1277
|
// if it's a singleton, return it (don't wrap it)
|
1294
1278
|
if (!(peek_css< exactly<'+'> >(position) ||
|
1295
1279
|
// condition is a bit misterious, but some combinations should not be counted as operations
|
@@ -1298,7 +1282,7 @@ namespace Sass {
|
|
1298
1282
|
peek< sequence < zero_plus < exactly <'-' > >, identifier > >(position))
|
1299
1283
|
{ return lhs; }
|
1300
1284
|
|
1301
|
-
std::vector<
|
1285
|
+
std::vector<Expression_Obj> operands;
|
1302
1286
|
std::vector<Operand> operators;
|
1303
1287
|
bool left_ws = peek < css_comments >() != NULL;
|
1304
1288
|
while (
|
@@ -1313,25 +1297,25 @@ namespace Sass {
|
|
1313
1297
|
|
1314
1298
|
bool right_ws = peek < css_comments >() != NULL;
|
1315
1299
|
operators.push_back({ lexed.to_string() == "+" ? Sass_OP::ADD : Sass_OP::SUB, left_ws, right_ws });
|
1316
|
-
operands.push_back(parse_operators());
|
1300
|
+
operands.push_back(&parse_operators());
|
1317
1301
|
left_ws = peek < css_comments >() != NULL;
|
1318
1302
|
}
|
1319
1303
|
|
1320
1304
|
if (operands.size() == 0) return lhs;
|
1321
|
-
|
1305
|
+
Expression_Obj ex = fold_operands(lhs, operands, operators);
|
1322
1306
|
state.offset = pstate - state + pstate.offset;
|
1323
1307
|
ex->pstate(state);
|
1324
1308
|
return ex;
|
1325
1309
|
}
|
1326
1310
|
|
1327
1311
|
// parse addition and subtraction operations
|
1328
|
-
|
1312
|
+
Expression_Obj Parser::parse_operators()
|
1329
1313
|
{
|
1330
1314
|
advanceToNextToken();
|
1331
1315
|
ParserState state(pstate);
|
1332
|
-
|
1316
|
+
Expression_Obj factor = parse_factor();
|
1333
1317
|
// if it's a singleton, return it (don't wrap it)
|
1334
|
-
std::vector<
|
1318
|
+
std::vector<Expression_Obj> operands; // factors
|
1335
1319
|
std::vector<Operand> operators; // ops
|
1336
1320
|
// lex operations to apply to lhs
|
1337
1321
|
const char* left_ws = peek < css_comments >();
|
@@ -1347,7 +1331,7 @@ namespace Sass {
|
|
1347
1331
|
left_ws = peek < css_comments >();
|
1348
1332
|
}
|
1349
1333
|
// operands and operators to binary expression
|
1350
|
-
|
1334
|
+
Expression_Obj ex = fold_operands(factor, operands, operators);
|
1351
1335
|
state.offset = pstate - state + pstate.offset;
|
1352
1336
|
ex->pstate(state);
|
1353
1337
|
return ex;
|
@@ -1357,67 +1341,67 @@ namespace Sass {
|
|
1357
1341
|
|
1358
1342
|
// called from parse_operators
|
1359
1343
|
// called from parse_value_schema
|
1360
|
-
|
1344
|
+
Expression_Obj Parser::parse_factor()
|
1361
1345
|
{
|
1362
1346
|
lex < css_comments >(false);
|
1363
1347
|
if (lex_css< exactly<'('> >()) {
|
1364
1348
|
// parse_map may return a list
|
1365
|
-
|
1349
|
+
Expression_Obj value = parse_map();
|
1366
1350
|
// lex the expected closing parenthesis
|
1367
1351
|
if (!lex_css< exactly<')'> >()) error("unclosed parenthesis", pstate);
|
1368
1352
|
// expression can be evaluated
|
1369
|
-
return value;
|
1353
|
+
return &value;
|
1370
1354
|
}
|
1371
1355
|
// string may be interpolated
|
1372
1356
|
// if (lex< quoted_string >()) {
|
1373
|
-
// return parse_string();
|
1357
|
+
// return &parse_string();
|
1374
1358
|
// }
|
1375
1359
|
else if (peek< ie_property >()) {
|
1376
|
-
return parse_ie_property();
|
1360
|
+
return &parse_ie_property();
|
1377
1361
|
}
|
1378
1362
|
else if (peek< ie_keyword_arg >()) {
|
1379
|
-
return parse_ie_keyword_arg();
|
1363
|
+
return &parse_ie_keyword_arg();
|
1380
1364
|
}
|
1381
1365
|
else if (peek< sequence < calc_fn_call, exactly <'('> > >()) {
|
1382
|
-
return parse_calc_function();
|
1366
|
+
return &parse_calc_function();
|
1383
1367
|
}
|
1384
1368
|
else if (lex < functional_schema >()) {
|
1385
|
-
return parse_function_call_schema();
|
1369
|
+
return &parse_function_call_schema();
|
1386
1370
|
}
|
1387
1371
|
else if (lex< identifier_schema >()) {
|
1388
|
-
|
1389
|
-
if (
|
1372
|
+
String_Obj string = parse_identifier_schema();
|
1373
|
+
if (String_Schema_Ptr schema = SASS_MEMORY_CAST(String_Schema, string)) {
|
1390
1374
|
if (lex < exactly < '(' > >()) {
|
1391
|
-
|
1375
|
+
schema->append(&parse_list());
|
1392
1376
|
lex < exactly < ')' > >();
|
1393
1377
|
}
|
1394
1378
|
}
|
1395
|
-
return string;
|
1379
|
+
return &string;
|
1396
1380
|
}
|
1397
1381
|
else if (peek< sequence< uri_prefix, W, real_uri_value > >()) {
|
1398
|
-
return parse_url_function_string();
|
1382
|
+
return &parse_url_function_string();
|
1399
1383
|
}
|
1400
1384
|
else if (peek< re_functional >()) {
|
1401
|
-
return parse_function_call();
|
1385
|
+
return &parse_function_call();
|
1402
1386
|
}
|
1403
1387
|
else if (lex< exactly<'+'> >()) {
|
1404
|
-
|
1388
|
+
Unary_Expression_Ptr ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::PLUS, &parse_factor());
|
1405
1389
|
if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
|
1406
1390
|
return ex;
|
1407
1391
|
}
|
1408
1392
|
else if (lex< exactly<'-'> >()) {
|
1409
|
-
|
1393
|
+
Unary_Expression_Ptr ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::MINUS, &parse_factor());
|
1410
1394
|
if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
|
1411
1395
|
return ex;
|
1412
1396
|
}
|
1413
1397
|
else if (lex< sequence< kwd_not > >()) {
|
1414
|
-
|
1398
|
+
Unary_Expression_Ptr ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::NOT, &parse_factor());
|
1415
1399
|
if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
|
1416
1400
|
return ex;
|
1417
1401
|
}
|
1418
1402
|
else if (peek < sequence < one_plus < alternatives < css_whitespace, exactly<'-'>, exactly<'+'> > >, number > >()) {
|
1419
|
-
if (parse_number_prefix()) return parse_value(); // prefix is positive
|
1420
|
-
|
1403
|
+
if (parse_number_prefix()) return &parse_value(); // prefix is positive
|
1404
|
+
Unary_Expression_Ptr ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::MINUS, &parse_value());
|
1421
1405
|
if (ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
|
1422
1406
|
return ex;
|
1423
1407
|
}
|
@@ -1427,74 +1411,74 @@ namespace Sass {
|
|
1427
1411
|
}
|
1428
1412
|
|
1429
1413
|
// parse one value for a list
|
1430
|
-
|
1414
|
+
Expression_Obj Parser::parse_value()
|
1431
1415
|
{
|
1432
1416
|
lex< css_comments >(false);
|
1433
1417
|
if (lex< ampersand >())
|
1434
1418
|
{
|
1435
|
-
return SASS_MEMORY_NEW(
|
1419
|
+
return SASS_MEMORY_NEW(Parent_Selector, pstate); }
|
1436
1420
|
|
1437
1421
|
if (lex< kwd_important >())
|
1438
|
-
{ return SASS_MEMORY_NEW(
|
1422
|
+
{ return SASS_MEMORY_NEW(String_Constant, pstate, "!important"); }
|
1439
1423
|
|
1440
1424
|
// parse `10%4px` into separated items and not a schema
|
1441
1425
|
if (lex< sequence < percentage, lookahead < number > > >())
|
1442
|
-
{ return SASS_MEMORY_NEW(
|
1426
|
+
{ return SASS_MEMORY_NEW(Textual, pstate, Textual::PERCENTAGE, lexed); }
|
1443
1427
|
|
1444
1428
|
if (lex< sequence < number, lookahead< sequence < op, number > > > >())
|
1445
|
-
{ return SASS_MEMORY_NEW(
|
1429
|
+
{ return SASS_MEMORY_NEW(Textual, pstate, Textual::NUMBER, lexed); }
|
1446
1430
|
|
1447
1431
|
// string may be interpolated
|
1448
1432
|
if (lex< sequence < quoted_string, lookahead < exactly <'-'> > > >())
|
1449
|
-
{ return parse_string(); }
|
1433
|
+
{ return &parse_string(); }
|
1450
1434
|
|
1451
1435
|
if (const char* stop = peek< value_schema >())
|
1452
|
-
{ return parse_value_schema(stop); }
|
1436
|
+
{ return &parse_value_schema(stop); }
|
1453
1437
|
|
1454
1438
|
// string may be interpolated
|
1455
1439
|
if (lex< quoted_string >())
|
1456
|
-
{ return parse_string(); }
|
1440
|
+
{ return &parse_string(); }
|
1457
1441
|
|
1458
1442
|
if (lex< kwd_true >())
|
1459
|
-
{ return SASS_MEMORY_NEW(
|
1443
|
+
{ return SASS_MEMORY_NEW(Boolean, pstate, true); }
|
1460
1444
|
|
1461
1445
|
if (lex< kwd_false >())
|
1462
|
-
{ return SASS_MEMORY_NEW(
|
1446
|
+
{ return SASS_MEMORY_NEW(Boolean, pstate, false); }
|
1463
1447
|
|
1464
1448
|
if (lex< kwd_null >())
|
1465
|
-
{ return SASS_MEMORY_NEW(
|
1449
|
+
{ return SASS_MEMORY_NEW(Null, pstate); }
|
1466
1450
|
|
1467
1451
|
if (lex< identifier >()) {
|
1468
|
-
return SASS_MEMORY_NEW(
|
1452
|
+
return SASS_MEMORY_NEW(String_Constant, pstate, lexed);
|
1469
1453
|
}
|
1470
1454
|
|
1471
1455
|
if (lex< percentage >())
|
1472
|
-
{ return SASS_MEMORY_NEW(
|
1456
|
+
{ return SASS_MEMORY_NEW(Textual, pstate, Textual::PERCENTAGE, lexed); }
|
1473
1457
|
|
1474
1458
|
// match hex number first because 0x000 looks like a number followed by an identifier
|
1475
1459
|
if (lex< sequence < alternatives< hex, hex0 >, negate < exactly<'-'> > > >())
|
1476
|
-
{ return SASS_MEMORY_NEW(
|
1460
|
+
{ return SASS_MEMORY_NEW(Textual, pstate, Textual::HEX, lexed); }
|
1477
1461
|
|
1478
1462
|
if (lex< sequence < exactly <'#'>, identifier > >())
|
1479
|
-
{ return SASS_MEMORY_NEW(
|
1463
|
+
{ return SASS_MEMORY_NEW(String_Quoted, pstate, lexed); }
|
1480
1464
|
|
1481
1465
|
// also handle the 10em- foo special case
|
1482
1466
|
// alternatives < exactly < '.' >, .. > -- `1.5em-.75em` is split into a list, not a binary expression
|
1483
1467
|
if (lex< sequence< dimension, optional< sequence< exactly<'-'>, lookahead< alternatives < space > > > > > >())
|
1484
|
-
{ return SASS_MEMORY_NEW(
|
1468
|
+
{ return SASS_MEMORY_NEW(Textual, pstate, Textual::DIMENSION, lexed); }
|
1485
1469
|
|
1486
1470
|
if (lex< sequence< static_component, one_plus< strict_identifier > > >())
|
1487
|
-
{ return SASS_MEMORY_NEW(
|
1471
|
+
{ return SASS_MEMORY_NEW(String_Constant, pstate, lexed); }
|
1488
1472
|
|
1489
1473
|
if (lex< number >())
|
1490
|
-
{ return SASS_MEMORY_NEW(
|
1474
|
+
{ return SASS_MEMORY_NEW(Textual, pstate, Textual::NUMBER, lexed); }
|
1491
1475
|
|
1492
1476
|
if (lex< variable >())
|
1493
|
-
{ return SASS_MEMORY_NEW(
|
1477
|
+
{ return SASS_MEMORY_NEW(Variable, pstate, Util::normalize_underscores(lexed)); }
|
1494
1478
|
|
1495
1479
|
// Special case handling for `%` proceeding an interpolant.
|
1496
1480
|
if (lex< sequence< exactly<'%'>, optional< percentage > > >())
|
1497
|
-
{ return SASS_MEMORY_NEW(
|
1481
|
+
{ return SASS_MEMORY_NEW(String_Constant, pstate, lexed); }
|
1498
1482
|
|
1499
1483
|
css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
|
1500
1484
|
|
@@ -1504,7 +1488,7 @@ namespace Sass {
|
|
1504
1488
|
|
1505
1489
|
// this parses interpolation inside other strings
|
1506
1490
|
// means the result should later be quoted again
|
1507
|
-
|
1491
|
+
String_Obj Parser::parse_interpolated_chunk(Token chunk, bool constant)
|
1508
1492
|
{
|
1509
1493
|
const char* i = chunk.begin;
|
1510
1494
|
// see if there any interpolants
|
@@ -1512,12 +1496,12 @@ namespace Sass {
|
|
1512
1496
|
find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, chunk.end);
|
1513
1497
|
|
1514
1498
|
if (!p) {
|
1515
|
-
|
1499
|
+
String_Quoted_Ptr str_quoted = SASS_MEMORY_NEW(String_Quoted, pstate, std::string(i, chunk.end));
|
1516
1500
|
if (!constant && str_quoted->quote_mark()) str_quoted->quote_mark('*');
|
1517
1501
|
return str_quoted;
|
1518
1502
|
}
|
1519
1503
|
|
1520
|
-
|
1504
|
+
String_Schema_Ptr schema = SASS_MEMORY_NEW(String_Schema, pstate);
|
1521
1505
|
schema->is_interpolant(true);
|
1522
1506
|
while (i < chunk.end) {
|
1523
1507
|
p = constant ? find_first_in_interval< exactly<hash_lbrace> >(i, chunk.end) :
|
@@ -1525,7 +1509,7 @@ namespace Sass {
|
|
1525
1509
|
if (p) {
|
1526
1510
|
if (i < p) {
|
1527
1511
|
// accumulate the preceding segment if it's nonempty
|
1528
|
-
(
|
1512
|
+
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(i, p)));
|
1529
1513
|
}
|
1530
1514
|
// we need to skip anything inside strings
|
1531
1515
|
// create a new target in parser/prelexer
|
@@ -1535,9 +1519,9 @@ namespace Sass {
|
|
1535
1519
|
const char* j = skip_over_scopes< exactly<hash_lbrace>, exactly<rbrace> >(p + 2, chunk.end); // find the closing brace
|
1536
1520
|
if (j) { --j;
|
1537
1521
|
// parse the interpolant and accumulate it
|
1538
|
-
|
1522
|
+
Expression_Obj interp_node = Parser::from_token(Token(p+2, j), ctx, pstate, source).parse_list();
|
1539
1523
|
interp_node->is_interpolant(true);
|
1540
|
-
(
|
1524
|
+
schema->append(&interp_node);
|
1541
1525
|
i = j;
|
1542
1526
|
}
|
1543
1527
|
else {
|
@@ -1547,7 +1531,7 @@ namespace Sass {
|
|
1547
1531
|
}
|
1548
1532
|
else { // no interpolants left; add the last segment if nonempty
|
1549
1533
|
// check if we need quotes here (was not sure after merge)
|
1550
|
-
if (i < chunk.end) (
|
1534
|
+
if (i < chunk.end) schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(i, chunk.end)));
|
1551
1535
|
break;
|
1552
1536
|
}
|
1553
1537
|
++ i;
|
@@ -1556,15 +1540,7 @@ namespace Sass {
|
|
1556
1540
|
return schema;
|
1557
1541
|
}
|
1558
1542
|
|
1559
|
-
|
1560
|
-
{
|
1561
|
-
if (peek< sequence< number, optional_spaces, exactly<'/'>, optional_spaces, number > >()) {
|
1562
|
-
return parse_static_value();
|
1563
|
-
}
|
1564
|
-
return 0;
|
1565
|
-
}
|
1566
|
-
|
1567
|
-
String_Constant* Parser::parse_static_value()
|
1543
|
+
String_Constant_Obj Parser::parse_static_value()
|
1568
1544
|
{
|
1569
1545
|
lex< static_value >();
|
1570
1546
|
Token str(lexed);
|
@@ -1574,16 +1550,16 @@ namespace Sass {
|
|
1574
1550
|
--str.end;
|
1575
1551
|
--position;
|
1576
1552
|
|
1577
|
-
|
1553
|
+
String_Constant_Ptr str_node = SASS_MEMORY_NEW(String_Constant, pstate, str.time_wspace());
|
1578
1554
|
return str_node;
|
1579
1555
|
}
|
1580
1556
|
|
1581
|
-
|
1557
|
+
String_Obj Parser::parse_string()
|
1582
1558
|
{
|
1583
1559
|
return parse_interpolated_chunk(Token(lexed));
|
1584
1560
|
}
|
1585
1561
|
|
1586
|
-
|
1562
|
+
String_Obj Parser::parse_ie_property()
|
1587
1563
|
{
|
1588
1564
|
lex< ie_property >();
|
1589
1565
|
Token str(lexed);
|
@@ -1591,15 +1567,15 @@ namespace Sass {
|
|
1591
1567
|
// see if there any interpolants
|
1592
1568
|
const char* p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(str.begin, str.end);
|
1593
1569
|
if (!p) {
|
1594
|
-
return SASS_MEMORY_NEW(
|
1570
|
+
return SASS_MEMORY_NEW(String_Quoted, pstate, std::string(str.begin, str.end));
|
1595
1571
|
}
|
1596
1572
|
|
1597
|
-
|
1573
|
+
String_Schema_Ptr schema = SASS_MEMORY_NEW(String_Schema, pstate);
|
1598
1574
|
while (i < str.end) {
|
1599
1575
|
p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, str.end);
|
1600
1576
|
if (p) {
|
1601
1577
|
if (i < p) {
|
1602
|
-
(
|
1578
|
+
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(i, p))); // accumulate the preceding segment if it's nonempty
|
1603
1579
|
}
|
1604
1580
|
if (peek < sequence < optional_spaces, exactly<rbrace> > >(p+2)) { position = p+2;
|
1605
1581
|
css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
|
@@ -1607,9 +1583,9 @@ namespace Sass {
|
|
1607
1583
|
const char* j = skip_over_scopes< exactly<hash_lbrace>, exactly<rbrace> >(p+2, str.end); // find the closing brace
|
1608
1584
|
if (j) {
|
1609
1585
|
// parse the interpolant and accumulate it
|
1610
|
-
|
1586
|
+
Expression_Obj interp_node = Parser::from_token(Token(p+2, j), ctx, pstate, source).parse_list();
|
1611
1587
|
interp_node->is_interpolant(true);
|
1612
|
-
(
|
1588
|
+
schema->append(&interp_node);
|
1613
1589
|
i = j;
|
1614
1590
|
}
|
1615
1591
|
else {
|
@@ -1619,7 +1595,7 @@ namespace Sass {
|
|
1619
1595
|
}
|
1620
1596
|
else { // no interpolants left; add the last segment if nonempty
|
1621
1597
|
if (i < str.end) {
|
1622
|
-
(
|
1598
|
+
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(i, str.end)));
|
1623
1599
|
}
|
1624
1600
|
break;
|
1625
1601
|
}
|
@@ -1627,27 +1603,27 @@ namespace Sass {
|
|
1627
1603
|
return schema;
|
1628
1604
|
}
|
1629
1605
|
|
1630
|
-
|
1606
|
+
String_Obj Parser::parse_ie_keyword_arg()
|
1631
1607
|
{
|
1632
|
-
|
1608
|
+
String_Schema_Ptr kwd_arg = SASS_MEMORY_NEW(String_Schema, pstate, 3);
|
1633
1609
|
if (lex< variable >()) {
|
1634
|
-
|
1610
|
+
kwd_arg->append(SASS_MEMORY_NEW(Variable, pstate, Util::normalize_underscores(lexed)));
|
1635
1611
|
} else {
|
1636
1612
|
lex< alternatives< identifier_schema, identifier > >();
|
1637
|
-
|
1613
|
+
kwd_arg->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
|
1638
1614
|
}
|
1639
1615
|
lex< exactly<'='> >();
|
1640
|
-
|
1641
|
-
if (peek< variable >())
|
1642
|
-
else if (lex< number >())
|
1643
|
-
else if (peek < ie_keyword_arg_value >()) {
|
1616
|
+
kwd_arg->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
|
1617
|
+
if (peek< variable >()) kwd_arg->append(&parse_list());
|
1618
|
+
else if (lex< number >()) kwd_arg->append(SASS_MEMORY_NEW(Textual, pstate, Textual::NUMBER, Util::normalize_decimals(lexed)));
|
1619
|
+
else if (peek < ie_keyword_arg_value >()) { kwd_arg->append(&parse_list()); }
|
1644
1620
|
return kwd_arg;
|
1645
1621
|
}
|
1646
1622
|
|
1647
|
-
|
1623
|
+
String_Schema_Obj Parser::parse_value_schema(const char* stop)
|
1648
1624
|
{
|
1649
1625
|
// initialize the string schema object to add tokens
|
1650
|
-
|
1626
|
+
String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
|
1651
1627
|
|
1652
1628
|
if (peek<exactly<'}'>>()) {
|
1653
1629
|
css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
|
@@ -1665,10 +1641,10 @@ namespace Sass {
|
|
1665
1641
|
}
|
1666
1642
|
if (need_space) {
|
1667
1643
|
need_space = false;
|
1668
|
-
// (
|
1644
|
+
// schema->append(SASS_MEMORY_NEW(String_Constant, pstate, " "));
|
1669
1645
|
}
|
1670
1646
|
if ((e = peek< re_functional >()) && e < stop) {
|
1671
|
-
(
|
1647
|
+
schema->append(&parse_function_call());
|
1672
1648
|
}
|
1673
1649
|
// lex an interpolant /#{...}/
|
1674
1650
|
else if (lex< exactly < hash_lbrace > >()) {
|
@@ -1676,35 +1652,36 @@ namespace Sass {
|
|
1676
1652
|
if (peek< exactly< rbrace > >()) {
|
1677
1653
|
css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
|
1678
1654
|
}
|
1679
|
-
|
1655
|
+
Expression_Obj ex = 0;
|
1680
1656
|
if (lex< re_static_expression >()) {
|
1681
|
-
ex = SASS_MEMORY_NEW(
|
1657
|
+
ex = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
|
1682
1658
|
} else {
|
1683
1659
|
ex = parse_list();
|
1684
1660
|
}
|
1685
1661
|
ex->is_interpolant(true);
|
1686
|
-
(
|
1687
|
-
|
1688
|
-
|
1662
|
+
schema->append(ex);
|
1663
|
+
if (!lex < exactly < rbrace > >()) {
|
1664
|
+
css_error("Invalid CSS", " after ", ": expected \"}\", was ");
|
1665
|
+
}
|
1689
1666
|
}
|
1690
1667
|
// lex some string constants or other valid token
|
1691
1668
|
// Note: [-+] chars are left over from i.e. `#{3}+3`
|
1692
1669
|
else if (lex< alternatives < exactly<'%'>, exactly < '-' >, exactly < '+' > > >()) {
|
1693
|
-
(
|
1670
|
+
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
|
1694
1671
|
}
|
1695
1672
|
// lex a quoted string
|
1696
1673
|
else if (lex< quoted_string >()) {
|
1697
1674
|
// need_space = true;
|
1698
|
-
// if (schema->length()) (
|
1675
|
+
// if (schema->length()) schema->append(SASS_MEMORY_NEW(String_Constant, pstate, " "));
|
1699
1676
|
// else need_space = true;
|
1700
|
-
(
|
1677
|
+
schema->append(&parse_string());
|
1701
1678
|
if ((*position == '"' || *position == '\'') || peek < alternatives < alpha > >()) {
|
1702
1679
|
// need_space = true;
|
1703
1680
|
}
|
1704
1681
|
if (peek < exactly < '-' > >()) break;
|
1705
1682
|
}
|
1706
1683
|
else if (lex< sequence < identifier > >()) {
|
1707
|
-
(
|
1684
|
+
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
|
1708
1685
|
if ((*position == '"' || *position == '\'') || peek < alternatives < alpha > >()) {
|
1709
1686
|
// need_space = true;
|
1710
1687
|
}
|
@@ -1712,30 +1689,30 @@ namespace Sass {
|
|
1712
1689
|
// lex (normalized) variable
|
1713
1690
|
else if (lex< variable >()) {
|
1714
1691
|
std::string name(Util::normalize_underscores(lexed));
|
1715
|
-
(
|
1692
|
+
schema->append(SASS_MEMORY_NEW(Variable, pstate, name));
|
1716
1693
|
}
|
1717
1694
|
// lex percentage value
|
1718
1695
|
else if (lex< percentage >()) {
|
1719
|
-
(
|
1696
|
+
schema->append(SASS_MEMORY_NEW(Textual, pstate, Textual::PERCENTAGE, lexed));
|
1720
1697
|
}
|
1721
1698
|
// lex dimension value
|
1722
1699
|
else if (lex< dimension >()) {
|
1723
|
-
(
|
1700
|
+
schema->append(SASS_MEMORY_NEW(Textual, pstate, Textual::DIMENSION, lexed));
|
1724
1701
|
}
|
1725
1702
|
// lex number value
|
1726
1703
|
else if (lex< number >()) {
|
1727
|
-
(
|
1704
|
+
schema->append( SASS_MEMORY_NEW(Textual, pstate, Textual::NUMBER, lexed));
|
1728
1705
|
}
|
1729
1706
|
// lex hex color value
|
1730
1707
|
else if (lex< sequence < hex, negate < exactly < '-' > > > >()) {
|
1731
|
-
(
|
1708
|
+
schema->append(SASS_MEMORY_NEW(Textual, pstate, Textual::HEX, lexed));
|
1732
1709
|
}
|
1733
1710
|
else if (lex< sequence < exactly <'#'>, identifier > >()) {
|
1734
|
-
(
|
1711
|
+
schema->append(SASS_MEMORY_NEW(String_Quoted, pstate, lexed));
|
1735
1712
|
}
|
1736
1713
|
// lex a value in parentheses
|
1737
1714
|
else if (peek< parenthese_scope >()) {
|
1738
|
-
(
|
1715
|
+
schema->append(&parse_factor());
|
1739
1716
|
}
|
1740
1717
|
else {
|
1741
1718
|
break;
|
@@ -1743,7 +1720,7 @@ namespace Sass {
|
|
1743
1720
|
++num_items;
|
1744
1721
|
}
|
1745
1722
|
if (position != stop) {
|
1746
|
-
(
|
1723
|
+
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(position, stop)));
|
1747
1724
|
position = stop;
|
1748
1725
|
}
|
1749
1726
|
end = ee;
|
@@ -1752,24 +1729,24 @@ namespace Sass {
|
|
1752
1729
|
|
1753
1730
|
// this parses interpolation outside other strings
|
1754
1731
|
// means the result must not be quoted again later
|
1755
|
-
|
1732
|
+
String_Obj Parser::parse_identifier_schema()
|
1756
1733
|
{
|
1757
1734
|
Token id(lexed);
|
1758
1735
|
const char* i = id.begin;
|
1759
1736
|
// see if there any interpolants
|
1760
1737
|
const char* p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(id.begin, id.end);
|
1761
1738
|
if (!p) {
|
1762
|
-
return SASS_MEMORY_NEW(
|
1739
|
+
return SASS_MEMORY_NEW(String_Constant, pstate, std::string(id.begin, id.end));
|
1763
1740
|
}
|
1764
1741
|
|
1765
|
-
|
1742
|
+
String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
|
1766
1743
|
while (i < id.end) {
|
1767
1744
|
p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, id.end);
|
1768
1745
|
if (p) {
|
1769
1746
|
if (i < p) {
|
1770
1747
|
// accumulate the preceding segment if it's nonempty
|
1771
1748
|
const char* o = position; position = i;
|
1772
|
-
|
1749
|
+
schema->append(&parse_value_schema(p));
|
1773
1750
|
position = o;
|
1774
1751
|
}
|
1775
1752
|
// we need to skip anything inside strings
|
@@ -1780,9 +1757,9 @@ namespace Sass {
|
|
1780
1757
|
const char* j = skip_over_scopes< exactly<hash_lbrace>, exactly<rbrace> >(p+2, id.end); // find the closing brace
|
1781
1758
|
if (j) {
|
1782
1759
|
// parse the interpolant and accumulate it
|
1783
|
-
|
1760
|
+
Expression_Obj interp_node = Parser::from_token(Token(p+2, j), ctx, pstate, source).parse_list(DELAYED);
|
1784
1761
|
interp_node->is_interpolant(true);
|
1785
|
-
(
|
1762
|
+
schema->append(interp_node);
|
1786
1763
|
// schema->has_interpolants(true);
|
1787
1764
|
i = j;
|
1788
1765
|
}
|
@@ -1794,17 +1771,17 @@ namespace Sass {
|
|
1794
1771
|
else { // no interpolants left; add the last segment if nonempty
|
1795
1772
|
if (i < end) {
|
1796
1773
|
const char* o = position; position = i;
|
1797
|
-
|
1774
|
+
schema->append(&parse_value_schema(id.end));
|
1798
1775
|
position = o;
|
1799
1776
|
}
|
1800
1777
|
break;
|
1801
1778
|
}
|
1802
1779
|
}
|
1803
|
-
return schema;
|
1780
|
+
return schema ? schema.detach() : 0;
|
1804
1781
|
}
|
1805
1782
|
|
1806
1783
|
// calc functions should preserve arguments
|
1807
|
-
|
1784
|
+
Function_Call_Obj Parser::parse_calc_function()
|
1808
1785
|
{
|
1809
1786
|
lex< identifier >();
|
1810
1787
|
std::string name(lexed);
|
@@ -1819,13 +1796,13 @@ namespace Sass {
|
|
1819
1796
|
exactly < ')' >
|
1820
1797
|
> >();
|
1821
1798
|
|
1822
|
-
|
1823
|
-
|
1824
|
-
|
1825
|
-
return SASS_MEMORY_NEW(
|
1799
|
+
Argument_Obj arg = SASS_MEMORY_NEW(Argument, arg_pos, &parse_interpolated_chunk(Token(arg_beg, arg_end)));
|
1800
|
+
Arguments_Obj args = SASS_MEMORY_NEW(Arguments, arg_pos);
|
1801
|
+
args->append(&arg);
|
1802
|
+
return SASS_MEMORY_NEW(Function_Call, call_pos, name, args);
|
1826
1803
|
}
|
1827
1804
|
|
1828
|
-
|
1805
|
+
String_Obj Parser::parse_url_function_string()
|
1829
1806
|
{
|
1830
1807
|
std::string prefix("");
|
1831
1808
|
if (lex< uri_prefix >()) {
|
@@ -1833,7 +1810,7 @@ namespace Sass {
|
|
1833
1810
|
}
|
1834
1811
|
|
1835
1812
|
lex < optional_spaces >();
|
1836
|
-
|
1813
|
+
String_Obj url_string = parse_url_function_argument();
|
1837
1814
|
|
1838
1815
|
std::string suffix("");
|
1839
1816
|
if (lex< real_uri_suffix >()) {
|
@@ -1841,23 +1818,23 @@ namespace Sass {
|
|
1841
1818
|
}
|
1842
1819
|
|
1843
1820
|
std::string uri("");
|
1844
|
-
if (url_string) {
|
1821
|
+
if (&url_string) {
|
1845
1822
|
uri = url_string->to_string({ NESTED, 5 });
|
1846
1823
|
}
|
1847
1824
|
|
1848
|
-
if (
|
1849
|
-
|
1850
|
-
(
|
1851
|
-
(
|
1852
|
-
(
|
1853
|
-
return res;
|
1825
|
+
if (String_Schema_Ptr schema = dynamic_cast<String_Schema_Ptr>(&url_string)) {
|
1826
|
+
String_Schema_Obj res = SASS_MEMORY_NEW(String_Schema, pstate);
|
1827
|
+
res->append(SASS_MEMORY_NEW(String_Constant, pstate, prefix));
|
1828
|
+
res->append(schema);
|
1829
|
+
res->append(SASS_MEMORY_NEW(String_Constant, pstate, suffix));
|
1830
|
+
return &res;
|
1854
1831
|
} else {
|
1855
1832
|
std::string res = prefix + uri + suffix;
|
1856
|
-
return SASS_MEMORY_NEW(
|
1833
|
+
return SASS_MEMORY_NEW(String_Constant, pstate, res);
|
1857
1834
|
}
|
1858
1835
|
}
|
1859
1836
|
|
1860
|
-
|
1837
|
+
String_Obj Parser::parse_url_function_argument()
|
1861
1838
|
{
|
1862
1839
|
const char* p = position;
|
1863
1840
|
|
@@ -1873,63 +1850,63 @@ namespace Sass {
|
|
1873
1850
|
pp = sequence< interpolant, real_uri_value >(pp);
|
1874
1851
|
}
|
1875
1852
|
position = pp;
|
1876
|
-
return parse_interpolated_chunk(Token(p, position));
|
1853
|
+
return &parse_interpolated_chunk(Token(p, position));
|
1877
1854
|
}
|
1878
1855
|
else if (uri != "") {
|
1879
1856
|
std::string res = Util::rtrim(uri);
|
1880
|
-
return SASS_MEMORY_NEW(
|
1857
|
+
return SASS_MEMORY_NEW(String_Constant, pstate, res);
|
1881
1858
|
}
|
1882
1859
|
|
1883
1860
|
return 0;
|
1884
1861
|
}
|
1885
1862
|
|
1886
|
-
|
1863
|
+
Function_Call_Obj Parser::parse_function_call()
|
1887
1864
|
{
|
1888
1865
|
lex< identifier >();
|
1889
1866
|
std::string name(lexed);
|
1890
1867
|
|
1891
1868
|
ParserState call_pos = pstate;
|
1892
|
-
|
1893
|
-
return SASS_MEMORY_NEW(
|
1869
|
+
Arguments_Obj args = parse_arguments();
|
1870
|
+
return SASS_MEMORY_NEW(Function_Call, call_pos, name, args);
|
1894
1871
|
}
|
1895
1872
|
|
1896
|
-
|
1873
|
+
Function_Call_Schema_Obj Parser::parse_function_call_schema()
|
1897
1874
|
{
|
1898
|
-
|
1875
|
+
String_Obj name = parse_identifier_schema();
|
1899
1876
|
ParserState source_position_of_call = pstate;
|
1877
|
+
Arguments_Obj args = parse_arguments();
|
1900
1878
|
|
1901
|
-
|
1902
|
-
return the_call;
|
1879
|
+
return SASS_MEMORY_NEW(Function_Call_Schema, source_position_of_call, name, args);
|
1903
1880
|
}
|
1904
1881
|
|
1905
|
-
|
1882
|
+
Content_Obj Parser::parse_content_directive()
|
1906
1883
|
{
|
1907
|
-
return SASS_MEMORY_NEW(
|
1884
|
+
return SASS_MEMORY_NEW(Content, pstate);
|
1908
1885
|
}
|
1909
1886
|
|
1910
|
-
|
1887
|
+
If_Obj Parser::parse_if_directive(bool else_if)
|
1911
1888
|
{
|
1912
1889
|
stack.push_back(Scope::Control);
|
1913
1890
|
ParserState if_source_position = pstate;
|
1914
1891
|
bool root = block_stack.back()->is_root();
|
1915
|
-
|
1916
|
-
|
1917
|
-
|
1892
|
+
Expression_Obj predicate = parse_list();
|
1893
|
+
Block_Obj block = parse_block(root);
|
1894
|
+
Block_Obj alternative = NULL;
|
1918
1895
|
|
1919
1896
|
// only throw away comment if we parse a case
|
1920
1897
|
// we want all other comments to be parsed
|
1921
1898
|
if (lex_css< elseif_directive >()) {
|
1922
|
-
alternative = SASS_MEMORY_NEW(
|
1923
|
-
(
|
1899
|
+
alternative = SASS_MEMORY_NEW(Block, pstate);
|
1900
|
+
alternative->append(&parse_if_directive(true));
|
1924
1901
|
}
|
1925
1902
|
else if (lex_css< kwd_else_directive >()) {
|
1926
|
-
alternative = parse_block(root);
|
1903
|
+
alternative = &parse_block(root);
|
1927
1904
|
}
|
1928
1905
|
stack.pop_back();
|
1929
|
-
return SASS_MEMORY_NEW(
|
1906
|
+
return SASS_MEMORY_NEW(If, if_source_position, predicate, block, alternative);
|
1930
1907
|
}
|
1931
1908
|
|
1932
|
-
|
1909
|
+
For_Obj Parser::parse_for_directive()
|
1933
1910
|
{
|
1934
1911
|
stack.push_back(Scope::Control);
|
1935
1912
|
ParserState for_source_position = pstate;
|
@@ -1937,15 +1914,15 @@ namespace Sass {
|
|
1937
1914
|
lex_variable();
|
1938
1915
|
std::string var(Util::normalize_underscores(lexed));
|
1939
1916
|
if (!lex< kwd_from >()) error("expected 'from' keyword in @for directive", pstate);
|
1940
|
-
|
1917
|
+
Expression_Obj lower_bound = parse_expression();
|
1941
1918
|
bool inclusive = false;
|
1942
1919
|
if (lex< kwd_through >()) inclusive = true;
|
1943
1920
|
else if (lex< kwd_to >()) inclusive = false;
|
1944
1921
|
else error("expected 'through' or 'to' keyword in @for directive", pstate);
|
1945
|
-
|
1946
|
-
|
1922
|
+
Expression_Obj upper_bound = parse_expression();
|
1923
|
+
Block_Obj body = parse_block(root);
|
1947
1924
|
stack.pop_back();
|
1948
|
-
return SASS_MEMORY_NEW(
|
1925
|
+
return SASS_MEMORY_NEW(For, for_source_position, var, lower_bound, upper_bound, body, inclusive);
|
1949
1926
|
}
|
1950
1927
|
|
1951
1928
|
// helper to parse a var token
|
@@ -1974,7 +1951,7 @@ namespace Sass {
|
|
1974
1951
|
return token;
|
1975
1952
|
}
|
1976
1953
|
|
1977
|
-
|
1954
|
+
Each_Obj Parser::parse_each_directive()
|
1978
1955
|
{
|
1979
1956
|
stack.push_back(Scope::Control);
|
1980
1957
|
ParserState each_source_position = pstate;
|
@@ -1987,113 +1964,114 @@ namespace Sass {
|
|
1987
1964
|
vars.push_back(Util::normalize_underscores(lexed));
|
1988
1965
|
}
|
1989
1966
|
if (!lex< kwd_in >()) error("expected 'in' keyword in @each directive", pstate);
|
1990
|
-
|
1991
|
-
|
1967
|
+
Expression_Obj list = parse_list();
|
1968
|
+
Block_Obj body = parse_block(root);
|
1992
1969
|
stack.pop_back();
|
1993
|
-
return SASS_MEMORY_NEW(
|
1970
|
+
return SASS_MEMORY_NEW(Each, each_source_position, vars, list, body);
|
1994
1971
|
}
|
1995
1972
|
|
1996
1973
|
// called after parsing `kwd_while_directive`
|
1997
|
-
|
1974
|
+
While_Obj Parser::parse_while_directive()
|
1998
1975
|
{
|
1999
1976
|
stack.push_back(Scope::Control);
|
2000
1977
|
bool root = block_stack.back()->is_root();
|
2001
1978
|
// create the initial while call object
|
2002
|
-
|
1979
|
+
While_Obj call = SASS_MEMORY_NEW(While, pstate, 0, 0);
|
2003
1980
|
// parse mandatory predicate
|
2004
|
-
|
1981
|
+
Expression_Obj predicate = parse_list();
|
2005
1982
|
call->predicate(predicate);
|
2006
1983
|
// parse mandatory block
|
2007
1984
|
call->block(parse_block(root));
|
2008
1985
|
// return ast node
|
2009
1986
|
stack.pop_back();
|
2010
1987
|
// return ast node
|
2011
|
-
return call;
|
1988
|
+
return call.detach();
|
2012
1989
|
}
|
2013
1990
|
|
2014
1991
|
// EO parse_while_directive
|
2015
|
-
|
1992
|
+
Media_Block_Obj Parser::parse_media_block()
|
2016
1993
|
{
|
2017
1994
|
stack.push_back(Scope::Media);
|
2018
|
-
|
1995
|
+
Media_Block_Obj media_block = SASS_MEMORY_NEW(Media_Block, pstate, 0, 0);
|
1996
|
+
|
2019
1997
|
media_block->media_queries(parse_media_queries());
|
2020
1998
|
|
2021
|
-
|
2022
|
-
last_media_block = media_block;
|
1999
|
+
Media_Block_Obj prev_media_block = last_media_block;
|
2000
|
+
last_media_block = &media_block;
|
2023
2001
|
media_block->block(parse_css_block());
|
2024
|
-
last_media_block = prev_media_block;
|
2002
|
+
last_media_block = &prev_media_block;
|
2025
2003
|
stack.pop_back();
|
2026
|
-
return media_block;
|
2004
|
+
return media_block.detach();
|
2027
2005
|
}
|
2028
2006
|
|
2029
|
-
|
2007
|
+
List_Obj Parser::parse_media_queries()
|
2030
2008
|
{
|
2031
2009
|
advanceToNextToken();
|
2032
|
-
|
2033
|
-
if (!peek_css < exactly <'{'> >()) (
|
2034
|
-
while (lex_css < exactly <','> >()) (
|
2035
|
-
|
2036
|
-
return
|
2010
|
+
List_Obj queries = SASS_MEMORY_NEW(List, pstate, 0, SASS_COMMA);
|
2011
|
+
if (!peek_css < exactly <'{'> >()) queries->append(&parse_media_query());
|
2012
|
+
while (lex_css < exactly <','> >()) queries->append(&parse_media_query());
|
2013
|
+
queries->update_pstate(pstate);
|
2014
|
+
return queries.detach();
|
2037
2015
|
}
|
2038
2016
|
|
2039
|
-
//
|
2040
|
-
|
2017
|
+
// Expression_Ptr Parser::parse_media_query()
|
2018
|
+
Media_Query_Obj Parser::parse_media_query()
|
2041
2019
|
{
|
2042
2020
|
advanceToNextToken();
|
2043
|
-
|
2021
|
+
Media_Query_Obj media_query = SASS_MEMORY_NEW(Media_Query, pstate);
|
2044
2022
|
if (lex < kwd_not >()) { media_query->is_negated(true); lex < css_comments >(false); }
|
2045
2023
|
else if (lex < kwd_only >()) { media_query->is_restricted(true); lex < css_comments >(false); }
|
2046
2024
|
|
2047
|
-
if (lex < identifier_schema >()) media_query->media_type(parse_identifier_schema());
|
2048
|
-
else if (lex < identifier >()) media_query->media_type(parse_interpolated_chunk(lexed));
|
2049
|
-
else (
|
2025
|
+
if (lex < identifier_schema >()) media_query->media_type(&parse_identifier_schema());
|
2026
|
+
else if (lex < identifier >()) media_query->media_type(&parse_interpolated_chunk(lexed));
|
2027
|
+
else media_query->append(&parse_media_expression());
|
2050
2028
|
|
2051
|
-
while (lex_css < kwd_and >()) (
|
2029
|
+
while (lex_css < kwd_and >()) media_query->append(&parse_media_expression());
|
2052
2030
|
if (lex < identifier_schema >()) {
|
2053
|
-
|
2054
|
-
|
2055
|
-
|
2056
|
-
|
2031
|
+
String_Schema_Ptr schema = SASS_MEMORY_NEW(String_Schema, pstate);
|
2032
|
+
schema->append(&media_query->media_type());
|
2033
|
+
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, " "));
|
2034
|
+
schema->append(&parse_identifier_schema());
|
2057
2035
|
media_query->media_type(schema);
|
2058
2036
|
}
|
2059
|
-
while (lex_css < kwd_and >()) (
|
2037
|
+
while (lex_css < kwd_and >()) media_query->append(&parse_media_expression());
|
2060
2038
|
|
2061
2039
|
media_query->update_pstate(pstate);
|
2062
2040
|
|
2063
2041
|
return media_query;
|
2064
2042
|
}
|
2065
2043
|
|
2066
|
-
|
2044
|
+
Media_Query_Expression_Obj Parser::parse_media_expression()
|
2067
2045
|
{
|
2068
2046
|
if (lex < identifier_schema >()) {
|
2069
|
-
|
2070
|
-
return SASS_MEMORY_NEW(
|
2047
|
+
String_Obj ss = parse_identifier_schema();
|
2048
|
+
return SASS_MEMORY_NEW(Media_Query_Expression, pstate, &ss, 0, true);
|
2071
2049
|
}
|
2072
2050
|
if (!lex_css< exactly<'('> >()) {
|
2073
2051
|
error("media query expression must begin with '('", pstate);
|
2074
2052
|
}
|
2075
|
-
|
2053
|
+
Expression_Obj feature = 0;
|
2076
2054
|
if (peek_css< exactly<')'> >()) {
|
2077
2055
|
error("media feature required in media query expression", pstate);
|
2078
2056
|
}
|
2079
|
-
feature = parse_expression();
|
2080
|
-
|
2057
|
+
feature = &parse_expression();
|
2058
|
+
Expression_Obj expression = 0;
|
2081
2059
|
if (lex_css< exactly<':'> >()) {
|
2082
|
-
expression = parse_list(DELAYED);
|
2060
|
+
expression = &parse_list(DELAYED);
|
2083
2061
|
}
|
2084
2062
|
if (!lex_css< exactly<')'> >()) {
|
2085
2063
|
error("unclosed parenthesis in media query expression", pstate);
|
2086
2064
|
}
|
2087
|
-
return SASS_MEMORY_NEW(
|
2065
|
+
return SASS_MEMORY_NEW(Media_Query_Expression, feature->pstate(), feature, expression);
|
2088
2066
|
}
|
2089
2067
|
|
2090
2068
|
// lexed after `kwd_supports_directive`
|
2091
2069
|
// these are very similar to media blocks
|
2092
|
-
|
2070
|
+
Supports_Block_Obj Parser::parse_supports_directive()
|
2093
2071
|
{
|
2094
|
-
|
2072
|
+
Supports_Condition_Obj cond = parse_supports_condition();
|
2095
2073
|
// create the ast node object for the support queries
|
2096
|
-
|
2074
|
+
Supports_Block_Obj query = SASS_MEMORY_NEW(Supports_Block, pstate, cond);
|
2097
2075
|
// additional block is mandatory
|
2098
2076
|
// parse inner block
|
2099
2077
|
query->block(parse_block());
|
@@ -2103,27 +2081,27 @@ namespace Sass {
|
|
2103
2081
|
|
2104
2082
|
// parse one query operation
|
2105
2083
|
// may encounter nested queries
|
2106
|
-
|
2084
|
+
Supports_Condition_Obj Parser::parse_supports_condition()
|
2107
2085
|
{
|
2108
2086
|
lex < css_whitespace >();
|
2109
|
-
|
2110
|
-
if (
|
2111
|
-
if (
|
2087
|
+
Supports_Condition_Obj cond = 0;
|
2088
|
+
if ((cond = parse_supports_negation())) return cond;
|
2089
|
+
if ((cond = parse_supports_operator())) return cond;
|
2090
|
+
if ((cond = parse_supports_interpolation())) return cond;
|
2112
2091
|
return cond;
|
2113
2092
|
}
|
2114
2093
|
|
2115
|
-
|
2094
|
+
Supports_Condition_Obj Parser::parse_supports_negation()
|
2116
2095
|
{
|
2117
2096
|
if (!lex < kwd_not >()) return 0;
|
2118
|
-
|
2119
|
-
|
2120
|
-
return SASS_MEMORY_NEW(ctx.mem, Supports_Negation, pstate, cond);
|
2097
|
+
Supports_Condition_Obj cond = parse_supports_condition_in_parens();
|
2098
|
+
return SASS_MEMORY_NEW(Supports_Negation, pstate, &cond);
|
2121
2099
|
}
|
2122
2100
|
|
2123
|
-
|
2101
|
+
Supports_Condition_Obj Parser::parse_supports_operator()
|
2124
2102
|
{
|
2125
|
-
|
2126
|
-
if (
|
2103
|
+
Supports_Condition_Obj cond = parse_supports_condition_in_parens();
|
2104
|
+
if (!&cond) return 0;
|
2127
2105
|
|
2128
2106
|
while (true) {
|
2129
2107
|
Supports_Operator::Operand op = Supports_Operator::OR;
|
@@ -2131,50 +2109,50 @@ namespace Sass {
|
|
2131
2109
|
else if(!lex < kwd_or >()) { break; }
|
2132
2110
|
|
2133
2111
|
lex < css_whitespace >();
|
2134
|
-
|
2112
|
+
Supports_Condition_Obj right = parse_supports_condition_in_parens();
|
2135
2113
|
|
2136
|
-
//
|
2137
|
-
cond = SASS_MEMORY_NEW(
|
2114
|
+
// Supports_Condition_Ptr cc = SASS_MEMORY_NEW(Supports_Condition, *static_cast<Supports_Condition_Ptr>(cond));
|
2115
|
+
cond = SASS_MEMORY_NEW(Supports_Operator, pstate, &cond, &right, op);
|
2138
2116
|
}
|
2139
2117
|
return cond;
|
2140
2118
|
}
|
2141
2119
|
|
2142
|
-
|
2120
|
+
Supports_Condition_Obj Parser::parse_supports_interpolation()
|
2143
2121
|
{
|
2144
2122
|
if (!lex < interpolant >()) return 0;
|
2145
2123
|
|
2146
|
-
|
2124
|
+
String_Obj interp = parse_interpolated_chunk(lexed);
|
2147
2125
|
if (!interp) return 0;
|
2148
2126
|
|
2149
|
-
return SASS_MEMORY_NEW(
|
2127
|
+
return SASS_MEMORY_NEW(Supports_Interpolation, pstate, &interp);
|
2150
2128
|
}
|
2151
2129
|
|
2152
2130
|
// TODO: This needs some major work. Although feature conditions
|
2153
2131
|
// look like declarations their semantics differ significantly
|
2154
|
-
|
2132
|
+
Supports_Condition_Obj Parser::parse_supports_declaration()
|
2155
2133
|
{
|
2156
|
-
|
2134
|
+
Supports_Condition_Ptr cond = 0;
|
2157
2135
|
// parse something declaration like
|
2158
|
-
|
2136
|
+
Declaration_Obj declaration = parse_declaration();
|
2159
2137
|
if (!declaration) error("@supports condition expected declaration", pstate);
|
2160
|
-
cond = SASS_MEMORY_NEW(
|
2138
|
+
cond = SASS_MEMORY_NEW(Supports_Declaration,
|
2161
2139
|
declaration->pstate(),
|
2162
|
-
declaration->property(),
|
2140
|
+
&declaration->property(),
|
2163
2141
|
declaration->value());
|
2164
2142
|
// ToDo: maybe we need an additional error condition?
|
2165
2143
|
return cond;
|
2166
2144
|
}
|
2167
2145
|
|
2168
|
-
|
2146
|
+
Supports_Condition_Obj Parser::parse_supports_condition_in_parens()
|
2169
2147
|
{
|
2170
|
-
|
2171
|
-
if (interp != 0) return interp;
|
2148
|
+
Supports_Condition_Obj interp = parse_supports_interpolation();
|
2149
|
+
if (&interp != 0) return interp;
|
2172
2150
|
|
2173
2151
|
if (!lex < exactly <'('> >()) return 0;
|
2174
2152
|
lex < css_whitespace >();
|
2175
2153
|
|
2176
|
-
|
2177
|
-
if (cond != 0) {
|
2154
|
+
Supports_Condition_Obj cond = parse_supports_condition();
|
2155
|
+
if (&cond != 0) {
|
2178
2156
|
if (!lex < exactly <')'> >()) error("unclosed parenthesis in @supports declaration", pstate);
|
2179
2157
|
} else {
|
2180
2158
|
cond = parse_supports_declaration();
|
@@ -2184,11 +2162,11 @@ namespace Sass {
|
|
2184
2162
|
return cond;
|
2185
2163
|
}
|
2186
2164
|
|
2187
|
-
|
2165
|
+
At_Root_Block_Obj Parser::parse_at_root_block()
|
2188
2166
|
{
|
2189
2167
|
ParserState at_source_position = pstate;
|
2190
|
-
|
2191
|
-
|
2168
|
+
Block_Obj body = 0;
|
2169
|
+
At_Root_Query_Obj expr;
|
2192
2170
|
Lookahead lookahead_result;
|
2193
2171
|
LOCAL_FLAG(in_at_root, true);
|
2194
2172
|
if (lex_css< exactly<'('> >()) {
|
@@ -2196,19 +2174,19 @@ namespace Sass {
|
|
2196
2174
|
}
|
2197
2175
|
if (peek_css < exactly<'{'> >()) {
|
2198
2176
|
lex <optional_spaces>();
|
2199
|
-
body = parse_block(true);
|
2177
|
+
body = &parse_block(true);
|
2200
2178
|
}
|
2201
2179
|
else if ((lookahead_result = lookahead_for_selector(position)).found) {
|
2202
|
-
|
2203
|
-
body = SASS_MEMORY_NEW(
|
2204
|
-
|
2180
|
+
Ruleset_Obj r = parse_ruleset(lookahead_result, false);
|
2181
|
+
body = SASS_MEMORY_NEW(Block, r->pstate(), 1, true);
|
2182
|
+
body->append(&r);
|
2205
2183
|
}
|
2206
|
-
|
2207
|
-
if (expr) at_root->expression(expr);
|
2184
|
+
At_Root_Block_Obj at_root = SASS_MEMORY_NEW(At_Root_Block, at_source_position, body);
|
2185
|
+
if (&expr) at_root->expression(&expr);
|
2208
2186
|
return at_root;
|
2209
2187
|
}
|
2210
2188
|
|
2211
|
-
|
2189
|
+
At_Root_Query_Obj Parser::parse_at_root_query()
|
2212
2190
|
{
|
2213
2191
|
if (peek< exactly<')'> >()) error("at-root feature required in at-root expression", pstate);
|
2214
2192
|
|
@@ -2216,40 +2194,40 @@ namespace Sass {
|
|
2216
2194
|
css_error("Invalid CSS", " after ", ": expected \"with\" or \"without\", was ");
|
2217
2195
|
}
|
2218
2196
|
|
2219
|
-
|
2197
|
+
Expression_Obj feature = parse_list();
|
2220
2198
|
if (!lex_css< exactly<':'> >()) error("style declaration must contain a value", pstate);
|
2221
|
-
|
2222
|
-
|
2199
|
+
Expression_Obj expression = parse_list();
|
2200
|
+
List_Obj value = SASS_MEMORY_NEW(List, feature->pstate(), 1);
|
2223
2201
|
|
2224
2202
|
if (expression->concrete_type() == Expression::LIST) {
|
2225
|
-
value =
|
2203
|
+
value = SASS_MEMORY_CAST(List, expression);
|
2226
2204
|
}
|
2227
|
-
else
|
2205
|
+
else value->append(expression);
|
2228
2206
|
|
2229
|
-
|
2207
|
+
At_Root_Query_Obj cond = SASS_MEMORY_NEW(At_Root_Query,
|
2230
2208
|
value->pstate(),
|
2231
2209
|
feature,
|
2232
|
-
value);
|
2210
|
+
&value);
|
2233
2211
|
if (!lex_css< exactly<')'> >()) error("unclosed parenthesis in @at-root expression", pstate);
|
2234
2212
|
return cond;
|
2235
2213
|
}
|
2236
2214
|
|
2237
|
-
|
2215
|
+
Directive_Obj Parser::parse_special_directive()
|
2238
2216
|
{
|
2239
2217
|
std::string kwd(lexed);
|
2240
2218
|
|
2241
2219
|
if (lexed == "@else") error("Invalid CSS: @else must come after @if", pstate);
|
2242
2220
|
|
2243
|
-
|
2221
|
+
Directive_Ptr at_rule = SASS_MEMORY_NEW(Directive, pstate, kwd);
|
2244
2222
|
Lookahead lookahead = lookahead_for_include(position);
|
2245
2223
|
if (lookahead.found && !lookahead.has_interpolants) {
|
2246
|
-
at_rule->selector(parse_selector_list(true));
|
2224
|
+
at_rule->selector(&parse_selector_list(true));
|
2247
2225
|
}
|
2248
2226
|
|
2249
2227
|
lex < css_comments >(false);
|
2250
2228
|
|
2251
2229
|
if (lex < static_property >()) {
|
2252
|
-
at_rule->value(parse_interpolated_chunk(Token(lexed)));
|
2230
|
+
at_rule->value(&parse_interpolated_chunk(Token(lexed)));
|
2253
2231
|
} else if (!(peek < alternatives < exactly<'{'>, exactly<'}'>, exactly<';'> > >())) {
|
2254
2232
|
at_rule->value(parse_list());
|
2255
2233
|
}
|
@@ -2263,24 +2241,24 @@ namespace Sass {
|
|
2263
2241
|
return at_rule;
|
2264
2242
|
}
|
2265
2243
|
|
2266
|
-
|
2244
|
+
Directive_Obj Parser::parse_prefixed_directive()
|
2267
2245
|
{
|
2268
2246
|
std::string kwd(lexed);
|
2269
2247
|
|
2270
2248
|
if (lexed == "@else") error("Invalid CSS: @else must come after @if", pstate);
|
2271
2249
|
|
2272
|
-
|
2250
|
+
Directive_Obj at_rule = SASS_MEMORY_NEW(Directive, pstate, kwd);
|
2273
2251
|
Lookahead lookahead = lookahead_for_include(position);
|
2274
2252
|
if (lookahead.found && !lookahead.has_interpolants) {
|
2275
|
-
at_rule->selector(parse_selector_list(true));
|
2253
|
+
at_rule->selector(&parse_selector_list(true));
|
2276
2254
|
}
|
2277
2255
|
|
2278
2256
|
lex < css_comments >(false);
|
2279
2257
|
|
2280
2258
|
if (lex < static_property >()) {
|
2281
|
-
at_rule->value(parse_interpolated_chunk(Token(lexed)));
|
2259
|
+
at_rule->value(&parse_interpolated_chunk(Token(lexed)));
|
2282
2260
|
} else if (!(peek < alternatives < exactly<'{'>, exactly<'}'>, exactly<';'> > >())) {
|
2283
|
-
at_rule->value(parse_list());
|
2261
|
+
at_rule->value(&parse_list());
|
2284
2262
|
}
|
2285
2263
|
|
2286
2264
|
lex < css_comments >(false);
|
@@ -2293,41 +2271,41 @@ namespace Sass {
|
|
2293
2271
|
}
|
2294
2272
|
|
2295
2273
|
|
2296
|
-
|
2274
|
+
Directive_Obj Parser::parse_directive()
|
2297
2275
|
{
|
2298
|
-
|
2299
|
-
|
2276
|
+
Directive_Obj directive = SASS_MEMORY_NEW(Directive, pstate, lexed);
|
2277
|
+
String_Schema_Obj val = parse_almost_any_value();
|
2300
2278
|
// strip left and right if they are of type string
|
2301
|
-
directive->value(val);
|
2279
|
+
directive->value(&val);
|
2302
2280
|
if (peek< exactly<'{'> >()) {
|
2303
2281
|
directive->block(parse_block());
|
2304
2282
|
}
|
2305
2283
|
return directive;
|
2306
2284
|
}
|
2307
2285
|
|
2308
|
-
|
2286
|
+
Expression_Obj Parser::lex_interpolation()
|
2309
2287
|
{
|
2310
2288
|
if (lex < interpolant >(true) != NULL) {
|
2311
|
-
return parse_interpolated_chunk(lexed, true);
|
2289
|
+
return &parse_interpolated_chunk(lexed, true);
|
2312
2290
|
}
|
2313
2291
|
return 0;
|
2314
2292
|
}
|
2315
2293
|
|
2316
|
-
|
2294
|
+
Expression_Obj Parser::lex_interp_uri()
|
2317
2295
|
{
|
2318
2296
|
// create a string schema by lexing optional interpolations
|
2319
2297
|
return lex_interp< re_string_uri_open, re_string_uri_close >();
|
2320
2298
|
}
|
2321
2299
|
|
2322
|
-
|
2300
|
+
Expression_Obj Parser::lex_interp_string()
|
2323
2301
|
{
|
2324
|
-
|
2325
|
-
if ((rv = lex_interp< re_string_double_open, re_string_double_close >())
|
2326
|
-
if ((rv = lex_interp< re_string_single_open, re_string_single_close >())
|
2302
|
+
Expression_Obj rv = 0;
|
2303
|
+
if ((rv = lex_interp< re_string_double_open, re_string_double_close >())) return rv;
|
2304
|
+
if ((rv = lex_interp< re_string_single_open, re_string_single_close >())) return rv;
|
2327
2305
|
return rv;
|
2328
2306
|
}
|
2329
2307
|
|
2330
|
-
|
2308
|
+
Expression_Obj Parser::lex_almost_any_value_chars()
|
2331
2309
|
{
|
2332
2310
|
const char* match =
|
2333
2311
|
lex <
|
@@ -2374,52 +2352,50 @@ namespace Sass {
|
|
2374
2352
|
>
|
2375
2353
|
>(false);
|
2376
2354
|
if (match) {
|
2377
|
-
|
2378
|
-
return SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, lexed);
|
2355
|
+
return SASS_MEMORY_NEW(String_Constant, pstate, lexed);
|
2379
2356
|
}
|
2380
2357
|
return NULL;
|
2381
2358
|
}
|
2382
2359
|
|
2383
|
-
|
2360
|
+
Expression_Obj Parser::lex_almost_any_value_token()
|
2384
2361
|
{
|
2385
|
-
|
2362
|
+
Expression_Obj rv = 0;
|
2386
2363
|
if (*position == 0) return 0;
|
2387
|
-
if ((rv = lex_almost_any_value_chars())
|
2388
|
-
// if ((rv = lex_block_comment())
|
2389
|
-
// if ((rv = lex_single_line_comment())
|
2390
|
-
if ((rv = lex_interp_string())
|
2391
|
-
if ((rv = lex_interp_uri())
|
2392
|
-
if ((rv = lex_interpolation())
|
2364
|
+
if ((rv = &lex_almost_any_value_chars())) return rv;
|
2365
|
+
// if ((rv = lex_block_comment())) return rv;
|
2366
|
+
// if ((rv = lex_single_line_comment())) return rv;
|
2367
|
+
if ((rv = &lex_interp_string())) return rv;
|
2368
|
+
if ((rv = &lex_interp_uri())) return rv;
|
2369
|
+
if ((rv = &lex_interpolation())) return rv;
|
2393
2370
|
return rv;
|
2394
2371
|
}
|
2395
2372
|
|
2396
|
-
|
2373
|
+
String_Schema_Obj Parser::parse_almost_any_value()
|
2397
2374
|
{
|
2398
2375
|
|
2399
|
-
|
2376
|
+
String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
|
2400
2377
|
if (*position == 0) return 0;
|
2401
2378
|
lex < spaces >(false);
|
2402
|
-
|
2379
|
+
Expression_Obj token = lex_almost_any_value_token();
|
2403
2380
|
if (!token) return 0;
|
2404
|
-
|
2405
|
-
*schema << token;
|
2381
|
+
schema->append(token);
|
2406
2382
|
if (*position == 0) {
|
2407
2383
|
schema->rtrim();
|
2408
|
-
return schema;
|
2384
|
+
return schema.detach();
|
2409
2385
|
}
|
2410
2386
|
|
2411
|
-
while ((token = lex_almost_any_value_token())) {
|
2412
|
-
|
2387
|
+
while ((token = &lex_almost_any_value_token())) {
|
2388
|
+
schema->append(token);
|
2413
2389
|
}
|
2414
2390
|
|
2415
2391
|
lex < css_whitespace >();
|
2416
2392
|
|
2417
2393
|
schema->rtrim();
|
2418
2394
|
|
2419
|
-
return schema;
|
2395
|
+
return schema.detach();
|
2420
2396
|
}
|
2421
2397
|
|
2422
|
-
|
2398
|
+
Warning_Obj Parser::parse_warning()
|
2423
2399
|
{
|
2424
2400
|
if (stack.back() != Scope::Root &&
|
2425
2401
|
stack.back() != Scope::Function &&
|
@@ -2428,10 +2404,10 @@ namespace Sass {
|
|
2428
2404
|
stack.back() != Scope::Rules) {
|
2429
2405
|
error("Illegal nesting: Only properties may be nested beneath properties.", pstate);
|
2430
2406
|
}
|
2431
|
-
return SASS_MEMORY_NEW(
|
2407
|
+
return SASS_MEMORY_NEW(Warning, pstate, parse_list(DELAYED));
|
2432
2408
|
}
|
2433
2409
|
|
2434
|
-
|
2410
|
+
Error_Obj Parser::parse_error()
|
2435
2411
|
{
|
2436
2412
|
if (stack.back() != Scope::Root &&
|
2437
2413
|
stack.back() != Scope::Function &&
|
@@ -2440,10 +2416,10 @@ namespace Sass {
|
|
2440
2416
|
stack.back() != Scope::Rules) {
|
2441
2417
|
error("Illegal nesting: Only properties may be nested beneath properties.", pstate);
|
2442
2418
|
}
|
2443
|
-
return SASS_MEMORY_NEW(
|
2419
|
+
return SASS_MEMORY_NEW(Error, pstate, parse_list(DELAYED));
|
2444
2420
|
}
|
2445
2421
|
|
2446
|
-
|
2422
|
+
Debug_Obj Parser::parse_debug()
|
2447
2423
|
{
|
2448
2424
|
if (stack.back() != Scope::Root &&
|
2449
2425
|
stack.back() != Scope::Function &&
|
@@ -2452,15 +2428,15 @@ namespace Sass {
|
|
2452
2428
|
stack.back() != Scope::Rules) {
|
2453
2429
|
error("Illegal nesting: Only properties may be nested beneath properties.", pstate);
|
2454
2430
|
}
|
2455
|
-
return SASS_MEMORY_NEW(
|
2431
|
+
return SASS_MEMORY_NEW(Debug, pstate, parse_list(DELAYED));
|
2456
2432
|
}
|
2457
2433
|
|
2458
|
-
|
2434
|
+
Return_Obj Parser::parse_return_directive()
|
2459
2435
|
{
|
2460
2436
|
// check that we do not have an empty list (ToDo: check if we got all cases)
|
2461
2437
|
if (peek_css < alternatives < exactly < ';' >, exactly < '}' >, end_of_file > >())
|
2462
2438
|
{ css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was "); }
|
2463
|
-
return SASS_MEMORY_NEW(
|
2439
|
+
return SASS_MEMORY_NEW(Return, pstate, &parse_list());
|
2464
2440
|
}
|
2465
2441
|
|
2466
2442
|
Lookahead Parser::lookahead_for_selector(const char* start)
|
@@ -2662,17 +2638,17 @@ namespace Sass {
|
|
2662
2638
|
}
|
2663
2639
|
|
2664
2640
|
|
2665
|
-
|
2641
|
+
Expression_Obj Parser::fold_operands(Expression_Obj base, std::vector<Expression_Obj>& operands, Operand op)
|
2666
2642
|
{
|
2667
2643
|
for (size_t i = 0, S = operands.size(); i < S; ++i) {
|
2668
|
-
base = SASS_MEMORY_NEW(
|
2644
|
+
base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), op, &base, operands[i]);
|
2669
2645
|
}
|
2670
2646
|
return base;
|
2671
2647
|
}
|
2672
2648
|
|
2673
|
-
|
2649
|
+
Expression_Obj Parser::fold_operands(Expression_Obj base, std::vector<Expression_Obj>& operands, std::vector<Operand>& ops, size_t i)
|
2674
2650
|
{
|
2675
|
-
if (
|
2651
|
+
if (String_Schema_Ptr schema = dynamic_cast<String_Schema_Ptr>(&base)) {
|
2676
2652
|
// return schema;
|
2677
2653
|
if (schema->has_interpolants()) {
|
2678
2654
|
if (i + 1 < operands.size() && (
|
@@ -2686,8 +2662,8 @@ namespace Sass {
|
|
2686
2662
|
|| (ops[0].operand == Sass_OP::LTE)
|
2687
2663
|
|| (ops[0].operand == Sass_OP::GTE)
|
2688
2664
|
)) {
|
2689
|
-
|
2690
|
-
rhs = SASS_MEMORY_NEW(
|
2665
|
+
Expression_Obj rhs = fold_operands(operands[i], operands, ops, i + 1);
|
2666
|
+
rhs = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[0], schema, &rhs);
|
2691
2667
|
return rhs;
|
2692
2668
|
}
|
2693
2669
|
// return schema;
|
@@ -2695,31 +2671,31 @@ namespace Sass {
|
|
2695
2671
|
}
|
2696
2672
|
|
2697
2673
|
for (size_t S = operands.size(); i < S; ++i) {
|
2698
|
-
if (
|
2674
|
+
if (String_Schema_Ptr schema = dynamic_cast<String_Schema_Ptr>(&operands[i])) {
|
2699
2675
|
if (schema->has_interpolants()) {
|
2700
2676
|
if (i + 1 < S) {
|
2701
|
-
|
2702
|
-
rhs = SASS_MEMORY_NEW(
|
2703
|
-
base = SASS_MEMORY_NEW(
|
2677
|
+
Expression_Obj rhs = fold_operands(operands[i+1], operands, ops, i + 2);
|
2678
|
+
rhs = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], schema, &rhs);
|
2679
|
+
base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], &base, &rhs);
|
2704
2680
|
return base;
|
2705
2681
|
}
|
2706
|
-
base = SASS_MEMORY_NEW(
|
2682
|
+
base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], &base, operands[i]);
|
2707
2683
|
return base;
|
2708
2684
|
} else {
|
2709
|
-
base = SASS_MEMORY_NEW(
|
2685
|
+
base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], &base, operands[i]);
|
2710
2686
|
}
|
2711
2687
|
} else {
|
2712
|
-
base = SASS_MEMORY_NEW(
|
2688
|
+
base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], &base, operands[i]);
|
2713
2689
|
}
|
2714
|
-
|
2690
|
+
Binary_Expression_Ptr b = static_cast<Binary_Expression_Ptr>(&base);
|
2715
2691
|
if (b && ops[i].operand == Sass_OP::DIV && b->left()->is_delayed() && b->right()->is_delayed()) {
|
2716
2692
|
base->is_delayed(true);
|
2717
2693
|
}
|
2718
2694
|
}
|
2719
2695
|
// nested binary expression are never to be delayed
|
2720
|
-
if (
|
2721
|
-
if (
|
2722
|
-
if (
|
2696
|
+
if (Binary_Expression_Ptr b = dynamic_cast<Binary_Expression_Ptr>(&base)) {
|
2697
|
+
if (SASS_MEMORY_CAST(Binary_Expression, b->left())) base->set_delayed(false);
|
2698
|
+
if (SASS_MEMORY_CAST(Binary_Expression, b->right())) base->set_delayed(false);
|
2723
2699
|
}
|
2724
2700
|
return base;
|
2725
2701
|
}
|