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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
use super::{CharSeq, ParserResult, Parser, Succ, Fail, Error}; pub struct Chainr<'a, T:'a> { term: &'a (Parser<T>+'a), operator: &'a (Parser<Box<Fn(T, T) -> T + 'a>>+'a), allow_trailing_operator: bool } pub fn chainr<'a, T>(p: &'a (Parser<T>+'a), o: &'a (Parser<Box<Fn(T, T) -> T + 'a>> + 'a), a: bool) -> Chainr<'a, T> { return Chainr{term: p, operator: o, allow_trailing_operator: a}; } impl<'a, T> Parser<T> for Chainr<'a, T> { #[allow(unused_variables)] fn _parse(&self, cs: &mut CharSeq) -> ParserResult<T> { match cs.accept(self.term) { Succ(l) => { match cs.accept(self.operator) { Succ(o) => match cs.accept(self) { Succ(r) => return Succ(o(l, r)), Fail(m, lo) => { if self.allow_trailing_operator { return Succ(l) } else { return Fail(m, lo) } }, Error(m, l) => return Error(m, l) }, Fail(m, lo) => return Succ(l), Error(m, lo) => return Succ(l), } }, Fail(m, l) => return Fail(m, l), Error(m, l) => return Error(m, l) } } } #[cfg(test)] #[allow(unused_variables)] #[allow(unused_imports)] mod tests { use super::chainr; use super::super::{CharSeq, re, ParserResult, Parser, Succ, Fail, Error}; struct Op<'a>; impl<'a> Parser<Box<Fn(isize, isize) -> isize + 'a>> for Op<'a> { fn _parse(&self, cs: &mut CharSeq) -> ParserResult<Box<Fn(isize, isize) -> isize + 'a>> { return cs.accept(&re("\\+|-")) .map(|o| { if o == "+" { return (Box::new(|a:isize, b:isize| a+b)) as Box<Fn(isize, isize) -> isize + 'a>; } else { return (Box::new(|a:isize, b:isize| a-b)) as Box<Fn(isize, isize) -> isize + 'a>; } }); } } struct Expr; impl Parser<isize> for Expr { fn _parse(&self, cs: &mut CharSeq) -> ParserResult<isize> { return cs.accept(&re("[1-9][0-9]*")).map(|x| x.as_slice().parse().unwrap()); } } #[test] fn test_chainr1() { let mut cs = CharSeq::new("1-5", "<mem>"); let term = Expr; let op = Op; let expr = chainr(&term, &op, false); match cs.accept(&expr) { Succ(c) => assert_eq!(c, -4), Fail(a, b) => assert!(false, "failed"), Error(a, b) => assert!(false, "error") } } #[test] fn test_chainr2() { let mut cs = CharSeq::new("1-5-6", "<mem>"); let term = Expr; let op = Op; let expr = chainr(&term, &op, false); match cs.accept(&expr) { Succ(c) => assert_eq!(c, 2), Fail(a, b) => assert!(false, "failed"), Error(a, b) => assert!(false, "error") } } #[test] fn test_chainr3() { let mut cs = CharSeq::new("30+5-6+12", "<mem>"); let term = Expr; let op = Op; let expr = chainr(&term, &op, false); match cs.accept(&expr) { Succ(c) => assert_eq!(c, 17), Fail(a, b) => assert!(false, "failed"), Error(a, b) => assert!(false, "error") } } #[test] fn test_chainr4() { let mut cs = CharSeq::new("30+5-", "<mem>"); let term = Expr; let op = Op; let expr = chainr(&term, &op, true); match cs.accept(&expr) { Succ(c) => assert_eq!(c, 35), Fail(a, b) => assert!(false, "failed"), Error(a, b) => assert!(false, "error") } } }