diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:35 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:35 +0000 |
commit | d1b2d29528b7794b41e66fc2136e395a02f8529b (patch) | |
tree | a4a17504b260206dec3cf55b2dca82929a348ac2 /vendor/winnow/src/_tutorial | |
parent | Releasing progress-linux version 1.72.1+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.tar.xz rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.zip |
Merging upstream version 1.73.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/winnow/src/_tutorial')
-rw-r--r-- | vendor/winnow/src/_tutorial/chapter_1.rs | 44 | ||||
-rw-r--r-- | vendor/winnow/src/_tutorial/chapter_2.rs | 185 | ||||
-rw-r--r-- | vendor/winnow/src/_tutorial/chapter_3.rs | 249 | ||||
-rw-r--r-- | vendor/winnow/src/_tutorial/chapter_4.rs | 48 | ||||
-rw-r--r-- | vendor/winnow/src/_tutorial/chapter_5.rs | 185 | ||||
-rw-r--r-- | vendor/winnow/src/_tutorial/chapter_6.rs | 89 | ||||
-rw-r--r-- | vendor/winnow/src/_tutorial/chapter_7.rs | 72 |
7 files changed, 581 insertions, 291 deletions
diff --git a/vendor/winnow/src/_tutorial/chapter_1.rs b/vendor/winnow/src/_tutorial/chapter_1.rs index d6a45c8b7..1bf146bec 100644 --- a/vendor/winnow/src/_tutorial/chapter_1.rs +++ b/vendor/winnow/src/_tutorial/chapter_1.rs @@ -9,51 +9,47 @@ //! - `Ok` indicates the parser successfully found what it was looking for; or //! - `Err` indicates the parser could not find what it was looking for. //! -//! Parsers do more than just return a binary "success"/"failure" code. If -//! the parser was successful, then it will return a tuple where the first field -//! will contain everything the parser did not process. The second will contain -//! everything the parser processed. The idea is that a parser can happily parse the first -//! *part* of an input, without being able to parse the whole thing. +//! Parsers do more than just return a binary "success"/"failure" code. +//! On success, the parser will return the processed data. The input will be left pointing to +//! data that still needs processing //! //! If the parser failed, then there are multiple errors that could be returned. //! For simplicity, however, in the next chapters we will leave these unexplored. //! //! ```text -//! ┌─► Ok( -//! │ what the parser didn't touch, -//! │ what matched the parser -//! │ ) +//! ┌─► Ok(what matched the parser) //! ┌─────────┐ │ //! my input───►│my parser├──►either──┤ //! └─────────┘ └─► Err(...) //! ``` //! //! -//! To represent this model of the world, winnow uses the [`IResult<I, O>`] type. -//! The `Ok` variant has a tuple of `(remainder: I, output: O)`; +//! To represent this model of the world, winnow uses the [`PResult<O>`] type. +//! The `Ok` variant has `output: O`; //! whereas the `Err` variant stores an error. //! //! You can import that from: //! //! ```rust -//! use winnow::IResult; +//! use winnow::PResult; //! ``` //! +//! To combine parsers, we need a common way to refer to them which is where the [`Parser<I, O, E>`] +//! trait comes in with [`Parser::parse_next`] being the primary way to drive +//! parsing forward. +//! //! You'll note that `I` and `O` are parameterized -- while most of the examples in this book //! will be with `&str` (i.e. parsing a string); they do not have to be strings; nor do they //! have to be the same type (consider the simple example where `I = &str`, and `O = u64` -- this //! parses a string into an unsigned integer.) //! -//! To combine parsers, we need a common way to refer to them which is where the [`Parser`] -//! trait comes in with [`Parser::parse_next`] being the primary way to drive -//! parsing forward. //! //! # Let's write our first parser! //! //! The simplest parser we can write is one which successfully does nothing. //! //! To make it easier to implement a [`Parser`], the trait is implemented for -//! functions of the form `Fn(I) -> IResult<I, O>`. +//! functions of the form `Fn(&mut I) -> PResult<O>`. //! //! This parser function should take in a `&str`: //! @@ -62,27 +58,27 @@ //! - Since it doesn't parse anything, it also should just return an empty string. //! //! ```rust -//! use winnow::IResult; +//! use winnow::PResult; //! use winnow::Parser; //! -//! pub fn do_nothing_parser(input: &str) -> IResult<&str, &str> { -//! Ok((input, "")) +//! pub fn do_nothing_parser<'s>(input: &mut &'s str) -> PResult<&'s str> { +//! Ok("") //! } //! //! fn main() { -//! let input = "0x1a2b Hello"; +//! let mut input = "0x1a2b Hello"; //! -//! let (remainder, output) = do_nothing_parser.parse_next(input).unwrap(); +//! let output = do_nothing_parser.parse_next(&mut input).unwrap(); //! // Same as: -//! // let (remainder, output) = do_nothing_parser(input).unwrap(); +//! // let output = do_nothing_parser(&mut input).unwrap(); //! -//! assert_eq!(remainder, "0x1a2b Hello"); +//! assert_eq!(input, "0x1a2b Hello"); //! assert_eq!(output, ""); //! } //! ``` #![allow(unused_imports)] -use crate::IResult; +use crate::PResult; use crate::Parser; pub use super::chapter_0 as previous; diff --git a/vendor/winnow/src/_tutorial/chapter_2.rs b/vendor/winnow/src/_tutorial/chapter_2.rs index 49b61f3f4..b0daedc74 100644 --- a/vendor/winnow/src/_tutorial/chapter_2.rs +++ b/vendor/winnow/src/_tutorial/chapter_2.rs @@ -4,54 +4,139 @@ //! //! ## Tokens //! -//! Matching a single token literal is common enough that `Parser` is implemented for -//! `char`. -//! +//! [`Stream`] provides some core operations to help with parsing. For example, to process a +//! single token, you can do: //! ```rust //! # use winnow::Parser; -//! # use winnow::IResult; -//! # -//! fn parse_prefix(input: &str) -> IResult<&str, char> { -//! '0'.parse_next(input) +//! # use winnow::PResult; +//! use winnow::stream::Stream; +//! use winnow::error::ParserError; +//! use winnow::error::ErrorKind; +//! use winnow::error::ErrMode; +//! +//! fn parse_prefix(input: &mut &str) -> PResult<char> { +//! let c = input.next_token().ok_or_else(|| { +//! ErrMode::from_error_kind(input, ErrorKind::Token) +//! })?; +//! if c != '0' { +//! return Err(ErrMode::from_error_kind(input, ErrorKind::Verify)); +//! } +//! Ok(c) //! } //! //! fn main() { -//! let input = "0x1a2b Hello"; +//! let mut input = "0x1a2b Hello"; //! -//! let (remainder, output) = parse_prefix.parse_next(input).unwrap(); +//! let output = parse_prefix.parse_next(&mut input).unwrap(); //! -//! assert_eq!(remainder, "x1a2b Hello"); +//! assert_eq!(input, "x1a2b Hello"); //! assert_eq!(output, '0'); //! -//! assert!(parse_prefix("d").is_err()); +//! assert!(parse_prefix.parse_next(&mut "d").is_err()); //! } //! ``` //! -//! ## Tags +//! [`any`] and [`Parser::verify`] are [`Parser`] building blocks on top of [`Stream`]: +//! ```rust +//! # use winnow::PResult; +//! use winnow::Parser; +//! use winnow::token::any; //! -//! One of the most frequent way of matching a token is when they are combined into a string. -//! Again, this is common enough that `Parser` is implemented for `&str`: +//! fn parse_prefix(input: &mut &str) -> PResult<char> { +//! any.verify(|c| *c == '0').parse_next(input) +//! } +//! # +//! # fn main() { +//! # let mut input = "0x1a2b Hello"; +//! # +//! # let output = parse_prefix.parse_next(&mut input).unwrap(); +//! # +//! # assert_eq!(input, "x1a2b Hello"); +//! # assert_eq!(output, '0'); +//! # +//! # assert!(parse_prefix.parse_next(&mut "d").is_err()); +//! # } +//! ``` +//! +//! Matching a single token literal is common enough that [`Parser`] is implemented for +//! `char`. //! //! ```rust -//! # use winnow::Parser; -//! # use winnow::IResult; +//! # use winnow::PResult; +//! use winnow::Parser; +//! +//! fn parse_prefix(input: &mut &str) -> PResult<char> { +//! '0'.parse_next(input) +//! } //! # -//! fn parse_prefix(input: &str) -> IResult<&str, &str> { -//! "0x".parse_next(input) +//! # fn main() { +//! # let mut input = "0x1a2b Hello"; +//! # +//! # let output = parse_prefix.parse_next(&mut input).unwrap(); +//! # +//! # assert_eq!(input, "x1a2b Hello"); +//! # assert_eq!(output, '0'); +//! # +//! # assert!(parse_prefix.parse_next(&mut "d").is_err()); +//! # } +//! ``` +//! +//! ## Tags +//! +//! [`Stream`] also supports processing slices of tokens: +//! ```rust +//! # use winnow::Parser; +//! # use winnow::PResult; +//! use winnow::stream::Stream; +//! use winnow::error::ParserError; +//! use winnow::error::ErrorKind; +//! use winnow::error::ErrMode; +//! +//! fn parse_prefix<'s>(input: &mut &'s str) -> PResult<&'s str> { +//! let expected = "0x"; +//! if input.len() < expected.len() { +//! return Err(ErrMode::from_error_kind(input, ErrorKind::Slice)); +//! } +//! let actual = input.next_slice(expected.len()); +//! if actual != expected { +//! return Err(ErrMode::from_error_kind(input, ErrorKind::Verify)); +//! } +//! Ok(actual) //! } //! //! fn main() { -//! let input = "0x1a2b Hello"; +//! let mut input = "0x1a2b Hello"; //! -//! let (remainder, output) = parse_prefix.parse_next(input).unwrap(); -//! assert_eq!(remainder, "1a2b Hello"); +//! let output = parse_prefix.parse_next(&mut input).unwrap(); +//! assert_eq!(input, "1a2b Hello"); //! assert_eq!(output, "0x"); //! -//! assert!(parse_prefix("0o123").is_err()); +//! assert!(parse_prefix.parse_next(&mut "0o123").is_err()); //! } //! ``` //! -//! In `winnow`, we call this type of parser a [`tag`]. +//! Again, matching a literal is common enough that [`Parser`] is implemented for `&str`: +//! ```rust +//! # use winnow::PResult; +//! use winnow::Parser; +//! +//! fn parse_prefix<'s>(input: &mut &'s str) -> PResult<&'s str> { +//! "0x".parse_next(input) +//! } +//! # +//! # fn main() { +//! # let mut input = "0x1a2b Hello"; +//! # +//! # let output = parse_prefix.parse_next(&mut input).unwrap(); +//! # assert_eq!(input, "1a2b Hello"); +//! # assert_eq!(output, "0x"); +//! # +//! # assert!(parse_prefix.parse_next(&mut "0o123").is_err()); +//! # } +//! ``` +//! +//! In `winnow`, we call this type of parser a [`tag`]. See [`token`] for additional individual +//! and token-slice parsers. //! //! ## Character Classes //! @@ -60,21 +145,21 @@ //! //! ```rust //! # use winnow::Parser; -//! # use winnow::IResult; +//! # use winnow::PResult; //! use winnow::token::one_of; //! -//! fn parse_digits(input: &str) -> IResult<&str, char> { -//! one_of("0123456789abcdefgABCDEFG").parse_next(input) +//! fn parse_digits(input: &mut &str) -> PResult<char> { +//! one_of(('0'..='9', 'a'..='f', 'A'..='F')).parse_next(input) //! } //! //! fn main() { -//! let input = "1a2b Hello"; +//! let mut input = "1a2b Hello"; //! -//! let (remainder, output) = parse_digits.parse_next(input).unwrap(); -//! assert_eq!(remainder, "a2b Hello"); +//! let output = parse_digits.parse_next(&mut input).unwrap(); +//! assert_eq!(input, "a2b Hello"); //! assert_eq!(output, '1'); //! -//! assert!(parse_digits("Z").is_err()); +//! assert!(parse_digits.parse_next(&mut "Z").is_err()); //! } //! ``` //! @@ -82,10 +167,10 @@ //! > Let's look at it more closely as its used above (resolving all generic parameters): //! > ```rust //! > # use winnow::prelude::*; -//! > # use winnow::error::Error; +//! > # use winnow::error::InputError; //! > pub fn one_of<'i>( -//! > list: &'static str -//! > ) -> impl Parser<&'i str, char, Error<&'i str>> { +//! > list: &'static [char] +//! > ) -> impl Parser<&'i str, char, InputError<&'i str>> { //! > // ... //! > # winnow::token::one_of(list) //! > } @@ -93,7 +178,7 @@ //! > If you have not programmed in a language where functions are values, the type signature of the //! > [`one_of`] function might be a surprise. //! > The function [`one_of`] *returns a function*. The function it returns is a -//! > `Parser`, taking a `&str` and returning an `IResult`. This is a common pattern in winnow for +//! > `Parser`, taking a `&str` and returning an `PResult`. This is a common pattern in winnow for //! > configurable or stateful parsers. //! //! Some of character classes are common enough that a named parser is provided, like with: @@ -104,48 +189,54 @@ //! You can then capture sequences of these characters with parsers like [`take_while`]. //! ```rust //! # use winnow::Parser; -//! # use winnow::IResult; +//! # use winnow::PResult; //! use winnow::token::take_while; //! -//! fn parse_digits(input: &str) -> IResult<&str, &str> { -//! take_while(1.., "0123456789abcdefgABCDEFG").parse_next(input) +//! fn parse_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { +//! take_while(1.., ('0'..='9', 'a'..='f', 'A'..='F')).parse_next(input) //! } //! //! fn main() { -//! let input = "1a2b Hello"; +//! let mut input = "1a2b Hello"; //! -//! let (remainder, output) = parse_digits.parse_next(input).unwrap(); -//! assert_eq!(remainder, " Hello"); +//! let output = parse_digits.parse_next(&mut input).unwrap(); +//! assert_eq!(input, " Hello"); //! assert_eq!(output, "1a2b"); //! -//! assert!(parse_digits("Z").is_err()); +//! assert!(parse_digits.parse_next(&mut "Z").is_err()); //! } //! ``` //! //! We could simplify this further with by using one of the built-in character classes, [`hex_digit1`]: //! ```rust //! # use winnow::Parser; -//! # use winnow::IResult; +//! # use winnow::PResult; //! use winnow::ascii::hex_digit1; //! -//! fn parse_digits(input: &str) -> IResult<&str, &str> { +//! fn parse_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! hex_digit1.parse_next(input) //! } //! //! fn main() { -//! let input = "1a2b Hello"; +//! let mut input = "1a2b Hello"; //! -//! let (remainder, output) = parse_digits.parse_next(input).unwrap(); -//! assert_eq!(remainder, " Hello"); +//! let output = parse_digits.parse_next(&mut input).unwrap(); +//! assert_eq!(input, " Hello"); //! assert_eq!(output, "1a2b"); //! -//! assert!(parse_digits("Z").is_err()); +//! assert!(parse_digits.parse_next(&mut "Z").is_err()); //! } //! ``` +//! +//! See [`ascii`] for more text-based parsers. #![allow(unused_imports)] +use crate::ascii; use crate::ascii::hex_digit1; use crate::stream::ContainsToken; +use crate::stream::Stream; +use crate::token; +use crate::token::any; use crate::token::one_of; use crate::token::tag; use crate::token::take_while; diff --git a/vendor/winnow/src/_tutorial/chapter_3.rs b/vendor/winnow/src/_tutorial/chapter_3.rs index 8d307e324..83714f4d7 100644 --- a/vendor/winnow/src/_tutorial/chapter_3.rs +++ b/vendor/winnow/src/_tutorial/chapter_3.rs @@ -10,15 +10,14 @@ //! Now that we can create more interesting parsers, we can sequence them together, like: //! //! ```rust +//! # use winnow::prelude::*; //! # use winnow::token::take_while; -//! # use winnow::Parser; -//! # use winnow::IResult; //! # -//! fn parse_prefix(input: &str) -> IResult<&str, &str> { +//! fn parse_prefix<'s>(input: &mut &'s str) -> PResult<&'s str> { //! "0x".parse_next(input) //! } //! -//! fn parse_digits(input: &str) -> IResult<&str, &str> { +//! fn parse_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! take_while(1.., ( //! ('0'..='9'), //! ('A'..='F'), @@ -27,28 +26,27 @@ //! } //! //! fn main() { -//! let input = "0x1a2b Hello"; +//! let mut input = "0x1a2b Hello"; //! -//! let (remainder, prefix) = parse_prefix.parse_next(input).unwrap(); -//! let (remainder, digits) = parse_digits.parse_next(remainder).unwrap(); +//! let prefix = parse_prefix.parse_next(&mut input).unwrap(); +//! let digits = parse_digits.parse_next(&mut input).unwrap(); //! //! assert_eq!(prefix, "0x"); //! assert_eq!(digits, "1a2b"); -//! assert_eq!(remainder, " Hello"); +//! assert_eq!(input, " Hello"); //! } //! ``` //! //! To sequence these together, you can just put them in a tuple: //! ```rust +//! # use winnow::prelude::*; //! # use winnow::token::take_while; -//! # use winnow::Parser; -//! # use winnow::IResult; //! # -//! # fn parse_prefix(input: &str) -> IResult<&str, &str> { +//! # fn parse_prefix<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # "0x".parse_next(input) //! # } //! # -//! # fn parse_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='9'), //! # ('A'..='F'), @@ -59,32 +57,31 @@ //! //... //! //! fn main() { -//! let input = "0x1a2b Hello"; +//! let mut input = "0x1a2b Hello"; //! -//! let (remainder, (prefix, digits)) = ( +//! let (prefix, digits) = ( //! parse_prefix, //! parse_digits -//! ).parse_next(input).unwrap(); +//! ).parse_next(&mut input).unwrap(); //! //! assert_eq!(prefix, "0x"); //! assert_eq!(digits, "1a2b"); -//! assert_eq!(remainder, " Hello"); +//! assert_eq!(input, " Hello"); //! } //! ``` //! //! Frequently, you won't care about the tag and you can instead use one of the provided combinators, //! like [`preceded`]: //! ```rust +//! # use winnow::prelude::*; //! # use winnow::token::take_while; -//! # use winnow::Parser; -//! # use winnow::IResult; //! use winnow::combinator::preceded; //! -//! # fn parse_prefix(input: &str) -> IResult<&str, &str> { +//! # fn parse_prefix<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # "0x".parse_next(input) //! # } //! # -//! # fn parse_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='9'), //! # ('A'..='F'), @@ -95,63 +92,72 @@ //! //... //! //! fn main() { -//! let input = "0x1a2b Hello"; +//! let mut input = "0x1a2b Hello"; //! -//! let (remainder, digits) = preceded( +//! let digits = preceded( //! parse_prefix, //! parse_digits -//! ).parse_next(input).unwrap(); +//! ).parse_next(&mut input).unwrap(); //! //! assert_eq!(digits, "1a2b"); -//! assert_eq!(remainder, " Hello"); +//! assert_eq!(input, " Hello"); //! } //! ``` //! +//! See [`combinator`] for more sequencing parsers. +//! //! ## Alternatives //! //! Sometimes, we might want to choose between two parsers; and we're happy with //! either being used. //! -//! The de facto way to do this in winnow is with the [`alt()`] combinator which will execute each -//! parser in a tuple until it finds one that does not error. If all error, then by default you are -//! given the error from the last parser. -//! -//! We can see a basic example of `alt()` below. +//! [`Stream::checkpoint`] helps us to retry parsing: //! ```rust -//! # use winnow::IResult; -//! # use winnow::Parser; +//! # use winnow::prelude::*; //! # use winnow::token::take_while; -//! use winnow::combinator::alt; +//! use winnow::stream::Stream; //! -//! fn parse_digits(input: &str) -> IResult<&str, (&str, &str)> { -//! alt(( -//! ("0b", parse_bin_digits), -//! ("0o", parse_oct_digits), -//! ("0d", parse_dec_digits), -//! ("0x", parse_hex_digits), -//! )).parse_next(input) +//! fn parse_digits<'s>(input: &mut &'s str) -> PResult<(&'s str, &'s str)> { +//! let start = input.checkpoint(); +//! +//! if let Ok(output) = ("0b", parse_bin_digits).parse_next(input) { +//! return Ok(output); +//! } +//! +//! input.reset(start); +//! if let Ok(output) = ("0o", parse_oct_digits).parse_next(input) { +//! return Ok(output); +//! } +//! +//! input.reset(start); +//! if let Ok(output) = ("0d", parse_dec_digits).parse_next(input) { +//! return Ok(output); +//! } +//! +//! input.reset(start); +//! ("0x", parse_hex_digits).parse_next(input) //! } //! //! // ... -//! # fn parse_bin_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_bin_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='7'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_oct_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_oct_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='7'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_dec_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_dec_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='9'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_hex_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_hex_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='9'), //! # ('A'..='F'), @@ -160,31 +166,147 @@ //! # } //! //! fn main() { -//! let input = "0x1a2b Hello"; +//! let mut input = "0x1a2b Hello"; //! -//! let (remainder, (prefix, digits)) = parse_digits.parse_next(input).unwrap(); +//! let (prefix, digits) = parse_digits.parse_next(&mut input).unwrap(); //! -//! assert_eq!(remainder, " Hello"); +//! assert_eq!(input, " Hello"); //! assert_eq!(prefix, "0x"); //! assert_eq!(digits, "1a2b"); //! -//! assert!(parse_digits("ghiWorld").is_err()); +//! assert!(parse_digits(&mut "ghiWorld").is_err()); //! } //! ``` //! +//! > **Warning:** the above example is for illustrative purposes and relying on `Result::Ok` or +//! > `Result::Err` can lead to incorrect behavior. This will be clarified in later when covering +//! > [error handling][`chapter_6`#errmode] +//! +//! [`opt`] is a basic building block for correctly handling retrying parsing: +//! ```rust +//! # use winnow::prelude::*; +//! # use winnow::token::take_while; +//! use winnow::combinator::opt; +//! +//! fn parse_digits<'s>(input: &mut &'s str) -> PResult<(&'s str, &'s str)> { +//! if let Some(output) = opt(("0b", parse_bin_digits)).parse_next(input)? { +//! Ok(output) +//! } else if let Some(output) = opt(("0o", parse_oct_digits)).parse_next(input)? { +//! Ok(output) +//! } else if let Some(output) = opt(("0d", parse_dec_digits)).parse_next(input)? { +//! Ok(output) +//! } else { +//! ("0x", parse_hex_digits).parse_next(input) +//! } +//! } +//! # +//! # fn parse_bin_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { +//! # take_while(1.., ( +//! # ('0'..='7'), +//! # )).parse_next(input) +//! # } +//! # +//! # fn parse_oct_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { +//! # take_while(1.., ( +//! # ('0'..='7'), +//! # )).parse_next(input) +//! # } +//! # +//! # fn parse_dec_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { +//! # take_while(1.., ( +//! # ('0'..='9'), +//! # )).parse_next(input) +//! # } +//! # +//! # fn parse_hex_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { +//! # take_while(1.., ( +//! # ('0'..='9'), +//! # ('A'..='F'), +//! # ('a'..='f'), +//! # )).parse_next(input) +//! # } +//! # +//! # fn main() { +//! # let mut input = "0x1a2b Hello"; +//! # +//! # let (prefix, digits) = parse_digits.parse_next(&mut input).unwrap(); +//! # +//! # assert_eq!(input, " Hello"); +//! # assert_eq!(prefix, "0x"); +//! # assert_eq!(digits, "1a2b"); +//! # +//! # assert!(parse_digits(&mut "ghiWorld").is_err()); +//! # } +//! ``` +//! +//! [`alt`] encapsulates this if/else-if ladder pattern, with the last case being the `else`: +//! ```rust +//! # use winnow::prelude::*; +//! # use winnow::token::take_while; +//! use winnow::combinator::alt; +//! +//! fn parse_digits<'s>(input: &mut &'s str) -> PResult<(&'s str, &'s str)> { +//! alt(( +//! ("0b", parse_bin_digits), +//! ("0o", parse_oct_digits), +//! ("0d", parse_dec_digits), +//! ("0x", parse_hex_digits), +//! )).parse_next(input) +//! } +//! # +//! # fn parse_bin_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { +//! # take_while(1.., ( +//! # ('0'..='7'), +//! # )).parse_next(input) +//! # } +//! # +//! # fn parse_oct_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { +//! # take_while(1.., ( +//! # ('0'..='7'), +//! # )).parse_next(input) +//! # } +//! # +//! # fn parse_dec_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { +//! # take_while(1.., ( +//! # ('0'..='9'), +//! # )).parse_next(input) +//! # } +//! # +//! # fn parse_hex_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { +//! # take_while(1.., ( +//! # ('0'..='9'), +//! # ('A'..='F'), +//! # ('a'..='f'), +//! # )).parse_next(input) +//! # } +//! # +//! # fn main() { +//! # let mut input = "0x1a2b Hello"; +//! # +//! # let (prefix, digits) = parse_digits.parse_next(&mut input).unwrap(); +//! # +//! # assert_eq!(input, " Hello"); +//! # assert_eq!(prefix, "0x"); +//! # assert_eq!(digits, "1a2b"); +//! # +//! # assert!(parse_digits(&mut "ghiWorld").is_err()); +//! # } +//! ``` +//! +//! > **Note:** [`success`] and [`fail`] are parsers that might be useful in the `else` case. +//! //! Sometimes a giant if/else-if ladder can be slow and you'd rather have a `match` statement for //! branches of your parser that have unique prefixes. In this case, you can use the //! [`dispatch`][crate::combinator::dispatch] macro: //! //! ```rust -//! # use winnow::IResult; -//! # use winnow::Parser; +//! # use winnow::prelude::*; //! # use winnow::token::take_while; //! use winnow::combinator::dispatch; //! use winnow::token::take; //! use winnow::combinator::fail; //! -//! fn parse_digits(input: &str) -> IResult<&str, &str> { +//! fn parse_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! dispatch!(take(2usize); //! "0b" => parse_bin_digits, //! "0o" => parse_oct_digits, @@ -195,25 +317,25 @@ //! } //! //! // ... -//! # fn parse_bin_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_bin_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='7'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_oct_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_oct_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='7'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_dec_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_dec_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='9'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_hex_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_hex_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='9'), //! # ('A'..='F'), @@ -222,21 +344,32 @@ //! # } //! //! fn main() { -//! let input = "0x1a2b Hello"; +//! let mut input = "0x1a2b Hello"; //! -//! let (remainder, digits) = parse_digits.parse_next(input).unwrap(); +//! let digits = parse_digits.parse_next(&mut input).unwrap(); //! -//! assert_eq!(remainder, " Hello"); +//! assert_eq!(input, " Hello"); //! assert_eq!(digits, "1a2b"); //! -//! assert!(parse_digits("ghiWorld").is_err()); +//! assert!(parse_digits(&mut "ghiWorld").is_err()); //! } //! ``` +//! +//! > **Note:** [`peek`] may be useful when [`dispatch`]ing from hints from each case's parser. +//! +//! See [`combinator`] for more alternative parsers. #![allow(unused_imports)] +use super::chapter_6; +use crate::combinator; use crate::combinator::alt; use crate::combinator::dispatch; +use crate::combinator::fail; +use crate::combinator::opt; +use crate::combinator::peek; use crate::combinator::preceded; +use crate::combinator::success; +use crate::stream::Stream; pub use super::chapter_2 as previous; pub use super::chapter_4 as next; diff --git a/vendor/winnow/src/_tutorial/chapter_4.rs b/vendor/winnow/src/_tutorial/chapter_4.rs index 315d185ba..fb14613f3 100644 --- a/vendor/winnow/src/_tutorial/chapter_4.rs +++ b/vendor/winnow/src/_tutorial/chapter_4.rs @@ -1,18 +1,18 @@ //! # Chapter 4: Parsers With Custom Return Types //! //! So far, we have seen mostly functions that take an `&str`, and return a -//! `IResult<&str, &str>`. Splitting strings into smaller strings and characters is certainly +//! `PResult<&str>`. Splitting strings into smaller strings and characters is certainly //! useful, but it's not the only thing winnow is capable of! //! //! A useful operation when parsing is to convert between types; for example //! parsing from `&str` to another primitive, like [`usize`]. //! //! All we need to do for our parser to return a different type is to change -//! the second type parameter of [`IResult`] to the desired return type. -//! For example, to return a `usize`, return a `IResult<&str, usize>`. -//! Recall that the first type parameter of the `IResult` is the input +//! the type parameter of [`PResult`] to the desired return type. +//! For example, to return a `usize`, return a `PResult<usize>`. +//! Recall that the type parameter of the `PResult` is the input //! type, so even if you're returning something different, if your input -//! is a `&str`, the first type argument of `IResult` should be also. +//! is a `&str`, the type argument of `PResult` should be also. //! //! One winnow-native way of doing a type conversion is to use the //! [`Parser::parse_to`] combinator @@ -20,38 +20,36 @@ //! //! The following code converts from a string containing a number to `usize`: //! ```rust -//! # use winnow::Parser; -//! # use winnow::IResult; +//! # use winnow::prelude::*; //! # use winnow::ascii::digit1; //! # -//! fn parse_digits(input: &str) -> IResult<&str, usize> { +//! fn parse_digits(input: &mut &str) -> PResult<usize> { //! digit1 //! .parse_to() //! .parse_next(input) //! } //! //! fn main() { -//! let input = "1024 Hello"; +//! let mut input = "1024 Hello"; //! -//! let (remainder, output) = parse_digits.parse_next(input).unwrap(); -//! assert_eq!(remainder, " Hello"); +//! let output = parse_digits.parse_next(&mut input).unwrap(); +//! assert_eq!(input, " Hello"); //! assert_eq!(output, 1024); //! -//! assert!(parse_digits("Z").is_err()); +//! assert!(parse_digits(&mut "Z").is_err()); //! } //! ``` //! //! `Parser::parse_to` is just a convenient form of [`Parser::try_map`] which we can use to handle //! all radices of numbers: //! ```rust -//! # use winnow::IResult; -//! # use winnow::Parser; +//! # use winnow::prelude::*; //! # use winnow::token::take_while; //! use winnow::combinator::dispatch; //! use winnow::token::take; //! use winnow::combinator::fail; //! -//! fn parse_digits(input: &str) -> IResult<&str, usize> { +//! fn parse_digits(input: &mut &str) -> PResult<usize> { //! dispatch!(take(2usize); //! "0b" => parse_bin_digits.try_map(|s| usize::from_str_radix(s, 2)), //! "0o" => parse_oct_digits.try_map(|s| usize::from_str_radix(s, 8)), @@ -62,25 +60,25 @@ //! } //! //! // ... -//! # fn parse_bin_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_bin_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='7'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_oct_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_oct_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='7'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_dec_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_dec_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='9'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_hex_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_hex_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='9'), //! # ('A'..='F'), @@ -89,19 +87,21 @@ //! # } //! //! fn main() { -//! let input = "0x1a2b Hello"; +//! let mut input = "0x1a2b Hello"; //! -//! let (remainder, digits) = parse_digits.parse_next(input).unwrap(); +//! let digits = parse_digits.parse_next(&mut input).unwrap(); //! -//! assert_eq!(remainder, " Hello"); +//! assert_eq!(input, " Hello"); //! assert_eq!(digits, 0x1a2b); //! -//! assert!(parse_digits("ghiWorld").is_err()); +//! assert!(parse_digits(&mut "ghiWorld").is_err()); //! } //! ``` +//! +//! See also [`Parser`] for more output-modifying parsers. #![allow(unused_imports)] -use crate::IResult; +use crate::PResult; use crate::Parser; use std::str::FromStr; diff --git a/vendor/winnow/src/_tutorial/chapter_5.rs b/vendor/winnow/src/_tutorial/chapter_5.rs index 3a4be4b32..95a89dc8c 100644 --- a/vendor/winnow/src/_tutorial/chapter_5.rs +++ b/vendor/winnow/src/_tutorial/chapter_5.rs @@ -1,12 +1,11 @@ //! # Chapter 5: Repetition //! //! In [`chapter_3`], we covered how to sequence different parsers into a tuple but sometimes you need to run a -//! single parser multiple times, collecting the result into a [`Vec`]. +//! single parser multiple times, collecting the result into a container, like [`Vec`]. //! -//! Let's take our `parse_digits` and collect a list of them with [`repeat`]: +//! Let's collect the result of `parse_digits`: //! ```rust -//! # use winnow::IResult; -//! # use winnow::Parser; +//! # use winnow::prelude::*; //! # use winnow::token::take_while; //! # use winnow::combinator::dispatch; //! # use winnow::token::take; @@ -15,40 +14,44 @@ //! use winnow::combinator::repeat; //! use winnow::combinator::terminated; //! -//! fn parse_list(input: &str) -> IResult<&str, Vec<usize>> { -//! repeat(0.., terminated(parse_digits, opt(','))).parse_next(input) +//! fn parse_list(input: &mut &str) -> PResult<Vec<usize>> { +//! let mut list = Vec::new(); +//! while let Some(output) = opt(terminated(parse_digits, opt(','))).parse_next(input)? { +//! list.push(output); +//! } +//! Ok(list) //! } //! //! // ... -//! # fn parse_digits(input: &str) -> IResult<&str, usize> { +//! # fn parse_digits(input: &mut &str) -> PResult<usize> { //! # dispatch!(take(2usize); -//! # "0b" => parse_bin_digits.try_map(|s| usize::from_str_radix(s, 2)), -//! # "0o" => parse_oct_digits.try_map(|s| usize::from_str_radix(s, 8)), -//! # "0d" => parse_dec_digits.try_map(|s| usize::from_str_radix(s, 10)), -//! # "0x" => parse_hex_digits.try_map(|s| usize::from_str_radix(s, 16)), -//! # _ => fail, -//! # ).parse_next(input) +//! # "0b" => parse_bin_digits.try_map(|s| usize::from_str_radix(s, 2)), +//! # "0o" => parse_oct_digits.try_map(|s| usize::from_str_radix(s, 8)), +//! # "0d" => parse_dec_digits.try_map(|s| usize::from_str_radix(s, 10)), +//! # "0x" => parse_hex_digits.try_map(|s| usize::from_str_radix(s, 16)), +//! # _ => fail, +//! # ).parse_next(input) //! # } //! # -//! # fn parse_bin_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_bin_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='7'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_oct_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_oct_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='7'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_dec_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_dec_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='9'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_hex_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_hex_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='9'), //! # ('A'..='F'), @@ -57,62 +60,126 @@ //! # } //! //! fn main() { -//! let input = "0x1a2b,0x3c4d,0x5e6f Hello"; +//! let mut input = "0x1a2b,0x3c4d,0x5e6f Hello"; //! -//! let (remainder, digits) = parse_list.parse_next(input).unwrap(); +//! let digits = parse_list.parse_next(&mut input).unwrap(); //! -//! assert_eq!(remainder, " Hello"); +//! assert_eq!(input, " Hello"); //! assert_eq!(digits, vec![0x1a2b, 0x3c4d, 0x5e6f]); //! -//! assert!(parse_digits("ghiWorld").is_err()); +//! assert!(parse_digits(&mut "ghiWorld").is_err()); //! } //! ``` //! +//! We can implement this declaratively with [`repeat`]: +//! ```rust +//! # use winnow::prelude::*; +//! # use winnow::token::take_while; +//! # use winnow::combinator::dispatch; +//! # use winnow::token::take; +//! # use winnow::combinator::fail; +//! use winnow::combinator::opt; +//! use winnow::combinator::repeat; +//! use winnow::combinator::terminated; +//! +//! fn parse_list(input: &mut &str) -> PResult<Vec<usize>> { +//! repeat(0.., +//! terminated(parse_digits, opt(',')) +//! ).parse_next(input) +//! } +//! # +//! # fn parse_digits(input: &mut &str) -> PResult<usize> { +//! # dispatch!(take(2usize); +//! # "0b" => parse_bin_digits.try_map(|s| usize::from_str_radix(s, 2)), +//! # "0o" => parse_oct_digits.try_map(|s| usize::from_str_radix(s, 8)), +//! # "0d" => parse_dec_digits.try_map(|s| usize::from_str_radix(s, 10)), +//! # "0x" => parse_hex_digits.try_map(|s| usize::from_str_radix(s, 16)), +//! # _ => fail, +//! # ).parse_next(input) +//! # } +//! # +//! # fn parse_bin_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { +//! # take_while(1.., ( +//! # ('0'..='7'), +//! # )).parse_next(input) +//! # } +//! # +//! # fn parse_oct_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { +//! # take_while(1.., ( +//! # ('0'..='7'), +//! # )).parse_next(input) +//! # } +//! # +//! # fn parse_dec_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { +//! # take_while(1.., ( +//! # ('0'..='9'), +//! # )).parse_next(input) +//! # } +//! # +//! # fn parse_hex_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { +//! # take_while(1.., ( +//! # ('0'..='9'), +//! # ('A'..='F'), +//! # ('a'..='f'), +//! # )).parse_next(input) +//! # } +//! # +//! # fn main() { +//! # let mut input = "0x1a2b,0x3c4d,0x5e6f Hello"; +//! # +//! # let digits = parse_list.parse_next(&mut input).unwrap(); +//! # +//! # assert_eq!(input, " Hello"); +//! # assert_eq!(digits, vec![0x1a2b, 0x3c4d, 0x5e6f]); +//! # +//! # assert!(parse_digits(&mut "ghiWorld").is_err()); +//! # } +//! ``` +//! //! You'll notice that the above allows trailing `,` when we intended to not support that. We can //! easily fix this by using [`separated0`]: //! ```rust -//! # use winnow::IResult; -//! # use winnow::Parser; +//! # use winnow::prelude::*; //! # use winnow::token::take_while; //! # use winnow::combinator::dispatch; //! # use winnow::token::take; //! # use winnow::combinator::fail; //! use winnow::combinator::separated0; //! -//! fn parse_list(input: &str) -> IResult<&str, Vec<usize>> { +//! fn parse_list(input: &mut &str) -> PResult<Vec<usize>> { //! separated0(parse_digits, ",").parse_next(input) //! } //! //! // ... -//! # fn parse_digits(input: &str) -> IResult<&str, usize> { +//! # fn parse_digits(input: &mut &str) -> PResult<usize> { //! # dispatch!(take(2usize); -//! # "0b" => parse_bin_digits.try_map(|s| usize::from_str_radix(s, 2)), -//! # "0o" => parse_oct_digits.try_map(|s| usize::from_str_radix(s, 8)), -//! # "0d" => parse_dec_digits.try_map(|s| usize::from_str_radix(s, 10)), -//! # "0x" => parse_hex_digits.try_map(|s| usize::from_str_radix(s, 16)), -//! # _ => fail, -//! # ).parse_next(input) +//! # "0b" => parse_bin_digits.try_map(|s| usize::from_str_radix(s, 2)), +//! # "0o" => parse_oct_digits.try_map(|s| usize::from_str_radix(s, 8)), +//! # "0d" => parse_dec_digits.try_map(|s| usize::from_str_radix(s, 10)), +//! # "0x" => parse_hex_digits.try_map(|s| usize::from_str_radix(s, 16)), +//! # _ => fail, +//! # ).parse_next(input) //! # } //! # -//! # fn parse_bin_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_bin_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='7'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_oct_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_oct_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='7'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_dec_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_dec_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='9'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_hex_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_hex_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='9'), //! # ('A'..='F'), @@ -121,14 +188,14 @@ //! # } //! //! fn main() { -//! let input = "0x1a2b,0x3c4d,0x5e6f Hello"; +//! let mut input = "0x1a2b,0x3c4d,0x5e6f Hello"; //! -//! let (remainder, digits) = parse_list.parse_next(input).unwrap(); +//! let digits = parse_list.parse_next(&mut input).unwrap(); //! -//! assert_eq!(remainder, " Hello"); +//! assert_eq!(input, " Hello"); //! assert_eq!(digits, vec![0x1a2b, 0x3c4d, 0x5e6f]); //! -//! assert!(parse_digits("ghiWorld").is_err()); +//! assert!(parse_digits(&mut "ghiWorld").is_err()); //! } //! ``` //! @@ -136,52 +203,50 @@ //! [`Accumulate`] to gather the results. This let's us make more complex parsers than we did in //! [`chapter_2`] by accumulating the results into a `()` and [`recognize`][Parser::recognize]-ing the captured input: //! ```rust -//! # use winnow::IResult; -//! # use winnow::Parser; +//! # use winnow::prelude::*; //! # use winnow::token::take_while; //! # use winnow::combinator::dispatch; //! # use winnow::token::take; //! # use winnow::combinator::fail; //! # use winnow::combinator::separated0; //! # -//! fn recognize_list(input: &str) -> IResult<&str, &str> { +//! fn recognize_list<'s>(input: &mut &'s str) -> PResult<&'s str> { //! parse_list.recognize().parse_next(input) //! } //! -//! fn parse_list(input: &str) -> IResult<&str, ()> { +//! fn parse_list(input: &mut &str) -> PResult<()> { //! separated0(parse_digits, ",").parse_next(input) //! } //! -//! // ... -//! # fn parse_digits(input: &str) -> IResult<&str, usize> { +//! # fn parse_digits(input: &mut &str) -> PResult<usize> { //! # dispatch!(take(2usize); -//! # "0b" => parse_bin_digits.try_map(|s| usize::from_str_radix(s, 2)), -//! # "0o" => parse_oct_digits.try_map(|s| usize::from_str_radix(s, 8)), -//! # "0d" => parse_dec_digits.try_map(|s| usize::from_str_radix(s, 10)), -//! # "0x" => parse_hex_digits.try_map(|s| usize::from_str_radix(s, 16)), -//! # _ => fail, -//! # ).parse_next(input) +//! # "0b" => parse_bin_digits.try_map(|s| usize::from_str_radix(s, 2)), +//! # "0o" => parse_oct_digits.try_map(|s| usize::from_str_radix(s, 8)), +//! # "0d" => parse_dec_digits.try_map(|s| usize::from_str_radix(s, 10)), +//! # "0x" => parse_hex_digits.try_map(|s| usize::from_str_radix(s, 16)), +//! # _ => fail, +//! # ).parse_next(input) //! # } //! # -//! # fn parse_bin_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_bin_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='7'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_oct_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_oct_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='7'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_dec_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_dec_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='9'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_hex_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_hex_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='9'), //! # ('A'..='F'), @@ -190,20 +255,22 @@ //! # } //! //! fn main() { -//! let input = "0x1a2b,0x3c4d,0x5e6f Hello"; +//! let mut input = "0x1a2b,0x3c4d,0x5e6f Hello"; //! -//! let (remainder, digits) = recognize_list.parse_next(input).unwrap(); +//! let digits = recognize_list.parse_next(&mut input).unwrap(); //! -//! assert_eq!(remainder, " Hello"); +//! assert_eq!(input, " Hello"); //! assert_eq!(digits, "0x1a2b,0x3c4d,0x5e6f"); //! -//! assert!(parse_digits("ghiWorld").is_err()); +//! assert!(parse_digits(&mut "ghiWorld").is_err()); //! } //! ``` +//! See [`combinator`] for more repetition parsers. #![allow(unused_imports)] use super::chapter_2; use super::chapter_3; +use crate::combinator; use crate::combinator::repeat; use crate::combinator::separated0; use crate::stream::Accumulate; diff --git a/vendor/winnow/src/_tutorial/chapter_6.rs b/vendor/winnow/src/_tutorial/chapter_6.rs index 268e38a31..d7d2c9fc8 100644 --- a/vendor/winnow/src/_tutorial/chapter_6.rs +++ b/vendor/winnow/src/_tutorial/chapter_6.rs @@ -2,51 +2,48 @@ //! //! ## `Error` //! -//! Back in [`chapter_1`], we glossed over the `Err` side of [`IResult`]. `IResult<I, O>` is -//! actually short for `IResult<I, O, E=Error>` where [`Error`] is a cheap, universal error type -//! for getting started. When humans are producing the file, like with `toml`, you might want to -//! sacrifice some performance for providing more details on how to resolve the problem +//! Back in [`chapter_1`], we glossed over the `Err` side of [`PResult`]. `PResult<O>` is +//! actually short for `PResult<O, E=ContextError>` where [`ContextError`] is a relatively cheap +//! way of building up reasonable errors for humans. //! -//! winnow includes [`VerboseError`] for this but you can [customize the error as you -//! wish][_topic::error]. You can use [`Parser::context`] to annotate the error with custom types +//! You can use [`Parser::context`] to annotate the error with custom types //! while unwinding to further improve the error quality. //! //! ```rust -//! # use winnow::IResult; -//! # use winnow::Parser; +//! # use winnow::prelude::*; //! # use winnow::token::take_while; //! # use winnow::combinator::alt; -//! use winnow::error::VerboseError; +//! use winnow::error::StrContext; //! -//! fn parse_digits(input: &str) -> IResult<&str, (&str, &str), VerboseError<&str>> { +//! fn parse_digits<'s>(input: &mut &'s str) -> PResult<(&'s str, &'s str)> { //! alt(( -//! ("0b", parse_bin_digits).context("binary"), -//! ("0o", parse_oct_digits).context("octal"), -//! ("0d", parse_dec_digits).context("decimal"), -//! ("0x", parse_hex_digits).context("hexadecimal"), +//! ("0b", parse_bin_digits).context(StrContext::Label("binary")), +//! ("0o", parse_oct_digits).context(StrContext::Label("octal")), +//! ("0d", parse_dec_digits).context(StrContext::Label("decimal")), +//! ("0x", parse_hex_digits).context(StrContext::Label("hexadecimal")), //! )).parse_next(input) //! } //! //! // ... -//! # fn parse_bin_digits(input: &str) -> IResult<&str, &str, VerboseError<&str>> { +//! # fn parse_bin_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='7'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_oct_digits(input: &str) -> IResult<&str, &str, VerboseError<&str>> { +//! # fn parse_oct_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='7'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_dec_digits(input: &str) -> IResult<&str, &str, VerboseError<&str>> { +//! # fn parse_dec_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='9'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_hex_digits(input: &str) -> IResult<&str, &str, VerboseError<&str>> { +//! # fn parse_hex_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='9'), //! # ('A'..='F'), @@ -55,11 +52,11 @@ //! # } //! //! fn main() { -//! let input = "0x1a2b Hello"; +//! let mut input = "0x1a2b Hello"; //! -//! let (remainder, (prefix, digits)) = parse_digits.parse_next(input).unwrap(); +//! let (prefix, digits) = parse_digits.parse_next(&mut input).unwrap(); //! -//! assert_eq!(remainder, " Hello"); +//! assert_eq!(input, " Hello"); //! assert_eq!(prefix, "0x"); //! assert_eq!(digits, "1a2b"); //! } @@ -71,58 +68,57 @@ //! //! ## `ErrMode` //! -//! Let's break down `IResult<I, O, E>` one step further: +//! Let's break down `PResult<O, E>` one step further: //! ```rust -//! # use winnow::error::Error; +//! # use winnow::error::ErrorKind; //! # use winnow::error::ErrMode; -//! pub type IResult<I, O, E = Error<I>> = Result<(I, O), ErrMode<E>>; +//! pub type OResult<O, E = ErrorKind> = Result<O, ErrMode<E>>; //! ``` -//! `IResult` is just a fancy wrapper around `Result` that wraps our error in an [`ErrMode`] +//! [`PResult`] is just a fancy wrapper around `Result` that wraps our error in an [`ErrMode`] //! type. //! -//! `ErrMode` is an enum with `Backtrack` and `Cut` variants (ignore `Incomplete` as its only -//! relevant for [streaming][_topic::stream]). By default, errors are `Backtrack`, meaning that -//! other parsing branches will be attempted on failure, like the next case of an `alt`. `Cut` +//! [`ErrMode`] is an enum with [`Backtrack`] and [`Cut`] variants (ignore [`Incomplete`] as its only +//! relevant for [streaming][_topic::stream]). By default, errors are [`Backtrack`], meaning that +//! other parsing branches will be attempted on failure, like the next case of an [`alt`]. [`Cut`] //! shortcircuits all other branches, immediately reporting the error. //! //! So we can get the correct `context` by modifying the above example with [`cut_err`]: //! ```rust -//! # use winnow::IResult; -//! # use winnow::Parser; +//! # use winnow::prelude::*; //! # use winnow::token::take_while; //! # use winnow::combinator::alt; -//! # use winnow::error::VerboseError; +//! # use winnow::error::StrContext; //! use winnow::combinator::cut_err; //! -//! fn parse_digits(input: &str) -> IResult<&str, (&str, &str), VerboseError<&str>> { +//! fn parse_digits<'s>(input: &mut &'s str) -> PResult<(&'s str, &'s str)> { //! alt(( -//! ("0b", cut_err(parse_bin_digits)).context("binary"), -//! ("0o", cut_err(parse_oct_digits)).context("octal"), -//! ("0d", cut_err(parse_dec_digits)).context("decimal"), -//! ("0x", cut_err(parse_hex_digits)).context("hexadecimal"), +//! ("0b", cut_err(parse_bin_digits)).context(StrContext::Label("binary")), +//! ("0o", cut_err(parse_oct_digits)).context(StrContext::Label("octal")), +//! ("0d", cut_err(parse_dec_digits)).context(StrContext::Label("decimal")), +//! ("0x", cut_err(parse_hex_digits)).context(StrContext::Label("hexadecimal")), //! )).parse_next(input) //! } //! //! // ... -//! # fn parse_bin_digits(input: &str) -> IResult<&str, &str, VerboseError<&str>> { +//! # fn parse_bin_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='7'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_oct_digits(input: &str) -> IResult<&str, &str, VerboseError<&str>> { +//! # fn parse_oct_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='7'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_dec_digits(input: &str) -> IResult<&str, &str, VerboseError<&str>> { +//! # fn parse_dec_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='9'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_hex_digits(input: &str) -> IResult<&str, &str, VerboseError<&str>> { +//! # fn parse_hex_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='9'), //! # ('A'..='F'), @@ -131,11 +127,11 @@ //! # } //! //! fn main() { -//! let input = "0x1a2b Hello"; +//! let mut input = "0x1a2b Hello"; //! -//! let (remainder, (prefix, digits)) = parse_digits.parse_next(input).unwrap(); +//! let (prefix, digits) = parse_digits.parse_next(&mut input).unwrap(); //! -//! assert_eq!(remainder, " Hello"); +//! assert_eq!(input, " Hello"); //! assert_eq!(prefix, "0x"); //! assert_eq!(digits, "1a2b"); //! } @@ -147,10 +143,11 @@ use super::chapter_1; use super::chapter_3; use crate::combinator::alt; use crate::combinator::cut_err; +use crate::error::ContextError; use crate::error::ErrMode; -use crate::error::Error; -use crate::error::VerboseError; -use crate::IResult; +use crate::error::ErrMode::*; +use crate::error::ErrorKind; +use crate::PResult; use crate::Parser; use crate::_topic; diff --git a/vendor/winnow/src/_tutorial/chapter_7.rs b/vendor/winnow/src/_tutorial/chapter_7.rs index c20607c36..45f2d2d2a 100644 --- a/vendor/winnow/src/_tutorial/chapter_7.rs +++ b/vendor/winnow/src/_tutorial/chapter_7.rs @@ -3,53 +3,62 @@ //! So far, we've highlighted how to incrementally parse, but how do we bring this all together //! into our application? //! -//! The type we've been working with looks like: +//! Parsers we've been working with look like: //! ```rust -//! # use winnow::error::VerboseError; +//! # use winnow::error::ContextError; //! # use winnow::error::ErrMode; -//! type IResult<'i, O> = Result< -//! (&'i str, O), -//! ErrMode< -//! VerboseError<&'i str> -//! > +//! # use winnow::Parser; +//! # +//! pub fn parser<'s>(input: &mut &'s str) -> PResult<&'s str> { +//! // ... +//! # Ok("") +//! } +//! +//! type PResult<O> = Result< +//! O, +//! ErrMode<ContextError> //! >; //! ``` -//! 1. We have to decide what to do about the `remainder` of the input. -//! 2. The error type is not compatible with the rest of the Rust ecosystem +//! 1. We have to decide what to do about the "remainder" of the `input`. +//! 2. The [`ErrMode<ContextError>`] is not compatible with the rest of the Rust ecosystem. +//! Normally, Rust applications want errors that are `std::error::Error + Send + Sync + 'static` +//! meaning: +//! - They implement the [`std::error::Error`] trait +//! - They can be sent across threads +//! - They are safe to be referenced across threads +//! - They do not borrow //! -//! Normally, Rust applications want errors that are `std::error::Error + Send + Sync + 'static` -//! meaning: -//! - They implement the [`std::error::Error`] trait -//! - They can be sent across threads -//! - They are safe to be referenced across threads -//! - They do not borrow -//! -//! winnow provides some helpers for this: +//! winnow provides [`Parser::parse`] to help with this: +//! - Ensures we hit [`eof`] +//! - Removes the [`ErrMode`] wrapper +//! - Wraps the error in [`ParseError`] +//! - Provides access to the original [`input`][ParseError::input] with the +//! [`offset`][ParseError::offset] of where it failed +//! - Provides a default renderer (via [`std::fmt::Display`]) //! ```rust -//! # use winnow::IResult; +//! # use winnow::prelude::*; //! # use winnow::token::take_while; //! # use winnow::combinator::dispatch; //! # use winnow::token::take; //! # use winnow::combinator::fail; //! use winnow::Parser; -//! use winnow::error::Error; //! //! #[derive(Debug, PartialEq, Eq)] //! pub struct Hex(usize); //! //! impl std::str::FromStr for Hex { -//! type Err = Error<String>; +//! type Err = String; //! //! fn from_str(input: &str) -> Result<Self, Self::Err> { //! parse_digits //! .map(Hex) //! .parse(input) -//! .map_err(|e| e.into_owned()) +//! .map_err(|e| e.to_string()) //! } //! } //! //! // ... -//! # fn parse_digits(input: &str) -> IResult<&str, usize> { +//! # fn parse_digits<'s>(input: &mut &'s str) -> PResult<usize> { //! # dispatch!(take(2usize); //! # "0b" => parse_bin_digits.try_map(|s| usize::from_str_radix(s, 2)), //! # "0o" => parse_oct_digits.try_map(|s| usize::from_str_radix(s, 8)), @@ -59,25 +68,25 @@ //! # ).parse_next(input) //! # } //! # -//! # fn parse_bin_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_bin_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='7'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_oct_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_oct_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='7'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_dec_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_dec_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='9'), //! # )).parse_next(input) //! # } //! # -//! # fn parse_hex_digits(input: &str) -> IResult<&str, &str> { +//! # fn parse_hex_digits<'s>(input: &mut &'s str) -> PResult<&'s str> { //! # take_while(1.., ( //! # ('0'..='9'), //! # ('A'..='F'), @@ -95,17 +104,14 @@ //! assert!(input.parse::<Hex>().is_err()); //! } //! ``` -//! - Ensures we hit [`eof`] -//! - Removes the [`ErrMode`] wrapper -//! -//! [`Error::into_owned`]: -//! - Converts the `&str` in `Error` to `String` which enables support for [`std::error::Error`] #![allow(unused_imports)] use super::chapter_1; use crate::combinator::eof; use crate::error::ErrMode; -use crate::error::Error; -use crate::IResult; +use crate::error::InputError; +use crate::error::ParseError; +use crate::PResult; +use crate::Parser; pub use super::chapter_6 as previous; |