我正在使用语法分析器组合子Nom来编写TOML语法分析器。我遇到的解析器函数使用chrono crate解析日期时间字符串。
fn offset_datetime<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, TomlValue, E> {
match DateTime::parse_from_rfc3339(input) {
ParseResult::Ok(dt) => IResult::Ok(("", TomlValue::OffsetDateTime(dt))),
ParseResult::Err(e) => {
Err(Err::Error(Error::from_error_kind(input, ErrorKind::Fail)))
}
}
}
游乐场
在上面的代码中,我使用chrono::DatetTime::parse_from_rfc3339
解析一个字符串切片,它返回一个chrono::format::ParseResult
。然后,我对其进行匹配,以便将其转换为适当的nom::IResult
。ParseResult::Ok
臂很好,但我无法为ParseResult::Err
编写正确的代码。以下是我在编译上面的代码片段时遇到的错误:
error[E0308]: mismatched types
--> src/parser.rs:193:28
|
188 | fn offset_datetime<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, TomlValue, E> {
| - this type parameter
...
193 | Err(Err::Error(Error::from_error_kind(input, ErrorKind::Fail)))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `E`, found struct `nom::error::Error`
|
= note: expected type parameter `E`
found struct `nom::error::Error<&str>`
Error::from_error_kind
中的Error
是Nom自己的结构之一,它确实实现了ParseError
特性,正如E
泛型所指定的那样。为什么编译器不能识别这一点?
无论何时给函数(offset_datetime
(一个泛型参数(E
(,都承诺该函数可以适用于E
可能是的所有类型,受其边界限制。您的函数签名承诺返回错误类型为E
的IResult
。但你不这么做;相反,您返回一个错误类型为nom::error::Error
的(使用Error::from_error_kind
(。
一个可能的解决方案是更改函数签名,以返回函数体实际执行的具体错误类型:
fn offset_datetime<'a>(input: &'a str) -> IResult<&'a str, TomlValue, Error<&'a str>> {
另一种方法是将函数体更改为使用签名声明的通用类型:
ParseResult::Err(e) => Err(Err::Error(E::from_error_kind(input, ErrorKind::Fail))),
请注意,它不是在具体类型nom::error::Error
上调用from_error_kind
,而是在类型变量E
上调用它(由于E: ParseError
绑定,它具有该方法(。
我不熟悉如何正确使用nom
,所以我无法告诉你哪一个更合适。