Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/winnow/src/_tutorial/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 9 kB image not shown  

Quelle  chapter_5.rs

  Sprache: Rust
 

//! # Chapter 5: Repetition
//!
//! In [`chapter_3`], we covered how to sequence different parsers into a tuple but sometimes you need to run a
//! single parser multiple times, collecting the result into a container, like `Vec`.
//!
//! Let's collect the result of `parse_digits`:
//! ```rust
//! # use winnow::prelude::*;
//! # use winnow::Result;
//! # use winnow::token::take_while;
//! # use winnow::combinator::dispatch;
//! # use winnow::token::take;
//! # use winnow::combinator::fail;
//! use winnow::combinator::opt;
//! use winnow::combinator::repeat;
//! use winnow::combinator::terminated;
//!
//! fn parse_list(input: &mut &str) -> Result<Vec<usize>> {
//!     let mut list = Vec::new();
//!     while let Some(output) = opt(terminated(parse_digits, opt(','))).parse_next(input)? {
//!         list.push(output);
//!     }
//!     Ok(list)
//! }
//!
//! // ...
//! # fn parse_digits(input: &mut &str) -> Result<usize> {
//! #     dispatch!(take(2usize);
//! #         "0b" => parse_bin_digits.try_map(|s| usize::from_str_radix(s, 2)),
//! #         "0o" => parse_oct_digits.try_map(|s| usize::from_str_radix(s, 8)),
//! #         "0d" => parse_dec_digits.try_map(|s| usize::from_str_radix(s, 10)),
//! #         "0x" => parse_hex_digits.try_map(|s| usize::from_str_radix(s, 16)),
//! #         _ => fail,
//! #     ).parse_next(input)
//! # }
//! #
//! # fn parse_bin_digits<'s>(input: &mut &'s str) -> Result<&'s str> {
//! #     take_while(1.., (
//! #         ('0'..='1'),
//! #     )).parse_next(input)
//! # }
//! #
//! # fn parse_oct_digits<'s>(input: &mut &'s str) -> Result<&'s str> {
//! #     take_while(1.., (
//! #         ('0'..='7'),
//! #     )).parse_next(input)
//! # }
//! #
//! # fn parse_dec_digits<'s>(input: &mut &'s str) -> Result<&'s str> {
//! #     take_while(1.., (
//! #         ('0'..='9'),
//! #     )).parse_next(input)
//! # }
//! #
//! # fn parse_hex_digits<'s>(input: &mut &'s str) -> Result<&'s str> {
//! #     take_while(1.., (
//! #         ('0'..='9'),
//! #         ('A'..='F'),
//! #         ('a'..='f'),
//! #     )).parse_next(input)
//! # }
//!
//! fn main() {
//!     let mut input = "0x1a2b,0x3c4d,0x5e6f Hello";
//!
//!     let digits = parse_list.parse_next(&mut input).unwrap();
//!
//!     assert_eq!(input, " Hello");
//!     assert_eq!(digits, vec![0x1a2b, 0x3c4d, 0x5e6f]);
//!
//!     assert!(parse_digits(&mut "ghiWorld").is_err());
//! }
//! ```
//!
//! We can implement this declaratively with [`repeat`]:
//! ```rust
//! # use winnow::prelude::*;
//! # use winnow::Result;
//! # use winnow::token::take_while;
//! # use winnow::combinator::dispatch;
//! # use winnow::token::take;
//! # use winnow::combinator::fail;
//! use winnow::combinator::opt;
//! use winnow::combinator::repeat;
//! use winnow::combinator::terminated;
//!
//! fn parse_list(input: &mut &str) -> Result<Vec<usize>> {
//!     repeat(0..,
//!         terminated(parse_digits, opt(','))
//!     ).parse_next(input)
//! }
//! #
//! # fn parse_digits(input: &mut &str) -> Result<usize> {
//! #     dispatch!(take(2usize);
//! #         "0b" => parse_bin_digits.try_map(|s| usize::from_str_radix(s, 2)),
//! #         "0o" => parse_oct_digits.try_map(|s| usize::from_str_radix(s, 8)),
//! #         "0d" => parse_dec_digits.try_map(|s| usize::from_str_radix(s, 10)),
//! #         "0x" => parse_hex_digits.try_map(|s| usize::from_str_radix(s, 16)),
//! #         _ => fail,
//! #     ).parse_next(input)
//! # }
//! #
//! # fn parse_bin_digits<'s>(input: &mut &'s str) -> Result<&'s str> {
//! #     take_while(1.., (
//! #         ('0'..='1'),
//! #     )).parse_next(input)
//! # }
//! #
//! # fn parse_oct_digits<'s>(input: &mut &'s str) -> Result<&'s str> {
//! #     take_while(1.., (
//! #         ('0'..='7'),
//! #     )).parse_next(input)
//! # }
//! #
//! # fn parse_dec_digits<'s>(input: &mut &'s str) -> Result<&'s str> {
//! #     take_while(1.., (
//! #         ('0'..='9'),
//! #     )).parse_next(input)
//! # }
//! #
//! # fn parse_hex_digits<'s>(input: &mut &'s str) -> Result<&'s str> {
//! #     take_while(1.., (
//! #         ('0'..='9'),
//! #         ('A'..='F'),
//! #         ('a'..='f'),
//! #     )).parse_next(input)
//! # }
//! #
//! # fn main() {
//! #     let mut input = "0x1a2b,0x3c4d,0x5e6f Hello";
//! #
//! #     let digits = parse_list.parse_next(&mut input).unwrap();
//! #
//! #     assert_eq!(input, " Hello");
//! #     assert_eq!(digits, vec![0x1a2b, 0x3c4d, 0x5e6f]);
//! #
//! #     assert!(parse_digits(&mut "ghiWorld").is_err());
//! # }
//! ```
//!
//! 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::Result;
//! # use winnow::token::take_while;
//! # use winnow::combinator::dispatch;
//! # use winnow::token::take;
//! # use winnow::combinator::fail;
//! use winnow::combinator::separated;
//!
//! fn parse_list(input: &mut &str) -> Result<Vec<usize>> {
//!     separated(0.., parse_digits, ",").parse_next(input)
//! }
//!
//! // ...
//! # fn parse_digits(input: &mut &str) -> Result<usize> {
//! #     dispatch!(take(2usize);
//! #         "0b" => parse_bin_digits.try_map(|s| usize::from_str_radix(s, 2)),
//! #         "0o" => parse_oct_digits.try_map(|s| usize::from_str_radix(s, 8)),
//! #         "0d" => parse_dec_digits.try_map(|s| usize::from_str_radix(s, 10)),
//! #         "0x" => parse_hex_digits.try_map(|s| usize::from_str_radix(s, 16)),
//! #         _ => fail,
//! #     ).parse_next(input)
//! # }
//! #
//! # fn parse_bin_digits<'s>(input: &mut &'s str) -> Result<&'s str> {
//! #     take_while(1.., (
//! #         ('0'..='1'),
//! #     )).parse_next(input)
//! # }
//! #
//! # fn parse_oct_digits<'s>(input: &mut &'s str) -> Result<&'s str> {
//! #     take_while(1.., (
//! #         ('0'..='7'),
//! #     )).parse_next(input)
//! # }
//! #
//! # fn parse_dec_digits<'s>(input: &mut &'s str) -> Result<&'s str> {
//! #     take_while(1.., (
//! #         ('0'..='9'),
//! #     )).parse_next(input)
//! # }
//! #
//! # fn parse_hex_digits<'s>(input: &mut &'s str) -> Result<&'s str> {
//! #     take_while(1.., (
//! #         ('0'..='9'),
//! #         ('A'..='F'),
//! #         ('a'..='f'),
//! #     )).parse_next(input)
//! # }
//!
//! fn main() {
//!     let mut input = "0x1a2b,0x3c4d,0x5e6f Hello";
//!
//!     let digits = parse_list.parse_next(&mut input).unwrap();
//!
//!     assert_eq!(input, " Hello");
//!     assert_eq!(digits, vec![0x1a2b, 0x3c4d, 0x5e6f]);
//!
//!     assert!(parse_digits(&mut "ghiWorld").is_err());
//! }
//! ```
//!
//! If you look closely at [`separated`] and [`repeat`], they aren't limited to collecting
//! the result into a `Vec`, but rather anything that implements the [`Accumulate`] trait.
//! [`Accumulate`] is for instance also implemented for [`HashSet`], [`String`] and `()`.
//!
//! This lets us build more complex parsers than we did in
//! [`chapter_2`] by accumulating the results into a `()` and [`take`][Parser::take]-ing
//! the consumed input.
//!
//! `take` works by
//! 1. Creating a [`checkpoint`][Stream::checkpoint]
//! 2. Running the inner parser, in our case the `parse_list` parser, which will advance the input
//! 3. Returning the slice from the first checkpoint to the current position.
//!
//! Since the result of `parse_list` gets thrown away, we
//! accumulates into a `()` to not waste work creating an unused `Vec`.
//!
//! ```rust
//! # use winnow::prelude::*;
//! # use winnow::Result;
//! # use winnow::token::take_while;
//! # use winnow::combinator::dispatch;
//! # use winnow::token::take;
//! # use winnow::combinator::fail;
//! # use winnow::combinator::separated;
//! #
//! fn take_list<'s>(input: &mut &'s str) -> Result<&'s str> {
//!     parse_list.take().parse_next(input)
//! }
//!
//! fn parse_list(input: &mut &str) -> Result<()> {
//!     separated(0.., parse_digits, ",").parse_next(input)
//! }
//!
//! # fn parse_digits(input: &mut &str) -> Result<usize> {
//! #     dispatch!(take(2usize);
//! #         "0b" => parse_bin_digits.try_map(|s| usize::from_str_radix(s, 2)),
//! #         "0o" => parse_oct_digits.try_map(|s| usize::from_str_radix(s, 8)),
//! #         "0d" => parse_dec_digits.try_map(|s| usize::from_str_radix(s, 10)),
//! #         "0x" => parse_hex_digits.try_map(|s| usize::from_str_radix(s, 16)),
//! #         _ => fail,
//! #     ).parse_next(input)
//! # }
//! #
//! # fn parse_bin_digits<'s>(input: &mut &'s str) -> Result<&'s str> {
//! #     take_while(1.., (
//! #         ('0'..='1'),
//! #     )).parse_next(input)
//! # }
//! #
//! # fn parse_oct_digits<'s>(input: &mut &'s str) -> Result<&'s str> {
//! #     take_while(1.., (
//! #         ('0'..='7'),
//! #     )).parse_next(input)
//! # }
//! #
//! # fn parse_dec_digits<'s>(input: &mut &'s str) -> Result<&'s str> {
//! #     take_while(1.., (
//! #         ('0'..='9'),
//! #     )).parse_next(input)
//! # }
//! #
//! # fn parse_hex_digits<'s>(input: &mut &'s str) -> Result<&'s str> {
//! #     take_while(1.., (
//! #         ('0'..='9'),
//! #         ('A'..='F'),
//! #         ('a'..='f'),
//! #     )).parse_next(input)
//! # }
//!
//! fn main() {
//!     let mut input = "0x1a2b,0x3c4d,0x5e6f Hello";
//!
//!     let digits = take_list.parse_next(&mut input).unwrap();
//!
//!     assert_eq!(input, " Hello");
//!     assert_eq!(digits, "0x1a2b,0x3c4d,0x5e6f");
//!
//!     assert!(parse_digits(&mut "ghiWorld").is_err());
//! }
//! ```
//! See [`combinator`] for more repetition parsers.

#![allow(unused_imports)]
use super::chapter_2;
use super::chapter_3;
use crate::combinator;
use crate::combinator::repeat;
use crate::combinator::separated;
use crate::stream::Accumulate;
use crate::stream::Stream;
use crate::Parser;
use std::collections::HashSet;

pub use super::chapter_4 as previous;
pub use super::chapter_6 as next;
pub use crate::_tutorial as table_of_contents;

Messung V0.5 in Prozent
C=67 H=96 G=82

¤ Dauer der Verarbeitung: 0.18 Sekunden  (vorverarbeitet am  2026-08-25) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.