1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
use super::{CharSeq, ParserResult, Parser, ParserHook};
use std::marker::PhantomData;

pub struct FunctionWrapper<F, T> {
    func: F,
    phantom: PhantomData<T>
}

impl<F, T> Parser<T> for FunctionWrapper<F, T> where F: Fn(&mut CharSeq) -> ParserResult<T> {
    fn _parse(&self, cs: &mut CharSeq) -> ParserResult<T> {
        (self.func)(cs)
    }
}

impl<F, T> ParserHook for FunctionWrapper<F, T> where F: Fn(&mut CharSeq) -> ParserResult<T> {
    fn hook(&self, cs: &mut CharSeq)  {
        (self.func)(cs);
    }
}

pub fn wrap<F, T>(f: F) -> FunctionWrapper<F, T> where F: Fn(&mut CharSeq) -> ParserResult<T> {
    FunctionWrapper{func: f, phantom:PhantomData}
}

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

    fn some_parser(cs: &mut CharSeq) -> ParserResult<Vec<String>> {
        let x = "abc";
        let y = "def";
        let z = "ghi";
        cs.accept(&x).and_then(|a|
            cs.accept(&y).and_then(|b|
            cs.accept(&z).map(|c| {
                vec!(a.to_string(), b.to_string(), c.to_string())
            }
        )))
    }

    #[test]
    fn test_wrap1() {
        let mut cs = CharSeq::new("abcdefghi", "");
        let w = wrap(some_parser);
        match cs.accept(&w) {
            Succ(x) => assert_eq!(x, vec!("abc".to_string(), "def".to_string(), "ghi".to_string())),
            Fail(m, l) => assert!(false, "failed"),
            Error(m, l) => assert!(false, "error")
        }
    }

    #[test]
    fn test_wrap2() {
        let w = wrap(some_parser);
        let mut cs = CharSeq::new("abcdefghixxxabcdefghi", "");
        cs.add_hook(&w);
        match cs.accept(&"xxx") {
            Succ(x) => assert_eq!(x.as_slice(), "xxx"),
            Fail(m, l) => assert!(false, "failed"),
            Error(m, l) => assert!(false, "error")
        }
    }
}