@@ -5,6 +5,8 @@ use std::collections::{BTreeSet, HashMap, VecDeque};
5
5
use std:: fmt;
6
6
use std:: hash:: Hash ;
7
7
use std:: io:: { self , Write } ;
8
+ use std:: iter;
9
+ use std:: rc:: Rc ;
8
10
use std:: str;
9
11
10
12
#[ derive( Copy , Clone , Debug , PartialEq , Eq , PartialOrd , Ord ) ]
@@ -51,6 +53,10 @@ pub trait GrammarReflector {
51
53
52
54
fn node_shape ( & self , kind : Self :: NodeKind ) -> NodeShape < Self :: NodeKind > ;
53
55
fn node_desc ( & self , kind : Self :: NodeKind ) -> String ;
56
+
57
+ fn choice_by_index ( & self , _kind : Self :: NodeKind , _i : usize ) -> Option < Self :: NodeKind > {
58
+ None
59
+ }
54
60
}
55
61
56
62
#[ derive( Copy , Clone , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
@@ -72,25 +78,25 @@ impl<P: fmt::Debug> fmt::Debug for Node<'_, P> {
72
78
}
73
79
74
80
/// A parse forest, in SPPF (Shared Packed Parse Forest) representation.
75
- pub struct ParseForest < ' i , G : GrammarReflector , I : Input > {
81
+ pub struct ParseForest < ' i , P , G , I : Input > {
76
82
pub grammar : G ,
77
83
// HACK(eddyb) `pub(crate)` only for `parser`.
78
84
pub ( crate ) input : Container < ' i , I :: Container > ,
79
- pub ( crate ) possible_choices : HashMap < Node < ' i , G :: NodeKind > , BTreeSet < G :: NodeKind > > ,
80
- pub ( crate ) possible_splits : HashMap < Node < ' i , G :: NodeKind > , BTreeSet < usize > > ,
85
+ pub ( crate ) possible_choices : HashMap < Node < ' i , P > , BTreeSet < P > > ,
86
+ pub ( crate ) possible_splits : HashMap < Node < ' i , P > , BTreeSet < usize > > ,
81
87
}
82
88
83
89
type_lambda ! {
84
- pub type <' i> ParseForestL <G : GrammarReflector , I : Input > = ParseForest <' i, G , I >;
90
+ pub type <' i> ParseForestL <P , G , I : Input > = ParseForest <' i, P , G , I >;
85
91
pub type <' i> NodeL <P > = Node <' i, P >;
86
92
}
87
93
88
- pub type OwnedParseForestAndNode < G , P , I > = ExistsL < PairL < ParseForestL < G , I > , NodeL < P > > > ;
94
+ pub type OwnedParseForestAndNode < G , P , I > = ExistsL < PairL < ParseForestL < P , G , I > , NodeL < P > > > ;
89
95
90
96
#[ derive( Debug ) ]
91
97
pub struct MoreThanOne ;
92
98
93
- impl < ' i , P , G , I : Input > ParseForest < ' i , G , I >
99
+ impl < ' i , P , G , I : Input > ParseForest < ' i , P , G , I >
94
100
where
95
101
// FIXME(eddyb) these shouldn't be needed, as they are bounds on
96
102
// `GrammarReflector::NodeKind`, but that's ignored currently.
@@ -225,14 +231,17 @@ where
225
231
}
226
232
}
227
233
228
- pub fn dump_graphviz ( & self , out : & mut dyn Write ) -> io:: Result < ( ) > {
234
+ pub fn dump_graphviz ( & self , root : Option < Node < ' i , P > > , out : & mut dyn Write ) -> io:: Result < ( ) > {
229
235
writeln ! ( out, "digraph forest {{" ) ?;
230
- let mut queue: VecDeque < _ > = self
231
- . possible_choices
232
- . keys ( )
233
- . chain ( self . possible_splits . keys ( ) )
234
- . cloned ( )
235
- . collect ( ) ;
236
+ let mut queue: VecDeque < _ > = match root {
237
+ Some ( root) => iter:: once ( root) . collect ( ) ,
238
+ None => self
239
+ . possible_choices
240
+ . keys ( )
241
+ . chain ( self . possible_splits . keys ( ) )
242
+ . cloned ( )
243
+ . collect ( ) ,
244
+ } ;
236
245
let mut seen: BTreeSet < _ > = queue. iter ( ) . cloned ( ) . collect ( ) ;
237
246
let mut p = 0 ;
238
247
let node_name = |Node { kind, range } | {
@@ -293,6 +302,126 @@ where
293
302
}
294
303
}
295
304
305
+ /// Inefficient expansion of a forest, for use when shapes are not statically known.
306
+ // TODO(eddyb) cache these `Rc`s, or maybe even use something better?
307
+ #[ derive( Clone , Debug ) ]
308
+ pub struct DynExpandedTree < ' i , P > {
309
+ pub node : Node < ' i , P > ,
310
+ pub kind : DynExpandedTreeKind < ' i , P > ,
311
+ }
312
+
313
+ #[ derive( Clone , Debug ) ]
314
+ pub enum DynExpandedTreeKind < ' i , P > {
315
+ Leaf ,
316
+ Or ( P , Rc < DynExpandedTree < ' i , P > > ) ,
317
+ Opt ( Option < Rc < DynExpandedTree < ' i , P > > > ) ,
318
+ Concat ( [ Rc < DynExpandedTree < ' i , P > > ; 2 ] ) ,
319
+ }
320
+
321
+ impl < ' i , P > DynExpandedTree < ' i , P >
322
+ // FIXME(eddyb) these shouldn't be needed, as they are bounds on
323
+ // `GrammarReflector::NodeKind`, but that's ignored currently.
324
+ where
325
+ P : fmt:: Debug + Ord + Hash + Copy ,
326
+ {
327
+ pub fn one_from_node < G , I > (
328
+ forest : & ParseForest < ' i , P , G , I > ,
329
+ node : Node < ' i , P > ,
330
+ ) -> Result < Rc < Self > , MoreThanOne >
331
+ where
332
+ G : GrammarReflector < NodeKind = P > ,
333
+ I : Input ,
334
+ {
335
+ let kind = match forest. grammar . node_shape ( node. kind ) {
336
+ NodeShape :: Opaque | NodeShape :: Alias ( _) => DynExpandedTreeKind :: Leaf ,
337
+ NodeShape :: Choice => {
338
+ let child = forest. one_choice ( node) ?;
339
+ DynExpandedTreeKind :: Or ( child. kind , Self :: one_from_node ( forest, child) ?)
340
+ }
341
+ NodeShape :: Opt ( _) => DynExpandedTreeKind :: Opt ( match forest. unpack_opt ( node) {
342
+ Some ( child) => Some ( Self :: one_from_node ( forest, child) ?) ,
343
+ None => None ,
344
+ } ) ,
345
+ NodeShape :: Split ( ..) => {
346
+ let ( left, right) = forest. one_split ( node) ?;
347
+ DynExpandedTreeKind :: Concat ( [
348
+ Self :: one_from_node ( forest, left) ?,
349
+ Self :: one_from_node ( forest, right) ?,
350
+ ] )
351
+ }
352
+ } ;
353
+ Ok ( Rc :: new ( DynExpandedTree { node, kind } ) )
354
+ }
355
+
356
+ pub fn all_from_node < G , I > (
357
+ forest : & ParseForest < ' i , P , G , I > ,
358
+ node : Node < ' i , P > ,
359
+ ) -> Vec < Rc < Self > >
360
+ where
361
+ G : GrammarReflector < NodeKind = P > ,
362
+ I : Input ,
363
+ {
364
+ let new = |kind| Rc :: new ( DynExpandedTree { node, kind } ) ;
365
+ match forest. grammar . node_shape ( node. kind ) {
366
+ NodeShape :: Opaque | NodeShape :: Alias ( _) => vec ! [ new( DynExpandedTreeKind :: Leaf ) ] ,
367
+ NodeShape :: Choice => forest
368
+ . all_choices ( node)
369
+ . flat_map ( |child| {
370
+ Self :: all_from_node ( forest, child)
371
+ . into_iter ( )
372
+ . map ( move |child_tree| new ( DynExpandedTreeKind :: Or ( child. kind , child_tree) ) )
373
+ } )
374
+ . collect ( ) ,
375
+ NodeShape :: Opt ( _) => match forest. unpack_opt ( node) {
376
+ Some ( child) => Self :: all_from_node ( forest, child)
377
+ . into_iter ( )
378
+ . map ( |child_tree| new ( DynExpandedTreeKind :: Opt ( Some ( child_tree) ) ) )
379
+ . collect ( ) ,
380
+ None => vec ! [ new( DynExpandedTreeKind :: Opt ( None ) ) ] ,
381
+ } ,
382
+ NodeShape :: Split ( ..) => forest
383
+ . all_splits ( node)
384
+ . flat_map ( |( left, right) | {
385
+ Self :: all_from_node ( forest, left)
386
+ . into_iter ( )
387
+ . flat_map ( move |left_tree| {
388
+ Self :: all_from_node ( forest, right)
389
+ . into_iter ( )
390
+ . map ( move |right_tree| {
391
+ new ( DynExpandedTreeKind :: Concat ( [
392
+ left_tree. clone ( ) ,
393
+ right_tree,
394
+ ] ) )
395
+ } )
396
+ } )
397
+ } )
398
+ . collect ( ) ,
399
+ }
400
+ }
401
+
402
+ pub fn get < G , I > ( & self , forest : & ParseForest < ' i , P , G , I > , i : usize ) -> Option < Rc < Self > >
403
+ where
404
+ G : GrammarReflector < NodeKind = P > ,
405
+ I : Input ,
406
+ {
407
+ match & self . kind {
408
+ DynExpandedTreeKind :: Leaf => unreachable ! ( ) ,
409
+ DynExpandedTreeKind :: Or ( child, child_tree) => {
410
+ if forest. grammar . choice_by_index ( self . node . kind , i) . unwrap ( ) == * child {
411
+ Some ( child_tree. clone ( ) )
412
+ } else {
413
+ None
414
+ }
415
+ }
416
+ DynExpandedTreeKind :: Opt ( child) => {
417
+ assert_eq ! ( i, 0 ) ;
418
+ child. clone ( )
419
+ }
420
+ DynExpandedTreeKind :: Concat ( children) => Some ( children[ i] . clone ( ) ) ,
421
+ }
422
+ }
423
+ }
424
+
296
425
// FIXME(rust-lang/rust#54175) work around iterator adapter compile-time
297
426
// blowup issues by using a makeshift "non-determinism arrow toolkit".
298
427
pub mod nd {
0 commit comments