topdown-rs 0.1.0

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

pub struct Split<'a, T> {
    parser: &'a (Parser<T>+'a),
    delim: &'a (Parser<String>+'a),
    allow_trailing_delim: bool
}

pub fn split<'a, T>(p: &'a (Parser<T> + 'a), d: &'a (Parser<String> + 'a), a: bool) -> Split<'a, T> {
    return Split{parser: p, delim: d, allow_trailing_delim: a};
}

impl<'a, T> Parser<Vec<T>> for Split<'a, T> {
    #[allow(unused_variables)]
    fn _parse(&self, cs: &mut CharSeq) -> ParserResult<Vec<T>> {
        let mut succ = true;
        let mut r = Vec::new();
        match self.parser.parse(cs) {
            Succ(c) => r.push(c),
            Fail(m, l) => return Succ(r),
            Error(m, l) => return Error(m, l)
        }
        while succ {
            match self.delim.parse(cs) {
                Succ(c) => (),
                Fail(m, l) => break,
                Error(m, l) => return Error(m, l)
            }
            match self.parser.parse(cs) {
                Succ(c) => r.push(c),
                Fail(m, l) => {
                    if self.allow_trailing_delim {
                        succ = false
                    } else {
                        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::split;
    use super::super::{CharSeq, re, ParserResult, Parser, Succ, Fail, Error};

    #[test]
    fn test_split1() {
        let mut cs = CharSeq::new("a,b,c", "");
        let s = re("[a-z]");
        let c = ",";
        let sp = split(&s, &c, false);
        match cs.accept(&sp) {
            Succ(r) => assert_eq!(r, vec!["a".to_string(), "b".to_string(), "c".to_string()]),
            Fail(m, l) => assert!(false),
            Error(m, l) => assert!(false),
        }
    }

    #[test]
    fn test_split2() {
        let mut cs = CharSeq::new("a,b,c,", "");
        let s = re("[a-z]");
        let c = ",";
        let sp = split(&s, &c, false);
        match cs.accept(&sp) {
            Fail(m, l) => (),
            Succ(r) => assert!(false),
            Error(m, l) => assert!(false),
        }
    }

    #[test]
    fn test_split3() {
        let mut cs = CharSeq::new("a,b,c,", "");
        let s = re("[a-z]");
        let c = ",";
        let sp = split(&s, &c, true);
        match cs.accept(&sp) {
            Succ(r) => assert_eq!(r, vec!["a".to_string(), "b".to_string(), "c".to_string()]),
            Fail(m, l) => assert!(false),
            Error(m, l) => assert!(false),
        }
    }

    #[test]
    fn test_split4() {
        let mut cs = CharSeq::new("", "");
        let s = re("[a-z]");
        let c = ",";
        let sp = split(&s, &c, false);
        match cs.accept(&sp) {
            Succ(r) => assert_eq!(0, r.len()),
            Fail(m, l) => assert!(false, m),
            Error(m, l) => assert!(false, m),
        }
    }

}