Skip to main content

oni_comb_parser/primitive/
take_while_n_m.rs

1use core::marker::PhantomData;
2
3use crate::error::ParseError;
4use crate::fail::{Fail, PResult};
5use crate::input::Input;
6use crate::parser::Parser;
7
8pub struct TakeWhileNM<F, I: Input> {
9  min: usize,
10  max: usize,
11  f: F,
12  _marker: PhantomData<fn(&mut I)>,
13}
14
15pub fn take_while_n_m<I: Input, F: FnMut(I::Token) -> bool>(min: usize, max: usize, f: F) -> TakeWhileNM<F, I> {
16  TakeWhileNM {
17    min,
18    max,
19    f,
20    _marker: PhantomData,
21  }
22}
23
24impl<I: Input, F> Parser<I> for TakeWhileNM<F, I>
25where
26  F: FnMut(I::Token) -> bool,
27{
28  type Error = ParseError;
29  type Output = I::Slice;
30
31  #[inline]
32  fn parse_next(&mut self, input: &mut I) -> PResult<I::Slice, ParseError> {
33    let pos = input.offset();
34    let cp = input.checkpoint();
35    let mut count = 0;
36    while count < self.max {
37      match input.peek_token() {
38        Some(t) if (self.f)(t) => {
39          input.next_token();
40          count += 1;
41        }
42        _ => break,
43      }
44    }
45    if count < self.min {
46      input.reset(cp);
47      return Err(Fail::Backtrack(ParseError::expected_description(
48        pos,
49        "not enough matching tokens",
50      )));
51    }
52    Ok(input.slice_since(cp))
53  }
54}