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}