#!/usr/bin/perl -w
# /\
# / \ (C) Copyright 2008 Parliament Hill Computers Ltd.
# \ / All rights reserved.
# \/
# . Author: Alain Williams, February 2008.
# . addw@phcomp.co.uk
# .
# .
#
# SCCS: @(#)UseOfOptions.pl 1.3 03/04/08 09:00:22
#
# Examples in the use of some of the options available via SetOpt().
use strict;
use Math::Expression;
my $trace = 0; # Debugging
# A function to provide more functions than those built in.
# Ie in ADDITION to the standard functions.
# This must return undef if the function is not recognised.
# Arguments are:
# 0 Object reference
# 1 Name of the function that we are to try to evaluate
# 2 .. Arguments to that function
sub moreFun {
print "moreFun called: '$_[1]'\n" if $trace;
my ($self, $fname, @arglist) = @_;
my $last = $arglist[$#arglist];
return length($last) if($fname eq 'strlen');
return undef; # There is no such extra function
}
my $ArithEnv = new Math::Expression;
$ArithEnv->SetOpt('ExtraFuncEval' => \&moreFun); # Say that we have an extra function evaluator
# Run some code and print the results
# An extra function:
my $tree0 = $ArithEnv->Parse('strlen("123456")');
print qq[strlen("123456") yeilds: ] . $ArithEnv->EvalToScalar($tree0) . "\n";
# A built in function:
my $tree1 = $ArithEnv->Parse('round(3.3)');
print qq[round(3.3) yeilds: ] . $ArithEnv->EvalToScalar($tree1) . "\n";
# You could have gone:
# $ArithEnv->SetOpt('FuncEval' => \&myFunEvaluator);
# In this case you need to provide evaluators for all of the built in functions.
# It is an error if variables are not initialised before used:
my $treeUndef = $ArithEnv->Parse('a + b');
print qq["a + b" yeilds: ] . $ArithEnv->EvalToScalar($treeUndef) . "\n";
# Auto initialise variables stops the error:
$ArithEnv->SetOpt('AutoInit' => 1);
print qq["a + b" yeilds: ] . $ArithEnv->EvalToScalar($treeUndef) . "\n";
# Think carefully before doing this, just because you no longer get an error
# message does not mean that it is doing the right thing.
# Alternative places to store variables.
# Variables are stored in a hash, you can specify that hash if you wish:
my %VarHash;
$ArithEnv->SetOpt('VarHash' => \%VarHash);
# This allows variables to given initialising values.
# Note that variables are always arrays:
$VarHash{count} = [22];
my $treeCount = $ArithEnv->Parse('count');
print qq["count" yeilds: ] . $ArithEnv->EvalToScalar($treeCount) . "\n";
my $treeSetResult = $ArithEnv->Parse('result := 42');
print qq["result := 42" yeilds: ] . $ArithEnv->EvalToScalar($treeSetResult) . "\n";
# You can access the variable within your perl script. Again - note that it is held
# as an array:
print "result direct from the hash: '$VarHash{result}[0]'\n";
# You can get more control of setting/getting variables, see the test program test.t
# for examples. (Functions VarValue, VarIsDef, VarSet)
# Define our own error printing function:
sub MyErrorFunction {
print "MyErrorFunction says: @_\n";
}
$ArithEnv->SetOpt('PrintErrFunc' => \&MyErrorFunction); # Use that function
# Call an unknown function:
my $treeBadFun = $ArithEnv->Parse('foo(0)');
print qq["foo(0)" yeilds: ] . $ArithEnv->EvalToScalar($treeBadFun) . "\n";
# To show how RoundNegatives affects the rounding of negative numbers:
foreach (0, 1) {
print "Arithmetic rounding with option RoundNegatives = $_\n";
$ArithEnv->SetOpt(RoundNegatives => $_);
foreach my $e (('round(0.6) ', 'round(-0.6) ', 'round(0.4) ', 'round(-0.4) ')) {
my $treeRound = $ArithEnv->Parse($e);
print qq[$e yeilds: ] . $ArithEnv->EvalToScalar($treeRound) . "\n";
}
}
# end