pcomb/parse.rs
1//! Generic static-dispatch-based parser combinators over slice types.
2//!
3//! For now, see the documentation for the [Parse] trait, which is the main trait of this module.
4// todo: add descriptive module documentation: introduce the idea of the remainder and output
5
6#[cfg(feature = "std")]
7use std::error::Error;
8
9use core::convert::Infallible;
10use core::fmt::{self, Display, Formatter};
11use core::iter::{self, Extend};
12use core::marker::PhantomData;
13use core::mem::{self, MaybeUninit};
14use core::ptr;
15
16use crate::slice::Slice;
17
18
19/// A non-descriptive failure to parse a given input
20#[derive(Debug, PartialEq, Eq, Clone, Hash)]
21pub enum ParseError {
22 /// General rejection: an invalid input has been rejected for an unspecified reason
23 Reject,
24 /// The input is insufficiently short to conclusively determine if it matches
25 Indeterminate, // todo: this is not respected in certain cases
26}
27
28impl Display for ParseError {
29 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
30 match self {
31 ParseError::Reject => write!(f, "Input rejected"),
32 ParseError::Indeterminate => {
33 write!(f, "Insufficent input to conclusively determine validity")
34 },
35 }
36 }
37}
38
39#[cfg(feature = "std")]
40impl Error for ParseError {}
41
42
43/// Tries to parse part of a slice into another form, returning the unparsed
44/// __remainder__ of the slice and the __output__ value, or an error.
45///
46/// This trait is also implemented for all `Fn(T) -> Result<(T, Output), Err>`,
47/// so it's possible to use a function to implement a parser.
48///
49/// # Examples
50/// ```
51/// use pcomb::parse::{Parse, ParseError};
52/// use pcomb::slice::Slice;
53///
54/// fn alpha(input: &str) -> Result<(&str, &str), ParseError> {
55/// let (char, rest) = Slice::split_at(&input, 1).ok_or(ParseError::Reject)?;
56///
57/// if "a" <= char && char <= "z" || "A" <= char && char <= "Z" {
58/// Ok((rest, char))
59/// } else {
60/// Err(ParseError::Reject)
61/// }
62/// }
63///
64/// assert_eq!(alpha.parse("asdf"), Ok(("sdf", "a")));
65/// assert_eq!(alpha.parse("1234"), Err(ParseError::Reject));
66/// ```
67#[must_use = "parsers are lazy and do not do anything until consumed"]
68pub trait Parse<T> {
69 type Output;
70 type Err;
71
72 /// Try to parse part of a slice, returning a tuple of the remainder (the
73 /// unparsed slice) and the output value.
74 fn parse(self, input: T) -> Result<(T, Self::Output), Self::Err>;
75
76
77 /// Maps the output of a parser with a function to produce a new output.
78 ///
79 /// # Examples
80 /// ```
81 /// use pcomb::parse::{Parse, Match, ParseError};
82 /// use pcomb::parsers::str::{alpha, integer};
83 ///
84 /// #[derive(Debug, Clone, PartialEq, Eq)]
85 /// enum Op { Add, Sub, Mul, Div, Int(u32) }
86 /// use Op::*;
87 ///
88 /// let parser = Match("+").map(|_| Add)
89 /// .or(Match("-").map(|_| Sub))
90 /// .or(Match("*").map(|_| Mul))
91 /// .or(Match("/").map(|_| Div))
92 /// .or(integer.map(|num| Int(num)));
93 ///
94 /// assert_eq!(parser.clone().parse("-"), Ok(("", Sub)));
95 /// assert_eq!(parser.clone().parse("24"), Ok(("", Int(24u32))));
96 /// assert_eq!(parser.clone().parse("/"), Ok(("", Div)));
97 /// assert_eq!(parser.clone().parse("*"), Ok(("", Mul)));
98 /// assert_eq!(parser.parse("^"), Err(ParseError::Reject));
99 /// ```
100 fn map<F, O>(self, func: F) -> Map<T, Self, F, O>
101 where F: Fn(Self::Output) -> O, Self: Sized {
102 Map { parser: self, func, _t: PhantomData }
103 }
104
105 // todo: doctest
106 /// Maps the error of a parser with a function to produce a new error.
107 fn map_err<F, E>(self, func: F) -> MapErr<T, Self, F, E>
108 where F: Fn(Self::Err) -> E, Self: Sized {
109 MapErr { parser: self, func, _t: PhantomData }
110 }
111
112 /// Executes the parser if possible, wrapping up the output in an Option.
113 ///
114 /// If you want to provide a default value for None results, see
115 /// [Maybe::unwrap_or].
116 ///
117 /// # Examples
118 /// ```
119 /// use pcomb::parse::{Parse, Match, ParseError};
120 ///
121 /// let parser = Match("http://example.com/index")
122 /// .fuse(Match(".html").maybe());
123 ///
124 /// assert_eq!(
125 /// parser.clone().parse("http://example.com/index"),
126 /// Ok(("", ("http://example.com/index", None)))
127 /// );
128 /// assert_eq!(
129 /// parser.clone().parse("http://example.com/index.html"),
130 /// Ok(("", ("http://example.com/index", Some(".html"))))
131 /// );
132 /// ```
133 fn maybe(self) -> Maybe<T, Self>
134 where T: Clone, Self: Sized {
135 Maybe { parser: self, _t: PhantomData }
136 }
137
138 // todo: doctest
139 /// Parses the output of this parser with an inner parser, and passes the
140 /// output through.
141 fn chain<I>(self, inner: I) -> Chain<T, Self, I>
142 where I: Parse<Self::Output, Err = Self::Err>, Self: Sized {
143 Chain { parser: self, inner_parser: inner, _t: PhantomData }
144 }
145
146 /// Takes the union of both combinators, accepting input which passes either
147 /// parser. Both parsers must output the same type.
148 ///
149 /// This is evaluated lazily: if the input would pass both combinators, the
150 /// first from `self` is used.
151 ///
152 /// # Examples
153 /// ```
154 /// use pcomb::parse::{Parse, Match, ParseError};
155 /// use pcomb::parsers::str::{alpha, integer};
156 ///
157 /// let parser = integer
158 /// .fuse(
159 /// Match("+")
160 /// .or(Match("-"))
161 /// .or(Match("*"))
162 /// .or(Match("/"))
163 /// ) // Output = (u32, &str)
164 /// .fuse(integer); // Output = ((u32, &str), u32)
165 ///
166 /// assert_eq!(parser.clone().parse("54+3"), Ok(("", ((54, "+"), 3))));
167 /// assert_eq!(parser.clone().parse("19/0"), Ok(("", ((19, "/"), 0))));
168 /// assert_eq!(parser.parse("-2"), Err(ParseError::Reject));
169 /// ```
170 fn or<O>(self, other: O) -> Or<T, Self, O>
171 where T: Clone, O: Parse<T, Output = Self::Output, Err = Self::Err>, Self: Sized {
172 Or { left: self, right: other, _t: PhantomData }
173 }
174
175 // todo: doctest
176 /// Takes the conjunction of both combinators, accepting input which passes
177 /// both parsers. The remainders of both combinators must be equal, otherwise
178 /// the specified length error is yielded.
179 ///
180 /// This is evaluated lazily: if the first input does not pass, the other is
181 /// not ran. If you want to ignore the output of one of the parsers, see
182 /// [And::first] or [And::second].
183 fn and<O>(self, length_err: Self::Err, other: O) -> And<T, Self, O>
184 where T: Clone + Eq, O: Parse<T, Err = Self::Err>, Self: Sized {
185 And { left: self, right: other, length_err: length_err, _t: PhantomData }
186 }
187
188 /// Accepts input which passes this parser first and then `other`, packing the
189 /// output as a tuple. The remainder of the input is passed to `other`.
190 ///
191 /// If you want to concatenate the output of both parsers, see
192 /// [Parse::fuse_extend]. If you want to ignore the output of one of the
193 /// parsers, see [Fuse::first] or [Fuse::second].
194 ///
195 /// # Examples
196 /// ```
197 /// use pcomb::parse::{Parse, Match, ParseError};
198 /// use pcomb::parsers::str::{alpha, integer};
199 ///
200 /// let parser = alpha
201 /// .fuse(Match(" = ")) // Fuse's Output = ("x", " = ")
202 /// .first() // now the Output = "x"
203 /// .fuse(integer); // Output = ("x", 2u32)
204 ///
205 /// assert_eq!(parser.parse("x = 2;"), Ok((";", ("x", 2u32))));
206 /// ```
207 fn fuse<O>(self, other: O) -> Fuse<T, Self, O>
208 where O: Parse<T, Err = Self::Err>, Self: Sized, {
209 Fuse { left: self, right: other, _t: PhantomData }
210 }
211
212 /// Accepts input which passes this parser first and then `other`, extending
213 /// this output with `other`'s output. The remainder of the input is passed
214 /// to `other`.
215 ///
216 ///
217 /// # Examples
218 /// ```
219 /// use pcomb::parse::{Parse, Match};
220 ///
221 /// // we want to verify it is an integer but ignore the output
222 /// let parser = Match("hello")
223 /// .map(|out| out.to_owned()) // map to a type that supports Extend
224 /// .fuse_extend(Match(" "))
225 /// .fuse_extend(Match("world"));
226 ///
227 /// assert_eq!(parser.parse("hello world!"), Ok(("!", "hello world".to_owned())));
228 /// ```
229 fn fuse_extend<O>(self, other: O) -> FuseExtend<T, Self, Self::Output, O>
230 where O: Parse<T, Err = Self::Err>, Self::Output: Extend<O::Output>, Self: Sized {
231 FuseExtend { left: self, right: other, _t: PhantomData }
232 }
233
234 /// Accepts exactly a constant amount of repetitions of this parser, packing
235 /// the output as a constant array.
236 ///
237 /// # Examples
238 /// ```
239 /// use pcomb::parse::{Parse, Match, ParseError};
240 /// use pcomb::parsers::str::alpha;
241 ///
242 /// let parser = alpha.repeat_const::<5>();
243 ///
244 /// assert_eq!(
245 /// parser.clone().parse("hello world!"),
246 /// Ok((" world!", ["h", "e", "l", "l", "o"]))
247 /// );
248 /// assert_eq!(parser.clone().parse("hi world"), Err(ParseError::Reject));
249 /// ```
250 fn repeat_const<const N: usize>(self) -> RepeatConst<T, Self, N>
251 where Self: Clone + Sized {
252 RepeatConst { parser: self, _t: PhantomData }
253 }
254
255 /// Accepts any amount of repetitions of this parser, extending the output
256 /// into the given collection.
257 ///
258 /// Default is the default value of the collection, and is what is yielded
259 /// when no repetitions occur.
260 ///
261 /// # Examples
262 /// ```
263 /// use pcomb::parse::{Parse, Match};
264 /// use pcomb::parsers::str::alpha;
265 ///
266 /// let word = alpha.repeat_greedy(String::new()); // a String of consecutive letters
267 /// let words_by_spaces = word.clone() // a Vec of words separated by spaces
268 /// .fuse(Match(" "))
269 /// .first()
270 /// .repeat_greedy(Vec::new());
271 ///
272 /// assert_eq!(
273 /// word.clone().parse("hello world"),
274 /// Ok((" world", "hello".to_owned()))
275 /// );
276 /// assert_eq!(
277 /// words_by_spaces.clone().parse("hello world "),
278 /// Ok(("", vec!["hello".to_owned(), "world".to_owned()]))
279 /// );
280 /// ```
281 fn repeat_greedy<O>(self, default: O) -> RepeatGreedy<T, Self, O>
282 where T: Clone, O: Extend<Self::Output>, Self: Clone + Sized {
283 RepeatGreedy { parser: self, output: default, _t: PhantomData }
284 }
285}
286
287impl<T, F, R, E> Parse<T> for F
288where F: Fn(T) -> Result<(T, R), E> {
289 type Err = E;
290 type Output = R;
291
292 fn parse(self, input: T) -> Result<(T, Self::Output), Self::Err> { self(input) }
293}
294
295
296// todo: doctest
297/// Accepts no input, and produce an empty output.
298///
299/// Empty is infallible: use [Parse::map_err] to specify an error type.
300#[derive(Debug, PartialEq, Eq, Clone, Hash, Default)]
301#[must_use = "parsers are lazy and do not do anything until consumed"]
302pub struct Empty;
303
304impl<T: Slice<Output = T>> Parse<T> for Empty {
305 type Err = Infallible; // convert to never type (!) when stable
306 type Output = T;
307
308 fn parse(self, input: T) -> Result<(T, Self::Output), Self::Err> {
309 Ok(input.split_at(input.len()).expect("slicing from [i..i] from to [..] must never fail"))
310 }
311}
312
313
314// todo: doctest
315/// Accept the entire remainder for any input.
316///
317/// Identity is infallible: use [Parse::map_err] to specify an error type.
318#[derive(Debug, PartialEq, Eq, Clone, Hash, Default)]
319#[must_use = "parsers are lazy and do not do anything until consumed"]
320pub struct Identity;
321
322impl<T: Slice<Output = T>> Parse<T> for Identity {
323 type Err = Infallible; // convert to never type (!) when stable
324 type Output = T;
325
326 fn parse(self, input: T) -> Result<(T, Self::Output), Self::Err> {
327 Ok(input.split_at(0).expect("slicing from [i..i] or from [..] must never fail"))
328 }
329}
330
331
332// todo: doctest
333/// Accepts the slice if the input matches the specified sliced.
334#[derive(Debug, PartialEq, Eq, Clone, Hash)]
335#[must_use = "parsers are lazy and do not do anything until consumed"]
336pub struct Match<T: Slice + Eq>(pub T);
337
338impl<T: Slice<Output = T> + Eq> Parse<T> for Match<T> {
339 type Err = ParseError;
340 type Output = T::Output;
341
342 fn parse(self, input: T) -> Result<(T, Self::Output), Self::Err> {
343 if self.0.len() > input.len() {
344 Err(ParseError::Indeterminate)
345 } else {
346 input
347 .split_at(self.0.len())
348 .filter(|(matched, _)| *matched == self.0)
349 .map(|(matched, rest)| (rest, matched))
350 .ok_or(ParseError::Reject)
351 }
352 }
353}
354
355
356/// The parser for [Parse::map], see method for documentation.
357#[derive(Debug, PartialEq, Eq, Clone, Hash)]
358#[must_use = "parsers are lazy and do not do anything until consumed"]
359pub struct Map<T, P, F, O>
360where P: Parse<T>, F: Fn(P::Output) -> O {
361 parser: P,
362 func: F,
363 _t: PhantomData<T>,
364}
365
366impl<T, P, F, O> Parse<T> for Map<T, P, F, O>
367where P: Parse<T>, F: Fn(P::Output) -> O {
368 type Err = P::Err;
369 type Output = O;
370
371 fn parse(self, input: T) -> Result<(T, Self::Output), Self::Err> {
372 self.parser.parse(input).map(|(rest, output)| {
373 (rest, (self.func)(output))
374 })
375 }
376}
377
378
379/// The parser for [Parse::map_err], see method for documentation.
380#[derive(Debug, PartialEq, Eq, Clone, Hash)]
381#[must_use = "parsers are lazy and do not do anything until consumed"]
382pub struct MapErr<T, P, F, E>
383where P: Parse<T>, F: Fn(P::Err) -> E {
384 parser: P,
385 func: F,
386 _t: PhantomData<T>,
387}
388
389impl<T, P, F, E> Parse<T> for MapErr<T, P, F, E>
390where P: Parse<T>, F: Fn(P::Err) -> E {
391 type Err = E;
392 type Output = P::Output;
393
394 fn parse(self, input: T) -> Result<(T, Self::Output), Self::Err> {
395 self.parser.parse(input).map_err(|err| { (self.func)(err) })
396 }
397}
398
399
400/// The parser for [Parse::maybe], see method for documentation.
401#[derive(Debug, PartialEq, Eq, Clone, Hash)]
402#[must_use = "parsers are lazy and do not do anything until consumed"]
403pub struct Maybe<T, P>
404where T: Clone, P: Parse<T> {
405 parser: P,
406 _t: PhantomData<T>,
407}
408
409impl<T, P> Maybe<T, P>
410where T: Clone, P: Parse<T> {
411 /// Unwraps the inner option if possible, or otherwise the provided default
412 /// value is used.
413 ///
414 /// # Examples
415 /// ```
416 /// use pcomb::parse::{Parse, Match, ParseError};
417 ///
418 /// let parser = Match("http://example.com/index").map(|str| str.to_owned())
419 /// .fuse_extend(Match(".html").maybe().unwrap_or(""));
420 ///
421 /// assert_eq!(
422 /// parser.clone().parse("http://example.com/index"),
423 /// Ok(("", "http://example.com/index".to_owned()))
424 /// );
425 /// assert_eq!(
426 /// parser.parse("http://example.com/index.html"),
427 /// Ok(("", "http://example.com/index.html".to_owned()))
428 /// );
429 /// ```
430 // note: the generic bounds on the impl Fn cannot include Copy + Send + Sync with specialization
431 pub fn unwrap_or(self, default: P::Output) ->
432 Map<T, Self, impl Clone + Fn(Option<P::Output>) -> P::Output, P::Output>
433 where P::Output: Clone {
434 self.map(move |option| option.unwrap_or(default.clone()))
435 }
436}
437
438impl<T, P> Parse<T> for Maybe<T, P>
439where T: Clone, P: Parse<T> {
440 type Err = P::Err;
441 type Output = Option<P::Output>;
442
443 fn parse(self, input: T) -> Result<(T, Self::Output), Self::Err> {
444 match self.parser.parse(input.clone()) {
445 Ok((rest, output)) => Ok((rest, Some(output))),
446 Err(_) => Ok((input, None)),
447 }
448 }
449}
450
451
452/// The parser for [Parse::chain], see method for documentation.
453#[derive(Debug, PartialEq, Eq, Clone, Hash)]
454#[must_use = "parsers are lazy and do not do anything until consumed"]
455pub struct Chain<T, P, I>
456where P: Parse<T>, I: Parse<P::Output, Err = P::Err> {
457 parser: P,
458 inner_parser: I,
459 _t: PhantomData<T>,
460}
461
462impl<T, P, I> Parse<T> for Chain<T, P, I>
463where P: Parse<T>, I: Parse<P::Output, Err = P::Err> + Clone {
464 type Err = P::Err;
465 type Output = I::Output;
466
467 fn parse(self, input: T) -> Result<(T, Self::Output), Self::Err> {
468 let (rest, res) = self.parser
469 .map(|output| self.inner_parser.clone().parse(output))
470 .parse(input)?;
471
472 let (_, output) = res?;
473 Ok((rest, output))
474 }
475}
476
477
478/// The parser for [Parse::or], see method for documentation.
479#[derive(Debug, PartialEq, Eq, Clone, Hash)]
480#[must_use = "parsers are lazy and do not do anything until consumed"]
481pub struct Or<T, L, R>
482where T: Clone, L: Parse<T>, R: Parse<T, Output = L::Output, Err = L::Err> {
483 left: L,
484 right: R,
485 _t: PhantomData<T>,
486}
487
488impl<T, L, R> Parse<T> for Or<T, L, R>
489where T: Clone, L: Parse<T>, R: Parse<T, Output = L::Output, Err = L::Err> {
490 type Err = L::Err;
491 type Output = L::Output;
492
493 fn parse(self, input: T) -> Result<(T, Self::Output), Self::Err> {
494 match self.left.parse(input.clone()) {
495 Ok(res) => Ok(res),
496 Err(_) => self.right.parse(input), // todo: consider handling Indeterminate differently
497 }
498 }
499}
500
501
502/// The parser for [Parse::or], see method for documentation.
503#[derive(Debug, PartialEq, Eq, Clone, Hash)]
504#[must_use = "parsers are lazy and do not do anything until consumed"]
505pub struct And<T, L, R>
506where T: Clone + Eq, L: Parse<T>, R: Parse<T, Err = L::Err> {
507 left: L,
508 right: R,
509 length_err: L::Err,
510 _t: PhantomData<T>,
511}
512
513impl<T, L, R> And<T, L, R>
514where T: Clone + Eq, L: Parse<T>, R: Parse<T, Err = L::Err> {
515 /// Pass through the first parser's output, dropping the output of the second.
516 ///
517 /// Due to the architecture of Parse, it is important to note that both
518 /// parsers are still ran. This is commonly used when the second output of a
519 /// conjunction parser is not desired, such as when checking a precondition.
520 ///
521 /// # Examples
522 /// ```
523 /// use pcomb::parse::{Parse, Match, ParseError};
524 /// use pcomb::parsers::str::integer;
525 ///
526 /// // we want to verify it is an integer but ignore the output
527 /// let parser = Match("420")
528 /// .and(ParseError::Reject, integer::<u32>) // this fuse has Output = ("420", 420)
529 /// .first(); // now Output = "420"
530 ///
531 /// assert_eq!(parser.parse("420.1"), Ok((".1", "420")));
532 /// ```
533 pub fn first(self) -> Map<T, Self, impl Clone + Copy + Send + Sync + Fn((L::Output, R::Output)) -> L::Output, L::Output> {
534 self.map(|(out, _)| out)
535 }
536
537 /// Pass through the second parser's output, dropping the output of the first.
538 ///
539 /// Due to the architecture of Parse, it is important to note that both
540 /// parsers are still ran. This is commonly used when the second output of a
541 /// conjunction parser is not desired, such as when checking a precondition.
542 ///
543 /// # Examples
544 /// ```
545 /// use pcomb::parse::{Parse, Match, ParseError};
546 /// use pcomb::parsers::str::integer;
547 ///
548 /// // we want to verify it is exactly 420 but want it as an integer
549 /// let parser = Match("420")
550 /// .and(ParseError::Reject, integer::<u32>) // this fuse has Output = ("420", 420)
551 /// .second(); // now Output = 420
552 ///
553 /// assert_eq!(parser.parse("420.1"), Ok((".1", 420)));
554 /// ```
555 pub fn second(self) -> Map<T, Self, impl Clone + Copy + Send + Sync + Fn((L::Output, R::Output)) -> R::Output, R::Output> {
556 self.map(|(_, out)| out)
557 }
558}
559
560impl<T, L, R> Parse<T> for And<T, L, R>
561where T: Clone + Eq, L: Parse<T>, R: Parse<T, Err = L::Err> {
562 type Err = L::Err;
563 type Output = (L::Output, R::Output);
564
565 fn parse(self, input: T) -> Result<(T, Self::Output), Self::Err> {
566 let (left_rest, left_output) = self.left.parse(input.clone())?;
567 let (right_rest, right_output) = self.right.parse(input)?;
568
569 if left_rest == right_rest {
570 Ok((left_rest, (left_output, right_output)))
571 } else {
572 Err(self.length_err)
573 }
574 }
575}
576
577
578/// The parser for [Parse::fuse], see method for documentation.
579#[derive(Debug, PartialEq, Eq, Clone, Hash)]
580#[must_use = "parsers are lazy and do not do anything until consumed"]
581pub struct Fuse<T, L, R>
582where L: Parse<T>, R: Parse<T, Err = L::Err> {
583 left: L,
584 right: R,
585 _t: PhantomData<T>,
586}
587
588impl<T, L, R> Fuse<T, L, R>
589where L: Parse<T>, R: Parse<T, Err = L::Err> {
590 /// Pass through the first parser's output, dropping the output of the second.
591 ///
592 /// Due to the architecture of Parse, it is important to note that both
593 /// parsers are still ran. This is commonly used when the second output of a
594 /// fused parser is not desired, such as when parsing delimiters.
595 ///
596 /// # Examples
597 /// ```
598 /// use pcomb::parse::{Parse, Match};
599 ///
600 /// let parser = Match("hello")
601 /// .fuse(Match(" ")) // this fuse has Output = ("hello", " ")
602 /// .first() // now Output = "hello"
603 /// .map(|out: &str| Vec::from([out])) // convert into a Vec and push it
604 /// .fuse_extend(Match("world"));
605 ///
606 /// // notice how the space get excluded
607 /// assert_eq!(parser.parse("hello world!"), Ok(("!", vec!["hello", "world"])));
608 /// ```
609 pub fn first(self) -> Map<T, Self, impl Clone + Copy + Send + Sync + Fn((L::Output, R::Output)) -> L::Output, L::Output> {
610 self.map(|(out, _)| out)
611 }
612
613 /// Pass through the second parser's output, dropping the output of the first.
614 ///
615 /// Due to the architecture of Parse, it is important to note that both
616 /// parsers are still ran. This is commonly used when the first output of a
617 /// fused parser is not desired, such as when parsing delimiters.
618 ///
619 /// # Examples
620 /// ```
621 /// use pcomb::parse::{Parse, Match};
622 /// use pcomb::parsers::str::{alpha, integer};
623 ///
624 /// let parser = Match("let ")
625 /// .fuse(alpha) // this fuse has Output = ("let ", "x")
626 /// .second() // now Output = "x"
627 /// .fuse(Match(" = ")) // Output = ("x", " = ")
628 /// .first() // Output = ("x")
629 /// .fuse(integer::<u32>); // Output = ("x", 4)
630 ///
631 /// assert_eq!(parser.parse("let x = 4;"), Ok((";", ("x", 4))));
632 /// ```
633 pub fn second(self) -> Map<T, Self, impl Clone + Copy + Send + Sync + Fn((L::Output, R::Output)) -> R::Output, R::Output> {
634 self.map(|(_, out)| out)
635 }
636}
637
638impl<T, L, R> Parse<T> for Fuse<T, L, R>
639where L: Parse<T>, R: Parse<T, Err = L::Err> {
640 type Err = L::Err;
641 type Output = (L::Output, R::Output);
642
643 fn parse(self, input: T) -> Result<(T, Self::Output), Self::Err> {
644 let (rest, left_output) = self.left.parse(input)?;
645 let (rest, right_output) = self.right.parse(rest)?;
646 Ok((rest, (left_output, right_output)))
647 }
648}
649
650
651/// The parser for [Parse::fuse_extend], see method for documentation.
652#[derive(Debug, PartialEq, Eq, Clone, Hash)]
653#[must_use = "parsers are lazy and do not do anything until consumed"]
654pub struct FuseExtend<T, L, LO, R>
655where L: Parse<T, Output = LO>, R: Parse<T, Err = L::Err>, LO: Extend<R::Output> {
656 left: L,
657 right: R,
658 _t: PhantomData<T>,
659}
660
661impl<T, L, LO, R> Parse<T> for FuseExtend<T, L, LO, R>
662where L: Parse<T, Output = LO>, R: Parse<T, Err = L::Err>, LO: Extend<R::Output> {
663 type Err = L::Err;
664 type Output = L::Output;
665
666 fn parse(self, input: T) -> Result<(T, Self::Output), Self::Err> {
667 let (rest, (mut left, right)) = self.left.fuse(self.right).parse(input)?;
668 left.extend(iter::once(right));
669 Ok((rest, left))
670 }
671}
672
673
674/// The parser for [Parse::repeat_const], see method for documentation.
675#[derive(Debug, PartialEq, Eq, Clone, Hash)]
676#[must_use = "parsers are lazy and do not do anything until consumed"]
677pub struct RepeatConst<T, P, const N: usize>
678where P: Parse<T> + Clone {
679 parser: P,
680 _t: PhantomData<T>,
681}
682
683impl<T, P, const N: usize> Parse<T> for RepeatConst<T, P, N>
684where P: Parse<T> + Clone {
685 type Err = P::Err;
686 type Output = [P::Output; N];
687
688 fn parse(self, input: T) -> Result<(T, Self::Output), Self::Err> {
689 let mut output: [MaybeUninit<P::Output>; N] = unsafe {
690 MaybeUninit::uninit().assume_init()
691 };
692
693 let mut rest = input;
694
695 for i in 0..N {
696 match self.parser.clone().parse(rest) {
697 Ok((new_rest, new_output)) => {
698 rest = new_rest;
699 output[i].write(new_output);
700 },
701 Err(error) => {
702 // since MaybeUninit doesn't implement Drop, we should drop individual
703 // elements if we are going to return early to avoid not running Drop
704 for item in &mut output[0..i] { // i is exclusive
705 // safety: we have written an element to every index before index i.
706 // since item can only be from before index i, we must of written to
707 // it before.
708 unsafe { ptr::drop_in_place(item.as_mut_ptr()); }
709 }
710
711 return Err(error);
712 }
713 }
714 }
715
716 // safety: at this point the entire array can only be full. We have written
717 // an element to every index. Therefore each element is initialized. Also
718 // MaybeUninit<T> is guaranteed to have the same binary representation as T,
719 // so transmuting from MaybeUninit<T> to T is always sound so long as T is
720 // initialized and valid.
721 // note: this requires transmute_copy because https://github.com/rust-lang/rust/issues/61956
722 let output: [P::Output; N] = unsafe { mem::transmute_copy(&output) };
723 Ok((rest, output))
724 }
725}
726
727
728/// The parser for [Parse::repeat_greedy], see method for documentation.
729#[derive(Debug, PartialEq, Eq, Clone, Hash)]
730#[must_use = "parsers are lazy and do not do anything until consumed"]
731pub struct RepeatGreedy<T, P, O>
732where T: Clone, P: Parse<T> + Clone, O: Extend<P::Output> {
733 parser: P,
734 output: O,
735 _t: PhantomData<T>,
736}
737
738impl<T, P, O> Parse<T> for RepeatGreedy<T, P, O>
739where T: Clone, P: Parse<T> + Clone, O: Extend<P::Output> {
740 type Err = P::Err; // todo: infallible
741 type Output = O;
742
743 fn parse(mut self, input: T) -> Result<(T, Self::Output), Self::Err> {
744 let mut rest = input;
745
746 loop {
747 match self.parser.clone().parse(rest.clone()) {
748 Ok((new_rest, output)) => {
749 rest = new_rest;
750 self.output.extend(iter::once(output));
751 },
752 // todo: consider an adapter which does not drop the error
753 Err(_) => return Ok((rest, self.output)),
754 }
755 }
756 }
757}
758
759
760// todo: RepeatLazy, a repeat with Err?, repeat_at_least, repeat not const
761
762
763// todo: macro docs
764#[macro_export]
765macro_rules! any_of {
766 ($parser1:expr $(, $parser:expr )* $(,)? ) => {
767 {
768 use $crate::parse::Parse;
769
770 $parser1
771 $(
772 .or($parser)
773 )*
774 }
775 };
776}
777
778#[macro_export]
779macro_rules! any_of_match {
780 ( $($parser:expr),* $(,)? ) => {
781 any_of!(
782 $(
783 Match($parser),
784 )*
785 )
786 };
787}
788
789#[macro_export]
790macro_rules! any_of_match_arr {
791 ( $($parser:expr),* $(,)? ) => {
792 any_of!(
793 $(
794 // todo: this is stupid, &[T; N] does not work in certain cases
795 Match(&[$parser][..]),
796 )*
797 )
798 };
799}
800
801
802#[cfg(test)]
803mod test {
804 use super::*;
805
806 #[test]
807 fn slice() {
808 let slice = "asdfghjk";
809 for i in 0..slice.len() + 1 {
810 for j in 0..slice.len() + 1 {
811 assert_eq!(slice.slice(i..j), slice.get(i..j));
812 }
813 }
814 }
815
816 #[test]
817 fn split_at() {
818 let slice = "asdfghjk";
819 assert_eq!(Slice::split_at(&slice, 3), Some(("asd", "fghjk")));
820 }
821
822 #[test]
823 fn match_test() {
824 let val = "asdfg";
825 assert_eq!(val.parse_with(Match("asd")), Ok(("fg", "asd")));
826 }
827
828 #[test]
829 fn any_of() {
830 let parser = any_of!(Match("a"), Match("b"), Match("c").map(|_| "C"));
831 assert_eq!(parser.clone().parse(&"abcde"), Ok(("bcde", "a")));
832 assert_eq!(parser.clone().parse(&"cde"), Ok(("de", "C")));
833 assert_eq!(parser.parse(&"def"), Err(ParseError::Reject));
834 }
835
836 #[test]
837 fn any_of_match() {
838 let parser = any_of_match!("a", "b", "c", "d", "e", "f");
839 assert_eq!(parser.clone().parse("fedcba"), Ok(("edcba", "f")));
840
841 let parser = any_of_match_arr![2i32, 4i32, 6i32, 8i32, 0i32];
842 assert_eq!(parser.parse(&[2i32, 3, 4][..]), Ok((&[3, 4][..], &[2][..])));
843 }
844}