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/// # 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("preceded", 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("terminated", move |input: &mut I| {
84        let 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("separated_pair", move |input: &mut I| {
126        let o1 = first.parse_next(input)?;
127        let _ = sep.parse_next(input)?;
128        second.parse_next(input).map(|o2| (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("delimited", move |input: &mut I| {
171        let _ = first.parse_next(input)?;
172        let o2 = second.parse_next(input)?;
173        third.parse_next(input).map(|_| o2)
174    })
175}