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