nom icon indicating copy to clipboard operation
nom copied to clipboard

Add combinator "erasing" output type

Open mwobat opened this issue 2 years ago • 5 comments

Recently I wanted to write something like this:

fn parser(input: &str) -> IResult<&str, Vec<&str>> {
    map(
        many_till(
            terminated(not_line_ending, line_ending),
            peek(alt((eof, header, modifier))),
        ),
        |(lines, _)| lines,
    )(input)
}

where eof, header and modifier are parsers having different output types.

Unfortunately that doesn't work, because alt only takes parsers having the same output type.

I propose a parser, which returns the unit type if the child parser was succesful. Otherwise just the error.

Let's call it ok here, then I could rewrite the line in question like this:

peek(alt((ok(eof), ok(header), ok(modifier))))

I found a similar combinator in the docs: recognize although it does have an overhead because it returns what the child parser consumed.

Also, please let me know if I missed something 😉

mwobat avatar Jul 18 '22 09:07 mwobat

I could've sworn there was a void combinator for this, but apparently not. It can be emulated with value((), p), but I agree it'd be a good addition to the library.

Xiretza avatar Jul 18 '22 09:07 Xiretza

It can be emulated with value((), p)

Oh, I didn't even think of that.

mwobat avatar Jul 18 '22 09:07 mwobat

You could use the toilet closure eof.map(|_| ())

Stargateur avatar Jul 18 '22 10:07 Stargateur

You could use the toilet closure eof.map(|_| ())

Yes, but it will be a little longer:

peek(alt((
    eof.map(|_| ()),
    page_header_num.map(|_| ()),
    choice.map(|_| ()),
)))

vs

peek(alt((void(eof), void(page_header_num), void(choice))))

I think the second looks more concise

mwobat avatar Jul 18 '22 10:07 mwobat

A more Rust centric name for this would be unit since () is the unit type.

epage avatar Dec 18 '22 01:12 epage