/* Emacs, this is -*- C++ -*- */
#ifndef _FI_H_
#define _FI_H_
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#include <iostream.h>
/** Type for callback on table lookup.
Functions of this type may be used as callback functions
to look up cells in a table.
@see #setLookupFunction()
*/
typedef double (*FI_LookupFunc)(const char*, int);
/** Type for callback on errors.
Functions of this type may be used as callback functions
for error reporting.
@see #setErrorFunction()
*/
typedef void (*FI_ErrorFunc) (const char*, const char*);
/** Class for representing variables in the formula interpreter.
A variable for the formula interpreter consists of a name
(maximum length maxNameLen=32) and a value.
@author Patrick Schemitz
*/
class Variable
{
public:
/// Construct empty variable.
Variable ();
/// Construct named variable, optionally with initial value.
Variable (const char*, double=0.0);
/// Change variable's name.
void setName (const char*);
/// Change variable's value.
void setValue (double v) { value = v; }
/// Retrieve variable's name.
const char* const getName () const { return name; }
/// Retrieve variable's value.
double getValue () { return value; }
private:
/// class constant for maximum name length (32 characters).
static const int maxNameLen = 32;
/// variable to store the name.
char name [maxNameLen];
/// variable to store the value.
double value;
};
/** Representation of a Formula.
A formula consists of an expression and a set of variables; some
of the variables are global (shared by all formulas), others are
local. Global variables are accessed via get/setGlobalVariable()
and affect all formulas; local variables are accessed via
get/setLocalVariable() and affect only the specified formula.
The expression which is to be evaluated can be accessed by the
functions set/getExpression(). The expression is a math term, e.g.
"sin(x)*cos(y)+0.5*z*z". Note that the expression may *not* contain
spaces or tab stops!
A formula can be evaluated by the () operator, by placing a pair of
brackets after an instance of class Formula.
Warning: internally, the formula interpreter uses exceptions
to handle errors. The file formula.cc must be compiled with
exception handling on.
@author Patrick Schemitz
*/
class Formula
{
public:
/** Construct formula from string/expression.
The expression may not contain spaces!
*/
Formula (const char*);
/** Copy constructor.
Creates a deep copy, i.e. copies the expression and all local
variables of the r.h.s. formula.
*/
Formula (const Formula&);
/** Destruct formula and local variables.
Frees all local variables; global variables remain untouched.
*/
~Formula ();
/** Assign string expression to a formula; local variables remain.
This just changes the expression of a formula. The same as
@ref #setExpression
*/
Formula& operator= (const char*);
/** Assign a formula to another formula.
Creates a deep copy, i.e. copies the expression and all local
variables of the r.h.s. formula. The former left hand side
formula is wiped out.
*/
Formula& operator= (const Formula&);
/** Evaluate formula.
This operator evaluates the expression and returns the result.
Note that the evaluation may take some time (depending on the
expression, of course).
Two external functions are of interest here: the lookup function
and the error function. While the latter is called on parse errors
or in case an undefined variable is accessed, the lookup function
is called when the parser finds a pattern "col(name,integer)".
The name of the requested column is passed to the lookup function,
along with the integer row number.
If the evaluation was successful, the @ref #state function will return
zero.
@see state() to check success.
@return value of the expression.
*/
double operator () ();
/** Set the expression.
This function redefines the expression, leaving all variables
as they are.
@see #operator=()
*/
void setExpression (const char*);
/** Retrieve the expression.
@return the expression of the formula.
*/
const char* expression () { return the_expression; }
/** Set global variable.
This static member function defines/changes a global variable.
If the variable already exists, it is redefined; if it doesn´t,
it is newly defined. If the formula interpreter runs out of global
variables, the error function is called.
A global variable is accessible for all formulas.
(As opposed to global variables.)
@see #setLocalVariable()
@see #getGlobalVariables()
*/
static void setGlobalVariable (Variable);
/** Set local variable.
This function defines/changes a local variable.
If the variable already exists, it is redefined; if it doesn´t,
it is newly defined. If the formula interpreter runs out of global
variables, the error function is called.
A local variable is accessible only in the formula in which it
is defined. (As opposed to global variables.)
@see #setGlobalVariable()
@see #getLocalVariables()
*/
void setLocalVariable (Variable);
/** Retrieve all global variables.
"v" must point to an (already allocated) array of variables,
and "max" must give the size of that array.
@param v Buffer to store the global variables in.
@param max Size of buffer "v".
@return Number of global variables in use.
@see #getLocalVariables()
@see #setGlobalVariable()
*/
static int getGlobalVariables (int max, Variable* v);
/** Retrieve all local variables.
"v" must point to an (already allocated) array of variables,
and "max" must give the size of that array.
@param v Buffer to store the local variables in.
@param max Size of buffer "v".
@return Number of local variables in use.
@see #getGlobalVariables()
@see #setLocalVariable()
*/
int getLocalVariables (int max, Variable* v);
/** Set lookup function for tables.
The lookup function is invoked if the expression contains
patterns "col(name,row)". Then, the lookup function
is called, with "name" and "row" as parameters.
Note that the lookup function, in case it fails to look up
the table's cell, should return NAN, not zero. This way, the
function calling the evaluation operator can conclude from
the result that something went wrong.
@return Pointer to old lookup function.
*/
static FI_LookupFunc setLookupFunction (FI_LookupFunc);
/** Set error report function.
The error function is called by the formula evaluation.
The default error handler prints out the message it gets passed,
and terminates the program. Your error handler might instead
open a message box, show the error message, and gracefully
close down the evaluation. Note that the error handler may
return (it does not *need* to terminate); in this case, the
evaluation will be aborted, and state() function will return
a non-zero value.
@return Pointer to old error function.
*/
static FI_ErrorFunc setErrorFunction (FI_ErrorFunc);
/** Toggle case sensitivity for expressions and variables.
Note that this won't toggle case sensitivity for table lookup,
since this is implemented completely different.
*/
static bool caseSensitive;
/** Check for errors during evaluation.
If the expression could be evaluated successfully, the
state() function returns zero; if there has been an error,
a non-zero value is returned. (Unless, of course, the error
handler function has terminated the program:-)
@see #operator()()
*/
int state () { return fi_state; }
private:
/// Internal. Evaluate expression and move pointer.
double eval (char*&);
/// Internal. Evaluate term and move pointer.
double term (char*&);
/// Internal. Evaluate factor and move pointer.
double factor (char*&);
/// Internal. Evaluate function and move pointer.
double function (char*&);
/// Internal. Evaluate numerical constant and move pointer.
double number (char*&);
/// Internal. Make call to lookup function.
double table (char*& expr);
/// Internal. Make call to built-in function.
double callf (char*,double);
/// Internal. Resolve variable.
double variable (char*);
private:
/// Internal. Class constant for max. number of global variables (1024).
static const int maxGlobalVars = 1024;
/// Internal. Class constant for max. number of local variables (1024).
static const int maxLocalVars = 1024;
/// Internal. Class constant for delta function (delta(fabs(x)<epsilon)=1).
static const double epsilon = 1e-15;
private:
/// Internal. Initialization of global variables.
static void init ();
/// Internal. String compare, w.r.t. case sensitivity.
static int stringcmp (const char* s1, const char* s2);
/// Internal. Strip whitespaces from string.
char* stripped_string (const char*);
/// Internal. State. See state() function.
int fi_state;
/// Internal. Global variable counter.
static int globalVarCount;
/// Internal. Global variables.
static Variable globalVar [maxGlobalVars];
/// Internal. Local variable counter.
int localVarCount;
/// Internal. Local variables.
Variable localVar [maxLocalVars];
/// Internal. Pointer to error handler function.
static FI_ErrorFunc error;
/// Internal. Pointer to lookup function.
static FI_LookupFunc lookup;
/// Internal. The expression string.
char* the_expression;
/// Internal. A working copy of the expression string pointer.
char* workcopy;
};
#endif // _FI_H_
Documentation generated by mh@jeff_clever on Thu Feb 5 14:15:25 MET 1998