使用VerboseError和convert_error编写nom解析器测试遇类型匹配问题
解决nom解析器测试宏的类型不匹配问题
你的问题核心是:convert_error函数期望接收VerboseError<&str>类型,但你传入的是被nom::Err枚举包裹的完整错误实例。nom的Err包含三种不同的错误变体,需要先从对应变体中提取出内部的VerboseError,或者确认convert_error的正确调用方式。
修正后的宏代码
根据nom解析器的标准返回格式(Result<(&剩余输入, 解析结果), Err<...>>),结合错误变体的处理,调整宏如下:
#[macro_export] macro_rules! assert_parses_to { ($parser:ident, $input:expr, $expectation:expr) => { match $parser($input) { // nom解析成功时,返回(剩余输入, 解析结果),我们只关心结果是否匹配 Ok((_, candidate_val)) => { if candidate_val != $expectation { panic!( "解析结果不匹配\n\ 实际值: {:?}\n\ 期望值: {:?}", candidate_val, $expectation ); } } // Error和Failure变体包含VerboseError实例,提取后传入convert_error Err(nom::Err::Error(err) | nom::Err::Failure(err)) => { panic!( "解析失败\n\ {}", convert_error($input, err) ); } // Incomplete变体表示需要更多输入,单独给出提示 Err(nom::Err::Incomplete(_)) => { panic!("解析器需要更多输入才能完成解析"); } } }; }
关键说明
- 修正解析结果处理:nom的解析器返回值是
Ok((剩余输入, 解析结果)),原宏直接匹配Ok(candidate_val)会把剩余输入错误地当成解析结果,导致后续匹配逻辑出错。 - 拆分Err变体:
Error:可恢复的解析错误,包含预期的VerboseErrorFailure:不可恢复的解析错误,同样包含VerboseErrorIncomplete:表示解析器需要更多输入才能完成,这类情况单独处理更友好
- 简化引用逻辑:直接使用解析器的返回值,避免不必要的引用和解引用,减少类型匹配问题。
额外注意
如果你使用的是nom官方的nom::error::convert_error函数,它的签名是fn convert_error(input: &str, err: Err<VerboseError<&str>>) -> String,此时你不需要提取内部的VerboseError,直接将完整的Err实例传入即可,对应代码块改为:
Err(err) => { panic!( "解析失败\n\ {}", nom::error::convert_error($input, err) ); }
注意不同nom版本的API可能有细微差异,请对照你使用的版本文档确认。
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

