#!/usr/bin/perl -w use strict; { my $exp; chomp ($exp = <STDIN>); init_regexes(); my $foo = treeify($exp); use Data::Dumper; print Dumper($foo); } my $TERM = ""; my $FUNCTION_CALL = ""; my $ATOM = ""; my $PAREN_EXP = ""; my $CONDITIONAL = ""; my $PAREN_COND = ""; my $OPERATOR = ""; my %OPS = ( '&' => 1, '|' => 2, '&&' => 3, '||' => 4, ); #regexes to parse C conditionals (more or less). sub init_regexes { $TERM = qr/ (?: (?: (??{$PAREN_COND}) ) | (?: (??{$FUNCTION_CALL}) ) | (?: (??{$ATOM}) ) ) /x; $PAREN_EXP = qr/ \( \s* (?: (?> [^()&|]+ ) | (??{$PAREN_EXP}) ) \s* \) /x; $ATOM = qr/ (?: (?: (?: [!*&] | \b ) \w+\b ) | (??{$PAREN_EXP}) ) /x; $FUNCTION_CALL = qr/ \b\w+\s? \( \s*(??{$TERM})\s* (?: ,\s*(??{$TERM})\s* )* \) /x; $OPERATOR = qr/ (?: && | \|\| | & | \| | \^ ) /x; $CONDITIONAL = qr/ ((??{$TERM})) (?: \s* ( (??{$OPERATOR}) ) \s* (?: ((??{$TERM})) ) )+ /x; $PAREN_COND = qr/ !? \( (?: (??{$CONDITIONAL}) ) \) /x; } #make a tree out of a C expression. sub treeify { my $exp = shift; my $tree; #find the first term in the string; put in $1 and delete. while ($exp =~ s/^($TERM)//) { my $term = $1; my $type = 'atom'; if ($term =~ /\s*($CONDITIONAL)\s*/) { $term = $1; $type = 'cond'; } my $new_term = { 'type' => $type, #if the term itself should be a node, process it. 'value' => $term, 'ref' => undef }; if ($type eq 'cond') { $new_term->{'ref'} = treeify($term); } push @{ $tree->{'terms'} }, $new_term; #now find, put in $1, and delete the next operator. if ($exp ne '' and $exp =~ s/^\s*($OPERATOR)\s*//) { $tree->{'op'} ||= $1; } else { return $tree; } } }
In reply to Recursion Woes by ColonelPanic
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |