Chapter 6: Repeating Parsers

A single parser which repeats a predicate is useful, but more useful still is a combinator that repeats a parser. Nom has multiple combinators which operate on this principle; the most obvious of which is many0, which applies a parser as many times as possible; and returns a vector of the results of those parses. Here is an example:

extern crate nom;
use std::error::Error;
use nom::IResult;
use nom::multi::many0;
use nom::bytes::complete::tag;

fn parser(s: &str) -> IResult<&str, Vec<&str>> {
  many0(tag("abc"))(s)
}

fn main() {
    assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"])));
    assert_eq!(parser("abc123"), Ok(("123", vec!["abc"])));
    assert_eq!(parser("123123"), Ok(("123123", vec![])));
    assert_eq!(parser(""), Ok(("", vec![])));
}

There are many different parsers to choose from:

combinatorusageinputoutputcomment
countcount(take(2), 3)"abcdefgh"Ok(("gh", vec!["ab", "cd", "ef"]))Applies the child parser a specified number of times
many0many0(tag("ab"))"abababc"Ok(("c", vec!["ab", "ab", "ab"]))Applies the parser 0 or more times and returns the list of results in a Vec. many1 does the same operation but must return at least one element
many_m_nmany_m_n(1, 3, tag("ab"))"ababc"Ok(("c", vec!["ab", "ab"]))Applies the parser between m and n times (n included) and returns the list of results in a Vec
many_tillmany_till(tag( "ab" ), tag( "ef" ))"ababefg"Ok(("g", (vec!["ab", "ab"], "ef")))Applies the first parser until the second applies. Returns a tuple containing the list of results from the first in a Vec and the result of the second
separated_list0separated_list0(tag(","), tag("ab"))"ab,ab,ab."Ok((".", vec!["ab", "ab", "ab"]))separated_list1 works like separated_list0 but must returns at least one element
fold_many0fold_many0(be_u8, \|\| 0, \|acc, item\| acc + item)[1, 2, 3]Ok(([], 6))Applies the parser 0 or more times and folds the list of return values. The fold_many1 version must apply the child parser at least one time
fold_many_m_nfold_many_m_n(1, 2, be_u8, \|\| 0, \|acc, item\| acc + item)[1, 2, 3]Ok(([3], 3))Applies the parser between m and n times (n included) and folds the list of return value
length_countlength_count(number, tag("ab"))"2ababab"Ok(("ab", vec!["ab", "ab"]))Gets a number from the first parser, then applies the second parser that many times