如何编写容易出错的 nom 解析器

How to write fallible nom parsers

如果我想编写一个可能在内部失败的 nom 解析器,我该如何传播错误?

例如,解析 NaiveDate 的内容可能如下所示:

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

parse_from_str may fail and returns its own ParseResult类型。

我实际上依靠它 success/failure 来确定此解析器是否有效。

如何将内部结果(在本例中为 chrono::format::ParseResult)转换为适用于 nom 的结果?

您可以使用 Nom 的 map_res 方法。 MapRes 仅发出 ErrorKind::MapRes(无自定义错误),但如果只需要 ok/err 结果就足够了。

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))
    );
}