use super::{CharSeq, ParserResult, Parser, Succ, Fail, Error};
pub struct Split<'a, T:'a> {
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),
}
}
}