Open EndilWayfare opened 4 years ago
Ok, decided to go a bit lower-level. Is this a dumb way to write a match1
combinator?
#[derive(Debug)]
#[derive(Error)]
#[error("Parser matched a zero-length sequence")]
pub struct EmptyMatchError;
pub fn match1<I, O, F, E>(mut parser: F) -> impl Parser<I, O, E>
where
I: Clone + PartialEq,
F: Parser<I, O, E>,
E: FromExternalError<I, EmptyMatchError>
{
move |input: I| {
let i = input.clone();
let (input, o) = parser.parse(input)?;
if i != input {
Ok((input, o))
} else {
Err(Err::Error(E::from_external_error(i, ErrorKind::MapRes, EmptyMatchError)))
}
}
}
I've run into a problem with using
nom::character::complete::not_line_ending
to match the entire contents of a line up to the line-ending. It works well in isolation, but usingnom::multi::many{1|0}
to parse multiple lines fails unexpectedly. As far as I can tell, this is becausenot_line_ending
can successfully match on empty input, promptingmany{1|0}
to error out rather than infinite looping. I was initially under the impression thatnot_line_ending
would behave likenot_line_ending1
(requiring at least one matching character) since there aren't {1|0} variants, but it actually behaves likenot_line_ending0
.I thought that wrapping the parser in a
terminated
that checked for line-ending or EOFI'm considering a
take_till1
that matches on a hand-rolledis_line_ending
predicate (sincenom::character::is_newline
doesn't work on file input from Windows), but the custom logic insidenot_line_ending
gave me pause. I assume there is some kind of performance/subtle-correctness reason that it's not implemented withtake_till
(or some suitable combinator) that I haven't logic'd through completely enough.Prerequisites
Here are a few things you should provide to help me understand the issue:
default
Test case
Please provide a short, complete (with crate import, etc) test case for the issue, showing clearly the expected and obtained results.
Example test case: