From d5e795df8ef2ff6df3a552d80200ff990a733b5b Mon Sep 17 00:00:00 2001 From: Arne Beer Date: Fri, 22 Nov 2024 15:54:50 +0100 Subject: [PATCH] docs(tutorial): Clarify examples in chapter 5 --- src/_tutorial/chapter_5.rs | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/_tutorial/chapter_5.rs b/src/_tutorial/chapter_5.rs index 30760a85..3a770a8d 100644 --- a/src/_tutorial/chapter_5.rs +++ b/src/_tutorial/chapter_5.rs @@ -136,8 +136,8 @@ //! # } //! ``` //! -//! You'll notice that the above allows trailing `,` when we intended to not support that. We can -//! easily fix this by using [`separated`]: +//! You'll notice that the above allows trailing `,`. However, if that's not desired, it +//! can easily be fixed by using [`separated`] instead of [`repeat`]: //! ```rust //! # use winnow::prelude::*; //! # use winnow::token::take_while; @@ -199,9 +199,23 @@ //! } //! ``` //! -//! If you look closely at [`repeat`], it isn't collecting directly into a [`Vec`] but -//! anything that implements the [`Accumulate`] trait to gather the results. This lets us make more complex parsers than we did in -//! [`chapter_2`] by accumulating the results into a `()` and [`take`][Parser::take]-ing the captured input: +//! If you look closely at [`separated`] and [`repeat`], they don't always collect the result into +//! a [`Vec`], but rather anything that implements the [`Accumulate`] trait. +//! [`Accumulate`] is for instance also implemented for [`HashSet`], [`String`] and `()`. +//! +//! This enables you to build more complex parsers than shown in [`chapter_2`] by accumulating +//! complex expressions into a single `&str`. This is done by `[`take`][Parser::take]-ing the +//! `parse_list` parser, which effectively encapsulates it in a [`Take`]. +//! +//! [`Take`] works by creating a [`checkpoint`][Stream::checkpoint] before running the +//! inner parser. In our case the `parse_list` parser then advances to the end of the digit list, +//! afterwards `Take` reads the offset (i.e. how many chars were matched by `parse_list`), +//! restores the checkpoint, and returns the whole digit list as a single string based on +//! the previously read offset. +//! +//! Due to this `Take` doesn't care about the result of `parse_list`, which is why `parse_list` +//! simply accumulates into a `()`, which effectively discards the product of `parse_list`. +//! //! ```rust //! # use winnow::prelude::*; //! # use winnow::token::take_while; @@ -273,8 +287,11 @@ use super::chapter_3; use crate::combinator; use crate::combinator::repeat; use crate::combinator::separated; +use crate::combinator::Take; use crate::stream::Accumulate; +use crate::stream::Stream; use crate::Parser; +use std::collections::HashSet; use std::vec::Vec; pub use super::chapter_4 as previous;