sub get_acyclic_sub { my $self = shift; my ($start,$nodelist_ref,$dflabel_ref,$string_ref,$accepting_ref,$lastDFLabel) = @_; my @ret = (); foreach my $adjacent (keys(%{$nodelist_ref->{$start}})) { $lastDFLabel++; if (!exists($dflabel_ref->{$adjacent})) { $dflabel_ref->{$adjacent} = $lastDFLabel; foreach my $symbol (@{$nodelist_ref->{$start}{$adjacent}}) { push(@{$string_ref},$symbol); my $string_clone = dclone($string_ref); my $dflabel_clone = dclone($dflabel_ref); push(@ret,sub { return $self->get_acyclic_sub($adjacent,$nodelist_ref,$dflabel_clone,$string_clone,$accepting_ref,$lastDFLabel); }); pop @{$string_ref}; } } } return {substack=>[@ret], lastDFLabel=>$lastDFLabel, string => ($self->array_is_subset([$start],[@{$accepting_ref}]) ? join('',@{$string_ref}) : undef)}; } sub init_acyclic_iterator { my $self = shift; my %dflabel = (); my @string = (); my $lastDFLabel = 0; my %nodelist = $self->as_node_list(); my @accepting = $self->get_accepting(); # initialize my @substack = (); my $r = $self->get_acyclic_sub($self->get_starting(),\%nodelist,\%dflabel,\@string,\@accepting,$lastDFLabel); push(@substack,@{$r->{substack}}); return sub { while (1) { if (!@substack) { return undef; } my $s = pop @substack; my $r = $s->(); push(@substack,@{$r->{substack}}); if ($r->{string}) { return $r->{string}; } } } } sub new_acyclic_string_generator { my $self = shift; return $self->init_acyclic_iterator(); }