1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use crate::;
use ;
/// A type alias for a reference-counted, mutable, optionally initialized parser.
///
/// This allows creating recursive parsers by holding a reference to a parser
/// that can be set later (after its creation), enabling self-referential parsers.
type ParserRef<'a, K, O> = ;
/// A parser combinator that supports recursive parser definitions.
///
/// `PRecursive` allows you to define parsers that refer to themselves,
/// which is useful for parsing recursive grammars (e.g., expressions, nested structures).
///
/// It works by internally holding a mutable reference to a parser that is
/// initialized later, enabling self-references.
/// Creates a new recursive parser by providing a function `f` that
/// receives a `PRecursive` instance and returns the actual parser implementation.
///
/// # Type Parameters
///
/// * `'a` - Lifetime of the input tokens.
/// * `K` - The token type.
/// * `O` - The output type of the parser.
/// * `F` - A function that takes a recursive parser and returns a boxed parser.
///
/// # Arguments
///
/// * `f` - A function that receives the recursive parser handle and returns
/// a boxed parser that can recursively call itself.
///
/// # Returns
///
/// A `PRecursive` instance implementing `ParserCore`, which supports
/// recursive parsing by delegating to the parser created inside `f`.
///
/// # Example
///
/// ```rust
/// use cypress::prelude::*;
/// let input = b"(1+(2+3))".into_input();
///
/// #[derive(Debug, PartialEq, Clone)]
/// enum AST {
/// Num(u32),
/// Expr(Box<AST>, Box<AST>),
/// }
///
/// let parser = recursive(|expr| {
/// Box::new(choice!(
/// pnum().map(|a: u8| AST::Num((a - b'0').into())),
/// just('(')
/// .then(expr.clone())
/// .then(just('+').then(expr))
/// .then(just(')'))
/// .map(|(((_, lhs), (_, rhs)), _)| AST::Expr(Box::new(lhs), Box::new(rhs)))
/// ))
/// });
///
/// match parser.parse(input) {
/// Ok(PSuccess { val, rest: _ }) => assert_eq!(
/// val,
/// AST::Expr(
/// Box::new(AST::Num(1)),
/// Box::new(AST::Expr(Box::new(AST::Num(2)), Box::new(AST::Num(3))))
/// )
/// ),
/// Err(_) => assert!(false),
/// }
/// ```