topdown-rs 0.3.3

A top-down parsing library
Documentation
use super::{CharSeq, ParserResult, Parser, Succ, Fail, Error};


pub struct ManyUntil<'a, S:'a, T:'a> {
    parser: &'a (Parser<S>+'a),
    stop: &'a (Parser<T>+'a)
}

pub fn many_until<'a, S, T>(p: &'a (Parser<S> + 'a), s: &'a (Parser<T> + 'a)) -> ManyUntil<'a, S, T> {
    return ManyUntil{parser: p, stop: s};
}

impl<'a, S, T> Parser<Vec<S>> for ManyUntil<'a, S, T> {
    #[allow(unused_variables)]
    fn _parse(&self, cs: &mut CharSeq) -> ParserResult<Vec<S>> {
        let mut r = Vec::new();
        let mut succ = true;
        while succ {
            match self.parser.parse(cs) {
                Succ(c) => r.push(c),
                Fail(m, l) => {
                    match self.stop.lookahead(cs) {
                        true => succ = false,
                        false => return Fail(m, l)
                    }
                },
                Error(m, l) => return Error(m, l)
            }
        }
        return Succ(r);
    }
}


#[cfg(test)]
#[allow(unused_variables)]
#[allow(unused_imports)]
mod tests {
    use super::many_until;
    use super::super::{CharSeq, ParserResult, EOF, Parser, Succ, Fail, Error};

    #[test]
    fn test_many_until1() {
        let mut cs = CharSeq::new("aaa", "<mem>");
        assert!(cs.pos == 0);
        let s = "a";
        let eof = EOF;
        let m = many_until(&s, &eof);
        match cs.accept(&m) {
            Succ(v) => assert_eq!(v, vec!["a", "a", "a"]),
            _ => assert!(false, "bug")
        }
        assert!(cs.pos == 3);
    }

    #[test]
    fn test_many_until2() {
        let mut cs = CharSeq::new("aaabbbccc", "<mem>");
        assert!(cs.pos == 0);
        let s = "a";
        let eof = EOF;
        let m = many_until(&s, &eof);
        match cs.accept(&m) {
            Fail(m, l) => assert_eq!(cs.pos, 3),
            _ => assert!(false, "bug")
        }
        assert!(cs.pos == 3);
        assert!(cs.view() == "bbbccc");
    }

    #[test]
    fn test_many_until3() {
        let mut cs = CharSeq::new("aaabbbccc", "<mem>");
        assert!(cs.pos == 0);
        let s = "x";
        let eof = EOF;
        let m = many_until(&s, &eof);
        match cs.accept(&m) {
            Fail(m, l) => {
                assert_eq!(l.col,1);
                assert_eq!(l.row,1);
            },
            Succ(a) => assert!(false, "bug"),
            Error(m, l) => assert!(false, "bug: {} {}", m, l)
        }
        assert!(cs.pos == 0);
        assert!(cs.view() == "aaabbbccc");
    }
}