sassc 2.3.0 → 2.4.0
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 +1 -0
- data/CHANGELOG.md +5 -0
- data/ext/libsass/VERSION +1 -1
- data/ext/libsass/include/sass/context.h +3 -0
- data/ext/libsass/src/MurmurHash2.hpp +91 -0
- data/ext/libsass/src/ast.cpp +117 -117
- data/ext/libsass/src/ast.hpp +160 -162
- data/ext/libsass/src/ast_def_macros.hpp +10 -10
- data/ext/libsass/src/ast_fwd_decl.cpp +2 -2
- data/ext/libsass/src/ast_fwd_decl.hpp +61 -52
- data/ext/libsass/src/ast_helpers.hpp +5 -5
- data/ext/libsass/src/ast_sel_cmp.cpp +18 -18
- data/ext/libsass/src/ast_sel_super.cpp +52 -52
- data/ext/libsass/src/ast_sel_unify.cpp +16 -16
- data/ext/libsass/src/ast_sel_weave.cpp +62 -62
- data/ext/libsass/src/ast_selectors.cpp +87 -77
- data/ext/libsass/src/ast_selectors.hpp +72 -62
- data/ext/libsass/src/ast_supports.cpp +35 -35
- data/ext/libsass/src/ast_supports.hpp +29 -29
- data/ext/libsass/src/ast_values.cpp +58 -58
- data/ext/libsass/src/ast_values.hpp +75 -75
- data/ext/libsass/src/backtrace.cpp +9 -9
- data/ext/libsass/src/backtrace.hpp +5 -5
- data/ext/libsass/src/base64vlq.cpp +2 -2
- data/ext/libsass/src/base64vlq.hpp +1 -1
- data/ext/libsass/src/bind.cpp +17 -17
- data/ext/libsass/src/bind.hpp +1 -1
- data/ext/libsass/src/c2ast.cpp +3 -3
- data/ext/libsass/src/c2ast.hpp +1 -1
- data/ext/libsass/src/check_nesting.cpp +36 -36
- data/ext/libsass/src/check_nesting.hpp +2 -2
- data/ext/libsass/src/color_maps.cpp +5 -5
- data/ext/libsass/src/color_maps.hpp +1 -1
- data/ext/libsass/src/context.cpp +63 -60
- data/ext/libsass/src/context.hpp +33 -33
- data/ext/libsass/src/cssize.cpp +30 -29
- data/ext/libsass/src/cssize.hpp +13 -13
- data/ext/libsass/src/dart_helpers.hpp +5 -5
- data/ext/libsass/src/debugger.hpp +127 -128
- data/ext/libsass/src/emitter.cpp +12 -12
- data/ext/libsass/src/emitter.hpp +10 -10
- data/ext/libsass/src/environment.cpp +27 -27
- data/ext/libsass/src/environment.hpp +24 -24
- data/ext/libsass/src/error_handling.cpp +42 -42
- data/ext/libsass/src/error_handling.hpp +38 -50
- data/ext/libsass/src/eval.cpp +138 -132
- data/ext/libsass/src/eval.hpp +17 -17
- data/ext/libsass/src/eval_selectors.cpp +3 -3
- data/ext/libsass/src/expand.cpp +70 -64
- data/ext/libsass/src/expand.hpp +12 -12
- data/ext/libsass/src/extender.cpp +55 -53
- data/ext/libsass/src/extender.hpp +14 -14
- data/ext/libsass/src/file.cpp +66 -58
- data/ext/libsass/src/file.hpp +23 -25
- data/ext/libsass/src/fn_colors.cpp +9 -9
- data/ext/libsass/src/fn_lists.cpp +18 -18
- data/ext/libsass/src/fn_maps.cpp +3 -3
- data/ext/libsass/src/fn_miscs.cpp +15 -15
- data/ext/libsass/src/fn_numbers.cpp +7 -7
- data/ext/libsass/src/fn_selectors.cpp +8 -8
- data/ext/libsass/src/fn_strings.cpp +34 -22
- data/ext/libsass/src/fn_utils.cpp +29 -26
- data/ext/libsass/src/fn_utils.hpp +10 -10
- data/ext/libsass/src/inspect.cpp +35 -34
- data/ext/libsass/src/inspect.hpp +21 -21
- data/ext/libsass/src/lexer.cpp +3 -1
- data/ext/libsass/src/listize.cpp +2 -2
- data/ext/libsass/src/mapping.hpp +1 -0
- data/ext/libsass/src/memory.hpp +12 -0
- data/ext/libsass/src/memory/allocator.cpp +48 -0
- data/ext/libsass/src/memory/allocator.hpp +138 -0
- data/ext/libsass/src/memory/config.hpp +20 -0
- data/ext/libsass/src/memory/memory_pool.hpp +186 -0
- data/ext/libsass/src/memory/{SharedPtr.cpp → shared_ptr.cpp} +2 -2
- data/ext/libsass/src/memory/{SharedPtr.hpp → shared_ptr.hpp} +18 -6
- data/ext/libsass/src/operation.hpp +44 -44
- data/ext/libsass/src/operators.cpp +18 -18
- data/ext/libsass/src/operators.hpp +11 -11
- data/ext/libsass/src/ordered_map.hpp +18 -18
- data/ext/libsass/src/output.cpp +16 -16
- data/ext/libsass/src/output.hpp +5 -5
- data/ext/libsass/src/parser.cpp +327 -345
- data/ext/libsass/src/parser.hpp +77 -87
- data/ext/libsass/src/parser_selectors.cpp +6 -6
- data/ext/libsass/src/permutate.hpp +39 -15
- data/ext/libsass/src/plugins.cpp +7 -7
- data/ext/libsass/src/plugins.hpp +8 -8
- data/ext/libsass/src/position.cpp +7 -26
- data/ext/libsass/src/position.hpp +44 -21
- data/ext/libsass/src/remove_placeholders.cpp +4 -4
- data/ext/libsass/src/remove_placeholders.hpp +3 -3
- data/ext/libsass/src/sass.cpp +16 -15
- data/ext/libsass/src/sass.hpp +9 -5
- data/ext/libsass/src/sass_context.cpp +52 -34
- data/ext/libsass/src/sass_values.cpp +8 -10
- data/ext/libsass/src/settings.hpp +19 -0
- data/ext/libsass/src/source.cpp +69 -0
- data/ext/libsass/src/source.hpp +95 -0
- data/ext/libsass/src/source_data.hpp +32 -0
- data/ext/libsass/src/source_map.cpp +22 -18
- data/ext/libsass/src/source_map.hpp +12 -9
- data/ext/libsass/src/units.cpp +19 -19
- data/ext/libsass/src/units.hpp +8 -8
- data/ext/libsass/src/utf8_string.cpp +9 -10
- data/ext/libsass/src/utf8_string.hpp +7 -6
- data/ext/libsass/src/util.cpp +38 -38
- data/ext/libsass/src/util.hpp +18 -18
- data/ext/libsass/src/util_string.cpp +13 -13
- data/ext/libsass/src/util_string.hpp +9 -8
- data/ext/libsass/src/values.cpp +12 -12
- data/lib/sassc/native.rb +3 -5
- data/lib/sassc/version.rb +1 -1
- data/test/native_test.rb +4 -4
- metadata +14 -5
- data/lib/sassc/native/lib_c.rb +0 -21
data/ext/libsass/src/output.cpp
CHANGED
@@ -30,7 +30,7 @@ namespace Sass {
|
|
30
30
|
throw Exception::InvalidValue({}, *n);
|
31
31
|
}
|
32
32
|
// use values to_string facility
|
33
|
-
|
33
|
+
sass::string res = n->to_string(opt);
|
34
34
|
// output the final token
|
35
35
|
append_token(res, n);
|
36
36
|
}
|
@@ -77,7 +77,7 @@ namespace Sass {
|
|
77
77
|
// declare the charset
|
78
78
|
if (output_style() != COMPRESSED)
|
79
79
|
charset = "@charset \"UTF-8\";"
|
80
|
-
+
|
80
|
+
+ sass::string(opt.linefeed);
|
81
81
|
else charset = "\xEF\xBB\xBF";
|
82
82
|
// abort search
|
83
83
|
break;
|
@@ -111,7 +111,7 @@ namespace Sass {
|
|
111
111
|
}
|
112
112
|
}
|
113
113
|
|
114
|
-
void Output::operator()(
|
114
|
+
void Output::operator()(StyleRule* r)
|
115
115
|
{
|
116
116
|
Block_Obj b = r->block();
|
117
117
|
SelectorListObj s = r->selector();
|
@@ -122,7 +122,7 @@ namespace Sass {
|
|
122
122
|
if (!Util::isPrintable(r, output_style())) {
|
123
123
|
for (size_t i = 0, L = b->length(); i < L; ++i) {
|
124
124
|
const Statement_Obj& stm = b->get(i);
|
125
|
-
if (Cast<
|
125
|
+
if (Cast<ParentStatement>(stm)) {
|
126
126
|
if (!Cast<Declaration>(stm)) {
|
127
127
|
stm->perform(this);
|
128
128
|
}
|
@@ -135,10 +135,10 @@ namespace Sass {
|
|
135
135
|
indentation += r->tabs();
|
136
136
|
}
|
137
137
|
if (opt.source_comments) {
|
138
|
-
|
138
|
+
sass::ostream ss;
|
139
139
|
append_indentation();
|
140
|
-
|
141
|
-
ss << "/* line " << r->pstate().
|
140
|
+
sass::string path(File::abs2rel(r->pstate().getPath()));
|
141
|
+
ss << "/* line " << r->pstate().getLine() << ", " << path << " */";
|
142
142
|
append_string(ss.str());
|
143
143
|
append_optional_linefeed();
|
144
144
|
}
|
@@ -151,7 +151,7 @@ namespace Sass {
|
|
151
151
|
// Check print conditions
|
152
152
|
if (Declaration* dec = Cast<Declaration>(stm)) {
|
153
153
|
if (const String_Constant* valConst = Cast<String_Constant>(dec->value())) {
|
154
|
-
const
|
154
|
+
const sass::string& val = valConst->value();
|
155
155
|
if (const String_Quoted* qstr = Cast<const String_Quoted>(valConst)) {
|
156
156
|
if (!qstr->quote_mark() && val.empty()) {
|
157
157
|
bPrintExpression = false;
|
@@ -199,18 +199,18 @@ namespace Sass {
|
|
199
199
|
append_scope_closer();
|
200
200
|
}
|
201
201
|
|
202
|
-
void Output::operator()(
|
202
|
+
void Output::operator()(SupportsRule* f)
|
203
203
|
{
|
204
204
|
if (f->is_invisible()) return;
|
205
205
|
|
206
|
-
|
206
|
+
SupportsConditionObj c = f->condition();
|
207
207
|
Block_Obj b = f->block();
|
208
208
|
|
209
209
|
// Filter out feature blocks that aren't printable (process its children though)
|
210
210
|
if (!Util::isPrintable(f, output_style())) {
|
211
211
|
for (size_t i = 0, L = b->length(); i < L; ++i) {
|
212
212
|
Statement_Obj stm = b->get(i);
|
213
|
-
if (Cast<
|
213
|
+
if (Cast<ParentStatement>(stm)) {
|
214
214
|
stm->perform(this);
|
215
215
|
}
|
216
216
|
}
|
@@ -253,11 +253,11 @@ namespace Sass {
|
|
253
253
|
}
|
254
254
|
}
|
255
255
|
|
256
|
-
void Output::operator()(
|
256
|
+
void Output::operator()(AtRule* a)
|
257
257
|
{
|
258
|
-
|
258
|
+
sass::string kwd = a->keyword();
|
259
259
|
Selector_Obj s = a->selector();
|
260
|
-
|
260
|
+
ExpressionObj v = a->value();
|
261
261
|
Block_Obj b = a->block();
|
262
262
|
|
263
263
|
append_indentation();
|
@@ -289,7 +289,7 @@ namespace Sass {
|
|
289
289
|
|
290
290
|
for (size_t i = 0, L = b->length(); i < L; ++i) {
|
291
291
|
Statement_Obj stm = b->get(i);
|
292
|
-
stm->perform(this);
|
292
|
+
if (stm) stm->perform(this);
|
293
293
|
if (i < L - 1 && format) append_special_linefeed();
|
294
294
|
}
|
295
295
|
|
@@ -309,7 +309,7 @@ namespace Sass {
|
|
309
309
|
|
310
310
|
void Output::operator()(String_Constant* s)
|
311
311
|
{
|
312
|
-
|
312
|
+
sass::string value(s->value());
|
313
313
|
if (!in_comment && !in_custom_property) {
|
314
314
|
append_token(string_to_output(value), s);
|
315
315
|
} else {
|
data/ext/libsass/src/output.hpp
CHANGED
@@ -20,17 +20,17 @@ namespace Sass {
|
|
20
20
|
virtual ~Output();
|
21
21
|
|
22
22
|
protected:
|
23
|
-
|
24
|
-
|
23
|
+
sass::string charset;
|
24
|
+
sass::vector<AST_Node*> top_nodes;
|
25
25
|
|
26
26
|
public:
|
27
27
|
OutputBuffer get_buffer(void);
|
28
28
|
|
29
29
|
virtual void operator()(Map*);
|
30
|
-
virtual void operator()(
|
31
|
-
virtual void operator()(
|
30
|
+
virtual void operator()(StyleRule*);
|
31
|
+
virtual void operator()(SupportsRule*);
|
32
32
|
virtual void operator()(CssMediaRule*);
|
33
|
-
virtual void operator()(
|
33
|
+
virtual void operator()(AtRule*);
|
34
34
|
virtual void operator()(Keyframe_Rule*);
|
35
35
|
virtual void operator()(Import*);
|
36
36
|
virtual void operator()(Comment*);
|
data/ext/libsass/src/parser.cpp
CHANGED
@@ -23,45 +23,39 @@ namespace Sass {
|
|
23
23
|
using namespace Constants;
|
24
24
|
using namespace Prelexer;
|
25
25
|
|
26
|
-
Parser Parser::from_c_str(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source, bool allow_parent)
|
27
|
-
{
|
28
|
-
pstate.offset.column = 0;
|
29
|
-
pstate.offset.line = 0;
|
30
|
-
Parser p(ctx, pstate, traces, allow_parent);
|
31
|
-
p.source = source ? source : beg;
|
32
|
-
p.position = beg ? beg : p.source;
|
33
|
-
p.end = p.position + strlen(p.position);
|
34
|
-
Block_Obj root = SASS_MEMORY_NEW(Block, pstate);
|
35
|
-
p.block_stack.push_back(root);
|
36
|
-
root->is_root(true);
|
37
|
-
return p;
|
38
|
-
}
|
39
26
|
|
40
|
-
Parser
|
27
|
+
Parser::Parser(SourceData* source, Context& ctx, Backtraces traces, bool allow_parent) :
|
28
|
+
SourceSpan(source),
|
29
|
+
ctx(ctx),
|
30
|
+
source(source),
|
31
|
+
begin(source->begin()),
|
32
|
+
position(source->begin()),
|
33
|
+
end(source->end()),
|
34
|
+
before_token(0, 0),
|
35
|
+
after_token(0, 0),
|
36
|
+
pstate(source->getSourceSpan()),
|
37
|
+
traces(traces),
|
38
|
+
indentation(0),
|
39
|
+
nestings(0),
|
40
|
+
allow_parent(allow_parent)
|
41
41
|
{
|
42
|
-
pstate.offset.column = 0;
|
43
|
-
pstate.offset.line = 0;
|
44
|
-
Parser p(ctx, pstate, traces, allow_parent);
|
45
|
-
p.source = source ? source : beg;
|
46
|
-
p.position = beg ? beg : p.source;
|
47
|
-
p.end = end ? end : p.position + strlen(p.position);
|
48
42
|
Block_Obj root = SASS_MEMORY_NEW(Block, pstate);
|
49
|
-
|
43
|
+
stack.push_back(Scope::Root);
|
44
|
+
block_stack.push_back(root);
|
50
45
|
root->is_root(true);
|
51
|
-
return p;
|
52
46
|
}
|
53
47
|
|
54
|
-
|
48
|
+
void Parser::advanceToNextToken() {
|
55
49
|
lex < css_comments >(false);
|
56
50
|
// advance to position
|
57
|
-
pstate += pstate.offset;
|
51
|
+
pstate.position += pstate.offset;
|
58
52
|
pstate.offset.column = 0;
|
59
53
|
pstate.offset.line = 0;
|
60
54
|
}
|
61
55
|
|
62
|
-
SelectorListObj Parser::parse_selector(
|
56
|
+
SelectorListObj Parser::parse_selector(SourceData* source, Context& ctx, Backtraces traces, bool allow_parent)
|
63
57
|
{
|
64
|
-
Parser p
|
58
|
+
Parser p(source, ctx, traces, allow_parent);
|
65
59
|
// ToDo: remap the source-map entries somehow
|
66
60
|
return p.parseSelectorList(false);
|
67
61
|
}
|
@@ -72,18 +66,6 @@ namespace Sass {
|
|
72
66
|
&& ! peek_css<exactly<'{'>>(start);
|
73
67
|
}
|
74
68
|
|
75
|
-
Parser Parser::from_token(Token t, Context& ctx, Backtraces traces, ParserState pstate, const char* source)
|
76
|
-
{
|
77
|
-
Parser p(ctx, pstate, traces);
|
78
|
-
p.source = source ? source : t.begin;
|
79
|
-
p.position = t.begin ? t.begin : p.source;
|
80
|
-
p.end = t.end ? t.end : p.position + strlen(p.position);
|
81
|
-
Block_Obj root = SASS_MEMORY_NEW(Block, pstate);
|
82
|
-
p.block_stack.push_back(root);
|
83
|
-
root->is_root(true);
|
84
|
-
return p;
|
85
|
-
}
|
86
|
-
|
87
69
|
/* main entry point to parse root block */
|
88
70
|
Block_Obj Parser::parse()
|
89
71
|
{
|
@@ -96,7 +78,7 @@ namespace Sass {
|
|
96
78
|
|
97
79
|
// report invalid utf8
|
98
80
|
if (it != end) {
|
99
|
-
pstate += Offset::init(position, it);
|
81
|
+
pstate.position += Offset::init(position, it);
|
100
82
|
traces.push_back(Backtrace(pstate));
|
101
83
|
throw Exception::InvalidSass(pstate, traces, "Invalid UTF-8 sequence");
|
102
84
|
}
|
@@ -107,7 +89,7 @@ namespace Sass {
|
|
107
89
|
// check seems a bit esoteric but works
|
108
90
|
if (ctx.resources.size() == 1) {
|
109
91
|
// apply headers only on very first include
|
110
|
-
ctx.apply_custom_headers(root,
|
92
|
+
ctx.apply_custom_headers(root, getPath(), pstate);
|
111
93
|
}
|
112
94
|
|
113
95
|
// parse children nodes
|
@@ -327,33 +309,33 @@ namespace Sass {
|
|
327
309
|
Import_Obj Parser::parse_import()
|
328
310
|
{
|
329
311
|
Import_Obj imp = SASS_MEMORY_NEW(Import, pstate);
|
330
|
-
|
312
|
+
sass::vector<std::pair<sass::string,Function_Call_Obj>> to_import;
|
331
313
|
bool first = true;
|
332
314
|
do {
|
333
315
|
while (lex< block_comment >());
|
334
316
|
if (lex< quoted_string >()) {
|
335
|
-
to_import.push_back(std::pair<
|
317
|
+
to_import.push_back(std::pair<sass::string,Function_Call_Obj>(sass::string(lexed), {}));
|
336
318
|
}
|
337
319
|
else if (lex< uri_prefix >()) {
|
338
320
|
Arguments_Obj args = SASS_MEMORY_NEW(Arguments, pstate);
|
339
|
-
Function_Call_Obj result = SASS_MEMORY_NEW(Function_Call, pstate,
|
321
|
+
Function_Call_Obj result = SASS_MEMORY_NEW(Function_Call, pstate, sass::string("url"), args);
|
340
322
|
|
341
323
|
if (lex< quoted_string >()) {
|
342
|
-
|
324
|
+
ExpressionObj quoted_url = parse_string();
|
343
325
|
args->append(SASS_MEMORY_NEW(Argument, quoted_url->pstate(), quoted_url));
|
344
326
|
}
|
345
327
|
else if (String_Obj string_url = parse_url_function_argument()) {
|
346
328
|
args->append(SASS_MEMORY_NEW(Argument, string_url->pstate(), string_url));
|
347
329
|
}
|
348
330
|
else if (peek < skip_over_scopes < exactly < '(' >, exactly < ')' > > >(position)) {
|
349
|
-
|
331
|
+
ExpressionObj braced_url = parse_list(); // parse_interpolated_chunk(lexed);
|
350
332
|
args->append(SASS_MEMORY_NEW(Argument, braced_url->pstate(), braced_url));
|
351
333
|
}
|
352
334
|
else {
|
353
335
|
error("malformed URL");
|
354
336
|
}
|
355
337
|
if (!lex< exactly<')'> >()) error("URI is missing ')'");
|
356
|
-
to_import.push_back(std::pair<
|
338
|
+
to_import.push_back(std::pair<sass::string, Function_Call_Obj>("", result));
|
357
339
|
}
|
358
340
|
else {
|
359
341
|
if (first) error("@import directive requires a url or quoted path");
|
@@ -372,9 +354,9 @@ namespace Sass {
|
|
372
354
|
imp->urls().push_back(location.second);
|
373
355
|
}
|
374
356
|
// check if custom importers want to take over the handling
|
375
|
-
else if (!ctx.call_importers(unquote(location.first),
|
357
|
+
else if (!ctx.call_importers(unquote(location.first), getPath(), pstate, imp)) {
|
376
358
|
// nobody wants it, so we do our import
|
377
|
-
ctx.import_url(imp, location.first,
|
359
|
+
ctx.import_url(imp, location.first, getPath());
|
378
360
|
}
|
379
361
|
}
|
380
362
|
|
@@ -383,12 +365,12 @@ namespace Sass {
|
|
383
365
|
|
384
366
|
Definition_Obj Parser::parse_definition(Definition::Type which_type)
|
385
367
|
{
|
386
|
-
|
368
|
+
sass::string which_str(lexed);
|
387
369
|
if (!lex< identifier >()) error("invalid name in " + which_str + " definition");
|
388
|
-
|
370
|
+
sass::string name(Util::normalize_underscores(lexed));
|
389
371
|
if (which_type == Definition::FUNCTION && (name == "and" || name == "or" || name == "not"))
|
390
372
|
{ error("Invalid function name \"" + name + "\"."); }
|
391
|
-
|
373
|
+
SourceSpan source_position_of_def = pstate;
|
392
374
|
Parameters_Obj params = parse_parameters();
|
393
375
|
if (which_type == Definition::MIXIN) stack.push_back(Scope::Mixin);
|
394
376
|
else stack.push_back(Scope::Function);
|
@@ -422,9 +404,9 @@ namespace Sass {
|
|
422
404
|
}
|
423
405
|
while (lex< alternatives < spaces, block_comment > >());
|
424
406
|
lex < variable >();
|
425
|
-
|
426
|
-
|
427
|
-
|
407
|
+
sass::string name(Util::normalize_underscores(lexed));
|
408
|
+
SourceSpan pos = pstate;
|
409
|
+
ExpressionObj val;
|
428
410
|
bool is_rest = false;
|
429
411
|
while (lex< alternatives < spaces, block_comment > >());
|
430
412
|
if (lex< exactly<':'> >()) { // there's a default value
|
@@ -468,16 +450,16 @@ namespace Sass {
|
|
468
450
|
Argument_Obj arg;
|
469
451
|
if (peek_css< sequence < variable, optional_css_comments, exactly<':'> > >()) {
|
470
452
|
lex_css< variable >();
|
471
|
-
|
472
|
-
|
453
|
+
sass::string name(Util::normalize_underscores(lexed));
|
454
|
+
SourceSpan p = pstate;
|
473
455
|
lex_css< exactly<':'> >();
|
474
|
-
|
456
|
+
ExpressionObj val = parse_space_list();
|
475
457
|
arg = SASS_MEMORY_NEW(Argument, p, val, name);
|
476
458
|
}
|
477
459
|
else {
|
478
460
|
bool is_arglist = false;
|
479
461
|
bool is_keyword = false;
|
480
|
-
|
462
|
+
ExpressionObj val = parse_space_list();
|
481
463
|
List* l = Cast<List>(val);
|
482
464
|
if (lex_css< exactly< ellipsis > >()) {
|
483
465
|
if (val->concrete_type() == Expression::MAP || (
|
@@ -492,13 +474,13 @@ namespace Sass {
|
|
492
474
|
|
493
475
|
Assignment_Obj Parser::parse_assignment()
|
494
476
|
{
|
495
|
-
|
496
|
-
|
477
|
+
sass::string name(Util::normalize_underscores(lexed));
|
478
|
+
SourceSpan var_source_position = pstate;
|
497
479
|
if (!lex< exactly<':'> >()) error("expected ':' after " + name + " in assignment statement");
|
498
480
|
if (peek_css< alternatives < exactly<';'>, end_of_file > >()) {
|
499
481
|
css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
|
500
482
|
}
|
501
|
-
|
483
|
+
ExpressionObj val;
|
502
484
|
Lookahead lookahead = lookahead_for_value(position);
|
503
485
|
if (lookahead.has_interpolants && lookahead.found) {
|
504
486
|
val = parse_value_schema(lookahead.found);
|
@@ -515,7 +497,7 @@ namespace Sass {
|
|
515
497
|
}
|
516
498
|
|
517
499
|
// a ruleset connects a selector and a block
|
518
|
-
|
500
|
+
StyleRuleObj Parser::parse_ruleset(Lookahead lookahead)
|
519
501
|
{
|
520
502
|
NESTING_GUARD(nestings);
|
521
503
|
// inherit is_root from parent block
|
@@ -524,7 +506,7 @@ namespace Sass {
|
|
524
506
|
// make sure to move up the the last position
|
525
507
|
lex < optional_css_whitespace >(false, true);
|
526
508
|
// create the connector object (add parts later)
|
527
|
-
|
509
|
+
StyleRuleObj ruleset = SASS_MEMORY_NEW(StyleRule, pstate);
|
528
510
|
// parse selector static or as schema to be evaluated later
|
529
511
|
if (lookahead.parsable) {
|
530
512
|
ruleset->selector(parseSelectorList(false));
|
@@ -569,9 +551,9 @@ namespace Sass {
|
|
569
551
|
if (const char* p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, end_of_selector)) {
|
570
552
|
// accumulate the preceding segment if the position has advanced
|
571
553
|
if (i < p) {
|
572
|
-
|
554
|
+
sass::string parsed(i, p);
|
573
555
|
String_Constant_Obj str = SASS_MEMORY_NEW(String_Constant, pstate, parsed);
|
574
|
-
pstate += Offset(parsed);
|
556
|
+
pstate.position += Offset(parsed);
|
575
557
|
str->update_pstate(pstate);
|
576
558
|
schema->append(str);
|
577
559
|
}
|
@@ -584,15 +566,16 @@ namespace Sass {
|
|
584
566
|
css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
|
585
567
|
}
|
586
568
|
// pass inner expression to the parser to resolve nested interpolations
|
587
|
-
|
588
|
-
|
569
|
+
LocalOption<const char*> partEnd(end, j);
|
570
|
+
LocalOption<const char*> partBeg(position, p + 2);
|
571
|
+
ExpressionObj interpolant = parse_list();
|
589
572
|
// set status on the list expression
|
590
573
|
interpolant->is_interpolant(true);
|
591
574
|
// schema->has_interpolants(true);
|
592
575
|
// add to the string schema
|
593
576
|
schema->append(interpolant);
|
594
577
|
// advance parser state
|
595
|
-
pstate.add(p+2, j);
|
578
|
+
pstate.position.add(p+2, j);
|
596
579
|
// advance position
|
597
580
|
i = j;
|
598
581
|
}
|
@@ -601,9 +584,9 @@ namespace Sass {
|
|
601
584
|
else {
|
602
585
|
// make sure to add the last bits of the string up to the end (if any)
|
603
586
|
if (i < end_of_selector) {
|
604
|
-
|
587
|
+
sass::string parsed(i, end_of_selector);
|
605
588
|
String_Constant_Obj str = SASS_MEMORY_NEW(String_Constant, pstate, parsed);
|
606
|
-
pstate += Offset(parsed);
|
589
|
+
pstate.position += Offset(parsed);
|
607
590
|
str->update_pstate(pstate);
|
608
591
|
i = end_of_selector;
|
609
592
|
schema->append(str);
|
@@ -620,7 +603,7 @@ namespace Sass {
|
|
620
603
|
selector_schema->update_pstate(pstate);
|
621
604
|
schema->update_pstate(pstate);
|
622
605
|
|
623
|
-
after_token = before_token = pstate;
|
606
|
+
after_token = before_token = pstate.position;
|
624
607
|
|
625
608
|
// return parsed result
|
626
609
|
return selector_schema.detach();
|
@@ -644,9 +627,9 @@ namespace Sass {
|
|
644
627
|
// lex identifier into `lexed` var
|
645
628
|
lex_identifier(); // may error out
|
646
629
|
// normalize underscores to hyphens
|
647
|
-
|
630
|
+
sass::string name(Util::normalize_underscores(lexed));
|
648
631
|
// create the initial mixin call object
|
649
|
-
Mixin_Call_Obj call = SASS_MEMORY_NEW(Mixin_Call, pstate, name, {}
|
632
|
+
Mixin_Call_Obj call = SASS_MEMORY_NEW(Mixin_Call, pstate, name, Arguments_Obj{});
|
650
633
|
// parse mandatory arguments
|
651
634
|
call->arguments(parse_arguments());
|
652
635
|
// parse using and optional block parameters
|
@@ -677,13 +660,13 @@ namespace Sass {
|
|
677
660
|
{
|
678
661
|
lex < css_comments >(false);
|
679
662
|
if (lex< class_name >()) {
|
680
|
-
return SASS_MEMORY_NEW(
|
663
|
+
return SASS_MEMORY_NEW(ClassSelector, pstate, lexed);
|
681
664
|
}
|
682
665
|
else if (lex< id_name >()) {
|
683
|
-
return SASS_MEMORY_NEW(
|
666
|
+
return SASS_MEMORY_NEW(IDSelector, pstate, lexed);
|
684
667
|
}
|
685
668
|
else if (lex< alternatives < variable, number, static_reference_combinator > >()) {
|
686
|
-
return SASS_MEMORY_NEW(
|
669
|
+
return SASS_MEMORY_NEW(TypeSelector, pstate, lexed);
|
687
670
|
}
|
688
671
|
else if (peek< pseudo_not >()) {
|
689
672
|
return parse_negated_selector2();
|
@@ -698,7 +681,7 @@ namespace Sass {
|
|
698
681
|
return parse_attribute_selector();
|
699
682
|
}
|
700
683
|
else if (lex< placeholder >()) {
|
701
|
-
return SASS_MEMORY_NEW(
|
684
|
+
return SASS_MEMORY_NEW(PlaceholderSelector, pstate, lexed);
|
702
685
|
}
|
703
686
|
else {
|
704
687
|
css_error("Invalid CSS", " after ", ": expected selector, was ");
|
@@ -707,18 +690,18 @@ namespace Sass {
|
|
707
690
|
return {};
|
708
691
|
}
|
709
692
|
|
710
|
-
|
693
|
+
PseudoSelectorObj Parser::parse_negated_selector2()
|
711
694
|
{
|
712
695
|
lex< pseudo_not >();
|
713
|
-
|
714
|
-
|
696
|
+
sass::string name(lexed);
|
697
|
+
SourceSpan nsource_position = pstate;
|
715
698
|
SelectorListObj negated = parseSelectorList(true);
|
716
699
|
if (!lex< exactly<')'> >()) {
|
717
700
|
error("negated selector is missing ')'");
|
718
701
|
}
|
719
702
|
name.erase(name.size() - 1);
|
720
703
|
|
721
|
-
|
704
|
+
PseudoSelector* sel = SASS_MEMORY_NEW(PseudoSelector, nsource_position, name.substr(1));
|
722
705
|
sel->selector(negated);
|
723
706
|
return sel;
|
724
707
|
}
|
@@ -732,7 +715,7 @@ namespace Sass {
|
|
732
715
|
|
733
716
|
// Lex one or two colon characters
|
734
717
|
if (lex<pseudo_prefix>()) {
|
735
|
-
|
718
|
+
sass::string colons(lexed);
|
736
719
|
// Check if it is a pseudo element
|
737
720
|
bool element = colons.size() == 2;
|
738
721
|
|
@@ -744,16 +727,16 @@ namespace Sass {
|
|
744
727
|
> >())
|
745
728
|
{
|
746
729
|
|
747
|
-
|
730
|
+
sass::string name(lexed);
|
748
731
|
name.erase(name.size() - 1);
|
749
|
-
|
732
|
+
SourceSpan p = pstate;
|
750
733
|
|
751
734
|
// specially parse nth-child pseudo selectors
|
752
735
|
if (lex_css < sequence < binomial, word_boundary >>()) {
|
753
|
-
|
736
|
+
sass::string parsed(lexed); // always compacting binominals (as dart-sass)
|
754
737
|
parsed.erase(std::unique(parsed.begin(), parsed.end(), BothAreSpaces), parsed.end());
|
755
738
|
String_Constant_Obj arg = SASS_MEMORY_NEW(String_Constant, pstate, parsed);
|
756
|
-
|
739
|
+
PseudoSelector* pseudo = SASS_MEMORY_NEW(PseudoSelector, p, name, element);
|
757
740
|
if (lex < sequence < css_whitespace, insensitive < of_kwd >>>(false)) {
|
758
741
|
pseudo->selector(parseSelectorList(true));
|
759
742
|
}
|
@@ -767,19 +750,19 @@ namespace Sass {
|
|
767
750
|
css_error("Invalid CSS", " after ", ": expected An+B expression, was ");
|
768
751
|
}
|
769
752
|
|
770
|
-
|
753
|
+
sass::string unvendored = Util::unvendor(name);
|
771
754
|
|
772
755
|
if (unvendored == "not" || unvendored == "matches" || unvendored == "current" || unvendored == "any" || unvendored == "has" || unvendored == "host" || unvendored == "host-context" || unvendored == "slotted") {
|
773
756
|
if (SelectorListObj wrapped = parseSelectorList(true)) {
|
774
757
|
if (wrapped && lex_css< exactly<')'> >()) {
|
775
|
-
|
758
|
+
PseudoSelector* pseudo = SASS_MEMORY_NEW(PseudoSelector, p, name, element);
|
776
759
|
pseudo->selector(wrapped);
|
777
760
|
return pseudo;
|
778
761
|
}
|
779
762
|
}
|
780
763
|
} else {
|
781
764
|
String_Schema_Obj arg = parse_css_variable_value();
|
782
|
-
|
765
|
+
PseudoSelector* pseudo = SASS_MEMORY_NEW(PseudoSelector, p, name, element);
|
783
766
|
pseudo->argument(arg);
|
784
767
|
|
785
768
|
if (lex_css< exactly<')'> >()) {
|
@@ -792,7 +775,7 @@ namespace Sass {
|
|
792
775
|
// EO if pseudo selector
|
793
776
|
|
794
777
|
else if (lex < sequence< optional < pseudo_prefix >, identifier > >()) {
|
795
|
-
return SASS_MEMORY_NEW(
|
778
|
+
return SASS_MEMORY_NEW(PseudoSelector, pstate, lexed, element);
|
796
779
|
}
|
797
780
|
else if (lex < pseudo_prefix >()) {
|
798
781
|
css_error("Invalid CSS", " after ", ": expected pseudoclass or pseudoelement, was ");
|
@@ -821,23 +804,23 @@ namespace Sass {
|
|
821
804
|
return sequence < insensitive<'i'>, re_attr_sensitive_close >(src);
|
822
805
|
}
|
823
806
|
|
824
|
-
|
807
|
+
AttributeSelectorObj Parser::parse_attribute_selector()
|
825
808
|
{
|
826
|
-
|
809
|
+
SourceSpan p = pstate;
|
827
810
|
if (!lex_css< attribute_name >()) error("invalid attribute name in attribute selector");
|
828
|
-
|
811
|
+
sass::string name(lexed);
|
829
812
|
if (lex_css< re_attr_sensitive_close >()) {
|
830
|
-
return SASS_MEMORY_NEW(
|
813
|
+
return SASS_MEMORY_NEW(AttributeSelector, p, name, "", String_Obj{});
|
831
814
|
}
|
832
815
|
else if (lex_css< re_attr_insensitive_close >()) {
|
833
816
|
char modifier = lexed.begin[0];
|
834
|
-
return SASS_MEMORY_NEW(
|
817
|
+
return SASS_MEMORY_NEW(AttributeSelector, p, name, "", String_Obj{}, modifier);
|
835
818
|
}
|
836
819
|
if (!lex_css< alternatives< exact_match, class_match, dash_match,
|
837
820
|
prefix_match, suffix_match, substring_match > >()) {
|
838
821
|
error("invalid operator in attribute selector for " + name);
|
839
822
|
}
|
840
|
-
|
823
|
+
sass::string matcher(lexed);
|
841
824
|
|
842
825
|
String_Obj value;
|
843
826
|
if (lex_css< identifier >()) {
|
@@ -851,11 +834,11 @@ namespace Sass {
|
|
851
834
|
}
|
852
835
|
|
853
836
|
if (lex_css< re_attr_sensitive_close >()) {
|
854
|
-
return SASS_MEMORY_NEW(
|
837
|
+
return SASS_MEMORY_NEW(AttributeSelector, p, name, matcher, value, 0);
|
855
838
|
}
|
856
839
|
else if (lex_css< re_attr_insensitive_close >()) {
|
857
840
|
char modifier = lexed.begin[0];
|
858
|
-
return SASS_MEMORY_NEW(
|
841
|
+
return SASS_MEMORY_NEW(AttributeSelector, p, name, matcher, value, modifier);
|
859
842
|
}
|
860
843
|
error("unterminated attribute selector for " + name);
|
861
844
|
return {}; // to satisfy compilers (error must not return)
|
@@ -878,12 +861,12 @@ namespace Sass {
|
|
878
861
|
String_Obj prop;
|
879
862
|
bool is_custom_property = false;
|
880
863
|
if (lex< sequence< optional< exactly<'*'> >, identifier_schema > >()) {
|
881
|
-
const
|
864
|
+
const sass::string property(lexed);
|
882
865
|
is_custom_property = property.compare(0, 2, "--") == 0;
|
883
866
|
prop = parse_identifier_schema();
|
884
867
|
}
|
885
868
|
else if (lex< sequence< optional< exactly<'*'> >, identifier, zero_plus< block_comment > > >()) {
|
886
|
-
const
|
869
|
+
const sass::string property(lexed);
|
887
870
|
is_custom_property = property.compare(0, 2, "--") == 0;
|
888
871
|
prop = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
|
889
872
|
}
|
@@ -891,7 +874,7 @@ namespace Sass {
|
|
891
874
|
css_error("Invalid CSS", " after ", ": expected \"}\", was ");
|
892
875
|
}
|
893
876
|
bool is_indented = true;
|
894
|
-
const
|
877
|
+
const sass::string property(lexed);
|
895
878
|
if (!lex_css< one_plus< exactly<':'> > >()) error("property \"" + escape_string(property) + "\" must be followed by a ':'");
|
896
879
|
if (!is_custom_property && match< sequence< optional_css_comments, exactly<';'> > >()) error("style declaration must contain a value");
|
897
880
|
if (match< sequence< optional_css_comments, exactly<'{'> > >()) is_indented = false; // don't indent if value is empty
|
@@ -903,7 +886,7 @@ namespace Sass {
|
|
903
886
|
return SASS_MEMORY_NEW(Declaration, prop->pstate(), prop, parse_static_value()/*, lex<kwd_important>()*/);
|
904
887
|
}
|
905
888
|
else {
|
906
|
-
|
889
|
+
ExpressionObj value;
|
907
890
|
Lookahead lookahead = lookahead_for_value(position);
|
908
891
|
if (lookahead.found) {
|
909
892
|
if (lookahead.has_interpolants) {
|
@@ -928,10 +911,10 @@ namespace Sass {
|
|
928
911
|
}
|
929
912
|
}
|
930
913
|
|
931
|
-
|
914
|
+
ExpressionObj Parser::parse_map()
|
932
915
|
{
|
933
916
|
NESTING_GUARD(nestings);
|
934
|
-
|
917
|
+
ExpressionObj key = parse_list();
|
935
918
|
List_Obj map = SASS_MEMORY_NEW(List, pstate, 0, SASS_HASH);
|
936
919
|
|
937
920
|
// it's not a map so return the lexed value as a list value
|
@@ -943,7 +926,7 @@ namespace Sass {
|
|
943
926
|
css_error("Invalid CSS", " after ", ": expected \")\", was ");
|
944
927
|
}
|
945
928
|
|
946
|
-
|
929
|
+
ExpressionObj value = parse_space_list();
|
947
930
|
|
948
931
|
map->append(key);
|
949
932
|
map->append(value);
|
@@ -965,14 +948,14 @@ namespace Sass {
|
|
965
948
|
map->append(value);
|
966
949
|
}
|
967
950
|
|
968
|
-
|
969
|
-
ps.offset = pstate - ps + pstate.offset;
|
951
|
+
SourceSpan ps = map->pstate();
|
952
|
+
ps.offset = pstate.position - ps.position + pstate.offset;
|
970
953
|
map->pstate(ps);
|
971
954
|
|
972
955
|
return map;
|
973
956
|
}
|
974
957
|
|
975
|
-
|
958
|
+
ExpressionObj Parser::parse_bracket_list()
|
976
959
|
{
|
977
960
|
NESTING_GUARD(nestings);
|
978
961
|
// check if we have an empty list
|
@@ -986,7 +969,7 @@ namespace Sass {
|
|
986
969
|
bool has_paren = peek_css< exactly<'('> >() != NULL;
|
987
970
|
|
988
971
|
// now try to parse a space list
|
989
|
-
|
972
|
+
ExpressionObj list = parse_space_list();
|
990
973
|
// if it's a singleton, return it (don't wrap it)
|
991
974
|
if (!peek_css< exactly<','> >(position)) {
|
992
975
|
List_Obj l = Cast<List>(list);
|
@@ -1019,14 +1002,14 @@ namespace Sass {
|
|
1019
1002
|
// parse list returns either a space separated list,
|
1020
1003
|
// a comma separated list or any bare expression found.
|
1021
1004
|
// so to speak: we unwrap items from lists if possible here!
|
1022
|
-
|
1005
|
+
ExpressionObj Parser::parse_list(bool delayed)
|
1023
1006
|
{
|
1024
1007
|
NESTING_GUARD(nestings);
|
1025
1008
|
return parse_comma_list(delayed);
|
1026
1009
|
}
|
1027
1010
|
|
1028
1011
|
// will return singletons unwrapped
|
1029
|
-
|
1012
|
+
ExpressionObj Parser::parse_comma_list(bool delayed)
|
1030
1013
|
{
|
1031
1014
|
NESTING_GUARD(nestings);
|
1032
1015
|
// check if we have an empty list
|
@@ -1038,7 +1021,7 @@ namespace Sass {
|
|
1038
1021
|
}
|
1039
1022
|
|
1040
1023
|
// now try to parse a space list
|
1041
|
-
|
1024
|
+
ExpressionObj list = parse_space_list();
|
1042
1025
|
// if it's a singleton, return it (don't wrap it)
|
1043
1026
|
if (!peek_css< exactly<','> >(position)) {
|
1044
1027
|
// set_delay doesn't apply to list children
|
@@ -1066,10 +1049,10 @@ namespace Sass {
|
|
1066
1049
|
// EO parse_comma_list
|
1067
1050
|
|
1068
1051
|
// will return singletons unwrapped
|
1069
|
-
|
1052
|
+
ExpressionObj Parser::parse_space_list()
|
1070
1053
|
{
|
1071
1054
|
NESTING_GUARD(nestings);
|
1072
|
-
|
1055
|
+
ExpressionObj disj1 = parse_disjunction();
|
1073
1056
|
// if it's a singleton, return it (don't wrap it)
|
1074
1057
|
if (peek_css< space_list_terminator >(position)
|
1075
1058
|
) {
|
@@ -1091,60 +1074,60 @@ namespace Sass {
|
|
1091
1074
|
// EO parse_space_list
|
1092
1075
|
|
1093
1076
|
// parse logical OR operation
|
1094
|
-
|
1077
|
+
ExpressionObj Parser::parse_disjunction()
|
1095
1078
|
{
|
1096
1079
|
NESTING_GUARD(nestings);
|
1097
1080
|
advanceToNextToken();
|
1098
|
-
|
1081
|
+
SourceSpan state(pstate);
|
1099
1082
|
// parse the left hand side conjunction
|
1100
|
-
|
1083
|
+
ExpressionObj conj = parse_conjunction();
|
1101
1084
|
// parse multiple right hand sides
|
1102
|
-
|
1085
|
+
sass::vector<ExpressionObj> operands;
|
1103
1086
|
while (lex_css< kwd_or >())
|
1104
1087
|
operands.push_back(parse_conjunction());
|
1105
1088
|
// if it's a singleton, return it directly
|
1106
1089
|
if (operands.size() == 0) return conj;
|
1107
1090
|
// fold all operands into one binary expression
|
1108
|
-
|
1109
|
-
state.offset = pstate - state + pstate.offset;
|
1091
|
+
ExpressionObj ex = fold_operands(conj, operands, { Sass_OP::OR });
|
1092
|
+
state.offset = pstate.position - state.position + pstate.offset;
|
1110
1093
|
ex->pstate(state);
|
1111
1094
|
return ex;
|
1112
1095
|
}
|
1113
1096
|
// EO parse_disjunction
|
1114
1097
|
|
1115
1098
|
// parse logical AND operation
|
1116
|
-
|
1099
|
+
ExpressionObj Parser::parse_conjunction()
|
1117
1100
|
{
|
1118
1101
|
NESTING_GUARD(nestings);
|
1119
1102
|
advanceToNextToken();
|
1120
|
-
|
1103
|
+
SourceSpan state(pstate);
|
1121
1104
|
// parse the left hand side relation
|
1122
|
-
|
1105
|
+
ExpressionObj rel = parse_relation();
|
1123
1106
|
// parse multiple right hand sides
|
1124
|
-
|
1107
|
+
sass::vector<ExpressionObj> operands;
|
1125
1108
|
while (lex_css< kwd_and >()) {
|
1126
1109
|
operands.push_back(parse_relation());
|
1127
1110
|
}
|
1128
1111
|
// if it's a singleton, return it directly
|
1129
1112
|
if (operands.size() == 0) return rel;
|
1130
1113
|
// fold all operands into one binary expression
|
1131
|
-
|
1132
|
-
state.offset = pstate - state + pstate.offset;
|
1114
|
+
ExpressionObj ex = fold_operands(rel, operands, { Sass_OP::AND });
|
1115
|
+
state.offset = pstate.position - state.position + pstate.offset;
|
1133
1116
|
ex->pstate(state);
|
1134
1117
|
return ex;
|
1135
1118
|
}
|
1136
1119
|
// EO parse_conjunction
|
1137
1120
|
|
1138
1121
|
// parse comparison operations
|
1139
|
-
|
1122
|
+
ExpressionObj Parser::parse_relation()
|
1140
1123
|
{
|
1141
1124
|
NESTING_GUARD(nestings);
|
1142
1125
|
advanceToNextToken();
|
1143
|
-
|
1126
|
+
SourceSpan state(pstate);
|
1144
1127
|
// parse the left hand side expression
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1128
|
+
ExpressionObj lhs = parse_expression();
|
1129
|
+
sass::vector<ExpressionObj> operands;
|
1130
|
+
sass::vector<Operand> operators;
|
1148
1131
|
// if it's a singleton, return it (don't wrap it)
|
1149
1132
|
while (peek< alternatives <
|
1150
1133
|
kwd_eq,
|
@@ -1177,8 +1160,8 @@ namespace Sass {
|
|
1177
1160
|
// correctly set to zero. After folding we also unwrap
|
1178
1161
|
// single nested items. So we cannot set delay on the
|
1179
1162
|
// returned result here, as we have lost nestings ...
|
1180
|
-
|
1181
|
-
state.offset = pstate - state + pstate.offset;
|
1163
|
+
ExpressionObj ex = fold_operands(lhs, operands, operators);
|
1164
|
+
state.offset = pstate.position - state.position + pstate.offset;
|
1182
1165
|
ex->pstate(state);
|
1183
1166
|
return ex;
|
1184
1167
|
}
|
@@ -1189,15 +1172,15 @@ namespace Sass {
|
|
1189
1172
|
// called from parse_for_directive
|
1190
1173
|
// called from parse_media_expression
|
1191
1174
|
// parse addition and subtraction operations
|
1192
|
-
|
1175
|
+
ExpressionObj Parser::parse_expression()
|
1193
1176
|
{
|
1194
1177
|
NESTING_GUARD(nestings);
|
1195
1178
|
advanceToNextToken();
|
1196
|
-
|
1179
|
+
SourceSpan state(pstate);
|
1197
1180
|
// parses multiple add and subtract operations
|
1198
1181
|
// NOTE: make sure that identifiers starting with
|
1199
1182
|
// NOTE: dashes do NOT count as subtract operation
|
1200
|
-
|
1183
|
+
ExpressionObj lhs = parse_operators();
|
1201
1184
|
// if it's a singleton, return it (don't wrap it)
|
1202
1185
|
if (!(peek_css< exactly<'+'> >(position) ||
|
1203
1186
|
// condition is a bit mysterious, but some combinations should not be counted as operations
|
@@ -1206,8 +1189,8 @@ namespace Sass {
|
|
1206
1189
|
peek< sequence < zero_plus < exactly <'-' > >, identifier > >(position))
|
1207
1190
|
{ return lhs; }
|
1208
1191
|
|
1209
|
-
|
1210
|
-
|
1192
|
+
sass::vector<ExpressionObj> operands;
|
1193
|
+
sass::vector<Operand> operators;
|
1211
1194
|
bool left_ws = peek < css_comments >() != NULL;
|
1212
1195
|
while (
|
1213
1196
|
lex_css< exactly<'+'> >() ||
|
@@ -1226,22 +1209,22 @@ namespace Sass {
|
|
1226
1209
|
}
|
1227
1210
|
|
1228
1211
|
if (operands.size() == 0) return lhs;
|
1229
|
-
|
1230
|
-
state.offset = pstate - state + pstate.offset;
|
1212
|
+
ExpressionObj ex = fold_operands(lhs, operands, operators);
|
1213
|
+
state.offset = pstate.position - state.position + pstate.offset;
|
1231
1214
|
ex->pstate(state);
|
1232
1215
|
return ex;
|
1233
1216
|
}
|
1234
1217
|
|
1235
1218
|
// parse addition and subtraction operations
|
1236
|
-
|
1219
|
+
ExpressionObj Parser::parse_operators()
|
1237
1220
|
{
|
1238
1221
|
NESTING_GUARD(nestings);
|
1239
1222
|
advanceToNextToken();
|
1240
|
-
|
1241
|
-
|
1223
|
+
SourceSpan state(pstate);
|
1224
|
+
ExpressionObj factor = parse_factor();
|
1242
1225
|
// if it's a singleton, return it (don't wrap it)
|
1243
|
-
|
1244
|
-
|
1226
|
+
sass::vector<ExpressionObj> operands; // factors
|
1227
|
+
sass::vector<Operand> operators; // ops
|
1245
1228
|
// lex operations to apply to lhs
|
1246
1229
|
const char* left_ws = peek < css_comments >();
|
1247
1230
|
while (lex_css< class_char< static_ops > >()) {
|
@@ -1256,8 +1239,8 @@ namespace Sass {
|
|
1256
1239
|
left_ws = peek < css_comments >();
|
1257
1240
|
}
|
1258
1241
|
// operands and operators to binary expression
|
1259
|
-
|
1260
|
-
state.offset = pstate - state + pstate.offset;
|
1242
|
+
ExpressionObj ex = fold_operands(factor, operands, operators);
|
1243
|
+
state.offset = pstate.position - state.position + pstate.offset;
|
1261
1244
|
ex->pstate(state);
|
1262
1245
|
return ex;
|
1263
1246
|
}
|
@@ -1266,13 +1249,13 @@ namespace Sass {
|
|
1266
1249
|
|
1267
1250
|
// called from parse_operators
|
1268
1251
|
// called from parse_value_schema
|
1269
|
-
|
1252
|
+
ExpressionObj Parser::parse_factor()
|
1270
1253
|
{
|
1271
1254
|
NESTING_GUARD(nestings);
|
1272
1255
|
lex < css_comments >(false);
|
1273
1256
|
if (lex_css< exactly<'('> >()) {
|
1274
1257
|
// parse_map may return a list
|
1275
|
-
|
1258
|
+
ExpressionObj value = parse_map();
|
1276
1259
|
// lex the expected closing parenthesis
|
1277
1260
|
if (!lex_css< exactly<')'> >()) error("unclosed parenthesis");
|
1278
1261
|
// expression can be evaluated
|
@@ -1280,7 +1263,7 @@ namespace Sass {
|
|
1280
1263
|
}
|
1281
1264
|
else if (lex_css< exactly<'['> >()) {
|
1282
1265
|
// explicit bracketed
|
1283
|
-
|
1266
|
+
ExpressionObj value = parse_bracket_list();
|
1284
1267
|
// lex the expected closing square bracket
|
1285
1268
|
if (!lex_css< exactly<']'> >()) error("unclosed squared bracket");
|
1286
1269
|
return value;
|
@@ -1342,7 +1325,7 @@ namespace Sass {
|
|
1342
1325
|
}
|
1343
1326
|
}
|
1344
1327
|
|
1345
|
-
bool number_has_zero(const
|
1328
|
+
bool number_has_zero(const sass::string& parsed)
|
1346
1329
|
{
|
1347
1330
|
size_t L = parsed.length();
|
1348
1331
|
return !( (L > 0 && parsed.substr(0, 1) == ".") ||
|
@@ -1351,7 +1334,7 @@ namespace Sass {
|
|
1351
1334
|
(L > 2 && parsed.substr(0, 3) == "-0.") );
|
1352
1335
|
}
|
1353
1336
|
|
1354
|
-
Number* Parser::lexed_number(const
|
1337
|
+
Number* Parser::lexed_number(const SourceSpan& pstate, const sass::string& parsed)
|
1355
1338
|
{
|
1356
1339
|
Number* nr = SASS_MEMORY_NEW(Number,
|
1357
1340
|
pstate,
|
@@ -1363,7 +1346,7 @@ namespace Sass {
|
|
1363
1346
|
return nr;
|
1364
1347
|
}
|
1365
1348
|
|
1366
|
-
Number* Parser::lexed_percentage(const
|
1349
|
+
Number* Parser::lexed_percentage(const SourceSpan& pstate, const sass::string& parsed)
|
1367
1350
|
{
|
1368
1351
|
Number* nr = SASS_MEMORY_NEW(Number,
|
1369
1352
|
pstate,
|
@@ -1375,17 +1358,17 @@ namespace Sass {
|
|
1375
1358
|
return nr;
|
1376
1359
|
}
|
1377
1360
|
|
1378
|
-
Number* Parser::lexed_dimension(const
|
1361
|
+
Number* Parser::lexed_dimension(const SourceSpan& pstate, const sass::string& parsed)
|
1379
1362
|
{
|
1380
1363
|
size_t L = parsed.length();
|
1381
1364
|
size_t num_pos = parsed.find_first_not_of(" \n\r\t");
|
1382
|
-
if (num_pos ==
|
1365
|
+
if (num_pos == sass::string::npos) num_pos = L;
|
1383
1366
|
size_t unit_pos = parsed.find_first_not_of("-+0123456789.", num_pos);
|
1384
1367
|
if (parsed[unit_pos] == 'e' && is_number(parsed[unit_pos+1]) ) {
|
1385
1368
|
unit_pos = parsed.find_first_not_of("-+0123456789.", ++ unit_pos);
|
1386
1369
|
}
|
1387
|
-
if (unit_pos ==
|
1388
|
-
const
|
1370
|
+
if (unit_pos == sass::string::npos) unit_pos = L;
|
1371
|
+
const sass::string& num = parsed.substr(num_pos, unit_pos - num_pos);
|
1389
1372
|
Number* nr = SASS_MEMORY_NEW(Number,
|
1390
1373
|
pstate,
|
1391
1374
|
sass_strtod(num.c_str()),
|
@@ -1396,18 +1379,18 @@ namespace Sass {
|
|
1396
1379
|
return nr;
|
1397
1380
|
}
|
1398
1381
|
|
1399
|
-
Value* Parser::lexed_hex_color(const
|
1382
|
+
Value* Parser::lexed_hex_color(const SourceSpan& pstate, const sass::string& parsed)
|
1400
1383
|
{
|
1401
1384
|
Color_RGBA* color = NULL;
|
1402
1385
|
if (parsed[0] != '#') {
|
1403
1386
|
return SASS_MEMORY_NEW(String_Quoted, pstate, parsed);
|
1404
1387
|
}
|
1405
1388
|
// chop off the '#'
|
1406
|
-
|
1389
|
+
sass::string hext(parsed.substr(1));
|
1407
1390
|
if (parsed.length() == 4) {
|
1408
|
-
|
1409
|
-
|
1410
|
-
|
1391
|
+
sass::string r(2, parsed[1]);
|
1392
|
+
sass::string g(2, parsed[2]);
|
1393
|
+
sass::string b(2, parsed[3]);
|
1411
1394
|
color = SASS_MEMORY_NEW(Color_RGBA,
|
1412
1395
|
pstate,
|
1413
1396
|
static_cast<double>(strtol(r.c_str(), NULL, 16)),
|
@@ -1417,10 +1400,10 @@ namespace Sass {
|
|
1417
1400
|
parsed);
|
1418
1401
|
}
|
1419
1402
|
else if (parsed.length() == 5) {
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1403
|
+
sass::string r(2, parsed[1]);
|
1404
|
+
sass::string g(2, parsed[2]);
|
1405
|
+
sass::string b(2, parsed[3]);
|
1406
|
+
sass::string a(2, parsed[4]);
|
1424
1407
|
color = SASS_MEMORY_NEW(Color_RGBA,
|
1425
1408
|
pstate,
|
1426
1409
|
static_cast<double>(strtol(r.c_str(), NULL, 16)),
|
@@ -1430,9 +1413,9 @@ namespace Sass {
|
|
1430
1413
|
parsed);
|
1431
1414
|
}
|
1432
1415
|
else if (parsed.length() == 7) {
|
1433
|
-
|
1434
|
-
|
1435
|
-
|
1416
|
+
sass::string r(parsed.substr(1,2));
|
1417
|
+
sass::string g(parsed.substr(3,2));
|
1418
|
+
sass::string b(parsed.substr(5,2));
|
1436
1419
|
color = SASS_MEMORY_NEW(Color_RGBA,
|
1437
1420
|
pstate,
|
1438
1421
|
static_cast<double>(strtol(r.c_str(), NULL, 16)),
|
@@ -1442,10 +1425,10 @@ namespace Sass {
|
|
1442
1425
|
parsed);
|
1443
1426
|
}
|
1444
1427
|
else if (parsed.length() == 9) {
|
1445
|
-
|
1446
|
-
|
1447
|
-
|
1448
|
-
|
1428
|
+
sass::string r(parsed.substr(1,2));
|
1429
|
+
sass::string g(parsed.substr(3,2));
|
1430
|
+
sass::string b(parsed.substr(5,2));
|
1431
|
+
sass::string a(parsed.substr(7,2));
|
1449
1432
|
color = SASS_MEMORY_NEW(Color_RGBA,
|
1450
1433
|
pstate,
|
1451
1434
|
static_cast<double>(strtol(r.c_str(), NULL, 16)),
|
@@ -1459,7 +1442,7 @@ namespace Sass {
|
|
1459
1442
|
return color;
|
1460
1443
|
}
|
1461
1444
|
|
1462
|
-
Value* Parser::color_or_string(const
|
1445
|
+
Value* Parser::color_or_string(const sass::string& lexed) const
|
1463
1446
|
{
|
1464
1447
|
if (auto color = name_to_color(lexed)) {
|
1465
1448
|
auto c = SASS_MEMORY_NEW(Color_RGBA, color);
|
@@ -1473,7 +1456,7 @@ namespace Sass {
|
|
1473
1456
|
}
|
1474
1457
|
|
1475
1458
|
// parse one value for a list
|
1476
|
-
|
1459
|
+
ExpressionObj Parser::parse_value()
|
1477
1460
|
{
|
1478
1461
|
lex< css_comments >(false);
|
1479
1462
|
if (lex< ampersand >())
|
@@ -1560,7 +1543,7 @@ namespace Sass {
|
|
1560
1543
|
find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, chunk.end);
|
1561
1544
|
|
1562
1545
|
if (!p) {
|
1563
|
-
String_Quoted* str_quoted = SASS_MEMORY_NEW(String_Quoted, pstate,
|
1546
|
+
String_Quoted* str_quoted = SASS_MEMORY_NEW(String_Quoted, pstate, sass::string(i, chunk.end), 0, false, false, true, css);
|
1564
1547
|
if (!constant && str_quoted->quote_mark()) str_quoted->quote_mark('*');
|
1565
1548
|
return str_quoted;
|
1566
1549
|
}
|
@@ -1573,7 +1556,7 @@ namespace Sass {
|
|
1573
1556
|
if (p) {
|
1574
1557
|
if (i < p) {
|
1575
1558
|
// accumulate the preceding segment if it's nonempty
|
1576
|
-
schema->append(SASS_MEMORY_NEW(String_Constant, pstate,
|
1559
|
+
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(i, p), css));
|
1577
1560
|
}
|
1578
1561
|
// we need to skip anything inside strings
|
1579
1562
|
// create a new target in parser/prelexer
|
@@ -1583,7 +1566,9 @@ namespace Sass {
|
|
1583
1566
|
const char* j = skip_over_scopes< exactly<hash_lbrace>, exactly<rbrace> >(p + 2, chunk.end); // find the closing brace
|
1584
1567
|
if (j) { --j;
|
1585
1568
|
// parse the interpolant and accumulate it
|
1586
|
-
|
1569
|
+
LocalOption<const char*> partEnd(end, j);
|
1570
|
+
LocalOption<const char*> partBeg(position, p + 2);
|
1571
|
+
ExpressionObj interp_node = parse_list();
|
1587
1572
|
interp_node->is_interpolant(true);
|
1588
1573
|
schema->append(interp_node);
|
1589
1574
|
i = j;
|
@@ -1595,7 +1580,7 @@ namespace Sass {
|
|
1595
1580
|
}
|
1596
1581
|
else { // no interpolants left; add the last segment if nonempty
|
1597
1582
|
// check if we need quotes here (was not sure after merge)
|
1598
|
-
if (i < chunk.end) schema->append(SASS_MEMORY_NEW(String_Constant, pstate,
|
1583
|
+
if (i < chunk.end) schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(i, chunk.end), css));
|
1599
1584
|
break;
|
1600
1585
|
}
|
1601
1586
|
++ i;
|
@@ -1607,7 +1592,7 @@ namespace Sass {
|
|
1607
1592
|
String_Schema_Obj Parser::parse_css_variable_value()
|
1608
1593
|
{
|
1609
1594
|
String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
|
1610
|
-
|
1595
|
+
sass::vector<char> brackets;
|
1611
1596
|
while (true) {
|
1612
1597
|
if (
|
1613
1598
|
(brackets.empty() && lex< css_variable_top_level_value >(false)) ||
|
@@ -1615,7 +1600,7 @@ namespace Sass {
|
|
1615
1600
|
) {
|
1616
1601
|
Token str(lexed);
|
1617
1602
|
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, str));
|
1618
|
-
} else if (
|
1603
|
+
} else if (ExpressionObj tok = lex_interpolation()) {
|
1619
1604
|
if (String_Schema* s = Cast<String_Schema>(tok)) {
|
1620
1605
|
if (s->empty()) break;
|
1621
1606
|
schema->concat(s);
|
@@ -1623,7 +1608,7 @@ namespace Sass {
|
|
1623
1608
|
schema->append(tok);
|
1624
1609
|
}
|
1625
1610
|
} else if (lex< quoted_string >()) {
|
1626
|
-
|
1611
|
+
ExpressionObj tok = parse_string();
|
1627
1612
|
if (tok.isNull()) break;
|
1628
1613
|
if (String_Schema* s = Cast<String_Schema>(tok)) {
|
1629
1614
|
if (s->empty()) break;
|
@@ -1634,18 +1619,18 @@ namespace Sass {
|
|
1634
1619
|
} else if (lex< alternatives< exactly<'('>, exactly<'['>, exactly<'{'> > >()) {
|
1635
1620
|
const char opening_bracket = *(position - 1);
|
1636
1621
|
brackets.push_back(opening_bracket);
|
1637
|
-
schema->append(SASS_MEMORY_NEW(String_Constant, pstate,
|
1622
|
+
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(1, opening_bracket)));
|
1638
1623
|
} else if (const char *match = peek< alternatives< exactly<')'>, exactly<']'>, exactly<'}'> > >()) {
|
1639
1624
|
if (brackets.empty()) break;
|
1640
1625
|
const char closing_bracket = *(match - 1);
|
1641
1626
|
if (brackets.back() != Util::opening_bracket_for(closing_bracket)) {
|
1642
|
-
|
1627
|
+
sass::string message = ": expected \"";
|
1643
1628
|
message += Util::closing_bracket_for(brackets.back());
|
1644
1629
|
message += "\", was ";
|
1645
1630
|
css_error("Invalid CSS", " after ", message);
|
1646
1631
|
}
|
1647
1632
|
lex< alternatives< exactly<')'>, exactly<']'>, exactly<'}'> > >();
|
1648
|
-
schema->append(SASS_MEMORY_NEW(String_Constant, pstate,
|
1633
|
+
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(1, closing_bracket)));
|
1649
1634
|
brackets.pop_back();
|
1650
1635
|
} else {
|
1651
1636
|
break;
|
@@ -1653,7 +1638,7 @@ namespace Sass {
|
|
1653
1638
|
}
|
1654
1639
|
|
1655
1640
|
if (!brackets.empty()) {
|
1656
|
-
|
1641
|
+
sass::string message = ": expected \"";
|
1657
1642
|
message += Util::closing_bracket_for(brackets.back());
|
1658
1643
|
message += "\", was ";
|
1659
1644
|
css_error("Invalid CSS", " after ", message);
|
@@ -1663,7 +1648,7 @@ namespace Sass {
|
|
1663
1648
|
return schema.detach();
|
1664
1649
|
}
|
1665
1650
|
|
1666
|
-
|
1651
|
+
ValueObj Parser::parse_static_value()
|
1667
1652
|
{
|
1668
1653
|
lex< static_value >();
|
1669
1654
|
Token str(lexed);
|
@@ -1690,7 +1675,7 @@ namespace Sass {
|
|
1690
1675
|
// see if there any interpolants
|
1691
1676
|
const char* p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(str.begin, str.end);
|
1692
1677
|
if (!p) {
|
1693
|
-
return SASS_MEMORY_NEW(String_Quoted, pstate,
|
1678
|
+
return SASS_MEMORY_NEW(String_Quoted, pstate, sass::string(str.begin, str.end));
|
1694
1679
|
}
|
1695
1680
|
|
1696
1681
|
String_Schema* schema = SASS_MEMORY_NEW(String_Schema, pstate);
|
@@ -1698,7 +1683,7 @@ namespace Sass {
|
|
1698
1683
|
p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, str.end);
|
1699
1684
|
if (p) {
|
1700
1685
|
if (i < p) {
|
1701
|
-
schema->append(SASS_MEMORY_NEW(String_Constant, pstate,
|
1686
|
+
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(i, p))); // accumulate the preceding segment if it's nonempty
|
1702
1687
|
}
|
1703
1688
|
if (peek < sequence < optional_spaces, exactly<rbrace> > >(p+2)) { position = p+2;
|
1704
1689
|
css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
|
@@ -1706,7 +1691,9 @@ namespace Sass {
|
|
1706
1691
|
const char* j = skip_over_scopes< exactly<hash_lbrace>, exactly<rbrace> >(p+2, str.end); // find the closing brace
|
1707
1692
|
if (j) {
|
1708
1693
|
// parse the interpolant and accumulate it
|
1709
|
-
|
1694
|
+
LocalOption<const char*> partEnd(end, j);
|
1695
|
+
LocalOption<const char*> partBeg(position, p + 2);
|
1696
|
+
ExpressionObj interp_node = parse_list();
|
1710
1697
|
interp_node->is_interpolant(true);
|
1711
1698
|
schema->append(interp_node);
|
1712
1699
|
i = j;
|
@@ -1718,7 +1705,7 @@ namespace Sass {
|
|
1718
1705
|
}
|
1719
1706
|
else { // no interpolants left; add the last segment if nonempty
|
1720
1707
|
if (i < str.end) {
|
1721
|
-
schema->append(SASS_MEMORY_NEW(String_Constant, pstate,
|
1708
|
+
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(i, str.end)));
|
1722
1709
|
}
|
1723
1710
|
break;
|
1724
1711
|
}
|
@@ -1739,7 +1726,7 @@ namespace Sass {
|
|
1739
1726
|
kwd_arg->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
|
1740
1727
|
if (peek< variable >()) kwd_arg->append(parse_list());
|
1741
1728
|
else if (lex< number >()) {
|
1742
|
-
|
1729
|
+
sass::string parsed(lexed);
|
1743
1730
|
Util::normalize_decimals(parsed);
|
1744
1731
|
kwd_arg->append(lexed_number(parsed));
|
1745
1732
|
}
|
@@ -1779,7 +1766,7 @@ namespace Sass {
|
|
1779
1766
|
if (peek< exactly< rbrace > >()) {
|
1780
1767
|
css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
|
1781
1768
|
}
|
1782
|
-
|
1769
|
+
ExpressionObj ex;
|
1783
1770
|
if (lex< re_static_expression >()) {
|
1784
1771
|
ex = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
|
1785
1772
|
} else {
|
@@ -1815,7 +1802,7 @@ namespace Sass {
|
|
1815
1802
|
}
|
1816
1803
|
// lex (normalized) variable
|
1817
1804
|
else if (lex< variable >()) {
|
1818
|
-
|
1805
|
+
sass::string name(Util::normalize_underscores(lexed));
|
1819
1806
|
schema->append(SASS_MEMORY_NEW(Variable, pstate, name));
|
1820
1807
|
}
|
1821
1808
|
// lex percentage value
|
@@ -1847,7 +1834,7 @@ namespace Sass {
|
|
1847
1834
|
++num_items;
|
1848
1835
|
}
|
1849
1836
|
if (position != stop) {
|
1850
|
-
schema->append(SASS_MEMORY_NEW(String_Constant, pstate,
|
1837
|
+
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(position, stop)));
|
1851
1838
|
position = stop;
|
1852
1839
|
}
|
1853
1840
|
end = ee;
|
@@ -1863,7 +1850,7 @@ namespace Sass {
|
|
1863
1850
|
// see if there any interpolants
|
1864
1851
|
const char* p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(id.begin, id.end);
|
1865
1852
|
if (!p) {
|
1866
|
-
return SASS_MEMORY_NEW(String_Constant, pstate,
|
1853
|
+
return SASS_MEMORY_NEW(String_Constant, pstate, sass::string(id.begin, id.end));
|
1867
1854
|
}
|
1868
1855
|
|
1869
1856
|
String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
|
@@ -1884,7 +1871,9 @@ namespace Sass {
|
|
1884
1871
|
const char* j = skip_over_scopes< exactly<hash_lbrace>, exactly<rbrace> >(p+2, id.end); // find the closing brace
|
1885
1872
|
if (j) {
|
1886
1873
|
// parse the interpolant and accumulate it
|
1887
|
-
|
1874
|
+
LocalOption<const char*> partEnd(end, j);
|
1875
|
+
LocalOption<const char*> partBeg(position, p + 2);
|
1876
|
+
ExpressionObj interp_node = parse_list(DELAYED);
|
1888
1877
|
interp_node->is_interpolant(true);
|
1889
1878
|
schema->append(interp_node);
|
1890
1879
|
// schema->has_interpolants(true);
|
@@ -1911,10 +1900,10 @@ namespace Sass {
|
|
1911
1900
|
Function_Call_Obj Parser::parse_calc_function()
|
1912
1901
|
{
|
1913
1902
|
lex< identifier >();
|
1914
|
-
|
1915
|
-
|
1903
|
+
sass::string name(lexed);
|
1904
|
+
SourceSpan call_pos = pstate;
|
1916
1905
|
lex< exactly<'('> >();
|
1917
|
-
|
1906
|
+
SourceSpan arg_pos = pstate;
|
1918
1907
|
const char* arg_beg = position;
|
1919
1908
|
parse_list();
|
1920
1909
|
const char* arg_end = position;
|
@@ -1931,20 +1920,20 @@ namespace Sass {
|
|
1931
1920
|
|
1932
1921
|
String_Obj Parser::parse_url_function_string()
|
1933
1922
|
{
|
1934
|
-
|
1923
|
+
sass::string prefix("");
|
1935
1924
|
if (lex< uri_prefix >()) {
|
1936
|
-
prefix =
|
1925
|
+
prefix = sass::string(lexed);
|
1937
1926
|
}
|
1938
1927
|
|
1939
1928
|
lex < optional_spaces >();
|
1940
1929
|
String_Obj url_string = parse_url_function_argument();
|
1941
1930
|
|
1942
|
-
|
1931
|
+
sass::string suffix("");
|
1943
1932
|
if (lex< real_uri_suffix >()) {
|
1944
|
-
suffix =
|
1933
|
+
suffix = sass::string(lexed);
|
1945
1934
|
}
|
1946
1935
|
|
1947
|
-
|
1936
|
+
sass::string uri("");
|
1948
1937
|
if (url_string) {
|
1949
1938
|
uri = url_string->to_string({ NESTED, 5 });
|
1950
1939
|
}
|
@@ -1956,7 +1945,7 @@ namespace Sass {
|
|
1956
1945
|
res->append(SASS_MEMORY_NEW(String_Constant, pstate, suffix));
|
1957
1946
|
return res;
|
1958
1947
|
} else {
|
1959
|
-
|
1948
|
+
sass::string res = prefix + uri + suffix;
|
1960
1949
|
return SASS_MEMORY_NEW(String_Constant, pstate, res);
|
1961
1950
|
}
|
1962
1951
|
}
|
@@ -1965,7 +1954,7 @@ namespace Sass {
|
|
1965
1954
|
{
|
1966
1955
|
const char* p = position;
|
1967
1956
|
|
1968
|
-
|
1957
|
+
sass::string uri("");
|
1969
1958
|
if (lex< real_uri_value >(false)) {
|
1970
1959
|
uri = lexed.to_string();
|
1971
1960
|
}
|
@@ -1981,7 +1970,7 @@ namespace Sass {
|
|
1981
1970
|
return parse_interpolated_chunk(Token(p, position));
|
1982
1971
|
}
|
1983
1972
|
else if (uri != "") {
|
1984
|
-
|
1973
|
+
sass::string res = Util::rtrim(uri);
|
1985
1974
|
return SASS_MEMORY_NEW(String_Constant, pstate, res);
|
1986
1975
|
}
|
1987
1976
|
|
@@ -1991,12 +1980,12 @@ namespace Sass {
|
|
1991
1980
|
Function_Call_Obj Parser::parse_function_call()
|
1992
1981
|
{
|
1993
1982
|
lex< identifier >();
|
1994
|
-
|
1983
|
+
sass::string name(lexed);
|
1995
1984
|
|
1996
1985
|
if (Util::normalize_underscores(name) == "content-exists" && stack.back() != Scope::Mixin)
|
1997
1986
|
{ error("Cannot call content-exists() except within a mixin."); }
|
1998
1987
|
|
1999
|
-
|
1988
|
+
SourceSpan call_pos = pstate;
|
2000
1989
|
Arguments_Obj args = parse_arguments();
|
2001
1990
|
return SASS_MEMORY_NEW(Function_Call, call_pos, name, args);
|
2002
1991
|
}
|
@@ -2004,7 +1993,7 @@ namespace Sass {
|
|
2004
1993
|
Function_Call_Obj Parser::parse_function_call_schema()
|
2005
1994
|
{
|
2006
1995
|
String_Obj name = parse_identifier_schema();
|
2007
|
-
|
1996
|
+
SourceSpan source_position_of_call = pstate;
|
2008
1997
|
Arguments_Obj args = parse_arguments();
|
2009
1998
|
|
2010
1999
|
return SASS_MEMORY_NEW(Function_Call, source_position_of_call, name, args);
|
@@ -2012,7 +2001,7 @@ namespace Sass {
|
|
2012
2001
|
|
2013
2002
|
Content_Obj Parser::parse_content_directive()
|
2014
2003
|
{
|
2015
|
-
|
2004
|
+
SourceSpan call_pos = pstate;
|
2016
2005
|
Arguments_Obj args = parse_arguments();
|
2017
2006
|
|
2018
2007
|
return SASS_MEMORY_NEW(Content, call_pos, args);
|
@@ -2021,9 +2010,9 @@ namespace Sass {
|
|
2021
2010
|
If_Obj Parser::parse_if_directive(bool else_if)
|
2022
2011
|
{
|
2023
2012
|
stack.push_back(Scope::Control);
|
2024
|
-
|
2013
|
+
SourceSpan if_source_position = pstate;
|
2025
2014
|
bool root = block_stack.back()->is_root();
|
2026
|
-
|
2015
|
+
ExpressionObj predicate = parse_list();
|
2027
2016
|
Block_Obj block = parse_block(root);
|
2028
2017
|
Block_Obj alternative;
|
2029
2018
|
|
@@ -2040,23 +2029,23 @@ namespace Sass {
|
|
2040
2029
|
return SASS_MEMORY_NEW(If, if_source_position, predicate, block, alternative);
|
2041
2030
|
}
|
2042
2031
|
|
2043
|
-
|
2032
|
+
ForRuleObj Parser::parse_for_directive()
|
2044
2033
|
{
|
2045
2034
|
stack.push_back(Scope::Control);
|
2046
|
-
|
2035
|
+
SourceSpan for_source_position = pstate;
|
2047
2036
|
bool root = block_stack.back()->is_root();
|
2048
2037
|
lex_variable();
|
2049
|
-
|
2038
|
+
sass::string var(Util::normalize_underscores(lexed));
|
2050
2039
|
if (!lex< kwd_from >()) error("expected 'from' keyword in @for directive");
|
2051
|
-
|
2040
|
+
ExpressionObj lower_bound = parse_expression();
|
2052
2041
|
bool inclusive = false;
|
2053
2042
|
if (lex< kwd_through >()) inclusive = true;
|
2054
2043
|
else if (lex< kwd_to >()) inclusive = false;
|
2055
2044
|
else error("expected 'through' or 'to' keyword in @for directive");
|
2056
|
-
|
2045
|
+
ExpressionObj upper_bound = parse_expression();
|
2057
2046
|
Block_Obj body = parse_block(root);
|
2058
2047
|
stack.pop_back();
|
2059
|
-
return SASS_MEMORY_NEW(
|
2048
|
+
return SASS_MEMORY_NEW(ForRule, for_source_position, var, lower_bound, upper_bound, body, inclusive);
|
2060
2049
|
}
|
2061
2050
|
|
2062
2051
|
// helper to parse a var token
|
@@ -2072,7 +2061,7 @@ namespace Sass {
|
|
2072
2061
|
css_error("Invalid CSS", " after ", ": expected identifier, was ");
|
2073
2062
|
}
|
2074
2063
|
// return object
|
2075
|
-
return
|
2064
|
+
return lexed;
|
2076
2065
|
}
|
2077
2066
|
// helper to parse identifier
|
2078
2067
|
Token Parser::lex_identifier()
|
@@ -2082,15 +2071,15 @@ namespace Sass {
|
|
2082
2071
|
css_error("Invalid CSS", " after ", ": expected identifier, was ");
|
2083
2072
|
}
|
2084
2073
|
// return object
|
2085
|
-
return
|
2074
|
+
return lexed;
|
2086
2075
|
}
|
2087
2076
|
|
2088
|
-
|
2077
|
+
EachRuleObj Parser::parse_each_directive()
|
2089
2078
|
{
|
2090
2079
|
stack.push_back(Scope::Control);
|
2091
|
-
|
2080
|
+
SourceSpan each_source_position = pstate;
|
2092
2081
|
bool root = block_stack.back()->is_root();
|
2093
|
-
|
2082
|
+
sass::vector<sass::string> vars;
|
2094
2083
|
lex_variable();
|
2095
2084
|
vars.push_back(Util::normalize_underscores(lexed));
|
2096
2085
|
while (lex< exactly<','> >()) {
|
@@ -2098,21 +2087,21 @@ namespace Sass {
|
|
2098
2087
|
vars.push_back(Util::normalize_underscores(lexed));
|
2099
2088
|
}
|
2100
2089
|
if (!lex< kwd_in >()) error("expected 'in' keyword in @each directive");
|
2101
|
-
|
2090
|
+
ExpressionObj list = parse_list();
|
2102
2091
|
Block_Obj body = parse_block(root);
|
2103
2092
|
stack.pop_back();
|
2104
|
-
return SASS_MEMORY_NEW(
|
2093
|
+
return SASS_MEMORY_NEW(EachRule, each_source_position, vars, list, body);
|
2105
2094
|
}
|
2106
2095
|
|
2107
2096
|
// called after parsing `kwd_while_directive`
|
2108
|
-
|
2097
|
+
WhileRuleObj Parser::parse_while_directive()
|
2109
2098
|
{
|
2110
2099
|
stack.push_back(Scope::Control);
|
2111
2100
|
bool root = block_stack.back()->is_root();
|
2112
2101
|
// create the initial while call object
|
2113
|
-
|
2102
|
+
WhileRuleObj call = SASS_MEMORY_NEW(WhileRule, pstate, ExpressionObj{}, Block_Obj{});
|
2114
2103
|
// parse mandatory predicate
|
2115
|
-
|
2104
|
+
ExpressionObj predicate = parse_list();
|
2116
2105
|
List_Obj l = Cast<List>(predicate);
|
2117
2106
|
if (!predicate || (l && !l->length())) {
|
2118
2107
|
css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ", false);
|
@@ -2127,9 +2116,9 @@ namespace Sass {
|
|
2127
2116
|
}
|
2128
2117
|
|
2129
2118
|
|
2130
|
-
|
2119
|
+
sass::vector<CssMediaQuery_Obj> Parser::parseCssMediaQueries()
|
2131
2120
|
{
|
2132
|
-
|
2121
|
+
sass::vector<CssMediaQuery_Obj> result;
|
2133
2122
|
do {
|
2134
2123
|
if (auto query = parseCssMediaQuery()) {
|
2135
2124
|
result.push_back(query);
|
@@ -2138,12 +2127,12 @@ namespace Sass {
|
|
2138
2127
|
return result;
|
2139
2128
|
}
|
2140
2129
|
|
2141
|
-
|
2130
|
+
sass::string Parser::parseIdentifier()
|
2142
2131
|
{
|
2143
2132
|
if (lex < identifier >(false)) {
|
2144
|
-
return
|
2133
|
+
return sass::string(lexed);
|
2145
2134
|
}
|
2146
|
-
return
|
2135
|
+
return sass::string();
|
2147
2136
|
}
|
2148
2137
|
|
2149
2138
|
CssMediaQuery_Obj Parser::parseCssMediaQuery()
|
@@ -2154,14 +2143,14 @@ namespace Sass {
|
|
2154
2143
|
// Check if any tokens are to parse
|
2155
2144
|
if (!peek_css<exactly<'('>>()) {
|
2156
2145
|
|
2157
|
-
|
2146
|
+
sass::string token1(parseIdentifier());
|
2158
2147
|
lex<css_comments>(false);
|
2159
2148
|
|
2160
2149
|
if (token1.empty()) {
|
2161
2150
|
return {};
|
2162
2151
|
}
|
2163
2152
|
|
2164
|
-
|
2153
|
+
sass::string token2(parseIdentifier());
|
2165
2154
|
lex<css_comments>(false);
|
2166
2155
|
|
2167
2156
|
if (Util::equalsLiteral("and", token2)) {
|
@@ -2187,7 +2176,7 @@ namespace Sass {
|
|
2187
2176
|
|
2188
2177
|
}
|
2189
2178
|
|
2190
|
-
|
2179
|
+
sass::vector<sass::string> queries;
|
2191
2180
|
|
2192
2181
|
do {
|
2193
2182
|
lex<css_comments>(false);
|
@@ -2195,7 +2184,7 @@ namespace Sass {
|
|
2195
2184
|
if (lex<exactly<'('>>()) {
|
2196
2185
|
// In dart sass parser returns a pure string
|
2197
2186
|
if (lex < skip_over_scopes < exactly < '(' >, exactly < ')' > > >()) {
|
2198
|
-
|
2187
|
+
sass::string decl("(" + sass::string(lexed));
|
2199
2188
|
queries.push_back(decl);
|
2200
2189
|
}
|
2201
2190
|
// Should be: parseDeclarationValue;
|
@@ -2247,15 +2236,17 @@ namespace Sass {
|
|
2247
2236
|
if (lex < kwd_not >()) { media_query->is_negated(true); lex < css_comments >(false); }
|
2248
2237
|
else if (lex < kwd_only >()) { media_query->is_restricted(true); lex < css_comments >(false); }
|
2249
2238
|
|
2250
|
-
if (lex < identifier_schema >())
|
2251
|
-
else if (lex < identifier >())
|
2239
|
+
if (lex < identifier_schema >()) media_query->media_type(parse_identifier_schema());
|
2240
|
+
else if (lex < identifier >()) media_query->media_type(parse_interpolated_chunk(lexed));
|
2252
2241
|
else media_query->append(parse_media_expression());
|
2253
2242
|
|
2254
2243
|
while (lex_css < kwd_and >()) media_query->append(parse_media_expression());
|
2255
2244
|
if (lex < identifier_schema >()) {
|
2256
|
-
|
2257
|
-
|
2258
|
-
|
2245
|
+
String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
|
2246
|
+
if (media_query->media_type()) {
|
2247
|
+
schema->append(media_query->media_type());
|
2248
|
+
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, " "));
|
2249
|
+
}
|
2259
2250
|
schema->append(parse_identifier_schema());
|
2260
2251
|
media_query->media_type(schema);
|
2261
2252
|
}
|
@@ -2266,21 +2257,21 @@ namespace Sass {
|
|
2266
2257
|
return media_query;
|
2267
2258
|
}
|
2268
2259
|
|
2269
|
-
|
2260
|
+
Media_Query_ExpressionObj Parser::parse_media_expression()
|
2270
2261
|
{
|
2271
2262
|
if (lex < identifier_schema >()) {
|
2272
2263
|
String_Obj ss = parse_identifier_schema();
|
2273
|
-
return SASS_MEMORY_NEW(Media_Query_Expression, pstate, ss, {}, true);
|
2264
|
+
return SASS_MEMORY_NEW(Media_Query_Expression, pstate, ss, ExpressionObj{}, true);
|
2274
2265
|
}
|
2275
2266
|
if (!lex_css< exactly<'('> >()) {
|
2276
2267
|
error("media query expression must begin with '('");
|
2277
2268
|
}
|
2278
|
-
|
2269
|
+
ExpressionObj feature;
|
2279
2270
|
if (peek_css< exactly<')'> >()) {
|
2280
2271
|
error("media feature required in media query expression");
|
2281
2272
|
}
|
2282
2273
|
feature = parse_expression();
|
2283
|
-
|
2274
|
+
ExpressionObj expression;
|
2284
2275
|
if (lex_css< exactly<':'> >()) {
|
2285
2276
|
expression = parse_list(DELAYED);
|
2286
2277
|
}
|
@@ -2292,11 +2283,11 @@ namespace Sass {
|
|
2292
2283
|
|
2293
2284
|
// lexed after `kwd_supports_directive`
|
2294
2285
|
// these are very similar to media blocks
|
2295
|
-
|
2286
|
+
SupportsRuleObj Parser::parse_supports_directive()
|
2296
2287
|
{
|
2297
|
-
|
2288
|
+
SupportsConditionObj cond = parse_supports_condition(/*top_level=*/true);
|
2298
2289
|
// create the ast node object for the support queries
|
2299
|
-
|
2290
|
+
SupportsRuleObj query = SASS_MEMORY_NEW(SupportsRule, pstate, cond);
|
2300
2291
|
// additional block is mandatory
|
2301
2292
|
// parse inner block
|
2302
2293
|
query->block(parse_block());
|
@@ -2306,43 +2297,43 @@ namespace Sass {
|
|
2306
2297
|
|
2307
2298
|
// parse one query operation
|
2308
2299
|
// may encounter nested queries
|
2309
|
-
|
2300
|
+
SupportsConditionObj Parser::parse_supports_condition(bool top_level)
|
2310
2301
|
{
|
2311
2302
|
lex < css_whitespace >();
|
2312
|
-
|
2303
|
+
SupportsConditionObj cond;
|
2313
2304
|
if ((cond = parse_supports_negation())) return cond;
|
2314
2305
|
if ((cond = parse_supports_operator(top_level))) return cond;
|
2315
2306
|
if ((cond = parse_supports_interpolation())) return cond;
|
2316
2307
|
return cond;
|
2317
2308
|
}
|
2318
2309
|
|
2319
|
-
|
2310
|
+
SupportsConditionObj Parser::parse_supports_negation()
|
2320
2311
|
{
|
2321
2312
|
if (!lex < kwd_not >()) return {};
|
2322
|
-
|
2323
|
-
return SASS_MEMORY_NEW(
|
2313
|
+
SupportsConditionObj cond = parse_supports_condition_in_parens(/*parens_required=*/true);
|
2314
|
+
return SASS_MEMORY_NEW(SupportsNegation, pstate, cond);
|
2324
2315
|
}
|
2325
2316
|
|
2326
|
-
|
2317
|
+
SupportsConditionObj Parser::parse_supports_operator(bool top_level)
|
2327
2318
|
{
|
2328
|
-
|
2319
|
+
SupportsConditionObj cond = parse_supports_condition_in_parens(/*parens_required=*/top_level);
|
2329
2320
|
if (cond.isNull()) return {};
|
2330
2321
|
|
2331
2322
|
while (true) {
|
2332
|
-
|
2333
|
-
if (lex < kwd_and >()) { op =
|
2323
|
+
SupportsOperation::Operand op = SupportsOperation::OR;
|
2324
|
+
if (lex < kwd_and >()) { op = SupportsOperation::AND; }
|
2334
2325
|
else if(!lex < kwd_or >()) { break; }
|
2335
2326
|
|
2336
2327
|
lex < css_whitespace >();
|
2337
|
-
|
2328
|
+
SupportsConditionObj right = parse_supports_condition_in_parens(/*parens_required=*/true);
|
2338
2329
|
|
2339
|
-
//
|
2340
|
-
cond = SASS_MEMORY_NEW(
|
2330
|
+
// SupportsCondition* cc = SASS_MEMORY_NEW(SupportsCondition, *static_cast<SupportsCondition*>(cond));
|
2331
|
+
cond = SASS_MEMORY_NEW(SupportsOperation, pstate, cond, right, op);
|
2341
2332
|
}
|
2342
2333
|
return cond;
|
2343
2334
|
}
|
2344
2335
|
|
2345
|
-
|
2336
|
+
SupportsConditionObj Parser::parse_supports_interpolation()
|
2346
2337
|
{
|
2347
2338
|
if (!lex < interpolant >()) return {};
|
2348
2339
|
|
@@ -2354,17 +2345,17 @@ namespace Sass {
|
|
2354
2345
|
|
2355
2346
|
// TODO: This needs some major work. Although feature conditions
|
2356
2347
|
// look like declarations their semantics differ significantly
|
2357
|
-
|
2348
|
+
SupportsConditionObj Parser::parse_supports_declaration()
|
2358
2349
|
{
|
2359
|
-
|
2350
|
+
SupportsCondition* cond;
|
2360
2351
|
// parse something declaration like
|
2361
|
-
|
2362
|
-
|
2352
|
+
ExpressionObj feature = parse_expression();
|
2353
|
+
ExpressionObj expression;
|
2363
2354
|
if (lex_css< exactly<':'> >()) {
|
2364
2355
|
expression = parse_list(DELAYED);
|
2365
2356
|
}
|
2366
2357
|
if (!feature || !expression) error("@supports condition expected declaration");
|
2367
|
-
cond = SASS_MEMORY_NEW(
|
2358
|
+
cond = SASS_MEMORY_NEW(SupportsDeclaration,
|
2368
2359
|
feature->pstate(),
|
2369
2360
|
feature,
|
2370
2361
|
expression);
|
@@ -2372,9 +2363,9 @@ namespace Sass {
|
|
2372
2363
|
return cond;
|
2373
2364
|
}
|
2374
2365
|
|
2375
|
-
|
2366
|
+
SupportsConditionObj Parser::parse_supports_condition_in_parens(bool parens_required)
|
2376
2367
|
{
|
2377
|
-
|
2368
|
+
SupportsConditionObj interp = parse_supports_interpolation();
|
2378
2369
|
if (interp != nullptr) return interp;
|
2379
2370
|
|
2380
2371
|
if (!lex < exactly <'('> >()) {
|
@@ -2386,7 +2377,7 @@ namespace Sass {
|
|
2386
2377
|
}
|
2387
2378
|
lex < css_whitespace >();
|
2388
2379
|
|
2389
|
-
|
2380
|
+
SupportsConditionObj cond = parse_supports_condition(/*top_level=*/false);
|
2390
2381
|
if (cond.isNull()) cond = parse_supports_declaration();
|
2391
2382
|
if (!lex < exactly <')'> >()) error("unclosed parenthesis in @supports declaration");
|
2392
2383
|
|
@@ -2394,10 +2385,10 @@ namespace Sass {
|
|
2394
2385
|
return cond;
|
2395
2386
|
}
|
2396
2387
|
|
2397
|
-
|
2388
|
+
AtRootRuleObj Parser::parse_at_root_block()
|
2398
2389
|
{
|
2399
2390
|
stack.push_back(Scope::AtRoot);
|
2400
|
-
|
2391
|
+
SourceSpan at_source_position = pstate;
|
2401
2392
|
Block_Obj body;
|
2402
2393
|
At_Root_Query_Obj expr;
|
2403
2394
|
Lookahead lookahead_result;
|
@@ -2409,11 +2400,11 @@ namespace Sass {
|
|
2409
2400
|
body = parse_block(true);
|
2410
2401
|
}
|
2411
2402
|
else if ((lookahead_result = lookahead_for_selector(position)).found) {
|
2412
|
-
|
2403
|
+
StyleRuleObj r = parse_ruleset(lookahead_result);
|
2413
2404
|
body = SASS_MEMORY_NEW(Block, r->pstate(), 1, true);
|
2414
2405
|
body->append(r);
|
2415
2406
|
}
|
2416
|
-
|
2407
|
+
AtRootRuleObj at_root = SASS_MEMORY_NEW(AtRootRule, at_source_position, body);
|
2417
2408
|
if (!expr.isNull()) at_root->expression(expr);
|
2418
2409
|
stack.pop_back();
|
2419
2410
|
return at_root;
|
@@ -2427,9 +2418,9 @@ namespace Sass {
|
|
2427
2418
|
css_error("Invalid CSS", " after ", ": expected \"with\" or \"without\", was ");
|
2428
2419
|
}
|
2429
2420
|
|
2430
|
-
|
2421
|
+
ExpressionObj feature = parse_list();
|
2431
2422
|
if (!lex_css< exactly<':'> >()) error("style declaration must contain a value");
|
2432
|
-
|
2423
|
+
ExpressionObj expression = parse_list();
|
2433
2424
|
List_Obj value = SASS_MEMORY_NEW(List, feature->pstate(), 1);
|
2434
2425
|
|
2435
2426
|
if (expression->concrete_type() == Expression::LIST) {
|
@@ -2445,9 +2436,9 @@ namespace Sass {
|
|
2445
2436
|
return cond;
|
2446
2437
|
}
|
2447
2438
|
|
2448
|
-
|
2439
|
+
AtRuleObj Parser::parse_directive()
|
2449
2440
|
{
|
2450
|
-
|
2441
|
+
AtRuleObj directive = SASS_MEMORY_NEW(AtRule, pstate, lexed);
|
2451
2442
|
String_Schema_Obj val = parse_almost_any_value();
|
2452
2443
|
// strip left and right if they are of type string
|
2453
2444
|
directive->value(val);
|
@@ -2457,7 +2448,7 @@ namespace Sass {
|
|
2457
2448
|
return directive;
|
2458
2449
|
}
|
2459
2450
|
|
2460
|
-
|
2451
|
+
ExpressionObj Parser::lex_interpolation()
|
2461
2452
|
{
|
2462
2453
|
if (lex < interpolant >(true) != NULL) {
|
2463
2454
|
return parse_interpolated_chunk(lexed, true);
|
@@ -2465,21 +2456,21 @@ namespace Sass {
|
|
2465
2456
|
return {};
|
2466
2457
|
}
|
2467
2458
|
|
2468
|
-
|
2459
|
+
ExpressionObj Parser::lex_interp_uri()
|
2469
2460
|
{
|
2470
2461
|
// create a string schema by lexing optional interpolations
|
2471
2462
|
return lex_interp< re_string_uri_open, re_string_uri_close >();
|
2472
2463
|
}
|
2473
2464
|
|
2474
|
-
|
2465
|
+
ExpressionObj Parser::lex_interp_string()
|
2475
2466
|
{
|
2476
|
-
|
2467
|
+
ExpressionObj rv;
|
2477
2468
|
if ((rv = lex_interp< re_string_double_open, re_string_double_close >())) return rv;
|
2478
2469
|
if ((rv = lex_interp< re_string_single_open, re_string_single_close >())) return rv;
|
2479
2470
|
return rv;
|
2480
2471
|
}
|
2481
2472
|
|
2482
|
-
|
2473
|
+
ExpressionObj Parser::lex_almost_any_value_chars()
|
2483
2474
|
{
|
2484
2475
|
const char* match =
|
2485
2476
|
lex <
|
@@ -2532,9 +2523,9 @@ namespace Sass {
|
|
2532
2523
|
return {};
|
2533
2524
|
}
|
2534
2525
|
|
2535
|
-
|
2526
|
+
ExpressionObj Parser::lex_almost_any_value_token()
|
2536
2527
|
{
|
2537
|
-
|
2528
|
+
ExpressionObj rv;
|
2538
2529
|
if (*position == 0) return {};
|
2539
2530
|
if ((rv = lex_almost_any_value_chars())) return rv;
|
2540
2531
|
// if ((rv = lex_block_comment())) return rv;
|
@@ -2553,7 +2544,7 @@ namespace Sass {
|
|
2553
2544
|
String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
|
2554
2545
|
if (*position == 0) return {};
|
2555
2546
|
lex < spaces >(false);
|
2556
|
-
|
2547
|
+
ExpressionObj token = lex_almost_any_value_token();
|
2557
2548
|
if (!token) return {};
|
2558
2549
|
schema->append(token);
|
2559
2550
|
if (*position == 0) {
|
@@ -2572,7 +2563,7 @@ namespace Sass {
|
|
2572
2563
|
return schema.detach();
|
2573
2564
|
}
|
2574
2565
|
|
2575
|
-
|
2566
|
+
WarningRuleObj Parser::parse_warning()
|
2576
2567
|
{
|
2577
2568
|
if (stack.back() != Scope::Root &&
|
2578
2569
|
stack.back() != Scope::Function &&
|
@@ -2581,10 +2572,10 @@ namespace Sass {
|
|
2581
2572
|
stack.back() != Scope::Rules) {
|
2582
2573
|
error("Illegal nesting: Only properties may be nested beneath properties.");
|
2583
2574
|
}
|
2584
|
-
return SASS_MEMORY_NEW(
|
2575
|
+
return SASS_MEMORY_NEW(WarningRule, pstate, parse_list(DELAYED));
|
2585
2576
|
}
|
2586
2577
|
|
2587
|
-
|
2578
|
+
ErrorRuleObj Parser::parse_error()
|
2588
2579
|
{
|
2589
2580
|
if (stack.back() != Scope::Root &&
|
2590
2581
|
stack.back() != Scope::Function &&
|
@@ -2593,10 +2584,10 @@ namespace Sass {
|
|
2593
2584
|
stack.back() != Scope::Rules) {
|
2594
2585
|
error("Illegal nesting: Only properties may be nested beneath properties.");
|
2595
2586
|
}
|
2596
|
-
return SASS_MEMORY_NEW(
|
2587
|
+
return SASS_MEMORY_NEW(ErrorRule, pstate, parse_list(DELAYED));
|
2597
2588
|
}
|
2598
2589
|
|
2599
|
-
|
2590
|
+
DebugRuleObj Parser::parse_debug()
|
2600
2591
|
{
|
2601
2592
|
if (stack.back() != Scope::Root &&
|
2602
2593
|
stack.back() != Scope::Function &&
|
@@ -2605,7 +2596,7 @@ namespace Sass {
|
|
2605
2596
|
stack.back() != Scope::Rules) {
|
2606
2597
|
error("Illegal nesting: Only properties may be nested beneath properties.");
|
2607
2598
|
}
|
2608
|
-
return SASS_MEMORY_NEW(
|
2599
|
+
return SASS_MEMORY_NEW(DebugRule, pstate, parse_list(DELAYED));
|
2609
2600
|
}
|
2610
2601
|
|
2611
2602
|
Return_Obj Parser::parse_return_directive()
|
@@ -2760,53 +2751,53 @@ namespace Sass {
|
|
2760
2751
|
void Parser::read_bom()
|
2761
2752
|
{
|
2762
2753
|
size_t skip = 0;
|
2763
|
-
|
2754
|
+
sass::string encoding;
|
2764
2755
|
bool utf_8 = false;
|
2765
|
-
switch ((unsigned char)
|
2756
|
+
switch ((unsigned char)position[0]) {
|
2766
2757
|
case 0xEF:
|
2767
|
-
skip = check_bom_chars(
|
2758
|
+
skip = check_bom_chars(position, end, utf_8_bom, 3);
|
2768
2759
|
encoding = "UTF-8";
|
2769
2760
|
utf_8 = true;
|
2770
2761
|
break;
|
2771
2762
|
case 0xFE:
|
2772
|
-
skip = check_bom_chars(
|
2763
|
+
skip = check_bom_chars(position, end, utf_16_bom_be, 2);
|
2773
2764
|
encoding = "UTF-16 (big endian)";
|
2774
2765
|
break;
|
2775
2766
|
case 0xFF:
|
2776
|
-
skip = check_bom_chars(
|
2777
|
-
skip += (skip ? check_bom_chars(
|
2767
|
+
skip = check_bom_chars(position, end, utf_16_bom_le, 2);
|
2768
|
+
skip += (skip ? check_bom_chars(position, end, utf_32_bom_le, 4) : 0);
|
2778
2769
|
encoding = (skip == 2 ? "UTF-16 (little endian)" : "UTF-32 (little endian)");
|
2779
2770
|
break;
|
2780
2771
|
case 0x00:
|
2781
|
-
skip = check_bom_chars(
|
2772
|
+
skip = check_bom_chars(position, end, utf_32_bom_be, 4);
|
2782
2773
|
encoding = "UTF-32 (big endian)";
|
2783
2774
|
break;
|
2784
2775
|
case 0x2B:
|
2785
|
-
skip = check_bom_chars(
|
2786
|
-
| check_bom_chars(
|
2787
|
-
| check_bom_chars(
|
2788
|
-
| check_bom_chars(
|
2789
|
-
| check_bom_chars(
|
2776
|
+
skip = check_bom_chars(position, end, utf_7_bom_1, 4)
|
2777
|
+
| check_bom_chars(position, end, utf_7_bom_2, 4)
|
2778
|
+
| check_bom_chars(position, end, utf_7_bom_3, 4)
|
2779
|
+
| check_bom_chars(position, end, utf_7_bom_4, 4)
|
2780
|
+
| check_bom_chars(position, end, utf_7_bom_5, 5);
|
2790
2781
|
encoding = "UTF-7";
|
2791
2782
|
break;
|
2792
2783
|
case 0xF7:
|
2793
|
-
skip = check_bom_chars(
|
2784
|
+
skip = check_bom_chars(position, end, utf_1_bom, 3);
|
2794
2785
|
encoding = "UTF-1";
|
2795
2786
|
break;
|
2796
2787
|
case 0xDD:
|
2797
|
-
skip = check_bom_chars(
|
2788
|
+
skip = check_bom_chars(position, end, utf_ebcdic_bom, 4);
|
2798
2789
|
encoding = "UTF-EBCDIC";
|
2799
2790
|
break;
|
2800
2791
|
case 0x0E:
|
2801
|
-
skip = check_bom_chars(
|
2792
|
+
skip = check_bom_chars(position, end, scsu_bom, 3);
|
2802
2793
|
encoding = "SCSU";
|
2803
2794
|
break;
|
2804
2795
|
case 0xFB:
|
2805
|
-
skip = check_bom_chars(
|
2796
|
+
skip = check_bom_chars(position, end, bocu_1_bom, 3);
|
2806
2797
|
encoding = "BOCU-1";
|
2807
2798
|
break;
|
2808
2799
|
case 0x84:
|
2809
|
-
skip = check_bom_chars(
|
2800
|
+
skip = check_bom_chars(position, end, gb_18030_bom, 4);
|
2810
2801
|
encoding = "GB-18030";
|
2811
2802
|
break;
|
2812
2803
|
default: break;
|
@@ -2826,7 +2817,7 @@ namespace Sass {
|
|
2826
2817
|
}
|
2827
2818
|
|
2828
2819
|
|
2829
|
-
|
2820
|
+
ExpressionObj Parser::fold_operands(ExpressionObj base, sass::vector<ExpressionObj>& operands, Operand op)
|
2830
2821
|
{
|
2831
2822
|
for (size_t i = 0, S = operands.size(); i < S; ++i) {
|
2832
2823
|
base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), op, base, operands[i]);
|
@@ -2834,7 +2825,7 @@ namespace Sass {
|
|
2834
2825
|
return base;
|
2835
2826
|
}
|
2836
2827
|
|
2837
|
-
|
2828
|
+
ExpressionObj Parser::fold_operands(ExpressionObj base, sass::vector<ExpressionObj>& operands, sass::vector<Operand>& ops, size_t i)
|
2838
2829
|
{
|
2839
2830
|
if (String_Schema* schema = Cast<String_Schema>(base)) {
|
2840
2831
|
// return schema;
|
@@ -2850,7 +2841,7 @@ namespace Sass {
|
|
2850
2841
|
|| (ops[0].operand == Sass_OP::LTE)
|
2851
2842
|
|| (ops[0].operand == Sass_OP::GTE)
|
2852
2843
|
)) {
|
2853
|
-
|
2844
|
+
ExpressionObj rhs = fold_operands(operands[i], operands, ops, i + 1);
|
2854
2845
|
rhs = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[0], schema, rhs);
|
2855
2846
|
return rhs;
|
2856
2847
|
}
|
@@ -2858,12 +2849,19 @@ namespace Sass {
|
|
2858
2849
|
}
|
2859
2850
|
}
|
2860
2851
|
|
2852
|
+
if (operands.size() > Constants::MaxCallStack) {
|
2853
|
+
// XXX: this is never hit via spec tests
|
2854
|
+
sass::ostream stm;
|
2855
|
+
stm << "Stack depth exceeded max of " << Constants::MaxCallStack;
|
2856
|
+
error(stm.str());
|
2857
|
+
}
|
2858
|
+
|
2861
2859
|
for (size_t S = operands.size(); i < S; ++i) {
|
2862
2860
|
if (String_Schema* schema = Cast<String_Schema>(operands[i])) {
|
2863
2861
|
if (schema->has_interpolants()) {
|
2864
2862
|
if (i + 1 < S) {
|
2865
2863
|
// this whole branch is never hit via spec tests
|
2866
|
-
|
2864
|
+
ExpressionObj rhs = fold_operands(operands[i+1], operands, ops, i + 2);
|
2867
2865
|
rhs = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], schema, rhs);
|
2868
2866
|
base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], base, rhs);
|
2869
2867
|
return base;
|
@@ -2889,28 +2887,14 @@ namespace Sass {
|
|
2889
2887
|
return base;
|
2890
2888
|
}
|
2891
2889
|
|
2892
|
-
void Parser::error(
|
2890
|
+
void Parser::error(sass::string msg)
|
2893
2891
|
{
|
2894
|
-
Position p(pos.line ? pos : before_token);
|
2895
|
-
ParserState pstate(path, source, p, Offset(0, 0));
|
2896
|
-
// `pstate.src` may not outlive stack unwind so we must copy it.
|
2897
|
-
// This is needed since we often parse dynamically generated code,
|
2898
|
-
// e.g. for interpolations, and we normally don't want to keep this
|
2899
|
-
// memory around after we parsed the AST tree successfully. Only on
|
2900
|
-
// errors we want to preserve them for better error reporting.
|
2901
|
-
char *src_copy = sass_copy_c_string(pstate.src);
|
2902
|
-
pstate.src = src_copy;
|
2903
2892
|
traces.push_back(Backtrace(pstate));
|
2904
|
-
throw Exception::InvalidSass(pstate, traces, msg
|
2905
|
-
}
|
2906
|
-
|
2907
|
-
void Parser::error(std::string msg)
|
2908
|
-
{
|
2909
|
-
error(msg, pstate);
|
2893
|
+
throw Exception::InvalidSass(pstate, traces, msg);
|
2910
2894
|
}
|
2911
2895
|
|
2912
2896
|
// print a css parsing error with actual context information from parsed source
|
2913
|
-
void Parser::css_error(const
|
2897
|
+
void Parser::css_error(const sass::string& msg, const sass::string& prefix, const sass::string& middle, const bool trim)
|
2914
2898
|
{
|
2915
2899
|
int max_len = 18;
|
2916
2900
|
const char* end = this->end;
|
@@ -2919,13 +2903,13 @@ namespace Sass {
|
|
2919
2903
|
if (!pos) pos = position;
|
2920
2904
|
|
2921
2905
|
const char* last_pos(pos);
|
2922
|
-
if (last_pos >
|
2923
|
-
utf8::prior(last_pos,
|
2906
|
+
if (last_pos > begin) {
|
2907
|
+
utf8::prior(last_pos, begin);
|
2924
2908
|
}
|
2925
2909
|
// backup position to last significant char
|
2926
|
-
while (trim && last_pos >
|
2910
|
+
while (trim && last_pos > begin&& last_pos < end) {
|
2927
2911
|
if (!Util::ascii_isspace(static_cast<unsigned char>(*last_pos))) break;
|
2928
|
-
utf8::prior(last_pos,
|
2912
|
+
utf8::prior(last_pos, begin);
|
2929
2913
|
}
|
2930
2914
|
|
2931
2915
|
bool ellipsis_left = false;
|
@@ -2934,9 +2918,9 @@ namespace Sass {
|
|
2934
2918
|
|
2935
2919
|
if (*pos_left) utf8::next(pos_left, end);
|
2936
2920
|
if (*end_left) utf8::next(end_left, end);
|
2937
|
-
while (pos_left >
|
2921
|
+
while (pos_left > begin) {
|
2938
2922
|
if (utf8::distance(pos_left, end_left) >= max_len) {
|
2939
|
-
utf8::prior(pos_left,
|
2923
|
+
utf8::prior(pos_left, begin);
|
2940
2924
|
ellipsis_left = *(pos_left) != '\n' &&
|
2941
2925
|
*(pos_left) != '\r';
|
2942
2926
|
utf8::next(pos_left, end);
|
@@ -2944,13 +2928,13 @@ namespace Sass {
|
|
2944
2928
|
}
|
2945
2929
|
|
2946
2930
|
const char* prev = pos_left;
|
2947
|
-
utf8::prior(prev,
|
2931
|
+
utf8::prior(prev, begin);
|
2948
2932
|
if (*prev == '\r') break;
|
2949
2933
|
if (*prev == '\n') break;
|
2950
2934
|
pos_left = prev;
|
2951
2935
|
}
|
2952
|
-
if (pos_left <
|
2953
|
-
pos_left =
|
2936
|
+
if (pos_left < begin) {
|
2937
|
+
pos_left = begin;
|
2954
2938
|
}
|
2955
2939
|
|
2956
2940
|
bool ellipsis_right = false;
|
@@ -2968,14 +2952,12 @@ namespace Sass {
|
|
2968
2952
|
}
|
2969
2953
|
// if (*end_right == 0) end_right ++;
|
2970
2954
|
|
2971
|
-
|
2972
|
-
|
2955
|
+
sass::string left(pos_left, end_left);
|
2956
|
+
sass::string right(pos_right, end_right);
|
2973
2957
|
size_t left_subpos = left.size() > 15 ? left.size() - 15 : 0;
|
2974
2958
|
size_t right_subpos = right.size() > 15 ? right.size() - 15 : 0;
|
2975
2959
|
if (left_subpos && ellipsis_left) left = ellipsis + left.substr(left_subpos);
|
2976
2960
|
if (right_subpos && ellipsis_right) right = right.substr(right_subpos) + ellipsis;
|
2977
|
-
// Hotfix when source is null, probably due to interpolation parsing!?
|
2978
|
-
if (source == NULL || *source == 0) source = pstate.src;
|
2979
2961
|
// now pass new message to the more generic error function
|
2980
2962
|
error(msg + prefix + quote(left) + middle + quote(right));
|
2981
2963
|
}
|