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
use super::{CharSeq, ParserResult, Parser, Succ, Error, Fail}; pub struct Chainl<'a, T:'a> { term: &'a (Parser<T>+'a), operator: &'a (Parser<Box<Fn(T, T) -> T + 'a>>+'a), allow_trailing_operator: bool } pub fn chainl<'a, T>(p: &'a (Parser<T>+'a), o: &'a (Parser<Box<Fn(T, T) -> T + 'a>>+'a), a: bool) -> Chainl<'a, T> { return Chainl{term: p, operator: o, allow_trailing_operator: a}; } impl<'a, T> Chainl<'a, T> { #[allow(unused_variables)] fn tail(&self, cs: &mut CharSeq, l: T) -> ParserResult<T> { match cs.accept(self.operator) { Succ(o) => { match cs.accept(self.term) { Succ(r) => return self.tail(cs, 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) => Succ(l), Error(m, lo) => Succ(l) } } } impl<'a, T> Parser<T> for Chainl<'a, T> { fn _parse(&self, cs: &mut CharSeq) -> ParserResult<T> { match cs.accept(self.term) { Succ(l) => return self.tail(cs, 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::chainl; 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_chainl1() { let mut cs = CharSeq::new("1-5", "<mem>"); let term = Expr; let op = Op; let expr = chainl(&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_chainl2() { let mut cs = CharSeq::new("1-5-6", "<mem>"); let term = Expr; let op = Op; let expr = chainl(&term, &op, false); match cs.accept(&expr) { Succ(c) => assert_eq!(c, -10), Fail(a, b) => assert!(false, "failed"), Error(a, b) => assert!(false, "error") } } }