• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 [`PResult<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::PResult;
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; 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) -> PResult<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::PResult;
62 //! use winnow::Parser;
63 //!
64 //! pub fn do_nothing_parser<'s>(input: &mut &'s str) -> PResult<&'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)]
81 use super::chapter_6;
82 use super::chapter_7;
83 use crate::PResult;
84 use crate::Parser;
85 
86 pub use super::chapter_0 as previous;
87 pub use super::chapter_2 as next;
88 pub use crate::_tutorial as table_of_contents;
89