Skip to main content

shrimple_parser/
parser.rs

1//! A collection of fundamental parsers to build out your own.
2
3use {
4    crate::{
5        error::{FullParsingError, ParsingError, ParsingResult},
6        input::Input,
7        pattern::{IntoPattern, Pattern},
8        tuple::{Tuple, first, map_second, tuple},
9        utils::PathLike,
10    },
11    std::{
12        convert::Infallible,
13        fmt::{Debug, Display},
14        iter::FusedIterator,
15        marker::PhantomData,
16        mem::replace,
17    },
18};
19
20/// A trait alias for a function that maps from the input & intermediate output to the rest of the
21/// input & a different output.
22///
23/// Used in [`Parser::map`].
24///
25/// See [`match_out`] for a convenient way to create such a mapper.
26pub trait MappingParser<In, Out, NewOut, Reason = Infallible>:
27    Sized + FnMut(In, Out) -> ParsingResult<In, NewOut, Reason>
28{
29}
30
31impl<In, Out, NewOut, Reason, F> MappingParser<In, Out, NewOut, Reason> for F where
32    F: Sized + FnMut(In, Out) -> ParsingResult<In, NewOut, Reason>
33{
34}
35
36/// A trait representing a function that takes some string-like input and
37/// returns either a tuple of (the rest of the input, the output) or a [`ParsingError`].
38pub trait Parser<In: Input, Out, Reason = Infallible>:
39    Sized + FnMut(In) -> ParsingResult<In, Out, Reason>
40{
41    /// Use the parser to produce the output.
42    #[expect(clippy::missing_errors_doc)]
43    fn parse(&mut self, input: In) -> ParsingResult<In, Out, Reason> {
44        self(input)
45    }
46
47    /// Turns output into a recoverable error if the output doesn't meet a condition.
48    fn filter(mut self, mut f: impl FnMut(&Out) -> bool) -> impl Parser<In, Out, Reason> {
49        move |src| match self(src.clone()) {
50            Ok((rest, res)) if f(&res) => Ok((rest, res)),
51            Ok(_) => Err(ParsingError::new_recoverable(src)),
52            Err(err) => Err(err),
53        }
54    }
55
56    /// Like [`Parser::filter`], but the possible error is instead fatal, with `reason`
57    // TODO: better name maybe?
58    fn filter_fatal(
59        mut self,
60        reason: Reason,
61        mut f: impl FnMut(&Out) -> bool,
62    ) -> impl Parser<In, Out, Reason>
63    where
64        Reason: Clone,
65    {
66        move |src| match self(src.clone()) {
67            Ok((rest, res)) if f(&res) => Ok((rest, res)),
68            Ok(_) => Err(ParsingError::new(src, reason.clone())),
69            Err(err) => Err(err),
70        }
71    }
72
73    /// Changes the error reason by passing it through `f`.
74    fn map_reason<NewReason>(
75        mut self,
76        mut f: impl FnMut(Reason) -> NewReason,
77    ) -> impl Parser<In, Out, NewReason> {
78        move |src| self(src).map_err(|e| e.map_reason(&mut f))
79    }
80
81    /// Converts the reason, if present, to another type using the [`From`] trait.
82    fn adapt_reason<NewReason>(mut self) -> impl Parser<In, Out, NewReason>
83    where
84        Infallible: From<Reason>,
85    {
86        move |i| self(i).map_err(ParsingError::adapt_reason)
87    }
88
89    /// Transforms the input & the output of the parser, if present.
90    ///
91    /// The argument is a function that maps the input & the current output of the parser to the
92    /// rest of the input & the new output.
93    ///
94    /// See [`crate::match_out`]
95    fn map<NewOut>(
96        mut self,
97        mut parser: impl MappingParser<In, Out, NewOut, Reason>,
98    ) -> impl Parser<In, NewOut, Reason> {
99        move |src| self(src).and_then(|(i, o)| parser(i, o))
100    }
101
102    /// Like [`Parser::map`], but only maps the current output, if present.
103    fn map_out<NewOut>(
104        mut self,
105        mut f: impl FnMut(Out) -> NewOut,
106    ) -> impl Parser<In, NewOut, Reason> {
107        move |src| self(src).map(map_second(&mut f))
108    }
109
110    /// Tranforms the output of the parser, if present, or try parsing the next value.
111    fn map_until<NewOut>(
112        mut self,
113        mut f: impl FnMut(Out) -> Option<NewOut>,
114    ) -> impl Parser<In, NewOut, Reason> {
115        move |mut src| {
116            let end = src.clone().end();
117            loop {
118                let (rest, value) = self(replace(&mut src, end.clone())).map(map_second(&mut f))?;
119                src = rest;
120                let Some(value) = value else {
121                    continue;
122                };
123                return Ok((src, value));
124            }
125        }
126    }
127
128    /// Like [`Parser::map`], but calls the provdied function using the Nightly [`FnMut::call_mut`]
129    /// method, effectively spreading the output as the arguments of the function.
130    ///
131    /// The following nIghtly Rust code:
132    /// ```ignore
133    /// use shrimple_parser::Parser;
134    /// parser.call(u32::pow)
135    /// ```
136    /// is equivalent to the following stable Rust code:
137    /// ```ignore
138    /// use shrimple_parser::Parser;
139    /// parser.map(|(x, y)| u32::pow(x, y))
140    /// ```
141    /// `T` for this method is constrained not by the [`crate::Tuple`] trait, but by the unstable
142    /// standard trait [`core::marker::Tuple`], which means that `T` can be a tuple of absolutely
143    /// any length.
144    ///
145    /// See also: [`crate::call`], a macro for a stable alternative to this method.
146    #[cfg(feature = "nightly")]
147    fn call<F>(mut self, mut f: F) -> impl Parser<In, F::Output, Reason>
148    where
149        F: FnMut<Out>,
150        Out: core::marker::Tuple,
151    {
152        move |src| self(src).map(map_second(|x| f.call_mut(x)))
153    }
154
155    /// Replaces a recoverable error with the result of `parser`.
156    ///
157    /// The input fed into the second parser is the rest of the input returned by the first parser.
158    ///
159    /// # Warning
160    /// Do not use this in combination with [`Parser::iter`]; Use [`Parser::or_nonempty`]
161    fn or(mut self, mut parser: impl Parser<In, Out, Reason>) -> impl Parser<In, Out, Reason> {
162        move |src| {
163            let fallback = src.clone();
164            match self(src) {
165                Ok(res) => Ok(res),
166                Err(err) if err.is_recoverable() => parser(fallback),
167                Err(err) => Err(err),
168            }
169        }
170    }
171
172    /// Like [`Parser::or`], but keeps the error if the rest of the input is empty.
173    ///
174    /// This allows to avoid slipping into an infinite loop, e.g. when using [`Parser::iter`]
175    /// somewhere down the line.
176    fn or_nonempty(
177        mut self,
178        mut parser: impl Parser<In, Out, Reason>,
179    ) -> impl Parser<In, Out, Reason> {
180        move |src| {
181            let fallback = src.clone();
182            match self(src) {
183                Ok(res) => Ok(res),
184                Err(err) if err.is_recoverable() && !err.rest.is_empty() => parser(fallback),
185                Err(err) => Err(err),
186            }
187        }
188    }
189
190    /// Replaces a recoverable error with the transformed remains of the input.
191    /// If the rest of the input in the recoverable error is already empty, does nothing.
192    /// The returned remains of the input are is an empty string that points to the end of the
193    /// input.
194    fn or_map_rest(mut self, mut f: impl FnMut(In) -> Out) -> impl Parser<In, Out, Reason> {
195        move |src| {
196            let fallback = src.clone();
197            match self(src) {
198                Ok(res) => Ok(res),
199                Err(err) if err.is_recoverable() && !err.rest.is_empty() => {
200                    Ok((fallback.clone().end(), f(fallback)))
201                }
202                Err(err) => Err(err),
203            }
204        }
205    }
206
207    /// Replaces a recoverable error with `value` & the rest of the input in the recoverable error.
208    ///
209    /// Be aware that `value` will be cloned every time it's to be returned.
210    ///
211    /// See [`Parser::or`], [`Parser::or_nonempty`], [`Parser::or_map_rest`].
212    fn or_value(mut self, value: Out) -> impl Parser<In, Out, Reason>
213    where
214        Out: Clone,
215    {
216        move |src| {
217            let fallback = src.clone();
218            match self(src) {
219                Ok(res) => Ok(res),
220                Err(err) if err.is_recoverable() => Ok((fallback, value.clone())),
221                Err(err) => Err(err),
222            }
223        }
224    }
225
226    /// Parses the rest of the input after the first parser, returning both outputs
227    /// & short-circuiting on an error.
228    ///
229    /// The reason for the errors of the first parser is adapted to the one of the second parser.
230    ///
231    /// See also [`Parser::add`], [`Parser::and_value`].
232    fn and<Other>(
233        mut self,
234        mut parser: impl Parser<In, Other, Reason>,
235    ) -> impl Parser<In, (Out, Other), Reason> {
236        move |src| {
237            let (rest, out) = self(src.clone())?;
238            match parser(rest) {
239                Ok((rest, new_out)) => Ok((rest, (out, new_out))),
240                Err(mut err) => {
241                    if err.is_recoverable() {
242                        err.rest = src;
243                    }
244                    Err(err)
245                }
246            }
247        }
248    }
249
250    /// Adds a value to the output of the parser
251    ///
252    /// Be aware that `value` will be cloned every time it's to be returned.
253    ///
254    /// See [`Parser::and`].
255    fn and_value<Other: Clone>(mut self, value: Other) -> impl Parser<In, (Out, Other), Reason> {
256        move |src| {
257            let (rest, out) = self(src)?;
258            Ok((rest, (out, value.clone())))
259        }
260    }
261
262    /// Like [`Parser::and`], but specific to parsers that output a tuple:
263    /// the new output is appended to the tuple of other tuples using the [`Tuple`] trait.
264    fn add<New>(
265        mut self,
266        mut parser: impl Parser<In, New, Reason>,
267    ) -> impl Parser<In, Out::Appended<New>, Reason>
268    where
269        Out: Tuple,
270    {
271        move |src| {
272            let (rest, out) = self(src.clone())?;
273            match parser(rest) {
274                Ok((rest, new_out)) => Ok((rest, out.append(new_out))),
275                Err(mut err) => {
276                    if err.is_recoverable() {
277                        err.rest = src;
278                    }
279                    Err(err)
280                }
281            }
282        }
283    }
284
285    /// Like [`Parser::and_value`], but specific to parsers that output a tuple:
286    /// the new output is appended to the tuple of other tuples using the [`Tuple`] trait.
287    fn add_value<Other: Clone>(
288        mut self,
289        value: Other,
290    ) -> impl Parser<In, Out::Appended<Other>, Reason>
291    where
292        Out: Tuple,
293    {
294        move |src| {
295            let (rest, out) = self(src)?;
296            Ok((rest, out.append(value.clone())))
297        }
298    }
299
300    /// Like [`Parser::and`], but discards the output of the first parser.
301    /// The reason for the errors of the first parser is adapted to the one of the second parser.
302    fn then<NewOut>(
303        mut self,
304        mut parser: impl Parser<In, NewOut, Reason>,
305    ) -> impl Parser<In, NewOut, Reason> {
306        move |src| {
307            let rest = self(src.clone())?.0;
308            parser(rest).map_err(|mut err| {
309                if err.is_recoverable() {
310                    err.rest = src;
311                }
312                err
313            })
314        }
315    }
316
317    /// Same as [`Parser::and`] but discards the output of the second parser.
318    ///
319    /// Effectively, all this function does is advance the input to right after the second parser,
320    /// if it succeeds, otherwise the input stays as if only the first parser was called.
321    fn skip<Skipped>(
322        mut self,
323        mut parser: impl Parser<In, Skipped, Reason>,
324    ) -> impl Parser<In, Out, Reason> {
325        move |src| {
326            let (rest, out) = self(src.clone())?;
327            match parser(rest) {
328                Ok((rest, _)) => Ok((rest, out)),
329                Err(mut err) => {
330                    if err.is_recoverable() {
331                        err.rest = src;
332                    }
333                    Err(err)
334                }
335            }
336        }
337    }
338
339    /// Sets the reason for errors returned from the parser, making all errors fatal.
340    fn expect<NewReason: Clone>(mut self, expected: NewReason) -> impl Parser<In, Out, NewReason> {
341        move |src| self(src).map_err(|e| e.reason(expected.clone()))
342    }
343
344    /// Makes a recoverable error fatal by giving it a reason. If the error is already fatal,
345    /// nothing is changed.
346    fn or_reason(mut self, reason: Reason) -> impl Parser<In, Out, Reason>
347    where
348        Reason: Clone,
349    {
350        move |src| self(src).map_err(|e| e.or_reason(reason.clone()))
351    }
352
353    /// Like [`Parser::or_reason`] but does nothing if the rest of the input is empty.
354    ///
355    /// Be aware that `reason` is cloned every time it's to be returned.
356    fn or_reason_if_nonempty(mut self, reason: Reason) -> impl Parser<In, Out, Reason>
357    where
358        Reason: Clone,
359    {
360        move |src| self(src).map_err(|e| e.or_reason_if_nonempty(reason.clone()))
361    }
362
363    /// Adds the part of the input that was consumed by the parser to the outputs.
364    ///
365    /// If the input increased in length after the parser (which should not happen), an empty
366    /// string is added.
367    /// See also [`Parser::add_span`], which adds the span to the tuple of other outputs.
368    fn and_span(self) -> impl Parser<In, (Out, In), Reason> {
369        self.map_out(tuple).add_span()
370    }
371
372    /// Like [`Parser::and_span`], but adds the output to the tuple of other outputs using the
373    /// [`Tuple`] trait.
374    fn add_span(mut self) -> impl Parser<In, Out::Appended<In>, Reason>
375    where
376        Out: Tuple,
377    {
378        move |src| {
379            let (rest, out) = self(src.clone())?;
380            let end = src.len().saturating_sub(rest.len());
381            let consumed = src.before(end);
382            Ok((rest, out.append(consumed)))
383        }
384    }
385
386    /// Adds a copy of rest of the input to the output.
387    fn and_rest(self) -> impl Parser<In, (Out, In), Reason> {
388        self.map_out(tuple).add_rest()
389    }
390
391    /// Like [`Parser::get_rest`], but adds the input to the tuple of other outputs using the
392    /// [`Tuple`] trait.
393    fn add_rest(mut self) -> impl Parser<In, Out::Appended<In>, Reason>
394    where
395        Out: Tuple,
396    {
397        move |src| self(src).map(|(rest, out)| (rest.clone(), out.append(rest)))
398    }
399
400    /// Replaces a recoverable error with `None`, making the output optional.
401    fn maybe(mut self) -> impl Parser<In, Option<Out>, Reason> {
402        move |src| match self(src) {
403            Ok((rest, out)) => Ok((rest, Some(out))),
404            Err(err) if err.is_recoverable() => Ok((err.rest, None)),
405            Err(err) => Err(err),
406        }
407    }
408
409    /// Replaces the output with `true` and a recoverable error with `false`
410    fn ok(mut self) -> impl Parser<In, bool, Reason> {
411        move |src| match self(src) {
412            Ok((rest, _)) => Ok((rest, true)),
413            Err(err) if err.is_recoverable() => Ok((err.rest, false)),
414            Err(err) => Err(err),
415        }
416    }
417
418    /// Repeats the parser until an error is met, discarding all the output.
419    fn repeat(mut self) -> impl Parser<In, (), Reason> {
420        move |mut src| loop {
421            match self(src) {
422                Ok((rest, _)) => src = rest,
423                Err(err) if err.is_recoverable() => return Ok((err.rest, ())),
424                Err(err) => return Err(err),
425            }
426        }
427    }
428
429    /// Applies the parser repeatedly, collecting the output into a collection, until an error is
430    /// met.
431    fn collect<C: Default + Extend<Out>>(mut self) -> impl Parser<In, C, Reason> {
432        move |mut src| {
433            let mut res = C::default();
434            loop {
435                match self(src) {
436                    Ok((rest, new)) => {
437                        res.extend([new]);
438                        src = rest;
439                    }
440                    Err(err) if err.is_recoverable() => return Ok((err.rest, res)),
441                    Err(err) => return Err(err),
442                }
443            }
444        }
445    }
446
447    /// Prints the output using its `Debug` implementation & the first 16 bytes of the rest of the
448    /// input, all along with a custom provided message.
449    fn dbg(mut self, label: impl Display) -> impl Parser<In, Out, Reason>
450    where
451        In: Input,
452        Out: Debug,
453        Reason: Debug,
454    {
455        move |src| match self(src) {
456            Ok((rest, out)) => {
457                let until = rest.char_indices().nth(16).map_or(rest.len(), |x| x.0);
458                let r = &rest[..until].escape_debug();
459                eprintln!("{label}: Ok({out:?}) : {r}...");
460                Ok((rest, out))
461            }
462            Err(err) => {
463                let until = err
464                    .rest
465                    .char_indices()
466                    .nth(16)
467                    .map_or(err.rest.len(), |x| x.0);
468                let r = &err.rest[..until].escape_debug();
469                eprintln!("{label}: Err({:?}) : {r}...", err.reason);
470                Err(err)
471            }
472        }
473    }
474
475    /// Turns the parser into an iterator that yields output until the first recoverable error.
476    /// If an error is yielded from the iterator, it's guaranteed to be fatal.
477    fn iter(self, input: In) -> Iter<In, Out, Reason, Self> {
478        Iter {
479            input: Some(input),
480            parser: self,
481            _params: PhantomData,
482        }
483    }
484
485    /// Augments the parsing error, if present, with location in the `input`.
486    /// `path` is the reported path to the file where the error occured.
487    /// Note that the `input` passed here is only used for error reporting, not as the input to the
488    /// parser.
489    fn with_full_error<'a>(
490        mut self,
491        path: impl PathLike<'a>,
492        full_src: &'a str,
493    ) -> impl FnOnce(In) -> Result<(In, Out), FullParsingError<'a, Reason>>
494    where
495        In: Input,
496    {
497        move |src| self(src).map_err(|e| e.with_src_loc(path, full_src))
498    }
499}
500
501impl<In, Out, Reason, F> Parser<In, Out, Reason> for F
502where
503    In: Input,
504    F: FnMut(In) -> ParsingResult<In, Out, Reason>,
505{
506}
507
508/// Iterator returned by [`Parser::iter`]
509pub struct Iter<In, Out, Reason, P> {
510    input: Option<In>,
511    parser: P,
512    _params: PhantomData<(Out, Reason)>,
513}
514
515impl<In, Out, Reason, P> Iterator for Iter<In, Out, Reason, P>
516where
517    In: Input,
518    P: Parser<In, Out, Reason>,
519{
520    type Item = Result<Out, ParsingError<In, Reason>>;
521
522    fn next(&mut self) -> Option<Self::Item> {
523        let input = self.input.take()?;
524        match (self.parser)(input) {
525            Ok((rest, res)) => {
526                self.input = Some(rest);
527                Some(Ok(res))
528            }
529            Err(err) if err.is_recoverable() => None,
530            Err(err) => Some(Err(err)),
531        }
532    }
533}
534
535impl<In, Out, Reason, P> FusedIterator for Iter<In, Out, Reason, P>
536where
537    In: Input,
538    P: Parser<In, Out, Reason>,
539{
540}
541
542impl<In, Out, Reason, P> Iter<In, Out, Reason, P>
543where
544    In: Input,
545    P: Parser<In, Out, Reason>,
546{
547    /// Returned the part of the input that hasn't been processed by the parser yet.
548    pub const fn remainder(&self) -> Option<&In> {
549        self.input.as_ref()
550    }
551}
552
553/// Returns a parser that always returns the provided value.
554///
555/// Beware that the value is always cloned.
556pub fn ready<In: Input, T: Clone, Reason>(value: T) -> impl Parser<In, T, Reason> {
557    move |i| Ok((i, value.clone()))
558}
559
560/// Parses 1 instance of pattern `pat`.
561///
562/// # Errors
563/// The returned parser returns a recoverable error if the pattern didn't match at the beginning of
564/// the input.
565pub fn one<In: Input, Reason>(pat: impl IntoPattern) -> impl Parser<In, In, Reason> {
566    let pat = pat.into_pattern();
567    move |input| {
568        pat.immediate_match(input)
569            .map_err(ParsingError::new_recoverable)
570    }
571}
572
573/// Parses contiguous instances of pattern `pat`.
574///
575/// The returned parser never returns an error, if no matches are found at the start of the input,
576/// the returned string is empty (but also points to the start of the input)
577///
578/// See also [`until`], [`until_ex`].
579pub fn many<In: Input, Reason>(pat: impl IntoPattern) -> impl Parser<In, In, Reason> {
580    let pat = pat.into_pattern();
581    move |input| Ok(pat.immediate_matches(input))
582}
583
584/// Parses a span of the input until a match of pattern `pat` is met.
585///
586/// The returned rest of the input will still have the match.
587///
588/// The returned parser never returns an error, if `pred` returns `false` for all the characters
589/// in the input, then the output is the entire input, and the rest of the input is an empty string.
590///
591/// See also [`many`], [`until_ex`].
592pub fn until<In: Input, Reason>(pat: impl IntoPattern) -> impl Parser<In, In, Reason> {
593    let pat = pat.into_pattern();
594    move |input| {
595        let input_len = input.len();
596        Ok({
597            pat.first_match(input)
598                .map_or_else(|input| input.split_at(input_len).rev(), map_second(first))
599        })
600    }
601}
602
603/// Like [`until`], but also removes the match of `pat` from the rest of the input.
604///
605/// # Errors
606/// Unlike [`until`], this parser returns a recoverable error if `pred` returned `false` for
607/// all the characters in the input.
608pub fn until_ex<In: Input, Reason>(pat: impl IntoPattern) -> impl Parser<In, In, Reason> {
609    let pat = pat.into_pattern();
610    move |input| {
611        pat.first_match_ex(input)
612            .map(map_second(first))
613            .map_err(ParsingError::new_recoverable)
614    }
615}
616
617/// Parse a balanced group of `open` & `close` patterns.
618///
619/// The start & end of the group are <u>included</u> in the output.
620/// See [`group_ex`] for a parser that excludes them.
621///
622/// # Errors
623/// - If no initial `open` was found, a recoverable error is returned.
624/// - If the end was reached before a matching `close` pattern, a fatal error is returned.
625///
626/// An example use of this is parsing balanced parentheses:
627/// ```rust
628/// # fn main() {
629/// use shrimple_parser::{parser::group, ParsingError};
630/// let src = "(foo ()) bar";
631/// assert_eq!(group('(', ')')(src), Ok((" bar", "(foo ())")));
632///
633/// let src = "(oops";
634/// assert_eq!(group('(', ')')(src), Err(ParsingError::new("oops", ())));
635/// # }
636/// ```
637pub fn group<In: Input>(open: impl IntoPattern, close: impl Pattern) -> impl Parser<In, In, ()> {
638    let open = open.into_pattern();
639    let close = close.into_pattern();
640    move |input| {
641        let Ok((mut rest, _)) = open.immediate_match(&*input) else {
642            return Err(ParsingError::new_recoverable(input));
643        };
644        let mut nesting = 1;
645        while nesting > 0 {
646            let (after_open, (before_open, open)) =
647                open.first_match_ex(rest).unwrap_or(("", (rest, "")));
648            let (after_close, (before_close, close)) =
649                close.first_match_ex(rest).unwrap_or(("", (rest, "")));
650
651            if [open, close] == ["", ""] {
652                // neither `open` nor `close` matched, and nesting > 0
653                let rest_start = input.len() - rest.len();
654                return Err(ParsingError::new(input.after(rest_start), ()));
655            }
656
657            if before_open.len() < before_close.len() {
658                rest = after_open;
659                nesting += 1;
660            } else {
661                rest = after_close;
662                nesting -= 1;
663            }
664        }
665
666        let res_len = input.len() - rest.len();
667        Ok(input.split_at(res_len).rev())
668    }
669}
670
671/// Parse a balanced group of `open` & `close` patterns.
672///
673/// The start & end of the group are <u>excluded</u> in the output.
674/// See [`group`] for a parser that includes them.
675///
676/// # Errors
677/// - If no initial `open` was found, a recoverable error is returned.
678/// - If the end was reached before a matching `close` pattern, a fatal error is returned.
679///
680/// An example use of this is parsing balanced parentheses:
681/// ```rust
682/// # fn main() {
683/// use shrimple_parser::{parser::group_ex, ParsingError};
684/// let src = "(foo ()) bar";
685/// assert_eq!(group_ex('(', ')')(src), Ok((" bar", "foo ()")));
686///
687/// let src = "(oops";
688/// assert_eq!(group_ex('(', ')')(src), Err(ParsingError::new("oops", ())));
689/// # }
690/// ```
691pub fn group_ex<In: Input>(
692    open: impl IntoPattern,
693    close: impl IntoPattern,
694) -> impl Parser<In, In, ()> {
695    let open = open.into_pattern();
696    let close = close.into_pattern();
697
698    move |input| {
699        let input = match open.immediate_match(input) {
700            Ok((rest, _)) => rest,
701            Err(input) => return Err(ParsingError::new_recoverable(input)),
702        };
703        let mut rest = &*input;
704        let mut nesting = 1;
705        let mut close_len = 0;
706        while nesting > 0 {
707            let (after_open, (before_open, open)) =
708                open.first_match_ex(rest).unwrap_or(("", (rest, "")));
709            let (after_close, (before_close, close)) =
710                close.first_match_ex(rest).unwrap_or(("", (rest, "")));
711
712            if [open, close] == ["", ""] {
713                // neither `open` nor `close` matched, and nesting > 0
714                let rest_start = input.len() - rest.len();
715                return Err(ParsingError::new(input.after(rest_start), ()));
716            }
717
718            if before_open.len() < before_close.len() {
719                rest = after_open;
720                nesting += 1;
721            } else {
722                rest = after_close;
723                close_len = close.len();
724                nesting -= 1;
725            }
726        }
727
728        let res_len = input.len() - rest.len() - close_len;
729        Ok(input
730            .split_at(res_len)
731            .map_second(|rest| rest.after(close_len))
732            .rev())
733    }
734}