Skip to main content

winnow/combinator/
sequence.rs

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