my $root = {}; my $node = $root; my @stack; while () { chomp; if (/^\s*BEGIN\s+(.*)/) { my $child = {}; $child->{_type} = $1; push(@{$node->{_children}}, $child); push(@stack, $node); $node = $child; } elsif (/^\s*END\s+(.*)/) { # check: $node->{_type} eq $1 $node = pop(@stack); } elsif (/^\s*(\S+)\s+(.*)/) { # remove quotes from $2 here? $node->{$1} = $2; } else { die "unexpected input: $_" } } use Data::Dumper; print Dumper($root);