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