Skip to content

Omit elements from many0 or many1 result #1782

Open
@mickvangelderen

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

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions