#!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11147096 use warnings; use List::AllUtils qw( all ); my $testdata = < $2 } ] : /\G([^{}\s]+) \{/gc ? [ @$e, { "$1" => (expr(), /\G\}/gc || die pos($_), ' missing } ', substr $_, pos($_))[0] } ] : /\G([^{}\s]+)/gc ? [ @$e, $1 ] : return ref $e eq 'ARRAY' && ( all { ref $_ eq 'HASH' } @$e ) ? { map %$_, @$e } : $e while 1 } local $_ = $testdata; # NOTE expr() expects input in $_ my $parse = expr(); pos($_) < length $_ and die "incomplete parse ", substr $_, pos($_); $Data::Dump::LINEWIDTH = 26; use Data::Dump 'dd'; dd $parse;