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
67
68
69
70
71
72
73
74
75
76
77
78
use parsers::execution::*;
use parsers::parser::*;
use parsers::response::*;
use std::marker::PhantomData;

// -------------------------------------------------------------------------------------------------
// Parser type definition
// -------------------------------------------------------------------------------------------------

pub struct FMap<E, A, B>(E, Box<Fn(A) -> B>) where E: Parser<A>;

impl<E, A, B> Parser<B> for FMap<E, A, B> where E: Parser<A> {}

pub trait FMapOperation<E, A, B> where E: Parser<A> {
    fn fmap(self, f: Box<(Fn(A) -> B)>) -> FMap<E, A, B>;
}

impl<E, A, B> FMapOperation<E, A, B> for E where E: Parser<A> {
    fn fmap(self, f: Box<(Fn(A) -> B)>) -> FMap<E, A, B> {
        FMap(self, f)
    }
}

// -------------------------------------------------------------------------------------------------

pub struct Bind<E, A, R, B>(E, Box<Fn(A) -> R>, PhantomData<B>) where E: Parser<A>, R: Parser<B>;

impl<E, A, R, B> Parser<B> for Bind<E, A, R, B> where E: Parser<A>, R: Parser<B> {}

pub trait BindOperation<E, A, R, B> where E: Parser<A>, R: Parser<B> {
    fn bind(self, f: Box<(Fn(A) -> R)>) -> Bind<E, A, R, B>;
}

impl<E, A, R, B> BindOperation<E, A, R, B> for E where E: Parser<A>, R: Parser<B> {
    fn bind(self, f: Box<(Fn(A) -> R)>) -> Bind<E, A, R, B> {
        Bind(self, f, PhantomData)
    }
}

// -------------------------------------------------------------------------------------------------
// Parser execution
// -------------------------------------------------------------------------------------------------

impl<E, A, B> Executable<B> for FMap<E, A, B>
    where E: Executable<A> + Parser<A>
{
    fn execute(&self, s: &[u8], o: usize) -> Response<B> {
        let FMap(p, f) = self;

        match p.execute(s, o) {
            Response::Reject(o, b) => Response::Reject(o, b),
            Response::Success(v, o, b) => Response::Success(f(v), o, b)
        }
    }
}

// -------------------------------------------------------------------------------------------------

impl<E, A, R, B> Executable<B> for Bind<E, A, R, B>
    where E: Executable<A> + Parser<A>,
          R: Executable<B> + Parser<B>
{
    fn execute(&self, s: &[u8], o: usize) -> Response<B> {
        let Bind(p, f, _) = self;

        match p.execute(s, o) {
            Response::Success(a1, i1, b1) => {
                match f(a1).execute(s, i1) {
                    Response::Success(a2, i2, b2) => Response::Success(a2, i2, b1 || b2),
                    Response::Reject(i2, b2) => Response::Reject(i2, b1 || b2),
                }
            }
            Response::Reject(i1, b1) => Response::Reject(i1, b1)
        }
    }
}

// -------------------------------------------------------------------------------------------------