Math-Expression

 view release on metacpan or  search on metacpan

Expression.pm  view on Meta::CPAN


	if($fname eq 'push' or $fname eq 'unshift') {
		# Evaluate right->right and push/unshift that
		my $vn = shift @arglist;		# var name

		my @vv = $self->{VarGetFun}($self, $vn);# var value
		my @vp = $self->EvalTree($tree->{right}->{right}, 0); # var to push/unshift

		$fname eq 'push' ? push(@vv, @vp) : unshift(@vv, @vp);
		$self->{VarSetFun}($self, $vn, @vv);

		return scalar @vv;
	}

	return length($last)					if($fname eq 'strlen');
	return scalar @arglist					if($fname eq 'count');

	# aindex(array, val) returns index (from 0) of val in array, -1 on error
	if($fname eq 'aindex') {
		my $val = $arglist[$#arglist];
		for( my $inx = 0; $inx <= $#arglist - 1; $inx++) {
			return $inx if($val eq $arglist[$inx]);
		}
		return -1;
	}

	$self->PrintError("Unknown Function '$fname'");

	return '';
}

# Create a new parse/evalutation object.
# Initialise default options.
sub new {
	my $class = shift;

	# What we store about this evaluation environment, default values:
	my %ExprVars = (
		PrintErrFunc	=>	'',			# Printf errors
		VarHash		=>	{(			# Variable hash
					EmptyArray	=>	[()],
					EmptyList	=>	[()],
			)},
		VarGetFun	=>	\&VarGetFun,		# Get a variable - function
		VarIsDefFun	=>	\&VarIsDefFun,		# Is a variable defined - function
		VarSetFun	=>	\&VarSetFun,		# Set an array variable - function
		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);

 view all matches for this distribution
 view release on metacpan -  search on metacpan

( run in 0.525 second using v1.00-cache-2.02-grep-82fe00e-cpan-3b7f77b76a6c )