Skip to main content

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