topdown/
split.rs

1use super::{CharSeq, ParserResult, Parser, Succ, Fail, Error};
2
3pub struct Split<'a, T:'a> {
4    parser: &'a (Parser<T>+'a),
5    delim: &'a (Parser<String>+'a),
6    allow_trailing_delim: bool
7}
8
9pub fn split<'a, T>(p: &'a (Parser<T> + 'a), d: &'a (Parser<String> + 'a), a: bool) -> Split<'a, T> {
10    return Split{parser: p, delim: d, allow_trailing_delim: a};
11}
12
13impl<'a, T> Parser<Vec<T>> for Split<'a, T> {
14    #[allow(unused_variables)]
15    fn _parse(&self, cs: &mut CharSeq) -> ParserResult<Vec<T>> {
16        let mut succ = true;
17        let mut r = Vec::new();
18        match self.parser.parse(cs) {
19            Succ(c) => r.push(c),
20            Fail(m, l) => return Succ(r),
21            Error(m, l) => return Error(m, l)
22        }
23        while succ {
24            match self.delim.parse(cs) {
25                Succ(c) => (),
26                Fail(m, l) => break,
27                Error(m, l) => return Error(m, l)
28            }
29            match self.parser.parse(cs) {
30                Succ(c) => r.push(c),
31                Fail(m, l) => {
32                    if self.allow_trailing_delim {
33                        succ = false
34                    } else {
35                        return Fail(m, l)
36                    }
37                },
38                Error(m, l) => return Error(m, l)
39            }
40        }
41        return Succ(r);
42    }
43}
44
45
46#[cfg(test)]
47#[allow(unused_variables)]
48#[allow(unused_imports)]
49mod tests {
50    use super::split;
51    use super::super::{CharSeq, re, ParserResult, Parser, Succ, Fail, Error};
52
53    #[test]
54    fn test_split1() {
55        let mut cs = CharSeq::new("a,b,c", "");
56        let s = re("[a-z]");
57        let c = ",";
58        let sp = split(&s, &c, false);
59        match cs.accept(&sp) {
60            Succ(r) => assert_eq!(r, vec!["a".to_string(), "b".to_string(), "c".to_string()]),
61            Fail(m, l) => assert!(false),
62            Error(m, l) => assert!(false),
63        }
64    }
65
66    #[test]
67    fn test_split2() {
68        let mut cs = CharSeq::new("a,b,c,", "");
69        let s = re("[a-z]");
70        let c = ",";
71        let sp = split(&s, &c, false);
72        match cs.accept(&sp) {
73            Fail(m, l) => (),
74            Succ(r) => assert!(false),
75            Error(m, l) => assert!(false),
76        }
77    }
78
79    #[test]
80    fn test_split3() {
81        let mut cs = CharSeq::new("a,b,c,", "");
82        let s = re("[a-z]");
83        let c = ",";
84        let sp = split(&s, &c, true);
85        match cs.accept(&sp) {
86            Succ(r) => assert_eq!(r, vec!["a".to_string(), "b".to_string(), "c".to_string()]),
87            Fail(m, l) => assert!(false),
88            Error(m, l) => assert!(false),
89        }
90    }
91
92    #[test]
93    fn test_split4() {
94        let mut cs = CharSeq::new("", "");
95        let s = re("[a-z]");
96        let c = ",";
97        let sp = split(&s, &c, false);
98        match cs.accept(&sp) {
99            Succ(r) => assert_eq!(0, r.len()),
100            Fail(m, l) => assert!(false, m),
101            Error(m, l) => assert!(false, m),
102        }
103    }
104
105}