oni_comb_parser/combinator/
many_fold.rs1use crate::fail::{Fail, PResult};
2use crate::input::Input;
3use crate::parser::Parser;
4
5pub struct ManyFold<P, B, F> {
6 pub(crate) parser: P,
7 pub(crate) init: B,
8 pub(crate) f: F,
9}
10
11impl<I, P, B, F, Acc> Parser<I> for ManyFold<P, B, F>
12where
13 I: Input,
14 P: Parser<I>,
15 B: FnMut() -> Acc,
16 F: FnMut(Acc, P::Output) -> Acc,
17{
18 type Error = P::Error;
19 type Output = Acc;
20
21 #[inline(always)]
22 fn parse_next(&mut self, input: &mut I) -> PResult<Self::Output, Self::Error> {
23 let mut acc = (self.init)();
24 loop {
25 let cp = input.checkpoint();
26 match self.parser.parse_next(input) {
27 Ok(v) => {
28 if input.checkpoint() == cp {
29 return Err(Fail::ZeroProgress);
30 }
31 acc = (self.f)(acc, v);
32 }
33 Err(Fail::Backtrack(_)) => {
34 input.reset(cp);
35 return Ok(acc);
36 }
37 Err(Fail::Cut(e)) => return Err(Fail::Cut(e)),
38 Err(Fail::Incomplete) => return Err(Fail::Incomplete),
39 Err(Fail::ZeroProgress) => return Err(Fail::ZeroProgress),
40 }
41 }
42 }
43}