add some check is good, and need to point at wrong line.
package MyPairList; use strict; use warnings; use feature 'state'; use Data::Dumper; use List::Util qw(all none); use Exporter 'import'; use feature 'current_sub'; our @EXPORT = qw(pair_list_parse); sub pair_list_parse { my $string = shift; my sub get_tokens { my $string = shift; my @tokens = $string =~ /([()\n]|[^()\s]+)/g; } my @tokens = get_tokens $string; my sub check_tokens { my $line; my @line; for my $token (@tokens) { if ($token eq "\n") { $line++; my $left = scalar grep {$_ eq '('} @line; my $right = scalar grep {$_ eq ')'} @line; my $is_open = $line[-1] eq '('; my $is_all_right = $right && not $left; my $is_closed = $right == $left; die "config line $line wrong" unless ( $is_open or $is_all_ +right or $is_closed); @line = (); } else { push @line, $token } } } check_tokens; my sub parse_list { my @list; while (my $token = shift @tokens) { if ($token eq "\n") { next; } elsif ($token eq '(') { push @list, __SUB__->(); } elsif ($token eq ')') { return \@list; } else { push @list, $token; } } return \@list; } my $list = parse_list; my 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 { __SUB__->($_) } @$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} = __SUB__->($ref); } return \%hash; } return parse_nested_list($list) } 1;
Every line can only brankets closed if not open or pure ')'

In reply to Re^11: parse lisp style config by vincentaxhe
in thread parse lisp style config by vincentaxhe

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.