#ifndef __MATH_PARSER_H_
#define __MATH_PARSER_H_
#include <map>
#include <vector>
#include <string>
#include <float.h>
#include <time.h>
#include <wchar.h>
#include <sstream>
#include <math.h>
using namespace std;
/**
* CParserException is used to report errors during parsing and evaluation in
* CMathParser class.
* GetMessage() function can be used to retrieve error message.
* GetInvalidPortionOfExpression() function reports the problematic
* part of the mathematical expression that caused the error.
*/
template<typename _CharT> class CParserException {
public:
//get error message:
basic_string<_CharT> GetMessage() {
return this->m_Message;
}
//get sub expression that we could not parse (might be empty):
basic_string<_CharT> GetInvalidPortionOfExpression() {
return this->m_InvalidPortionOfExpression;
}
};
/**
* CMathParser template class implements mathematical expression parsing algorithm.
* User can define variables, functions, set variable values,
* set a mathematical expression and request that it's value be computed.
* CMathParser will convert the string expression to an internal representation of a tree
* structure. If Optimization is turned on, it will walk the tree to convert non-parametric
* branches (branches whose value do not depend on variables) into a constant value.
* Once this is done successfully, the expression can be evaluated very quickly for
* different variable values.
*/
template<typename _CharT, typename _ValueT> class CMathParser {
friend class COneParamNode<_CharT, _ValueT>;
friend class CTwoParamNode<_CharT, _ValueT>;
friend class CNParamNode<_CharT, _ValueT>;
public:
/**
* String type used in variable, function names, and reporting messages.
* It is nothing but a basic_string<> of std.
*/
typedef basic_string<_CharT> string_t;
/**
* ParserFunction type specifies the prototype of the functions that users can
* add to the list of available functions with N parameters to be used in an expression.
* p[] array holds the value for each paramater.
* count is the number of paramaters (number of elements in p[]).
* pParentParser parameter is a way to carry the current context into the user defined function.
* Applications can create their own parsers that are "Application Aware". Then inside the user
* defined function, pParentParser can be cast to application specific parser type and it's members
* can be used to access application domain.
*/
typedef _ValueT ParserFunction(CMathParser<typename _CharT, typename _ValueT> pParentParser,
const _ValueT p[], const int count);
typedef ParserFunction* PParserFunction;
typedef CParserException<_CharT> ParserException;
public:
/**
* Constructor to create a CMathParser instance.
* It initializes member variables and creates default functions and variables.
*/
CMathParser();
/**
* Virtual destructor to free memory.
*/
virtual ~CMathParser();
/**
* Parse the expression. It is fast to parse the expression once,
* then loop to evaluate the expression multiple times by setting different variable
* values.
* throws CMathParser::ParserException on error.
*/
void Parse() throw (ParserException);
/**
* Returns TRUE if the given function name is already registered as a function.
*/
BOOL IsFunction(string_t funcName);
/**
* Returns TRUE if the given variable name is already registered as a variable.
*/
BOOL IsVariable(string_t varName);
/**
* Return TRUE if a given variable was used in the current expression.
* Return FALSE if the expression does not contain this variable.
* Throw CMathParser::ParserException if the expression cannot be parsed.
*/
BOOL IsVariableUsed(string_t varName) throw (ParserException);
/**
* Return TRUE if a given function is being used in the current expression.
* Return FALSE if the expression is not using the function.
* Throw CMathParser::ParserException if the expression cannot be parsed.
*/
BOOL IsFuncUsed(string_t funcName) throw (ParserException);
/**
* Free the parse tree that was used to parse previous expression.
* This does not have to be called explicitly.
* This is only useful for an unusual case where a very big expression was
* parsed and tree takes alot of memory and you want to free it because
* you will not use the parser instance for a while.
* Otherwise, next expression parse will delete previous tree.
*/
void FreeParseTree();
/**
* Init random _ValueT generator for rnd built-in function.
*/
void Randomize();
/**
* Delete all functions defined for the parser.
*/
void DeleteAllFuncs();
/**
* Delete all defined variables.
*/
void DeleteAllVars();
/**
* Delete a function from defined functions list.
* Ignore if not found.
*/
void DeleteFunc(string_t funcName);
/**
* Delete an existing variable name.
* If it does not exist, it is ignored.
*/
void DeleteVar(string_t varName);
/**
* Define a variable with initial value.
*/
void CreateVar(string_t varName, _ValueT varValue);
/**
* Create a user defined function with given name, number of params, function address to call.
* The uppercase version of given function name can be used in the expressions.
* If the expression does not specify correct number of parameters, then a
* CMathParser::ParserException will be thrown during parsing. if number of parameters is specified as -1, then the
* function can take 1 or more number of parameters. Number of parameters will not be verified
* during parse operation.
* If invalid number of parameters are passed to a function, the function implementation itself can choose
* to throw exception during evaluate operation.
*/
void CreateFunc(string_t newFuncName, int numParams,
PParserFunction funcAddress) throw(ParserException);
/**
* Create default built-in variables such as X, Y, PI.
* Override to define different set of variables.
*/
virtual void CreateDefaultVars();
/**
* Create default functions.
* You can override CreateDefaultFuncs to define (or not define)
* a different set of functions.
*
* Predefined functions that take one parameter are:
* SQR: Square function which can be used as SQR(X)
*
* SIN: Sinus function which can be used as SIN(X), X is a real-type expression. Sin returns the sine of the angle X in radians.
*
* COS: Cosinus function which can be used as COS(X), X is a real-type expression. COS returns the cosine of the angle X in radians.
*
* ATAN: ArcTangent function which can be used as ATAN(X)
*
* SINH: Sinus Hyperbolic function which can be used as SINH(X)
*
* COSH: Cosinus Hyperbolic function which can be used as COSH(X)
*
* COTAN: which can be used as COTAN(X)
*
* TAN: which can be used as TAN(X)
*
* EXP: which can be used as EXP(X)
*
* LN: natural log, which can be used as LN(X)
*
* LOG: 10 based log, which can be used as LOG(X)
*
* SQRT: which can be used as SQRT(X)
*
* ABS: absolute value, which can be used as ABS(X)
*
* SIGN: SIGN(X) returns -1 if X<0; +1 if X>0, 0 if X=0; it can be used as SQR(X)
*
* TRUNC: Discards the fractional part of a number. e.g. TRUNC(-3.2) is -3, TRUNC(3.2) is 3.
*
* CEIL: CEIL(-3.2) = -3, CEIL(3.2) = 4
*
* FLOOR: FLOOR(-3.2) = -4, FLOOR(3.2) = 3
*
* RND: Random number generator.
*
* RND(X) generates a random INTEGER number such that 0 <= Result < int(X). Call Parser.Randomize to initialize the random number generator with a random seed value before using RND function in your expression.
*
* RANDOM: Random number generator.
*
* RANDOM(X) generates a random floating point number such that 0 <= Result < X. Call Parser.Randomize to initialize the random number generator with a random seed value before using RANDOM function in your expression.
*
* Predefined functions that take two parameters are:
*
* INTPOW: The INTPOW function raises Base to an integral power. INTPOW(2, 3) = 8. Note that result of INTPOW(2, 3.4) = 8 as well.
*
* POW: The Power function raises Base to any power. For fractional exponents or exponents greater than MaxInt, Base must be greater than 0.
*
* LOGN: The LogN function returns the log base N of X. Example: LOGN(10, 100) = 2
*
* MIN: MIN(2, 3, 4, 5) is 2.
*
* MAX: MAX(2, 3, 1, 0) is 3.
*
* IF: IF(1, 2, 3) is 2.
*
* SUM: SUM(1, 2, 3, 4) is 10.
*
* AVG: AVG(1, 2, 3, 4, 5) is 3.
*
*/
virtual void CreateDefaultFuncs();
/**
* Evaluate the expression to it's value.
* Throw CMathParser::ParserException if the expression can not be parsed.
*/
_ValueT Evaluate() throw (ParserException);
/**
* Return current optimization setting.
* If OptimizationOn is set to TRUE, then the parser will eliminate
* expression sub-trees that evaluate to a constant expression so that
* they can be skipped in repeated evaluations.
*/
BOOL GetOptimizationOn();
/**
* If OptimizationOn is set to TRUE, then the parser will eliminate
* expression sub-trees that evaluate to a constant expression so that
* they can be skipped in repeated evaluations.
*/
void SetOptimizationOn(BOOL newVal);
/**
* Set the value of a variable. This will define the variable if it is not defined yet.
*/
void SetVariable(string_t varName, _ValueT varValue) throw(ParserException);
/**
* Get the current value of a variable.
* Throws CMathParser::ParserException if variable is not defined yet.
*/
_ValueT GetVariable(string_t varName);
/**
* Return value of variable Y.
*
* Since X, and Y are commonly used in math expressions, CMathParser defines them by default.
* If you don't like X and Y, you can override CreateDefaultVars, or you can
* call DeleteAllVars() function.
*/
_ValueT GetY();
/**
* Set value of variable Y.
*
* Since X, and Y are commonly used in math expressions, CMathParser defines them by default.
* If you don't like X and Y, you can override CreateDefaultVars, or you can
* call DeleteAllVars() function.
*/
void SetY(_ValueT newVal);
/**
* Return value of variable X.
*
* Since X, and Y are commonly used in math expressions, CMathParser defines them by default.
* If you don't like X and Y, you can override CreateDefaultVars, or you can
* call DeleteAllVars() function.
*/
_ValueT GetX();
/**
* Set value of variable X.
*
* Since X, and Y are commonly used in math expressions, CMathParser defines them by default.
* If you don't like X and Y, you can override CreateDefaultVars, or you can
* call DeleteAllVars() function.
*/
void SetX(_ValueT newVal);
/**
* Parse the expression, evaluate it and return the result.
*/
_ValueT GetValue();
/**
* Set the expression to parse.
* The expression may contain :
* 1. variables such as X, Y, Z, TEMP, STRESS, STRAIN etc.
* 2. functions such as SIN(X), MIN(A,B), MYFUNC(D)
* 3. constants such as 2, 3, 50
* 4. scientific notation like: 3E+10
* 5. aithmetic operators: +,-,*,/,%(modulus),^(power)
* 6. logical operators : =,<,>,<>,>=,<=
*
* Example expressions are:
*
* "X+Y/2"
* "SIN(X)+AVG(A,B,C)"
* "SUM(X,Y,Z,K,L)/5"
*/
void SetExpression(string_t expr);
/**
* Return the current expression string.
*/
string_t GetExpression();
/**
* VariableCallback is a function that is implemented by the user to provide values for undefined variables.
* If VariableCallback is set for the CMathParser instance, then the parser will
* tolerate undefined variables during parsing and it will invoke the user defined
* VariableCallback function to retrieve the variables values during evaluation.
* If VariableCallback is NULL, then the parser will require that all variables used in an expression
* are predefined before the parse operation.
* VariableCallback is useful in situations where the application domain is so large that
* defining every possible variable ahead of time is not possible.
* VariableCallback implementation should decide whether a variable name is valid and what it's
* value should be. If the variable name is not valid, then the VariableCallback should throw
* an exception and stop the expression evaluation.
* VariableCallback typedef for the function signature is as follows:
* typedef _ValueT VariableCallback(CMathParser<_CharT, _ValueT> *pParentParser, const string_t varName);
* The user defined function takes two parameters:
* 1. A pointer to the parser instance making this call.
* 2. The variable name as a string.
* Return value shall be the desired value for this variable name.
* If the variable is not valid, then an exception should be thrown.
* CMathParser::ParserException is a good canditate to throw in such case.
*/
void SetVariableCallback(PVariableCallback callbackFunction);
/**
* See SetVariableCallback.
*/
PVariableCallback GetVariableCallback();
/**
* Returns the list of currently defined functions as a vector of strings.
*/
vector<string_t> GetDefinedFunctionNames();
/**
* Returns the list of currently defined variables as a vector of strings.
*/
vector<string_t> GetDefinedVariableNames();
/**
* Returns the list of currently defined functions (and their respective param counts) as a map of strings and ints.
*/
std::map<string_t, int> GetDefinedFunctionInfo();
}
#endif //__MATH_PARSER_H_
|