-
Notifications
You must be signed in to change notification settings - Fork 836
Description
Hello! I am trying to create a nom 5 style combinator in order to parse an arbitrary number of brackets from a string (e.g. "(((abc)))" => "abc"
). I have a working implementation like so...
pub fn brackets<I, O, E, F>(f: F) -> impl Fn(I) -> IResult<I, O, E>
where
I: Slice<RangeFrom<usize>> + InputIter + Clone + PartialEq,
<I as InputIter>::Item: AsChar,
E: ParseError<I>,
F: Fn(I) -> IResult<I, O, E>,
{
move |input: I| {
let (input, brackets) = many1_count(char('('))(input)?;
let (input, output) = f(input)?;
let (input, _) = count(char(')'), brackets)(input)?;
Ok((input, output))
}
}
...however when I attempt to use the terminated()
combinator within my generated closure like so...
pub fn brackets<I, O, E, F>(f: F) -> impl Fn(I) -> IResult<I, O, E>
where
I: Slice<RangeFrom<usize>> + InputIter + Clone + PartialEq,
<I as InputIter>::Item: AsChar,
E: ParseError<I>,
F: Fn(I) -> IResult<I, O, E>,
{
move |input: I| {
let (input, brackets) = many1_count(char('('))(input)?;
terminated(f, count(char(')'), brackets))(input)
}
}
...the compiler won't allow it because it cannot move out of 'f', a captured variable in an 'Fn' closure
. Essentially, for this to work the Fn
s would have to be replaced with FnOnce
s (which is not what nom uses), see this question.
The first method works and is acceptable but this has got me thinking about whether it is possible to use existing combinators within new ones like this? I assume this would have worked quite differently with the nom 4 macro-based approach but nonetheless seems like an important feature.
Sorry if I am being stupid, any pointers in the right direction would be much appreciated!