use strict; use warnings; use Data::Dumper; # read text from DATA my $text = do { local $/; }; # parse text and convert to AoA my @stack; while ($text =~ m/\G([\w-]+|.)/sg) { my $tok = $1; if ($tok eq '{' or $tok =~ /^\w/) { push @stack, $tok; } elsif ($tok eq '}') { # stack: ... '{' key val(s) my $arr = []; while ($stack[-1] ne '{') { unshift @$arr, pop @stack; } pop @stack; # '{' push @stack, $arr; } } print Dumper(\@stack); __DATA__ {chart { {1 { {title title_1} {xlable X-lab} {ylable Y-lab} {description desc1} {type line} {series { {1 { {x_data {1 2 3 4 5} } {y_data {20 90 60 50 30}} } } } } } } } }