nom
nom copied to clipboard
Implements combinator `flat_some`.
Hello nom
team.
This is my very first contribution to nom
, so I maybe did things wrong here. Also, please note that I'm quite bad at naming things, so flat_some
might not be the most meaningful name!
I'm writing a parser using nom
(which is a great library btw), and I came across the following pattern which I found verbose to express with nom
, especially because I'm using it a lot:
use nom::combinator;
use nom::IResult;
use nom::bytes::complete as bytes;
fn parse_if_some<'a>(s: Option<&'a str>) -> impl Fn(&'a str) -> IResult<&'a str, Option<&'a str>> {
move |i: &str| if s.is_some() {
combinator::map(
bytes::tag("next"),
Some,
)(i)
} else {
combinator::success(None)(i)
}
}
fn parser(s: &str) -> IResult<&str, Option<&str>> {
combinator::flat_map(
combinator::opt(bytes::tag("first")),
parse_if_some,
)(s)
}
fn main() {
assert_eq!(parser("firstnext"), Ok(("", Some("next"))));
assert!(parser("firstinvalid").is_err());
}
The idea is that if a first parser succeed, then we discard its result, and apply a second one on the following input.
It is close to sequence::preceded
, but if the first parser failed, then we return None
, otherwise it returns either an Error
or an Option<O>
.
I'm using it over combinator::opt
because I want to make sure that if I recognize a first pattern, then the following input must be correct. But if I don't recognize that first pattern, then it's fine and we can move on.
Maybe there are other "simpler" ways to do it without implementing a new combinator, and in this case I'm fine with discarding this PR. :)