I'd like to write a nom parser combinator that takes a generic parser inner
, builds two different variants of it using combinators that already exist in nom, and then tries them in say an alt
combinator. Conceptually, I'd like to do
alt((some_existing_combinator(inner), some_other_existing_combinator(inner)))
Of course, this doesn't work, because inner
isn't in general of a type that is Copy
(or even Clone
). From my understanding, no parser built from nom combinators is Copy
or Clone
. Thus, I'm clearly barking up the wrong tree here. How does one typically approach this kind of problem?
You basically have two options: wrap the whole delimited
thing in its own parsing function, which is Copy
; or create a zero-arg closure (or function) that creates one-off delimited
parsers each time you need one. The toy example below compiles.
use nom::{
branch::alt,
bytes::complete::tag,
character::complete::{digit1, multispace0},
combinator::map_res,
multi::{many0, many1},
sequence::delimited,
IResult, Parser,
};
fn parser(s: &str) -> IResult<&str, i32> {
map_res((tag("num="), digit1), |(_, n): (_, &str)| n.parse::<i32>())
.parse(s)
}
// a fn, therefore Copy
fn my_delimited(s: &str) -> IResult<&str, i32> {
delimited(multispace0, parser, multispace0).parse(s)
}
fn main() {
// makes a fresh parser each time it's called
let make_inner = || delimited(multispace0, parser, multispace0);
let parser_1 = alt((many0(my_delimited), many1(my_delimited)));
let parser_2 = alt((many0(make_inner()), many1(make_inner())));
}