Skip to main content

winnow/combinator/
sequence.rs

1use crate::combinator::trace;
2use crate::error::ParserError;
3use crate::stream::Stream;
4use crate::Parser;
5
6/// Sequence two parsers, only returning the output from the second.
7///
8/// See also [`seq`][crate::combinator::seq] to generalize this across any number of fields.
9///
10/// # Example
11///
12/// ```rust
13/// # use winnow::{error::ErrMode, error::Needed};
14/// # use winnow::prelude::*;
15/// # use winnow::error::Needed::Size;
16/// use winnow::combinator::preceded;
17///
18/// fn parser<'i>(input: &mut &'i str) -> ModalResult<&'i str> {
19///     preceded("abc", "efg").parse_next(input)
20/// }
21///
22/// assert_eq!(parser.parse_peek("abcefg"), Ok(("", "efg")));
23/// assert_eq!(parser.parse_peek("abcefghij"), Ok(("hij", "efg")));
24/// assert!(parser.parse_peek("").is_err());
25/// assert!(parser.parse_peek("123").is_err());
26/// ```
27#[doc(alias = "ignore_then")]
28pub fn preceded<Input, Ignored, Output, Error, IgnoredParser, ParseNext>(
29    mut ignored: IgnoredParser,
30    mut parser: ParseNext,
31) -> impl Parser<Input, Output, Error>
32where
33    Input: Stream,
34    Error: ParserError<Input>,
35    IgnoredParser: Parser<Input, Ignored, Error>,
36    ParseNext: Parser<Input, Output, Error>,
37{
38    trace("preceded", move |input: &mut Input| {
39        let _ = ignored.parse_next(input)?;
40        parser.parse_next(input)
41    })
42}
43
44/// Sequence two parsers, only returning the output of the first.
45///
46/// See also [`seq`][crate::combinator::seq] to generalize this across any number of fields.
47///
48/// # Example
49///
50/// ```rust
51/// # use winnow::{error::ErrMode, error::Needed};
52/// # use winnow::prelude::*;
53/// # use winnow::error::Needed::Size;
54/// use winnow::combinator::terminated;
55///
56/// fn parser<'i>(input: &mut &'i str) -> ModalResult<&'i str> {
57///     terminated("abc", "efg").parse_next(input)
58/// }
59///
60/// assert_eq!(parser.parse_peek("abcefg"), Ok(("", "abc")));
61/// assert_eq!(parser.parse_peek("abcefghij"), Ok(("hij", "abc")));
62/// assert!(parser.parse_peek("").is_err());
63/// assert!(parser.parse_peek("123").is_err());
64/// ```
65#[doc(alias = "then_ignore")]
66pub fn terminated<Input, Output, Ignored, Error, ParseNext, IgnoredParser>(
67    mut parser: ParseNext,
68    mut ignored: IgnoredParser,
69) -> impl Parser<Input, Output, Error>
70where
71    Input: Stream,
72    Error: ParserError<Input>,
73    ParseNext: Parser<Input, Output, Error>,
74    IgnoredParser: Parser<Input, Ignored, Error>,
75{
76    trace("terminated", move |input: &mut Input| {
77        let o = parser.parse_next(input)?;
78        ignored.parse_next(input).map(|_| o)
79    })
80}
81
82/// Sequence three parsers, only returning the values of the first and third.
83///
84/// See also [`seq`][crate::combinator::seq] to generalize this across any number of fields.
85///
86/// # Example
87///
88/// ```rust
89/// # use winnow::{error::ErrMode, error::Needed};
90/// # use winnow::error::Needed::Size;
91/// # use winnow::prelude::*;
92/// use winnow::combinator::separated_pair;
93///
94/// fn parser<'i>(input: &mut &'i str) -> ModalResult<(&'i str, &'i str)> {
95///     separated_pair("abc", "|", "efg").parse_next(input)
96/// }
97///
98/// assert_eq!(parser.parse_peek("abc|efg"), Ok(("", ("abc", "efg"))));
99/// assert_eq!(parser.parse_peek("abc|efghij"), Ok(("hij", ("abc", "efg"))));
100/// assert!(parser.parse_peek("").is_err());
101/// assert!(parser.parse_peek("123").is_err());
102/// ```
103pub fn separated_pair<Input, O1, Sep, O2, Error, P1, SepParser, P2>(
104    mut first: P1,
105    mut sep: SepParser,
106    mut second: P2,
107) -> impl Parser<Input, (O1, O2), Error>
108where
109    Input: Stream,
110    Error: ParserError<Input>,
111    P1: Parser<Input, O1, Error>,
112    SepParser: Parser<Input, Sep, Error>,
113    P2: Parser<Input, O2, Error>,
114{
115    trace("separated_pair", move |input: &mut Input| {
116        let o1 = first.parse_next(input)?;
117        let _ = sep.parse_next(input)?;
118        second.parse_next(input).map(|o2| (o1, o2))
119    })
120}
121
122/// Sequence three parsers, only returning the output of the second.
123///
124/// See also [`seq`][crate::combinator::seq] to generalize this across any number of fields.
125///
126/// # Example
127///
128/// ```rust
129/// # use winnow::{error::ErrMode, error::Needed};
130/// # use winnow::error::Needed::Size;
131/// # use winnow::prelude::*;
132/// use winnow::combinator::delimited;
133///
134/// fn parser<'i>(input: &mut &'i str) -> ModalResult<&'i str> {
135///     delimited("(", "abc", ")").parse_next(input)
136/// }
137///
138/// assert_eq!(parser.parse_peek("(abc)"), Ok(("", "abc")));
139/// assert_eq!(parser.parse_peek("(abc)def"), Ok(("def", "abc")));
140/// assert!(parser.parse_peek("").is_err());
141/// assert!(parser.parse_peek("123").is_err());
142/// ```
143#[doc(alias = "between")]
144#[doc(alias = "padded")]
145pub fn delimited<
146    Input,
147    Ignored1,
148    Output,
149    Ignored2,
150    Error,
151    IgnoredParser1,
152    ParseNext,
153    IgnoredParser2,
154>(
155    mut ignored1: IgnoredParser1,
156    mut parser: ParseNext,
157    mut ignored2: IgnoredParser2,
158) -> impl Parser<Input, Output, Error>
159where
160    Input: Stream,
161    Error: ParserError<Input>,
162    IgnoredParser1: Parser<Input, Ignored1, Error>,
163    ParseNext: Parser<Input, Output, Error>,
164    IgnoredParser2: Parser<Input, Ignored2, Error>,
165{
166    trace("delimited", move |input: &mut Input| {
167        let _ = ignored1.parse_next(input)?;
168        let o2 = parser.parse_next(input)?;
169        ignored2.parse_next(input).map(|_| o2)
170    })
171}