use strict; use warnings; use Data::Dumper (); use Parse::RecDescent (); my $grammar = <<'__EOI__'; { use strict; use warnings; sub treeify { my $t = shift; $t = [ shift, $t, shift ] while @_; return $t; } } parse : expr EOF { $item[1] } expr : assign { $item[1] } # Lowest precedence. assign : IDENT '=' assign { [ $item[2], $item[1], $item[3] ] } | log_or { $item[1] } log_or : {treeify(@{$item[1]})} log_and : {treeify(@{$item[1]})} sum : {treeify(@{$item[1]})} prod : {treeify(@{$item[1]})} # Highest precedence. term : '(' expr ')' { $item[2] } | NUMBER { [ $item[0], $item[1] ] } # Tokens NUMBER : /\d+/ IDENT : /\w+/ LOG_OR : '||' LOG_AND : '&&' SUM : '+' | '-' PROD : '*' | '/' | '\\' | '%' EOF : /^\Z/ __EOI__ # $::RD_HINT = 1; # $::RD_TRACE = 1; my $parser = Parse::RecDescent->new($grammar) or die("Bad grammar\n"); foreach ( '1*2*3', '1%2*3', '1+2*3', 'a=b=c=1', ) { print(Data::Dumper->Dump([ $parser->parse($_) ], [ $_ ])); print("\n"); }