Skip to content

Recursively defining nom 5 combinators #1044

@zakcutner

Description

@zakcutner

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 Fns would have to be replaced with FnOnces (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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions