If your parser can easily be extended to handle function calls I'll have a go at adapting it for my application.
I said it would be easy, didn't I? Well I've got to put my money (er, code) where my mouth is, so I adapted it to process function calls. With this global spec, which defines 2 functions:
my %function = (
sumsq => sub { my $sum = 0; foreach(@_) { $sum += $_*$_; } return $
+sum; }, # sum of squares
sqrt => sub { return sqrt shift; },
);
I added this piece in
parse_value(), just in front of the code to handle variables:
if(/\G((?i:[a-z]\w*))\s*\(/gc) { # function '('
my $function = $1;
$function{$function} or die sprintf "Undefined function '$func
+tion' called at: \"%s\"", where();
my @arg;
unless(/\G\s*(?=\))/gc) {
while(1){
my($value) = parse_expr() or die sprintf "Expression e
+xpected at: \"%s\"", where();
push @arg, $value;
/\G\s*,/gc or last;
}
}
/\G\s+/gc;
/\G\)/gc or die sprintf "Parse error: ')' expected at: \"%s\""
+, where();
trace(sprintf "function '$function' called with %d argument%s"
+, scalar @arg, @arg==1 ? "" : "s");
return $function{$function}->(@arg);
}
and with the data string "
sumsq(3,2+2)*sqrt(36)", the output is:
Line 29 "·sumsq(3,2+2)*sqrt(36)"
Line 29 "sumsq(·3,2+2)*sqrt(36)"
Line 31 "sumsq(3·,2+2)*sqrt(36)" value=3
Line 29 "sumsq(3,·2+2)*sqrt(36)"
Line 31 "sumsq(3,2·+2)*sqrt(36)" value=2
Line 36 "sumsq(3,2+·2)*sqrt(36)" op=+
Line 29 "sumsq(3,2+·2)*sqrt(36)"
Line 31 "sumsq(3,2+2·)*sqrt(36)" value=2
Line 43 "sumsq(3,2+2·)*sqrt(36)" popping 2 +
Line 45 "sumsq(3,2+2·)*sqrt(36)" result = 4
Line 85 "sumsq(3,2+2)·*sqrt(36)" function 'sumsq' called with 2 argume
+nts
Line 31 "sumsq(3,2+2)·*sqrt(36)" value=25
Line 36 "sumsq(3,2+2)*·sqrt(36)" op=*
Line 29 "sumsq(3,2+2)*·sqrt(36)"
Line 29 "sumsq(3,2+2)*sqrt(·36)"
Line 31 "sumsq(3,2+2)*sqrt(36·)" value=36
Line 85 "sumsq(3,2+2)*sqrt(36)·" function 'sqrt' called with 1 argumen
+t
Line 31 "sumsq(3,2+2)*sqrt(36)·" value=6
Line 43 "sumsq(3,2+2)*sqrt(36)·" popping 25 *
Line 45 "sumsq(3,2+2)*sqrt(36)·" result = 150
150
Stack: This value is never affected
It seems to work fine, was finished in something like 1/4 hour, and it definitely doesn't take hundreds of lines of code. :)