#!/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; } sub print_tree { my ($cur_elem, $recursion_lvl, $enum_label) = @_; print q/ / x (3 * $recursion_lvl) , $enum_label , q/ / , $cur_elem->{name} , qq/\n/ if exists $cur_elem->{name}; my $num = 1; for my $child_elem (@{$cur_elem->{children}}) { print_tree( $child_elem , $recursion_lvl + 1 , $enum_label . $num . q/./ ); $num++; } } print_tree($root_elem, -1, q//);