parser_fuck 0.6.0

A simple parser combinator library
Documentation
use crate::*;
use std::marker::PhantomData;

/// Multiple parsing
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Many<A, I = ()> {
    a: A,
    min: usize,
    max: Option<usize>,
    _i: PhantomData<I>,
}
impl<I: TimeTravel, A> Many<A, I>
where
    A: Parser<I>,
{
    #[inline]
    pub fn new(a: A, min: usize, max: Option<usize>) -> Self {
        if let Some(max) = max {
            if max < min {
                panic!("max must be >= min")
            }
        }
        Self {
            a,
            min,
            max,
            _i: PhantomData,
        }
    }
}
impl<I: TimeTravel, A> Parser<I> for Many<A, I>
where
    A: Parser<I>,
{
    type Output = Vec<A::Output>;

    fn parse(&self, mut input: I) -> Option<Self::Output> {
        let mut vec: Vec<A::Output> = vec![];
        if let Some(max) = self.max {
            loop {
                let from = input.save();
                let a = self.a.parse(input.ref_clone());
                if let Some(a) = a {
                    vec.push(a);
                    if vec.len() > max {
                        return None;
                    }
                } else {
                    input.back(from);
                    if vec.len() >= self.min {
                        return Some(vec);
                    } else {
                        return None;
                    }
                }
                input.re_ready()
            }
        } else {
            loop {
                let from = input.save();
                let a = self.a.parse(input.ref_clone());
                if let Some(a) = a {
                    vec.push(a);
                } else {
                    input.back(from);
                    if vec.len() >= self.min {
                        return Some(vec);
                    } else {
                        return None;
                    }
                }
                input.re_ready()
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::*;

    #[test]
    fn test() {
        let code = "asdasdasd";
        let span = code.span();
        let a = substr("asd");
        let x = a.many();

        let r = x.parse(span);
        println!("{:?}", r);
        assert_eq!(r, Some(vec![0..3, 3..6, 6..9]));
    }

    #[test]
    fn test_multi1() {
        let code = "asd123";
        let span = code.span();
        let a = substr("asd");
        let b = substr("123");
        let x = a.many();
        let y = b.many();

        let r = x.parse(span.ref_clone());
        println!("{:?}", r);
        assert_eq!(r, Some(vec![0..3]));
        let r = y.parse(span);
        println!("{:?}", r);
        assert_eq!(r, Some(vec![3..6]));
    }

    #[test]
    fn test_multi() {
        let code = "asdasd123123";
        let span = code.span();
        let a = substr("asd");
        let b = substr("123");
        let x = a.many();
        let y = b.many();

        let r = x.parse(span.ref_clone());
        println!("{:?}", r);
        assert_eq!(r, Some(vec![0..3, 3..6]));
        let r = y.parse(span);
        println!("{:?}", r);
        assert_eq!(r, Some(vec![6..9, 9..12]));
    }

    #[test]
    fn test_partial() {
        let code = "asdasdqwe";
        let span = code.span();
        let a = substr("asd");
        let x = a.many();

        let r = x.parse(span);
        println!("{:?}", r);
        assert_eq!(r, Some(vec![0..3, 3..6]));
    }

    #[test]
    fn test_0() {
        let code = "qwe123";
        let span = code.span();
        let a = substr("asd");
        let x = a.many();

        let r = x.parse(span);
        println!("{:?}", r);
        assert_eq!(r, Some(vec![]));
    }

    #[test]
    fn test_1() {
        let code = "qwe123";
        let span = code.span();
        let a = substr("asd");
        let x = a.many1();

        let r = x.parse(span);
        println!("{:?}", r);
        assert_eq!(r, None);
    }
    #[test]
    fn test_1_has() {
        let code = "asdqwe123";
        let span = code.span();
        let a = substr("asd");
        let x = a.many1();

        let r = x.parse(span);
        println!("{:?}", r);
        assert_eq!(r, Some(vec![0..3]));
    }

    #[test]
    fn test_1_more() {
        let code = "asdasd123";
        let span = code.span();
        let a = substr("asd");
        let x = a.many1();

        let r = x.parse(span);
        println!("{:?}", r);
        assert_eq!(r, Some(vec![0..3, 3..6]));
    }

    #[test]
    fn test_1_all() {
        let code = "asdasdasd";
        let span = code.span();
        let a = substr("asd");
        let x = a.many1();

        let r = x.parse(span);
        println!("{:?}", r);
        assert_eq!(r, Some(vec![0..3, 3..6, 6..9]));
    }

    #[test]
    fn test_max() {
        let code = "asdasdasd";
        let span = code.span();
        let a = substr("asd");
        let x = a.many_max(1);

        let r = x.parse(span);
        println!("{:?}", r);
        assert_eq!(r, None);
    }

    #[test]
    fn test_max_some() {
        let code = "asd123asd";
        let span = code.span();
        let a = substr("asd");
        let x = a.many_max(1);

        let r = x.parse(span);
        println!("{:?}", r);
        assert_eq!(r, Some(vec![0..3]));
    }

    #[test]
    fn test_max_empty() {
        let code = "qwe123asd";
        let span = code.span();
        let a = substr("asd");
        let x = a.many_max(1);

        let r = x.parse(span);
        println!("{:?}", r);
        assert_eq!(r, Some(vec![]));
    }

    #[test]
    fn test_range_1() {
        let code = "asd123asd";
        let span = code.span();
        let a = substr("asd");
        let x = a.many_min_max(1, 1);

        let r = x.parse(span);
        println!("{:?}", r);
        assert_eq!(r, Some(vec![0..3]));
    }

    #[test]
    fn test_range_2() {
        let code = "asdasdasd";
        let span = code.span();
        let a = substr("asd");
        let x = a.many_min_max(1, 1);

        let r = x.parse(span);
        println!("{:?}", r);
        assert_eq!(r, None);
    }

    #[test]
    fn test_range_3() {
        let code = "123qwe";
        let span = code.span();
        let a = substr("asd");
        let x = a.many_min_max(1, 1);

        let r = x.parse(span);
        println!("{:?}", r);
        assert_eq!(r, None);
    }

    #[test]
    fn test_range_4() {
        let code = "asdasd123";
        let span = code.span();
        let a = substr("asd");
        let x = a.many_min_max(1, 2);

        let r = x.parse(span);
        println!("{:?}", r);
        assert_eq!(r, Some(vec![0..3, 3..6]));
    }

    #[test]
    fn test_range_5() {
        let code = "asdasdasd123";
        let span = code.span();
        let a = substr("asd");
        let x = a.some(3);

        let r = x.parse(span);
        println!("{:?}", r);
        assert_eq!(r, Some(vec![0..3, 3..6, 6..9]));
    }

    #[test]
    #[should_panic]
    fn test_max_lt_min() {
        let code = "asdasdasd123";
        let span = code.span();
        let a = substr("asd");
        let x = a.many_min_max(3, 1);
        let r = x.parse(span);
        println!("{:?}", r);
    }
}