http://www.perlmonks.org?node_id=534671

rg0now has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks!

I have largish data structures, organized into trees, and I have to perform rather complex transformations on this data. When I first encounterd with attribute grammars I immediately fell in love with the concept.

So I installed luqui's Language::AttributeGrammar, wrote a little tree data representation:

#!/usr/bin/perl use strict; use warnings; use Language::AttributeGrammar; package Leaf; sub new{ return bless { value => $_[1] }, 'Leaf'; } package Branch; sub new{ return bless { value => $_[1], _list => undef }, 'Branch'; } sub add_child{ my $self = shift; push @{ $self->{_list} }, @_; return $self; } sub list { if (@_) { bless { head => $_[0], tail => list(@_[1..$#_]) }, 'Cons'; } else { bless {}, 'Nil'; } } sub children{ return list( @{ $_[0]->{_list} }); }
and a simple attribute grammar to count the number of nodes in a tree
package main; my $grammar = new Language::AttributeGrammar <<'EOG'; Branch: $/.len = { 1 + $<children>.len } Leaf: $/.len = { 1 } Cons: $/.len = { $<head>.len + $<tail>.len } Nil: $/.len = { 0 } EOG
and an example
my $tree = Branch->new(3)->add_child( Branch->new(1.1)->add_child( Leaf->new(1), Leaf->new(1.2) ), Branch->new(2.0)->add_child( Leaf->new(2.1), # Leaf->new(2.15), Leaf->new(2.2), ) ); my $result = $grammar->apply($tree, 'len'); print "$result\n";
Everything works like charm as long as the line that is commented out remains commented out. As soon as I add the node back to the tree, I get
Deep recursion on subroutine "Language::AttributeGrammar::Thunk::get" +at (eval 29) line 5.
and the script runs into a seemingly infinite loop. Does anyone have a clue why this happens? I would greatly appreciate any ideas.

Update: sorry I mixed up: it works with 3 leafs, but stops working as soon as I comment out the offending line...

p.s.: if luqui reads this: there is a typo in the SYNOPSIS of Language::AttributeGrammar:

# find the global minimum and propagate it back down the tree ROOT: $/.gmin = { $/.min } Branch: $<left>.gmin = { $/.gmin } | $<right>.gmin) = { $/.gmin } ^ | this is superfluous