winnow/_tutorial/
chapter_1.rs

1//! # Chapter 1: The Winnow Way
2//!
3//! First of all, we need to understand the way that winnow thinks about parsing.
4//! As discussed in the introduction, winnow lets us compose more complex parsers from more simple
5//! ones (using "combinators").
6//!
7//! Let's discuss what a "parser" actually does. A parser takes an input and advances it until it returns
8//! a result, where:
9//!  - `Ok` indicates the parser successfully found what it was looking for; or
10//!  - `Err` indicates the parser could not find what it was looking for.
11//!
12//! Parsers do more than just return a binary "success"/"failure" code.
13//! - On success, the parser will return the processed data. The input will be advanced to the end of
14//!   what was processed, pointing to what will be parsed next.
15//! - If the parser failed, then there are multiple errors that could be returned.
16//!   We'll explore this further in [`chapter_7`].
17//!
18//! ```text
19//!                                  ┌─► Ok(what matched the parser)
20//!             ┌────────┐           │
21//! my input───►│a parser├──►either──┤
22//!             └────────┘           └─► Err(...)
23//! ```
24//!
25//!
26//! To represent this model of the world, winnow uses the [`Result<O>`] type.
27//! The `Ok` variant has `output: O`;
28//! whereas the `Err` variant stores an error.
29//!
30//! You can import that from:
31//!
32//! ```rust
33//! use winnow::Result;
34//! ```
35//!
36//! To combine parsers, we need a common way to refer to them which is where the [`Parser<I, O, E>`]
37//! trait comes in with [`Parser::parse_next`] being the primary way to drive
38//! parsing forward.
39//! In [`chapter_6`], we'll cover how to integrate these into your application, particularly with
40//! [`Parser::parse`].
41//!
42//! You'll note that `I` and `O` are parameterized -- while most of the examples in this book
43//! will be with `&str` (i.e. parsing a string); [they do not have to be strings][stream]; nor do they
44//! have to be the same type (consider the simple example where `I = &str`, and `O = u64` -- this
45//! parses a string into an unsigned integer.)
46//!
47//! # Let's write our first parser!
48//!
49//! The simplest parser we can write is one which successfully does nothing.
50//!
51//! To make it easier to implement a [`Parser`], the trait is implemented for
52//! functions of the form `Fn(&mut I) -> Result<O>`.
53//!
54//! This parser function should take in a `&str`:
55//!
56//!  - Since it is supposed to succeed, we know it will return the `Ok` variant.
57//!  - Since it does nothing to our input, the input will be left where it started.
58//!  - Since it doesn't parse anything, it also should just return an empty string.
59//!
60//! ```rust
61//! use winnow::Result;
62//! use winnow::Parser;
63//!
64//! pub fn do_nothing_parser<'s>(input: &mut &'s str) -> Result<&'s str> {
65//!     Ok("")
66//! }
67//!
68//! fn main() {
69//!     let mut input = "0x1a2b Hello";
70//!
71//!     let output = do_nothing_parser.parse_next(&mut input).unwrap();
72//!     // Same as:
73//!     // let output = do_nothing_parser(&mut input).unwrap();
74//!
75//!     assert_eq!(input, "0x1a2b Hello");
76//!     assert_eq!(output, "");
77//! }
78//! ```
79
80#![allow(unused_imports)]
81use super::chapter_6;
82use super::chapter_7;
83use crate::Parser;
84use crate::_topic::stream;
85
86pub use super::chapter_0 as previous;
87pub use super::chapter_2 as next;
88pub use crate::_tutorial as table_of_contents;