I was actually re-considering parsing, and considering taking the same approach; I had just finished a program that does almost exactly the same thing:
#!/usr/bin/perl
use strict;
use warnings FATAL => 'all';
use Data::Dumper;
use Term::ReadLine;
my %data = (
a => 5,
b => 1,
c => 7,
d => 100,
);
my $term = Term::ReadLine->new('foo');
my $expr;
while (1) {
$expr = $term->readline('Enter expression: ');
my $sub = compile($expr);
print Dumper($sub->(\%data));
}
sub compile {
my ( $expr ) = @_;
$expr =~ s/(\w+)/\$set->{$1}/g;
my $sub;
my $stuff = "\$sub = sub { my (\$set) = \@_; $expr }";
eval $stuff;
if ( $@ ) {
return sub { $@ };
}
return $sub;
}
The more I think about it, the more I think this is sufficient.