The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Math::Expression - Evaluate arithmetic/string expressions

SYNOPSIS

  use strict;
  use Math::Expression;

  my $ArithEnv = new Math::Expression;

  # Some/all of these read from a config file:
  my $tree1 = $ArithEnv->Parse('ConfVar := 42');

  my $tree2 = $ArithEnv->Parse('ConfVar * 3');

  ...

  $ArithEnv->Eval($tree1);
  my $ConfValue = $ArithEnv->EvalToScalar($tree2);

DESCRIPTION

This solves the problem of evaluating expressions read from config/... files without the use of eval. String and arithmetic operators are supported, as are: conditions, arrays and functions. 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.

DESCRIPTION

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. You might also want to take computation results from stored variables.

For further examples of use please see the test program for the module.

Package functions

new

This must be used before anything else to obtain a handle that can be used in calling other functions.

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 new function.

PrintErrFunc

This is a printf style function that will be called in the event of an error, the error text will not have a trailing newline. The default is printf STDERR.

VarHash

The argument is a hash that will be used to store variables. If this is called several times it is possible to manage distinct name spaces. The name EmptyList should, by convention, exist and be an empty array; this may be used to assign an empty value to a variable.

VarGetFun

This specifies the that function returns the value of a variable as an array. The arguments are: 0 - the value returned by new; 1 - the name of the variable wanted. If no value is available you may return the empty array.

VarIsDefFun

This should return 1 if the variable is defined, 0 if it is not defined. The arguments are the same as for VarGetFun.

VarSetFun

This sets the value of a variable as an array. The arguments are: 0 - the value returned by new; 1 - the name of the variable to be set; 2 - the value to set as an array. The return value should be the variable value.

VarSetScalar

This sets the value of a variable as a simple scalar (ie one value). The arguments are: 0 - the value returned by new; 1 - the name of the variable to be set; 2 - the value to set as a scalar. The return value should be the variable value.

FuncEval

This will evaluate functions. The arguments are: 0 - the value returned by new; 1 - the name of the function to be evaluated; 2... - an array of function arguments. This should return the value of the function: scalar or array.

The purpose is to permit different functions than those provided (eg abs()) to be made available. This option replaces the in built function evaluator FuncValue which may be used as a model for your own evaluator.

ExtraFuncEval

If defined this will be called when evaluating functions. If a defined value is returned that value is used in the expression, it should be numeric or string. This is called before the standard functions are tested and thus can redefine the built in functions. The arguments are as FuncEval.

RoundNegatives

See the description of the round function.

AutoInit

If true automatically initialise undefined values, to the empty string or '0' depending on use. The default is that undefined values cause an error, except that concatentation (.) always results in the empty string being assumed.

Example:

  my %Vars = (
        EmptyList       =>      [()],
  );

  $ArithEnv->SetOpt(VarHash => \%Vars,
        VarGetFun => \&VarValue,
        VarIsDefFun => \&VarIsDef,
        PrintErrFunc => \&MyPrintError,
        AutoInit => 1,
        );

   my $ArithEnv2 = new Math::Expression(RoundNegatives => 1);
ParseString

This parses an expression string and returns a tree that may be evaluated later. The arguments are: 0 - the value returned by new; 1 - the string to parse. If there is an error a complaint will be made via PrintErrFunc and the undefined value returned.

CheckTree

This checks a parsed tree. The arguments are: 0 - the value returned by new; 1 - the tree to check. The input tree is returned. If there is an error a complaint will be made via PrintErrFunc and the undefined value returned.

Parse

This combines ParseString and CheckTree.

VarSetFun

This sets a variable, see the description in &SetOpt.

VarSetScalar

This sets a variable, see the description in &SetOpt.

FuncValue

This evaluates a function, see the description in &SetOpt.

EvalTree

Evaluate a tree. The result is an array, if you are expecting a single value it is the last (probably $#'th) element. The arguments are: 0 - the value returned by new; 1 - tree to evaluate; 2 - true if a variable name is to be returned rather than it's value (don't set this). You should not use this, use &Eval or &EvalToScalar instead.

Eval

Evaluate a tree. The result is an array, if you are expecting a single value it is the last (probably $#'th) element. The arguments are: 0 - the value returned by new; 1 - tree to evaluate.

EvalToScalar

Evaluate a tree. The result is a scalar (simple variable). The arguments are: 0 - the value returned by new; 1 - tree to evaluate.

Functions that may be used in expressions

The following functions may be used in expressions, if you want more than this write your own function evaluator and set it with &SetOpt; The POSIX package is used to provide some of the functions.

int

Returns the integer part of an expression.

abs

Returns the absolute value of an expression.

round

Adds 0.5 to input and returns the integer part. If the option RoundNegatives is set round() is sign sensitive, so for negative input subtracts 0.5 from input and returns the integer part.

split

Perl split, the 0th argument is the RE to split on, the last argument what will be split.

join

Joins arguments 1..$#, separating elements with the 0th argument.

printf

The standard perl printf, returns the formatted result.

mktime

Passes all the arguments to mktime, returns the result.

strftime

Passes all the arguments to strftime, returns the result.

localtime

Returns the result of applying localtime to the last argument.

defined

Applies the VarIsDefFun to the last argument.

aindex

Searches the arguments for the last argument and returns the index. Return -1 if it is not found. Eg the following will return 1:

  months := 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
  aindex(months, 'Feb')

Variables

Variables can 3 three forms, there is no difference in usage between any of them. A variable name is either alphanumeric (starting with alpha), numeric (with a leading $ or ${, or any non white space between {} or one non white space after a $:

        Variable
        $Variable
        ${Variable}
        $123
        ${123}
        $#
        ${###=##}

Literals

Literals may be: integers, floating point in the form nn.nn, strings bounded by matching singe or double quotes. Escapes are not looked for in literal strings.

Operators and precedence

The operators should not surprise any Perl/C programmer, with the exception that assignemnt is :=. Operators associate left to right except for := which associates right to left. Precedence may be overridden with parenthesis. Unary + and - do not exist. <> is the same as !=.

        + - ~ ! (Monadic)
        * / %
        + -
        .       String concatenation
        > < >= <= == != <>
        lt gt le ge eq ne
        &&
        ||
        ? :
        ,
        :=

Arrays

Variables are implemented as arrays, if a simple scalar value is wanted (eg you want to go +) the last element of the array is used. Arrays may be built using the comma operator, arrays may be joined using , eg:

        a1 := (1, 2, 3, 4)
        a2 := (9, 8, 7, 6)
        a1 , a2

yeilds:

        1, 2, 3, 4, 9, 8, 7, 6

And:

        a2 + 10

yeilds:

        16

Arrays may be used to assign multiple values, eg:

        (v1, v2, v3) := (42, 44, 48)

If there are too many values the last variable receives the remainder. If there are not enough values the last ones are unchanged.

Conditions

Conditional assignment may be done by use of the ternary operator:

        a > b ? ( c := 3 ) : 0

Variables may be the result of a conditional, so below one of aa or bb is assigned a value:

        a > b ? aa : bb := 124

Miscellaneous and examples

There is no ; so each strings Parsed must be one expression. my $tree1 = $ArithEnv->Parse('a := 10'); my $tree2 = $ArithEnv->Parse('b := 3'); my $tree3 = $ArithEnv->Parse('a + b');

        $ArithEnv->EvalToScalar($tree1);
        $ArithEnv->EvalToScalar($tree2);
        print "Result: ", $ArithEnv->EvalToScalar($tree2), "\n";

prints: Result: 13

AUTHOR

Alain D D Williams <addw@phcomp.co.uk>

Version "1.21", this is available as: $Math::Expression::Version.

Copyright (c) 2003 Parliament Hill Computers Ltd/Alain D D Williams. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Please see the module source for the full copyright.