How to write fallible nom parsers

705 views Asked by At

If I want to write a nom parser that could fail internally, how do I propagate the error?

As an example, something to parse a NaiveDate might look like:

fn parse_date(i: &str) -> IResult<&str, NaiveDate> {
    map(take(10), |s| NaiveDate::parse_from_str(s, "%m/%d/%Y")?)(i)
}

The parse_from_str may fail and returns its own ParseResult type.

I actually rely on it's success/failure to determine if this parser works.

How can I convert an inner Result (in this case chrono::format::ParseResult) to something that works with nom?

1

There are 1 answers

0
Mika Vatanen On BEST ANSWER

You can use Nom's map_res method. MapRes emits only the ErrorKind::MapRes (no custom error), but if only ok/err result is needed that should suffice.

use chrono::NaiveDate;
use nom::bytes::streaming::take;
use nom::combinator::map_res;
use nom::error::{Error, ErrorKind};
use nom::IResult;

fn parse_date(i: &str) -> IResult<&str, NaiveDate> {
    map_res(take(10usize), |s| NaiveDate::parse_from_str(s, "%m/%d/%Y"))(i)
}

fn main() {
    assert_eq!(
        parse_date("01/31/2022: rest").unwrap(),
        (": rest", NaiveDate::from_ymd(2022, 01, 31))
    );

    assert_eq!(
        parse_date("yy/xx/2022").unwrap_err(),
        nom::Err::Error(Error::new("yy/xx/2022", ErrorKind::MapRes))
    );
}