I'm looking to create a function like alt that instead of consuming parsers from a tuple, it consumes parsers from an iterator.
The trouble I'm having is with the bound FnMut on the parameterized parsers.
Parser is implemented for FnMut, but not Fn.
FnMut is not cloneable, which means I have to put it in a Box of some sort and then mutably borrow from it.
Here is the signature I would start off with:
use nom::{Parser,error::ParseError};
fn alt<I, O, E, P>(parsers: impl IntoIterator<Item = P>) -> impl Parser<I, O, E>
where
P: Parser<I, O, E>
{
move |input| {
// implementation
}
}
This implementation works, but only when everything is mutable:
use nom::{error::ParseError, InputIter, InputTake, Parser};
pub fn alt_many<I, O, E, P>(mut parsers: Vec<&mut P>) -> impl Parser<I, O, E> + '_
where
P: Parser<I, O, E>,
I: InputIter + InputTake + Copy,
E: ParseError<I>,
{
move |mut input| {
use nom::bytes::complete::take;
use nom::combinator::fail;
let mut value: Option<O> = None;
for parser in &mut parsers {
if let Ok((input_, o)) = parser.parse(input) {
input = input_;
value = Some(o);
break;
} else {
(input, _) = take::<u8, I, E>(1)(input)?;
};
}
value
.map(|output| Ok((input, output)))
.unwrap_or_else(|| fail::<I, O, E>(input))
}
}
Are there any other possible solutions available?
Assuming you want the actual behavior of
altinstead of your different one with thetakeyou can writealt_manylike this: