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}