css_parse/traits/
parse.rs1use crate::{Build, Parser, Peek, Result, diagnostics};
2use bumpalo::collections::Vec;
3
4pub 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);