Nom解析器无法保留无效输入为剩余内容,测试失败
问题解决:parse_line空行解析失败的修复
问题根源
你的parse_line函数使用many1(many_till(space0, parse_token))强制要求至少解析一个token,但当输入为空行(仅\n)时,没有任何token可以匹配,导致many1解析失败,最终整个函数返回错误,不符合测试中Ok(("\n", vec![]))的预期。
解决方案
使用nom的opt组合器包裹原有的非空行解析逻辑,当非空行解析失败时(即遇到空行),直接返回空向量和原输入,满足测试要求。
修改后的完整代码:
use nom::{ branch::alt, bytes::complete::tag, character::complete::space0, multi::{many1, many_till}, sequence::pair, combinator::opt, IResult, }; fn parse_token(input: &str) -> IResult<&str, bool> { let (remaining, token) = alt((tag("0"), tag("1")))(input)?; Ok((remaining, token == "1")) } #[allow(dead_code)] fn parse_line(input: &str) -> IResult<&str, Vec<bool>> { // 定义非空行的解析规则:至少一个token,后跟换行 let parse_non_empty_line = pair( many1(many_till(space0, parse_token)), many_till(space0, tag("\n")), ); match opt(parse_non_empty_line)(input) { Ok((remaining, Some((tokens_raw, _)))) => { // 转换解析出的token集合 let tokens = tokens_raw.into_iter().map(|(_, token)| token).collect(); Ok((remaining, tokens)) } Ok((remaining, None)) => { // 空行或无法解析为非空行时,返回空向量和原输入 Ok((remaining, vec![])) } Err(e) => Err(e), } } #[cfg(test)] mod tests { use super::*; #[test] fn parse_token_test() { assert_eq!(parse_token("0"), Ok(("", false))); assert_eq!(parse_token("1"), Ok(("", true))); } #[test] fn parse_line_test() { assert_eq!(parse_line("1\n"), Ok(("", vec![true]))); assert_eq!(parse_line("0\n"), Ok(("", vec![false]))); assert_eq!( parse_line("1 1 1 1\n"), Ok(("", vec![true, true, true, true])) ); } #[test] fn parse_line_repeat() { let rtn = parse_line("1\n 1\n"); assert_eq!(rtn, Ok((" 1\n", vec![true]))); let rtn = parse_line(rtn.unwrap().0); assert_eq!(rtn, Ok(("", vec![true]))); let rtn = parse_line("1\n 1\n\n"); assert_eq!(rtn, Ok((" 1\n\n", vec![true]))); let rtn = parse_line(rtn.unwrap().0); assert_eq!(rtn, Ok(("\n", vec![true]))); let rtn = parse_line(rtn.unwrap().0); assert_eq!(rtn, Ok(("\n", vec![]))); } }
代码说明
opt组合器的作用:尝试执行传入的解析器,成功则返回Some(解析结果),失败则返回None且不消耗输入,完美适配空行的处理场景。- 分支处理:
- 非空行解析成功时,按原有逻辑转换token并返回结果;
- 解析失败时(对应空行),直接返回空向量和原输入,完全匹配测试中的预期。
- 兼容性:原有非空行的解析逻辑未被修改,保证
parse_line_test和parse_token_test依然可以通过。
修改后运行cargo test,所有测试都会成功通过。
内容的提问来源于stack exchange,提问作者Delfin
相关产品推荐
相关产品推荐

