pub fn repeat<Input, Output, Accumulator, Error, ParseNext>(
occurrences: impl Into<Range>,
parser: ParseNext,
) -> Repeat<ParseNext, Input, Output, Accumulator, Error>where
Input: Stream,
Accumulator: Accumulate<Output>,
ParseNext: Parser<Input, Output, Error>,
Error: ParserError<Input>,
Expand description
Accumulate
the output of a parser into a container, like Vec
This stops before n
when the parser returns ErrMode::Backtrack
. To instead chain an error up, see
cut_err
.
To take a series of tokens, Accumulate
into a ()
(e.g. with .map(|()| ())
)
and then Parser::take
.
Warning: If the parser passed to repeat
accepts empty inputs
(like alpha0
or digit0
), repeat
will return an error,
to prevent going into an infinite loop.
ยงExample
Zero or more repetitions:
use winnow::combinator::repeat;
fn parser(s: &str) -> IResult<&str, Vec<&str>> {
repeat(0.., "abc").parse_peek(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![])));
One or more repetitions:
use winnow::combinator::repeat;
fn parser(s: &str) -> IResult<&str, Vec<&str>> {
repeat(1.., "abc").parse_peek(s)
}
assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"])));
assert_eq!(parser("abc123"), Ok(("123", vec!["abc"])));
assert_eq!(parser("123123"), Err(ErrMode::Backtrack(InputError::new("123123", ErrorKind::Tag))));
assert_eq!(parser(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag))));
Fixed number of repetitions:
use winnow::combinator::repeat;
fn parser(s: &str) -> IResult<&str, Vec<&str>> {
repeat(2, "abc").parse_peek(s)
}
assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"])));
assert_eq!(parser("abc123"), Err(ErrMode::Backtrack(InputError::new("123", ErrorKind::Tag))));
assert_eq!(parser("123123"), Err(ErrMode::Backtrack(InputError::new("123123", ErrorKind::Tag))));
assert_eq!(parser(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag))));
assert_eq!(parser("abcabcabc"), Ok(("abc", vec!["abc", "abc"])));
Arbitrary repetitions:
use winnow::combinator::repeat;
fn parser(s: &str) -> IResult<&str, Vec<&str>> {
repeat(0..=2, "abc").parse_peek(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"])));