Today I started to study with enthusiasm the module
Regexp::Grammars. The demo directory of the current distribution
Regexp-Grammars-1.001005 is a good starting point.
Namely, the
demo/demo_calc_class.pl example illustrates
how to build a parser for arithmetic expressions
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>
| \( <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->{""}->eval();
}
sub Literal::eval {
my ($self) = @_;
return $self->{value};
}
But the interpreter does not match the traditional left associative semantics of the minus and division operators.
See an execution:
$ perl5_10_1 demo_calc_class.pl
2-3-5
--> 4
The result must be
-6.
The same occurs with the division:
$ perl5_10_1 demo_calc_class.pl
8/4/2
--> 4
The expected result is
1.
Does anyone knows how to modify the grammar to make it
work with the ordinary left-associative semantic?