sub
visit_prefix {
my
(
$node
,
$visitor
,
$parent
);
my
$path
;
if
(
ref
(
$_
[0] ) eq
'PATH'
) {
$node
=
$_
[0];
$path
=
$node
->[0];
}
else
{
(
$node
,
$visitor
,
$parent
) = (
shift
,
shift
,
shift
);
}
if
(
ref
(
$node
) eq
'ARRAY'
) {
my
$h
= [];
for
my
$key
( 0 ..
$#$node
) {
my
$res
= visit_prefix(
$node
->[
$key
],
$visitor
,
$parent
,
@_
);
if
(
$res
) {
push
@$h
,
$res
;
}
else
{
push
@$h
,
$node
->[
$key
];
}
}
return
$h
;
}
elsif
(
ref
$node
eq
'HASH'
|| blessed
$node
) {
my
$visited
=
$visitor
->(
$node
,
$parent
,
@_
);
return
$visited
if
defined
$visited
;
my
$h
= {};
for
my
$key
(
sort
keys
%$node
) {
my
$res
;
if
(
$key
ne
'__node_parent__'
) {
$res
=
visit_prefix(
$node
->{
$key
},
$visitor
,
ref
$node
eq
'HASH'
?
$parent
:
$node
,
@_
);
}
if
(
$res
) {
$h
->{
$key
} =
$res
;
}
else
{
$h
->{
$key
} =
$node
->{
$key
};
}
}
bless
$h
,
ref
(
$node
)
unless
ref
(
$node
) eq
'HASH'
;
return
$h
;
}
else
{
return
$node
;
}
}
sub
visit_postfix {
my
(
$node
,
$visitor
,
$parent
) = (
shift
,
shift
,
shift
);
if
(
ref
(
$node
) eq
'ARRAY'
) {
my
$h
= [];
for
my
$key
( 0 ..
$#$node
) {
my
$res
= visit_postfix(
$node
->[
$key
],
$visitor
,
$parent
,
@_
);
if
(
$res
) {
push
@$h
,
$res
;
}
else
{
push
@$h
,
$node
->[
$key
];
}
}
return
$h
;
}
elsif
(
ref
$node
eq
'HASH'
|| blessed
$node
) {
my
$h
= {};
for
my
$key
(
sort
keys
%$node
) {
my
$res
;
if
(
$key
ne
'__node_parent__'
) {
$res
=
visit_postfix(
$node
->{
$key
},
$visitor
,
ref
$node
eq
'HASH'
?
$parent
:
$node
,
@_
);
}
if
(
$res
) {
$h
->{
$key
} =
$res
;
}
else
{
$h
->{
$key
} =
$node
->{
$key
};
}
}
bless
$h
,
ref
(
$node
)
unless
ref
(
$node
) eq
'HASH'
;
my
$res
=
$visitor
->(
$h
,
$parent
,
@_
);
return
$res
if
$res
;
return
$h
;
}
else
{
return
$node
;
}
}
1;