topdown-rs 0.3.3

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

pub struct Choice<'a, T: 'a> {
    parsers: &'a [&'a(Parser<T>+'a)]
}

pub fn choice<'a, T>(p: &'a [&'a (Parser<T> + 'a)]) -> Choice<'a, T> {
    return Choice{parsers: p};
}

impl<'a, T> Parser<T> for Choice<'a, T> {
    #[allow(unused_variables)]
    fn _parse(&self, cs: &mut CharSeq) -> ParserResult<T> {
        let pos = cs.pos;
        let mut vec = Vec::new();
        for p in self.parsers.iter() {
            match p.parse(cs) {
                Succ(r) => return Succ(r),
                Fail(m, l) => {
                    vec.push((m, l));
                    cs.pos = pos;
                },
                Error(m, l) => return Error(m, l)
            }
        }
        vec.sort_by(|a, b| a.1.cmp(&b.1));
        match vec.pop() {
            Some(p) => {
                cs.pos = pos;
                let (m, l) = p;
                return Fail(m, l);
            },
            None => ()
        }
        let r = cs.fail("");
        cs.pos = pos;
        return r;
    }
}

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

    #[test]
    fn test_choice1() {
        let mut cs = CharSeq::new("abcdefghi", "<mem>");
        let l: &[&Parser<String>] = &[&("abc"), &("def")];
        let choice = choice(l);
        match cs.accept(&choice) {
            Succ(c) => assert!(c.as_slice() == "abc"),
            Fail(a, b) => assert!(false, "failed"),
            Error(a, b) => assert!(false, "error")
        }
    }

    #[test]
    fn test_choice2() {
        let mut cs = CharSeq::new("abcdefghi", "<mem>");
        let l: &[&Parser<String>] = &[&("ghi"), &("def")];
        let choice = choice(l);
        match cs.accept(&choice) {
            Succ(c) => assert!(false, c),
            Fail(a, b) => (),
            Error(a, b) => assert!(false, "error")
        }
    }

    #[test]
    fn test_choice3() {
        let mut cs = CharSeq::new("abcdefghi", "<mem>");
        let a = S{fst: "abc", snd:"ghi"};
        let b = S{fst: "abc", snd:"jkl"};
        let l: &[&Parser<String>] = &[&a, &b];
        let choice = choice(l);
        match cs.accept(&choice) {
            Succ(c) => assert!(false, c),
            Fail(a, b) => {
                assert_eq!(0, cs.pos);
                assert_eq!(4, b.col);
            },
            Error(a, b) => assert!(false, "error")
        }
    }

    struct S<'a> {
        fst: &'a str,
        snd: &'a str
    }
    impl<'a> Parser<String> for S<'a> {
        fn _parse(&self, cs: &mut CharSeq) -> ParserResult<String> {
            cs.accept(&self.fst).and_then(|x| cs.accept(&self.snd))
        }
    }
}