The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
use v5.10;
use warnings;

my $calculator = do{
    use Regexp::Grammars;
    qr{
        <Answer>

        <objrule: Answer>
            <X=Mult> <Op=([+-])> <Y=Answer>
          | <MATCH=Mult>

        <objrule: Mult>
            <X=Pow> <Op=([*/%])> <Y=Mult>
          | <MATCH=Pow>

        <objrule: Pow>
            <X=Term> <Op=(\^)> <Y=Pow>
          | <MATCH=Term>

        <objrule: Term>
               <MATCH=Literal>
          | <Sign=([+-]?)> \( <Answer> \)
          | \( <MATCH=Answer> \)

        <objtoken: Literal>
            <value=( [+-]? \d++ (?: \. \d++ )?+ )>
    }xms
};

while (my $input = <>) {

    my $debug = $input =~ s{^show \s+}{}xms;

    if ($input =~ $calculator) {
        if ($debug) {
            use Data::Dumper 'Dumper';
            warn Dumper \%/;
        }
        else {
            say '--> ', $/{Answer}->eval();
        }
    }
}

sub Answer::eval {
    my ($self) = @_;

    my $x = $self->{X}->eval();
    my $y = $self->{Y}->eval();
    return $self->{Op} eq '+'  ?  $x + $y
         :                        $x - $y;
}

sub Mult::eval {
    my ($self) = @_;

    my $x = $self->{X}->eval();
    my $y = $self->{Y}->eval();
    return $self->{Op} eq '*'  ?  $x * $y
         : $self->{Op} eq '/'  ?  $x / $y
         :                        $x % $y;
}

sub Pow::eval {
    my ($self) = @_;

    return $self->{X}->eval() **  $self->{Y}->eval();
}

sub Term::eval {
    my ($self) = @_;

    return $self->{Sign} eq '-' ? -$self->{Answer}->eval()
                                :  $self->{Answer}->eval();
}

sub Literal::eval {
    my ($self) = @_;

    return $self->{value};
}