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