css_parse/traits/
parse.rs

1use crate::{Build, Parser, Peek, Result, diagnostics};
2use bumpalo::collections::Vec;
3
4/// This trait allows AST nodes to construct themselves from a mutable [Parser] instance.
5///
6/// Nodes that implement this trait are entitled to consume any number of [Cursors][css_lexer::Cursor] from [Parser] in
7/// order to construct themselves. They may also consume some amount of tokens and still return an [Err] - there is no
8/// need to try and reset the [Parser] state on failure ([Parser::try_parse()] exists for this reason).
9///
10/// When wanting to parse child nodes, implementations should _not_ call [Parse::parse()] directly. Instead - call
11/// [`Parser::parse<T>()`]. Other convenience methods such as [`Parser::parse_if_peek<T>()`] and [`Parser::try_parse<T>()`]
12/// exist.
13///
14/// Any node implementing [Parse::parse()] gets [Parse::try_parse()] for free. It's unlikely that nodes can come up with
15/// a more efficient algorithm than the provided one, so it is not worth re-implementing [Parse::try_parse()].
16///
17/// If a Node can construct itself from a single [Cursor][css_lexer::Cursor] it should instead implement
18/// [Peek][crate::Peek] and [Build][crate::Build], which will provide [Parse] for free.
19pub trait Parse<'a>: Sized {
20	fn parse(p: &mut Parser<'a>) -> Result<Self>;
21
22	fn try_parse(p: &mut Parser<'a>) -> Result<Self> {
23		let checkpoint = p.checkpoint();
24		Self::parse(p).inspect_err(|_| p.rewind(checkpoint))
25	}
26}
27
28impl<'a, T> Parse<'a> for T
29where
30	T: Peek<'a> + Build<'a>,
31{
32	fn parse(p: &mut Parser<'a>) -> Result<Self> {
33		if p.peek::<Self>() {
34			let c = p.next();
35			Ok(Self::build(p, c))
36		} else {
37			let c = p.next();
38			Err(diagnostics::Unexpected(c.into(), c.into()))?
39		}
40	}
41}
42
43impl<'a, T> Parse<'a> for Option<T>
44where
45	T: Peek<'a> + Parse<'a>,
46{
47	fn parse(p: &mut Parser<'a>) -> Result<Self> {
48		p.parse_if_peek::<T>()
49	}
50}
51
52impl<'a, T> Parse<'a> for Vec<'a, T>
53where
54	T: Peek<'a> + Parse<'a>,
55{
56	fn parse(p: &mut Parser<'a>) -> Result<Self> {
57		let mut vec = Vec::new_in(p.bump());
58		while let Some(item) = p.parse_if_peek::<T>()? {
59			vec.push(item);
60		}
61		Ok(vec)
62	}
63}
64
65macro_rules! impl_tuple {
66    ($($T:ident),*) => {
67        impl<'a, $($T),*> Parse<'a> for ($($T),*)
68        where
69            $($T: Parse<'a>),*
70        {
71            #[allow(non_snake_case)]
72            #[allow(unused)]
73            fn parse(p: &mut Parser<'a>) -> Result<Self> {
74                $(let $T = p.parse::<$T>()?;)*
75                Ok(($($T),*))
76            }
77        }
78    };
79}
80
81impl_tuple!(T, U);
82impl_tuple!(T, U, V);
83impl_tuple!(T, U, V, W);