oni_comb_parser/combinator/
recursive.rs1use alloc::boxed::Box;
2use alloc::rc::Rc;
3use core::cell::UnsafeCell;
4
5use crate::fail::PResult;
6use crate::parser::Parser;
7use crate::str_input::StrInput;
8
9struct RecursiveInner<'a, O, E> {
10 inner: UnsafeCell<Option<Box<dyn Parser<StrInput<'a>, Output = O, Error = E> + 'a>>>,
11}
12
13pub struct Recursive<'a, O, E> {
18 shared: Rc<RecursiveInner<'a, O, E>>,
19}
20
21impl<'a, O, E> Clone for Recursive<'a, O, E> {
22 fn clone(&self) -> Self {
23 Recursive {
24 shared: Rc::clone(&self.shared),
25 }
26 }
27}
28
29impl<'a, O, E> Parser<StrInput<'a>> for Recursive<'a, O, E> {
30 type Error = E;
31 type Output = O;
32
33 #[inline]
34 fn parse_next(&mut self, input: &mut StrInput<'a>) -> PResult<O, E> {
35 unsafe {
40 (*self.shared.inner.get())
41 .as_mut()
42 .expect("recursive parser not initialized")
43 .parse_next(input)
44 }
45 }
46}
47
48pub fn recursive<'a, O, E, F, P>(f: F) -> Recursive<'a, O, E>
61where
62 F: FnOnce(Recursive<'a, O, E>) -> P,
63 P: Parser<StrInput<'a>, Output = O, Error = E> + 'a, {
64 let rec = Recursive {
65 shared: Rc::new(RecursiveInner {
66 inner: UnsafeCell::new(None),
67 }),
68 };
69 let parser = f(rec.clone());
70 unsafe {
71 *rec.shared.inner.get() = Some(Box::new(parser));
72 }
73 rec
74}