Re: [SPOILER] Solution for QotW #25 (RPN calculator)

Michael Carman <[email protected]> Fri, 01 Oct 2004 15:09:55 -0500
Newsgroups gmane.comp.lang.perl.qotw.discuss
Message-ID <[email protected]>
On 10/1/2004 11:12 AM, [email protected] wrote:
> 
> I thought about using eval STRING, but decided against it. Instead, my 
> solution is based around a dispatch table [...]
> 
> sub do_token {
> 	my $t = shift;
> 
> 	if (exists $op{$t}) {
> 		my $n = $op{$t}{n};
> 
> 		unless (@stack >= $n) {
> 			print "ERROR: Not enough elements for operation.\n";
> 			return;
> 		}
> 
> 		my @arg = $n ? splice(@stack, -$n) : ();
> 		my $rv  = $op{$t}{f}->(@arg);
> 
> 		push @stack, $rv if defined $rv;
> 	}
> 	else {
> 		push @stack, ($t =~ /^0\w/) ? oct($t) : $t;
> 	}
> }

Upon further consideration, I do want an eval: eval BLOCK. Otherwise, a user
entering something like "1 0 /" would kill the program. The following
replacement for do_token() catches fatal errors, prints the error message, and
restores the stack.

sub do_token {
	my $t = shift;

	if (exists $op{$t}) {
		my $n = $op{$t}{n};

		unless (@stack >= $n) {
			print "ERROR: Not enough elements for operation.\n";
			return;
		}

		my @arg = $n ? splice(@stack, -$n) : ();
		my $rv  = eval { $op{$t}{f}->(@arg) };

		if ($@) {
			(my $err = $@) =~ s/ at .*//;
			print "ERROR: $err\n";
			push @stack, @arg;
		}

		push @stack, $rv if defined $rv;
	}
	else {
		push @stack, ($t =~ /^0\w/) ? oct($t) : $t;
	}
}