1#ifndef SASS_PRELEXER_H
2#define SASS_PRELEXER_H
3
4#include <cstring>
5#include "lexer.hpp"
6
7namespace Sass {
8 // using namespace Lexer;
9 namespace Prelexer {
10
11 //####################################
12 // KEYWORD "REGEX" MATCHERS
13 //####################################
14
15 // Match Sass boolean keywords.
16 const char* kwd_true(const char* src);
17 const char* kwd_false(const char* src);
18 const char* kwd_only(const char* src);
19 const char* kwd_and(const char* src);
20 const char* kwd_or(const char* src);
21 const char* kwd_not(const char* src);
22 const char* kwd_eq(const char* src);
23 const char* kwd_neq(const char* src);
24 const char* kwd_gt(const char* src);
25 const char* kwd_gte(const char* src);
26 const char* kwd_lt(const char* src);
27 const char* kwd_lte(const char* src);
28 const char* kwd_using(const char* src);
29
30 // Match standard control chars
31 const char* kwd_at(const char* src);
32 const char* kwd_dot(const char* src);
33 const char* kwd_comma(const char* src);
34 const char* kwd_colon(const char* src);
35 const char* kwd_slash(const char* src);
36 const char* kwd_star(const char* src);
37 const char* kwd_plus(const char* src);
38 const char* kwd_minus(const char* src);
39
40 //####################################
41 // SPECIAL "REGEX" CONSTRUCTS
42 //####################################
43
44 // Match a sequence of characters delimited by the supplied chars.
45 template <char beg, char end, bool esc>
46 const char* delimited_by(const char* src) {
47 src = exactly<beg>(src);
48 if (!src) return 0;
49 const char* stop;
50 while (true) {
51 if (!*src) return 0;
52 stop = exactly<end>(src);
53 if (stop && (!esc || *(src - 1) != '\\')) return stop;
54 src = stop ? stop : src + 1;
55 }
56 }
57
58 // skip to delimiter (mx) inside given range
59 // this will savely skip over all quoted strings
60 // recursive skip stuff delimited by start/stop
61 // first start/opener must be consumed already!
62 template<prelexer start, prelexer stop>
63 const char* skip_over_scopes(const char* src, const char* end) {
64
65 size_t level = 0;
66 bool in_squote = false;
67 bool in_dquote = false;
68 bool in_backslash_escape = false;
69
70 while ((end == nullptr || src < end) && *src != '\0') {
71 // has escaped sequence?
72 if (in_backslash_escape) {
73 in_backslash_escape = false;
74 }
75 else if (*src == '\\') {
76 in_backslash_escape = true;
77 }
78 else if (*src == '"') {
79 in_dquote = ! in_dquote;
80 }
81 else if (*src == '\'') {
82 in_squote = ! in_squote;
83 }
84 else if (in_dquote || in_squote) {
85 // take everything literally
86 }
87
88 // find another opener inside?
89 else if (const char* pos = start(src)) {
90 ++ level; // increase counter
91 src = pos - 1; // advance position
92 }
93
94 // look for the closer (maybe final, maybe not)
95 else if (const char* final = stop(src)) {
96 // only close one level?
97 if (level > 0) -- level;
98 // return position at end of stop
99 // delimiter may be multiple chars
100 else return final;
101 // advance position
102 src = final - 1;
103 }
104
105 // next
106 ++ src;
107 }
108
109 return 0;
110 }
111
112 // skip to a skip delimited by parentheses
113 // uses smart `skip_over_scopes` internally
114 const char* parenthese_scope(const char* src);
115
116 // skip to delimiter (mx) inside given range
117 // this will savely skip over all quoted strings
118 // recursive skip stuff delimited by start/stop
119 // first start/opener must be consumed already!
120 template<prelexer start, prelexer stop>
121 const char* skip_over_scopes(const char* src) {
122 return skip_over_scopes<start, stop>(src, nullptr);
123 }
124
125 // Match a sequence of characters delimited by the supplied chars.
126 template <prelexer start, prelexer stop>
127 const char* recursive_scopes(const char* src) {
128 // parse opener
129 src = start(src);
130 // abort if not found
131 if (!src) return 0;
132 // parse the rest until final closer
133 return skip_over_scopes<start, stop>(src);
134 }
135
136 // Match a sequence of characters delimited by the supplied strings.
137 template <const char* beg, const char* end, bool esc>
138 const char* delimited_by(const char* src) {
139 src = exactly<beg>(src);
140 if (!src) return 0;
141 const char* stop;
142 while (true) {
143 if (!*src) return 0;
144 stop = exactly<end>(src);
145 if (stop && (!esc || *(src - 1) != '\\')) return stop;
146 src = stop ? stop : src + 1;
147 }
148 }
149
150 // Tries to match a certain number of times (between the supplied interval).
151 template<prelexer mx, size_t lo, size_t hi>
152 const char* between(const char* src) {
153 for (size_t i = 0; i < lo; ++i) {
154 src = mx(src);
155 if (!src) return 0;
156 }
157 for (size_t i = lo; i <= hi; ++i) {
158 const char* new_src = mx(src);
159 if (!new_src) return src;
160 src = new_src;
161 }
162 return src;
163 }
164
165 // equivalent of STRING_REGULAR_EXPRESSIONS
166 const char* re_string_double_open(const char* src);
167 const char* re_string_double_close(const char* src);
168 const char* re_string_single_open(const char* src);
169 const char* re_string_single_close(const char* src);
170 const char* re_string_uri_open(const char* src);
171 const char* re_string_uri_close(const char* src);
172
173 // Match a line comment.
174 const char* line_comment(const char* src);
175
176 // Match a block comment.
177 const char* block_comment(const char* src);
178 // Match either.
179 const char* comment(const char* src);
180 // Match double- and single-quoted strings.
181 const char* double_quoted_string(const char* src);
182 const char* single_quoted_string(const char* src);
183 const char* quoted_string(const char* src);
184 // Match interpolants.
185 const char* interpolant(const char* src);
186 // Match number prefix ([\+\-]+)
187 const char* number_prefix(const char* src);
188
189 // Match zero plus white-space or line_comments
190 const char* optional_css_whitespace(const char* src);
191 const char* css_whitespace(const char* src);
192 // Match optional_css_whitepace plus block_comments
193 const char* optional_css_comments(const char* src);
194 const char* css_comments(const char* src);
195
196 // Match one backslash escaped char
197 const char* escape_seq(const char* src);
198
199 // Match CSS css variables.
200 const char* custom_property_name(const char* src);
201 // Match a CSS identifier.
202 const char* identifier(const char* src);
203 const char* identifier_alpha(const char* src);
204 const char* identifier_alnum(const char* src);
205 const char* strict_identifier(const char* src);
206 const char* strict_identifier_alpha(const char* src);
207 const char* strict_identifier_alnum(const char* src);
208 // Match a CSS unit identifier.
209 const char* one_unit(const char* src);
210 const char* multiple_units(const char* src);
211 const char* unit_identifier(const char* src);
212 // const char* strict_identifier_alnums(const char* src);
213 // Match reference selector.
214 const char* re_reference_combinator(const char* src);
215 const char* static_reference_combinator(const char* src);
216 const char* schema_reference_combinator(const char* src);
217
218 // Match interpolant schemas
219 const char* identifier_schema(const char* src);
220 const char* value_schema(const char* src);
221 const char* sass_value(const char* src);
222 // const char* filename(const char* src);
223 // const char* filename_schema(const char* src);
224 // const char* url_schema(const char* src);
225 // const char* url_value(const char* src);
226 const char* vendor_prefix(const char* src);
227
228 const char* re_special_directive(const char* src);
229 const char* re_prefixed_directive(const char* src);
230 const char* re_almost_any_value_token(const char* src);
231
232 // Match CSS '@' keywords.
233 const char* at_keyword(const char* src);
234 const char* kwd_import(const char* src);
235 const char* kwd_at_root(const char* src);
236 const char* kwd_with_directive(const char* src);
237 const char* kwd_without_directive(const char* src);
238 const char* kwd_media(const char* src);
239 const char* kwd_supports_directive(const char* src);
240 // const char* keyframes(const char* src);
241 // const char* keyf(const char* src);
242 const char* kwd_mixin(const char* src);
243 const char* kwd_function(const char* src);
244 const char* kwd_return_directive(const char* src);
245 const char* kwd_include_directive(const char* src);
246 const char* kwd_content_directive(const char* src);
247 const char* kwd_charset_directive(const char* src);
248 const char* kwd_extend(const char* src);
249
250 const char* unicode_seq(const char* src);
251
252 const char* kwd_if_directive(const char* src);
253 const char* kwd_else_directive(const char* src);
254 const char* elseif_directive(const char* src);
255
256 const char* kwd_for_directive(const char* src);
257 const char* kwd_from(const char* src);
258 const char* kwd_to(const char* src);
259 const char* kwd_through(const char* src);
260
261 const char* kwd_each_directive(const char* src);
262 const char* kwd_in(const char* src);
263
264 const char* kwd_while_directive(const char* src);
265
266 const char* re_nothing(const char* src);
267
268 const char* re_special_fun(const char* src);
269
270 const char* kwd_warn(const char* src);
271 const char* kwd_err(const char* src);
272 const char* kwd_dbg(const char* src);
273
274 const char* kwd_null(const char* src);
275
276 const char* re_selector_list(const char* src);
277 const char* re_type_selector(const char* src);
278 const char* re_static_expression(const char* src);
279
280 // identifier that can start with hyphens
281 const char* css_identifier(const char* src);
282 const char* css_ip_identifier(const char* src);
283
284 // Match CSS type selectors
285 const char* namespace_schema(const char* src);
286 const char* namespace_prefix(const char* src);
287 const char* type_selector(const char* src);
288 const char* hyphens_and_identifier(const char* src);
289 const char* hyphens_and_name(const char* src);
290 const char* universal(const char* src);
291 // Match CSS id names.
292 const char* id_name(const char* src);
293 // Match CSS class names.
294 const char* class_name(const char* src);
295 // Attribute name in an attribute selector
296 const char* attribute_name(const char* src);
297 // Match placeholder selectors.
298 const char* placeholder(const char* src);
299 // Match CSS numeric constants.
300 const char* op(const char* src);
301 const char* sign(const char* src);
302 const char* unsigned_number(const char* src);
303 const char* number(const char* src);
304 const char* coefficient(const char* src);
305 const char* binomial(const char* src);
306 const char* percentage(const char* src);
307 const char* ampersand(const char* src);
308 const char* dimension(const char* src);
309 const char* hex(const char* src);
310 const char* hexa(const char* src);
311 const char* hex0(const char* src);
312 // const char* rgb_prefix(const char* src);
313 // Match CSS uri specifiers.
314 const char* uri_prefix(const char* src);
315 // Match CSS "!important" keyword.
316 const char* kwd_important(const char* src);
317 // Match CSS "!optional" keyword.
318 const char* kwd_optional(const char* src);
319 // Match Sass "!default" keyword.
320 const char* default_flag(const char* src);
321 const char* global_flag(const char* src);
322 // Match CSS pseudo-class/element prefixes
323 const char* pseudo_prefix(const char* src);
324 // Match CSS function call openers.
325 const char* re_functional(const char* src);
326 const char* re_pseudo_selector(const char* src);
327 const char* functional_schema(const char* src);
328 const char* pseudo_not(const char* src);
329 // Match CSS 'odd' and 'even' keywords for functional pseudo-classes.
330 const char* even(const char* src);
331 const char* odd(const char* src);
332 // Match CSS attribute-matching operators.
333 const char* exact_match(const char* src);
334 const char* class_match(const char* src);
335 const char* dash_match(const char* src);
336 const char* prefix_match(const char* src);
337 const char* suffix_match(const char* src);
338 const char* substring_match(const char* src);
339 // Match CSS combinators.
340 // const char* adjacent_to(const char* src);
341 // const char* precedes(const char* src);
342 // const char* parent_of(const char* src);
343 // const char* ancestor_of(const char* src);
344
345 // Match SCSS variable names.
346 const char* variable(const char* src);
347 const char* calc_fn_call(const char* src);
348
349 // IE stuff
350 const char* ie_progid(const char* src);
351 const char* ie_expression(const char* src);
352 const char* ie_property(const char* src);
353 const char* ie_keyword_arg(const char* src);
354 const char* ie_keyword_arg_value(const char* src);
355 const char* ie_keyword_arg_property(const char* src);
356
357 // characters that terminate parsing of a list
358 const char* list_terminator(const char* src);
359 const char* space_list_terminator(const char* src);
360
361 // match url()
362 const char* H(const char* src);
363 const char* W(const char* src);
364 // `UNICODE` makes VS sad
365 const char* UUNICODE(const char* src);
366 const char* NONASCII(const char* src);
367 const char* ESCAPE(const char* src);
368 const char* real_uri(const char* src);
369 const char* real_uri_suffix(const char* src);
370 // const char* real_uri_prefix(const char* src);
371 const char* real_uri_value(const char* src);
372
373 // Path matching functions.
374 // const char* folder(const char* src);
375 // const char* folders(const char* src);
376
377
378 const char* static_string(const char* src);
379 const char* static_component(const char* src);
380 const char* static_property(const char* src);
381 const char* static_value(const char* src);
382
383 const char* css_variable_value(const char* src);
384 const char* css_variable_top_level_value(const char* src);
385
386 // Utility functions for finding and counting characters in a string.
387 template<char c>
388 const char* find_first(const char* src) {
389 while (*src && *src != c) ++src;
390 return *src ? src : 0;
391 }
392 template<prelexer mx>
393 const char* find_first(const char* src) {
394 while (*src && !mx(src)) ++src;
395 return *src ? src : 0;
396 }
397 template<prelexer mx>
398 const char* find_first_in_interval(const char* beg, const char* end) {
399 bool esc = false;
400 while ((beg < end) && *beg) {
401 if (esc) esc = false;
402 else if (*beg == '\\') esc = true;
403 else if (mx(beg)) return beg;
404 ++beg;
405 }
406 return 0;
407 }
408 template<prelexer mx, prelexer skip>
409 const char* find_first_in_interval(const char* beg, const char* end) {
410 bool esc = false;
411 while ((beg < end) && *beg) {
412 if (esc) esc = false;
413 else if (*beg == '\\') esc = true;
414 else if (const char* pos = skip(beg)) beg = pos;
415 else if (mx(beg)) return beg;
416 ++beg;
417 }
418 return 0;
419 }
420 template <prelexer mx>
421 unsigned int count_interval(const char* beg, const char* end) {
422 unsigned int counter = 0;
423 bool esc = false;
424 while (beg < end && *beg) {
425 const char* p;
426 if (esc) {
427 esc = false;
428 ++beg;
429 } else if (*beg == '\\') {
430 esc = true;
431 ++beg;
432 } else if ((p = mx(beg))) {
433 ++counter;
434 beg = p;
435 }
436 else {
437 ++beg;
438 }
439 }
440 return counter;
441 }
442
443 template <size_t size, prelexer mx, prelexer pad>
444 const char* padded_token(const char* src)
445 {
446 size_t got = 0;
447 const char* pos = src;
448 while (got < size) {
449 if (!mx(pos)) break;
450 ++ pos; ++ got;
451 }
452 while (got < size) {
453 if (!pad(pos)) break;
454 ++ pos; ++ got;
455 }
456 return got ? pos : 0;
457 }
458
459 template <size_t min, size_t max, prelexer mx>
460 const char* minmax_range(const char* src)
461 {
462 size_t got = 0;
463 const char* pos = src;
464 while (got < max) {
465 if (!mx(pos)) break;
466 ++ pos; ++ got;
467 }
468 if (got < min) return 0;
469 if (got > max) return 0;
470 return pos;
471 }
472
473 template <char min, char max>
474 const char* char_range(const char* src)
475 {
476 if (*src < min) return 0;
477 if (*src > max) return 0;
478 return src + 1;
479 }
480
481 }
482}
483
484#endif
485

source code of gtk/subprojects/libsass/src/prelexer.hpp