advent-of-code/2021/day16/rust/src/parsers.rs
2022-12-01 19:24:06 +01:00

42 lines
945 B
Rust

use std::ops::ControlFlow;
use nom::{
error::{ErrorKind, ParseError},
Err, InputLength, Parser,
};
pub fn fold_till<I, O, E, St, P, F, G>(
mut p: P,
mut init: F,
mut acc: G,
) -> impl FnMut(I) -> nom::IResult<I, St, E>
where
I: InputLength,
E: ParseError<I>,
P: Parser<I, O, E>,
F: FnMut() -> St,
G: FnMut(St, O) -> ControlFlow<St, St>,
{
move |i| {
let mut res = init();
let mut input = i;
loop {
let len = input.input_len();
let (i, o) = p.parse(input)?;
if i.input_len() == len {
return Err(Err::Error(E::from_error_kind(i, ErrorKind::Many0)));
}
match acc(res, o) {
ControlFlow::Continue(next) => {
res = next;
input = i;
}
ControlFlow::Break(res) => return Ok((i, res)),
}
}
}
}