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