如何编写容易出错的 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))
);
}
如果我想编写一个可能在内部失败的 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))
);
}