winnow/combinator/
core.rs

1use crate::combinator::trace;
2use crate::error::{ErrMode, ErrorKind, Needed, ParserError};
3use crate::stream::Stream;
4use 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]
30pub fn rest<Input, Error>(input: &mut Input) -> PResult<<Input as Stream>::Slice, Error>
31where
32    Input: Stream,
33    Error: ParserError<Input>,
34{
35    trace("rest", 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]
64pub fn rest_len<Input, Error>(input: &mut Input) -> PResult<usize, Error>
65where
66    Input: Stream,
67    Error: ParserError<Input>,
68{
69    trace("rest_len", move |input: &mut Input| {
70        let len = 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/// ```
97pub fn opt<Input: Stream, Output, Error, ParseNext>(
98    mut parser: ParseNext,
99) -> impl Parser<Input, Option<Output>, Error>
100where
101    ParseNext: Parser<Input, Output, Error>,
102    Error: ParserError<Input>,
103{
104    trace("opt", move |input: &mut Input| {
105        let start = input.checkpoint();
106        match parser.parse_next(input) {
107            Ok(o) => Ok(Some(o)),
108            Err(ErrMode::Backtrack(_)) => {
109                input.reset(&start);
110                Ok(None)
111            }
112            Err(e) => 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/// ```
138pub fn cond<Input, Output, Error, ParseNext>(
139    cond: bool,
140    mut parser: ParseNext,
141) -> impl Parser<Input, Option<Output>, Error>
142where
143    Input: Stream,
144    ParseNext: Parser<Input, Output, Error>,
145    Error: ParserError<Input>,
146{
147    trace("cond", move |input: &mut Input| {
148        if cond {
149            parser.parse_next(input).map(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")]
175pub fn peek<Input, Output, Error, ParseNext>(
176    mut parser: ParseNext,
177) -> impl Parser<Input, Output, Error>
178where
179    Input: Stream,
180    Error: ParserError<Input>,
181    ParseNext: Parser<Input, Output, Error>,
182{
183    trace("peek", move |input: &mut Input| {
184        let start = input.checkpoint();
185        let res = 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")]
220pub fn eof<Input, Error>(input: &mut Input) -> PResult<<Input as Stream>::Slice, Error>
221where
222    Input: Stream,
223    Error: ParserError<Input>,
224{
225    trace("eof", move |input: &mut Input| {
226        if input.eof_offset() == 0 {
227            Ok(input.next_slice(0))
228        } else {
229            Err(ErrMode::from_error_kind(input, 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/// ```
254pub fn not<Input, Output, Error, ParseNext>(mut parser: ParseNext) -> impl Parser<Input, (), Error>
255where
256    Input: Stream,
257    Error: ParserError<Input>,
258    ParseNext: Parser<Input, Output, Error>,
259{
260    trace("not", move |input: &mut Input| {
261        let start = input.checkpoint();
262        let res = parser.parse_next(input);
263        input.reset(&start);
264        match res {
265            Ok(_) => Err(ErrMode::from_error_kind(input, ErrorKind::Not)),
266            Err(ErrMode::Backtrack(_)) => Ok(()),
267            Err(e) => 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_7] 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/// ```
329pub fn cut_err<Input, Output, Error, ParseNext>(
330    mut parser: ParseNext,
331) -> impl Parser<Input, Output, Error>
332where
333    Input: Stream,
334    Error: ParserError<Input>,
335    ParseNext: Parser<Input, Output, Error>,
336{
337    trace("cut_err", move |input: &mut Input| {
338        parser.parse_next(input).map_err(|e| 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].
346pub fn backtrack_err<Input, Output, Error, ParseNext>(
347    mut parser: ParseNext,
348) -> impl Parser<Input, Output, Error>
349where
350    Input: Stream,
351    Error: ParserError<Input>,
352    ParseNext: Parser<Input, Output, Error>,
353{
354    trace("backtrack_err", move |input: &mut Input| {
355        parser.parse_next(input).map_err(|e| 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]
378pub fn todo<Input, Output, Error>(input: &mut Input) -> PResult<Output, Error>
379where
380    Input: Stream,
381{
382    #![allow(clippy::todo)]
383    trace("todo", 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/// ```
411pub fn iterator<Input, Output, Error, ParseNext>(
412    input: Input,
413    parser: ParseNext,
414) -> ParserIterator<ParseNext, Input, Output, Error>
415where
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`].
429pub struct ParserIterator<F, I, O, E>
430where
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
440impl<F, I, O, E> ParserIterator<F, I, O, E>
441where
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) => Err(ErrMode::Cut(e)),
450            State::Incomplete(i) => Err(ErrMode::Incomplete(i)),
451        }
452    }
453}
454
455impl<'a, F, I, O, E> core::iter::Iterator for &'a mut ParserIterator<F, I, O, E>
456where
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
491enum 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")]
531pub fn empty<Input, Error>(_input: &mut Input) -> PResult<(), Error>
532where
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")]
555pub fn fail<Input, Output, Error>(i: &mut Input) -> PResult<Output, Error>
556where
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(i)
564}