Note: This site is currently "Under construction". I'm migrating to a new version of my site building software. Lots of things are in a state of disrepair as a result (for example, footnote links aren't working). It's all part of the process of building in public. Most things should still be readable though.

Using Multiple Levels Of "many" In Rust's nom Parser

I kept running into stuff with `many0``, `many1``, and `many_till`` in nom that I thought should have worked. Specifically when I was having one looping over another one by nesting them

I finally broke things out to it's own file and got things working by using `many1`` in both cases. Adding an `opt`` to the first one makes sure that things pass.

Code

use nom::bytes::complete::tag;
use nom::combinator::opt;
use nom::multi::many1;
use nom::IResult;

fn main() {
    dbg!(parse("aaaabbbb")).unwrap();
    dbg!(parse("wwwwxxxx")).unwrap();
    dbg!(parse("xxxxyyyy")).unwrap();
}

fn parse(source: &str) -> IResult<&str, Option<Vec<Vec<&str>>>> {
    let (source, response) = opt(many1(level2))(source)?;
    Ok((source, response))
}
fn level2(source: &str) -> IResult<&str, Vec<&str>> {
    dbg!(&source);
    let (source, response) = many1(tag("x"))(source)?;
    Ok((source, response))
}

Code

// // this doesn't work either
// fn parse(source: &str) -> IResult<&str, Vec<Vec<&str>>> {
//     let (source, response) = many_till(level2, eof)(source)?;
//     Ok((source, response.0))
// }
// fn level2(source: &str) -> IResult<&str, Vec<&str>> {
//     dbg!(&source);
//     let (source, response) = many0(tag("a"))(source)?;
//     Ok((source, response))
// }

// // these don't work. it throws an error because
// it looks like its sending an empty string to
// many0 on the second time thru
// fn parse(source: &str) -> IResult<&str, Vec<String>> {
//     let (source, response) = many0(level2)(source)?;
//     Ok((source, response))
// }
// fn level2(source: &str) -> IResult<&str, String> {
//     dbg!(&source);
//     let (source, response) = many0(is_not("x"))(source)?;
//     Ok((source, response.join("")))
// }