Math-Expression
view release on metacpan or search on metacpan
Expression.pm view on Meta::CPAN
VarSetScalar => \&VarSetScalar, # Set a scalar variable - function
FuncEval => \&FuncValue, # Evaluate - function
AutoInit => 0, # If true auto initialise variables
ExtraFuncEval => undef, # User supplied extra function evaluator function
RoundNegatives => 0, # Round behaves differently with -ve numbers
PermitLoops => 0, # Are loops allowed
MaxLoopCount => 50, # Max # all loops
ArrayMaxIndex => 100, # Max index of an array
StringMaxLength => 1000, # Max string length
EnablePrintf => 0, # Enable printf function
Functions => {%InFuns}, # Known functions, initialise to builtins
);
my $self = bless \%ExprVars => $class;
$self->SetOpt(@_); # Process new options
return $self;
}
# Set an option in the %template.
sub SetOpt {
my $self = shift @_;
while($#_ > 0) {
$self->PrintError("Unknown option '$_[0]'") unless(exists($self->{$_[0]}));
$self->PrintError("No value to option '$_[0]'") unless(defined($_[1]));
$self->{$_[0]} = $_[1];
shift;shift;
}
}
1;
__END__
=head1 NAME
Math::Expression - Safely evaluate arithmetic/string expressions
=head1 DESCRIPTION
Evaluating an expression from an untrusted source can result in security or denial of service attacks.
Sometimes this needs to be done to do what the user wants.
This module solves the problem of evaluating expressions read from sources such as config/...
files and user web forms without the use of C<eval>.
String and arithmetic operators are supported (as in C/Perl),
as are: variables, loops, conditions, arrays and be functions (inbuilt & user defined).
The program may set initial values for variables and obtain their values once the expression
has been evaluated.
The name-space is managed (for security), user provided functions may be specified to set/get
variable values.
Error messages may be via a user provided function.
This is not designed for high computation use.
=head1 EXAMPLE
Shipping cost depends on item price by some arbitrary formula. The VAT amount can also
vary depending on political edict. Rather than nail these formula into the application code the
formula are obtained at run time from some configuration source. These formula are
entered by a non technical manager and are thus not to be trusted.
use Math::Expression;
my $ArithEnv = new Math::Expression;
# Obtain from a configuration source:
my $ShippingFormula = 'Price >= 100 ? Price * 0.1 : (Price >= 50 ? Price * 0.15 : Price * 0.2)';
my $VatFormula = 'VatTax := Price * 0.2';
# Price of what you are selling, set the price variable:
my $price = 100;
$ArithEnv->VarSetScalar('Price', $price);
# Obtain VAT & Shipping using the configured formula:
my $VatTax = $ArithEnv->ParseToScalar($VatFormula);
my $Shipping = $ArithEnv->ParseToScalar($ShippingFormula);
say "Price=$price VatTax=$VatTax Shipping=$Shipping";
# If these will be run many times, parse the formula once:
my $VatExpr = $ArithEnv->Parse($VatFormula);
my $ShipExpr = $ArithEnv->Parse($ShippingFormula);
# Evaluate it with the current price many times:
$ArithEnv->VarSetScalar('Price', $price);
$VatTax = $ArithEnv->EvalToScalar($VatExpr);
$Shipping = $ArithEnv->EvalToScalar($ShipExpr);
=head1 HOW TO USE
An expression needs to be first compiled (parsed) and the resulting tree may be run (evaluated)
many times.
The result of an evaluation is an array.
Variables are preserved between evaluations.
You might also want to take computation results from stored variables.
Method C<ParseToScalar> does it all in one: parse, check & evaluate.
See examples later in this document.
For further examples of use please see the test program for the module.
=head2 Package methods
=over 4
=item new
This must be used before anything else to obtain a handle that can be used in calling other
functions.
=item SetOpt
The items following may be set.
In many cases you will want to set a function to extend what the standard one does.
These options may also be given to the C<new> function.
=over 4
=item PermitLoops
This must be set C<true> otherwise loops (C<while>) will not be allowed.
This is to prevent a denial of service attack when the expression is from an
untrusted source.
Default: false
=item MaxLoopCount
This it the maximum number of times that loops will be allowed to iterate.
Where there is more than one loop, all loops count towards this limit.
Think carefully before making this too high.
If set to zero, there is no iteration limit. This is probably unwise.
The count restarts when an Eval function is used to evaluate a tree.
( run in 1.005 second using v1.01-cache-2.11-cpan-e1769b4cff6 )