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