sassc 1.9.0 → 1.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +30 -3
- data/ext/libsass/.gitignore +3 -0
- data/ext/libsass/.travis.yml +1 -1
- data/ext/libsass/GNUmakefile.am +7 -7
- data/ext/libsass/Makefile +7 -4
- data/ext/libsass/Makefile.conf +0 -1
- data/ext/libsass/appveyor.yml +6 -2
- data/ext/libsass/docs/api-context.md +4 -4
- data/ext/libsass/docs/api-doc.md +29 -11
- data/ext/libsass/docs/api-importer-example.md +5 -5
- data/ext/libsass/docs/build-on-windows.md +1 -1
- data/ext/libsass/include/sass/base.h +10 -0
- data/ext/libsass/include/sass/version.h +4 -0
- data/ext/libsass/include/sass/version.h.in +4 -0
- data/ext/libsass/include/sass2scss.h +1 -1
- data/ext/libsass/script/ci-build-libsass +15 -3
- data/ext/libsass/src/ast.cpp +161 -6
- data/ext/libsass/src/ast.hpp +71 -44
- data/ext/libsass/src/ast_factory.hpp +1 -1
- data/ext/libsass/src/ast_fwd_decl.hpp +2 -2
- data/ext/libsass/src/constants.cpp +2 -4
- data/ext/libsass/src/constants.hpp +3 -4
- data/ext/libsass/src/context.cpp +16 -17
- data/ext/libsass/src/context.hpp +2 -2
- data/ext/libsass/src/cssize.cpp +19 -8
- data/ext/libsass/src/cssize.hpp +5 -2
- data/ext/libsass/src/debugger.hpp +6 -3
- data/ext/libsass/src/emitter.cpp +1 -1
- data/ext/libsass/src/environment.cpp +1 -1
- data/ext/libsass/src/eval.cpp +42 -14
- data/ext/libsass/src/eval.hpp +1 -1
- data/ext/libsass/src/expand.cpp +24 -8
- data/ext/libsass/src/expand.hpp +2 -1
- data/ext/libsass/src/extend.cpp +55 -15
- data/ext/libsass/src/extend.hpp +5 -1
- data/ext/libsass/src/functions.cpp +10 -5
- data/ext/libsass/src/inspect.cpp +25 -19
- data/ext/libsass/src/inspect.hpp +2 -2
- data/ext/libsass/src/json.cpp +20 -9
- data/ext/libsass/src/json.hpp +5 -5
- data/ext/libsass/src/lexer.cpp +4 -1
- data/ext/libsass/src/lexer.hpp +21 -0
- data/ext/libsass/src/listize.cpp +2 -1
- data/ext/libsass/src/operation.hpp +4 -4
- data/ext/libsass/src/output.cpp +1 -1
- data/ext/libsass/src/output.hpp +1 -1
- data/ext/libsass/src/parser.cpp +189 -90
- data/ext/libsass/src/parser.hpp +42 -2
- data/ext/libsass/src/prelexer.cpp +474 -7
- data/ext/libsass/src/prelexer.hpp +15 -2
- data/ext/libsass/src/remove_placeholders.cpp +5 -5
- data/ext/libsass/src/remove_placeholders.hpp +3 -2
- data/ext/libsass/src/sass.cpp +33 -3
- data/ext/libsass/src/sass2scss.cpp +7 -0
- data/ext/libsass/src/sass_context.cpp +32 -62
- data/ext/libsass/src/sass_functions.cpp +3 -3
- data/ext/libsass/src/sass_values.cpp +5 -5
- data/ext/libsass/src/utf8/unchecked.h +16 -16
- data/ext/libsass/src/util.cpp +51 -30
- data/ext/libsass/src/util.hpp +6 -1
- data/ext/libsass/win/libsass.targets +0 -2
- data/ext/libsass/win/libsass.vcxproj.filters +0 -6
- data/lib/sassc/engine.rb +4 -1
- data/lib/sassc/error.rb +23 -1
- data/lib/sassc/version.rb +1 -1
- data/test/error_test.rb +27 -0
- data/test/native_test.rb +1 -1
- metadata +5 -5
- data/ext/libsass/include/sass/interface.h +0 -105
- data/ext/libsass/src/sass_interface.cpp +0 -215
data/ext/libsass/src/parser.hpp
CHANGED
@@ -133,6 +133,8 @@ namespace Sass {
|
|
133
133
|
const char* lex(bool lazy = true, bool force = false)
|
134
134
|
{
|
135
135
|
|
136
|
+
if (*position == 0) return 0;
|
137
|
+
|
136
138
|
// position considered before lexed token
|
137
139
|
// we can skip whitespace or comments for
|
138
140
|
// lazy developers (but we need control)
|
@@ -298,12 +300,22 @@ namespace Sass {
|
|
298
300
|
Supports_Condition* parse_supports_declaration();
|
299
301
|
Supports_Condition* parse_supports_condition_in_parens();
|
300
302
|
At_Root_Block* parse_at_root_block();
|
301
|
-
|
302
|
-
|
303
|
+
At_Root_Query* parse_at_root_query();
|
304
|
+
String_Schema* parse_almost_any_value();
|
305
|
+
Directive* parse_special_directive();
|
306
|
+
Directive* parse_prefixed_directive();
|
307
|
+
Directive* parse_directive();
|
303
308
|
Warning* parse_warning();
|
304
309
|
Error* parse_error();
|
305
310
|
Debug* parse_debug();
|
306
311
|
|
312
|
+
// be more like ruby sass
|
313
|
+
Expression* lex_almost_any_value_token();
|
314
|
+
Expression* lex_almost_any_value_chars();
|
315
|
+
Expression* lex_interp_string();
|
316
|
+
Expression* lex_interp_uri();
|
317
|
+
Expression* lex_interpolation();
|
318
|
+
|
307
319
|
// these will throw errors
|
308
320
|
Token lex_variable();
|
309
321
|
Token lex_identifier();
|
@@ -319,6 +331,34 @@ namespace Sass {
|
|
319
331
|
|
320
332
|
void throw_syntax_error(std::string message, size_t ln = 0);
|
321
333
|
void throw_read_error(std::string message, size_t ln = 0);
|
334
|
+
|
335
|
+
|
336
|
+
template <Prelexer::prelexer open, Prelexer::prelexer close>
|
337
|
+
Expression* lex_interp()
|
338
|
+
{
|
339
|
+
if (lex < open >(false)) {
|
340
|
+
String_Schema* schema = SASS_MEMORY_NEW(ctx.mem, String_Schema, pstate);
|
341
|
+
// std::cerr << "LEX [[" << std::string(lexed) << "]]\n";
|
342
|
+
*schema << SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, lexed);
|
343
|
+
if (position[0] == '#' && position[1] == '{') {
|
344
|
+
Expression* itpl = lex_interpolation();
|
345
|
+
if (itpl) *schema << itpl;
|
346
|
+
while (lex < close >(false)) {
|
347
|
+
// std::cerr << "LEX [[" << std::string(lexed) << "]]\n";
|
348
|
+
*schema << SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, lexed);
|
349
|
+
if (position[0] == '#' && position[1] == '{') {
|
350
|
+
Expression* itpl = lex_interpolation();
|
351
|
+
if (itpl) *schema << itpl;
|
352
|
+
} else {
|
353
|
+
return schema;
|
354
|
+
}
|
355
|
+
}
|
356
|
+
} else {
|
357
|
+
return SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, lexed);
|
358
|
+
}
|
359
|
+
}
|
360
|
+
return 0;
|
361
|
+
}
|
322
362
|
};
|
323
363
|
|
324
364
|
size_t check_bom_chars(const char* src, const char *end, const unsigned char* bom, size_t len);
|
@@ -16,6 +16,248 @@ namespace Sass {
|
|
16
16
|
namespace Prelexer {
|
17
17
|
|
18
18
|
|
19
|
+
/*
|
20
|
+
|
21
|
+
def string_re(open, close)
|
22
|
+
/#{open}((?:\\.|\#(?!\{)|[^#{close}\\#])*)(#{close}|#\{)/m
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# A hash of regular expressions that are used for tokenizing strings.
|
27
|
+
#
|
28
|
+
# The key is a `[Symbol, Boolean]` pair.
|
29
|
+
# The symbol represents which style of quotation to use,
|
30
|
+
# while the boolean represents whether or not the string
|
31
|
+
# is following an interpolated segment.
|
32
|
+
STRING_REGULAR_EXPRESSIONS = {
|
33
|
+
:double => {
|
34
|
+
/#{open}((?:\\.|\#(?!\{)|[^#{close}\\#])*)(#{close}|#\{)/m
|
35
|
+
false => string_re('"', '"'),
|
36
|
+
true => string_re('', '"')
|
37
|
+
},
|
38
|
+
:single => {
|
39
|
+
false => string_re("'", "'"),
|
40
|
+
true => string_re('', "'")
|
41
|
+
},
|
42
|
+
:uri => {
|
43
|
+
false => /url\(#{W}(#{URLCHAR}*?)(#{W}\)|#\{)/,
|
44
|
+
true => /(#{URLCHAR}*?)(#{W}\)|#\{)/
|
45
|
+
},
|
46
|
+
# Defined in https://developer.mozilla.org/en/CSS/@-moz-document as a
|
47
|
+
# non-standard version of http://www.w3.org/TR/css3-conditional/
|
48
|
+
:url_prefix => {
|
49
|
+
false => /url-prefix\(#{W}(#{URLCHAR}*?)(#{W}\)|#\{)/,
|
50
|
+
true => /(#{URLCHAR}*?)(#{W}\)|#\{)/
|
51
|
+
},
|
52
|
+
:domain => {
|
53
|
+
false => /domain\(#{W}(#{URLCHAR}*?)(#{W}\)|#\{)/,
|
54
|
+
true => /(#{URLCHAR}*?)(#{W}\)|#\{)/
|
55
|
+
}
|
56
|
+
}
|
57
|
+
*/
|
58
|
+
|
59
|
+
/*
|
60
|
+
/#{open}
|
61
|
+
(
|
62
|
+
\\.
|
63
|
+
|
|
64
|
+
\# (?!\{)
|
65
|
+
|
|
66
|
+
[^#{close}\\#]
|
67
|
+
)*
|
68
|
+
(#{close}|#\{)
|
69
|
+
/m
|
70
|
+
false => string_re('"', '"'),
|
71
|
+
true => string_re('', '"')
|
72
|
+
*/
|
73
|
+
extern const char string_double_negates[] = "\"\\#";
|
74
|
+
const char* re_string_double_close(const char* src)
|
75
|
+
{
|
76
|
+
return sequence <
|
77
|
+
// valid chars
|
78
|
+
zero_plus <
|
79
|
+
alternatives <
|
80
|
+
// escaped char
|
81
|
+
sequence <
|
82
|
+
exactly <'\\'>,
|
83
|
+
any_char
|
84
|
+
>,
|
85
|
+
// non interpolate hash
|
86
|
+
sequence <
|
87
|
+
exactly <'#'>,
|
88
|
+
negate <
|
89
|
+
exactly <'{'>
|
90
|
+
>
|
91
|
+
>,
|
92
|
+
// other valid chars
|
93
|
+
neg_class_char <
|
94
|
+
string_double_negates
|
95
|
+
>
|
96
|
+
>
|
97
|
+
>,
|
98
|
+
// quoted string closer
|
99
|
+
// or interpolate opening
|
100
|
+
alternatives <
|
101
|
+
exactly <'"'>,
|
102
|
+
lookahead < exactly< hash_lbrace > >
|
103
|
+
>
|
104
|
+
>(src);
|
105
|
+
}
|
106
|
+
|
107
|
+
const char* re_string_double_open(const char* src)
|
108
|
+
{
|
109
|
+
return sequence <
|
110
|
+
// quoted string opener
|
111
|
+
exactly <'"'>,
|
112
|
+
// valid chars
|
113
|
+
zero_plus <
|
114
|
+
alternatives <
|
115
|
+
// escaped char
|
116
|
+
sequence <
|
117
|
+
exactly <'\\'>,
|
118
|
+
any_char
|
119
|
+
>,
|
120
|
+
// non interpolate hash
|
121
|
+
sequence <
|
122
|
+
exactly <'#'>,
|
123
|
+
negate <
|
124
|
+
exactly <'{'>
|
125
|
+
>
|
126
|
+
>,
|
127
|
+
// other valid chars
|
128
|
+
neg_class_char <
|
129
|
+
string_double_negates
|
130
|
+
>
|
131
|
+
>
|
132
|
+
>,
|
133
|
+
// quoted string closer
|
134
|
+
// or interpolate opening
|
135
|
+
alternatives <
|
136
|
+
exactly <'"'>,
|
137
|
+
lookahead < exactly< hash_lbrace > >
|
138
|
+
>
|
139
|
+
>(src);
|
140
|
+
}
|
141
|
+
|
142
|
+
extern const char string_single_negates[] = "'\\#";
|
143
|
+
const char* re_string_single_close(const char* src)
|
144
|
+
{
|
145
|
+
return sequence <
|
146
|
+
// valid chars
|
147
|
+
zero_plus <
|
148
|
+
alternatives <
|
149
|
+
// escaped char
|
150
|
+
sequence <
|
151
|
+
exactly <'\\'>,
|
152
|
+
any_char
|
153
|
+
>,
|
154
|
+
// non interpolate hash
|
155
|
+
sequence <
|
156
|
+
exactly <'#'>,
|
157
|
+
negate <
|
158
|
+
exactly <'{'>
|
159
|
+
>
|
160
|
+
>,
|
161
|
+
// other valid chars
|
162
|
+
neg_class_char <
|
163
|
+
string_single_negates
|
164
|
+
>
|
165
|
+
>
|
166
|
+
>,
|
167
|
+
// quoted string closer
|
168
|
+
// or interpolate opening
|
169
|
+
alternatives <
|
170
|
+
exactly <'\''>,
|
171
|
+
lookahead < exactly< hash_lbrace > >
|
172
|
+
>
|
173
|
+
>(src);
|
174
|
+
}
|
175
|
+
|
176
|
+
const char* re_string_single_open(const char* src)
|
177
|
+
{
|
178
|
+
return sequence <
|
179
|
+
// quoted string opener
|
180
|
+
exactly <'\''>,
|
181
|
+
// valid chars
|
182
|
+
zero_plus <
|
183
|
+
alternatives <
|
184
|
+
// escaped char
|
185
|
+
sequence <
|
186
|
+
exactly <'\\'>,
|
187
|
+
any_char
|
188
|
+
>,
|
189
|
+
// non interpolate hash
|
190
|
+
sequence <
|
191
|
+
exactly <'#'>,
|
192
|
+
negate <
|
193
|
+
exactly <'{'>
|
194
|
+
>
|
195
|
+
>,
|
196
|
+
// other valid chars
|
197
|
+
neg_class_char <
|
198
|
+
string_single_negates
|
199
|
+
>
|
200
|
+
>
|
201
|
+
>,
|
202
|
+
// quoted string closer
|
203
|
+
// or interpolate opening
|
204
|
+
alternatives <
|
205
|
+
exactly <'\''>,
|
206
|
+
lookahead < exactly< hash_lbrace > >
|
207
|
+
>
|
208
|
+
>(src);
|
209
|
+
}
|
210
|
+
|
211
|
+
/*
|
212
|
+
:uri => {
|
213
|
+
false => /url\(#{W}(#{URLCHAR}*?)(#{W}\)|#\{)/,
|
214
|
+
true => /(#{URLCHAR}*?)(#{W}\)|#\{)/
|
215
|
+
},
|
216
|
+
*/
|
217
|
+
const char* re_string_uri_close(const char* src)
|
218
|
+
{
|
219
|
+
return sequence <
|
220
|
+
non_greedy<
|
221
|
+
alternatives<
|
222
|
+
class_char< real_uri_chars >,
|
223
|
+
uri_character,
|
224
|
+
NONASCII,
|
225
|
+
ESCAPE
|
226
|
+
>,
|
227
|
+
alternatives<
|
228
|
+
sequence < optional < W >, exactly <')'> >,
|
229
|
+
lookahead < exactly< hash_lbrace > >
|
230
|
+
>
|
231
|
+
>,
|
232
|
+
optional <
|
233
|
+
sequence < optional < W >, exactly <')'> >
|
234
|
+
>
|
235
|
+
>(src);
|
236
|
+
}
|
237
|
+
|
238
|
+
const char* re_string_uri_open(const char* src)
|
239
|
+
{
|
240
|
+
return sequence <
|
241
|
+
exactly <'u'>,
|
242
|
+
exactly <'r'>,
|
243
|
+
exactly <'l'>,
|
244
|
+
exactly <'('>,
|
245
|
+
W,
|
246
|
+
non_greedy<
|
247
|
+
alternatives<
|
248
|
+
class_char< real_uri_chars >,
|
249
|
+
uri_character,
|
250
|
+
NONASCII,
|
251
|
+
ESCAPE
|
252
|
+
>,
|
253
|
+
alternatives<
|
254
|
+
sequence < W, exactly <')'> >,
|
255
|
+
exactly< hash_lbrace >
|
256
|
+
>
|
257
|
+
>
|
258
|
+
>(src);
|
259
|
+
}
|
260
|
+
|
19
261
|
// Match a line comment (/.*?(?=\n|\r\n?|\Z)/.
|
20
262
|
const char* line_comment(const char* src)
|
21
263
|
{
|
@@ -370,6 +612,133 @@ namespace Sass {
|
|
370
612
|
return sequence<exactly<'@'>, identifier>(src);
|
371
613
|
}
|
372
614
|
|
615
|
+
/*
|
616
|
+
tok(%r{
|
617
|
+
(
|
618
|
+
\\.
|
619
|
+
|
|
620
|
+
(?!url\()
|
621
|
+
[^"'/\#!;\{\}] # "
|
622
|
+
|
|
623
|
+
/(?![\*\/])
|
624
|
+
|
|
625
|
+
\#(?!\{)
|
626
|
+
|
|
627
|
+
!(?![a-z]) # TODO: never consume "!" when issue 1126 is fixed.
|
628
|
+
)+
|
629
|
+
}xi) || tok(COMMENT) || tok(SINGLE_LINE_COMMENT) || interp_string || interp_uri ||
|
630
|
+
interpolation(:warn_for_color)
|
631
|
+
*/
|
632
|
+
const char* re_almost_any_value_token(const char* src) {
|
633
|
+
|
634
|
+
return alternatives <
|
635
|
+
one_plus <
|
636
|
+
alternatives <
|
637
|
+
sequence <
|
638
|
+
exactly <'\\'>,
|
639
|
+
any_char
|
640
|
+
>,
|
641
|
+
sequence <
|
642
|
+
negate <
|
643
|
+
sequence <
|
644
|
+
exactly < url_kwd >,
|
645
|
+
exactly <'('>
|
646
|
+
>
|
647
|
+
>,
|
648
|
+
neg_class_char <
|
649
|
+
almost_any_value_class
|
650
|
+
>
|
651
|
+
>,
|
652
|
+
sequence <
|
653
|
+
exactly <'/'>,
|
654
|
+
negate <
|
655
|
+
alternatives <
|
656
|
+
exactly <'/'>,
|
657
|
+
exactly <'*'>
|
658
|
+
>
|
659
|
+
>
|
660
|
+
>,
|
661
|
+
sequence <
|
662
|
+
exactly <'\\'>,
|
663
|
+
exactly <'#'>,
|
664
|
+
negate <
|
665
|
+
exactly <'{'>
|
666
|
+
>
|
667
|
+
>,
|
668
|
+
sequence <
|
669
|
+
exactly <'!'>,
|
670
|
+
negate <
|
671
|
+
alpha
|
672
|
+
>
|
673
|
+
>
|
674
|
+
>
|
675
|
+
>,
|
676
|
+
block_comment,
|
677
|
+
line_comment,
|
678
|
+
interpolant,
|
679
|
+
space,
|
680
|
+
sequence <
|
681
|
+
exactly<'u'>,
|
682
|
+
exactly<'r'>,
|
683
|
+
exactly<'l'>,
|
684
|
+
exactly<'('>,
|
685
|
+
zero_plus <
|
686
|
+
alternatives <
|
687
|
+
class_char< real_uri_chars >,
|
688
|
+
uri_character,
|
689
|
+
NONASCII,
|
690
|
+
ESCAPE
|
691
|
+
>
|
692
|
+
>,
|
693
|
+
// false => /url\(#{W}(#{URLCHAR}*?)(#{W}\)|#\{)/,
|
694
|
+
// true => /(#{URLCHAR}*?)(#{W}\)|#\{)/
|
695
|
+
exactly<')'>
|
696
|
+
>
|
697
|
+
>(src);
|
698
|
+
}
|
699
|
+
|
700
|
+
/*
|
701
|
+
DIRECTIVES = Set[:mixin, :include, :function, :return, :debug, :warn, :for,
|
702
|
+
:each, :while, :if, :else, :extend, :import, :media, :charset, :content,
|
703
|
+
:_moz_document, :at_root, :error]
|
704
|
+
*/
|
705
|
+
const char* re_special_directive(const char* src) {
|
706
|
+
return alternatives <
|
707
|
+
word < mixin_kwd >,
|
708
|
+
word < include_kwd >,
|
709
|
+
word < function_kwd >,
|
710
|
+
word < return_kwd >,
|
711
|
+
word < debug_kwd >,
|
712
|
+
word < warn_kwd >,
|
713
|
+
word < for_kwd >,
|
714
|
+
word < each_kwd >,
|
715
|
+
word < while_kwd >,
|
716
|
+
word < if_kwd >,
|
717
|
+
word < else_kwd >,
|
718
|
+
word < extend_kwd >,
|
719
|
+
word < import_kwd >,
|
720
|
+
word < media_kwd >,
|
721
|
+
word < charset_kwd >,
|
722
|
+
word < content_kwd >,
|
723
|
+
// exactly < moz_document_kwd >,
|
724
|
+
word < at_root_kwd >,
|
725
|
+
word < error_kwd >
|
726
|
+
>(src);
|
727
|
+
}
|
728
|
+
|
729
|
+
const char* re_prefixed_directive(const char* src) {
|
730
|
+
return sequence <
|
731
|
+
optional <
|
732
|
+
sequence <
|
733
|
+
exactly <'-'>,
|
734
|
+
one_plus < alnum >,
|
735
|
+
exactly <'-'>
|
736
|
+
>
|
737
|
+
>,
|
738
|
+
exactly < supports_kwd >
|
739
|
+
>(src);
|
740
|
+
}
|
741
|
+
|
373
742
|
const char* re_reference_combinator(const char* src) {
|
374
743
|
return sequence <
|
375
744
|
optional <
|
@@ -508,7 +877,7 @@ namespace Sass {
|
|
508
877
|
return one_plus< alternatives< alnum,
|
509
878
|
exactly<'-'>,
|
510
879
|
exactly<'_'>,
|
511
|
-
|
880
|
+
escape_seq > >(src);
|
512
881
|
}
|
513
882
|
|
514
883
|
const char* kwd_warn(const char* src) {
|
@@ -586,7 +955,7 @@ namespace Sass {
|
|
586
955
|
}
|
587
956
|
|
588
957
|
const char* hyphens_and_identifier(const char* src) {
|
589
|
-
return sequence< zero_plus< exactly< '-' > >,
|
958
|
+
return sequence< zero_plus< exactly< '-' > >, identifier_alnums >(src);
|
590
959
|
}
|
591
960
|
const char* hyphens_and_name(const char* src) {
|
592
961
|
return sequence< zero_plus< exactly< '-' > >, name >(src);
|
@@ -596,11 +965,11 @@ namespace Sass {
|
|
596
965
|
}
|
597
966
|
// Match CSS id names.
|
598
967
|
const char* id_name(const char* src) {
|
599
|
-
return sequence<exactly<'#'>,
|
968
|
+
return sequence<exactly<'#'>, identifier_alnums >(src);
|
600
969
|
}
|
601
970
|
// Match CSS class names.
|
602
971
|
const char* class_name(const char* src) {
|
603
|
-
return sequence<exactly<'.'>, identifier>(src);
|
972
|
+
return sequence<exactly<'.'>, identifier >(src);
|
604
973
|
}
|
605
974
|
// Attribute name in an attribute selector.
|
606
975
|
const char* attribute_name(const char* src) {
|
@@ -609,7 +978,7 @@ namespace Sass {
|
|
609
978
|
}
|
610
979
|
// match placeholder selectors
|
611
980
|
const char* placeholder(const char* src) {
|
612
|
-
return sequence<exactly<'%'>,
|
981
|
+
return sequence<exactly<'%'>, identifier_alnums >(src);
|
613
982
|
}
|
614
983
|
// Match CSS numeric constants.
|
615
984
|
|
@@ -825,6 +1194,22 @@ namespace Sass {
|
|
825
1194
|
return sequence<exactly<'$'>, identifier>(src);
|
826
1195
|
}
|
827
1196
|
|
1197
|
+
// parse `calc`, `-a-calc` and `--b-c-calc`
|
1198
|
+
// but do not parse `foocalc` or `foo-calc`
|
1199
|
+
const char* calc_fn_call(const char* src) {
|
1200
|
+
return sequence <
|
1201
|
+
optional < sequence <
|
1202
|
+
hyphens,
|
1203
|
+
one_plus < sequence <
|
1204
|
+
strict_identifier,
|
1205
|
+
hyphens
|
1206
|
+
> >
|
1207
|
+
> >,
|
1208
|
+
exactly < calc_fn_kwd >,
|
1209
|
+
word_boundary
|
1210
|
+
>(src);
|
1211
|
+
}
|
1212
|
+
|
828
1213
|
// Match Sass boolean keywords.
|
829
1214
|
const char* kwd_true(const char* src) {
|
830
1215
|
return word<true_kwd>(src);
|
@@ -1167,6 +1552,83 @@ namespace Sass {
|
|
1167
1552
|
>(src);
|
1168
1553
|
}
|
1169
1554
|
|
1555
|
+
const char* re_selector_list(const char* src) {
|
1556
|
+
return alternatives <
|
1557
|
+
// partial bem selector
|
1558
|
+
sequence <
|
1559
|
+
ampersand,
|
1560
|
+
one_plus <
|
1561
|
+
exactly < '-' >
|
1562
|
+
>,
|
1563
|
+
word_boundary,
|
1564
|
+
optional_spaces
|
1565
|
+
>,
|
1566
|
+
// main selector matching
|
1567
|
+
one_plus <
|
1568
|
+
alternatives <
|
1569
|
+
// consume whitespace and comments
|
1570
|
+
spaces, block_comment, line_comment,
|
1571
|
+
// match `/deep/` selector (pass-trough)
|
1572
|
+
// there is no functionality for it yet
|
1573
|
+
schema_reference_combinator,
|
1574
|
+
// match selector ops /[*&%,\[\]]/
|
1575
|
+
class_char < selector_lookahead_ops >,
|
1576
|
+
// match selector combinators /[>+~]/
|
1577
|
+
class_char < selector_combinator_ops >,
|
1578
|
+
// match attribute compare operators
|
1579
|
+
sequence <
|
1580
|
+
exactly <'('>,
|
1581
|
+
optional_spaces,
|
1582
|
+
optional <re_selector_list>,
|
1583
|
+
optional_spaces,
|
1584
|
+
exactly <')'>
|
1585
|
+
>,
|
1586
|
+
alternatives <
|
1587
|
+
exact_match, class_match, dash_match,
|
1588
|
+
prefix_match, suffix_match, substring_match
|
1589
|
+
>,
|
1590
|
+
// main selector match
|
1591
|
+
sequence <
|
1592
|
+
// allow namespace prefix
|
1593
|
+
optional < namespace_schema >,
|
1594
|
+
// modifiers prefixes
|
1595
|
+
alternatives <
|
1596
|
+
sequence <
|
1597
|
+
exactly <'#'>,
|
1598
|
+
// not for interpolation
|
1599
|
+
negate < exactly <'{'> >
|
1600
|
+
>,
|
1601
|
+
// class match
|
1602
|
+
exactly <'.'>,
|
1603
|
+
// single or double colon
|
1604
|
+
optional < pseudo_prefix >
|
1605
|
+
>,
|
1606
|
+
// accept hypens in token
|
1607
|
+
one_plus < sequence <
|
1608
|
+
// can start with hyphens
|
1609
|
+
zero_plus < exactly<'-'> >,
|
1610
|
+
// now the main token
|
1611
|
+
alternatives <
|
1612
|
+
kwd_optional,
|
1613
|
+
exactly <'*'>,
|
1614
|
+
quoted_string,
|
1615
|
+
interpolant,
|
1616
|
+
identifier,
|
1617
|
+
variable,
|
1618
|
+
percentage,
|
1619
|
+
binomial,
|
1620
|
+
dimension,
|
1621
|
+
alnum
|
1622
|
+
>
|
1623
|
+
> >,
|
1624
|
+
// can also end with hyphens
|
1625
|
+
zero_plus < exactly<'-'> >
|
1626
|
+
>
|
1627
|
+
>
|
1628
|
+
>
|
1629
|
+
>(src);
|
1630
|
+
}
|
1631
|
+
|
1170
1632
|
const char* type_selector(const char* src) {
|
1171
1633
|
return sequence< optional<namespace_schema>, identifier>(src);
|
1172
1634
|
}
|
@@ -1183,6 +1645,12 @@ namespace Sass {
|
|
1183
1645
|
// lexer special_fn: these functions cannot be overloaded
|
1184
1646
|
// (/((-[\w-]+-)?(calc|element)|expression|progid:[a-z\.]*)\(/i)
|
1185
1647
|
const char* re_special_fun(const char* src) {
|
1648
|
+
|
1649
|
+
// match this first as we test prefix hyphens
|
1650
|
+
if (const char* calc = calc_fn_call(src)) {
|
1651
|
+
return calc;
|
1652
|
+
}
|
1653
|
+
|
1186
1654
|
return sequence <
|
1187
1655
|
optional <
|
1188
1656
|
sequence <
|
@@ -1197,8 +1665,7 @@ namespace Sass {
|
|
1197
1665
|
>
|
1198
1666
|
>,
|
1199
1667
|
alternatives <
|
1200
|
-
|
1201
|
-
exactly < expression_kwd >,
|
1668
|
+
word < expression_kwd >,
|
1202
1669
|
sequence <
|
1203
1670
|
sequence <
|
1204
1671
|
exactly < progid_kwd >,
|