Open
Description
As part of a parser I am writing, I would like to define something that expects at least one multispace
and can include line-ended comments. I would like to collect the comments into a Vec.
To accomplish this, I was looking for a multi combinator that would let me collect only certain values. I found fold_many1
and used it as follows:
fn push_some<T>(mut acc: Vec<T>, item: Option<T>) -> Vec<T> {
if let Some(item) = item {
acc.push(item);
}
acc
}
fn comment<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, &'a str, E>
{
preceded(char('#'), is_not("\n\r"))(input)
}
// At least 1 multispace or comment, outputs the comment contents if possible.
fn space_or_comment(input: &str) -> IResult<&str, Option<&str>> {
alt((
value(None, multispace1),
map(comment, Some),
))(input)
}
fn spacing1(input: &str) -> IResult<&str, Vec<&str>> {
fold_many1(space_or_comment, Vec::default, push_some)(input)
}
I was wondering if it made sense to have combinators filter_many0
and filter_many1
defined as :
fn push_some<T>(mut acc: Vec<T>, item: Option<T>) -> Vec<T> {
if let Some(item) = item {
acc.push(item);
}
acc
}
pub fn filter_many0<I, O, E, F>(f: F) -> impl FnMut(I) -> IResult<I, Vec<O>, E>
where
I: Clone + nom::InputLength,
F: nom::Parser<I, Option<O>, E>,
E: ParseError<I>,
{
nom::multi::fold_many0(f, Vec::default, push_some)
}
pub fn filter_many1<I, O, E, F>(f: F) -> impl FnMut(I) -> IResult<I, Vec<O>, E>
where
I: Clone + nom::InputLength,
F: nom::Parser<I, Option<O>, E>,
E: ParseError<I>,
{
nom::multi::fold_many1(f, Vec::default, push_some)
}
With these combinators, I could write:
fn spacing1(input: &str) -> IResult<&str, Vec<&str>> {
filter_many1(space_or_comment)(input)
}
Perhaps there is a better way to think about the problem and I don't actually need this.
Metadata
Assignees
Labels
No labels