sub parse_brackets { my @parse; my @stack = \@parse; my $fewer_indents = 1; # Try setting this to 0 or 1 my $line_no; foreach my $line ( @_ ) { $line_no ++; $line =~ s/\A\s+//; $line =~ s/\s+\Z//; if ( $line !~ /\S/ ) { next; } elsif ( $line =~ s/\s*\{$// ) { my @line = split ' ', $line; push @{ $stack[0] }, \@line; if ( $fewer_indents ) { unshift @stack, \@line; } else { my @kids = (); push @line, \@kids; unshift @stack, \@kids; } } elsif ( $line eq '}' ) { shift @stack; scalar @stack or die("Too many right brackets at line $line_no"); } else { push @{ $stack[0] }, $line; } } return @parse; } use Data::Dumper; print Dumper( parse_brackets( split "\n", <<'EXAMPLE' ) ); page p1 { question 4B { label { Do you like your pie with ice cream? } single { 1 Yes 2 No } } question 4C { label { Do you like your pie with whipped cream? } single { 1 Yes 2 No } } } EXAMPLE