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