in reply to Parsing nested parentheses

This is probably a klunky solution, but it reminded me of a parser I had written.. (Evaluate Expressions.)

Quickly hacking at it and only testing a few simple cases (you've been warned)

You could use the returned structure to search for whatever criteria you desire. I'm sure someone here has a much more elegant solution, but my regex abilities are rather limited...
#!/usr/bin/perl use warnings; use strict; use Data::Dumper; my $input = '(a,b,(c,d,(e,f,g)))'; print Dumper parse_expression($input); sub parse_expression { my $exp = shift; my @tokens = (); $exp=~s/\s*([()])\s*/ $1 /go; # Get tokens push @tokens, $1 while $exp=~/\G\s*(".*?")/gc or $exp=~/\G\s*('.*? +')/gc or $exp=~/\G\s*(\S+)/gc; # Find any parens. my (@lp,@rp) = (); for (my $p =0; $p < @tokens; $p++){ if ($tokens[$p] eq '('){ push @lp,$p; }elsif($tokens[$p] eq ')'){ push @rp,$p; } } if ( @lp != @rp){ warn "Mismatched parens in expression.\n"; return; } my @temp = @tokens; for (my $i=0; $i < @rp; $i++){ my @wanted; for (my $j = $#lp; $j >= 0 ; $j--){ if ( defined $lp[$j] && $lp[$j] < $rp[$i] ){ (undef,@wanted) = @tokens[ $lp[$j] .. ($rp[$i] - 1 ) +] ; @tokens[ $lp[$j] .. ($rp[$i]) ] = [ grep {defined $_ +} @wanted]; push @temp, map {split /\s*,\s*/} @wanted; $lp[$j] = $rp[$i] = undef; last; } } } return $tokens[0]; } __DATA__ # OUTPUT $VAR1 = [ 'a,b,', [ 'c,d,', [ 'e,f,g' ] ] ];


-Lee

"To be civilized is to deny one's nature."

Replies are listed 'Best First'.
Re^2: Parsing nested parentheses
by bassfox (Initiate) on Jun 19, 2008 at 08:20 UTC
    Hi there, ever thought of using the perl internal functions to import a nested data structure to a LoL? If you do not have to avoid using eval, you could do it real simple like this:
    #!/usr/bin/perl -w use strict; use Data::Dumper; my $string = "(a,b,(c,d,(e,f,g)))"; $string =~ s/([^,\(\)]+)/"$1"/gsm; # quote content $string =~ tr/\(\)/\[\]/; # replace braces my @LoL; # define list eval("\@LoL = $test;"); # fill LoL print Dumper @LoL; __DATA__ Output: $VAR1 = [ 'a', 'b', [ 'c', 'd', [ 'e', 'f', 'g' ] ] ];
    It is not extensively tested, but should work for most items. - frank