separated_listX bug with separator that's allowed to be empty
brundonsmith opened this issue · 1 comments
brundonsmith commented
Nom v7.1.1
fn whitespace(i: &str) -> IResult<&str, &str, VerboseError<&str>> {
take_while(move |c| c == ' ')(i)
}
#[test]
fn demonstration() {
println!("{:?}", separated_list0(whitespace, tag("abc"))("abc"));
}
Err(Error(VerboseError { errors: [("", Nom(SeparatedList))] }))
whitespace
succeeds on its own against an empty input, but when used with separated_list0
and at the very end of the input, an infinite-loop is falsely detected and an error is returned. Instead, I think we should wait to check for no-progress until after the item's parser has also been run:
pub fn separated_list0<I, O, O2, E, F, G>(
mut sep: G,
mut f: F,
) -> impl FnMut(I) -> IResult<I, Vec<O>, E>
where
I: Clone + InputLength,
F: Parser<I, O, E>,
G: Parser<I, O2, E>,
E: ParseError<I>,
{
move |mut i: I| {
let mut res = Vec::new();
match f.parse(i.clone()) {
Err(Err::Error(_)) => return Ok((i, res)),
Err(e) => return Err(e),
Ok((i1, o)) => {
res.push(o);
i = i1;
}
}
loop {
let len = i.input_len();
match sep.parse(i.clone()) {
Err(Err::Error(_)) => return Ok((i, res)),
Err(e) => return Err(e),
Ok((i1, _)) => {
// infinite loop check: the parser must always consume
// if i1.input_len() == len {
// return Err(Err::Error(E::from_error_kind(i1, ErrorKind::SeparatedList)));
// }
match f.parse(i1.clone()) {
Err(Err::Error(_)) => return Ok((i, res)),
Err(e) => return Err(e),
Ok((i2, o)) => {
// infinite loop check: the parser must always consume
if i2.input_len() == len {
return Err(Err::Error(E::from_error_kind(i2, ErrorKind::SeparatedList)));
}
res.push(o);
i = i2;
}
}
}
}
}
}
}
SaltyKitkat commented
Any progress on this?