use strict; use FindBin; use lib "$FindBin::Bin/lib"; use Pegex; use Runner; my $grammar = <<'...'; # Precedence Climbing grammar: expr: add-sub add-sub: mul-div+ % /- ( [ '+-' ])/ mul-div: power+ % /- ([ '*/' ])/ power: token+ % /- '^' / token: /- '(' -/ expr /- ')'/ | number number: /- ( '-'? DIGIT+ )/ ... { package Calculator; use base 'Pegex::Tree'; sub gotrule { my ($self, $list) = @_; return $list unless ref $list; # Right associative: if ($self->rule eq 'power') { while (@$list > 1) { my ($a, $b) = splice(@$list, -2, 2); push @$list, $a ** $b; } } # Left associative: else { while (@$list > 1) { my ($a, $op, $b) = splice(@$list, 0, 3); unshift @$list, ($op eq '+') ? ($a + $b) : ($op eq '-') ? ($a - $b) : ($op eq '*') ? ($a * $b) : ($op eq '/') ? ($a / $b) : die; } } return @$list; } } Runner->new(args => \@ARGV)->run( sub { pegex($grammar, 'Calculator')->parse($_[0]) } );