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