1 | use crate::error::{ErrMode, ErrorKind, Needed, ParseError}; |
2 | use crate::stream::Stream; |
3 | use crate::trace::trace; |
4 | use crate::*; |
5 | |
6 | /// Return the remaining input. |
7 | /// |
8 | /// # Example |
9 | /// |
10 | /// ```rust |
11 | /// # use winnow::error::ErrorKind; |
12 | /// # use winnow::error::Error; |
13 | /// use winnow::combinator::rest; |
14 | /// assert_eq!(rest::<_,Error<_>>("abc" ), Ok(("" , "abc" ))); |
15 | /// assert_eq!(rest::<_,Error<_>>("" ), Ok(("" , "" ))); |
16 | /// ``` |
17 | #[inline ] |
18 | pub fn rest<I, E: ParseError<I>>(input: I) -> IResult<I, <I as Stream>::Slice, E> |
19 | where |
20 | I: Stream, |
21 | { |
22 | traceimpl Parser::Slice, …>(name:"rest" , parser:move |input: I| { |
23 | Ok(input.next_slice(input.eof_offset())) |
24 | }) |
25 | .parse_next(input) |
26 | } |
27 | |
28 | /// Return the length of the remaining input. |
29 | /// |
30 | /// Note: this does not advance the [`Stream`] |
31 | /// |
32 | /// # Example |
33 | /// |
34 | /// ```rust |
35 | /// # use winnow::error::ErrorKind; |
36 | /// # use winnow::error::Error; |
37 | /// use winnow::combinator::rest_len; |
38 | /// assert_eq!(rest_len::<_,Error<_>>("abc" ), Ok(("abc" , 3))); |
39 | /// assert_eq!(rest_len::<_,Error<_>>("" ), Ok(("" , 0))); |
40 | /// ``` |
41 | #[inline ] |
42 | pub fn rest_len<I, E: ParseError<I>>(input: I) -> IResult<I, usize, E> |
43 | where |
44 | I: Stream, |
45 | { |
46 | traceimpl Parser(name:"rest_len" , parser:move |input: I| { |
47 | let len: usize = input.eof_offset(); |
48 | Ok((input, len)) |
49 | }) |
50 | .parse_next(input) |
51 | } |
52 | |
53 | /// Apply a [`Parser`], producing `None` on [`ErrMode::Backtrack`]. |
54 | /// |
55 | /// To chain an error up, see [`cut_err`]. |
56 | /// |
57 | /// # Example |
58 | /// |
59 | /// ```rust |
60 | /// # use winnow::{error::ErrMode, error::ErrorKind, error::Error}; |
61 | /// # use winnow::prelude::*; |
62 | /// use winnow::combinator::opt; |
63 | /// use winnow::ascii::alpha1; |
64 | /// # fn main() { |
65 | /// |
66 | /// fn parser(i: &str) -> IResult<&str, Option<&str>> { |
67 | /// opt(alpha1).parse_next(i) |
68 | /// } |
69 | /// |
70 | /// assert_eq!(parser("abcd;" ), Ok((";" , Some("abcd" )))); |
71 | /// assert_eq!(parser("123;" ), Ok(("123;" , None))); |
72 | /// # } |
73 | /// ``` |
74 | pub fn opt<I: Stream, O, E: ParseError<I>, F>(mut f: F) -> impl Parser<I, Option<O>, E> |
75 | where |
76 | F: Parser<I, O, E>, |
77 | { |
78 | trace(name:"opt" , parser:move |input: I| { |
79 | let i: I = input.clone(); |
80 | match f.parse_next(input) { |
81 | Ok((i: I, o: O)) => Ok((i, Some(o))), |
82 | Err(ErrMode::Backtrack(_)) => Ok((i, None)), |
83 | Err(e: ErrMode) => Err(e), |
84 | } |
85 | }) |
86 | } |
87 | |
88 | /// Calls the parser if the condition is met. |
89 | /// |
90 | /// # Example |
91 | /// |
92 | /// ```rust |
93 | /// # use winnow::{error::ErrMode, error::{Error, ErrorKind}, IResult}; |
94 | /// # use winnow::prelude::*; |
95 | /// use winnow::combinator::cond; |
96 | /// use winnow::ascii::alpha1; |
97 | /// # fn main() { |
98 | /// |
99 | /// fn parser(b: bool, i: &str) -> IResult<&str, Option<&str>> { |
100 | /// cond(b, alpha1).parse_next(i) |
101 | /// } |
102 | /// |
103 | /// assert_eq!(parser(true, "abcd;" ), Ok((";" , Some("abcd" )))); |
104 | /// assert_eq!(parser(false, "abcd;" ), Ok(("abcd;" , None))); |
105 | /// assert_eq!(parser(true, "123;" ), Err(ErrMode::Backtrack(Error::new("123;" , ErrorKind::Slice)))); |
106 | /// assert_eq!(parser(false, "123;" ), Ok(("123;" , None))); |
107 | /// # } |
108 | /// ``` |
109 | pub fn cond<I, O, E: ParseError<I>, F>(b: bool, mut f: F) -> impl Parser<I, Option<O>, E> |
110 | where |
111 | I: Stream, |
112 | F: Parser<I, O, E>, |
113 | { |
114 | trace(name:"cond" , parser:move |input: I| { |
115 | if b { |
116 | match f.parse_next(input) { |
117 | Ok((i: I, o: O)) => Ok((i, Some(o))), |
118 | Err(e: ErrMode) => Err(e), |
119 | } |
120 | } else { |
121 | Ok((input, None)) |
122 | } |
123 | }) |
124 | } |
125 | |
126 | /// Tries to apply its parser without consuming the input. |
127 | /// |
128 | /// # Example |
129 | /// |
130 | /// ```rust |
131 | /// # use winnow::{error::ErrMode, error::ErrorKind, error::Error, IResult}; |
132 | /// # use winnow::prelude::*; |
133 | /// use winnow::combinator::peek; |
134 | /// use winnow::ascii::alpha1; |
135 | /// # fn main() { |
136 | /// |
137 | /// let mut parser = peek(alpha1); |
138 | /// |
139 | /// assert_eq!(parser.parse_next("abcd;" ), Ok(("abcd;" , "abcd" ))); |
140 | /// assert_eq!(parser.parse_next("123;" ), Err(ErrMode::Backtrack(Error::new("123;" , ErrorKind::Slice)))); |
141 | /// # } |
142 | /// ``` |
143 | #[doc (alias = "look_ahead" )] |
144 | #[doc (alias = "rewind" )] |
145 | pub fn peek<I: Stream, O, E: ParseError<I>, F>(mut f: F) -> impl Parser<I, O, E> |
146 | where |
147 | F: Parser<I, O, E>, |
148 | { |
149 | trace(name:"peek" , parser:move |input: I| { |
150 | let i: I = input.clone(); |
151 | match f.parse_next(input) { |
152 | Ok((_, o: O)) => Ok((i, o)), |
153 | Err(e: ErrMode) => Err(e), |
154 | } |
155 | }) |
156 | } |
157 | |
158 | /// Match the end of the [`Stream`] |
159 | /// |
160 | /// Otherwise, it will error. |
161 | /// |
162 | /// # Example |
163 | /// |
164 | /// ```rust |
165 | /// # use std::str; |
166 | /// # use winnow::{error::ErrMode, error::ErrorKind, error::Error}; |
167 | /// # use winnow::combinator::eof; |
168 | /// # use winnow::prelude::*; |
169 | /// |
170 | /// let mut parser = eof; |
171 | /// assert_eq!(parser.parse_next("abc" ), Err(ErrMode::Backtrack(Error::new("abc" , ErrorKind::Eof)))); |
172 | /// assert_eq!(parser.parse_next("" ), Ok(("" , "" ))); |
173 | /// ``` |
174 | #[doc (alias = "end" )] |
175 | #[doc (alias = "eoi" )] |
176 | pub fn eof<I, E: ParseError<I>>(input: I) -> IResult<I, <I as Stream>::Slice, E> |
177 | where |
178 | I: Stream, |
179 | { |
180 | traceimpl Parser::Slice, …>(name:"eof" , parser:move |input: I| { |
181 | if input.eof_offset() == 0 { |
182 | Ok(input.next_slice(offset:0)) |
183 | } else { |
184 | Err(ErrMode::from_error_kind(input, kind:ErrorKind::Eof)) |
185 | } |
186 | }) |
187 | .parse_next(input) |
188 | } |
189 | |
190 | /// Succeeds if the child parser returns an error. |
191 | /// |
192 | /// **Note:** This does not advance the [`Stream`] |
193 | /// |
194 | /// # Example |
195 | /// |
196 | /// ```rust |
197 | /// # use winnow::{error::ErrMode, error::ErrorKind, error::Error, IResult}; |
198 | /// # use winnow::prelude::*; |
199 | /// use winnow::combinator::not; |
200 | /// use winnow::ascii::alpha1; |
201 | /// # fn main() { |
202 | /// |
203 | /// let mut parser = not(alpha1); |
204 | /// |
205 | /// assert_eq!(parser.parse_next("123" ), Ok(("123" , ()))); |
206 | /// assert_eq!(parser.parse_next("abcd" ), Err(ErrMode::Backtrack(Error::new("abcd" , ErrorKind::Not)))); |
207 | /// # } |
208 | /// ``` |
209 | pub fn not<I: Stream, O, E: ParseError<I>, F>(mut parser: F) -> impl Parser<I, (), E> |
210 | where |
211 | F: Parser<I, O, E>, |
212 | { |
213 | trace(name:"not" , parser:move |input: I| { |
214 | let i: I = input.clone(); |
215 | match parser.parse_next(input) { |
216 | Ok(_) => Err(ErrMode::from_error_kind(input:i, kind:ErrorKind::Not)), |
217 | Err(ErrMode::Backtrack(_)) => Ok((i, ())), |
218 | Err(e: ErrMode) => Err(e), |
219 | } |
220 | }) |
221 | } |
222 | |
223 | /// Transforms an [`ErrMode::Backtrack`] (recoverable) to [`ErrMode::Cut`] (unrecoverable) |
224 | /// |
225 | /// This commits the parse result, preventing alternative branch paths like with |
226 | /// [`winnow::combinator::alt`][crate::combinator::alt]. |
227 | /// |
228 | /// # Example |
229 | /// |
230 | /// Without `cut_err`: |
231 | /// ```rust |
232 | /// # use winnow::{error::ErrMode, error::ErrorKind, error::Error}; |
233 | /// # use winnow::token::one_of; |
234 | /// # use winnow::ascii::digit1; |
235 | /// # use winnow::combinator::rest; |
236 | /// # use winnow::combinator::alt; |
237 | /// # use winnow::combinator::preceded; |
238 | /// # use winnow::prelude::*; |
239 | /// # fn main() { |
240 | /// |
241 | /// fn parser(input: &str) -> IResult<&str, &str> { |
242 | /// alt(( |
243 | /// preceded(one_of("+-" ), digit1), |
244 | /// rest |
245 | /// )).parse_next(input) |
246 | /// } |
247 | /// |
248 | /// assert_eq!(parser("+10 ab" ), Ok((" ab" , "10" ))); |
249 | /// assert_eq!(parser("ab" ), Ok(("" , "ab" ))); |
250 | /// assert_eq!(parser("+" ), Ok(("" , "+" ))); |
251 | /// # } |
252 | /// ``` |
253 | /// |
254 | /// With `cut_err`: |
255 | /// ```rust |
256 | /// # use winnow::{error::ErrMode, error::ErrorKind, error::Error}; |
257 | /// # use winnow::prelude::*; |
258 | /// # use winnow::token::one_of; |
259 | /// # use winnow::ascii::digit1; |
260 | /// # use winnow::combinator::rest; |
261 | /// # use winnow::combinator::alt; |
262 | /// # use winnow::combinator::preceded; |
263 | /// use winnow::combinator::cut_err; |
264 | /// # fn main() { |
265 | /// |
266 | /// fn parser(input: &str) -> IResult<&str, &str> { |
267 | /// alt(( |
268 | /// preceded(one_of("+-" ), cut_err(digit1)), |
269 | /// rest |
270 | /// )).parse_next(input) |
271 | /// } |
272 | /// |
273 | /// assert_eq!(parser("+10 ab" ), Ok((" ab" , "10" ))); |
274 | /// assert_eq!(parser("ab" ), Ok(("" , "ab" ))); |
275 | /// assert_eq!(parser("+" ), Err(ErrMode::Cut(Error { input: "" , kind: ErrorKind::Slice }))); |
276 | /// # } |
277 | /// ``` |
278 | pub fn cut_err<I, O, E: ParseError<I>, F>(mut parser: F) -> impl Parser<I, O, E> |
279 | where |
280 | I: Stream, |
281 | F: Parser<I, O, E>, |
282 | { |
283 | trace(name:"cut_err" , parser:move |input: I| { |
284 | parser.parse_next(input).map_err(|e: ErrMode| e.cut()) |
285 | }) |
286 | } |
287 | |
288 | /// Transforms an [`ErrMode::Cut`] (unrecoverable) to [`ErrMode::Backtrack`] (recoverable) |
289 | /// |
290 | /// This attempts the parse, allowing other parsers to be tried on failure, like with |
291 | /// [`winnow::combinator::alt`][crate::combinator::alt]. |
292 | pub fn backtrack_err<I, O, E: ParseError<I>, F>(mut parser: F) -> impl Parser<I, O, E> |
293 | where |
294 | I: Stream, |
295 | F: Parser<I, O, E>, |
296 | { |
297 | trace(name:"backtrack_err" , parser:move |input: I| { |
298 | parser.parse_next(input).map_err(|e: ErrMode| e.backtrack()) |
299 | }) |
300 | } |
301 | |
302 | /// A placeholder for a not-yet-implemented [`Parser`] |
303 | /// |
304 | /// This is analogous to the [`todo!`] macro and helps with prototyping. |
305 | /// |
306 | /// # Panic |
307 | /// |
308 | /// This will panic when parsing |
309 | /// |
310 | /// # Example |
311 | /// |
312 | /// ```rust |
313 | /// # use winnow::prelude::*; |
314 | /// # use winnow::combinator::todo; |
315 | /// |
316 | /// fn parser(input: &str) -> IResult<&str, u64> { |
317 | /// todo(input) |
318 | /// } |
319 | /// ``` |
320 | #[track_caller ] |
321 | pub fn todo<I, O, E>(input: I) -> IResult<I, O, E> |
322 | where |
323 | I: Stream, |
324 | { |
325 | #![allow (clippy::todo)] |
326 | trace(name:"todo" , parser:move |_input: I| todo!("unimplemented parse" )).parse_next(input) |
327 | } |
328 | |
329 | /// Repeats the embedded parser, lazily returning the results |
330 | /// |
331 | /// Call the iterator's [`ParserIterator::finish`] method to get the remaining input if successful, |
332 | /// or the error value if we encountered an error. |
333 | /// |
334 | /// On [`ErrMode::Backtrack`], iteration will stop. To instead chain an error up, see [`cut_err`]. |
335 | /// |
336 | /// # Example |
337 | /// |
338 | /// ```rust |
339 | /// use winnow::{combinator::iterator, IResult, token::tag, ascii::alpha1, combinator::terminated}; |
340 | /// use std::collections::HashMap; |
341 | /// |
342 | /// let data = "abc|defg|hijkl|mnopqr|123" ; |
343 | /// let mut it = iterator(data, terminated(alpha1, "|" )); |
344 | /// |
345 | /// let parsed = it.map(|v| (v, v.len())).collect::<HashMap<_,_>>(); |
346 | /// let res: IResult<_,_> = it.finish(); |
347 | /// |
348 | /// assert_eq!(parsed, [("abc" , 3usize), ("defg" , 4), ("hijkl" , 5), ("mnopqr" , 6)].iter().cloned().collect()); |
349 | /// assert_eq!(res, Ok(("123" , ()))); |
350 | /// ``` |
351 | pub fn iterator<I, O, E, F>(input: I, parser: F) -> ParserIterator<F, I, O, E> |
352 | where |
353 | F: Parser<I, O, E>, |
354 | I: Stream, |
355 | E: ParseError<I>, |
356 | { |
357 | ParserIterator { |
358 | parser, |
359 | input, |
360 | state: Some(State::Running), |
361 | o: Default::default(), |
362 | } |
363 | } |
364 | |
365 | /// Main structure associated to [`iterator`]. |
366 | pub struct ParserIterator<F, I, O, E> |
367 | where |
368 | F: Parser<I, O, E>, |
369 | I: Stream, |
370 | { |
371 | parser: F, |
372 | input: I, |
373 | state: Option<State<E>>, |
374 | o: core::marker::PhantomData<O>, |
375 | } |
376 | |
377 | impl<F, I, O, E> ParserIterator<F, I, O, E> |
378 | where |
379 | F: Parser<I, O, E>, |
380 | I: Stream, |
381 | { |
382 | /// Returns the remaining input if parsing was successful, or the error if we encountered an error. |
383 | pub fn finish(mut self) -> IResult<I, (), E> { |
384 | match self.state.take().unwrap() { |
385 | State::Running | State::Done => Ok((self.input, ())), |
386 | State::Failure(e: E) => Err(ErrMode::Cut(e)), |
387 | State::Incomplete(i: Needed) => Err(ErrMode::Incomplete(i)), |
388 | } |
389 | } |
390 | } |
391 | |
392 | impl<'a, F, I, O, E> core::iter::Iterator for &'a mut ParserIterator<F, I, O, E> |
393 | where |
394 | F: Parser<I, O, E>, |
395 | I: Stream, |
396 | { |
397 | type Item = O; |
398 | |
399 | fn next(&mut self) -> Option<Self::Item> { |
400 | if let State::Running = self.state.take().unwrap() { |
401 | let input = self.input.clone(); |
402 | |
403 | match self.parser.parse_next(input) { |
404 | Ok((i, o)) => { |
405 | self.input = i; |
406 | self.state = Some(State::Running); |
407 | Some(o) |
408 | } |
409 | Err(ErrMode::Backtrack(_)) => { |
410 | self.state = Some(State::Done); |
411 | None |
412 | } |
413 | Err(ErrMode::Cut(e)) => { |
414 | self.state = Some(State::Failure(e)); |
415 | None |
416 | } |
417 | Err(ErrMode::Incomplete(i)) => { |
418 | self.state = Some(State::Incomplete(i)); |
419 | None |
420 | } |
421 | } |
422 | } else { |
423 | None |
424 | } |
425 | } |
426 | } |
427 | |
428 | enum State<E> { |
429 | Running, |
430 | Done, |
431 | Failure(E), |
432 | Incomplete(Needed), |
433 | } |
434 | |
435 | /// Always succeeds with given value without consuming any input. |
436 | /// |
437 | /// For example, it can be used as the last alternative in `alt` to |
438 | /// specify the default case. |
439 | /// |
440 | /// **Note:** This never advances the [`Stream`] |
441 | /// |
442 | /// # Example |
443 | /// |
444 | /// ```rust |
445 | /// # use winnow::{error::ErrMode, error::ErrorKind, error::Error}; |
446 | /// # use winnow::prelude::*; |
447 | /// use winnow::combinator::alt; |
448 | /// use winnow::combinator::success; |
449 | /// |
450 | /// let mut parser = success::<_,_,Error<_>>(10); |
451 | /// assert_eq!(parser.parse_next("xyz" ), Ok(("xyz" , 10))); |
452 | /// |
453 | /// fn sign(input: &str) -> IResult<&str, isize> { |
454 | /// alt(( |
455 | /// '-' .value(-1), |
456 | /// '+' .value(1), |
457 | /// success::<_,_,Error<_>>(1) |
458 | /// )).parse_next(input) |
459 | /// } |
460 | /// assert_eq!(sign("+10" ), Ok(("10" , 1))); |
461 | /// assert_eq!(sign("-10" ), Ok(("10" , -1))); |
462 | /// assert_eq!(sign("10" ), Ok(("10" , 1))); |
463 | /// ``` |
464 | #[doc (alias = "value" )] |
465 | #[doc (alias = "empty" )] |
466 | pub fn success<I: Stream, O: Clone, E: ParseError<I>>(val: O) -> impl Parser<I, O, E> { |
467 | trace(name:"success" , parser:move |input: I| Ok((input, val.clone()))) |
468 | } |
469 | |
470 | /// A parser which always fails. |
471 | /// |
472 | /// For example, it can be used as the last alternative in `alt` to |
473 | /// control the error message given. |
474 | /// |
475 | /// # Example |
476 | /// |
477 | /// ```rust |
478 | /// # use winnow::{error::ErrMode, error::ErrorKind, error::Error, IResult}; |
479 | /// use winnow::combinator::fail; |
480 | /// |
481 | /// let s = "string" ; |
482 | /// assert_eq!(fail::<_, &str, _>(s), Err(ErrMode::Backtrack(Error::new(s, ErrorKind::Fail)))); |
483 | /// ``` |
484 | #[doc (alias = "unexpected" )] |
485 | pub fn fail<I: Stream, O, E: ParseError<I>>(i: I) -> IResult<I, O, E> { |
486 | trace("fail" , |i| { |
487 | Err(ErrMode::from_error_kind(i, ErrorKind::Fail)) |
488 | }) |
489 | .parse_next(input:i) |
490 | } |
491 | |