diff options
Diffstat (limited to 'vendor/winnow/src/_tutorial/chapter_1.rs')
-rw-r--r-- | vendor/winnow/src/_tutorial/chapter_1.rs | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/vendor/winnow/src/_tutorial/chapter_1.rs b/vendor/winnow/src/_tutorial/chapter_1.rs new file mode 100644 index 000000000..d6a45c8b7 --- /dev/null +++ b/vendor/winnow/src/_tutorial/chapter_1.rs @@ -0,0 +1,89 @@ +//! # Chapter 1: The Winnow Way +//! +//! First of all, we need to understand the way that winnow thinks about parsing. +//! As discussed in the introduction, winnow lets us build simple parsers, and +//! then combine them (using "combinators"). +//! +//! Let's discuss what a "parser" actually does. A parser takes an input and returns +//! a result, where: +//! - `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. +//! +//! 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 +//! │ ) +//! ┌─────────┐ │ +//! 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)`; +//! whereas the `Err` variant stores an error. +//! +//! You can import that from: +//! +//! ```rust +//! use winnow::IResult; +//! ``` +//! +//! 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>`. +//! +//! This parser function should take in a `&str`: +//! +//! - Since it is supposed to succeed, we know it will return the Ok Variant. +//! - Since it does nothing to our input, the remaining input is the same as the input. +//! - Since it doesn't parse anything, it also should just return an empty string. +//! +//! ```rust +//! use winnow::IResult; +//! use winnow::Parser; +//! +//! pub fn do_nothing_parser(input: &str) -> IResult<&str, &str> { +//! Ok((input, "")) +//! } +//! +//! fn main() { +//! let input = "0x1a2b Hello"; +//! +//! let (remainder, output) = do_nothing_parser.parse_next(input).unwrap(); +//! // Same as: +//! // let (remainder, output) = do_nothing_parser(input).unwrap(); +//! +//! assert_eq!(remainder, "0x1a2b Hello"); +//! assert_eq!(output, ""); +//! } +//! ``` + +#![allow(unused_imports)] +use crate::IResult; +use crate::Parser; + +pub use super::chapter_0 as previous; +pub use super::chapter_2 as next; |