#!/usr/bin/perl use strict; use warnings; use Scalar::Util qw/weaken/; my $root_elem = { }; my @indent_levels = (-1); my $pos_in_tree = $root_elem; while (my $line = <>) { chomp $line; $line =~ s/^\s*//; my $indent_part = $&; $indent_part =~ s/\t/q{ } x 8/ge; my $cur_indent_len = length $indent_part; my $new_elem = { name => $line }; while ($cur_indent_len < $indent_levels[-1]) { pop @indent_levels; $pos_in_tree = $pos_in_tree->{parent}; die <<"_E" if scalar @indent_levels == 1; Indent level underflow at line $., containing "$line". _E die <<"_E" if $cur_indent_len > $indent_levels[-1]; Indent level mismatch: $cur_indent_len should be $indent_levels[-1] at line $., containing "$line". _E } if ($cur_indent_len > $indent_levels[-1]) { push @indent_levels, $cur_indent_len; $new_elem->{parent} = $pos_in_tree; } else { $new_elem->{parent} = $pos_in_tree->{parent}; } weaken($new_elem->{parent}); push @{$new_elem->{parent}{children}}, $new_elem; $pos_in_tree = $new_elem; } use Data::Dumper; $Data::Dumper::Purity = 1; my $new_tree; eval Data::Dumper->Dump([$root_elem], ["new_tree"]); die "Error in data loading: $@" if $@; print Data::Dumper->Dump([$new_tree], ["new_tree"]);