I use the SNAP (Stacked Nodes Affect Parent) method. I use it for my YAPE modules. The process is rather simple. Make two variables refer to the same reference, and you create an array for stacking.
my $node = my $tree = [];
my @stack;
You never modify
$tree directly -- you do all the manipulation on
$node, and when you need to recurse, you add a new "field" to
$node; then you push the
$node onto the
@stack, and then you set
$node equal to the field:
if ($token eq '(') {
push @{ $node }, [];
push @stack, $node;
$node = $node->[-1]; # the new empty array ref
}
When you return from the recursion, you get the top value from the
@stack:
if ($token eq ')') {
$node = pop @stack;
}
Now,
$node contains what it was before, PLUS any modifications to that empty array reference. And because
$node and
$tree refer to the same data, modifying the data in
$node modifies
$tree.
It's important to realize that saying:
$a = $b = [];
$a = 2;
does not affect
$b in any way. It's the changing of the data referred to by
$a that affects
$b.
Without further ado, here is my implementation of a directory tree structure, using SNAP.
#!/usr/bin/perl -w
use File::Find;
use Data::Dumper;
use strict;
$Data::Dumper::Indent = 1;
build_tree(my $tree, shift);
print Dumper $tree;
{
sub build_tree {
my $node = $_[0] = {};
my @s;
find( sub {
# fixed 'if' => 'while' -- thanks Rudif
$node = (pop @s)->[1] while @s and $File::Find::dir ne $s[-1][0]
+;
return $node->{$_} = -s if -f;
push @s, [ $File::Find::name, $node ];
$node = $node->{$_} = {};
}, $_[1]);
$_[0]{$_[1]} = delete $_[0]{'.'};
}
}
The recursion is not handled by me, it's handled by
find(), so I had to kludge my way into faking the start and end of a recursion. But it works.
japhy --
Perl and Regex Hacker