/// Helper trait for the [`alt()`] combinator. /// /// This trait is implemented for tuples of up to 21 elements pubtrait Alt<I, O, E> { /// Tests each parser in the tuple and returns the result of the first one that succeeds fn choice(&mutself, input: &mut I) -> Result<O, E>;
}
/// Pick the first successful parser /// /// To stop on an error, rather than trying further cases, see /// [`cut_err`][crate::combinator::cut_err] ([example][crate::_tutorial::chapter_7]). /// /// For tight control over the error when no match is found, add a final case using [`fail`][crate::combinator::fail]. /// Alternatively, with a [custom error type][crate::_topic::error], it is possible to track all /// errors or return the error of the parser that went the farthest in the input data. /// /// When the alternative cases have unique prefixes, [`dispatch`] can offer better performance. /// /// # Example /// /// ```rust /// # use winnow::{error::ErrMode, error::Needed}; /// # use winnow::prelude::*; /// use winnow::ascii::{alpha1, digit1}; /// use winnow::combinator::alt; /// # fn main() { /// fn parser<'i>(input: &mut &'i str) -> ModalResult<&'i str> { /// alt((alpha1, digit1)).parse_next(input) /// }; /// /// // the first parser, alpha1, takes the input /// assert_eq!(parser.parse_peek("abc"), Ok(("", "abc"))); /// /// // the first parser returns an error, so alt tries the second one /// assert_eq!(parser.parse_peek("123456"), Ok(("", "123456"))); /// /// // both parsers failed, and with the default error type, alt will return the last error /// assert!(parser.parse_peek(" ").is_err()); /// # } /// ``` #[doc(alias = "choice")] #[inline(always)] pubfn alt<Input: Stream, Output, Error, Alternatives>( mut alternatives: Alternatives,
) -> impl Parser<Input, Output, Error> where
Alternatives: Alt<Input, Output, Error>,
Error: ParserError<Input>,
{
trace("alt", move |i: &mut Input| alternatives.choice(i))
}
/// Helper trait for the [`permutation()`] combinator. /// /// This trait is implemented for tuples of up to 21 elements pubtrait Permutation<I, O, E> { /// Tries to apply all parsers in the tuple in various orders until all of them succeed fn permutation(&mutself, input: &mut I) -> Result<O, E>;
}
/// Applies a list of parsers in any order. /// /// Permutation will succeed if all of the child parsers succeeded. /// It takes as argument a tuple of parsers, and returns a /// tuple of the parser results. /// /// To stop on an error, rather than trying further permutations, see /// [`cut_err`][crate::combinator::cut_err] ([example][crate::_tutorial::chapter_7]). /// /// # Example /// /// ```rust /// # use winnow::{error::ErrMode, error::Needed}; /// # use winnow::prelude::*; /// use winnow::ascii::{alpha1, digit1}; /// use winnow::combinator::permutation; /// # fn main() { /// fn parser<'i>(input: &mut &'i str) -> ModalResult<(&'i str, &'i str)> { /// permutation((alpha1, digit1)).parse_next(input) /// } /// /// // permutation takes alphabetic characters then digit /// assert_eq!(parser.parse_peek("abc123"), Ok(("", ("abc", "123")))); /// /// // but also in inverse order /// assert_eq!(parser.parse_peek("123abc"), Ok(("", ("abc", "123")))); /// /// // it will fail if one of the parsers failed /// assert!(parser.parse_peek("abc;").is_err()); /// # } /// ``` /// /// The parsers are applied greedily: if there are multiple unapplied parsers /// that could parse the next slice of input, the first one is used. /// ```rust /// # use winnow::error::ErrMode; /// # use winnow::prelude::*; /// use winnow::combinator::permutation; /// use winnow::token::any; /// /// fn parser(input: &mut &str) -> ModalResult<(char, char)> { /// permutation((any, 'a')).parse_next(input) /// } /// /// // any parses 'b', then char('a') parses 'a' /// assert_eq!(parser.parse_peek("ba"), Ok(("", ('b', 'a')))); /// /// // any parses 'a', then char('a') fails on 'b', /// // even though char('a') followed by any would succeed /// assert!(parser.parse_peek("ab").is_err()); /// ``` /// #[inline(always)] pubfn permutation<I: Stream, O, E: ParserError<I>, List: Permutation<I, O, E>>( mut l: List,
) -> impl Parser<I, O, E> {
trace("permutation", move |i: &mut I| l.permutation(i))
}
impl<const N: usize, I: Stream, O, E: ParserError<I>, P: Parser<I, O, E>> Alt<I, O, E> for [P; N] { fn choice(&mutself, input: &mut I) -> Result<O, E> { letmut error: Option<E> = None;
let start = input.checkpoint(); for branch inself {
input.reset(&start); match branch.parse_next(input) {
Err(e) if e.is_backtrack() => {
error = match error {
Some(error) => Some(error.or(e)),
None => Some(e),
};
}
res => return res,
}
}
match error {
Some(e) => Err(e.append(input, &start)),
None => Err(ParserError::assert(
input, "`alt` needs at least one parser",
)),
}
}
}
impl<I: Stream, O, E: ParserError<I>, P: Parser<I, O, E>> Alt<I, O, E> for &mut[P] { fn choice(&mutself, input: &mut I) -> Result<O, E> { letmut error: Option<E> = None;
let start = input.checkpoint(); for branch inself.iter_mut() {
input.reset(&start); match branch.parse_next(input) {
Err(e) if e.is_backtrack() => {
error = match error {
Some(error) => Some(error.or(e)),
None => Some(e),
};
}
res => return res,
}
}
match error {
Some(e) => Err(e.append(input, &start)),
None => Err(ParserError::assert(
input, "`alt` needs at least one parser",
)),
}
}
}
// Manually implement Alt for (A,), the 1-tuple type impl<I: Stream, O, E: ParserError<I>, A: Parser<I, O, E>> Alt<I, O, E> for (A,) { fn choice(&mutself, input: &mut I) -> Result<O, E> { self.0.parse_next(input)
}
}
// If we reach here, every iterator has either been applied before, // or errored on the remaining input iflet Some(err) = err { // There are remaining parsers, and all errored on the remaining input
input.reset(&start); return Err(err.append(input, &start));
}
// All parsers were applied match res {
($(Some($item)),+) => return Ok(($($item),+)),
_ => unreachable!(),
}
}
}
}
);
);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.