]>
Commit | Line | Data |
---|---|---|
49aad941 FG |
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 build simple parsers, and | |
5 | //! then combine them (using "combinators"). | |
6 | //! | |
7 | //! Let's discuss what a "parser" actually does. A parser takes an input and 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 | //! | |
add651ee | 12 | //! Parsers do more than just return a binary "success"/"failure" code. |
4b012472 | 13 | //! On success, the parser will return the processed data. The input will be left pointing to |
add651ee | 14 | //! data that still needs processing |
49aad941 FG |
15 | //! |
16 | //! If the parser failed, then there are multiple errors that could be returned. | |
17 | //! For simplicity, however, in the next chapters we will leave these unexplored. | |
18 | //! | |
19 | //! ```text | |
4b012472 FG |
20 | //! ┌─► Ok(what matched the parser) |
21 | //! ┌─────────┐ │ | |
22 | //! my input───►│my parser├──►either──┤ | |
23 | //! └─────────┘ └─► Err(...) | |
49aad941 FG |
24 | //! ``` |
25 | //! | |
26 | //! | |
add651ee FG |
27 | //! To represent this model of the world, winnow uses the [`PResult<O>`] type. |
28 | //! The `Ok` variant has `output: O`; | |
49aad941 FG |
29 | //! whereas the `Err` variant stores an error. |
30 | //! | |
31 | //! You can import that from: | |
32 | //! | |
33 | //! ```rust | |
add651ee | 34 | //! use winnow::PResult; |
49aad941 FG |
35 | //! ``` |
36 | //! | |
add651ee FG |
37 | //! To combine parsers, we need a common way to refer to them which is where the [`Parser<I, O, E>`] |
38 | //! trait comes in with [`Parser::parse_next`] being the primary way to drive | |
39 | //! parsing forward. | |
40 | //! | |
49aad941 FG |
41 | //! You'll note that `I` and `O` are parameterized -- while most of the examples in this book |
42 | //! will be with `&str` (i.e. parsing a string); they do not have to be strings; nor do they | |
43 | //! have to be the same type (consider the simple example where `I = &str`, and `O = u64` -- this | |
44 | //! parses a string into an unsigned integer.) | |
45 | //! | |
49aad941 FG |
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 | |
add651ee | 52 | //! functions of the form `Fn(&mut I) -> PResult<O>`. |
49aad941 FG |
53 | //! |
54 | //! This parser function should take in a `&str`: | |
55 | //! | |
4b012472 | 56 | //! - Since it is supposed to succeed, we know it will return the `Ok` variant. |
49aad941 FG |
57 | //! - Since it does nothing to our input, the remaining input is the same as the input. |
58 | //! - Since it doesn't parse anything, it also should just return an empty string. | |
59 | //! | |
60 | //! ```rust | |
add651ee | 61 | //! use winnow::PResult; |
49aad941 FG |
62 | //! use winnow::Parser; |
63 | //! | |
add651ee FG |
64 | //! pub fn do_nothing_parser<'s>(input: &mut &'s str) -> PResult<&'s str> { |
65 | //! Ok("") | |
49aad941 FG |
66 | //! } |
67 | //! | |
68 | //! fn main() { | |
add651ee | 69 | //! let mut input = "0x1a2b Hello"; |
49aad941 | 70 | //! |
add651ee | 71 | //! let output = do_nothing_parser.parse_next(&mut input).unwrap(); |
49aad941 | 72 | //! // Same as: |
add651ee | 73 | //! // let output = do_nothing_parser(&mut input).unwrap(); |
49aad941 | 74 | //! |
add651ee | 75 | //! assert_eq!(input, "0x1a2b Hello"); |
49aad941 FG |
76 | //! assert_eq!(output, ""); |
77 | //! } | |
78 | //! ``` | |
79 | ||
80 | #![allow(unused_imports)] | |
add651ee | 81 | use crate::PResult; |
49aad941 FG |
82 | use crate::Parser; |
83 | ||
84 | pub use super::chapter_0 as previous; | |
85 | pub use super::chapter_2 as next; | |
781aab86 | 86 | pub use crate::_tutorial as table_of_contents; |