use crate::{Cursor, Parser, Peek, Result};
use bumpalo::collections::Vec;
pub trait Parse<'a>: Sized {
fn parse<I>(p: &mut Parser<'a, I>) -> Result<Self>
where
I: Iterator<Item = Cursor> + Clone;
fn try_parse<I>(p: &mut Parser<'a, I>) -> Result<Self>
where
I: Iterator<Item = Cursor> + Clone,
{
let checkpoint = p.checkpoint();
Self::parse(p).inspect_err(|_| p.rewind(checkpoint))
}
}
impl<'a, T> Parse<'a> for Option<T>
where
T: Peek<'a> + Parse<'a>,
{
fn parse<Iter>(p: &mut Parser<'a, Iter>) -> Result<Self>
where
Iter: Iterator<Item = Cursor> + Clone,
{
p.parse_if_peek::<T>()
}
}
impl<'a, T> Parse<'a> for Vec<'a, T>
where
T: Peek<'a> + Parse<'a>,
{
fn parse<Iter>(p: &mut Parser<'a, Iter>) -> Result<Self>
where
Iter: Iterator<Item = Cursor> + Clone,
{
let mut vec = Vec::new_in(p.bump());
while let Some(item) = p.parse_if_peek::<T>()? {
vec.push(item);
}
Ok(vec)
}
}
macro_rules! impl_tuple {
($($T:ident),*) => {
impl<'a, $($T),*> Parse<'a> for ($($T),*)
where
$($T: Parse<'a>),*
{
#[allow(non_snake_case)]
#[allow(unused)]
fn parse<Iter>(p: &mut Parser<'a, Iter>) -> Result<Self>
where
Iter: Iterator<Item = Cursor> + Clone,
{
$(let $T = p.parse::<$T>()?;)*
Ok(($($T),*))
}
}
};
}
impl_tuple!(A, B);
impl_tuple!(A, B, C);
impl_tuple!(A, B, C, D);
impl_tuple!(A, B, C, D, E);
impl_tuple!(A, B, C, D, E, F);
impl_tuple!(A, B, C, D, E, F, G);
impl_tuple!(A, B, C, D, E, F, G, H);
impl_tuple!(A, B, C, D, E, F, G, H, I);
impl_tuple!(A, B, C, D, E, F, G, H, I, J);
impl_tuple!(A, B, C, D, E, F, G, H, I, J, K);
impl_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);