cypress/parser/bind.rs
1use crate::{error::Error, parser::*};
2use std::sync::Arc;
3
4/// A parser combinator that applies a transformation function to the result of a parser.
5///
6/// This is useful for mapping parsed values into a new representation,
7/// such as converting a parsed string into an integer, or wrapping a result in a custom enum.
8///
9/// # Type Parameters
10/// - `P`: The inner parser
11/// - `O1`: The output type of the inner parser `P`
12/// - `O2`: The output type after applying the transformation function
13#[derive(Clone)]
14pub struct PBind<P, O1, O2> {
15 p: P,
16 f: Arc<dyn Fn(O1) -> O2>,
17}
18
19/// Constructs a `PBind` parser that applies a function `f` to the result of parser `p`.
20///
21/// This is similar to the `map` or `bind` operation in functional programming.
22///
23/// # Parameters
24/// - `p`: The parser to apply
25/// - `f`: The transformation function that converts the parser’s result
26///
27/// # Returns
28/// A new parser that parses with `p` and transforms its result using `f`.
29///
30/// # Example
31/// ```rust
32/// use cypress::prelude::*;
33///
34/// let input = b"A".into_input();
35/// let parser = just('A').map(|_| 1);
36///
37/// match parser.parse(input) {
38/// Ok(PSuccess { val, rest: _ }) => assert_eq!(val, 1),
39/// Err(_) => assert!(false),
40/// }
41/// ```
42pub fn pbind<P, F, O1, O2>(p: P, f: F) -> PBind<P, O1, O2>
43where
44 F: Fn(O1) -> O2 + 'static,
45{
46 PBind { p, f: Arc::new(f) }
47}
48
49impl<'a, P, K, O1, O2> ParserCore<'a, K, O2> for PBind<P, O1, O2>
50where
51 K: PartialEq + Clone + 'a,
52 O1: Clone + 'a,
53 P: Parser<'a, K, O1>,
54{
55 /// Applies the inner parser, then transforms its result using the function `f`.
56 ///
57 /// If parsing succeeds, the transformation function is applied to the result,
58 /// and the transformed value is returned.
59 ///
60 /// # Errors
61 /// Returns a parse failure if the inner parser `p` fails.
62 fn parse(&self, i: PInput<'a, K>) -> Result<PSuccess<'a, K, O2>, Error<'a, K>> {
63 // Apply the inner parser
64 let PSuccess { val, rest } = self.p.parse(i)?;
65
66 // Transform the result and return
67 Ok(PSuccess {
68 val: (self.f)(val),
69 rest,
70 })
71 }
72}
73
74impl<'a, P, K, O1, O2> Parser<'a, K, O2> for PBind<P, O1, O2>
75where
76 K: PartialEq + Clone + 'a,
77 O1: Clone + 'a,
78 O2: Clone + 'a,
79 P: Parser<'a, K, O1>,
80{
81}