1 | // sass.hpp must go before all system headers to get the |
2 | // __EXTENSIONS__ fix on Solaris. |
3 | #include "sass.hpp" |
4 | |
5 | #include <iostream> |
6 | #include <iomanip> |
7 | #include "util.hpp" |
8 | #include "util_string.hpp" |
9 | #include "position.hpp" |
10 | #include "prelexer.hpp" |
11 | #include "constants.hpp" |
12 | |
13 | |
14 | namespace Sass { |
15 | // using namespace Lexer; |
16 | using namespace Constants; |
17 | |
18 | namespace Prelexer { |
19 | |
20 | |
21 | /* |
22 | |
23 | def string_re(open, close) |
24 | /#{open}((?:\\.|\#(?!\{)|[^#{close}\\#])*)(#{close}|#\{)/m |
25 | end |
26 | end |
27 | |
28 | # A hash of regular expressions that are used for tokenizing strings. |
29 | # |
30 | # The key is a `[Symbol, Boolean]` pair. |
31 | # The symbol represents which style of quotation to use, |
32 | # while the boolean represents whether or not the string |
33 | # is following an interpolated segment. |
34 | STRING_REGULAR_EXPRESSIONS = { |
35 | :double => { |
36 | /#{open}((?:\\.|\#(?!\{)|[^#{close}\\#])*)(#{close}|#\{)/m |
37 | false => string_re('"', '"'), |
38 | true => string_re('', '"') |
39 | }, |
40 | :single => { |
41 | false => string_re("'", "'"), |
42 | true => string_re('', "'") |
43 | }, |
44 | :uri => { |
45 | false => /url\(#{W}(#{URLCHAR}*?)(#{W}\)|#\{)/, |
46 | true => /(#{URLCHAR}*?)(#{W}\)|#\{)/ |
47 | }, |
48 | # Defined in https://developer.mozilla.org/en/CSS/@-moz-document as a |
49 | # non-standard version of http://www.w3.org/TR/css3-conditional/ |
50 | :url_prefix => { |
51 | false => /url-prefix\(#{W}(#{URLCHAR}*?)(#{W}\)|#\{)/, |
52 | true => /(#{URLCHAR}*?)(#{W}\)|#\{)/ |
53 | }, |
54 | :domain => { |
55 | false => /domain\(#{W}(#{URLCHAR}*?)(#{W}\)|#\{)/, |
56 | true => /(#{URLCHAR}*?)(#{W}\)|#\{)/ |
57 | } |
58 | } |
59 | */ |
60 | |
61 | /* |
62 | /#{open} |
63 | ( |
64 | \\. |
65 | | |
66 | \# (?!\{) |
67 | | |
68 | [^#{close}\\#] |
69 | )* |
70 | (#{close}|#\{) |
71 | /m |
72 | false => string_re('"', '"'), |
73 | true => string_re('', '"') |
74 | */ |
75 | extern const char string_double_negates[] = "\"\\#" ; |
76 | const char* re_string_double_close(const char* src) |
77 | { |
78 | return sequence < |
79 | // valid chars |
80 | zero_plus < |
81 | alternatives < |
82 | // escaped char |
83 | sequence < |
84 | exactly <'\\'>, |
85 | any_char |
86 | >, |
87 | // non interpolate hash |
88 | sequence < |
89 | exactly <'#'>, |
90 | negate < |
91 | exactly <'{'> |
92 | > |
93 | >, |
94 | // other valid chars |
95 | neg_class_char < |
96 | string_double_negates |
97 | > |
98 | > |
99 | >, |
100 | // quoted string closer |
101 | // or interpolate opening |
102 | alternatives < |
103 | exactly <'"'>, |
104 | lookahead < exactly< hash_lbrace > > |
105 | > |
106 | >(src); |
107 | } |
108 | |
109 | const char* re_string_double_open(const char* src) |
110 | { |
111 | return sequence < |
112 | // quoted string opener |
113 | exactly <'"'>, |
114 | // valid chars |
115 | zero_plus < |
116 | alternatives < |
117 | // escaped char |
118 | sequence < |
119 | exactly <'\\'>, |
120 | any_char |
121 | >, |
122 | // non interpolate hash |
123 | sequence < |
124 | exactly <'#'>, |
125 | negate < |
126 | exactly <'{'> |
127 | > |
128 | >, |
129 | // other valid chars |
130 | neg_class_char < |
131 | string_double_negates |
132 | > |
133 | > |
134 | >, |
135 | // quoted string closer |
136 | // or interpolate opening |
137 | alternatives < |
138 | exactly <'"'>, |
139 | lookahead < exactly< hash_lbrace > > |
140 | > |
141 | >(src); |
142 | } |
143 | |
144 | extern const char string_single_negates[] = "'\\#" ; |
145 | const char* re_string_single_close(const char* src) |
146 | { |
147 | return sequence < |
148 | // valid chars |
149 | zero_plus < |
150 | alternatives < |
151 | // escaped char |
152 | sequence < |
153 | exactly <'\\'>, |
154 | any_char |
155 | >, |
156 | // non interpolate hash |
157 | sequence < |
158 | exactly <'#'>, |
159 | negate < |
160 | exactly <'{'> |
161 | > |
162 | >, |
163 | // other valid chars |
164 | neg_class_char < |
165 | string_single_negates |
166 | > |
167 | > |
168 | >, |
169 | // quoted string closer |
170 | // or interpolate opening |
171 | alternatives < |
172 | exactly <'\''>, |
173 | lookahead < exactly< hash_lbrace > > |
174 | > |
175 | >(src); |
176 | } |
177 | |
178 | const char* re_string_single_open(const char* src) |
179 | { |
180 | return sequence < |
181 | // quoted string opener |
182 | exactly <'\''>, |
183 | // valid chars |
184 | zero_plus < |
185 | alternatives < |
186 | // escaped char |
187 | sequence < |
188 | exactly <'\\'>, |
189 | any_char |
190 | >, |
191 | // non interpolate hash |
192 | sequence < |
193 | exactly <'#'>, |
194 | negate < |
195 | exactly <'{'> |
196 | > |
197 | >, |
198 | // other valid chars |
199 | neg_class_char < |
200 | string_single_negates |
201 | > |
202 | > |
203 | >, |
204 | // quoted string closer |
205 | // or interpolate opening |
206 | alternatives < |
207 | exactly <'\''>, |
208 | lookahead < exactly< hash_lbrace > > |
209 | > |
210 | >(src); |
211 | } |
212 | |
213 | /* |
214 | :uri => { |
215 | false => /url\(#{W}(#{URLCHAR}*?)(#{W}\)|#\{)/, |
216 | true => /(#{URLCHAR}*?)(#{W}\)|#\{)/ |
217 | }, |
218 | */ |
219 | const char* re_string_uri_close(const char* src) |
220 | { |
221 | return sequence < |
222 | non_greedy< |
223 | alternatives< |
224 | class_char< real_uri_chars >, |
225 | uri_character, |
226 | NONASCII, |
227 | ESCAPE |
228 | >, |
229 | alternatives< |
230 | sequence < optional < W >, exactly <')'> >, |
231 | lookahead < exactly< hash_lbrace > > |
232 | > |
233 | >, |
234 | optional < |
235 | sequence < optional < W >, exactly <')'> > |
236 | > |
237 | >(src); |
238 | } |
239 | |
240 | const char* re_string_uri_open(const char* src) |
241 | { |
242 | return sequence < |
243 | exactly <'u'>, |
244 | exactly <'r'>, |
245 | exactly <'l'>, |
246 | exactly <'('>, |
247 | W, |
248 | alternatives< |
249 | quoted_string, |
250 | non_greedy< |
251 | alternatives< |
252 | class_char< real_uri_chars >, |
253 | uri_character, |
254 | NONASCII, |
255 | ESCAPE |
256 | >, |
257 | alternatives< |
258 | sequence < W, exactly <')'> >, |
259 | exactly< hash_lbrace > |
260 | > |
261 | > |
262 | > |
263 | >(src); |
264 | } |
265 | |
266 | // Match a line comment (/.*?(?=\n|\r\n?|\f|\Z)/. |
267 | const char* (const char* src) |
268 | { |
269 | return sequence< |
270 | exactly < |
271 | slash_slash |
272 | >, |
273 | non_greedy< |
274 | any_char, |
275 | end_of_line |
276 | > |
277 | >(src); |
278 | } |
279 | |
280 | // Match a block comment. |
281 | const char* (const char* src) |
282 | { |
283 | return sequence< |
284 | delimited_by< |
285 | slash_star, |
286 | star_slash, |
287 | false |
288 | > |
289 | >(src); |
290 | } |
291 | /* not use anymore - remove? |
292 | const char* block_comment_prefix(const char* src) { |
293 | return exactly<slash_star>(src); |
294 | } |
295 | // Match either comment. |
296 | const char* comment(const char* src) { |
297 | return line_comment(src); |
298 | } |
299 | */ |
300 | |
301 | // Match zero plus white-space or line_comments |
302 | const char* optional_css_whitespace(const char* src) { |
303 | return zero_plus< alternatives<spaces, line_comment> >(src); |
304 | } |
305 | const char* css_whitespace(const char* src) { |
306 | return one_plus< alternatives<spaces, line_comment> >(src); |
307 | } |
308 | // Match optional_css_whitepace plus block_comments |
309 | const char* (const char* src) { |
310 | return zero_plus< alternatives<spaces, line_comment, block_comment> >(src); |
311 | } |
312 | const char* (const char* src) { |
313 | return one_plus< alternatives<spaces, line_comment, block_comment> >(src); |
314 | } |
315 | |
316 | // Match one backslash escaped char /\\./ |
317 | const char* escape_seq(const char* src) |
318 | { |
319 | return sequence< |
320 | exactly<'\\'>, |
321 | alternatives < |
322 | minmax_range< |
323 | 1, 3, xdigit |
324 | >, |
325 | any_char |
326 | >, |
327 | optional < |
328 | exactly <' '> |
329 | > |
330 | >(src); |
331 | } |
332 | |
333 | // Match identifier start |
334 | const char* identifier_alpha(const char* src) |
335 | { |
336 | return alternatives< |
337 | unicode_seq, |
338 | alpha, |
339 | nonascii, |
340 | exactly<'-'>, |
341 | exactly<'_'>, |
342 | NONASCII, |
343 | ESCAPE, |
344 | escape_seq |
345 | >(src); |
346 | } |
347 | |
348 | // Match identifier after start |
349 | const char* identifier_alnum(const char* src) |
350 | { |
351 | return alternatives< |
352 | unicode_seq, |
353 | alnum, |
354 | nonascii, |
355 | exactly<'-'>, |
356 | exactly<'_'>, |
357 | NONASCII, |
358 | ESCAPE, |
359 | escape_seq |
360 | >(src); |
361 | } |
362 | |
363 | // Match CSS identifiers. |
364 | const char* strict_identifier(const char* src) |
365 | { |
366 | return sequence< |
367 | one_plus < strict_identifier_alpha >, |
368 | zero_plus < strict_identifier_alnum > |
369 | // word_boundary not needed |
370 | >(src); |
371 | } |
372 | |
373 | // Match CSS identifiers. |
374 | const char* identifier(const char* src) |
375 | { |
376 | return sequence< |
377 | zero_plus< exactly<'-'> >, |
378 | one_plus < identifier_alpha >, |
379 | zero_plus < identifier_alnum > |
380 | // word_boundary not needed |
381 | >(src); |
382 | } |
383 | |
384 | const char* strict_identifier_alpha(const char* src) |
385 | { |
386 | return alternatives < |
387 | alpha, |
388 | nonascii, |
389 | escape_seq, |
390 | exactly<'_'> |
391 | >(src); |
392 | } |
393 | |
394 | const char* strict_identifier_alnum(const char* src) |
395 | { |
396 | return alternatives < |
397 | alnum, |
398 | nonascii, |
399 | escape_seq, |
400 | exactly<'_'> |
401 | >(src); |
402 | } |
403 | |
404 | // Match a single CSS unit |
405 | const char* one_unit(const char* src) |
406 | { |
407 | return sequence < |
408 | optional < exactly <'-'> >, |
409 | strict_identifier_alpha, |
410 | zero_plus < alternatives< |
411 | strict_identifier_alnum, |
412 | sequence < |
413 | one_plus < exactly<'-'> >, |
414 | strict_identifier_alpha |
415 | > |
416 | > > |
417 | >(src); |
418 | } |
419 | |
420 | // Match numerator/denominator CSS units |
421 | const char* multiple_units(const char* src) |
422 | { |
423 | return |
424 | sequence < |
425 | one_unit, |
426 | zero_plus < |
427 | sequence < |
428 | exactly <'*'>, |
429 | one_unit |
430 | > |
431 | > |
432 | >(src); |
433 | } |
434 | |
435 | // Match complex CSS unit identifiers |
436 | const char* unit_identifier(const char* src) |
437 | { |
438 | return sequence < |
439 | multiple_units, |
440 | optional < |
441 | sequence < |
442 | exactly <'/'>, |
443 | negate < sequence < |
444 | exactly < calc_fn_kwd >, |
445 | exactly < '(' > |
446 | > >, |
447 | multiple_units |
448 | > > |
449 | >(src); |
450 | } |
451 | |
452 | const char* identifier_alnums(const char* src) |
453 | { |
454 | return one_plus< identifier_alnum >(src); |
455 | } |
456 | |
457 | // Match number prefix ([\+\-]+) |
458 | const char* number_prefix(const char* src) { |
459 | return alternatives < |
460 | exactly < '+' >, |
461 | sequence < |
462 | exactly < '-' >, |
463 | optional_css_whitespace, |
464 | exactly< '-' > |
465 | > |
466 | >(src); |
467 | } |
468 | |
469 | // Match interpolant schemas |
470 | const char* identifier_schema(const char* src) { |
471 | |
472 | return sequence < |
473 | one_plus < |
474 | sequence < |
475 | zero_plus < |
476 | alternatives < |
477 | sequence < |
478 | optional < |
479 | exactly <'$'> |
480 | >, |
481 | identifier |
482 | >, |
483 | exactly <'-'> |
484 | > |
485 | >, |
486 | interpolant, |
487 | zero_plus < |
488 | alternatives < |
489 | digits, |
490 | sequence < |
491 | optional < |
492 | exactly <'$'> |
493 | >, |
494 | identifier |
495 | >, |
496 | quoted_string, |
497 | exactly<'-'> |
498 | > |
499 | > |
500 | > |
501 | >, |
502 | negate < |
503 | exactly<'%'> |
504 | > |
505 | > (src); |
506 | } |
507 | |
508 | // interpolants can be recursive/nested |
509 | const char* interpolant(const char* src) { |
510 | return recursive_scopes< exactly<hash_lbrace>, exactly<rbrace> >(src); |
511 | } |
512 | |
513 | // $re_squote = /'(?:$re_itplnt|\\.|[^'])*'/ |
514 | const char* single_quoted_string(const char* src) { |
515 | // match a single quoted string, while skipping interpolants |
516 | return sequence < |
517 | exactly <'\''>, |
518 | zero_plus < |
519 | alternatives < |
520 | // skip escapes |
521 | sequence < |
522 | exactly < '\\' >, |
523 | re_linebreak |
524 | >, |
525 | escape_seq, |
526 | unicode_seq, |
527 | // skip interpolants |
528 | interpolant, |
529 | // skip non delimiters |
530 | any_char_but < '\'' > |
531 | > |
532 | >, |
533 | exactly <'\''> |
534 | >(src); |
535 | } |
536 | |
537 | // $re_dquote = /"(?:$re_itp|\\.|[^"])*"/ |
538 | const char* double_quoted_string(const char* src) { |
539 | // match a single quoted string, while skipping interpolants |
540 | return sequence < |
541 | exactly <'"'>, |
542 | zero_plus < |
543 | alternatives < |
544 | // skip escapes |
545 | sequence < |
546 | exactly < '\\' >, |
547 | re_linebreak |
548 | >, |
549 | escape_seq, |
550 | unicode_seq, |
551 | // skip interpolants |
552 | interpolant, |
553 | // skip non delimiters |
554 | any_char_but < '"' > |
555 | > |
556 | >, |
557 | exactly <'"'> |
558 | >(src); |
559 | } |
560 | |
561 | // $re_quoted = /(?:$re_squote|$re_dquote)/ |
562 | const char* quoted_string(const char* src) { |
563 | // match a quoted string, while skipping interpolants |
564 | return alternatives< |
565 | single_quoted_string, |
566 | double_quoted_string |
567 | >(src); |
568 | } |
569 | |
570 | const char* sass_value(const char* src) { |
571 | return alternatives < |
572 | quoted_string, |
573 | identifier, |
574 | percentage, |
575 | hex, |
576 | dimension, |
577 | number |
578 | >(src); |
579 | } |
580 | |
581 | // this is basically `one_plus < sass_value >` |
582 | // takes care to not parse invalid combinations |
583 | const char* value_combinations(const char* src) { |
584 | // `2px-2px` is invalid combo |
585 | bool was_number = false; |
586 | const char* pos; |
587 | while (src) { |
588 | if ((pos = alternatives < quoted_string, identifier, percentage, hex >(src))) { |
589 | was_number = false; |
590 | src = pos; |
591 | } else if (!was_number && !exactly<'+'>(src) && (pos = alternatives < dimension, number >(src))) { |
592 | was_number = true; |
593 | src = pos; |
594 | } else { |
595 | break; |
596 | } |
597 | } |
598 | return src; |
599 | } |
600 | |
601 | // must be at least one interpolant |
602 | // can be surrounded by sass values |
603 | // make sure to never parse (dim)(dim) |
604 | // since this wrongly consumes `2px-1px` |
605 | // `2px1px` is valid number (unit `px1px`) |
606 | const char* value_schema(const char* src) |
607 | { |
608 | return sequence < |
609 | one_plus < |
610 | sequence < |
611 | optional < value_combinations >, |
612 | interpolant, |
613 | optional < value_combinations > |
614 | > |
615 | > |
616 | >(src); |
617 | } |
618 | |
619 | // Match CSS '@' keywords. |
620 | const char* at_keyword(const char* src) { |
621 | return sequence<exactly<'@'>, identifier>(src); |
622 | } |
623 | |
624 | /* |
625 | tok(%r{ |
626 | ( |
627 | \\. |
628 | | |
629 | (?!url\() |
630 | [^"'/\#!;\{\}] # " |
631 | | |
632 | /(?![\*\/]) |
633 | | |
634 | \#(?!\{) |
635 | | |
636 | !(?![a-z]) # TODO: never consume "!" when issue 1126 is fixed. |
637 | )+ |
638 | }xi) || tok(COMMENT) || tok(SINGLE_LINE_COMMENT) || interp_string || interp_uri || |
639 | interpolation(:warn_for_color) |
640 | */ |
641 | const char* re_almost_any_value_token(const char* src) { |
642 | |
643 | return alternatives < |
644 | one_plus < |
645 | alternatives < |
646 | sequence < |
647 | exactly <'\\'>, |
648 | any_char |
649 | >, |
650 | sequence < |
651 | negate < |
652 | uri_prefix |
653 | >, |
654 | neg_class_char < |
655 | almost_any_value_class |
656 | > |
657 | >, |
658 | sequence < |
659 | exactly <'/'>, |
660 | negate < |
661 | alternatives < |
662 | exactly <'/'>, |
663 | exactly <'*'> |
664 | > |
665 | > |
666 | >, |
667 | sequence < |
668 | exactly <'\\'>, |
669 | exactly <'#'>, |
670 | negate < |
671 | exactly <'{'> |
672 | > |
673 | >, |
674 | sequence < |
675 | exactly <'!'>, |
676 | negate < |
677 | alpha |
678 | > |
679 | > |
680 | > |
681 | >, |
682 | block_comment, |
683 | line_comment, |
684 | interpolant, |
685 | space, |
686 | sequence < |
687 | exactly<'u'>, |
688 | exactly<'r'>, |
689 | exactly<'l'>, |
690 | exactly<'('>, |
691 | zero_plus < |
692 | alternatives < |
693 | class_char< real_uri_chars >, |
694 | uri_character, |
695 | NONASCII, |
696 | ESCAPE |
697 | > |
698 | >, |
699 | // false => /url\(#{W}(#{URLCHAR}*?)(#{W}\)|#\{)/, |
700 | // true => /(#{URLCHAR}*?)(#{W}\)|#\{)/ |
701 | exactly<')'> |
702 | > |
703 | >(src); |
704 | } |
705 | |
706 | /* |
707 | DIRECTIVES = Set[:mixin, :include, :function, :return, :debug, :warn, :for, |
708 | :each, :while, :if, :else, :extend, :import, :media, :charset, :content, |
709 | :_moz_document, :at_root, :error] |
710 | */ |
711 | const char* re_special_directive(const char* src) { |
712 | return alternatives < |
713 | word < mixin_kwd >, |
714 | word < include_kwd >, |
715 | word < function_kwd >, |
716 | word < return_kwd >, |
717 | word < debug_kwd >, |
718 | word < warn_kwd >, |
719 | word < for_kwd >, |
720 | word < each_kwd >, |
721 | word < while_kwd >, |
722 | word < if_kwd >, |
723 | word < else_kwd >, |
724 | word < extend_kwd >, |
725 | word < import_kwd >, |
726 | word < media_kwd >, |
727 | word < charset_kwd >, |
728 | word < content_kwd >, |
729 | // exactly < moz_document_kwd >, |
730 | word < at_root_kwd >, |
731 | word < error_kwd > |
732 | >(src); |
733 | } |
734 | |
735 | const char* re_prefixed_directive(const char* src) { |
736 | return sequence < |
737 | optional < |
738 | sequence < |
739 | exactly <'-'>, |
740 | one_plus < alnum >, |
741 | exactly <'-'> |
742 | > |
743 | >, |
744 | exactly < supports_kwd > |
745 | >(src); |
746 | } |
747 | |
748 | const char* re_reference_combinator(const char* src) { |
749 | return sequence < |
750 | optional < |
751 | sequence < |
752 | zero_plus < |
753 | exactly <'-'> |
754 | >, |
755 | identifier, |
756 | exactly <'|'> |
757 | > |
758 | >, |
759 | zero_plus < |
760 | exactly <'-'> |
761 | >, |
762 | identifier |
763 | >(src); |
764 | } |
765 | |
766 | const char* static_reference_combinator(const char* src) { |
767 | return sequence < |
768 | exactly <'/'>, |
769 | re_reference_combinator, |
770 | exactly <'/'> |
771 | >(src); |
772 | } |
773 | |
774 | const char* schema_reference_combinator(const char* src) { |
775 | return sequence < |
776 | exactly <'/'>, |
777 | optional < |
778 | sequence < |
779 | css_ip_identifier, |
780 | exactly <'|'> |
781 | > |
782 | >, |
783 | css_ip_identifier, |
784 | exactly <'/'> |
785 | > (src); |
786 | } |
787 | |
788 | const char* kwd_import(const char* src) { |
789 | return word<import_kwd>(src); |
790 | } |
791 | |
792 | const char* kwd_at_root(const char* src) { |
793 | return word<at_root_kwd>(src); |
794 | } |
795 | |
796 | const char* kwd_with_directive(const char* src) { |
797 | return word<with_kwd>(src); |
798 | } |
799 | |
800 | const char* kwd_without_directive(const char* src) { |
801 | return word<without_kwd>(src); |
802 | } |
803 | |
804 | const char* kwd_media(const char* src) { |
805 | return word<media_kwd>(src); |
806 | } |
807 | |
808 | const char* kwd_supports_directive(const char* src) { |
809 | return word<supports_kwd>(src); |
810 | } |
811 | |
812 | const char* kwd_mixin(const char* src) { |
813 | return word<mixin_kwd>(src); |
814 | } |
815 | |
816 | const char* kwd_function(const char* src) { |
817 | return word<function_kwd>(src); |
818 | } |
819 | |
820 | const char* kwd_return_directive(const char* src) { |
821 | return word<return_kwd>(src); |
822 | } |
823 | |
824 | const char* kwd_include_directive(const char* src) { |
825 | return word<include_kwd>(src); |
826 | } |
827 | |
828 | const char* kwd_content_directive(const char* src) { |
829 | return word<content_kwd>(src); |
830 | } |
831 | |
832 | const char* kwd_charset_directive(const char* src) { |
833 | return word<charset_kwd>(src); |
834 | } |
835 | |
836 | const char* kwd_extend(const char* src) { |
837 | return word<extend_kwd>(src); |
838 | } |
839 | |
840 | |
841 | const char* kwd_if_directive(const char* src) { |
842 | return word<if_kwd>(src); |
843 | } |
844 | |
845 | const char* kwd_else_directive(const char* src) { |
846 | return word<else_kwd>(src); |
847 | } |
848 | const char* elseif_directive(const char* src) { |
849 | return sequence< exactly< else_kwd >, |
850 | optional_css_comments, |
851 | word< if_after_else_kwd > >(src); |
852 | } |
853 | |
854 | const char* kwd_for_directive(const char* src) { |
855 | return word<for_kwd>(src); |
856 | } |
857 | |
858 | const char* kwd_from(const char* src) { |
859 | return word<from_kwd>(src); |
860 | } |
861 | |
862 | const char* kwd_to(const char* src) { |
863 | return word<to_kwd>(src); |
864 | } |
865 | |
866 | const char* kwd_through(const char* src) { |
867 | return word<through_kwd>(src); |
868 | } |
869 | |
870 | const char* kwd_each_directive(const char* src) { |
871 | return word<each_kwd>(src); |
872 | } |
873 | |
874 | const char* kwd_in(const char* src) { |
875 | return word<in_kwd>(src); |
876 | } |
877 | |
878 | const char* kwd_while_directive(const char* src) { |
879 | return word<while_kwd>(src); |
880 | } |
881 | |
882 | const char* name(const char* src) { |
883 | return one_plus< alternatives< alnum, |
884 | exactly<'-'>, |
885 | exactly<'_'>, |
886 | escape_seq > >(src); |
887 | } |
888 | |
889 | const char* kwd_warn(const char* src) { |
890 | return word<warn_kwd>(src); |
891 | } |
892 | |
893 | const char* kwd_err(const char* src) { |
894 | return word<error_kwd>(src); |
895 | } |
896 | |
897 | const char* kwd_dbg(const char* src) { |
898 | return word<debug_kwd>(src); |
899 | } |
900 | |
901 | /* not used anymore - remove? |
902 | const char* directive(const char* src) { |
903 | return sequence< exactly<'@'>, identifier >(src); |
904 | } */ |
905 | |
906 | const char* kwd_null(const char* src) { |
907 | return word<null_kwd>(src); |
908 | } |
909 | |
910 | const char* css_identifier(const char* src) { |
911 | return sequence < |
912 | zero_plus < |
913 | exactly <'-'> |
914 | >, |
915 | identifier |
916 | >(src); |
917 | } |
918 | |
919 | const char* css_ip_identifier(const char* src) { |
920 | return sequence < |
921 | zero_plus < |
922 | exactly <'-'> |
923 | >, |
924 | alternatives < |
925 | identifier, |
926 | interpolant |
927 | > |
928 | >(src); |
929 | } |
930 | |
931 | // Match CSS type selectors |
932 | const char* namespace_prefix(const char* src) { |
933 | return sequence < |
934 | optional < |
935 | alternatives < |
936 | exactly <'*'>, |
937 | css_identifier |
938 | > |
939 | >, |
940 | exactly <'|'>, |
941 | negate < |
942 | exactly <'='> |
943 | > |
944 | >(src); |
945 | } |
946 | |
947 | // Match CSS type selectors |
948 | const char* namespace_schema(const char* src) { |
949 | return sequence < |
950 | optional < |
951 | alternatives < |
952 | exactly <'*'>, |
953 | css_ip_identifier |
954 | > |
955 | >, |
956 | exactly<'|'>, |
957 | negate < |
958 | exactly <'='> |
959 | > |
960 | >(src); |
961 | } |
962 | |
963 | const char* hyphens_and_identifier(const char* src) { |
964 | return sequence< zero_plus< exactly< '-' > >, identifier_alnums >(src); |
965 | } |
966 | const char* hyphens_and_name(const char* src) { |
967 | return sequence< zero_plus< exactly< '-' > >, name >(src); |
968 | } |
969 | const char* universal(const char* src) { |
970 | return sequence< optional<namespace_schema>, exactly<'*'> >(src); |
971 | } |
972 | // Match CSS id names. |
973 | const char* id_name(const char* src) { |
974 | return sequence<exactly<'#'>, identifier_alnums >(src); |
975 | } |
976 | // Match CSS class names. |
977 | const char* class_name(const char* src) { |
978 | return sequence<exactly<'.'>, identifier >(src); |
979 | } |
980 | // Attribute name in an attribute selector. |
981 | const char* attribute_name(const char* src) { |
982 | return alternatives< sequence< optional<namespace_schema>, identifier>, |
983 | identifier >(src); |
984 | } |
985 | // match placeholder selectors |
986 | const char* placeholder(const char* src) { |
987 | return sequence<exactly<'%'>, identifier_alnums >(src); |
988 | } |
989 | // Match CSS numeric constants. |
990 | |
991 | const char* op(const char* src) { |
992 | return class_char<op_chars>(src); |
993 | } |
994 | const char* sign(const char* src) { |
995 | return class_char<sign_chars>(src); |
996 | } |
997 | const char* unsigned_number(const char* src) { |
998 | return alternatives<sequence< zero_plus<digits>, |
999 | exactly<'.'>, |
1000 | one_plus<digits> >, |
1001 | digits>(src); |
1002 | } |
1003 | const char* number(const char* src) { |
1004 | return sequence< |
1005 | optional<sign>, |
1006 | unsigned_number, |
1007 | optional< |
1008 | sequence< |
1009 | exactly<'e'>, |
1010 | optional<sign>, |
1011 | unsigned_number |
1012 | > |
1013 | > |
1014 | >(src); |
1015 | } |
1016 | const char* coefficient(const char* src) { |
1017 | return alternatives< sequence< optional<sign>, digits >, |
1018 | sign >(src); |
1019 | } |
1020 | const char* binomial(const char* src) { |
1021 | return sequence < |
1022 | optional < sign >, |
1023 | optional < digits >, |
1024 | exactly <'n'>, |
1025 | zero_plus < sequence < |
1026 | optional_css_whitespace, sign, |
1027 | optional_css_whitespace, digits |
1028 | > > |
1029 | >(src); |
1030 | } |
1031 | const char* percentage(const char* src) { |
1032 | return sequence< number, exactly<'%'> >(src); |
1033 | } |
1034 | const char* ampersand(const char* src) { |
1035 | return exactly<'&'>(src); |
1036 | } |
1037 | |
1038 | /* not used anymore - remove? |
1039 | const char* em(const char* src) { |
1040 | return sequence< number, exactly<em_kwd> >(src); |
1041 | } */ |
1042 | const char* dimension(const char* src) { |
1043 | return sequence<number, unit_identifier >(src); |
1044 | } |
1045 | const char* hex(const char* src) { |
1046 | const char* p = sequence< exactly<'#'>, one_plus<xdigit> >(src); |
1047 | ptrdiff_t len = p - src; |
1048 | return (len != 4 && len != 7) ? 0 : p; |
1049 | } |
1050 | const char* hexa(const char* src) { |
1051 | const char* p = sequence< exactly<'#'>, one_plus<xdigit> >(src); |
1052 | ptrdiff_t len = p - src; |
1053 | return (len != 5 && len != 9) ? 0 : p; |
1054 | } |
1055 | const char* hex0(const char* src) { |
1056 | const char* p = sequence< exactly<'0'>, exactly<'x'>, one_plus<xdigit> >(src); |
1057 | ptrdiff_t len = p - src; |
1058 | return (len != 5 && len != 8) ? 0 : p; |
1059 | } |
1060 | |
1061 | /* no longer used - remove? |
1062 | const char* rgb_prefix(const char* src) { |
1063 | return word<rgb_fn_kwd>(src); |
1064 | }*/ |
1065 | // Match CSS uri specifiers. |
1066 | |
1067 | const char* uri_prefix(const char* src) { |
1068 | return sequence < |
1069 | exactly < |
1070 | url_kwd |
1071 | >, |
1072 | zero_plus < |
1073 | sequence < |
1074 | exactly <'-'>, |
1075 | one_plus < |
1076 | alpha |
1077 | > |
1078 | > |
1079 | >, |
1080 | exactly <'('> |
1081 | >(src); |
1082 | } |
1083 | |
1084 | // TODO: rename the following two functions |
1085 | /* no longer used - remove? |
1086 | const char* uri(const char* src) { |
1087 | return sequence< exactly<url_kwd>, |
1088 | optional<spaces>, |
1089 | quoted_string, |
1090 | optional<spaces>, |
1091 | exactly<')'> >(src); |
1092 | }*/ |
1093 | /* no longer used - remove? |
1094 | const char* url_value(const char* src) { |
1095 | return sequence< optional< sequence< identifier, exactly<':'> > >, // optional protocol |
1096 | one_plus< sequence< zero_plus< exactly<'/'> >, filename > >, // one or more folders and/or trailing filename |
1097 | optional< exactly<'/'> > >(src); |
1098 | }*/ |
1099 | /* no longer used - remove? |
1100 | const char* url_schema(const char* src) { |
1101 | return sequence< optional< sequence< identifier, exactly<':'> > >, // optional protocol |
1102 | filename_schema >(src); // optional trailing slash |
1103 | }*/ |
1104 | // Match CSS "!important" keyword. |
1105 | const char* kwd_important(const char* src) { |
1106 | return sequence< exactly<'!'>, |
1107 | optional_css_whitespace, |
1108 | word<important_kwd> >(src); |
1109 | } |
1110 | // Match CSS "!optional" keyword. |
1111 | const char* kwd_optional(const char* src) { |
1112 | return sequence< exactly<'!'>, |
1113 | optional_css_whitespace, |
1114 | word<optional_kwd> >(src); |
1115 | } |
1116 | // Match Sass "!default" keyword. |
1117 | const char* default_flag(const char* src) { |
1118 | return sequence< exactly<'!'>, |
1119 | optional_css_whitespace, |
1120 | word<default_kwd> >(src); |
1121 | } |
1122 | // Match Sass "!global" keyword. |
1123 | const char* global_flag(const char* src) { |
1124 | return sequence< exactly<'!'>, |
1125 | optional_css_whitespace, |
1126 | word<global_kwd> >(src); |
1127 | } |
1128 | // Match CSS pseudo-class/element prefixes. |
1129 | const char* pseudo_prefix(const char* src) { |
1130 | return sequence< exactly<':'>, optional< exactly<':'> > >(src); |
1131 | } |
1132 | // Match CSS function call openers. |
1133 | const char* functional_schema(const char* src) { |
1134 | return sequence < |
1135 | one_plus < |
1136 | sequence < |
1137 | zero_plus < |
1138 | alternatives < |
1139 | identifier, |
1140 | exactly <'-'> |
1141 | > |
1142 | >, |
1143 | one_plus < |
1144 | sequence < |
1145 | interpolant, |
1146 | alternatives < |
1147 | digits, |
1148 | identifier, |
1149 | exactly<'+'>, |
1150 | exactly<'-'> |
1151 | > |
1152 | > |
1153 | > |
1154 | > |
1155 | >, |
1156 | negate < |
1157 | exactly <'%'> |
1158 | >, |
1159 | lookahead < |
1160 | exactly <'('> |
1161 | > |
1162 | > (src); |
1163 | } |
1164 | |
1165 | const char* re_nothing(const char* src) { |
1166 | return src; |
1167 | } |
1168 | |
1169 | const char* re_functional(const char* src) { |
1170 | return sequence< identifier, optional < block_comment >, exactly<'('> >(src); |
1171 | } |
1172 | const char* re_pseudo_selector(const char* src) { |
1173 | return sequence< identifier, optional < block_comment >, exactly<'('> >(src); |
1174 | } |
1175 | // Match the CSS negation pseudo-class. |
1176 | const char* pseudo_not(const char* src) { |
1177 | return word< pseudo_not_fn_kwd >(src); |
1178 | } |
1179 | // Match CSS 'odd' and 'even' keywords for functional pseudo-classes. |
1180 | const char* even(const char* src) { |
1181 | return word<even_kwd>(src); |
1182 | } |
1183 | const char* odd(const char* src) { |
1184 | return word<odd_kwd>(src); |
1185 | } |
1186 | // Match CSS attribute-matching operators. |
1187 | const char* exact_match(const char* src) { return exactly<'='>(src); } |
1188 | const char* class_match(const char* src) { return exactly<tilde_equal>(src); } |
1189 | const char* dash_match(const char* src) { return exactly<pipe_equal>(src); } |
1190 | const char* prefix_match(const char* src) { return exactly<caret_equal>(src); } |
1191 | const char* suffix_match(const char* src) { return exactly<dollar_equal>(src); } |
1192 | const char* substring_match(const char* src) { return exactly<star_equal>(src); } |
1193 | // Match CSS combinators. |
1194 | /* not used anymore - remove? |
1195 | const char* adjacent_to(const char* src) { |
1196 | return sequence< optional_spaces, exactly<'+'> >(src); |
1197 | } |
1198 | const char* precedes(const char* src) { |
1199 | return sequence< optional_spaces, exactly<'~'> >(src); |
1200 | } |
1201 | const char* parent_of(const char* src) { |
1202 | return sequence< optional_spaces, exactly<'>'> >(src); |
1203 | } |
1204 | const char* ancestor_of(const char* src) { |
1205 | return sequence< spaces, negate< exactly<'{'> > >(src); |
1206 | }*/ |
1207 | |
1208 | // Match SCSS variable names. |
1209 | const char* variable(const char* src) { |
1210 | return sequence<exactly<'$'>, identifier>(src); |
1211 | } |
1212 | |
1213 | // parse `calc`, `-a-calc` and `--b-c-calc` |
1214 | // but do not parse `foocalc` or `foo-calc` |
1215 | const char* calc_fn_call(const char* src) { |
1216 | return sequence < |
1217 | optional < sequence < |
1218 | hyphens, |
1219 | one_plus < sequence < |
1220 | strict_identifier, |
1221 | hyphens |
1222 | > > |
1223 | > >, |
1224 | exactly < calc_fn_kwd >, |
1225 | word_boundary |
1226 | >(src); |
1227 | } |
1228 | |
1229 | // Match Sass boolean keywords. |
1230 | const char* kwd_true(const char* src) { |
1231 | return word<true_kwd>(src); |
1232 | } |
1233 | const char* kwd_false(const char* src) { |
1234 | return word<false_kwd>(src); |
1235 | } |
1236 | const char* kwd_only(const char* src) { |
1237 | return keyword < only_kwd >(src); |
1238 | } |
1239 | const char* kwd_and(const char* src) { |
1240 | return keyword < and_kwd >(src); |
1241 | } |
1242 | const char* kwd_or(const char* src) { |
1243 | return keyword < or_kwd >(src); |
1244 | } |
1245 | const char* kwd_not(const char* src) { |
1246 | return keyword < not_kwd >(src); |
1247 | } |
1248 | const char* kwd_eq(const char* src) { |
1249 | return exactly<eq>(src); |
1250 | } |
1251 | const char* kwd_neq(const char* src) { |
1252 | return exactly<neq>(src); |
1253 | } |
1254 | const char* kwd_gt(const char* src) { |
1255 | return exactly<gt>(src); |
1256 | } |
1257 | const char* kwd_gte(const char* src) { |
1258 | return exactly<gte>(src); |
1259 | } |
1260 | const char* kwd_lt(const char* src) { |
1261 | return exactly<lt>(src); |
1262 | } |
1263 | const char* kwd_lte(const char* src) { |
1264 | return exactly<lte>(src); |
1265 | } |
1266 | const char* kwd_using(const char* src) { |
1267 | return keyword<using_kwd>(src); |
1268 | } |
1269 | |
1270 | // match specific IE syntax |
1271 | const char* ie_progid(const char* src) { |
1272 | return sequence < |
1273 | word<progid_kwd>, |
1274 | exactly<':'>, |
1275 | alternatives< identifier_schema, identifier >, |
1276 | zero_plus< sequence< |
1277 | exactly<'.'>, |
1278 | alternatives< identifier_schema, identifier > |
1279 | > >, |
1280 | zero_plus < sequence< |
1281 | exactly<'('>, |
1282 | optional_css_whitespace, |
1283 | optional < sequence< |
1284 | alternatives< variable, identifier_schema, identifier >, |
1285 | optional_css_whitespace, |
1286 | exactly<'='>, |
1287 | optional_css_whitespace, |
1288 | alternatives< variable, identifier_schema, identifier, quoted_string, number, hex, hexa >, |
1289 | zero_plus< sequence< |
1290 | optional_css_whitespace, |
1291 | exactly<','>, |
1292 | optional_css_whitespace, |
1293 | sequence< |
1294 | alternatives< variable, identifier_schema, identifier >, |
1295 | optional_css_whitespace, |
1296 | exactly<'='>, |
1297 | optional_css_whitespace, |
1298 | alternatives< variable, identifier_schema, identifier, quoted_string, number, hex, hexa > |
1299 | > |
1300 | > > |
1301 | > >, |
1302 | optional_css_whitespace, |
1303 | exactly<')'> |
1304 | > > |
1305 | >(src); |
1306 | } |
1307 | const char* ie_expression(const char* src) { |
1308 | return sequence < word<expression_kwd>, exactly<'('>, skip_over_scopes< exactly<'('>, exactly<')'> > >(src); |
1309 | } |
1310 | const char* ie_property(const char* src) { |
1311 | return alternatives < ie_expression, ie_progid >(src); |
1312 | } |
1313 | |
1314 | // const char* ie_args(const char* src) { |
1315 | // return sequence< alternatives< ie_keyword_arg, value_schema, quoted_string, interpolant, number, identifier, delimited_by< '(', ')', true> >, |
1316 | // zero_plus< sequence< optional_css_whitespace, exactly<','>, optional_css_whitespace, alternatives< ie_keyword_arg, value_schema, quoted_string, interpolant, number, identifier, delimited_by<'(', ')', true> > > > >(src); |
1317 | // } |
1318 | |
1319 | const char* ie_keyword_arg_property(const char* src) { |
1320 | return alternatives < |
1321 | variable, |
1322 | identifier_schema, |
1323 | identifier |
1324 | >(src); |
1325 | } |
1326 | const char* ie_keyword_arg_value(const char* src) { |
1327 | return alternatives < |
1328 | variable, |
1329 | identifier_schema, |
1330 | identifier, |
1331 | quoted_string, |
1332 | number, |
1333 | hex, |
1334 | hexa, |
1335 | sequence < |
1336 | exactly < '(' >, |
1337 | skip_over_scopes < |
1338 | exactly < '(' >, |
1339 | exactly < ')' > |
1340 | > |
1341 | > |
1342 | >(src); |
1343 | } |
1344 | |
1345 | const char* ie_keyword_arg(const char* src) { |
1346 | return sequence < |
1347 | ie_keyword_arg_property, |
1348 | optional_css_whitespace, |
1349 | exactly<'='>, |
1350 | optional_css_whitespace, |
1351 | ie_keyword_arg_value |
1352 | >(src); |
1353 | } |
1354 | |
1355 | // Path matching functions. |
1356 | /* not used anymore - remove? |
1357 | const char* folder(const char* src) { |
1358 | return sequence< zero_plus< any_char_except<'/'> >, |
1359 | exactly<'/'> >(src); |
1360 | } |
1361 | const char* folders(const char* src) { |
1362 | return zero_plus< folder >(src); |
1363 | }*/ |
1364 | /* not used anymore - remove? |
1365 | const char* chunk(const char* src) { |
1366 | char inside_str = 0; |
1367 | const char* p = src; |
1368 | size_t depth = 0; |
1369 | while (true) { |
1370 | if (!*p) { |
1371 | return 0; |
1372 | } |
1373 | else if (!inside_str && (*p == '"' || *p == '\'')) { |
1374 | inside_str = *p; |
1375 | } |
1376 | else if (*p == inside_str && *(p-1) != '\\') { |
1377 | inside_str = 0; |
1378 | } |
1379 | else if (*p == '(' && !inside_str) { |
1380 | ++depth; |
1381 | } |
1382 | else if (*p == ')' && !inside_str) { |
1383 | if (depth == 0) return p; |
1384 | else --depth; |
1385 | } |
1386 | ++p; |
1387 | } |
1388 | // unreachable |
1389 | return 0; |
1390 | } |
1391 | */ |
1392 | |
1393 | // follow the CSS spec more closely and see if this helps us scan URLs correctly |
1394 | /* not used anymore - remove? |
1395 | const char* NL(const char* src) { |
1396 | return alternatives< exactly<'\n'>, |
1397 | sequence< exactly<'\r'>, exactly<'\n'> >, |
1398 | exactly<'\r'>, |
1399 | exactly<'\f'> >(src); |
1400 | }*/ |
1401 | |
1402 | const char* H(const char* src) { |
1403 | return Util::ascii_isxdigit(c: static_cast<unsigned char>(*src)) ? src+1 : 0; |
1404 | } |
1405 | |
1406 | const char* W(const char* src) { |
1407 | return zero_plus< alternatives< |
1408 | space, |
1409 | exactly< '\t' >, |
1410 | exactly< '\r' >, |
1411 | exactly< '\n' >, |
1412 | exactly< '\f' > |
1413 | > >(src); |
1414 | } |
1415 | |
1416 | const char* UUNICODE(const char* src) { |
1417 | return sequence< exactly<'\\'>, |
1418 | between<H, 1, 6>, |
1419 | optional< W > |
1420 | >(src); |
1421 | } |
1422 | |
1423 | const char* NONASCII(const char* src) { |
1424 | return nonascii(src); |
1425 | } |
1426 | |
1427 | const char* ESCAPE(const char* src) { |
1428 | return alternatives< |
1429 | UUNICODE, |
1430 | sequence< |
1431 | exactly<'\\'>, |
1432 | alternatives< |
1433 | NONASCII, |
1434 | escapable_character |
1435 | > |
1436 | > |
1437 | >(src); |
1438 | } |
1439 | |
1440 | const char* list_terminator(const char* src) { |
1441 | return alternatives < |
1442 | exactly<';'>, |
1443 | exactly<'}'>, |
1444 | exactly<'{'>, |
1445 | exactly<')'>, |
1446 | exactly<']'>, |
1447 | exactly<':'>, |
1448 | end_of_file, |
1449 | exactly<ellipsis>, |
1450 | default_flag, |
1451 | global_flag |
1452 | >(src); |
1453 | }; |
1454 | |
1455 | const char* space_list_terminator(const char* src) { |
1456 | return alternatives < |
1457 | exactly<','>, |
1458 | list_terminator |
1459 | >(src); |
1460 | }; |
1461 | |
1462 | |
1463 | // const char* real_uri_prefix(const char* src) { |
1464 | // return alternatives< |
1465 | // exactly< url_kwd >, |
1466 | // exactly< url_prefix_kwd > |
1467 | // >(src); |
1468 | // } |
1469 | |
1470 | const char* real_uri(const char* src) { |
1471 | return sequence< |
1472 | exactly< url_kwd >, |
1473 | exactly< '(' >, |
1474 | W, |
1475 | real_uri_value, |
1476 | exactly< ')' > |
1477 | >(src); |
1478 | } |
1479 | |
1480 | const char* real_uri_suffix(const char* src) { |
1481 | return sequence< W, exactly< ')' > >(src); |
1482 | } |
1483 | |
1484 | const char* real_uri_value(const char* src) { |
1485 | return |
1486 | sequence< |
1487 | non_greedy< |
1488 | alternatives< |
1489 | class_char< real_uri_chars >, |
1490 | uri_character, |
1491 | NONASCII, |
1492 | ESCAPE |
1493 | >, |
1494 | alternatives< |
1495 | real_uri_suffix, |
1496 | exactly< hash_lbrace > |
1497 | > |
1498 | > |
1499 | > |
1500 | (src); |
1501 | } |
1502 | |
1503 | const char* static_string(const char* src) { |
1504 | const char* pos = src; |
1505 | const char * s = quoted_string(src: pos); |
1506 | Token t(pos, s); |
1507 | const unsigned int p = count_interval< interpolant >(beg: t.begin, end: t.end); |
1508 | return (p == 0) ? t.end : 0; |
1509 | } |
1510 | |
1511 | const char* unicode_seq(const char* src) { |
1512 | return sequence < |
1513 | alternatives < |
1514 | exactly< 'U' >, |
1515 | exactly< 'u' > |
1516 | >, |
1517 | exactly< '+' >, |
1518 | padded_token < |
1519 | 6, xdigit, |
1520 | exactly < '?' > |
1521 | > |
1522 | >(src); |
1523 | } |
1524 | |
1525 | const char* static_component(const char* src) { |
1526 | return alternatives< identifier, |
1527 | static_string, |
1528 | percentage, |
1529 | hex, |
1530 | hexa, |
1531 | exactly<'|'>, |
1532 | // exactly<'+'>, |
1533 | sequence < number, unit_identifier >, |
1534 | number, |
1535 | sequence< exactly<'!'>, word<important_kwd> > |
1536 | >(src); |
1537 | } |
1538 | |
1539 | const char* static_property(const char* src) { |
1540 | return |
1541 | sequence < |
1542 | zero_plus< |
1543 | sequence < |
1544 | optional_css_comments, |
1545 | alternatives < |
1546 | exactly<','>, |
1547 | exactly<'('>, |
1548 | exactly<')'>, |
1549 | kwd_optional, |
1550 | quoted_string, |
1551 | interpolant, |
1552 | identifier, |
1553 | percentage, |
1554 | dimension, |
1555 | variable, |
1556 | alnum, |
1557 | sequence < |
1558 | exactly <'\\'>, |
1559 | any_char |
1560 | > |
1561 | > |
1562 | > |
1563 | >, |
1564 | lookahead < |
1565 | sequence < |
1566 | optional_css_comments, |
1567 | alternatives < |
1568 | exactly <';'>, |
1569 | exactly <'}'>, |
1570 | end_of_file |
1571 | > |
1572 | > |
1573 | > |
1574 | >(src); |
1575 | } |
1576 | |
1577 | const char* static_value(const char* src) { |
1578 | return sequence< sequence< |
1579 | static_component, |
1580 | zero_plus< identifier > |
1581 | >, |
1582 | zero_plus < sequence< |
1583 | alternatives< |
1584 | sequence< optional_spaces, alternatives< |
1585 | exactly < '/' >, |
1586 | exactly < ',' >, |
1587 | exactly < ' ' > |
1588 | >, optional_spaces >, |
1589 | spaces |
1590 | >, |
1591 | static_component |
1592 | > >, |
1593 | zero_plus < spaces >, |
1594 | alternatives< exactly<';'>, exactly<'}'> > |
1595 | >(src); |
1596 | } |
1597 | |
1598 | extern const char css_variable_url_negates[] = "()[]{}\"'#/" ; |
1599 | const char* css_variable_value(const char* src) { |
1600 | return sequence< |
1601 | alternatives< |
1602 | sequence< |
1603 | negate< exactly< url_fn_kwd > >, |
1604 | one_plus< neg_class_char< css_variable_url_negates > > |
1605 | >, |
1606 | sequence< exactly<'#'>, negate< exactly<'{'> > >, |
1607 | sequence< exactly<'/'>, negate< exactly<'*'> > >, |
1608 | static_string, |
1609 | real_uri, |
1610 | block_comment |
1611 | > |
1612 | >(src); |
1613 | } |
1614 | |
1615 | extern const char css_variable_url_top_level_negates[] = "()[]{}\"'#/;" ; |
1616 | const char* css_variable_top_level_value(const char* src) { |
1617 | return sequence< |
1618 | alternatives< |
1619 | sequence< |
1620 | negate< exactly< url_fn_kwd > >, |
1621 | one_plus< neg_class_char< css_variable_url_top_level_negates > > |
1622 | >, |
1623 | sequence< exactly<'#'>, negate< exactly<'{'> > >, |
1624 | sequence< exactly<'/'>, negate< exactly<'*'> > >, |
1625 | static_string, |
1626 | real_uri, |
1627 | block_comment |
1628 | > |
1629 | >(src); |
1630 | } |
1631 | |
1632 | const char* parenthese_scope(const char* src) { |
1633 | return sequence < |
1634 | exactly < '(' >, |
1635 | skip_over_scopes < |
1636 | exactly < '(' >, |
1637 | exactly < ')' > |
1638 | > |
1639 | >(src); |
1640 | } |
1641 | |
1642 | const char* re_selector_list(const char* src) { |
1643 | return alternatives < |
1644 | // partial bem selector |
1645 | sequence < |
1646 | ampersand, |
1647 | one_plus < |
1648 | exactly < '-' > |
1649 | >, |
1650 | word_boundary, |
1651 | optional_spaces |
1652 | >, |
1653 | // main selector matching |
1654 | one_plus < |
1655 | alternatives < |
1656 | // consume whitespace and comments |
1657 | spaces, block_comment, line_comment, |
1658 | // match `/deep/` selector (pass-trough) |
1659 | // there is no functionality for it yet |
1660 | schema_reference_combinator, |
1661 | // match selector ops /[*&%,\[\]]/ |
1662 | class_char < selector_lookahead_ops >, |
1663 | // match selector combinators /[>+~]/ |
1664 | class_char < selector_combinator_ops >, |
1665 | // match pseudo selectors |
1666 | sequence < |
1667 | exactly <'('>, |
1668 | optional_spaces, |
1669 | optional <re_selector_list>, |
1670 | optional_spaces, |
1671 | exactly <')'> |
1672 | >, |
1673 | // match attribute compare operators |
1674 | alternatives < |
1675 | exact_match, class_match, dash_match, |
1676 | prefix_match, suffix_match, substring_match |
1677 | >, |
1678 | // main selector match |
1679 | sequence < |
1680 | // allow namespace prefix |
1681 | optional < namespace_schema >, |
1682 | // modifiers prefixes |
1683 | alternatives < |
1684 | sequence < |
1685 | exactly <'#'>, |
1686 | // not for interpolation |
1687 | negate < exactly <'{'> > |
1688 | >, |
1689 | // class match |
1690 | exactly <'.'>, |
1691 | // single or double colon |
1692 | sequence < |
1693 | optional < pseudo_prefix >, |
1694 | // fix libsass issue 2376 |
1695 | negate < uri_prefix > |
1696 | > |
1697 | >, |
1698 | // accept hypens in token |
1699 | one_plus < sequence < |
1700 | // can start with hyphens |
1701 | zero_plus < |
1702 | sequence < |
1703 | exactly <'-'>, |
1704 | optional_spaces |
1705 | > |
1706 | >, |
1707 | // now the main token |
1708 | alternatives < |
1709 | kwd_optional, |
1710 | exactly <'*'>, |
1711 | quoted_string, |
1712 | interpolant, |
1713 | identifier, |
1714 | variable, |
1715 | percentage, |
1716 | binomial, |
1717 | dimension, |
1718 | alnum |
1719 | > |
1720 | > >, |
1721 | // can also end with hyphens |
1722 | zero_plus < exactly<'-'> > |
1723 | > |
1724 | > |
1725 | > |
1726 | >(src); |
1727 | } |
1728 | |
1729 | const char* type_selector(const char* src) { |
1730 | return sequence< optional<namespace_schema>, identifier>(src); |
1731 | } |
1732 | const char* re_type_selector(const char* src) { |
1733 | return alternatives< type_selector, universal, dimension, percentage, number, identifier_alnums >(src); |
1734 | } |
1735 | const char* re_static_expression(const char* src) { |
1736 | return sequence< number, optional_spaces, exactly<'/'>, optional_spaces, number >(src); |
1737 | } |
1738 | |
1739 | // lexer special_fn: these functions cannot be overloaded |
1740 | // (/((-[\w-]+-)?(calc|element)|expression|progid:[a-z\.]*)\(/i) |
1741 | const char* re_special_fun(const char* src) { |
1742 | |
1743 | // match this first as we test prefix hyphens |
1744 | if (const char* calc = calc_fn_call(src)) { |
1745 | return calc; |
1746 | } |
1747 | |
1748 | return sequence < |
1749 | optional < |
1750 | sequence < |
1751 | exactly <'-'>, |
1752 | one_plus < |
1753 | alternatives < |
1754 | alpha, |
1755 | exactly <'+'>, |
1756 | exactly <'-'> |
1757 | > |
1758 | > |
1759 | > |
1760 | >, |
1761 | alternatives < |
1762 | word < expression_kwd >, |
1763 | sequence < |
1764 | sequence < |
1765 | exactly < progid_kwd >, |
1766 | exactly <':'> |
1767 | >, |
1768 | zero_plus < |
1769 | alternatives < |
1770 | char_range <'a', 'z'>, |
1771 | exactly <'.'> |
1772 | > |
1773 | > |
1774 | > |
1775 | > |
1776 | >(src); |
1777 | } |
1778 | |
1779 | } |
1780 | } |
1781 | |