Skip to content

Commit

Permalink
fix(multi): Replace fold_repeat0/fold_repeat1 with fold_repeat
Browse files Browse the repository at this point in the history
  • Loading branch information
epage committed May 2, 2023
1 parent 618bcfd commit a27efb2
Show file tree
Hide file tree
Showing 12 changed files with 100 additions and 112 deletions.
4 changes: 2 additions & 2 deletions assets/trace.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 5 additions & 3 deletions examples/arithmetic/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use winnow::{
ascii::{digit1 as digits, space0 as spaces},
combinator::alt,
combinator::delimited,
combinator::fold_repeat0,
combinator::fold_repeat,
token::one_of,
IResult,
};
Expand All @@ -15,7 +15,8 @@ use winnow::{
pub fn expr(i: &str) -> IResult<&str, i64> {
let (i, init) = term(i)?;

fold_repeat0(
fold_repeat(
0..,
(one_of("+-"), term),
move || init,
|acc, (op, val): (char, i64)| {
Expand All @@ -35,7 +36,8 @@ pub fn expr(i: &str) -> IResult<&str, i64> {
fn term(i: &str) -> IResult<&str, i64> {
let (i, init) = factor(i)?;

fold_repeat0(
fold_repeat(
0..,
(one_of("*/"), factor),
move || init,
|acc, (op, val): (char, i64)| {
Expand Down
4 changes: 2 additions & 2 deletions examples/json/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use winnow::{
combinator::alt,
combinator::cut_err,
combinator::{delimited, preceded, separated_pair, terminated},
combinator::{fold_repeat0, separated0},
combinator::{fold_repeat, separated0},
error::{ContextError, ParseError},
token::{any, none_of, take, take_while0},
};
Expand Down Expand Up @@ -87,7 +87,7 @@ fn string<'i, E: ParseError<Stream<'i>> + ContextError<Stream<'i>, &'static str>
// right branch (since we found the `"` character) but encountered an error when
// parsing the string
cut_err(terminated(
fold_repeat0(character, String::new, |mut string, c| {
fold_repeat(0.., character, String::new, |mut string, c| {
string.push(c);
string
}),
Expand Down
4 changes: 2 additions & 2 deletions examples/json/parser_dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use winnow::{
combinator::success,
combinator::{alt, dispatch},
combinator::{delimited, preceded, separated_pair, terminated},
combinator::{fold_repeat0, separated0},
combinator::{fold_repeat, separated0},
error::{ContextError, ParseError},
token::{any, none_of, take, take_while0},
};
Expand Down Expand Up @@ -96,7 +96,7 @@ fn string<'i, E: ParseError<Stream<'i>> + ContextError<Stream<'i>, &'static str>
// right branch (since we found the `"` character) but encountered an error when
// parsing the string
cut_err(terminated(
fold_repeat0(character, String::new, |mut string, c| {
fold_repeat(0.., character, String::new, |mut string, c| {
string.push(c);
string
}),
Expand Down
4 changes: 2 additions & 2 deletions examples/json/parser_partial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use winnow::{
combinator::alt,
combinator::{cut_err, rest},
combinator::{delimited, preceded, separated_pair, terminated},
combinator::{fold_repeat0, separated0},
combinator::{fold_repeat, separated0},
error::{ContextError, ParseError},
stream::Partial,
token::{any, none_of, take, take_while0},
Expand Down Expand Up @@ -88,7 +88,7 @@ fn string<'i, E: ParseError<Stream<'i>> + ContextError<Stream<'i>, &'static str>
// right branch (since we found the `"` character) but encountered an error when
// parsing the string
cut_err(terminated(
fold_repeat0(character, String::new, |mut string, c| {
fold_repeat(0.., character, String::new, |mut string, c| {
string.push(c);
string
}),
Expand Down
4 changes: 2 additions & 2 deletions examples/ndjson/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use winnow::{
combinator::alt,
combinator::cut_err,
combinator::{delimited, preceded, separated_pair, terminated},
combinator::{fold_repeat0, separated0},
combinator::{fold_repeat, separated0},
error::{ContextError, ParseError},
stream::Partial,
token::{any, none_of, take, take_while0},
Expand Down Expand Up @@ -92,7 +92,7 @@ fn string<'i, E: ParseError<Stream<'i>> + ContextError<Stream<'i>, &'static str>
// right branch (since we found the `"` character) but encountered an error when
// parsing the string
cut_err(terminated(
fold_repeat0(character, String::new, |mut string, c| {
fold_repeat(0.., character, String::new, |mut string, c| {
string.push(c);
string
}),
Expand Down
9 changes: 5 additions & 4 deletions examples/string/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

use winnow::ascii::multispace1;
use winnow::combinator::alt;
use winnow::combinator::fold_repeat0;
use winnow::combinator::fold_repeat;
use winnow::combinator::{delimited, preceded};
use winnow::error::{FromExternalError, ParseError};
use winnow::prelude::*;
Expand All @@ -23,9 +23,10 @@ pub fn parse_string<'a, E>(input: &'a str) -> IResult<&'a str, String, E>
where
E: ParseError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError>,
{
// fold_repeat0 is the equivalent of iterator::fold. It runs a parser in a loop,
// fold_repeat is the equivalent of iterator::fold. It runs a parser in a loop,
// and for each output value, calls a folding function on each output value.
let build_string = fold_repeat0(
let build_string = fold_repeat(
0..,
// Our parser function – parses a single string fragment
parse_fragment,
// Our init value, an empty string
Expand All @@ -44,7 +45,7 @@ where

// Finally, parse the string. Note that, if `build_string` could accept a raw
// " character, the closing delimiter " would never match. When using
// `delimited` with a looping parser (like fold_repeat0), be sure that the
// `delimited` with a looping parser (like fold_repeat), be sure that the
// loop won't accidentally match your closing delimiter!
delimited('"', build_string, '"').parse_next(input)
}
Expand Down
8 changes: 5 additions & 3 deletions fuzz/fuzz_targets/fuzz_arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use winnow::prelude::*;
use winnow::{
ascii::{digit1 as digit, space0 as space},
combinator::alt,
combinator::fold_repeat0,
combinator::fold_repeat,
combinator::{delimited, terminated},
};

Expand Down Expand Up @@ -64,7 +64,8 @@ fn term(i: &str) -> IResult<&str, i64> {
e
})?;

let res = fold_repeat0(
let res = fold_repeat(
0..,
alt((('*', factor), ('/', factor.verify(|i| *i != 0)))),
|| init,
|acc, (op, val): (char, i64)| {
Expand Down Expand Up @@ -93,7 +94,8 @@ fn expr(i: &str) -> IResult<&str, i64> {
e
})?;

let res = fold_repeat0(
let res = fold_repeat(
0..,
(alt(('+', '-')), term),
|| init,
|acc, (op, val): (char, i64)| {
Expand Down
1 change: 0 additions & 1 deletion src/combinator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
//! | [`repeat`][crate::combinator::repeat] | `repeat(1..=3, "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|
//! | [`repeat_till0`][crate::combinator::repeat_till0] | `repeat_till0(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|
//! | [`separated0`][crate::combinator::separated0] | `separated0("ab", ",")` | `"ab,ab,ab."` | `Ok((".", vec!["ab", "ab", "ab"]))` |`separated1` works like `separated0` but must returns at least one element|
//! | [`fold_repeat0`][crate::combinator::fold_repeat0] | `fold_repeat0(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_repeat1` version must apply the child parser at least one time|
//! | [`fold_repeat`][crate::combinator::fold_repeat] | `fold_repeat(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|
//!
//! ## Partial related
Expand Down
139 changes: 59 additions & 80 deletions src/combinator/multi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,57 @@ where
///
/// # Example
///
/// Zero or more repetitions:
/// ```rust
/// # use winnow::{error::ErrMode, error::ErrorKind, error::Needed};
/// # use winnow::prelude::*;
/// use winnow::combinator::fold_repeat;
/// use winnow::token::tag;
///
/// fn parser(s: &str) -> IResult<&str, Vec<&str>> {
/// fold_repeat(
/// 0..,
/// "abc",
/// Vec::new,
/// |mut acc: Vec<_>, item| {
/// acc.push(item);
/// acc
/// }
/// ).parse_next(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:
/// ```rust
/// # use winnow::{error::ErrMode, error::{Error, ErrorKind}, error::Needed};
/// # use winnow::prelude::*;
/// use winnow::combinator::fold_repeat;
/// use winnow::token::tag;
///
/// fn parser(s: &str) -> IResult<&str, Vec<&str>> {
/// fold_repeat(
/// 1..,
/// "abc",
/// Vec::new,
/// |mut acc: Vec<_>, item| {
/// acc.push(item);
/// acc
/// }
/// ).parse_next(s)
/// }
///
/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"])));
/// assert_eq!(parser("abc123"), Ok(("123", vec!["abc"])));
/// assert_eq!(parser("123123"), Err(ErrMode::Backtrack(Error::new("123123", ErrorKind::Many))));
/// assert_eq!(parser(""), Err(ErrMode::Backtrack(Error::new("", ErrorKind::Many))));
/// ```
///
/// Arbitrary number of repetitions:
/// ```rust
/// # use winnow::{error::ErrMode, error::ErrorKind, error::Needed};
/// # use winnow::prelude::*;
Expand All @@ -736,6 +787,8 @@ where
/// assert_eq!(parser(""), Ok(("", vec![])));
/// assert_eq!(parser("abcabcabc"), Ok(("abc", vec!["abc", "abc"])));
/// ```
#[doc(alias = "fold_many0")]
#[doc(alias = "fold_many1")]
#[doc(alias = "fold_many_m_n")]
#[inline(always)]
pub fn fold_repeat<I, O, E, F, G, H, R>(
Expand Down Expand Up @@ -771,46 +824,9 @@ where
})
}

/// Repeats the embedded parser, calling `g` to gather the results.
///
/// This stops on [`ErrMode::Backtrack`]. To instead chain an error up, see
/// [`cut_err`][crate::combinator::cut_err].
///
/// # Arguments
/// * `f` The parser to apply.
/// * `init` A function returning the initial value.
/// * `g` The function that combines a result of `f` with
/// the current accumulator.
///
/// **Warning:** if the parser passed in accepts empty inputs (like `alpha0` or `digit0`),
/// `fold_repeat0` will
/// return an error, to prevent going into an infinite loop
///
/// # Example
///
/// ```rust
/// # use winnow::{error::ErrMode, error::ErrorKind, error::Needed};
/// # use winnow::prelude::*;
/// use winnow::combinator::fold_repeat0;
/// use winnow::token::tag;
///
/// fn parser(s: &str) -> IResult<&str, Vec<&str>> {
/// fold_repeat0(
/// "abc",
/// Vec::new,
/// |mut acc: Vec<_>, item| {
/// acc.push(item);
/// acc
/// }
/// ).parse_next(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![])));
/// ```
#[doc(alias = "fold_many0")]
/// Deprecated, replaced by [`fold_repeat`]
#[deprecated(since = "0.4.6", note = "Replaced with `fold_repeat`")]
#[inline(always)]
pub fn fold_repeat0<I, O, E, F, G, H, R>(mut f: F, mut init: H, mut g: G) -> impl Parser<I, R, E>
where
I: Stream,
Expand Down Expand Up @@ -858,46 +874,9 @@ where
}
}

/// Repeats the embedded parser, calling `g` to gather the results.
///
/// This stops on [`ErrMode::Backtrack`] if there is at least one result. To instead chain an error up,
/// see [`cut_err`][crate::combinator::cut_err].
///
/// # Arguments
/// * `f` The parser to apply.
/// * `init` A function returning the initial value.
/// * `g` The function that combines a result of `f` with
/// the current accumulator.
///
/// **Warning:** If the parser passed to `fold_repeat1` accepts empty inputs
/// (like `alpha0` or `digit0`), `fold_repeat1` will return an error,
/// to prevent going into an infinite loop.
///
/// # Example
///
/// ```rust
/// # use winnow::{error::ErrMode, error::{Error, ErrorKind}, error::Needed};
/// # use winnow::prelude::*;
/// use winnow::combinator::fold_repeat1;
/// use winnow::token::tag;
///
/// fn parser(s: &str) -> IResult<&str, Vec<&str>> {
/// fold_repeat1(
/// "abc",
/// Vec::new,
/// |mut acc: Vec<_>, item| {
/// acc.push(item);
/// acc
/// }
/// ).parse_next(s)
/// }
///
/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"])));
/// assert_eq!(parser("abc123"), Ok(("123", vec!["abc"])));
/// assert_eq!(parser("123123"), Err(ErrMode::Backtrack(Error::new("123123", ErrorKind::Many))));
/// assert_eq!(parser(""), Err(ErrMode::Backtrack(Error::new("", ErrorKind::Many))));
/// ```
#[doc(alias = "fold_many1")]
/// Deprecated, replaced by [`fold_repeat`]
#[deprecated(since = "0.4.6", note = "Replaced with `fold_repeat`")]
#[inline(always)]
pub fn fold_repeat1<I, O, E, F, G, H, R>(mut f: F, mut init: H, mut g: G) -> impl Parser<I, R, E>
where
I: Stream,
Expand Down
12 changes: 6 additions & 6 deletions src/multi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ where
pub use combinator::count;
pub use combinator::fill;

/// Deprecated, replaced by [`combinator::fold_repeat0`]
#[deprecated(since = "0.4.2", note = "Replaced with `combinator::fold_repeat0`")]
/// Deprecated, replaced by [`combinator::fold_repeat`]
#[deprecated(since = "0.4.2", note = "Replaced with `combinator::fold_repeat`")]
#[inline(always)]
pub fn fold_many0<I, O, E, F, G, H, R>(f: F, init: H, g: G) -> impl Parser<I, R, E>
where
Expand All @@ -81,11 +81,11 @@ where
H: FnMut() -> R,
E: ParseError<I>,
{
combinator::fold_repeat0(f, init, g)
combinator::fold_repeat(0.., f, init, g)
}

/// Deprecated, replaced by [`combinator::fold_repeat1`]
#[deprecated(since = "0.4.2", note = "Replaced with `combinator::fold_repeat1`")]
/// Deprecated, replaced by [`combinator::fold_repeat`]
#[deprecated(since = "0.4.2", note = "Replaced with `combinator::fold_repeat`")]
#[inline(always)]
pub fn fold_many1<I, O, E, F, G, H, R>(f: F, init: H, g: G) -> impl Parser<I, R, E>
where
Expand All @@ -95,7 +95,7 @@ where
H: FnMut() -> R,
E: ParseError<I>,
{
combinator::fold_repeat1(f, init, g)
combinator::fold_repeat(1.., f, init, g)
}

/// Deprecated, replaced by [`combinator::fold_repeat`]
Expand Down
Loading

0 comments on commit a27efb2

Please sign in to comment.