#!/usr/bin/perl use warnings; use strict; use PostfixWithActions; my $debug = 0; my $pparser = PostfixWithActions->new(); print "Write an expression: "; my $x = "@ARGV"; # First, translate to postfix ... $pparser->Run($debug, $x); exit(1) if $pparser->YYNberr; # And then selectively substitute # some semantic actions # to obtain an infix calculator ... my %s; $pparser->YYSetaction( 'OP:ASSIGN' => sub { $s{$_[1]} = $_[3] }, 'OP:PLUS' => sub { $_[1] + $_[3] }, 'OP:TIMES' => sub { $_[1] * $_[3] }, 'OP:DIV' => sub { $_[1] / $_[3] }, 'OP:NEG' => sub { -$_[2] }, ); $pparser->Run($debug, $x); # Let su reuse the grammar a third time. # Now we use it to generate the AST my $buildtree = sub { my $self = $_[0]; my $fullname = $self->YYName(); my ($name, $label) = split /:/, $fullname; my $x = &Parse::Eyapp::Driver::YYBuildAST(@_); bless $x, $label if defined($label); $x; }; { no strict 'refs'; @{$_."::ISA"} = ('Parse::Eyapp::Node') for qw{ASSIGN PLUS TIMES DIV NEG NUM VAR}; } $pparser->YYSetaction( 'EXP' => sub { $_[1] }, # bypass 'OPERAND:NUM' => $buildtree, 'OPERAND:VAR' => $buildtree, 'OP:ASSIGN' => $buildtree, 'OP:PLUS' => $buildtree, 'OP:TIMES' => $buildtree, 'OP:DIV' => $buildtree, 'OP:NEG' => $buildtree, ); my $t = $pparser->Run($debug, $x); print $t->str."\n"; package TERMINAL; sub info { $_[0]{attr} }; package NUM; sub info { $_[0]{attr} };