pub fn many<I, E, Collection, F, G>(
range: G,
parser: F,
) -> impl Parser<I, Output = Collection, Error = E>
Expand description
Repeats the embedded parser and collects the results in a type implementing Extend + Default
.
Fails if the amount of time the embedded parser is run is not
within the specified range.
ยงArguments
range
Constrains the number of iterations.- A range without an upper bound
a..
is equivalent to a range ofa..=usize::MAX
. - A single
usize
value is equivalent tovalue..=value
. - An empty range is invalid.
- A range without an upper bound
parse
The parser to apply.
use nom::multi::many;
use nom::bytes::complete::tag;
fn parser(s: &str) -> IResult<&str, Vec<&str>> {
many(0..=2, tag("abc")).parse(s)
}
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![])));
assert_eq!(parser("abcabcabc"), Ok(("abc", vec!["abc", "abc"])));
This is not limited to Vec
, other collections like HashMap
can be used:
use nom::multi::many;
use nom::bytes::complete::{tag, take_while};
use nom::sequence::{separated_pair, terminated};
use nom::AsChar;
use std::collections::HashMap;
fn key_value(s: &str) -> IResult<&str, HashMap<&str, &str>> {
many(0.., terminated(
separated_pair(
take_while(AsChar::is_alpha),
tag("="),
take_while(AsChar::is_alpha)
),
tag(";")
)).parse(s)
}
assert_eq!(
key_value("a=b;c=d;"),
Ok(("", HashMap::from([("a", "b"), ("c", "d")])))
);
If more control is needed on the default value, fold can be used instead:
use nom::multi::fold;
use nom::bytes::complete::tag;
fn parser(s: &str) -> IResult<&str, Vec<&str>> {
fold(
0..=4,
tag("abc"),
// preallocates a vector of the max size
|| Vec::with_capacity(4),
|mut acc: Vec<_>, item| {
acc.push(item);
acc
}
).parse(s)
}
assert_eq!(parser("abcabcabcabc"), Ok(("", vec!["abc", "abc", "abc", "abc"])));