@@ -130,6 +130,15 @@ impl<P: ?Sized> Recursive<P> {
130130 . expect ( "Recursive parser used before being defined" ) ,
131131 }
132132 }
133+
134+ fn weak ( & self ) -> Self {
135+ Self {
136+ inner : match & self . inner {
137+ RecursiveInner :: Owned ( x) => RecursiveInner :: Unowned ( Rc :: downgrade ( x) ) ,
138+ RecursiveInner :: Unowned ( x) => RecursiveInner :: Unowned ( x. clone ( ) ) ,
139+ } ,
140+ }
141+ }
133142}
134143
135144impl < P : ?Sized > Clone for Recursive < P > {
@@ -239,23 +248,195 @@ where
239248/// ])));
240249/// ```
241250// INFO: Clone bound not actually needed, but good to be safe for future compat
242- pub fn recursive < ' src , ' b , I , O , E , A , F > ( f : F ) -> Recursive < Direct < ' src , ' b , I , O , E > >
251+ pub fn recursive < ' src , ' b , I , O , E , A , F > ( f : F ) -> Recursive < Indirect < ' src , ' b , I , O , E > >
243252where
244253 I : Input < ' src > ,
245254 E : ParserExtra < ' src , I > ,
246255 A : Parser < ' src , I , O , E > + Clone + ' b ,
247- F : FnOnce ( Recursive < Direct < ' src , ' b , I , O , E > > ) -> A ,
256+ F : FnOnce ( Recursive < Indirect < ' src , ' b , I , O , E > > ) -> A ,
257+ {
258+ recursive_fold ( |recursive| ( f ( recursive) , ( ) ) ) . 0
259+ }
260+ /// Construct two mutually recursive parsers (i.e: two parser that may reference each other).
261+ ///
262+ /// The given function must create the parser. The parser must not be used to parse input before this function returns.
263+ ///
264+ /// The output type of this parser is `O1`, the same as the inner parser.
265+ ///
266+ /// # Examples
267+ ///
268+ /// ```
269+ /// # use chumsky::prelude::*;
270+ /// use chumsky::recursive::recursive_2;
271+ /// #[derive(Debug, PartialEq)]
272+ /// enum Tree<'a> {
273+ /// Leaf(&'a str),
274+ /// Branch(Vec<Tree<'a>>),
275+ /// }
276+ ///
277+ /// // Parser that recursively parses nested lists with ordinary or square brackets
278+ /// let tree = recursive_2::<_, _, _, extra::Err<Simple<char>>, _, _, _, _>(|bracket, square| {
279+ /// (choice((bracket.clone()
280+ /// .separated_by(just(','))
281+ /// .collect::<Vec<_>>()
282+ /// .delimited_by(just('('), just(')'))
283+ /// .map(Tree::Branch)
284+ /// .or(text::ascii::ident().map(Tree::Leaf))
285+ /// .padded(), square.clone())),
286+ /// choice((square
287+ /// .separated_by(just(','))
288+ /// .collect::<Vec<_>>()
289+ /// .delimited_by(just('['), just(']'))
290+ /// .map(Tree::Branch)
291+ /// .or(text::ascii::ident().map(Tree::Leaf))
292+ /// .padded(), bracket.clone())))
293+ /// });
294+ ///
295+ /// assert_eq!(tree.parse("hello").into_result(), Ok(Tree::Leaf("hello")));
296+ /// assert_eq!(tree.parse("(a, b, c)").into_result(), Ok(Tree::Branch(vec![
297+ /// Tree::Leaf("a"),
298+ /// Tree::Leaf("b"),
299+ /// Tree::Leaf("c"),
300+ /// ])));
301+ /// // The parser can deal with arbitrarily complex nested lists
302+ /// assert_eq!(tree.parse("[(a, b), c, [d, (e, f)]]").into_result(), Ok(Tree::Branch(vec![
303+ /// Tree::Branch(vec![
304+ /// Tree::Leaf("a"),
305+ /// Tree::Leaf("b"),
306+ /// ]),
307+ /// Tree::Leaf("c"),
308+ /// Tree::Branch(vec![
309+ /// Tree::Leaf("d"),
310+ /// Tree::Branch(vec![
311+ /// Tree::Leaf("e"),
312+ /// Tree::Leaf("f"),
313+ /// ]),
314+ /// ]),
315+ /// ])));
316+ /// // Both sides of the parser can be used
317+ /// assert_eq!(tree.flip().parse("(a, b, c)").into_result(), Ok(Tree::Branch(vec![
318+ /// Tree::Leaf("a"),
319+ /// Tree::Leaf("b"),
320+ /// Tree::Leaf("c"),
321+ /// ])));
322+ /// ```
323+ ///
324+ ///
325+ pub fn recursive_2 < ' src , ' b , I , O1 , O2 , E , A1 , A2 , R , F > (
326+ f : F ,
327+ ) -> EitherParser < Recursive < Indirect < ' src , ' b , I , O1 , E > > , Recursive < Indirect < ' src , ' b , I , O2 , E > > >
328+ where
329+ I : Input < ' src > ,
330+ E : ParserExtra < ' src , I > ,
331+ A1 : Parser < ' src , I , O1 , E > + Clone + ' b ,
332+ A2 : Parser < ' src , I , O2 , E > + Clone + ' b ,
333+ R : Into < EitherParser < A1 , A2 > > ,
334+ F : FnOnce (
335+ Recursive < Indirect < ' src , ' b , I , O1 , E > > ,
336+ Recursive < Indirect < ' src , ' b , I , O2 , E > > ,
337+ ) -> R ,
338+ {
339+ recursive_fold ( |left| recursive_fold ( |right| f ( left, right) . into ( ) . flip ( ) ) . flip ( ) )
340+ }
341+
342+ /// Construct an EitherParser<A1, A2> with A1 recursive and a guarantee that A1 and A2 are dropped together.
343+ /// This function is useful for constructing recursive parser combinators.
344+ ///
345+ /// The given function must create the parser. The parser must not be used to parse input before this function returns.
346+ ///
347+ /// The output type of this parser is `O1`, the same as the left parser.
348+ ///
349+ /// # Examples
350+ ///
351+ /// Please see [recursive] and [recursive_2] for how recursive_fold can be used to define new recursive combinators.
352+ pub fn recursive_fold < ' a , ' b , I , O1 , A1 , A2 , R , F , E > (
353+ f : F ,
354+ ) -> EitherParser < Recursive < Indirect < ' a , ' b , I , O1 , E > > , A2 >
355+ where
356+ I : Input < ' a > ,
357+ E : ParserExtra < ' a , I > ,
358+ A1 : Parser < ' a , I , O1 , E > + Clone + ' b ,
359+ R : Into < EitherParser < A1 , A2 > > ,
360+ F : FnOnce ( Recursive < Indirect < ' a , ' b , I , O1 , E > > ) -> R ,
361+ {
362+ let mut left_parser = Recursive :: declare ( ) ;
363+ let either = f ( left_parser. weak ( ) ) . into ( ) ;
364+ left_parser. define ( either. 0 ) ;
365+ EitherParser ( left_parser, either. 1 )
366+ }
367+
368+ /// A parser that parses using A1 while guaranteeing that A1 and A2 are dropped together.
369+ #[ derive( Clone ) ]
370+ pub struct EitherParser < A1 , A2 > ( A1 , A2 ) ;
371+
372+ impl < A1 , A2 > From < ( A1 , A2 ) > for EitherParser < A1 , A2 > {
373+ fn from ( value : ( A1 , A2 ) ) -> Self {
374+ EitherParser ( value. 0 , value. 1 )
375+ }
376+ }
377+
378+ impl < ' src , I , O , E , A1 , A2 > Parser < ' src , I , O , E > for EitherParser < A1 , A2 >
379+ where
380+ I : Input < ' src > ,
381+ E : ParserExtra < ' src , I > ,
382+ A1 : Parser < ' src , I , O , E > ,
248383{
249- let rc = Rc :: new_cyclic ( |rc| {
250- let rc: rc:: Weak < DynParser < ' src , ' b , I , O , E > > = rc. clone ( ) as _ ;
251- let parser = Recursive {
252- inner : RecursiveInner :: Unowned ( rc. clone ( ) ) ,
253- } ;
384+ fn go < M : Mode > ( & self , inp : & mut InputRef < ' src , ' _ , I , E > ) -> PResult < M , O > {
385+ self . 0 . go :: < M > ( inp)
386+ }
387+
388+ go_extra ! ( O ) ;
389+ }
390+
391+ impl < A1 , A2 > EitherParser < A1 , A2 > {
392+ /// Flip the position of A1 and A2
393+ pub fn flip ( self ) -> EitherParser < A2 , A1 > {
394+ EitherParser ( self . 1 , self . 0 )
395+ }
396+
397+ #[ allow( missing_docs) ]
398+ pub fn left ( & self ) -> & A1 {
399+ & self . 0
400+ }
401+
402+ #[ allow( missing_docs) ]
403+ pub fn right ( & self ) -> & A2 {
404+ & self . 1
405+ }
406+ }
254407
255- f ( parser)
256- } ) ;
408+ #[ cfg( test) ]
409+ mod tests {
410+ use crate :: prelude:: * ;
411+ use crate :: recursive:: { recursive_2, RecursiveInner } ;
412+
413+ #[ test]
414+ fn no_strong_references_after_drop ( ) {
415+ fn check_ref_count < T > ( recursive_inner : & RecursiveInner < T > , expected : usize ) {
416+ match recursive_inner {
417+ RecursiveInner :: Owned ( _) => {
418+ panic ! ( "a user must not have access to strong references" )
419+ }
420+ RecursiveInner :: Unowned ( weak) => {
421+ assert_eq ! ( weak. strong_count( ) , expected) ;
422+ }
423+ } ;
424+ }
425+
426+ let mut smuggle_r1 = None ;
427+ let mut smuggle_r2 = None ;
428+
429+ {
430+ let _ = recursive_2 :: < & str , ( ) , ( ) , extra:: Err < Simple < char > > , _ , _ , _ , _ > ( |r1, r2| {
431+ check_ref_count ( & r1. inner , 1 ) ;
432+ check_ref_count ( & r2. inner , 1 ) ;
433+ smuggle_r1. replace ( r1. clone ( ) ) ;
434+ smuggle_r2. replace ( r2. clone ( ) ) ;
435+ ( r1, r2)
436+ } ) ;
437+ }
257438
258- Recursive {
259- inner : RecursiveInner :: Owned ( rc ) ,
439+ check_ref_count ( & smuggle_r1 . unwrap ( ) . inner , 0 ) ;
440+ check_ref_count ( & smuggle_r2 . unwrap ( ) . inner , 0 ) ;
260441 }
261442}
0 commit comments