1use crate::{
2 Build, Cursor, CursorSink, DimensionUnit, Kind, KindSet, Parse, Parser, Peek, Result, Span, ToNumberValue, Token,
3 diagnostics,
4};
5
6macro_rules! cursor_wrapped {
7 ($ident:ident) => {
8 impl $crate::ToCursors for $ident {
9 fn to_cursors(&self, s: &mut impl CursorSink) {
10 s.append((*self).into());
11 }
12 }
13
14 impl From<$ident> for $crate::Cursor {
15 fn from(value: $ident) -> Self {
16 value.0.into()
17 }
18 }
19
20 impl From<$ident> for $crate::Token {
21 fn from(value: $ident) -> Self {
22 value.0.into()
23 }
24 }
25
26 impl $crate::ToSpan for $ident {
27 fn to_span(&self) -> Span {
28 self.0.to_span()
29 }
30 }
31 };
32}
33
34macro_rules! define_kinds {
35 ($($(#[$meta:meta])* $ident:ident,)*) => {
36 $(
37 $(#[$meta])*
38 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
39 #[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
40 pub struct $ident($crate::Cursor);
41
42 impl $ident {
43 pub const fn dummy() -> Self {
44 Self($crate::Cursor::dummy($crate::Token::dummy($crate::Kind::$ident)))
45 }
46
47 pub fn associated_whitespace(&self) -> $crate::AssociatedWhitespaceRules {
48 self.0.token().associated_whitespace()
49 }
50
51 pub fn with_associated_whitespace(&self, rules: $crate::AssociatedWhitespaceRules) -> Self {
52 Self(self.0.with_associated_whitespace(rules))
53 }
54 }
55
56 impl $crate::ToCursors for $ident {
57 fn to_cursors(&self, s: &mut impl $crate::CursorSink) {
58 s.append((*self).into());
59 }
60 }
61
62 impl<'a> $crate::Peek<'a> for $ident {
63 fn peek(_: &$crate::Parser<'a>, c: $crate::Cursor) -> bool {
64 c == $crate::Kind::$ident
65 }
66 }
67
68 impl<'a> $crate::Build<'a> for $ident {
69 fn build(_: &$crate::Parser<'a>, c: $crate::Cursor) -> Self {
70 Self(c)
71 }
72 }
73
74 impl From<$ident> for $crate::Cursor {
75 fn from(value: $ident) -> Self {
76 value.0.into()
77 }
78 }
79
80 impl From<$ident> for $crate::Token {
81 fn from(value: $ident) -> Self {
82 value.0.into()
83 }
84 }
85
86 impl $crate::ToSpan for $ident {
87 fn to_span(&self) -> $crate::Span {
88 self.0.to_span()
89 }
90 }
91 )*
92 };
93}
94
95macro_rules! define_kind_idents {
96 ($($(#[$meta:meta])* $ident:ident,)*) => {
97 $(
98 $(#[$meta])*
99 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
100 #[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
101 pub struct $ident($crate::Cursor);
102
103 impl $crate::ToCursors for $ident {
104 fn to_cursors(&self, s: &mut impl $crate::CursorSink) {
105 s.append((*self).into());
106 }
107 }
108
109 impl<'a> $crate::Peek<'a> for $ident {
110 fn peek(_: &$crate::Parser<'a>, c: $crate::Cursor) -> bool {
111 c == $crate::Kind::$ident
112 }
113 }
114
115 impl<'a> $crate::Build<'a> for $ident {
116 fn build(_: &$crate::Parser<'a>, c: $crate::Cursor) -> Self {
117 Self(c)
118 }
119 }
120
121 impl From<$ident> for $crate::Kind {
122 fn from(value: $ident) -> Self {
123 value.0.into()
124 }
125 }
126
127 impl From<$ident> for $crate::Cursor {
128 fn from(value: $ident) -> Self {
129 value.0
130 }
131 }
132
133 impl From<$ident> for $crate::Token {
134 fn from(value: $ident) -> Self {
135 value.0.into()
136 }
137 }
138
139 impl $crate::ToSpan for $ident {
140 fn to_span(&self) -> $crate::Span {
141 self.0.to_span()
142 }
143 }
144
145 impl $ident {
146 pub fn is_dashed_ident(&self) -> bool {
148 self.0.token().is_dashed_ident()
149 }
150
151 pub const fn dummy() -> Self {
152 Self($crate::Cursor::dummy($crate::Token::dummy($crate::Kind::$ident)))
153 }
154 }
155 )*
156 };
157}
158
159#[macro_export]
174macro_rules! custom_delim {
175 ($(#[$meta:meta])* $ident:ident, $ch:literal) => {
176 $(#[$meta])*
177 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
178 #[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
179 pub struct $ident($crate::T![Delim]);
180
181 impl $crate::ToCursors for $ident {
182 fn to_cursors(&self, s: &mut impl $crate::CursorSink) {
183 s.append((*self).into());
184 }
185 }
186
187 impl<'a> $crate::Peek<'a> for $ident {
188 fn peek(_: &$crate::Parser<'a>, c: $crate::Cursor) -> bool {
189 c == $crate::Kind::Delim && c == $ch
190 }
191 }
192
193 impl<'a> $crate::Build<'a> for $ident {
194 fn build(p: &$crate::Parser<'a>, c: $crate::Cursor) -> Self {
195 Self(<$crate::T![Delim]>::build(p, c))
196 }
197 }
198
199 impl From<$ident> for $crate::Cursor {
200 fn from(value: $ident) -> Self {
201 value.0.into()
202 }
203 }
204
205 impl $crate::ToSpan for $ident {
206 fn to_span(&self) -> $crate::Span {
207 self.0.to_span()
208 }
209 }
210
211 impl PartialEq<char> for $ident {
212 fn eq(&self, other: &char) -> bool {
213 self.0 == *other
214 }
215 }
216 };
217}
218
219#[doc(hidden)]
220#[macro_export]
221macro_rules! custom_dimension {
222 ($(#[$meta:meta])*$ident: ident, $str: tt) => {
223 $(#[$meta])*
224 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
225 #[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
226 pub struct $ident($crate::Cursor);
227
228 impl $ident {
229 pub fn value(&self) -> f32 {
231 self.0.token().value()
232 }
233
234 pub const fn dummy() -> Self {
235 Self($crate::Cursor::dummy($crate::Token::dummy($crate::Kind::Dimension)))
236 }
237 }
238
239 impl From<$ident> for $crate::Cursor {
240 fn from(value: $ident) -> Self {
241 value.0
242 }
243 }
244
245 impl $crate::ToCursors for $ident {
246 fn to_cursors(&self, s: &mut impl $crate::CursorSink) {
247 s.append((*self).into());
248 }
249 }
250
251 impl $crate::ToSpan for $ident {
252 fn to_span(&self) -> $crate::Span {
253 self.0.to_span()
254 }
255 }
256
257 impl PartialEq<f32> for $ident {
258 fn eq(&self, other: &f32) -> bool {
259 self.value() == *other
260 }
261 }
262
263 impl $crate::ToNumberValue for $ident {
264 fn to_number_value(&self) -> Option<f32> {
265 Some(self.value())
266 }
267 }
268
269 impl<'a> $crate::Peek<'a> for $ident {
270 fn peek(p: &$crate::Parser<'a>, c: $crate::Cursor) -> bool {
271 c == $crate::Kind::Dimension
272 && (c == $crate::DimensionUnit::$ident || p.eq_ignore_ascii_case(c, $str))
273 }
274 }
275
276 impl<'a> $crate::Build<'a> for $ident {
277 fn build(_: &$crate::Parser<'a>, c: $crate::Cursor) -> Self {
278 Self(c)
279 }
280 }
281
282 impl From<$ident> for i32 {
283 fn from(value: $ident) -> Self {
284 value.value() as i32
285 }
286 }
287
288 impl From<$ident> for f32 {
289 fn from(value: $ident) -> Self {
290 value.value()
291 }
292 }
293 };
294}
295
296#[macro_export]
312macro_rules! custom_double_delim {
313 ($(#[$meta:meta])*$ident: ident, $first: literal, $second: literal) => {
314 $(#[$meta])*
315 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
316 #[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
317 pub struct $ident(pub $crate::T![Delim], pub $crate::T![Delim]);
318
319 impl $ident {
320 pub const fn dummy() -> Self {
321 Self(<$crate::T![Delim]>::dummy(), <$crate::T![Delim]>::dummy())
322 }
323 }
324
325 impl<'a> $crate::Peek<'a> for $ident {
326 fn peek(p: &$crate::Parser<'a>, c: $crate::Cursor) -> bool {
327 c == $first && p.peek_n(2) == $second
328 }
329 }
330
331 impl<'a> $crate::Parse<'a> for $ident {
332 fn parse(p: &mut $crate::Parser<'a>) -> $crate::Result<Self> {
333 let first = p.parse::<$crate::T![Delim]>()?;
334 if first != $first {
335 let c: Cursor = first.into();
336 Err($crate::diagnostics::ExpectedDelim(c))?;
337 }
338 let skip = p.set_skip(KindSet::NONE);
339 let second = p.parse::<$crate::T![Delim]>();
340 p.set_skip(skip);
341 let second = second?;
342 if second != $second {
343 let c:Cursor = second.into();
344 Err($crate::diagnostics::ExpectedDelim(c))?;
345 }
346 Ok(Self(first, second))
347 }
348 }
349
350 impl<'a> $crate::ToCursors for $ident {
351 fn to_cursors(&self, s: &mut impl $crate::CursorSink) {
352 s.append(self.0.into());
353 s.append(self.1.into());
354 }
355 }
356
357 impl $crate::ToSpan for $ident {
358 fn to_span(&self) -> $crate::Span {
359 self.0.to_span() + self.1.to_span()
360 }
361 }
362 };
363}
364
365#[macro_export]
394macro_rules! keyword_set {
395 ($(#[$meta:meta])* $vis:vis enum $name: ident { $( $variant: ident: $variant_str: tt$(,)?)+ }) => {
396 $(#[$meta])*
397 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
398 #[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
399 $vis enum $name {
400 $($variant($crate::token_macros::Ident)),+
401 }
402 impl<'a> $crate::Peek<'a> for $name {
403 fn peek(p: &$crate::Parser<'a>, c: $crate::Cursor) -> bool {
404 c == $crate::Kind::Ident && Self::MAP.get(&p.parse_str_lower(c)).is_some()
405 }
406 }
407 impl<'a> $crate::Build<'a> for $name {
408 fn build(p: &$crate::Parser<'a>, c: $crate::Cursor) -> Self {
409 use $crate::Peek;
410 debug_assert!(Self::peek(p, c));
411 let val = Self::MAP.get(&p.parse_str_lower(c)).unwrap();
412 let ident = $crate::token_macros::Ident::build(p, c);
413 match val {
414 $(Self::$variant(_) => Self::$variant(ident),)+
415 }
416 }
417 }
418 impl $name {
419 const MAP: phf::Map<&'static str, $name> = phf::phf_map! {
420 $($variant_str => $name::$variant($crate::token_macros::Ident::dummy())),+
421 };
422 }
423
424 impl From<$name> for $crate::Kind {
425 fn from(value: $name) -> Self {
426 match value {
427 $($name::$variant(t) => t.into(),)+
428 }
429 }
430 }
431
432 impl From<$name> for $crate::Token {
433 fn from(value: $name) -> Self {
434 match value {
435 $($name::$variant(t) => t.into(),)+
436 }
437 }
438 }
439
440 impl From<$name> for $crate::Cursor {
441 fn from(value: $name) -> Self {
442 match value {
443 $($name::$variant(t) => t.into(),)+
444 }
445 }
446 }
447
448 impl From<$name> for $crate::token_macros::Ident {
449 fn from(value: $name) -> Self {
450 match value {
451 $($name::$variant(t) => t,)+
452 }
453 }
454 }
455
456 impl $crate::ToCursors for $name {
457 fn to_cursors(&self, s: &mut impl $crate::CursorSink) {
458 s.append((*self).into());
459 }
460 }
461
462 impl $crate::ToSpan for $name {
463 fn to_span(&self) -> $crate::Span {
464 match self {
465 $($name::$variant(t) => (t.to_span()),)+
466 }
467 }
468 }
469 };
470
471 ($(#[$meta:meta])* $vis:vis struct $name: ident $str: tt) => {
472 $(#[$meta])*
473 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
474 #[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
475 $vis struct $name($crate::T![Ident]);
476
477 impl $crate::ToCursors for $name {
478 fn to_cursors(&self, s: &mut impl $crate::CursorSink) {
479 s.append((*self).into());
480 }
481 }
482
483 impl<'a> $crate::Peek<'a> for $name {
484 fn peek(p: &$crate::Parser<'a>, c: $crate::Cursor) -> bool {
485 <$crate::T![Ident]>::peek(p, c) && p.eq_ignore_ascii_case(c, $str)
486 }
487 }
488
489 impl<'a> $crate::Build<'a> for $name {
490 fn build(p: &$crate::Parser<'a>, c: $crate::Cursor) -> Self {
491 use $crate::Peek;
492 debug_assert!(Self::peek(p, c));
493 Self(<$crate::T![Ident]>::build(p, c))
494 }
495 }
496
497 impl From<$name> for $crate::Cursor {
498 fn from(value: $name) -> Self {
499 value.0.into()
500 }
501 }
502
503 impl From<$name> for $crate::Token {
504 fn from(value: $name) -> Self {
505 value.0.into()
506 }
507 }
508
509 impl $crate::ToSpan for $name {
510 fn to_span(&self) -> $crate::Span {
511 self.0.to_span()
512 }
513 }
514
515 impl<'a> From<$name> for $crate::token_macros::Ident {
516 fn from(value: $name) -> Self {
517 value.0
518 }
519 }
520 };
521}
522
523#[macro_export]
552macro_rules! function_set {
553 ($(#[$meta:meta])* $vis:vis enum $name: ident { $( $variant: ident: $variant_str: tt$(,)?)+ }) => {
554 $(#[$meta])*
555 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
556 #[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
557 $vis enum $name {
558 $($variant($crate::token_macros::Function)),+
559 }
560 impl<'a> $crate::Peek<'a> for $name {
561 fn peek(p: &$crate::Parser<'a>, c: $crate::Cursor) -> bool {
562 c == $crate::Kind::Function && Self::MAP.get(p.parse_str_lower(c)).is_some()
563 }
564 }
565 impl<'a> $crate::Build<'a> for $name {
566 fn build(p: &$crate::Parser<'a>, c: $crate::Cursor) -> Self {
567 use $crate::Peek;
568 debug_assert!(Self::peek(p, c));
569 let val = Self::MAP.get(p.parse_str_lower(c)).unwrap();
570 let function = $crate::token_macros::Function::build(p, c);
571 match val {
572 $(Self::$variant(_) => Self::$variant(function),)+
573 }
574 }
575 }
576 impl $name {
577 const MAP: phf::Map<&'static str, $name> = phf::phf_map! {
578 $($variant_str => $name::$variant($crate::token_macros::Function::dummy())),+
579 };
580 }
581
582 impl From<$name> for $crate::Token {
583 fn from(value: $name) -> Self {
584 match value {
585 $($name::$variant(t) => t.into(),)+
586 }
587 }
588 }
589
590 impl From<$name> for $crate::Cursor {
591 fn from(value: $name) -> Self {
592 match value {
593 $($name::$variant(t) => t.into(),)+
594 }
595 }
596 }
597
598 impl $crate::ToCursors for $name {
599 fn to_cursors(&self, s: &mut impl $crate::CursorSink) {
600 s.append((*self).into());
601 }
602 }
603
604 impl $crate::ToSpan for $name {
605 fn to_span(&self) -> $crate::Span {
606 match self {
607 $($name::$variant(t) => (t.to_span()),)+
608 }
609 }
610 }
611
612 impl<'a> From<$name> for $crate::token_macros::Function {
613 fn from(value: $name) -> Self {
614 match value {
615 $($name::$variant(t) => t,)+
616 }
617 }
618 }
619 };
620
621 ($(#[$meta:meta])* $vis:vis struct $name: ident $str: tt) => {
622 $(#[$meta])*
623 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
624 #[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
625 $vis struct $name($crate::T![Function]);
626
627 impl $crate::ToCursors for $name {
628 fn to_cursors(&self, s: &mut impl $crate::CursorSink) {
629 s.append((*self).into());
630 }
631 }
632
633 impl<'a> $crate::Peek<'a> for $name {
634 fn peek(p: &$crate::Parser<'a>, c: $crate::Cursor) -> bool {
635 <$crate::T![Function]>::peek(p, c) && p.eq_ignore_ascii_case(c, $str)
636 }
637 }
638
639 impl<'a> $crate::Build<'a> for $name {
640 fn build(p: &$crate::Parser<'a>, c: $crate::Cursor) -> Self {
641 use $crate::Peek;
642 debug_assert!(Self::peek(p, c));
643 Self(<$crate::T![Function]>::build(p, c))
644 }
645 }
646
647 impl From<$name> for $crate::Cursor {
648 fn from(value: $name) -> Self {
649 value.0.into()
650 }
651 }
652
653 impl From<$name> for $crate::Token {
654 fn from(value: $name) -> Self {
655 value.0.into()
656 }
657 }
658
659 impl $crate::ToSpan for $name {
660 fn to_span(&self) -> $crate::Span {
661 self.0.to_span()
662 }
663 }
664
665 impl<'a> From<$name> for $crate::token_macros::Function {
666 fn from(value: $name) -> Self {
667 value.0
668 }
669 }
670 };
671}
672
673#[macro_export]
702macro_rules! atkeyword_set {
703 ($(#[$meta:meta])* $vis:vis enum $name: ident { $( $variant: ident: $variant_str: tt$(,)?)+ }) => {
704 $(#[$meta])*
705 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
706 #[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
707 $vis enum $name {
708 $($variant($crate::token_macros::AtKeyword)),+
709 }
710 impl<'a> $crate::Peek<'a> for $name {
711 fn peek(p: &$crate::Parser<'a>, c: $crate::Cursor) -> bool {
712 c == $crate::Kind::AtKeyword && Self::MAP.get(&p.parse_str_lower(c)).is_some()
713 }
714 }
715 impl<'a> $crate::Build<'a> for $name {
716 fn build(p: &$crate::Parser<'a>, c: $crate::Cursor) -> Self {
717 use $crate::Peek;
718 debug_assert!(Self::peek(p, c));
719 let val = Self::MAP.get(&p.parse_str_lower(c)).unwrap();
720 let at_keyword = $crate::token_macros::AtKeyword::build(p, c);
721 match val {
722 $(Self::$variant(_) => Self::$variant(at_keyword),)+
723 }
724 }
725 }
726 impl $name {
727 const MAP: phf::Map<&'static str, $name> = phf::phf_map! {
728 $($variant_str => $name::$variant($crate::token_macros::AtKeyword::dummy())),+
729 };
730 }
731
732 impl From<$name> for $crate::Token {
733 fn from(value: $name) -> Self {
734 match value {
735 $($name::$variant(t) => t.into(),)+
736 }
737 }
738 }
739
740 impl From<$name> for $crate::Cursor {
741 fn from(value: $name) -> Self {
742 match value {
743 $($name::$variant(t) => t.into(),)+
744 }
745 }
746 }
747
748 impl $crate::ToCursors for $name {
749 fn to_cursors(&self, s: &mut impl $crate::CursorSink) {
750 s.append((*self).into());
751 }
752 }
753
754 impl $crate::ToSpan for $name {
755 fn to_span(&self) -> $crate::Span {
756 match self {
757 $($name::$variant(t) => (t.to_span()),)+
758 }
759 }
760 }
761
762 impl<'a> From<$name> for $crate::token_macros::AtKeyword {
763 fn from(value: $name) -> Self {
764 match value {
765 $($name::$variant(t) => t,)+
766 }
767 }
768 }
769 };
770 ($(#[$meta:meta])* $vis:vis struct $name: ident $str: tt) => {
771 $(#[$meta])*
772 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
773 #[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
774 $vis struct $name($crate::T![AtKeyword]);
775
776 impl $crate::ToCursors for $name {
777 fn to_cursors(&self, s: &mut impl $crate::CursorSink) {
778 s.append((*self).into());
779 }
780 }
781
782 impl<'a> $crate::Peek<'a> for $name {
783 fn peek(p: &$crate::Parser<'a>, c: $crate::Cursor) -> bool {
784 <$crate::T![AtKeyword]>::peek(p, c) && p.eq_ignore_ascii_case(c, $str)
785 }
786 }
787
788 impl<'a> $crate::Build<'a> for $name {
789 fn build(p: &$crate::Parser<'a>, c: $crate::Cursor) -> Self {
790 use $crate::Peek;
791 debug_assert!(Self::peek(p, c));
792 Self(<$crate::T![AtKeyword]>::build(p, c))
793 }
794 }
795
796 impl From<$name> for $crate::Cursor {
797 fn from(value: $name) -> Self {
798 value.0.into()
799 }
800 }
801
802 impl From<$name> for $crate::Token {
803 fn from(value: $name) -> Self {
804 value.0.into()
805 }
806 }
807
808 impl $crate::ToSpan for $name {
809 fn to_span(&self) -> $crate::Span {
810 self.0.to_span()
811 }
812 }
813
814 impl<'a> From<$name> for $crate::token_macros::AtKeyword {
815 fn from(value: $name) -> Self {
816 value.0
817 }
818 }
819 };
820}
821
822define_kinds! {
823 Eof,
825
826 Comment,
828
829 CdcOrCdo,
831
832 BadString,
834
835 BadUrl,
837
838 Delim,
840
841 Colon,
843
844 Semicolon,
846
847 Comma,
849
850 LeftCurly,
852
853 RightCurly,
855
856 LeftSquare,
858
859 RightSquare,
861
862 LeftParen,
864
865 RightParen,
867}
868
869impl PartialEq<char> for Delim {
870 fn eq(&self, other: &char) -> bool {
871 self.0 == *other
872 }
873}
874
875define_kind_idents! {
876 Ident,
878
879 String,
881
882 Url,
884
885 Function,
887
888 AtKeyword,
890
891 Hash,
893}
894
895#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
898#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
899pub struct Whitespace(Cursor);
900cursor_wrapped!(Whitespace);
901
902impl<'a> Peek<'a> for Whitespace {
903 fn peek(p: &Parser<'a>, _: Cursor) -> bool {
904 let c = p.peek_next_including_whitespace();
906 c == Kind::Whitespace
907 }
908}
909
910impl<'a> Parse<'a> for Whitespace {
911 fn parse(p: &mut Parser<'a>) -> Result<Self> {
912 let skip = p.set_skip(KindSet::COMMENTS);
915 let c = p.next();
916 p.set_skip(skip);
917 if c != Kind::Whitespace {
918 Err(diagnostics::Unexpected(c))?
919 }
920 Ok(Self(c))
921 }
922}
923
924#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
927#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
928pub struct DashedIdent(Ident);
929cursor_wrapped!(DashedIdent);
930
931impl<'a> Peek<'a> for DashedIdent {
932 fn peek(_: &Parser<'a>, c: Cursor) -> bool {
933 c == Kind::Ident && c.token().is_dashed_ident()
934 }
935}
936
937impl<'a> Build<'a> for DashedIdent {
938 fn build(p: &Parser<'a>, c: Cursor) -> Self {
939 Self(Ident::build(p, c))
940 }
941}
942
943#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
945#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
946pub struct Dimension(Cursor);
947cursor_wrapped!(Dimension);
948
949impl PartialEq<f32> for Dimension {
950 fn eq(&self, other: &f32) -> bool {
951 self.0.token().value() == *other
952 }
953}
954
955impl<'a> Peek<'a> for Dimension {
956 fn peek(_: &Parser<'a>, c: Cursor) -> bool {
957 c == Kind::Dimension
958 }
959}
960
961impl<'a> Build<'a> for Dimension {
962 fn build(_: &Parser<'a>, c: Cursor) -> Self {
963 Self(c)
964 }
965}
966
967impl From<Dimension> for f32 {
968 fn from(val: Dimension) -> Self {
969 val.0.token().value()
970 }
971}
972
973impl ToNumberValue for Dimension {
974 fn to_number_value(&self) -> Option<f32> {
975 Some(self.0.token().value())
976 }
977}
978
979impl From<Dimension> for (f32, DimensionUnit) {
980 fn from(val: Dimension) -> Self {
981 let value = val.0.token().value();
982 let unit = val.0.token().dimension_unit();
983 (value, unit)
984 }
985}
986
987impl Dimension {
988 pub fn value(&self) -> f32 {
990 self.0.token().value()
991 }
992
993 pub fn dimension_unit(&self) -> DimensionUnit {
998 self.0.token().dimension_unit()
999 }
1000}
1001
1002#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1003#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
1004pub struct DimensionIdent(Cursor, DimensionUnit);
1005cursor_wrapped!(DimensionIdent);
1006
1007impl<'a> Peek<'a> for DimensionIdent {
1008 fn peek(p: &Parser<'a>, c: Cursor) -> bool {
1009 Ident::peek(p, c) && (DimensionUnit::from(p.parse_str_lower(c)) != DimensionUnit::Unknown)
1010 }
1011}
1012
1013impl<'a> Build<'a> for DimensionIdent {
1014 fn build(p: &Parser<'a>, c: Cursor) -> Self {
1015 Self(c, DimensionUnit::from(p.parse_str_lower(c)))
1016 }
1017}
1018
1019#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1021#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
1022pub struct Number(Cursor);
1023cursor_wrapped!(Number);
1024
1025impl Number {
1026 pub const NUMBER_ZERO: Number = Number(Cursor::dummy(Token::NUMBER_ZERO));
1027 pub const ZERO: Number = Number(Cursor::dummy(Token::NUMBER_ZERO));
1028
1029 pub fn value(&self) -> f32 {
1031 self.0.token().value()
1032 }
1033
1034 pub fn is_int(&self) -> bool {
1035 self.0.token().is_int()
1036 }
1037
1038 pub fn is_float(&self) -> bool {
1039 self.0.token().is_float()
1040 }
1041
1042 pub fn has_sign(&self) -> bool {
1043 self.0.token().has_sign()
1044 }
1045}
1046
1047impl<'a> Peek<'a> for Number {
1048 fn peek(_: &Parser<'a>, c: Cursor) -> bool {
1049 c == Kind::Number
1050 }
1051}
1052
1053impl<'a> Build<'a> for Number {
1054 fn build(_: &Parser<'a>, c: Cursor) -> Self {
1055 Self(c)
1056 }
1057}
1058
1059impl From<Number> for f32 {
1060 fn from(value: Number) -> Self {
1061 value.value()
1062 }
1063}
1064
1065impl From<Number> for i32 {
1066 fn from(value: Number) -> Self {
1067 value.value() as i32
1068 }
1069}
1070
1071impl PartialEq<f32> for Number {
1072 fn eq(&self, other: &f32) -> bool {
1073 self.value() == *other
1074 }
1075}
1076
1077impl ToNumberValue for Number {
1078 fn to_number_value(&self) -> Option<f32> {
1079 Some(self.value())
1080 }
1081}
1082
1083pub mod delim {
1085 custom_delim! {
1086 And, '&'
1089 }
1090 custom_delim! {
1091 At, '@'
1095 }
1096 custom_delim! {
1097 Caret, '^'
1100 }
1101 custom_delim! {
1102 Dash, '-'
1105 }
1106 custom_delim! {
1107 Dollar, '$'
1110 }
1111 custom_delim! {
1112 Dot, '.'
1115 }
1116 custom_delim! {
1117 Eq, '='
1120 }
1121 custom_delim! {
1122 Gt, '>'
1125 }
1126 custom_delim! {
1127 Hash, '#'
1131 }
1132 custom_delim! {
1133 Lt, '<'
1136 }
1137 custom_delim! {
1138 Bang, '!'
1141 }
1142 custom_delim! {
1143 Or, '|'
1146 }
1147 custom_delim! {
1148 Percent, '%'
1151 }
1152 custom_delim! {
1153 Plus, '+'
1156 }
1157 custom_delim! {
1158 Question, '?'
1161 }
1162 custom_delim! {
1163 Slash, '/'
1166 }
1167 custom_delim! {
1168 Star, '*'
1171 }
1172 custom_delim! {
1173 Tilde, '~'
1176 }
1177 custom_delim! {
1178 Underscore, '_'
1181 }
1182 custom_delim! {
1183 Backtick, '`'
1186 }
1187}
1188
1189pub mod double {
1193 use crate::{Cursor, CursorSink, Kind, KindSet, Parse, Parser, Peek, Result, Span, T, ToCursors, ToSpan};
1194
1195 custom_double_delim! {
1196 GreaterThanEqual, '>', '='
1200 }
1201 custom_double_delim! {
1202 LessThanEqual, '<', '='
1206 }
1207 custom_double_delim! {
1208 StarPipe, '*', '|'
1212 }
1213 custom_double_delim! {
1214 PipePipe, '|', '|'
1218 }
1219 custom_double_delim! {
1220 EqualEqual, '=', '='
1224 }
1225 custom_double_delim! {
1226 TildeEqual, '~', '='
1230 }
1231 custom_double_delim! {
1232 PipeEqual, '|', '='
1236 }
1237 custom_double_delim! {
1238 CaretEqual, '^', '='
1242 }
1243 custom_double_delim! {
1244 DollarEqual, '$', '='
1248 }
1249 custom_double_delim! {
1250 StarEqual, '*', '='
1254 }
1255
1256 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1259 #[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
1260 pub struct ColonColon(T![:], T![:]);
1261
1262 impl ColonColon {
1263 pub const fn dummy() -> Self {
1264 Self(<T![:]>::dummy(), <T![:]>::dummy())
1265 }
1266 }
1267
1268 impl<'a> Peek<'a> for ColonColon {
1269 fn peek(p: &Parser<'a>, c: Cursor) -> bool {
1270 c == Kind::Colon && p.peek_n(2) == Kind::Colon
1271 }
1272 }
1273
1274 impl<'a> Parse<'a> for ColonColon {
1275 fn parse(p: &mut Parser<'a>) -> Result<Self> {
1276 let first = p.parse::<T![:]>()?;
1277 let skip = p.set_skip(KindSet::NONE);
1278 let second = p.parse::<T![:]>();
1279 p.set_skip(skip);
1280 Ok(Self(first, second?))
1281 }
1282 }
1283
1284 impl ToCursors for ColonColon {
1285 fn to_cursors(&self, s: &mut impl CursorSink) {
1286 s.append(self.0.into());
1287 s.append(self.1.into());
1288 }
1289 }
1290
1291 impl ToSpan for ColonColon {
1292 fn to_span(&self) -> Span {
1293 self.0.to_span() + self.1.to_span()
1294 }
1295 }
1296}
1297
1298pub mod dimension {
1301 custom_dimension! {
1302 Cap, "cap"
1305 }
1306 custom_dimension! {
1307 Ch, "ch"
1310 }
1311 custom_dimension! {
1312 Cm, "cm"
1315 }
1316 custom_dimension! {
1317 Cqb, "cqb"
1320 }
1321 custom_dimension! {
1322 Cqh, "cqh"
1325 }
1326 custom_dimension! {
1327 Cqi, "cqi"
1330 }
1331 custom_dimension! {
1332 Cqmax, "cqmax"
1335 }
1336 custom_dimension! {
1337 Cqmin, "cqmin"
1340 }
1341 custom_dimension! {
1342 Cqw, "cqw"
1345 }
1346 custom_dimension! {
1347 Db, "db"
1350 }
1351 custom_dimension! {
1352 Deg, "deg"
1355 }
1356 custom_dimension! {
1357 Dpcm, "dpcm"
1360 }
1361 custom_dimension! {
1362 Dpi, "dpi"
1365 }
1366 custom_dimension! {
1367 Dppx, "dppx"
1370 }
1371 custom_dimension! {
1372 Dvb, "dvb"
1375 }
1376 custom_dimension! {
1377 Dvh, "dvh"
1380 }
1381 custom_dimension! {
1382 Dvi, "dvi"
1385 }
1386 custom_dimension! {
1387 Dvmax, "dvmax"
1390 }
1391 custom_dimension! {
1392 Dvmin, "dvmin"
1395 }
1396 custom_dimension! {
1397 Dvw, "dvw"
1400 }
1401 custom_dimension! {
1402 Em, "em"
1405 }
1406 custom_dimension! {
1407 Ex, "ex"
1410 }
1411 custom_dimension! {
1412 Fr, "fr"
1415 }
1416 custom_dimension! {
1417 Grad, "grad"
1420 }
1421 custom_dimension! {
1422 Hz, "hz"
1425 }
1426 custom_dimension! {
1427 Ic, "ic"
1430 }
1431 custom_dimension! {
1432 In, "in"
1435 }
1436 custom_dimension! {
1437 Khz, "khz"
1440 }
1441 custom_dimension! {
1442 Lh, "lh"
1445 }
1446 custom_dimension! {
1447 Lvb, "lvb"
1450 }
1451 custom_dimension! {
1452 Lvh, "lvh"
1455 }
1456 custom_dimension! {
1457 Lvi, "lvi"
1460 }
1461 custom_dimension! {
1462 Lvmax, "lvmax"
1465 }
1466 custom_dimension! {
1467 Lvmin, "lvmin"
1470 }
1471 custom_dimension! {
1472 Lvw, "lvw"
1475 }
1476 custom_dimension! {
1477 Mm, "mm"
1480 }
1481 custom_dimension! {
1482 Ms, "ms"
1485 }
1486 custom_dimension! {
1487 Pc, "pc"
1490 }
1491 custom_dimension! {
1492 Percent, "%"
1495 }
1496 custom_dimension! {
1497 Pt, "pt"
1500 }
1501 custom_dimension! {
1502 Px, "px"
1505 }
1506 custom_dimension! {
1507 Q, "q"
1510 }
1511 custom_dimension! {
1512 Rad, "rad"
1515 }
1516 custom_dimension! {
1517 Rcap, "rcap"
1520 }
1521 custom_dimension! {
1522 Rch, "rch"
1525 }
1526 custom_dimension! {
1527 Rem, "rem"
1530 }
1531 custom_dimension! {
1532 Rex, "rex"
1535 }
1536 custom_dimension! {
1537 Ric, "ric"
1540 }
1541 custom_dimension! {
1542 Rlh, "rlh"
1545 }
1546 custom_dimension! {
1547 S, "s"
1550 }
1551 custom_dimension! {
1552 Svb, "svb"
1555 }
1556 custom_dimension! {
1557 Svh, "svh"
1560 }
1561 custom_dimension! {
1562 Svi, "svi"
1565 }
1566 custom_dimension! {
1567 Svmax, "svmax"
1570 }
1571 custom_dimension! {
1572 Svmin, "svmin"
1575 }
1576 custom_dimension! {
1577 Svw, "svw"
1580 }
1581 custom_dimension! {
1582 Turn, "turn"
1585 }
1586 custom_dimension! {
1587 Vb, "vb"
1590 }
1591 custom_dimension! {
1592 Vh, "vh"
1595 }
1596 custom_dimension! {
1597 Vi, "vi"
1600 }
1601 custom_dimension! {
1602 Vmax, "vmax"
1605 }
1606 custom_dimension! {
1607 Vmin, "vmin"
1610 }
1611 custom_dimension! {
1612 Vw, "vw"
1615 }
1616 custom_dimension! {
1617 X, "x"
1620 }
1621}
1622
1623#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1625#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
1626pub struct Any(Cursor);
1627cursor_wrapped!(Any);
1628
1629impl<'a> Peek<'a> for Any {
1630 fn peek(_: &Parser<'a>, _: Cursor) -> bool {
1631 true
1632 }
1633}
1634
1635impl<'a> Build<'a> for Any {
1636 fn build(_: &Parser<'a>, c: Cursor) -> Self {
1637 Self(c)
1638 }
1639}
1640
1641#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1644#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
1645pub struct PairWiseStart(Cursor);
1646cursor_wrapped!(PairWiseStart);
1647
1648impl PairWiseStart {
1649 pub fn kind(&self) -> Kind {
1650 self.0.token().kind()
1651 }
1652
1653 pub fn end(&self) -> Kind {
1654 match self.kind() {
1655 Kind::LeftCurly => Kind::RightCurly,
1656 Kind::LeftParen => Kind::RightParen,
1657 Kind::LeftSquare => Kind::RightSquare,
1658 k => k,
1659 }
1660 }
1661}
1662
1663impl<'a> Peek<'a> for PairWiseStart {
1664 const PEEK_KINDSET: KindSet = KindSet::new(&[Kind::LeftCurly, Kind::LeftSquare, Kind::LeftParen]);
1665}
1666
1667impl<'a> Build<'a> for PairWiseStart {
1668 fn build(_: &Parser<'a>, c: Cursor) -> Self {
1669 Self(c)
1670 }
1671}
1672
1673#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1676#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
1677pub struct PairWiseEnd(Cursor);
1678cursor_wrapped!(PairWiseEnd);
1679
1680impl PairWiseEnd {
1681 pub fn kind(&self) -> Kind {
1682 self.0.token().kind()
1683 }
1684
1685 pub fn start(&self) -> Kind {
1686 match self.kind() {
1687 Kind::RightCurly => Kind::LeftCurly,
1688 Kind::RightParen => Kind::LeftParen,
1689 Kind::RightSquare => Kind::LeftSquare,
1690 k => k,
1691 }
1692 }
1693}
1694
1695impl<'a> Peek<'a> for PairWiseEnd {
1696 const PEEK_KINDSET: KindSet = KindSet::new(&[Kind::RightCurly, Kind::RightSquare, Kind::RightParen]);
1697}
1698
1699impl<'a> Build<'a> for PairWiseEnd {
1700 fn build(_: &Parser<'a>, c: Cursor) -> Self {
1701 Self(c)
1702 }
1703}
1704
1705#[macro_export]
1708macro_rules! T {
1709 [:] => { $crate::token_macros::Colon };
1710 [;] => { $crate::token_macros::Semicolon };
1711 [,] => { $crate::token_macros::Comma };
1712 ['{'] => { $crate::token_macros::LeftCurly };
1713 ['}'] => { $crate::token_macros::RightCurly };
1714 ['['] => { $crate::token_macros::LeftSquare };
1715 [']'] => { $crate::token_macros::RightSquare };
1716 ['('] => { $crate::token_macros::LeftParen };
1717 [')'] => { $crate::token_macros::RightParen };
1718 [' '] => { $crate::token_macros::Whitespace };
1719
1720 [&] => { $crate::token_macros::delim::And };
1721 [@] => { $crate::token_macros::delim::At };
1722 [^] => { $crate::token_macros::delim::Caret };
1723 [-] => { $crate::token_macros::delim::Dash };
1724 [$] => { $crate::token_macros::delim::Dollar };
1725 [.] => { $crate::token_macros::delim::Dot };
1726 [=] => { $crate::token_macros::delim::Eq };
1727 [>] => { $crate::token_macros::delim::Gt };
1728 [#] => { $crate::token_macros::delim::Hash };
1729 [<] => { $crate::token_macros::delim::Lt };
1730 [!] => { $crate::token_macros::delim::Bang };
1731 [|] => { $crate::token_macros::delim::Or };
1732 [%] => { $crate::token_macros::delim::Percent };
1733 [+] => { $crate::token_macros::delim::Plus };
1734 [?] => { $crate::token_macros::delim::Question };
1735 [/] => { $crate::token_macros::delim::Slash };
1736 [*] => { $crate::token_macros::delim::Star };
1737 [~] => { $crate::token_macros::delim::Tilde };
1738 [_] => { $crate::token_macros::delim::Underscore };
1739 ['`'] => { $crate::token_macros::delim::Backtick };
1740
1741 [>=] => { $crate::token_macros::double::GreaterThanEqual };
1742 [<=] => { $crate::token_macros::double::LessThanEqual };
1743 [*|] => { $crate::token_macros::double::StarPipe };
1744 [::] => { $crate::token_macros::double::ColonColon };
1745 [||] => { $crate::token_macros::double::PipePipe };
1746 [==] => { $crate::token_macros::double::EqualEqual };
1747 [~=] => { $crate::token_macros::double::TildeEqual };
1748 [|=] => { $crate::token_macros::double::PipeEqual };
1749 [^=] => { $crate::token_macros::double::CaretEqual };
1750 ["$="] => { $crate::token_macros::double::DollarEqual };
1751 [*=] => { $crate::token_macros::double::StarEqual };
1752
1753 [Dimension::$ident: ident] => { $crate::token_macros::dimension::$ident };
1754 [Dimension::%] => { $crate::token_macros::dimension::Percent };
1755 [DimensionIdent] => { $crate::token_macros::DimensionIdent };
1756
1757 [!important] => { $crate::token_macros::double::BangImportant };
1758
1759 [$ident:ident] => { $crate::token_macros::$ident }
1760}
1761
1762#[cfg(test)]
1763mod tests {
1764 use crate::{Cursor, DimensionUnit, Parser};
1765 use bumpalo::Bump;
1766
1767 #[test]
1768 fn test_custom_dimension() {
1769 custom_dimension!(Px, "px");
1770 let allocator = Bump::new();
1771 let mut p = Parser::new(&allocator, "1px");
1772 let result = p.parse_entirely::<Px>();
1773 assert!(matches!(result.output, Some(Px(_))));
1774 let c: Cursor = result.output.unwrap().into();
1775 assert!(c.token().value() == 1.0);
1776 assert!(c.token().dimension_unit() == DimensionUnit::Px);
1777 let mut p = Parser::new(&allocator, "1rem");
1778 let result = p.parse_entirely::<Px>();
1779 assert!(result.output.is_none());
1780 }
1781}