And the code , in the form of a shell session , showing that it works
$ cat ideone-6TneLv.pl #!/usr/bin/perl our @v; # external values stack our ($allnouns, %nouns) = ( qr/\d+(?{'number'})|[-(]/, 'number' => sub { push @v, pop }, '-' => sub { expr( qr/\*{2}/ ); $v[-1] = -$v[-1] }, '(' => sub { expr(); /\G\s*\)/gcx or err("no )") }, ); our ($allverbs, %verbs) = ( qr/[-+\/]|\*{1,2}/, '+' => sub { expr( qr/\*{1,2}|\// ); $v[-2] += pop @v }, '-' => sub { expr( qr/\*{1,2}|\// ); $v[-2] -= pop @v }, '*' => sub { expr( qr/\*{2}/ ); $v[-2] *= pop @v }, '/' => sub { expr( qr/\*{2}/ ); $v[-2] /= pop @v }, '**' => sub { expr( qr/\*{2}/ ); $v[-2] **= pop @v }, ); sub expr # takes regex of verbs that will shift { (my $shifters, $^R) = pop // $allverbs; /\G\s*($allnouns)/gcx ? $nouns{$^R // $1}->($1) : err('bad noun'); $verbs{$1}->() while /\G\s*($shifters)/gcx; } while(<>) { eval { @v = (); expr(); /\G\s*\z/gcx or err('incomplete') } or err($ +@); print s/\s*\z/ = @v\n/r; } sub err { exit print "ERROR ", s/\G/ <@_> /r, " \n" } $ $ cat ideone-6TneLv.stdin.txt 2 * 3 2+3 2*3-4 (2-3*4) -2**4 1+2+3+4+5+6+7+8+9+10 $ perl ideone-6TneLv.pl < ideone-6TneLv.stdin.txt > ideone-6TneLv.stdo +ut.txt $ cat ideone-6TneLv.stdout.txt 2 * 3 = 6 2+3 = 5 2*3-4 = 2 (2-3*4) = -10 -2**4 = -16 1+2+3+4+5+6+7+8+9+10 = 55
It needs Minimum version of perl : v5.13.2
That website says the code was forked 3 times but I can't work out how to see those forks
This is how you would turn that while loop into sub calc
sub Calc { local($_) = @_; local @v = (); eval { expr(); /\G\s*\z/gcx or err( 'incomplete' ); } or err( $@ ); return @v; } while( <> ) { s/[\r\n]*//g; ## "chomp" print $_," = ", Calc($_), "\n"; }
You might further modify it to run on more perl versions, remove defined-or operator(//) and non-destructive substitution (r flag in s///r)
In reply to Re: execute a string
by beech
in thread execute a string
by Anonymous Monk
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |