package MyPairList;
use strict;
use warnings;
use feature 'state';
use Data::Dumper;
use List::Util qw(all none);
use Exporter 'import';
our @EXPORT = qw(pair_list_parse);
sub pair_list_parse {
my $string = shift;
sub get_tokens {
my $string = shift;
my @tokens = $string =~ /([()]|[^()\s]+)/g;
}
my @tokens = get_tokens $string;
sub parse_list {
state @tokens = @_;
my @list;
while (my $token = shift @tokens) {
if ($token eq '(') {
push @list, parse_list();
} elsif ($token eq ')') {
return \@list;
} else {
push @list, $token;
}
}
return \@list;
}
my $list = parse_list @tokens;
sub parse_nested_list {
my ($list) = @_;
my %hash;
if (none {ref $_} @$list) {
if (@$list == 1) {
return $list->[0];
} elsif (@$list == 2) {
return { $list->[0] => $list->[1] };
} else {
return $list
}
} elsif (all {ref $_} @$list) {
return [ map { parse_nested_list($_) } @$list ];
} else {
my ($key, $ref, @remain) = @$list;
die 'wrong key ', Dumper $key if ref $key;
die 'wrong value ', Dumper $ref unless ref $ref;
die 'redundant value', Dumper \@remain if @remain;
$hash{$key} = parse_nested_list($ref);
}
return \%hash;
}
return parse_nested_list($list)
}
1;
####
(config(
(a A)
(b B)
((good) (bad))
(d e f)
(a (a1 (a2 A)))
)
)
####
$VAR1 = [
{
'config' => [
{
'a' => 'A'
},
{
'b' => 'B'
},
[
'good',
'bad'
],
[
'd',
'e',
'f'
],
{
'a' => {
'a1' => {
'a2' => 'A'
}
}
}
]
}
];