use strict; use Data::Dumper; use Regexp::Common; my $name = qr/[a-z0-9_]+/i; my $val = qr/\S+/; my $braces = qr/$RE{balanced}{-parens=>'{}'}/; my $node = qr/($name) \s+ ($braces)/x; my $assign = qr/($name) [=:] \s* ($val) (?:\s+ | })/x; my $graph = <{$1} = $2; redo PARSE; } elsif($graph =~ /\G .*? $node/sgcx) { push @{ $tree->{$1} }, parse_graph($2); redo PARSE; } } return $tree; } __output__ $VAR1 = { 'graph' => [ { 'edge' => [ { 'sourcename' => '"node1"', 'targetname' => '"node2"' } ], 'node' => [ { 'title' => '"node1"', 'loc' => [ { 'x' => '10', 'y' => '20' } ] }, { 'title' => '"node2"', 'loc' => [ { 'x' => '10', 'y' => '20' } ] } ] } ] };