/* Copyright (c) 2008-2019 Jan W. Krieger () This software is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License (LGPL) for more details. You should have received a copy of the GNU Lesser General Public License (LGPL) along with this program. If not, see . */ /*! \defgroup jkmp Parser/Evaluator for Mathematical Expressions \ingroup jkqtptools_math In this group there are classes that form a parser and evaluator for mathematical expressions. In the context of the sequencer program this is a tool class that can be used by the classes in the project. E.g. used by JKQTPXParsedFunctionLineGraph, JKQTPYParsedFunctionLineGraph */ /** * \defgroup jkmpultil utilities for jkMathParser function parser class * \ingroup jkmp */ /** * \defgroup jkmpNodes memory representation of expressions * \ingroup jkmp */ /** * \defgroup jkmpErrorhandling error handling * \ingroup jkmp */ /** \file jkqtpmathparser.h * \ingroup jkmp */ #include #include #include #include #include #include #include #include #include #include #include #include "jkqtplottertools/jkqtptools.h" #ifndef JKQTPMATHPARSER_H #define JKQTPMATHPARSER_H /*! \brief A simple function parser to parse (build memory tree representation) and evaluate simple mathematical expressions \ingroup jkmp This class implements a simple function parser which can parse mathematical expressions like z=a*3+2.34^2*sin(pi*sqrt(x)) . More than one expression can be separated by semicolon ';'. The result of a parse operation will be a memory structure (tree) representing the given expression. The parser can cope with constants and (user defined) variables and supports the data types number (double precision floating point), boolean (true/false) and string. It already contains a lot of fundamental mathematical functions (i.e. nearly all the functions from C StdLib). \section jkmp_constantsAndVars constants and variables: This class provides management utilities for constants and variables. Variables can also be defined as external variables, when a pointer to corresponding memory is provided by the calling program. The parser supports a variable assign operation \code a=\endcode which allows to define new variables during evaluation. There are some mathematical standard constants registered by calling jkMathParser::addStandardVariables(): - \c pi = \f$ \pi \f$ - \c e = \f$ \exp(1) \f$ - \c sqrt2 = \f$ \sqrt{2} \f$ - \c version = the parser version - \c log2e = \f$ \log_2(e) \f$ - \c log10e = \f$ \log_{10}(e) \f$ - \c ln2 = \f$ \ln(2)=\log_{e}(2) \f$ - \c ln10 = \f$ \ln(10)=\log_{e}(10) \f$ - \c h = \f$ 6.6260689633\cdot 10^{-34}\;\mathrm{J\cdot s} \f$ (planck constant) - \c hbar = \f$ \hbar=\frac{h}{2\pi}= 1.05457162853\cdot 10^{-34}\;\mathrm{J\cdot s} \f$ (planck constant) - \c epsilon0 = \f$ \epsilon_0= 8.854187817\cdot 10^{-12}\;\mathrm{\frac{F}{m}} \f$ (electric constant) - \c mu0 = \f$ \mu_0=2\pi\cdot 10^{-7}= 12.566370614\cdot 10^{-7}\;\mathrm{\frac{N}{A^2}} \f$ (magnetic constant) - \c c = \f$ 299792458\;\mathrm{\frac{m}{s}} \f$ (speed of light in vacuum) - \c ce = \f$ 1.60217648740\cdot 10^{-19}\;\mathrm{C}\f$ (elementary charge) - \c muB = \f$ \mu_B= 927.40091523\cdot 10^{-26}\;\mathrm{\frac{J}{T}} \f$ (Bohr magneton) - \c muB_eV = \f$ \mu_B=5.788381755579\cdot 10^{-5}\;\mathrm{\frac{eV}{T}} \f$ (Bohr magneton) - \c muN = \f$ \mu_N=5.0507832413\cdot 10^{-27}\;\mathrm{\frac{J}{T}} \f$ (nuclear magneton) - \c muN_eV = \f$ \mu_N=3.152451232645\cdot 10^{-8}\;\mathrm{\frac{eV}{T}} \f$ (nuclear magneton) - \c me = \f$ m_e= 9.1093821545\cdot 10^{-31}\;\mathrm{kg} \f$ (mass of electron) - \c mp = \f$ m_p= 1.67262163783\cdot 10^{-27}\;\mathrm{kg} \f$ (mass of proton) - \c mn = \f$ m_n= 1.67492721184\cdot 10^{-27}\;\mathrm{kg} \f$ (mass of neutron) - \c NA = \f$ N_A= 6.0221417930\cdot 10^{23} \f$ (Avogadro constant = particles in 1 mol) - \c kB = \f$ k_B=1.380650424\cdot 10^{-23}\;\mathrm{\frac{J}{K}} \f$ (Boltzman constant) - \c kB_eV = \f$ k_B=8.61734315\cdot 10^{-5}\;\mathrm{\frac{eV}{K}} \f$ (Boltzman constant) . You can add user-defined contants by calling jkMathParser::addVariableDouble() jkMathParser::addVariableBoolean() or jkMathParser::addVariableString() \section jkmp_functions functions: this class provides a wide range of (mathematical) functions: - sinc, gauss, slit, theta, tanc, sigmoid - asin, acos, atan, atan2, - sin, cos, tan, - sinh, cosh, tanh - log, log2, log10, - exp, sqr, sqrt - abs, sign - if - erf, erfc, lgamma, tgamma, j0, j1, jn, y0, y1, yn - rand, srand - ceil, floor, trunc, round, - fmod, min, max - floattostr, booltostr/bool2str, inttostr, num2str - tosystempathseparator - setdefault - strdate - cmdparam, argv . these functions are registere by calling jkMathParser::addStandardFunctions(). you can add new functions by calling jkMathParser::addFunction(); \section jkmp_resultsofparsing result of parsing and evaluation: The result of calling jkMathParser::parse() will be a tree-like structure in memory. The parse() function will return a pointer to the root node of this structure. All nodes inherit from jkmpNode class. To evaluate such a structure simply call jkmpNode::evaluate() of the root node. This will then return a jkmpResult structure which contains the result. This scheme allows for once parsing and multiply evaluating an expression. So if you want to define a function by an expression you can provide an external variable x as the argument and then evaluate the function for each x. \section jkmp_ebnf EBNF definition of the parsed expressions
 logical_expression ->  logical_term
                      | logical_expression or logical_term
                      | logical_expression || logical_term
 logical_term    ->  comp_expression
                      | logical_term and comp_expression
                      | logical_term && comp_expression
 comp_expression  ->  math_expression
                      | expression == math_expression
                      | expression != math_expression
                      | expression >= math_expression
                      | expression <= math_expression
                      | expression > math_expression
                      | expression < math_expression
  math_expression ->  term
                      | math_expression + math_term
                      | math_expression - math_term
  math_term       ->  primary
                      | term * primary
                      | term / primary
                      | term ( % | mod ) primary
  primary         ->  true | false
                      | string_constant
                      | NUMBER
                      | NAME
                      | NAME = logical_expression
                      | + primary | - primary | ! primary | not primary
                      | ( logical_expression )
                      | NAME( parameter_list )
                      | primary ^ primary
  string_constant -> " STRING " | ' STRING '
  parameter_list  ->  \f$ \lambda \f$ | logical_expression | logical_expression , parameter_list
\section jkmp_example Simple Example of Usage \code try { jkMathParser mp; // instanciate jkmpNode* n; jkmpResult r; // parse some numeric expression n=mp.parse("pi^2+4*sin(65*pi/exp(3.45))"); r=n->evaluate(); cout<evaluate(); if (r.type==jkmpBool) { if (r.boolean) cout<<"true"; else cout<<"false"; } if (r.type==jkmpDouble) cout<evaluate(); if (r.type==jkmpString) cout<' */ COMP_SMALLER, /*!< \brief smaller than operation '<' */ COMP_GEQUAL, /*!< \brief greater than or equal operation '>=' */ COMP_SEQUAL, /*!< \brief smaller than or equal operation '<=' */ }; /** \brief internal names for logic operations * \ingroup jkmpultil */ enum { jkmpLOPand='a', jkmpLOPor='o', jkmpLOPxor='x', jkmpLOPnor='n', jkmpLOPnand='A', jkmpLOPnot='n' }; /** \brief jkmpCOMPdefs internal names for compare operations * \ingroup jkmpultil*/ enum { jkmpCOMPequal='=', jkmpCOMPnequal='!', jkmpCOMPlesser='<', jkmpCOMPgreater='>', jkmpCOMPlesserequal='a', jkmpCOMPgreaterequal='b' }; public: /** \brief possible result types * \ingroup jkmpultil */ enum jkmpResultType {jkmpDouble, /*!< \brief a floating-point number with double precision. This is also used to deal with integers */ jkmpString, /*!< \brief a string of characters */ jkmpBool}; /*!< \brief a boolean value true|false */ /** \brief result of any expression * \ingroup jkmpultil*/ struct jkmpResult { jkmpResult(); bool isValid; jkmpResultType type; /*!< \brief type of the result */ std::string str; /*!< \brief contains result if \c type==jkmpString */ double num; /*!< \brief contains result if \c type==jkmpDouble */ bool boolean; /*!< \brief contains result if \c type==jkmpBool */ /** \brief convert the value this struct representens into a std::string */ inline std::string toString() { switch(type) { case jkmpDouble: return jkqtp_floattostr(num); case jkmpString: return str; case jkmpBool: return jkqtp_booltostr(boolean); } return ""; } /** \brief convert the value this struct representens into a std::string and adds the name of the datatype in \c [...] */ inline std::string toTypeString() { switch(type) { case jkmpDouble: return jkqtp_floattostr(num)+" [number]"; case jkmpString: return str+" [string]"; case jkmpBool: return jkqtp_booltostr(boolean)+" [bool]"; } return ""; } }; /** \brief This struct is for managing variables. Unlike jkmpResult this struct * only contains pointers to the data * \ingroup jkmpultil */ struct jkmpVariable { jkmpVariable(); jkmpResultType type; /*!< \brief type of the variable */ bool internal; /*!< \brief this is an internal variable */ std::string *str; /*!< \brief this points to the variable data if \c type==jkmpString */ double *num; /*!< \brief this points to the variable data if \c type==jkmpDouble */ bool *boolean; /*!< \brief this points to the variable data if \c type==jkmpBool */ }; /** \brief This struct is for managing temporary variables. It is generally like jkmpVariable. * \ingroup jkmpultil */ struct jkmpTempVariable { std::string name; /*!< \brief name of the variable */ jkmpResultType type; /*!< \brief type of the variable */ bool internal; /*!< \brief this is an internal variable */ std::string *str; /*!< \brief this points to the variable data if \c type==jkmpString */ double *num; /*!< \brief this points to the variable data if \c type==jkmpDouble */ bool *boolean; /*!< \brief this points to the variable data if \c type==jkmpBool */ }; /** \brief This is a function prototype for adding new mathematical functions * to the parser * * If you want to add more math functions (like sin, cos , abs ...) to the * parser, you will have to implement it with this prototype and then register * it with jkMathParser::addFunction(). The first parameter points to an array * containing the input parameters while the second one specifies the number * of supplied parameters. The result has to be of type jkmpResult. * * All error handling has to be done inside the function definition. Here is a * simple example: * \code * jkmpResult Abs(jkmpResult* params, unsigned char n){ * jkmpResult r; * r.type=jkmpDouble; * if (n!=1) jkmpError("abs accepts 1 argument"); * if (params[0].type!=jkmpDouble) jkmpError("abs needs double argument"); * r.num=fabs(params[0].num); * return r; * } * \endcode */ typedef jkmpResult (*jkmpEvaluateFunc)(jkmpResult*, unsigned char, JKQTPMathParser*); /** \brief description of a user registered function */ struct jkmpFunctionDescriptor { jkmpEvaluateFunc function; /*!< \brief a pointer to the function implementation */ std::string name; /*!< \brief name of the function */ }; /** * \brief This class is the abstract base class for nodes. * All allowed node types must inherit from jkmpNode * \ingroup jkmpNodes */ class jkmpNode { protected: JKQTPMathParser* parser; /*!< \brief points to the parser object that is used to evaluate this node */ jkmpNode* parent; /*!< \brief points to the parent node */ public: /** \brief virtual class destructor */ virtual ~jkmpNode(); /** \brief evaluate this node */ virtual jkmpResult evaluate()=0; /** \brief return a pointer to the jkMathParser */ inline JKQTPMathParser* getParser(){ return parser; } /** \brief set the jkMathParser */ inline void setParser(JKQTPMathParser* mp){ parser=mp; } /** \brief returns a pointer to the parent node */ inline jkmpNode* getParent(){ return parent; } /** \brief sets the parent node */ inline void setParent(jkmpNode* par) { parent=par; } }; /** * \brief This class represents a binary arithmetic operation: * add (+), subtract (-), multiply (*), divide (/), a to the power of b (a^b) * \ingroup jkmpNodes */ class jkmpBinaryArithmeticNode: public jkmpNode { private: jkmpNode* left, *right; char operation; public: /** \brief constructor for a jkmpBinaryArithmeticNode * \param op the operation to be performed: add (+), subtract (-), multiply (*), divide (/), a to the power of b (a^b) * \param l left child node/operand * \param r right child node/operand * \param p a pointer to a jkMathParser object * \param par a pointer to the parent node */ jkmpBinaryArithmeticNode(char op, jkmpNode* l, jkmpNode* r, JKQTPMathParser* p, jkmpNode* par); /** \brief standard destructor, also destroy the children (recursively) */ virtual ~jkmpBinaryArithmeticNode() override; /** \brief evaluate this node */ virtual jkmpResult evaluate() override; }; /** * \brief This class represents a binary boolean operation: and, or, xor, nor, nand * \ingroup jkmpNodes */ class jkmpBinaryBoolNode: public jkmpNode { private: jkmpNode* left, *right; char operation; public: /** \brief constructor for a jkmpBinaryBoolNode * \param op the operation to be performed: (a)nd, (o)r, (x)or, (n)or, nand (A) * \param l left child node/operand * \param r right child node/operand * \param p a pointer to a jkMathParser object * \param par a pointer to the parent node */ jkmpBinaryBoolNode(char op, jkmpNode* l, jkmpNode* r, JKQTPMathParser* p, jkmpNode* par); /** \brief standard destructor, also destroy the children (recursively) */ virtual ~jkmpBinaryBoolNode() override; /** \brief evaluate this node */ virtual jkmpResult evaluate() override; }; /** * \brief This class represents a binary compare operation: !=, ==, >=, <=, >, < * \ingroup jkmpNodes */ class jkmpCompareNode: public jkmpNode { private: jkmpNode* left, *right; char operation; public: /** \brief constructor for a jkmpCompareNode * \param op the operation to be performed: != (!), == (=), >= (b), <= (a), (>), (<) * \param l left child node/operand * \param r right child node/operand * \param p a pointer to a jkMathParser object * \param par a pointer to the parent node */ jkmpCompareNode(char op, jkmpNode* l, jkmpNode* r, JKQTPMathParser* p, jkmpNode* par); /** \brief standard destructor, also destroy the children (recursively) */ virtual ~jkmpCompareNode () override; /** \brief evaluate this node */ virtual jkmpResult evaluate() override; }; /** * \brief This class represents a unary operations: ! (bool negation), - (arithmetic negation) * \ingroup jkmpNodes */ class jkmpUnaryNode: public jkmpNode { private: jkmpNode* child; char operation; public: /** \brief constructor for a jkmpUnaryNode * \param op the operation to be performed: (!), (-) * \param c child node/operand * \param p a pointer to a jkMathParser object * \param par a pointer to the parent node */ jkmpUnaryNode(char op, jkmpNode* c, JKQTPMathParser* p, jkmpNode* par); /** \brief standard destructor, also destroy the children (recursively) */ virtual ~jkmpUnaryNode() override; /** \brief evaluate this node */ virtual jkmpResult evaluate() override; }; /** * \brief This class represents a variable assignment (a = expression) * \ingroup jkmpNodes */ class jkmpVariableAssignNode: public jkmpNode { private: jkmpNode* child; std::string variable; //char operation; public: /** \brief standard destructor, also destroy the children (recursively) */ virtual ~jkmpVariableAssignNode() override; /** \brief constructor for a jkmpVariableAssignNode * \param var name of the variable to assign to * \param c child node/right-hand-side expression * \param p a pointer to a jkMathParser object * \param par a pointer to the parent node */ jkmpVariableAssignNode(std::string var, jkmpNode* c, JKQTPMathParser* p, jkmpNode* par); /** \brief evaluate this node */ virtual jkmpResult evaluate() override; }; /** * \brief This class represents a number, a string contant or a boolean contant (true/false) * \ingroup jkmpNodes */ class jkmpConstantNode: public jkmpNode { private: jkmpResult data; public: /** \brief constructor for a jkmpConstantNode * \param d the value of the constant * \param p a pointer to a jkMathParser object * \param par a pointer to the parent node */ jkmpConstantNode(jkmpResult d, JKQTPMathParser* p, jkmpNode* par); /** \brief evaluate this node */ virtual jkmpResult evaluate() override; }; /** * \brief This class represents a variable. * \ingroup jkmpNodes */ class jkmpVariableNode: public jkmpNode { private: std::string var; public: /** \brief constructor for a jkmpVariableNode * \param name name of the variable * \param p a pointer to a jkMathParser object * \param par a pointer to the parent node */ jkmpVariableNode(std::string name, JKQTPMathParser* p, jkmpNode* par); /** \brief evaluate this node */ virtual jkmpResult evaluate() override; }; /** * \brief This class represents an arbitrary function. * \ingroup jkmpNodes * * When initialized this class will get the function description that is * linked to the supplied function name from jkMathParser object. This * information is saved locally and won't be changed when evaluating! * * Functions may have 8 parameters at the most. */ class jkmpFunctionNode: public jkmpNode { private: std::string fun; jkmpNode** child; unsigned char n; jkmpEvaluateFunc function; public: /** \brief constructor for a jkmpFunctionNode * \param name name of the function * \param c a pointer to an array of jkmpNode objects that represent the parameter expressions * \param num number of children in c * \param p a pointer to a jkMathParser object * \param par a pointer to the parent node */ jkmpFunctionNode(std::string name, jkmpNode** c, unsigned char num, JKQTPMathParser* p, jkmpNode* par); /** \brief standard destructor, also destroy the children (recursively) */ virtual ~jkmpFunctionNode() override; /** \brief evaluate this node */ virtual jkmpResult evaluate() override; }; /** * \brief This class represents a list of jkmpNode. * \ingroup jkmpNodes * * when evaluating the result will be the result of the last node in the list. */ class jkmpNodeList: public jkmpNode { private: std::vector list; public: /** \brief constructor for a jkmpNodeList * \param p a pointer to a jkMathParser object */ jkmpNodeList(JKQTPMathParser* p); /** \brief standard destructor, also destroy the children (recursively) */ virtual ~jkmpNodeList() override; /** \brief add a jkmpNode n to the list */ void add(jkmpNode* n); /** \brief evaluate the node */ virtual jkmpResult evaluate() override; /** \brief get the number of nodes in the list */ inline int getCount() {return list.size();}; }; /*@}*/ public: /** \brief error handling: exceptions of the type of this class will be thrown if an error occurs * \ingroup jkmpErrorhandling * * \attention If you do not want to use the exception handling which throws * jkmpException exceptions, but want to write your own error handling, you should write your own * error handler and assign it (function pointer) to the global variable jkmathparser_exception_function. * If this is not nullptr this function will be called instead of throwing an exception. */ class jkmpException : public std::exception { private: /** \brief the error message */ std::string errormessage; public: /** \brief class constructors */ inline jkmpException() { errormessage="unknown error"; } /** \brief constructor with supplied error message */ inline jkmpException(std::string msg) { errormessage=msg; } /** \brief class destructors */ virtual ~jkmpException() override; /** \brief returns the assigned errormessage */ inline std::string getMessage() const { return errormessage; } /** \brief returns the error description as C string */ virtual const char* what() const throw(); }; /** \brief type for a custom error handler. This an alternative error handling * \ingroup jkmpErrorhandling */ typedef void (*jkmpexceptionf)(std::string); /** \brief function that throws an exception or calls an error handler * \ingroup jkmpErrorhandling */ inline void jkmpError(std::string st) { if (jkmathparser_exception_function!=nullptr) { jkmathparser_exception_function(st); } else { throw jkmpException(st); } } private: /** \brief if this is nullptr then an exception may be thrown otherwise this should point to an error handler that will be called. * \ingroup jkmpErrorhandling */ jkmpexceptionf jkmathparser_exception_function; public: /** \brief activate error handling by use of an exception function * \ingroup jkmpErrorhandling */ inline void set_exception_function(jkmpexceptionf exception_function) { jkmathparser_exception_function=exception_function; } /** \brief deactivate error handling by use of an exception function * \ingroup jkmpErrorhandling */ inline void reset_exception_function() { jkmathparser_exception_function=nullptr; } protected: /** \brief return the given token as human-readable string */ std::string tokentostring(jkmpTokenType token); /** \brief return the current token as human-readable string */ std::string currenttokentostring(); /** \brief Tokenizer: extract the next token from the input */ jkmpTokenType getToken(); /** \brief return a delimited text, i.e. extract the texte between the delimiters " in: of "Hallo!", i.e. returns Hallo! * This is used to parse string constants. * * This functions actually reads pascal style delimited string constants. So if you want to use the delimiter as part of the string you will have to * write it as doubled character. So 'Jan''s Test' stands for Jan's Test. */ std::string readDelim(char delimiter); /** \brief recognizes an compExpression while parsing. If \a get ist \c true, this function first retrieves a new token by calling getToken() */ jkmpNode* compExpression(bool get); /** \brief recognizes a logicalExpression while parsing. If \a get ist \c true, this function first retrieves a new token by calling getToken() */ jkmpNode* logicalExpression(bool get); /** \brief recognizes a logicalTerm while parsing. If \a get ist \c true, this function first retrieves a new token by calling getToken() */ jkmpNode* logicalTerm(bool get); /** \brief recognizes a mathExpression while parsing. If \a get ist \c true, this function first retrieves a new token by calling getToken() */ jkmpNode* mathExpression(bool get); /** \brief recognizes a term while parsing. If \a get ist \c true, this function first retrieves a new token by calling getToken() */ jkmpNode* mathTerm(bool get); /** \brief recognizes a primary while parsing. If \a get ist \c true, this function first retrieves a new token by calling getToken() */ jkmpNode* primary(bool get); /** \brief this stream is used to read in the program. An object is created and assigned * (and destroyed) by the parse()-function */ std::istringstream* program; /** \brief vector containing all temporary variables */ std::vector tempvariables; /** \brief map to manage all currently defined variables */ std::map variables; /** \brief map to manage all currently rtegistered functions */ std::map functions; /** \brief the current token while parsing a string */ jkmpTokenType CurrentToken; /** \brief the string value of the current token (when applicable) during the parsing step */ std::string StringValue; /** \brief the string value of the current token (when applicable) during the parsing step */ double NumberValue; /** \brief set the defining struct of the given variable */ void setVariable(std::string name, jkmpResult value); /** \brief set the defining struct of the given variable */ void setVariableDouble(std::string name, double value); /** \brief adds a temporary variable */ void addTempVariable(std::string name, jkmpResult value); protected: int argc; char **argv; public: /** \brief class constructor */ JKQTPMathParser(); /** \brief class destructor */ virtual ~JKQTPMathParser(); /*! \brief sets the property data to the specified \a __value. \details Description of the parameter data is:
\copybrief data
\see data for more information */ inline virtual void set_data(void* __value) { this->data = __value; } /*! \brief returns the property data. \details Description of the parameter data is:
\copybrief data
\see data for more information */ inline virtual void* get_data() const { return this->data; } /** \brief register a new function * \param name name of the new function * \param function a pointer to the implementation */ void addFunction(std::string name, jkmpEvaluateFunc function); /** \brief register a new external variable of type double * \param name name of the new variable * \param v pointer to the variable memory */ void addVariableDouble(std::string name, double* v); /** \brief register a new external variable of type string * \param name name of the new variable * \param v pointer to the variable memory */ void addVariableString(std::string name, std::string* v); /** \brief register a new external variable of type boolean * \param name name of the new variable * \param v pointer to the variable memory */ void addVariableBoolean(std::string name, bool* v); /** \brief register a new internal variable of type double * \param name name of the new variable * \param v initial value of this variable */ void addVariableDouble(std::string name, double v); /** \brief register a new internal variable of type string * \param name name of the new variable * \param v initial value of this variable */ void addVariableString(std::string name, std::string v); /** \brief register a new internal variable of type boolean * \param name name of the new variable * \param v initial value of this variable */ void addVariableBoolean(std::string name, bool v); /** \brief register a new internal variable of type boolean * \param name name of the new variable * \param v initial value of this variable */ void addVariable(std::string name, jkmpResult result); /** \brief returns the value of the given variable */ jkmpResult getVariable(std::string name); /** \brief returns the value of the given variable */ jkmpResult getVariableOrInvalid(std::string name); /** \brief returns the defining structure of the given variable */ jkmpVariable getVariableDef(std::string name); /** \brief evaluates a registered function * \param name name of the (registered function) to be evaluated * \param params array of the input parameters * \param n number of input parameters (<=8) */ jkmpResult evaluateFunction(std::string name, jkmpResult* params, unsigned char n); /** \brief returns the defining structure of the given function */ jkmpEvaluateFunc getFunctionDef(std::string name); /** \brief tests whether a temporary variable exists */ inline bool tempvariableExists(std::string name){ if (tempvariables.size()<=0) return false; for (int i=tempvariables.size()-1; i>=0; i--) { if (tempvariables[i].name==name) return true; } return false; } /** \brief tests whether a variable exists */ inline bool variableExists(std::string name){ return tempvariableExists(name)||(variables.find(name)!=variables.end()); }; /** \brief tests whether a function exists */ inline bool functionExists(std::string name){ return !(functions.find(name)==functions.end()); }; /** \brief deletes all defined variables. the memory of internal variables * will be released. the external memory will not be released. */ void clearVariables(); /** \brief delete the specified variabale and releases its internal memory.*/ void deleteVariable(std::string name); /** \brief clears the list of internal functions*/ inline void clearFunctions() {functions.clear();} /** \brief registers standard variables*/ void addStandardVariables(); /** \brief registers standard functions*/ void addStandardFunctions(); /** \brief parses the given expression*/ jkmpNode* parse(std::string prog); /** \brief evaluate the given expression */ jkmpResult evaluate(std::string prog); /** \brief prints a list of all registered variables */ void printVariables(); /** \brief returns all registered variables */ std::vector > getVariables(); /** \brief store programs command-line arguments, so they are available in the parser */ void setArgCV(int argc, char **argv); /** \brief return one of programs command-line arguments, or \a defaultResult if it is not present */ std::string getArgCVParam(std::string name, std::string defaultResult); }; #endif // JKQTPMATHPARSER_H