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	pub fn preserve_sign(self) -> Self {
567		if self.has_sign() { Self(self.0.with_sign_required()) } else { self }
568	}
569}
570
571impl<'a> Peek<'a> for Number {
572	fn peek<I>(_: &Parser<'a, I>, c: Cursor) -> bool
573	where
574		I: Iterator<Item = Cursor> + Clone,
575	{
576		c == Kind::Number
577	}
578}
579
580impl<'a> Parse<'a> for Number {
581	fn parse<I>(p: &mut Parser<'a, I>) -> Result<Self>
582	where
583		I: Iterator<Item = Cursor> + Clone,
584	{
585		let c = p.next();
586		if Self::peek(p, c) { Ok(Self(c)) } else { Err(crate::Diagnostic::new(c, crate::Diagnostic::unexpected))? }
587	}
588}
589
590impl From<Number> for f32 {
591	fn from(value: Number) -> Self {
592		value.value()
593	}
594}
595
596impl From<Number> for i32 {
597	fn from(value: Number) -> Self {
598		value.value() as i32
599	}
600}
601
602impl PartialEq<f32> for Number {
603	fn eq(&self, other: &f32) -> bool {
604		self.value() == *other
605	}
606}
607
608impl ToNumberValue for Number {
609	fn to_number_value(&self) -> Option<f32> {
610		Some(self.value())
611	}
612}
613
614/// Various [T!s][crate::T] representing a tokens with [Kind::Delim], but each represents a discrete character.
615pub mod delim {
616	custom_delim! {
617		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `&`. Use [T![&]][crate::T] to
618		/// refer to this.
619		And, '&'
620	}
621	custom_delim! {
622		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `@`. Use [T![@]][crate::T] to
623		/// refer to this. Not to be conused with [T![AtKeyword]][crate::T] which represents a token with
624		/// [Kind::AtKeyword][crate::Kind::AtKeyword].
625		At, '@'
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		Caret, '^'
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		Dash, '-'
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		Dollar, '$'
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.
645		Dot, '.'
646	}
647	custom_delim! {
648		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `=`. Use [T![=]][crate::T] to
649		/// refer to this.
650		Eq, '='
651	}
652	custom_delim! {
653		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `>`. Use [T![>]][crate::T] to
654		/// refer to this.
655		Gt, '>'
656	}
657	custom_delim! {
658		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `#`. Use [T![#]][crate::T] to
659		/// refer to this. Not to be conused with [T![Hash]][crate::T] which represents a token with
660		/// [Kind::Hash][crate::Kind::Hash].
661		Hash, '#'
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		Lt, '<'
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		Bang, '!'
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		Or, '|'
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		Percent, '%'
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		Plus, '+'
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		Question, '?'
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		Slash, '/'
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		Star, '*'
702	}
703	custom_delim! {
704		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `~`. Use [T![~]][crate::T] to
705		/// refer to this.
706		Tilde, '~'
707	}
708	custom_delim! {
709		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char `_`. Use [T![_]][crate::T] to
710		/// refer to this.
711		Underscore, '_'
712	}
713	custom_delim! {
714		/// Represents a token with [Kind::Delim][crate::Kind::Delim] that has the char ```. Use [T!['`']][crate::T] to
715		/// refer to this.
716		Backtick, '`'
717	}
718}
719
720/// Various [T!s][crate::T] representing two consecutive tokens that cannot be separated by any other tokens. These are
721/// convenient as it can be tricky to parse two consecutive tokens given the default behaviour of the parser is to skip
722/// whitespace and comments.
723pub mod double {
724	use crate::{
725		Cursor, CursorSink, Kind, KindSet, Parse, Parser, Peek, Result, SemanticEq, Span, T, ToCursors, ToSpan,
726	};
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		GreaterThanEqual, '>', '='
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		LessThanEqual, '<', '='
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		StarPipe, '*', '|'
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		PipePipe, '|', '|'
751	}
752	custom_double_delim! {
753		/// Represents a two consecutive tokens with [Kind::Delim][crate::Kind::Delim] that cannot be separated by any
754		/// other token. The first token has the char `=` while the second has the char `=`, representing `==`. Use
755		/// [T![==]][crate::T] to refer to this.
756		EqualEqual, '=', '='
757	}
758	custom_double_delim! {
759		/// Represents a two consecutive tokens with [Kind::Delim][crate::Kind::Delim] that cannot be separated by any
760		/// other token. The first token has the char `~` while the second has the char `=`, representing `~=`. Use
761		/// [T![~=]][crate::T] to refer to this.
762		TildeEqual, '~', '='
763	}
764	custom_double_delim! {
765		/// Represents a two consecutive tokens with [Kind::Delim][crate::Kind::Delim] that cannot be separated by any
766		/// other token. The first token has the char `|` while the second has the char `=`, representing `|=`. Use
767		/// [T![|=]][crate::T] to refer to this.
768		PipeEqual, '|', '='
769	}
770	custom_double_delim! {
771		/// Represents a two consecutive tokens with [Kind::Delim][crate::Kind::Delim] that cannot be separated by any
772		/// other token. The first token has the char `^` while the second has the char `=`, representing `^=`. Use
773		/// [T![\^=]][crate::T] to refer to this.
774		CaretEqual, '^', '='
775	}
776	custom_double_delim! {
777		/// Represents a two consecutive tokens with [Kind::Delim][crate::Kind::Delim] that cannot be separated by any
778		/// other token. The first token has the char `$` while the second has the char `=`, representing `$=`. Use
779		/// [T![$=]][crate::T] to refer to this.
780		DollarEqual, '$', '='
781	}
782	custom_double_delim! {
783		/// Represents a two consecutive tokens with [Kind::Delim][crate::Kind::Delim] that cannot be separated by any
784		/// other token. The first token has the char `*` while the second has the char `=`, representing `*=`. Use
785		/// [T![*=]][crate::T] to refer to this.
786		StarEqual, '*', '='
787	}
788	custom_double_delim! {
789		/// Represents a two consecutive tokens with [Kind::Delim][crate::Kind::Delim] that cannot be separated by any
790		/// other token. The first token has the char `!` while the second has the char `=`, representing `!=`. Use
791		/// [T![!=]][crate::T] to refer to this.
792		BangEqual, '*', '='
793	}
794
795	/// Represents a two consecutive tokens with [Kind::Colon] that cannot be separated by any other token, representing
796	/// `::`. Use [T![::]][crate::T] to refer to this.
797	#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
798	#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
799	pub struct ColonColon(T![:], T![:]);
800
801	impl ColonColon {
802		pub const fn dummy() -> Self {
803			Self(<T![:]>::dummy(), <T![:]>::dummy())
804		}
805	}
806
807	impl<'a> Peek<'a> for ColonColon {
808		fn peek<I>(p: &Parser<'a, I>, c: Cursor) -> bool
809		where
810			I: Iterator<Item = Cursor> + Clone,
811		{
812			c == Kind::Colon && p.peek_n(2) == Kind::Colon
813		}
814	}
815
816	impl<'a> Parse<'a> for ColonColon {
817		fn parse<I>(p: &mut Parser<'a, I>) -> Result<Self>
818		where
819			I: Iterator<Item = Cursor> + Clone,
820		{
821			let first = p.parse::<T![:]>()?;
822			let skip = p.set_skip(KindSet::NONE);
823			let second = p.parse::<T![:]>();
824			p.set_skip(skip);
825			Ok(Self(first, second?))
826		}
827	}
828
829	impl ToCursors for ColonColon {
830		fn to_cursors(&self, s: &mut impl CursorSink) {
831			s.append(self.0.into());
832			s.append(self.1.into());
833		}
834	}
835
836	impl ToSpan for ColonColon {
837		fn to_span(&self) -> Span {
838			self.0.to_span() + self.1.to_span()
839		}
840	}
841
842	impl SemanticEq for ColonColon {
843		fn semantic_eq(&self, other: &Self) -> bool {
844			self.0.semantic_eq(&other.0) && self.1.semantic_eq(&other.1)
845		}
846	}
847}
848
849/// Represents any possible single token. Use [T![Any]][crate::T] to refer to this.
850#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
851#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
852pub struct Any(Cursor);
853cursor_wrapped!(Any);
854
855impl<'a> Peek<'a> for Any {
856	fn peek<I>(_: &Parser<'a, I>, _: Cursor) -> bool
857	where
858		I: Iterator<Item = Cursor> + Clone,
859	{
860		true
861	}
862}
863
864impl<'a> Parse<'a> for Any {
865	fn parse<I>(p: &mut Parser<'a, I>) -> Result<Self>
866	where
867		I: Iterator<Item = Cursor> + Clone,
868	{
869		let c = p.next();
870		Ok(Self(c))
871	}
872}
873
874/// Represents a token with either [Kind::LeftCurly], [Kind::LeftParen] or [Kind::LeftSquare]. Use
875/// [T![PairWiseStart]][crate::T] to refer to this.
876#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
877#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
878pub struct PairWiseStart(Cursor);
879cursor_wrapped!(PairWiseStart);
880
881impl PairWiseStart {
882	pub fn kind(&self) -> Kind {
883		self.0.token().kind()
884	}
885
886	pub fn end(&self) -> Kind {
887		match self.kind() {
888			Kind::LeftCurly => Kind::RightCurly,
889			Kind::LeftParen => Kind::RightParen,
890			Kind::LeftSquare => Kind::RightSquare,
891			k => k,
892		}
893	}
894}
895
896impl<'a> Peek<'a> for PairWiseStart {
897	const PEEK_KINDSET: KindSet = KindSet::new(&[Kind::LeftCurly, Kind::LeftSquare, Kind::LeftParen]);
898}
899
900impl<'a> Parse<'a> for PairWiseStart {
901	fn parse<I>(p: &mut Parser<'a, I>) -> Result<Self>
902	where
903		I: Iterator<Item = Cursor> + Clone,
904	{
905		let c = p.next();
906		if Self::peek(p, c) { Ok(Self(c)) } else { Err(crate::Diagnostic::new(c, crate::Diagnostic::unexpected))? }
907	}
908}
909
910/// Represents a token with either [Kind::RightCurly], [Kind::RightParen] or [Kind::RightSquare]. Use
911/// [T![PairWiseEnd]][crate::T] to refer to this.
912#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
913#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
914pub struct PairWiseEnd(Cursor);
915cursor_wrapped!(PairWiseEnd);
916
917impl PairWiseEnd {
918	pub fn kind(&self) -> Kind {
919		self.0.token().kind()
920	}
921
922	pub fn start(&self) -> Kind {
923		match self.kind() {
924			Kind::RightCurly => Kind::LeftCurly,
925			Kind::RightParen => Kind::LeftParen,
926			Kind::RightSquare => Kind::LeftSquare,
927			k => k,
928		}
929	}
930}
931
932impl<'a> Peek<'a> for PairWiseEnd {
933	const PEEK_KINDSET: KindSet = KindSet::new(&[Kind::RightCurly, Kind::RightSquare, Kind::RightParen]);
934}
935
936impl<'a> Parse<'a> for PairWiseEnd {
937	fn parse<I>(p: &mut Parser<'a, I>) -> Result<Self>
938	where
939		I: Iterator<Item = Cursor> + Clone,
940	{
941		let c = p.next();
942		if Self::peek(p, c) { Ok(Self(c)) } else { Err(crate::Diagnostic::new(c, crate::Diagnostic::unexpected))? }
943	}
944}
945
946/// 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
947/// fields to type child nodes.
948#[macro_export]
949macro_rules! T {
950	[:] => { $crate::token_macros::Colon };
951	[;] => { $crate::token_macros::Semicolon };
952	[,] => { $crate::token_macros::Comma };
953	['{'] => { $crate::token_macros::LeftCurly };
954	['}'] => { $crate::token_macros::RightCurly };
955	['['] => { $crate::token_macros::LeftSquare };
956	[']'] => { $crate::token_macros::RightSquare };
957	['('] => { $crate::token_macros::LeftParen };
958	[')'] => { $crate::token_macros::RightParen };
959	[' '] => { $crate::token_macros::Whitespace };
960
961	[&] => { $crate::token_macros::delim::And };
962	[@] => { $crate::token_macros::delim::At };
963	[^] => { $crate::token_macros::delim::Caret };
964	[-] => { $crate::token_macros::delim::Dash };
965	[$] => { $crate::token_macros::delim::Dollar };
966	[.] => { $crate::token_macros::delim::Dot };
967	[=] => { $crate::token_macros::delim::Eq };
968	[>] => { $crate::token_macros::delim::Gt };
969	[#] => { $crate::token_macros::delim::Hash };
970	[<] => { $crate::token_macros::delim::Lt };
971	[!] => { $crate::token_macros::delim::Bang };
972	[|] => { $crate::token_macros::delim::Or };
973	[%] => { $crate::token_macros::delim::Percent };
974	[+] => { $crate::token_macros::delim::Plus };
975	[?] => { $crate::token_macros::delim::Question };
976	[/] => { $crate::token_macros::delim::Slash };
977	[*] => { $crate::token_macros::delim::Star };
978	[~] => { $crate::token_macros::delim::Tilde };
979	[_] => { $crate::token_macros::delim::Underscore };
980	['`'] => { $crate::token_macros::delim::Backtick };
981
982	[>=] => { $crate::token_macros::double::GreaterThanEqual };
983	[<=] => { $crate::token_macros::double::LessThanEqual };
984	[*|] => { $crate::token_macros::double::StarPipe };
985	[::] => { $crate::token_macros::double::ColonColon };
986	[||] => { $crate::token_macros::double::PipePipe };
987	[==] => { $crate::token_macros::double::EqualEqual };
988	[~=] => { $crate::token_macros::double::TildeEqual };
989	[|=] => { $crate::token_macros::double::PipeEqual };
990	[^=] => { $crate::token_macros::double::CaretEqual };
991	["$="] => { $crate::token_macros::double::DollarEqual };
992	[*=] => { $crate::token_macros::double::StarEqual };
993	[!=] => { $crate::token_macros::double::BangEqual };
994
995	[Dimension::$ident: ident] => { $crate::token_macros::dimension::$ident };
996
997	[!important] => { $crate::token_macros::double::BangImportant };
998
999	[$ident:ident] => { $crate::token_macros::$ident }
1000}