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 /// # 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]
rest<I, E: ParserError<I>>(input: &mut I) -> PResult<<I as Stream>::Slice, E> where I: Stream,19 pub fn rest<I, E: ParserError<I>>(input: &mut I) -> PResult<<I as Stream>::Slice, E>
20 where
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]
rest_len<I, E: ParserError<I>>(input: &mut I) -> PResult<usize, E> where I: Stream,41 pub fn rest_len<I, E: ParserError<I>>(input: &mut I) -> PResult<usize, E>
42 where
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 /// ```
opt<I: Stream, O, E: ParserError<I>, F>(mut f: F) -> impl Parser<I, Option<O>, E> where F: Parser<I, O, E>,73 pub fn opt<I: Stream, O, E: ParserError<I>, F>(mut f: F) -> impl Parser<I, Option<O>, E>
74 where
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 /// ```
cond<I, O, E: ParserError<I>, F>(b: bool, mut f: F) -> impl Parser<I, Option<O>, E> where I: Stream, F: Parser<I, O, E>,111 pub fn cond<I, O, E: ParserError<I>, F>(b: bool, mut f: F) -> impl Parser<I, Option<O>, E>
112 where
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")]
peek<I: Stream, O, E: ParserError<I>, F>(mut f: F) -> impl Parser<I, O, E> where F: Parser<I, O, E>,144 pub fn peek<I: Stream, O, E: ParserError<I>, F>(mut f: F) -> impl Parser<I, O, E>
145 where
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")]
eof<I, E: ParserError<I>>(input: &mut I) -> PResult<<I as Stream>::Slice, E> where I: Stream,174 pub fn eof<I, E: ParserError<I>>(input: &mut I) -> PResult<<I as Stream>::Slice, E>
175 where
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 /// ```
not<I: Stream, O, E: ParserError<I>, F>(mut parser: F) -> impl Parser<I, (), E> where F: Parser<I, O, E>,207 pub fn not<I: Stream, O, E: ParserError<I>, F>(mut parser: F) -> impl Parser<I, (), E>
208 where
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 /// ```
cut_err<I, O, E: ParserError<I>, F>(mut parser: F) -> impl Parser<I, O, E> where I: Stream, F: Parser<I, O, E>,280 pub fn cut_err<I, O, E: ParserError<I>, F>(mut parser: F) -> impl Parser<I, O, E>
281 where
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].
backtrack_err<I, O, E: ParserError<I>, F>(mut parser: F) -> impl Parser<I, O, E> where I: Stream, F: Parser<I, O, E>,294 pub fn backtrack_err<I, O, E: ParserError<I>, F>(mut parser: F) -> impl Parser<I, O, E>
295 where
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]
todo<I, O, E>(input: &mut I) -> PResult<O, E> where I: Stream,323 pub fn todo<I, O, E>(input: &mut I) -> PResult<O, E>
324 where
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 /// ```
iterator<I, O, E, F>(input: I, parser: F) -> ParserIterator<F, I, O, E> where F: Parser<I, O, E>, I: Stream, E: ParserError<I>,353 pub fn iterator<I, O, E, F>(input: I, parser: F) -> ParserIterator<F, I, O, E>
354 where
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`].
368 pub struct ParserIterator<F, I, O, E>
369 where
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
379 impl<F, I, O, E> ParserIterator<F, I, O, E>
380 where
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.
finish(mut self) -> PResult<(I, ()), E>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
394 impl<'a, F, I, O, E> core::iter::Iterator for &'a mut ParserIterator<F, I, O, E>
395 where
396 F: Parser<I, O, E>,
397 I: Stream,
398 {
399 type Item = O;
400
next(&mut self) -> Option<Self::Item>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
430 enum 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")]
empty<I: Stream, E: ParserError<I>>(_input: &mut I) -> PResult<(), E>470 pub 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(...)`")]
success<I: Stream, O: Clone, E: ParserError<I>>(val: O) -> impl Parser<I, O, E>476 pub 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")]
fail<I: Stream, O, E: ParserError<I>>(i: &mut I) -> PResult<O, E>496 pub 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 }
502