@@ -73,7 +73,7 @@ impl Item {
7373 let mut used_non_term = vec ! [ false ; grammar. get_non_terminal( ) . len( ) ] ;
7474 let mut non_terminals = Self :: compute_closure_queue ( items, & mut used_non_term) ;
7575
76- let dot_production = Self :: add_initial_sep ( grammar. transitions_to_adj_list ( ) ) ;
76+ let dot_production = Self :: add_initial_sep ( grammar. productions_to_adj_list ( ) ) ;
7777
7878 // apply the closure to all the non terminals in non_terminals
7979 while let Some ( ( non_terminal, letter_first) ) = non_terminals. pop_front ( ) {
@@ -82,14 +82,14 @@ impl Item {
8282 . iter ( )
8383 . for_each ( |rhs| {
8484 // with dot_production, the dot is always at 0, so the first letter is 1
85- if rhs. len ( ) >= 1 {
85+ if rhs. len ( ) >= 2 {
8686 let letter = & rhs[ 1 ] ;
8787
8888 if let Letter :: NonTerminal ( non_term) = letter {
8989 if !used_non_term[ * non_term as usize ] {
9090 used_non_term[ * non_term as usize ] = true ;
9191
92- if rhs. len ( ) >= 2 {
92+ if rhs. len ( ) >= 3 {
9393 non_terminals. push_back ( ( * non_term, Some ( rhs[ 2 ] . clone ( ) ) ) ) ;
9494 } else {
9595 non_terminals. push_back ( ( * non_term, None ) ) ;
@@ -232,6 +232,149 @@ mod tests {
232232
233233 #[ test]
234234 fn closure_0 ( ) {
235+ // S -> (S)
236+ // S -> A
237+ // A -> a
238+ let mut grammar = Grammar :: new (
239+ 0 ,
240+ vec ! [
241+ Production { lhs: 0 , rhs: vec![ Letter :: Terminal ( '(' ) , Letter :: NonTerminal ( 0 ) , Letter :: Terminal ( ')' ) ] } ,
242+ Production { lhs: 0 , rhs: vec![ Letter :: NonTerminal ( 1 ) ] } ,
243+ Production { lhs: 1 , rhs: vec![ Letter :: Terminal ( 'a' ) ] } ,
244+ ] ,
245+ ) ;
246+ grammar. add_fake_initial_state ( ) ;
247+
248+ let mut start_item = set ! [ Item {
249+ production: Production { lhs: 2 , rhs: vec![ Letter :: Terminal ( ITEM_SEP ) , Letter :: NonTerminal ( 0 ) ] } ,
250+ look_ahead: None ,
251+ } ] ;
252+ let closure = Item :: closure ( & mut start_item, & mut grammar) . into_iter ( )
253+ . map ( |item| item. production )
254+ . collect :: < Vec < _ > > ( ) ;
255+
256+ let result = vec ! [
257+ Production { lhs: 2 , rhs: vec![ Letter :: Terminal ( ITEM_SEP ) , Letter :: NonTerminal ( 0 ) ] } ,
258+ Production { lhs: 0 , rhs: vec![ Letter :: Terminal ( ITEM_SEP ) , Letter :: Terminal ( '(' ) , Letter :: NonTerminal ( 0 ) , Letter :: Terminal ( ')' ) ] } ,
259+ Production { lhs: 0 , rhs: vec![ Letter :: Terminal ( ITEM_SEP ) , Letter :: NonTerminal ( 1 ) ] } ,
260+ Production { lhs: 1 , rhs: vec![ Letter :: Terminal ( ITEM_SEP ) , Letter :: Terminal ( 'a' ) ] } ,
261+ ] ;
262+
263+ assert ! ( closure. iter( ) . all( |item| result. contains( item) ) ) ;
264+ assert ! ( result. iter( ) . all( |item| closure. contains( item) ) ) ;
265+ }
266+
267+ #[ test]
268+ fn closure_1 ( ) {
269+ // S -> CC
270+ // C -> cC
271+ // C -> d
272+
273+ let mut grammar = Grammar :: new (
274+ 0 ,
275+ vec ! [
276+ Production { lhs: 0 , rhs: vec![ Letter :: NonTerminal ( 1 ) , Letter :: NonTerminal ( 1 ) ] } ,
277+ Production { lhs: 1 , rhs: vec![ Letter :: Terminal ( 'c' ) , Letter :: NonTerminal ( 1 ) ] } ,
278+ Production { lhs: 1 , rhs: vec![ Letter :: Terminal ( 'd' ) ] } ,
279+ ] ,
280+ ) ;
281+
282+ grammar. add_fake_initial_state ( ) ;
283+
284+ let mut start_item = set ! [ Item {
285+ production: Production { lhs: 2 , rhs: vec![ Letter :: Terminal ( ITEM_SEP ) , Letter :: NonTerminal ( 0 ) ] } ,
286+ look_ahead: Some ( STRING_END ) ,
287+ } ] ;
288+
289+ let closure: Vec < Item > = Item :: closure ( & mut start_item, & mut grammar) . into_iter ( ) . collect ( ) ;
290+
291+ let result = vec ! [
292+ Item {
293+ production: Production { lhs: 2 , rhs: vec![ Letter :: Terminal ( ITEM_SEP ) , Letter :: NonTerminal ( 0 ) ] } ,
294+ look_ahead: Some ( STRING_END ) ,
295+ } ,
296+ Item {
297+ production: Production { lhs: 0 , rhs: vec![ Letter :: Terminal ( ITEM_SEP ) , Letter :: NonTerminal ( 1 ) , Letter :: NonTerminal ( 1 ) ] } ,
298+ look_ahead: Some ( STRING_END ) ,
299+ } ,
300+ Item {
301+ production: Production { lhs: 1 , rhs: vec![ Letter :: Terminal ( ITEM_SEP ) , Letter :: Terminal ( 'c' ) , Letter :: NonTerminal ( 1 ) ] } ,
302+ look_ahead: Some ( 'c' ) ,
303+ } ,
304+ Item {
305+ production: Production { lhs: 1 , rhs: vec![ Letter :: Terminal ( ITEM_SEP ) , Letter :: Terminal ( 'c' ) , Letter :: NonTerminal ( 1 ) ] } ,
306+ look_ahead: Some ( 'd' ) ,
307+ } ,
308+ Item {
309+ production: Production { lhs: 1 , rhs: vec![ Letter :: Terminal ( ITEM_SEP ) , Letter :: Terminal ( 'd' ) ] } ,
310+ look_ahead: Some ( 'c' ) ,
311+ } ,
312+ Item {
313+ production: Production { lhs: 1 , rhs: vec![ Letter :: Terminal ( ITEM_SEP ) , Letter :: Terminal ( 'd' ) ] } ,
314+ look_ahead: Some ( 'd' ) ,
315+ } ,
316+ ] ;
317+
318+ assert ! ( closure. iter( ) . all( |item| result. contains( item) ) ) ;
319+ assert ! ( result. iter( ) . all( |item| closure. contains( item) ) ) ;
320+ }
321+
322+ #[ test]
323+ fn goto ( ) {
324+ // S -> (S)
325+ // S -> ()
326+ let mut grammar = Grammar :: new (
327+ 0 ,
328+ vec ! [
329+ Production { lhs: 0 , rhs: vec![ Letter :: Terminal ( '(' ) , Letter :: NonTerminal ( 0 ) , Letter :: Terminal ( ')' ) ] } ,
330+ Production { lhs: 0 , rhs: vec![ Letter :: Terminal ( '(' ) , Letter :: Terminal ( ')' ) ] } ,
331+ ] ,
332+ ) ;
333+ grammar. add_fake_initial_state ( ) ;
334+
335+ let mut start_item = set ! [ Item {
336+ production: Production { lhs: 1 , rhs: vec![ Letter :: Terminal ( ITEM_SEP ) , Letter :: NonTerminal ( 0 ) ] } ,
337+ look_ahead: None ,
338+ } ] ;
339+
340+ let closure = Item :: closure ( & mut start_item, & mut grammar) ;
341+ let goto = Item :: goto ( & closure, & Letter :: Terminal ( '(' ) ) . into_iter ( )
342+ . map ( |item| item. production )
343+ . collect :: < Vec < _ > > ( ) ;
344+
345+ // result should be
346+ // S -> (.S)
347+ // S -> (.)
348+ let result = vec ! [
349+ Production { lhs: 0 , rhs: vec![ Letter :: Terminal ( '(' ) , Letter :: Terminal ( ITEM_SEP ) , Letter :: NonTerminal ( 0 ) , Letter :: Terminal ( ')' ) ] } ,
350+ Production { lhs: 0 , rhs: vec![ Letter :: Terminal ( '(' ) , Letter :: Terminal ( ITEM_SEP ) , Letter :: Terminal ( ')' ) ] } ,
351+ ] ;
352+
353+ assert ! ( goto. iter( ) . all( |item| result. contains( item) ) ) ;
354+ assert ! ( result. iter( ) . all( |item| goto. contains( item) ) ) ;
355+
356+ // SECOND PART OF TEST, APPLY CLOSURE TO GOTO'S OUTPUT
357+ let mut goto_items = goto. into_iter ( )
358+ . map ( |item| Item {
359+ production : item,
360+ look_ahead : None ,
361+ } )
362+ . collect :: < BTreeSet < _ > > ( ) ;
363+
364+ let closure = Item :: closure ( & mut goto_items, & mut grammar)
365+ . into_iter ( )
366+ . map ( |item| item. production )
367+ . collect :: < Vec < _ > > ( ) ;
368+
369+ let result = vec ! [
370+ Production { lhs: 0 , rhs: vec![ Letter :: Terminal ( '(' ) , Letter :: Terminal ( ITEM_SEP ) , Letter :: NonTerminal ( 0 ) , Letter :: Terminal ( ')' ) ] } ,
371+ Production { lhs: 0 , rhs: vec![ Letter :: Terminal ( '(' ) , Letter :: Terminal ( ITEM_SEP ) , Letter :: Terminal ( ')' ) ] } ,
372+ Production { lhs: 0 , rhs: vec![ Letter :: Terminal ( ITEM_SEP ) , Letter :: Terminal ( '(' ) , Letter :: NonTerminal ( 0 ) , Letter :: Terminal ( ')' ) ] } ,
373+ Production { lhs: 0 , rhs: vec![ Letter :: Terminal ( ITEM_SEP ) , Letter :: Terminal ( '(' ) , Letter :: Terminal ( ')' ) ] } ,
374+ ] ;
375+
376+ assert ! ( closure. iter( ) . all( |item| result. contains( item) ) ) ;
377+ assert ! ( result. iter( ) . all( |item| closure. contains( item) ) ) ;
235378
236379 }
237380}
0 commit comments