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