css_parse/
token_macros.rs

1use crate::{Cursor, CursorSink, Kind, KindSet, Parse, Parser, Peek, Result, Span, ToNumberValue, Token};
2
3macro_rules! cursor_wrapped {
4	($ident:ident) => {
5		impl $crate::ToCursors for $ident {
6			fn to_cursors(&self, s: &mut impl CursorSink) {
7				s.append((*self).into());
8			}
9		}
10
11		impl From<$ident> for $crate::Cursor {
12			fn from(value: $ident) -> Self {
13				value.0.into()
14			}
15		}
16
17		impl From<$ident> for $crate::Token {
18			fn from(value: $ident) -> Self {
19				value.0.into()
20			}
21		}
22
23		impl $crate::ToSpan for $ident {
24			fn to_span(&self) -> Span {
25				self.0.to_span()
26			}
27		}
28
29		impl $crate::SemanticEq for $ident {
30			fn semantic_eq(&self, s: &Self) -> bool {
31				self.0.semantic_eq(&s.0)
32			}
33		}
34	};
35}
36
37macro_rules! define_kinds {
38	($($(#[$meta:meta])* $ident:ident,)*) => {
39		$(
40		$(#[$meta])*
41		#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
42		#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
43		pub struct $ident($crate::Cursor);
44
45		impl $ident {
46			pub const fn dummy() -> Self {
47				Self($crate::Cursor::dummy($crate::Token::dummy($crate::Kind::$ident)))
48			}
49
50			pub fn associated_whitespace(&self) -> $crate::AssociatedWhitespaceRules {
51				self.0.token().associated_whitespace()
52			}
53
54			pub fn with_associated_whitespace(&self, rules: $crate::AssociatedWhitespaceRules) -> Self {
55				Self(self.0.with_associated_whitespace(rules))
56			}
57		}
58
59		impl $crate::ToCursors for $ident {
60			fn to_cursors(&self, s: &mut impl $crate::CursorSink) {
61				s.append((*self).into());
62			}
63		}
64
65		impl<'a> $crate::Peek<'a> for $ident {
66			fn peek<I>(_: &$crate::Parser<'a, I>, c: $crate::Cursor) -> bool
67			where
68				I: ::std::iter::Iterator<Item = $crate::Cursor> + ::std::clone::Clone,
69			{
70				c == $crate::Kind::$ident
71			}
72		}
73
74		impl<'a> $crate::Parse<'a> for $ident {
75			fn parse<I>(p: &mut $crate::Parser<'a, I>) -> $crate::Result<Self>
76			where
77				I: ::std::iter::Iterator<Item = $crate::Cursor> + ::std::clone::Clone,
78			{
79				let c = p.next();
80				if Self::peek(p, c) { Ok(Self(c)) } else { Err($crate::Diagnostic::new(c, $crate::Diagnostic::unexpected))? }
81			}
82		}
83
84
85		impl From<$ident> for $crate::Cursor {
86			fn from(value: $ident) -> Self {
87				value.0.into()
88			}
89		}
90
91		impl From<$ident> for $crate::Token {
92			fn from(value: $ident) -> Self {
93				value.0.into()
94			}
95		}
96
97		impl $crate::ToSpan for $ident {
98			fn to_span(&self) -> $crate::Span {
99				self.0.to_span()
100			}
101		}
102
103		impl $crate::SemanticEq for $ident {
104			fn semantic_eq(&self, s: &Self) -> bool {
105				self.0.semantic_eq(&s.0)
106			}
107		}
108		)*
109	};
110}
111
112macro_rules! define_kind_idents {
113	($($(#[$meta:meta])* $ident:ident,)*) => {
114		$(
115		$(#[$meta])*
116		#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
117		#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
118		pub struct $ident($crate::Cursor);
119
120		impl $crate::ToCursors for $ident {
121			fn to_cursors(&self, s: &mut impl $crate::CursorSink) {
122				s.append((*self).into());
123			}
124		}
125
126		impl<'a> $crate::Peek<'a> for $ident {
127			fn peek<I>(_: &$crate::Parser<'a, I>, c: $crate::Cursor) -> bool
128			where
129				I: ::std::iter::Iterator<Item = $crate::Cursor> + ::std::clone::Clone,
130			{
131				c == $crate::Kind::$ident
132			}
133		}
134
135		impl<'a> $crate::Parse<'a> for $ident {
136			fn parse<I>(p: &mut $crate::Parser<'a, I>) -> $crate::Result<Self>
137			where
138				I: ::std::iter::Iterator<Item = $crate::Cursor> + ::std::clone::Clone,
139			{
140				let c = p.next();
141				if Self::peek(p, c) { Ok(Self(c)) } else { Err($crate::Diagnostic::new(c, $crate::Diagnostic::unexpected))? }
142			}
143		}
144
145
146		impl From<$ident> for $crate::Kind {
147			fn from(value: $ident) -> Self {
148				value.0.into()
149			}
150		}
151
152		impl From<$ident> for $crate::Cursor {
153			fn from(value: $ident) -> Self {
154				value.0
155			}
156		}
157
158		impl From<$ident> for $crate::Token {
159			fn from(value: $ident) -> Self {
160				value.0.into()
161			}
162		}
163
164		impl $crate::ToSpan for $ident {
165			fn to_span(&self) -> $crate::Span {
166				self.0.to_span()
167			}
168		}
169
170		impl $crate::SemanticEq for $ident {
171			fn semantic_eq(&self, s: &Self) -> bool {
172				self.0.semantic_eq(&s.0)
173			}
174		}
175
176		impl $ident {
177			/// Checks if the ident begins with two HYPHEN MINUS (`--`) characters.
178			pub fn is_dashed_ident(&self) -> bool {
179				self.0.token().is_dashed_ident()
180			}
181
182			pub const fn dummy() -> Self {
183				Self($crate::Cursor::dummy($crate::Token::dummy($crate::Kind::$ident)))
184			}
185		}
186		)*
187	};
188}
189
190/// A macro for defining a struct which captures a [Kind::Delim][Kind::Delim] with a specific character.
191///
192/// # Example
193///
194/// ```
195/// use css_parse::*;
196/// use bumpalo::Bump;
197/// custom_delim!{
198///   /// A £ character.
199///   PoundSterling, '£'
200/// }
201///
202/// assert_parse!(EmptyAtomSet::ATOMS, PoundSterling, "£");
203/// ```
204#[macro_export]
205macro_rules! custom_delim {
206	($(#[$meta:meta])* $ident:ident, $ch:literal) => {
207		$(#[$meta])*
208		#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
209		#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
210		pub struct $ident($crate::T![Delim]);
211
212		impl $crate::ToCursors for $ident {
213			fn to_cursors(&self, s: &mut impl $crate::CursorSink) {
214				s.append((*self).into());
215			}
216		}
217
218		impl<'a> $crate::Peek<'a> for $ident {
219			fn peek<I>(_: &$crate::Parser<'a, I>, c: $crate::Cursor) -> bool
220			where
221				I: ::std::iter::Iterator<Item = $crate::Cursor> + ::std::clone::Clone,
222			{
223				c == $crate::Kind::Delim && c == $ch
224			}
225		}
226
227		impl<'a> $crate::Parse<'a> for $ident {
228			fn parse<I>(p: &mut $crate::Parser<'a, I>) -> $crate::Result<Self>
229			where
230				I: ::std::iter::Iterator<Item = $crate::Cursor> + ::std::clone::Clone,
231			{
232				use $crate::Peek;
233				let delim = p.parse::<$crate::T![Delim]>()?;
234				if Self::peek(p, delim.into()) {
235					Ok(Self(delim))
236				} else {
237					Err($crate::Diagnostic::new(delim.into(), $crate::Diagnostic::unexpected))?
238				}
239			}
240		}
241
242
243
244		impl From<$ident> for $crate::Cursor {
245			fn from(value: $ident) -> Self {
246				value.0.into()
247			}
248		}
249
250		impl $crate::ToSpan for $ident {
251			fn to_span(&self) -> $crate::Span {
252				self.0.to_span()
253			}
254		}
255
256		impl PartialEq<char> for $ident {
257			fn eq(&self, other: &char) -> bool {
258				self.0 == *other
259			}
260		}
261
262		impl $crate::SemanticEq for $ident {
263			fn semantic_eq(&self, other: &Self) -> bool {
264				self.0.semantic_eq(&other.0)
265			}
266		}
267	};
268}
269
270/// A macro for defining a struct which captures two adjacent [Kind::Delim][Kind::Delim] tokens, each with a
271/// specific character.
272///
273/// # Example
274///
275/// ```
276/// use css_parse::*;
277/// use bumpalo::Bump;
278/// custom_double_delim!{
279///   /// Two % adjacent symbols
280///   DoublePercent, '%', '%'
281/// }
282///
283/// assert_parse!(EmptyAtomSet::ATOMS, DoublePercent, "%%");
284/// ```
285#[macro_export]
286macro_rules! custom_double_delim {
287	($(#[$meta:meta])*$ident: ident, $first: literal, $second: literal) => {
288		$(#[$meta])*
289		#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
290		#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
291		pub struct $ident($crate::T![Delim], pub $crate::T![Delim]);
292
293		impl $ident {
294			pub const fn dummy() -> Self {
295				Self(<$crate::T![Delim]>::dummy(), <$crate::T![Delim]>::dummy())
296			}
297		}
298
299		impl<'a> $crate::Peek<'a> for $ident {
300			fn peek<I>(p: &$crate::Parser<'a, I>, c: $crate::Cursor) -> bool
301			where
302				I: ::std::iter::Iterator<Item = $crate::Cursor> + ::std::clone::Clone,
303			{
304				c == $first && p.peek_n(2) == $second
305			}
306		}
307
308		impl<'a> $crate::Parse<'a> for $ident {
309			fn parse<I>(p: &mut $crate::Parser<'a, I>) -> $crate::Result<Self>
310			where
311				I: ::std::iter::Iterator<Item = $crate::Cursor> + ::std::clone::Clone,
312			{
313				let first = p.parse::<$crate::T![Delim]>()?;
314				if first != $first {
315					let c: Cursor = first.into();
316					Err($crate::Diagnostic::new(c, $crate::Diagnostic::expected_delim))?;
317				}
318				let skip = p.set_skip($crate::KindSet::NONE);
319				let second = p.parse::<$crate::T![Delim]>();
320				p.set_skip(skip);
321				let second = second?;
322				if second != $second {
323					let c:Cursor = second.into();
324					Err($crate::Diagnostic::new(c, $crate::Diagnostic::expected_delim))?;
325				}
326				Ok(Self(first, second))
327			}
328		}
329
330		impl<'a> $crate::ToCursors for $ident {
331			fn to_cursors(&self, s: &mut impl $crate::CursorSink) {
332				s.append(self.0.into());
333				s.append(self.1.into());
334			}
335		}
336
337		impl $crate::ToSpan for $ident {
338			fn to_span(&self) -> $crate::Span {
339				self.0.to_span() + self.1.to_span()
340			}
341		}
342
343		impl $crate::SemanticEq for $ident {
344			fn semantic_eq(&self, other: &Self) -> bool {
345				self.0.semantic_eq(&other.0) && self.1.semantic_eq(&other.1)
346			}
347		}
348	};
349}
350
351define_kinds! {
352	/// Represents a token with [Kind::Eof][Kind::Eof]. Use [T![Eof]][crate::T] to refer to this.
353	Eof,
354
355	/// Represents a token with [Kind::Comment][Kind::Comment]. Use [T![Comment]][crate::T] to refer to this.
356	Comment,
357
358	/// Represents a token with [Kind::CdcOrCdo][Kind::CdcOrCdo]. Use [T![CdcOrCdo]][crate::T] to refer to this.
359	CdcOrCdo,
360
361	/// Represents a token with [Kind::BadString][Kind::BadString]. Use [T![BadString]][crate::T] to refer to this.
362	BadString,
363
364	/// Represents a token with [Kind::BadUrl][Kind::BadUrl]. Use [T![BadUrl]][crate::T] to refer to this.[
365	BadUrl,
366
367	/// Represents a token with [Kind::Delim][Kind::Delim], can be any single character. Use [T![Delim]][crate::T] to refer to this.
368	Delim,
369
370	/// Represents a token with [Kind::Colon][Kind::Colon] - a `:` character. Use [T![:]][crate::T] to refer to this.
371	Colon,
372
373	/// Represents a token with [Kind::Semicolon][Kind::Semicolon] - a `;` character. Use [T![;]][crate::T] to refer to this.
374	Semicolon,
375
376	/// Represents a token with [Kind::Comma][Kind::Comma] - a `,` character. Use [T![,]][crate::T] to refer to this.
377	Comma,
378
379	/// Represents a token with [Kind::LeftCurly][Kind::LeftCurly] - a `{` character. Use [T!['{']][crate::T] to refer to this.
380	LeftCurly,
381
382	/// Represents a token with [Kind::LeftCurly][Kind::LeftCurly] - a `}` character. Use [T!['}']][crate::T] to refer to this.
383	RightCurly,
384
385	/// Represents a token with [Kind::LeftSquare][Kind::LeftSquare] - a `[` character. Use [T!['[']][crate::T] to refer to this.
386	LeftSquare,
387
388	/// Represents a token with [Kind::RightSquare][Kind::RightSquare] - a `]` character. Use [T![']']][crate::T] to refer to this.
389	RightSquare,
390
391	/// Represents a token with [Kind::LeftParen][Kind::LeftParen] - a `(` character. Use [T!['(']][crate::T] to refer to this.
392	LeftParen,
393
394	/// Represents a token with [Kind::RightParen][Kind::RightParen] - a `(` character. Use [T![')']][crate::T] to refer to this.
395	RightParen,
396}
397
398impl PartialEq<char> for Delim {
399	fn eq(&self, other: &char) -> bool {
400		self.0 == *other
401	}
402}
403
404define_kind_idents! {
405	/// Represents a token with [Kind::Ident][Kind::Ident]. Use [T![Ident]][crate::T] to refer to this.
406	Ident,
407
408	/// Represents a token with [Kind::String][Kind::String]. Use [T![String]][crate::T] to refer to this.
409	String,
410
411	/// Represents a token with [Kind::Url][Kind::Url]. Use [T![Url]][crate::T] to refer to this.
412	Url,
413
414	/// Represents a token with [Kind::Function][Kind::Function]. Use [T![Function]][crate::T] to refer to this.
415	Function,
416
417	/// Represents a token with [Kind::AtKeyword][Kind::AtKeyword]. Use [T![AtKeyword]][crate::T] to refer to this.
418	AtKeyword,
419
420	/// Represents a token with [Kind::Hash][Kind::Hash]. Use [T![Hash]][crate::T] to refer to this.
421	Hash,
422}
423
424/// Represents a token with [Kind::Whitespace]. Use [T![Whitespace]][crate::T] to refer to
425/// this.
426#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
427#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
428pub struct Whitespace(Cursor);
429cursor_wrapped!(Whitespace);
430
431impl<'a> Peek<'a> for Whitespace {
432	fn peek<I>(p: &Parser<'a, I>, _: Cursor) -> bool
433	where
434		I: Iterator<Item = Cursor> + Clone,
435	{
436		// Whitespace needs to peek its own cursor because it was likely given one that skipped Whitespace.
437		let c = p.peek_n_with_skip(1, KindSet::COMMENTS);
438		c == Kind::Whitespace
439	}
440}
441
442impl<'a> Parse<'a> for Whitespace {
443	fn parse<I>(p: &mut Parser<'a, I>) -> Result<Self>
444	where
445		I: Iterator<Item = Cursor> + Clone,
446	{
447		// Whitespace needs to implement parse so that it can change the skip-state to only ensuring Whitespace
448		// is not ignored.
449		let skip = p.set_skip(KindSet::COMMENTS);
450		let c = p.next();
451		p.set_skip(skip);
452		if c != Kind::Whitespace {
453			Err(crate::Diagnostic::new(c, crate::Diagnostic::unexpected))?
454		}
455		Ok(Self(c))
456	}
457}
458
459/// Represents a token with [Kind::Ident] that also begins with two HYPHEN MINUS (`--`)
460/// characters. Use [T![DashedIdent]][crate::T] to refer to this.
461#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
462#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
463pub struct DashedIdent(Ident);
464cursor_wrapped!(DashedIdent);
465
466impl<'a> Peek<'a> for DashedIdent {
467	fn peek<I>(_: &Parser<'a, I>, c: Cursor) -> bool
468	where
469		I: Iterator<Item = Cursor> + Clone,
470	{
471		c == Kind::Ident && c.token().is_dashed_ident()
472	}
473}
474
475impl<'a> Parse<'a> for DashedIdent {
476	fn parse<I>(p: &mut Parser<'a, I>) -> Result<Self>
477	where
478		I: Iterator<Item = Cursor> + Clone,
479	{
480		let c = p.next();
481		if Self::peek(p, c) {
482			Ok(Self(Ident(c)))
483		} else {
484			Err(crate::Diagnostic::new(c, crate::Diagnostic::unexpected))?
485		}
486	}
487}
488
489/// Represents a token with [Kind::Dimension]. Use [T![Dimension]][crate::T] to refer to this.
490#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
491#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
492pub struct Dimension(Cursor);
493cursor_wrapped!(Dimension);
494
495impl PartialEq<f32> for Dimension {
496	fn eq(&self, other: &f32) -> bool {
497		self.0.token().value() == *other
498	}
499}
500
501impl<'a> Peek<'a> for Dimension {
502	fn peek<I>(_: &Parser<'a, I>, c: Cursor) -> bool
503	where
504		I: Iterator<Item = Cursor> + Clone,
505	{
506		c == Kind::Dimension
507	}
508}
509
510impl<'a> Parse<'a> for Dimension {
511	fn parse<I>(p: &mut Parser<'a, I>) -> Result<Self>
512	where
513		I: Iterator<Item = Cursor> + Clone,
514	{
515		let c = p.next();
516		if Self::peek(p, c) { Ok(Self(c)) } else { Err(crate::Diagnostic::new(c, crate::Diagnostic::unexpected))? }
517	}
518}
519
520impl From<Dimension> for f32 {
521	fn from(val: Dimension) -> Self {
522		val.0.token().value()
523	}
524}
525
526impl ToNumberValue for Dimension {
527	fn to_number_value(&self) -> Option<f32> {
528		Some(self.0.token().value())
529	}
530}
531
532impl Dimension {
533	/// Returns the [f32] representation of the dimension's value.
534	pub fn value(&self) -> f32 {
535		self.0.token().value()
536	}
537}
538
539/// Represents a token with [Kind::Number]. Use [T![Number]][crate::T] to refer to this.
540#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
541#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
542pub struct Number(Cursor);
543cursor_wrapped!(Number);
544
545impl Number {
546	pub const NUMBER_ZERO: Number = Number(Cursor::dummy(Token::NUMBER_ZERO));
547	pub const ZERO: Number = Number(Cursor::dummy(Token::NUMBER_ZERO));
548
549	/// Returns the [f32] representation of the number's value.
550	pub fn value(&self) -> f32 {
551		self.0.token().value()
552	}
553
554	pub fn is_int(&self) -> bool {
555		self.0.token().is_int()
556	}
557
558	pub fn is_float(&self) -> bool {
559		self.0.token().is_float()
560	}
561
562	pub fn has_sign(&self) -> bool {
563		self.0.token().has_sign()
564	}
565}
566
567impl<'a> Peek<'a> for Number {
568	fn peek<I>(_: &Parser<'a, I>, c: Cursor) -> bool
569	where
570		I: Iterator<Item = Cursor> + Clone,
571	{
572		c == Kind::Number
573	}
574}
575
576impl<'a> Parse<'a> for Number {
577	fn parse<I>(p: &mut Parser<'a, I>) -> Result<Self>
578	where
579		I: Iterator<Item = Cursor> + Clone,
580	{
581		let c = p.next();
582		if Self::peek(p, c) { Ok(Self(c)) } else { Err(crate::Diagnostic::new(c, crate::Diagnostic::unexpected))? }
583	}
584}
585
586impl From<Number> for f32 {
587	fn from(value: Number) -> Self {
588		value.value()
589	}
590}
591
592impl From<Number> for i32 {
593	fn from(value: Number) -> Self {
594		value.value() as i32
595	}
596}
597
598impl PartialEq<f32> for Number {
599	fn eq(&self, other: &f32) -> bool {
600		self.value() == *other
601	}
602}
603
604impl ToNumberValue for Number {
605	fn to_number_value(&self) -> Option<f32> {
606		Some(self.value())
607	}
608}
609
610/// Various [T!s][crate::T] representing a tokens with [Kind::Delim], but each represents a discrete character.
611pub mod delim {
612	custom_delim! {
613		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `&`. Use [T![&]][crate::T] to
614		/// refer to this.
615		And, '&'
616	}
617	custom_delim! {
618		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `@`. Use [T![@]][crate::T] to
619		/// refer to this. Not to be conused with [T![AtKeyword]][crate::T] which represents a token with
620		/// [Kind::AtKeyword][crate::Kind::AtKeyword].
621		At, '@'
622	}
623	custom_delim! {
624		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `^`. Use [T![^]][crate::T] to
625		/// refer to this.
626		Caret, '^'
627	}
628	custom_delim! {
629		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `-`. Use [T![-]][crate::T] to
630		/// refer to this.
631		Dash, '-'
632	}
633	custom_delim! {
634		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `$`. Use [T![$]][crate::T] to
635		/// refer to this.
636		Dollar, '$'
637	}
638	custom_delim! {
639		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `.`. Use [T![.]][crate::T] to
640		/// refer to this.
641		Dot, '.'
642	}
643	custom_delim! {
644		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `=`. Use [T![=]][crate::T] to
645		/// refer to this.
646		Eq, '='
647	}
648	custom_delim! {
649		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `>`. Use [T![>]][crate::T] to
650		/// refer to this.
651		Gt, '>'
652	}
653	custom_delim! {
654		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `#`. Use [T![#]][crate::T] to
655		/// refer to this. Not to be conused with [T![Hash]][crate::T] which represents a token with
656		/// [Kind::Hash][crate::Kind::Hash].
657		Hash, '#'
658	}
659	custom_delim! {
660		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `<`. Use [T![<]][crate::T] to
661		/// refer to this.
662		Lt, '<'
663	}
664	custom_delim! {
665		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `!`. Use [T![!]][crate::T] to
666		/// refer to this.
667		Bang, '!'
668	}
669	custom_delim! {
670		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `|`. Use [T![|]][crate::T] to
671		/// refer to this.
672		Or, '|'
673	}
674	custom_delim! {
675		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `%`. Use [T![%]][crate::T] to
676		/// refer to this.
677		Percent, '%'
678	}
679	custom_delim! {
680		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `+`. Use [T![+]][crate::T] to
681		/// refer to this.
682		Plus, '+'
683	}
684	custom_delim! {
685		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `?`. Use [T![?]][crate::T] to
686		/// refer to this.
687		Question, '?'
688	}
689	custom_delim! {
690		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `/`. Use [T![/]][crate::T] to
691		/// refer to this.
692		Slash, '/'
693	}
694	custom_delim! {
695		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `*`. Use [T![*]][crate::T] to
696		/// refer to this.
697		Star, '*'
698	}
699	custom_delim! {
700		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `~`. Use [T![~]][crate::T] to
701		/// refer to this.
702		Tilde, '~'
703	}
704	custom_delim! {
705		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `_`. Use [T![_]][crate::T] to
706		/// refer to this.
707		Underscore, '_'
708	}
709	custom_delim! {
710		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char ```. Use [T!['`']][crate::T] to
711		/// refer to this.
712		Backtick, '`'
713	}
714}
715
716/// Various [T!s][crate::T] representing two consecutive tokens that cannot be separated by any other tokens. These are
717/// convenient as it can be tricky to parse two consecutive tokens given the default behaviour of the parser is to skip
718/// whitespace and comments.
719pub mod double {
720	use crate::{
721		Cursor, CursorSink, Kind, KindSet, Parse, Parser, Peek, Result, SemanticEq, Span, T, ToCursors, ToSpan,
722	};
723
724	custom_double_delim! {
725		/// Represents a two consecutive tokens with [Kind::Delim][crate::Kind::Delim] that cannot be separated by any
726		/// other token. The first token has the char `>` while the second has the char `=`, representing `>=`. Use
727		/// [T![>=]][crate::T] to refer to this.
728		GreaterThanEqual, '>', '='
729	}
730	custom_double_delim! {
731		/// Represents a two consecutive tokens with [Kind::Delim][crate::Kind::Delim] that cannot be separated by any
732		/// other token. The first token has the char `<` while the second has the char `=`, representing `<=`. Use
733		/// [T![<=]][crate::T] to refer to this.
734		LessThanEqual, '<', '='
735	}
736	custom_double_delim! {
737		/// Represents a two consecutive tokens with [Kind::Delim][crate::Kind::Delim] that cannot be separated by any
738		/// other token. The first token has the char `*` while the second has the char `|`, representing `*|`. Use
739		/// [T![*|]][crate::T] to refer to this.
740		StarPipe, '*', '|'
741	}
742	custom_double_delim! {
743		/// Represents a two consecutive tokens with [Kind::Delim][crate::Kind::Delim] that cannot be separated by any
744		/// other token. The first token has the char `|` while the second has the char `|`, representing `||`. Use
745		/// [T![||]][crate::T] to refer to this.
746		PipePipe, '|', '|'
747	}
748	custom_double_delim! {
749		/// Represents a two consecutive tokens with [Kind::Delim][crate::Kind::Delim] that cannot be separated by any
750		/// other token. The first token has the char `=` while the second has the char `=`, representing `==`. Use
751		/// [T![==]][crate::T] to refer to this.
752		EqualEqual, '=', '='
753	}
754	custom_double_delim! {
755		/// Represents a two consecutive tokens with [Kind::Delim][crate::Kind::Delim] that cannot be separated by any
756		/// other token. The first token has the char `~` while the second has the char `=`, representing `~=`. Use
757		/// [T![~=]][crate::T] to refer to this.
758		TildeEqual, '~', '='
759	}
760	custom_double_delim! {
761		/// Represents a two consecutive tokens with [Kind::Delim][crate::Kind::Delim] that cannot be separated by any
762		/// other token. The first token has the char `|` while the second has the char `=`, representing `|=`. Use
763		/// [T![|=]][crate::T] to refer to this.
764		PipeEqual, '|', '='
765	}
766	custom_double_delim! {
767		/// Represents a two consecutive tokens with [Kind::Delim][crate::Kind::Delim] that cannot be separated by any
768		/// other token. The first token has the char `^` while the second has the char `=`, representing `^=`. Use
769		/// [T![\^=]][crate::T] to refer to this.
770		CaretEqual, '^', '='
771	}
772	custom_double_delim! {
773		/// Represents a two consecutive tokens with [Kind::Delim][crate::Kind::Delim] that cannot be separated by any
774		/// other token. The first token has the char `$` while the second has the char `=`, representing `$=`. Use
775		/// [T![$=]][crate::T] to refer to this.
776		DollarEqual, '$', '='
777	}
778	custom_double_delim! {
779		/// Represents a two consecutive tokens with [Kind::Delim][crate::Kind::Delim] that cannot be separated by any
780		/// other token. The first token has the char `*` while the second has the char `=`, representing `*=`. Use
781		/// [T![*=]][crate::T] to refer to this.
782		StarEqual, '*', '='
783	}
784
785	/// Represents a two consecutive tokens with [Kind::Colon] that cannot be separated by any other token, representing
786	/// `::`. Use [T![::]][crate::T] to refer to this.
787	#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
788	#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
789	pub struct ColonColon(T![:], T![:]);
790
791	impl ColonColon {
792		pub const fn dummy() -> Self {
793			Self(<T![:]>::dummy(), <T![:]>::dummy())
794		}
795	}
796
797	impl<'a> Peek<'a> for ColonColon {
798		fn peek<I>(p: &Parser<'a, I>, c: Cursor) -> bool
799		where
800			I: Iterator<Item = Cursor> + Clone,
801		{
802			c == Kind::Colon && p.peek_n(2) == Kind::Colon
803		}
804	}
805
806	impl<'a> Parse<'a> for ColonColon {
807		fn parse<I>(p: &mut Parser<'a, I>) -> Result<Self>
808		where
809			I: Iterator<Item = Cursor> + Clone,
810		{
811			let first = p.parse::<T![:]>()?;
812			let skip = p.set_skip(KindSet::NONE);
813			let second = p.parse::<T![:]>();
814			p.set_skip(skip);
815			Ok(Self(first, second?))
816		}
817	}
818
819	impl ToCursors for ColonColon {
820		fn to_cursors(&self, s: &mut impl CursorSink) {
821			s.append(self.0.into());
822			s.append(self.1.into());
823		}
824	}
825
826	impl ToSpan for ColonColon {
827		fn to_span(&self) -> Span {
828			self.0.to_span() + self.1.to_span()
829		}
830	}
831
832	impl SemanticEq for ColonColon {
833		fn semantic_eq(&self, other: &Self) -> bool {
834			self.0.semantic_eq(&other.0) && self.1.semantic_eq(&other.1)
835		}
836	}
837}
838
839/// Represents any possible single token. Use [T![Any]][crate::T] to refer to this.
840#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
841#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
842pub struct Any(Cursor);
843cursor_wrapped!(Any);
844
845impl<'a> Peek<'a> for Any {
846	fn peek<I>(_: &Parser<'a, I>, _: Cursor) -> bool
847	where
848		I: Iterator<Item = Cursor> + Clone,
849	{
850		true
851	}
852}
853
854impl<'a> Parse<'a> for Any {
855	fn parse<I>(p: &mut Parser<'a, I>) -> Result<Self>
856	where
857		I: Iterator<Item = Cursor> + Clone,
858	{
859		let c = p.next();
860		Ok(Self(c))
861	}
862}
863
864/// Represents a token with either [Kind::LeftCurly], [Kind::LeftParen] or [Kind::LeftSquare]. Use
865/// [T![PairWiseStart]][crate::T] to refer to this.
866#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
867#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
868pub struct PairWiseStart(Cursor);
869cursor_wrapped!(PairWiseStart);
870
871impl PairWiseStart {
872	pub fn kind(&self) -> Kind {
873		self.0.token().kind()
874	}
875
876	pub fn end(&self) -> Kind {
877		match self.kind() {
878			Kind::LeftCurly => Kind::RightCurly,
879			Kind::LeftParen => Kind::RightParen,
880			Kind::LeftSquare => Kind::RightSquare,
881			k => k,
882		}
883	}
884}
885
886impl<'a> Peek<'a> for PairWiseStart {
887	const PEEK_KINDSET: KindSet = KindSet::new(&[Kind::LeftCurly, Kind::LeftSquare, Kind::LeftParen]);
888}
889
890impl<'a> Parse<'a> for PairWiseStart {
891	fn parse<I>(p: &mut Parser<'a, I>) -> Result<Self>
892	where
893		I: Iterator<Item = Cursor> + Clone,
894	{
895		let c = p.next();
896		if Self::peek(p, c) { Ok(Self(c)) } else { Err(crate::Diagnostic::new(c, crate::Diagnostic::unexpected))? }
897	}
898}
899
900/// Represents a token with either [Kind::RightCurly], [Kind::RightParen] or [Kind::RightSquare]. Use
901/// [T![PairWiseEnd]][crate::T] to refer to this.
902#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
903#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
904pub struct PairWiseEnd(Cursor);
905cursor_wrapped!(PairWiseEnd);
906
907impl PairWiseEnd {
908	pub fn kind(&self) -> Kind {
909		self.0.token().kind()
910	}
911
912	pub fn start(&self) -> Kind {
913		match self.kind() {
914			Kind::RightCurly => Kind::LeftCurly,
915			Kind::RightParen => Kind::LeftParen,
916			Kind::RightSquare => Kind::LeftSquare,
917			k => k,
918		}
919	}
920}
921
922impl<'a> Peek<'a> for PairWiseEnd {
923	const PEEK_KINDSET: KindSet = KindSet::new(&[Kind::RightCurly, Kind::RightSquare, Kind::RightParen]);
924}
925
926impl<'a> Parse<'a> for PairWiseEnd {
927	fn parse<I>(p: &mut Parser<'a, I>) -> Result<Self>
928	where
929		I: Iterator<Item = Cursor> + Clone,
930	{
931		let c = p.next();
932		if Self::peek(p, c) { Ok(Self(c)) } else { Err(crate::Diagnostic::new(c, crate::Diagnostic::unexpected))? }
933	}
934}
935
936/// The [T!][crate::T] macro expands to the name of a type representing the Token of the same name. These can be used in struct
937/// fields to type child nodes.
938#[macro_export]
939macro_rules! T {
940	[:] => { $crate::token_macros::Colon };
941	[;] => { $crate::token_macros::Semicolon };
942	[,] => { $crate::token_macros::Comma };
943	['{'] => { $crate::token_macros::LeftCurly };
944	['}'] => { $crate::token_macros::RightCurly };
945	['['] => { $crate::token_macros::LeftSquare };
946	[']'] => { $crate::token_macros::RightSquare };
947	['('] => { $crate::token_macros::LeftParen };
948	[')'] => { $crate::token_macros::RightParen };
949	[' '] => { $crate::token_macros::Whitespace };
950
951	[&] => { $crate::token_macros::delim::And };
952	[@] => { $crate::token_macros::delim::At };
953	[^] => { $crate::token_macros::delim::Caret };
954	[-] => { $crate::token_macros::delim::Dash };
955	[$] => { $crate::token_macros::delim::Dollar };
956	[.] => { $crate::token_macros::delim::Dot };
957	[=] => { $crate::token_macros::delim::Eq };
958	[>] => { $crate::token_macros::delim::Gt };
959	[#] => { $crate::token_macros::delim::Hash };
960	[<] => { $crate::token_macros::delim::Lt };
961	[!] => { $crate::token_macros::delim::Bang };
962	[|] => { $crate::token_macros::delim::Or };
963	[%] => { $crate::token_macros::delim::Percent };
964	[+] => { $crate::token_macros::delim::Plus };
965	[?] => { $crate::token_macros::delim::Question };
966	[/] => { $crate::token_macros::delim::Slash };
967	[*] => { $crate::token_macros::delim::Star };
968	[~] => { $crate::token_macros::delim::Tilde };
969	[_] => { $crate::token_macros::delim::Underscore };
970	['`'] => { $crate::token_macros::delim::Backtick };
971
972	[>=] => { $crate::token_macros::double::GreaterThanEqual };
973	[<=] => { $crate::token_macros::double::LessThanEqual };
974	[*|] => { $crate::token_macros::double::StarPipe };
975	[::] => { $crate::token_macros::double::ColonColon };
976	[||] => { $crate::token_macros::double::PipePipe };
977	[==] => { $crate::token_macros::double::EqualEqual };
978	[~=] => { $crate::token_macros::double::TildeEqual };
979	[|=] => { $crate::token_macros::double::PipeEqual };
980	[^=] => { $crate::token_macros::double::CaretEqual };
981	["$="] => { $crate::token_macros::double::DollarEqual };
982	[*=] => { $crate::token_macros::double::StarEqual };
983
984	[Dimension::$ident: ident] => { $crate::token_macros::dimension::$ident };
985
986	[!important] => { $crate::token_macros::double::BangImportant };
987
988	[$ident:ident] => { $crate::token_macros::$ident }
989}