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}