1use super::{CharSeq, ParserResult, Parser, Succ, Fail, Error};
2
3pub struct Chainr<'a, T:'a> {
4 term: &'a (Parser<T>+'a),
5 operator: &'a (Parser<Box<Fn(T, T) -> T + 'a>>+'a),
6 allow_trailing_operator: bool
7}
8
9pub fn chainr<'a, T>(p: &'a (Parser<T>+'a), o: &'a (Parser<Box<Fn(T, T) -> T + 'a>> + 'a), a: bool) -> Chainr<'a, T> {
10 return Chainr{term: p, operator: o, allow_trailing_operator: a};
11}
12
13impl<'a, T> Parser<T> for Chainr<'a, T> {
14 #[allow(unused_variables)]
15 fn _parse(&self, cs: &mut CharSeq) -> ParserResult<T> {
16 match cs.accept(self.term) {
17 Succ(l) => {
18 match cs.accept(self.operator) {
19 Succ(o) => match cs.accept(self) {
20 Succ(r) => return Succ(o(l, r)),
21 Fail(m, lo) => {
22 if self.allow_trailing_operator {
23 return Succ(l)
24 } else {
25 return Fail(m, lo)
26 }
27 },
28 Error(m, l) => return Error(m, l)
29 },
30 Fail(m, lo) => return Succ(l),
31 Error(m, lo) => return Succ(l),
32 }
33 },
34 Fail(m, l) => return Fail(m, l),
35 Error(m, l) => return Error(m, l)
36 }
37 }
38}
39
40#[cfg(test)]
41#[allow(unused_variables)]
42#[allow(unused_imports)]
43mod tests {
44 use super::chainr;
45 use super::super::{CharSeq, re, ParserResult, Parser, Succ, Fail, Error};
46
47 struct Op<'a>;
48
49 impl<'a> Parser<Box<Fn(isize, isize) -> isize + 'a>> for Op<'a> {
50 fn _parse(&self, cs: &mut CharSeq) -> ParserResult<Box<Fn(isize, isize) -> isize + 'a>> {
51 return cs.accept(&re("\\+|-"))
52 .map(|o| {
53 if o == "+" {
54 return (Box::new(|a:isize, b:isize| a+b)) as Box<Fn(isize, isize) -> isize + 'a>;
55 } else {
56 return (Box::new(|a:isize, b:isize| a-b)) as Box<Fn(isize, isize) -> isize + 'a>;
57 }
58 });
59 }
60 }
61
62 struct Expr;
63
64 impl Parser<isize> for Expr {
65 fn _parse(&self, cs: &mut CharSeq) -> ParserResult<isize> {
66 return cs.accept(&re("[1-9][0-9]*")).map(|x| x.as_slice().parse().unwrap());
67 }
68 }
69
70 #[test]
71 fn test_chainr1() {
72 let mut cs = CharSeq::new("1-5", "<mem>");
73 let term = Expr;
74 let op = Op;
75 let expr = chainr(&term, &op, false);
76 match cs.accept(&expr) {
77 Succ(c) => assert_eq!(c, -4),
78 Fail(a, b) => assert!(false, "failed"),
79 Error(a, b) => assert!(false, "error")
80 }
81 }
82
83
84 #[test]
85 fn test_chainr2() {
86 let mut cs = CharSeq::new("1-5-6", "<mem>");
87 let term = Expr;
88 let op = Op;
89 let expr = chainr(&term, &op, false);
90 match cs.accept(&expr) {
91 Succ(c) => assert_eq!(c, 2),
92 Fail(a, b) => assert!(false, "failed"),
93 Error(a, b) => assert!(false, "error")
94 }
95 }
96
97
98 #[test]
99 fn test_chainr3() {
100 let mut cs = CharSeq::new("30+5-6+12", "<mem>");
101 let term = Expr;
102 let op = Op;
103 let expr = chainr(&term, &op, false);
104 match cs.accept(&expr) {
105 Succ(c) => assert_eq!(c, 17),
106 Fail(a, b) => assert!(false, "failed"),
107 Error(a, b) => assert!(false, "error")
108 }
109 }
110
111
112 #[test]
113 fn test_chainr4() {
114 let mut cs = CharSeq::new("30+5-", "<mem>");
115 let term = Expr;
116 let op = Op;
117 let expr = chainr(&term, &op, true);
118 match cs.accept(&expr) {
119 Succ(c) => assert_eq!(c, 35),
120 Fail(a, b) => assert!(false, "failed"),
121 Error(a, b) => assert!(false, "error")
122 }
123 }
124}
125