JKQTPlotter trunk/v5.0.0
an extensive Qt5+Qt6 Plotter framework (including a feature-richt plotter widget, a speed-optimized, but limited variant and a LaTeX equation renderer!), written fully in C/C++ and without external dependencies
Loading...
Searching...
No Matches
jkqtpmathparser.h
1/*
2 Copyright (c) 2008-2024 Jan W. Krieger (<jan@jkrieger.de>)
3
4
5
6 This software is free software: you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License (LGPL) as published by
8 the Free Software Foundation, either version 2.1 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License (LGPL) for more details.
15
16 You should have received a copy of the GNU Lesser General Public License (LGPL)
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20
21#include <iostream>
22#include <string>
23#include <cstdio>
24#include <vector>
25#include <map>
26#include <sstream>
27#include <exception>
28#include <ctype.h>
29#include <list>
30#include <utility>
31#include "jkqtmath/jkqtmath_imexport.h"
32
33#ifndef JKQTPMATHPARSER_H
34#define JKQTPMATHPARSER_H
35
36
37
38
39/*! \brief A simple function parser to parse (build memory tree representation) and
40 evaluate simple mathematical expressions
41 \ingroup jkqtptools_math_parser
42
43
44 This class implements a simple function parser which can parse
45 mathematical expressions like <code> z=a*3+2.34^2*sin(pi*sqrt(x))</code> .
46 More than one expression can be separated by semicolon ';'. The result of
47 a parse operation will be a memory structure (tree) representing the given
48 expression.
49 The parser can cope with constants and (user defined) variables and supports
50 the data types number (double precision floating point), boolean (true/false)
51 and string. It already contains a lot of fundamental mathematical functions
52 (i.e. nearly all the functions from C StdLib).
53
54 \section jkmp_constantsAndVars constants and variables:
55 This class provides management utilities for constants and variables. Variables
56 can also be defined as external variables, when a pointer to corresponding
57 memory is provided by the calling program. The parser supports a variable
58 assign operation \code a=<expression>\endcode which allows to define new
59 variables during evaluation. There are some mathematical standard constants
60 registered by calling JKQTPMathParser::addStandardVariables():
61 - \c pi = \f$ \pi \f$
62 - \c e = \f$ \exp(1) \f$
63 - \c sqrt2 = \f$ \sqrt{2} \f$
64 - \c version = the parser version
65 - \c log2e = \f$ \log_2(e) \f$
66 - \c log10e = \f$ \log_{10}(e) \f$
67 - \c ln2 = \f$ \ln(2)=\log_{e}(2) \f$
68 - \c ln10 = \f$ \ln(10)=\log_{e}(10) \f$
69 - \c h = \f$ 6.6260689633\cdot 10^{-34}\;\mathrm{J\cdot s} \f$ (planck constant)
70 - \c hbar = \f$ \hbar=\frac{h}{2\pi}= 1.05457162853\cdot 10^{-34}\;\mathrm{J\cdot s} \f$ (planck constant)
71 - \c epsilon0 = \f$ \epsilon_0= 8.854187817\cdot 10^{-12}\;\mathrm{\frac{F}{m}} \f$ (electric constant)
72 - \c mu0 = \f$ \mu_0=2\pi\cdot 10^{-7}= 12.566370614\cdot 10^{-7}\;\mathrm{\frac{N}{A^2}} \f$ (magnetic constant)
73 - \c c = \f$ 299792458\;\mathrm{\frac{m}{s}} \f$ (speed of light in vacuum)
74 - \c ce = \f$ 1.60217648740\cdot 10^{-19}\;\mathrm{C}\f$ (elementary charge)
75 - \c muB = \f$ \mu_B= 927.40091523\cdot 10^{-26}\;\mathrm{\frac{J}{T}} \f$ (Bohr magneton)
76 - \c muB_eV = \f$ \mu_B=5.788381755579\cdot 10^{-5}\;\mathrm{\frac{eV}{T}} \f$ (Bohr magneton)
77 - \c muN = \f$ \mu_N=5.0507832413\cdot 10^{-27}\;\mathrm{\frac{J}{T}} \f$ (nuclear magneton)
78 - \c muN_eV = \f$ \mu_N=3.152451232645\cdot 10^{-8}\;\mathrm{\frac{eV}{T}} \f$ (nuclear magneton)
79 - \c me = \f$ m_e= 9.1093821545\cdot 10^{-31}\;\mathrm{kg} \f$ (mass of electron)
80 - \c mp = \f$ m_p= 1.67262163783\cdot 10^{-27}\;\mathrm{kg} \f$ (mass of proton)
81 - \c mn = \f$ m_n= 1.67492721184\cdot 10^{-27}\;\mathrm{kg} \f$ (mass of neutron)
82 - \c NA = \f$ N_A= 6.0221417930\cdot 10^{23} \f$ (Avogadro constant = particles in 1 mol)
83 - \c kB = \f$ k_B=1.380650424\cdot 10^{-23}\;\mathrm{\frac{J}{K}} \f$ (Boltzman constant)
84 - \c kB_eV = \f$ k_B=8.61734315\cdot 10^{-5}\;\mathrm{\frac{eV}{K}} \f$ (Boltzman constant)
85.
86 You can add user-defined contants by calling JKQTPMathParser::addVariableDouble()
87 JKQTPMathParser::addVariableBoolean() or JKQTPMathParser::addVariableString()
88
89
90 \section jkmp_functions functions:
91 this class provides a wide range of (mathematical) functions:
92 - sinc, gauss, slit, theta, tanc, sigmoid
93 - asin, acos, atan, atan2,
94 - sin, cos, tan,
95 - sinh, cosh, tanh
96 - log, log2, log10,
97 - exp, sqr, sqrt
98 - abs, sign
99 - if
100 - erf, erfc, lgamma, tgamma, j0, j1, jn, y0, y1, yn
101 - rand, srand
102 - ceil, floor, trunc, round,
103 - fmod, min, max
104 - floattostr, booltostr/bool2str, inttostr, num2str
105 - tosystempathseparator
106 - setdefault
107 - strdate
108 - cmdparam, argv
109 .
110
111 these functions are registered by calling JKQTPMathParser::addStandardFunctions().
112 you can add new functions by calling JKQTPMathParser::addFunction();
113
114 \section jkmp_resultsofparsing result of parsing and evaluation:
115 The result of calling JKQTPMathParser::parse()
116 will be a tree-like structure in memory. The parse() function will return
117 a pointer to the root node of this structure. All nodes inherit from
118 jkmpNode class. To evaluate such a structure simply call jkmpNode::evaluate()
119 of the root node. This will then return a jkmpResult structure which contains
120 the result. This scheme allows for once parsing and multiply evaluating an expression.
121 So if you want to define a function by an expression you can provide an
122 external variable x as the argument and then evaluate the function for
123 each x.
124
125 \section jkmp_ebnf EBNF definition of the parsed expressions
126
127<pre> logical_expression -> logical_term
128 | logical_expression <b>or</b> logical_term
129 | logical_expression <b>||</b> logical_term</pre>
130<pre> logical_term -> comp_expression
131 | logical_term <b>and</b> comp_expression
132 | logical_term <b>&amp;&amp;</b> comp_expression</pre>
133<pre> comp_expression -> math_expression
134 | expression <b>==</b> math_expression
135 | expression <b>!=</b> math_expression
136 | expression <b>&gt;=</b> math_expression
137 | expression <b>&lt;=</b> math_expression
138 | expression <b>&gt;</b> math_expression
139 | expression <b>&lt;</b> math_expression</pre>
140<pre> math_expression -> term
141 | math_expression <b>+</b> math_term
142 | math_expression <b>-</b> math_term</pre>
143<pre> math_term -> primary
144 | term <b>*</b> primary
145 | term <b>/</b> primary
146 | term ( <b>%</b> | <b>mod</b> ) primary</pre>
147<pre> primary -> <b>true</b> | <b>false</b>
148 | string_constant
149 | NUMBER
150 | NAME
151 | NAME <b>=</b> logical_expression
152 | <b>+</b> primary | <b>-</b> primary | <b>!</b> primary | <b>not</b> primary
153 | <b>(</b> logical_expression <b>)</b>
154 | NAME<b>(</b> parameter_list <b>)</b>
155 | primary <b>^</b> primary</pre>
156<pre> string_constant -> <b>&quot;</b> STRING <b>&quot;</b> | <b>&apos;</b> STRING <b>&apos;</b></pre>
157<pre> parameter_list -> \f$ \lambda \f$ | logical_expression | logical_expression <b>,</b> parameter_list</pre>
158
159
160
161
162 \section jkmp_example Simple Example of Usage
163 \code
164 try {
165 JKQTPMathParser mp; // instanciate
166 jkmpNode* n;
167 jkmpResult r;
168 // parse some numeric expression
169 n=mp.parse("pi^2+4*sin(65*pi/exp(3.45))");
170 r=n->evaluate();
171 cout<<r.num<<endl;
172 //delete n;
173
174 // parse some boolean expression
175 n=mp.parse("true==false");
176 r=n->evaluate();
177 if (r.type==jkmpBool) {
178 if (r.boolean) cout<<"true";
179 else cout<<"false";
180 }
181 if (r.type==jkmpDouble) cout<<r.num<<endl;
182 if (r.type==jkmpString) cout<<r.str<<endl;
183 delete n;
184
185 // parse some string expression
186 n=mp.parse("var1='false'; var1+'true'");
187 r=n->evaluate();
188 if (r.type==jkmpString) cout<<r.str<<endl;
189 delete n;
190 } catch(std::exception& E) {
191 cout<<"ERROR!!!\n "<<E.what()<<endl<<endl;
192 }
193 \endcode
194
195
196
197 \section jkmp_errorhandling Error Handling
198
199 In the above example we use error handling by use of exception (default behauviour).
200
201
202 It is also possible to change the error handling from using exceptions to calling a specific
203 error handling function. This can be usefull in programs that don't support exceptions.
204 To do so, use this cod:
205 \code
206 void error(const std::string& message) {
207 cout<<"error: "+message;
208 system("PAUSE");
209 abort();
210 }
211
212 int main() {
213 JKQTPMathParser mp;
214 mp.setException_function(error); // make error ahndler known
215 ...
216 }
217 \endcode
218 */
220{
221 public:
222
223/** @name Abstract Syntax Tree / Memory Representation of Expressions */
224/**@{*/
225
226 /** \brief possible result types */
227 enum jkmpResultType {jkmpDouble, /*!< \brief a floating-point number with double precision. This is also used to deal with integers */
228 jkmpString, /*!< \brief a string of characters */
229 jkmpBool}; /*!< \brief a boolean value true|false */
230
231
232
233 /** \brief result of any expression*/
236
238 jkmpResultType type; /*!< \brief type of the result */
239 std::string str; /*!< \brief contains result if \c type==jkmpString */
240 double num; /*!< \brief contains result if \c type==jkmpDouble */
241 bool boolean; /*!< \brief contains result if \c type==jkmpBool */
242
243 /** \brief convert the value this struct representens into a std::string */
244 std::string toString();
245
246 /** \brief convert the value this struct representens into a std::string and adds the name of the datatype in \c [...] */
247 std::string toTypeString();
248 };
249
250
251 /** \brief This struct is for managing variables. Unlike jkmpResult this struct
252 * only contains pointers to the data */
255 jkmpResultType type; /*!< \brief type of the variable */
256 bool internal; /*!< \brief this is an internal variable */
257 std::string *str; /*!< \brief this points to the variable data if \c type==jkmpString */
258 double *num; /*!< \brief this points to the variable data if \c type==jkmpDouble */
259 bool *boolean; /*!< \brief this points to the variable data if \c type==jkmpBool */
260 };
261
262 /** \brief This struct is for managing temporary variables. It is generally like jkmpVariable. */
265 std::string name; /*!< \brief name of the variable */
266 jkmpResultType type; /*!< \brief type of the variable */
267 bool internal; /*!< \brief this is an internal variable */
268 std::string *str; /*!< \brief this points to the variable data if \c type==jkmpString */
269 double *num; /*!< \brief this points to the variable data if \c type==jkmpDouble */
270 bool *boolean; /*!< \brief this points to the variable data if \c type==jkmpBool */
271 };
272
273
274
275 /** \brief This is a function prototype for adding new mathematical functions
276 * to the parser
277 *
278 * If you want to add more math functions (like sin, cos , abs ...) to the
279 * parser, you will have to implement it with this prototype and then register
280 * it with JKQTPMathParser::addFunction(). The first parameter points to an array
281 * containing the input parameters while the second one specifies the number
282 * of supplied parameters. The result has to be of type jkmpResult.
283 *
284 * All error handling has to be done inside the function definition. Here is a
285 * simple example:
286 * \code
287 * jkmpResult Abs(jkmpResult* params, unsigned char n){
288 * jkmpResult r;
289 * r.type=jkmpDouble;
290 * if (n!=1) jkmpError("abs accepts 1 argument");
291 * if (params[0].type!=jkmpDouble) jkmpError("abs needs double argument");
292 * r.num=fabs(params[0].num);
293 * return r;
294 * }
295 * \endcode
296 */
297 typedef jkmpResult (*jkmpEvaluateFunc)(jkmpResult*, unsigned char, JKQTPMathParser*);
298
299
300 /** \brief description of a user registered function */
302 jkmpFunctionDescriptor(jkmpEvaluateFunc function_=nullptr);
303 jkmpEvaluateFunc function; /*!< \brief a pointer to the function implementation */
304 std::string name; /*!< \brief name of the function */
305 };
306
307
308
309
310
311
312 /**
313 * \brief This class is the abstract base class for nodes.
314 * All allowed node types must inherit from jkmpNode
315 */
317 protected:
318 JKQTPMathParser* parser; /*!< \brief points to the parser object that is used to evaluate this node */
319 jkmpNode* parent; /*!< \brief points to the parent node */
320 public:
321 jkmpNode(JKQTPMathParser* parser_=nullptr, jkmpNode* parent_=nullptr);
322 /** \brief virtual class destructor */
323 virtual ~jkmpNode();
324
325 /** \brief evaluate this node */
326 virtual jkmpResult evaluate()=0;
327
328 /** \brief return a pointer to the JKQTPMathParser */
330
331 /** \brief set the JKQTPMathParser */
333
334 /** \brief returns a pointer to the parent node */
336
337 /** \brief sets the parent node */
338 void setParent(jkmpNode* par);
339 };
340
341
342 /**
343 * \brief This class represents a binary arithmetic operation:
344 * add (+), subtract (-), multiply (*), divide (/), a to the power of b (a^b)
345 */
347 private:
348 jkmpNode* left, *right;
350 public:
351 /** \brief constructor for a jkmpBinaryArithmeticNode
352 * \param op the operation to be performed: add (+), subtract (-), multiply (*), divide (/), a to the power of b (a^b)
353 * \param l left child node/operand
354 * \param r right child node/operand
355 * \param p a pointer to a JKQTPMathParser object
356 * \param par a pointer to the parent node
357 */
359
360 /** \brief standard destructor, also destroy the children (recursively) */
361 virtual ~jkmpBinaryArithmeticNode() override;
362
363 /** \brief evaluate this node */
364 virtual jkmpResult evaluate() override;
365 };
366
367 /** \brief internal names for logic operations */
368 enum class jkmpLOP{
369 LOPand='a',
370 LOPor='o',
371 LOPxor='x',
372 LOPnor='n',
373 LOPnand='A'
374 };
375
376
377 /** \brief This class represents a binary boolean operation: and, or, xor, nor, nand */
379 private:
380 jkmpNode* left, *right;
382 public:
383 /** \brief constructor for a jkmpBinaryBoolNode
384 * \param op the operation to be performed: (a)nd, (o)r, (x)or, (n)or, nand (A)
385 * \param l left child node/operand
386 * \param r right child node/operand
387 * \param p a pointer to a JKQTPMathParser object
388 * \param par a pointer to the parent node
389 */
391
392 /** \brief standard destructor, also destroy the children (recursively) */
393 virtual ~jkmpBinaryBoolNode() override;
394
395 /** \brief evaluate this node */
396 virtual jkmpResult evaluate() override;
397 };
398
399
400 /** \brief jkmpCOMPdefs internal names for compare operations */
401 enum class jkmpCOMP {
402 equal='=',
403 nequal='!',
404 lesser='<',
405 greater='>',
406 lesserequal='a',
407 greaterequal='b'
408 };
409
410 /** \brief This class represents a binary compare operation: !=, ==, >=, <=, >, < */
412 private:
413 jkmpNode* left, *right;
415 public:
416 /** \brief constructor for a jkmpCompareNode
417 * \param op the operation to be performed: != (!), == (=), >= (b), <= (a), (>), (<)
418 * \param l left child node/operand
419 * \param r right child node/operand
420 * \param p a pointer to a JKQTPMathParser object
421 * \param par a pointer to the parent node
422 */
424
425 /** \brief standard destructor, also destroy the children (recursively) */
426 virtual ~jkmpCompareNode () override;
427
428 /** \brief evaluate this node */
429 virtual jkmpResult evaluate() override;
430 };
431
432 /** \brief This class represents a unary operations: ! (bool negation), - (arithmetic negation) */
434 private:
437 public:
438 /** \brief constructor for a jkmpUnaryNode
439 * \param op the operation to be performed: (!), (-)
440 * \param c child node/operand
441 * \param p a pointer to a JKQTPMathParser object
442 * \param par a pointer to the parent node
443 */
445
446 /** \brief standard destructor, also destroy the children (recursively) */
447 virtual ~jkmpUnaryNode() override;
448
449 /** \brief evaluate this node */
450 virtual jkmpResult evaluate() override;
451 };
452
453 /**
454 * \brief This class represents a variable assignment (<code>a = expression</code>) */
456 private:
458 std::string variable;
459 //char operation;
460 public:
461 /** \brief standard destructor, also destroy the children (recursively) */
462 virtual ~jkmpVariableAssignNode() override;
463
464 /** \brief constructor for a jkmpVariableAssignNode
465 * \param var name of the variable to assign to
466 * \param c child node/right-hand-side expression
467 * \param p a pointer to a JKQTPMathParser object
468 * \param par a pointer to the parent node
469 */
470 jkmpVariableAssignNode(const std::string& var, jkmpNode* c, JKQTPMathParser* p, jkmpNode* par);
471
472 /** \brief evaluate this node */
473 virtual jkmpResult evaluate() override;
474 };
475
476 /** \brief This class represents a number, a string contant or a boolean contant (\c true / \c false ) */
478 private:
480 public:
481 /** \brief constructor for a jkmpConstantNode
482 * \param d the value of the constant
483 * \param p a pointer to a JKQTPMathParser object
484 * \param par a pointer to the parent node
485 */
487
488 /** \brief evaluate this node */
489 virtual jkmpResult evaluate() override;
490 };
491
492 /** \brief This class represents a variable. */
494 private:
495 std::string var;
496 public:
497 /** \brief constructor for a jkmpVariableNode
498 * \param name name of the variable
499 * \param p a pointer to a JKQTPMathParser object
500 * \param par a pointer to the parent node
501 */
502 jkmpVariableNode(const std::string& name, JKQTPMathParser* p, jkmpNode* par);
503
504 /** \brief evaluate this node */
505 virtual jkmpResult evaluate() override;
506 };
507
508 /** \brief This class represents an arbitrary function.
509 *
510 * When initialized this class will get the function description that is
511 * linked to the supplied function name from JKQTPMathParser object. This
512 * information is saved locally and won't be changed when evaluating!
513 *
514 * Functions may have 8 parameters at the most.
515 */
517 private:
518 std::string fun;
520 unsigned char n;
521 jkmpEvaluateFunc function;
522 public:
523 /** \brief constructor for a jkmpFunctionNode
524 * \param name name of the function
525 * \param c a pointer to an array of jkmpNode objects that represent the parameter expressions
526 * \param num number of children in c
527 * \param p a pointer to a JKQTPMathParser object
528 * \param par a pointer to the parent node
529 */
530 jkmpFunctionNode(const std::string& name, jkmpNode** c, unsigned char num, JKQTPMathParser* p, jkmpNode* par);
531
532 /** \brief standard destructor, also destroy the children (recursively) */
533 virtual ~jkmpFunctionNode() override;
534
535 /** \brief evaluate this node */
536 virtual jkmpResult evaluate() override;
537 };
538
539 /**
540 * \brief This class represents a list of jkmpNode.
541 *
542 * when evaluating the result will be the result of the last node in the list.
543 */
545 private:
546 std::vector<jkmpNode*> list;
547 public:
548 /** \brief constructor for a jkmpNodeList
549 * \param p a pointer to a JKQTPMathParser object
550 */
552
553 /** \brief standard destructor, also destroy the children (recursively) */
554 virtual ~jkmpNodeList() override;
555
556 /** \brief add a jkmpNode n to the list */
557 void add(jkmpNode* n);
558
559 /** \brief evaluate the node */
560 virtual jkmpResult evaluate() override;
561
562 /** \brief get the number of nodes in the list */
563 int getCount();
564 };
565
566 /**@}*/
567
568
569 public:
570
571
572
573/**@}*/
574
575
576 public:
577
578/** @name Error Handling */
579/**@{*/
580
581
582 /** \brief error handling: exceptions of the type of this class will be thrown if an error occurs
583 *
584 * \attention If you do not want to use the exception handling which throws
585 * jkmpException exceptions, but want to write your own error handling, you should write your own
586 * error handler and assign it (function pointer) to the global variable jkmathparser_exception_function.
587 * If this is not nullptr this function will be called instead of throwing an exception.
588 */
589 class jkqtmath_LIB_EXPORT jkmpException : public std::exception {
590 private:
591 /** \brief the error message */
592 std::string errormessage;
593 public:
594 /** \brief class constructors */
596
597 /** \brief constructor with supplied error message */
598 jkmpException(const std::string& msg);
599
600 /** \brief class destructors */
601 virtual ~jkmpException() override;
602
603 /** \brief returns the assigned errormessage */
604 std::string getMessage() const;
605
606 /** \brief returns the error description as C string */
607 virtual const char* what() const noexcept override;
608 };
609
610 /** \brief type for a custom error handler. This an alternative error handling */
611 typedef void (*jkmpexceptionf)(std::string);
612
613
614 /** \brief function that throws an exception or calls an error handler */
615 void jkmpError(const std::string& st);
616
617 private:
618 /** \brief if this is nullptr then an exception may be thrown otherwise this should point to an error handler that will be called. */
619 jkmpexceptionf jkmathparser_exception_function;
620
621 public:
622 /** \brief activate error handling by use of an exception function */
623 void setException_function(jkmpexceptionf exception_function);
624
625 /** \brief deactivate error handling by use of an exception function */
626 void resetException_function();
627/**@}*/
628
629
630 protected:
631/** @name Tokenizer */
632/**@{*/
633 /** \brief the possible tokens that can be recognized by the tokenizer in JKQTPMathParser::getToken() */
635 END, /*!< \brief end token */
636 PRINT, /*!< \brief a semicolon ';' */
637 PARAMETER_DIV, /*!< \brief a comma ',' between two function parameters */
638 STRING_DELIM, /*!< \brief a string delimiter ' or " */
639 NAME, /*!< \brief a name (consisting of characters) of a variable or function */
640 NUMBER, /*!< \brief a number in scientific notation */
641 PLUS, /*!< \brief a plus operator '+' */
642 MINUS, /*!< \brief a minus operator '-' */
643 MUL, /*!< \brief a multiplication operator '*' */
644 DIV, /*!< \brief a division operator '/' */
645 MODULO, /*!< \brief a modulo operator '%' */
646 ASSIGN, /*!< \brief a variable assignment = */
647 LBRACKET, /*!< \brief left brackets '(' */
648 RBRACKET, /*!< \brief right brackets ')' */
649 POWER, /*!< \brief a power operator '^' */
650 FACTORIAL_LOGIC_NOT, /*!< \brief a factorial operator or a logical NOT '!' */
651 LOGIC_NOT, /*!< \brief a logical NOT '!' / 'not' */
652 LOGIC_AND, /*!< \brief a logical AND operator '&&' / 'and' */
653 LOGIC_OR, /*!< \brief a logical OR operator '||' / 'or' */
654 LOGIC_XOR, /*!< \brief a logical XOR operator 'xor' */
655 LOGIC_NOR, /*!< \brief a logical NOR operator 'nor' */
656 LOGIC_NAND, /*!< \brief a logical NAND operator 'nand' */
657 LOGIC_TRUE, /*!< \brief 'true' */
658 LOGIC_FALSE, /*!< \brief 'false' */
659 COMP_EQUALT, /*!< \brief equals operation '==' */
660 COMP_UNEQUAL, /*!< \brief unequal operation '!=' */
661 COMP_GREATER, /*!< \brief greater than operation '>' */
662 COMP_SMALLER, /*!< \brief smaller than operation '<' */
663 COMP_GEQUAL, /*!< \brief greater than or equal operation '>=' */
664 COMP_SEQUAL, /*!< \brief smaller than or equal operation '<=' */
665 };
666
667
668 /** \brief return the given token as human-readable string */
669 std::string tokentostring(jkmpTokenType token);
670
671 /** \brief return the current token as human-readable string */
672 std::string currenttokentostring();
673
674 /** \brief Tokenizer: extract the next token from the input */
676
677 /** \brief return a delimited text, i.e. extract the texte between the delimiters <code>"</code> in: of <code>"Hallo!"</code>, i.e. returns <code> Hallo!</code>
678 * This is used to parse string constants.
679 *
680 * 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
681 * write it as doubled character. So <code>'Jan''s Test'</code> stands for <code>Jan's Test</code>.
682 */
683 std::string readDelim(char delimiter);
684
685 /** \brief the current token while parsing a string */
687
688 /** \brief the string value of the current token (when applicable) during the parsing step */
689 std::string StringValue;
690
691 /** \brief the string value of the current token (when applicable) during the parsing step */
693
694 /** \brief this stream is used to read in the program. An object is created and assigned
695 * (and destroyed) by the parse()-function */
696 std::istringstream* program;
697
698
699/**@}*/
700
701
702/** @name Parser */
703/**@{*/
704
705 /** \brief recognizes an compExpression while parsing. If \a get ist \c true, this function first retrieves a new token by calling getToken() */
707
708 /** \brief recognizes a logicalExpression while parsing. If \a get ist \c true, this function first retrieves a new token by calling getToken() */
710
711 /** \brief recognizes a logicalTerm while parsing. If \a get ist \c true, this function first retrieves a new token by calling getToken() */
713
714 /** \brief recognizes a mathExpression while parsing. If \a get ist \c true, this function first retrieves a new token by calling getToken() */
716
717 /** \brief recognizes a term while parsing. If \a get ist \c true, this function first retrieves a new token by calling getToken() */
718 jkmpNode* mathTerm(bool get);
719
720 /** \brief recognizes a primary while parsing. If \a get ist \c true, this function first retrieves a new token by calling getToken() */
721 jkmpNode* primary(bool get);
722
723/**@}*/
724
725 /** \brief vector containing all temporary variables */
726 std::vector<jkmpTempVariable> tempvariables;
727
728 /** \brief map to manage all currently defined variables */
729 std::map<std::string, jkmpVariable> variables;
730
731 /** \brief map to manage all currently rtegistered functions */
732 std::map<std::string, jkmpFunctionDescriptor> functions;
733
734 /** \brief set the defining struct of the given variable */
735 void setVariable(const std::string& name, jkmpResult value);
736 /** \brief set the defining struct of the given variable */
737 void setVariableDouble(const std::string& name, double value);
738
739
740 /** \brief adds a temporary variable */
741 void addTempVariable(const std::string& name, jkmpResult value);
742
743 protected:
744 /** \brief storage for program argument cound, used by the standard functions \c cmdparam and \c argv \see setArgCV() and getArgCVParam() */
745 int argc;
746 /** \brief storage for program arguments, used by the standard functions \c cmdparam and \c argv \see setArgCV() and getArgCVParam() */
747 char **argv;
748
749 public:
750 /** \brief class constructor
751 *
752 * \note This also registers all standatd functions and constants by calling addStandardFunctions() and addStandardVariables()
753 */
755
756 /** \brief class destructor */
758
759
760 /** \brief register a new function
761 * \param name name of the new function
762 * \param function a pointer to the implementation
763 */
764 void addFunction(const std::string& name, jkmpEvaluateFunc function);
765
766 /** \brief register a new external variable of type double
767 * \param name name of the new variable
768 * \param v pointer to the variable memory
769 */
770 void addVariableDouble(const std::string& name, double* v);
771
772 /** \brief register a new external variable of type string
773 * \param name name of the new variable
774 * \param v pointer to the variable memory
775 */
776 void addVariableString(const std::string& name, std::string* v);
777
778 /** \brief register a new external variable of type boolean
779 * \param name name of the new variable
780 * \param v pointer to the variable memory
781 */
782 void addVariableBoolean(const std::string& name, bool* v);
783
784
785 /** \brief register a new internal variable of type double
786 * \param name name of the new variable
787 * \param v initial value of this variable
788 */
789 void addVariableDouble(const std::string& name, double v);
790
791 /** \brief register a new internal variable of type string
792 * \param name name of the new variable
793 * \param v initial value of this variable
794 */
795 void addVariableString(const std::string& name, const std::string& v);
796
797 /** \brief register a new internal variable of type boolean
798 * \param name name of the new variable
799 * \param v initial value of this variable
800 */
801 void addVariableBoolean(const std::string& name, bool v);
802
803 /** \brief register a new internal variable of type boolean
804 * \param name name of the new variable
805 * \param result initial value of this variable
806 */
807 void addVariable(const std::string& name, jkmpResult result);
808
809
810
811 /** \brief returns the value of the given variable */
812 jkmpResult getVariable(const std::string& name);
813 /** \brief returns the value of the given variable */
814 jkmpResult getVariableOrInvalid(const std::string& name);
815
816 /** \brief returns the defining structure of the given variable */
817 jkmpVariable getVariableDef(const std::string& name);
818
819
820 /** \brief evaluates a registered function
821 * \param name name of the (registered function) to be evaluated
822 * \param params array of the input parameters
823 * \param n number of input parameters (<=8)
824 */
825 jkmpResult evaluateFunction(const std::string& name, jkmpResult* params, unsigned char n);
826
827 /** \brief returns the defining structure of the given function */
828 jkmpEvaluateFunc getFunctionDef(const std::string& name);
829
830 /** \brief tests whether a temporary variable exists */
831 bool tempvariableExists(const std::string& name);
832
833 /** \brief tests whether a variable exists */
834 bool variableExists(const std::string& name);
835
836 /** \brief tests whether a function exists */
837 bool functionExists(const std::string& name);
838
839 /** \brief deletes all defined variables. the memory of internal variables
840 * will be released. the external memory will not be released.
841 */
843
844 /** \brief delete the specified variabale and releases its internal memory.*/
845 void deleteVariable(const std::string& name);
846
847 /** \brief clears the list of internal functions*/
849
850 /** \brief registers standard variables */
852
853 /** \brief registers standard functions*/
855
856 /** \brief parses the given expression*/
857 jkmpNode* parse(const std::string& prog);
858
859 /** \brief evaluate the given expression */
860 jkmpResult evaluate(const std::string& prog);
861
862 /** \brief prints a list of all registered variables */
864
865 /** \brief returns all registered variables */
866 std::vector<std::pair<std::string, jkmpVariable> > getVariables();
867
868 /** \brief store programs command-line arguments, so they are available in the parser, used by the standard functions \c cmdparam and \c argv */
869 void setArgCV(int argc, char **argv);
870
871 /** \brief return one of programs command-line arguments, or \a defaultResult if it is not present, used by the standard functions \c cmdparam and \c argv */
872 std::string getArgCVParam(const std::string& name, const std::string& defaultResult);
873};
874
875#endif // JKQTPMATHPARSER_H
This class represents a binary arithmetic operation: add (+), subtract (-), multiply (*),...
Definition jkqtpmathparser.h:346
virtual jkmpResult evaluate() override
evaluate this node
jkmpBinaryArithmeticNode(char op, jkmpNode *l, jkmpNode *r, JKQTPMathParser *p, jkmpNode *par)
constructor for a jkmpBinaryArithmeticNode
jkmpNode * left
Definition jkqtpmathparser.h:348
char operation
Definition jkqtpmathparser.h:349
virtual ~jkmpBinaryArithmeticNode() override
standard destructor, also destroy the children (recursively)
This class represents a binary boolean operation: and, or, xor, nor, nand.
Definition jkqtpmathparser.h:378
jkmpBinaryBoolNode(jkmpLOP op, jkmpNode *l, jkmpNode *r, JKQTPMathParser *p, jkmpNode *par)
constructor for a jkmpBinaryBoolNode
virtual ~jkmpBinaryBoolNode() override
standard destructor, also destroy the children (recursively)
jkmpNode * left
Definition jkqtpmathparser.h:380
virtual jkmpResult evaluate() override
evaluate this node
jkmpLOP operation
Definition jkqtpmathparser.h:381
This class represents a binary compare operation: !=, ==, >=, <=, >, <
Definition jkqtpmathparser.h:411
jkmpCOMP operation
Definition jkqtpmathparser.h:414
virtual jkmpResult evaluate() override
evaluate this node
jkmpNode * left
Definition jkqtpmathparser.h:413
jkmpCompareNode(jkmpCOMP op, jkmpNode *l, jkmpNode *r, JKQTPMathParser *p, jkmpNode *par)
constructor for a jkmpCompareNode
virtual ~jkmpCompareNode() override
standard destructor, also destroy the children (recursively)
This class represents a number, a string contant or a boolean contant (true / false )
Definition jkqtpmathparser.h:477
jkmpResult data
Definition jkqtpmathparser.h:479
jkmpConstantNode(jkmpResult d, JKQTPMathParser *p, jkmpNode *par)
constructor for a jkmpConstantNode
virtual jkmpResult evaluate() override
evaluate this node
error handling: exceptions of the type of this class will be thrown if an error occurs
Definition jkqtpmathparser.h:589
std::string getMessage() const
returns the assigned errormessage
jkmpException()
class constructors
std::string errormessage
the error message
Definition jkqtpmathparser.h:592
virtual ~jkmpException() override
class destructors
jkmpException(const std::string &msg)
constructor with supplied error message
virtual const char * what() const noexcept override
returns the error description as C string
This class represents an arbitrary function.
Definition jkqtpmathparser.h:516
virtual jkmpResult evaluate() override
evaluate this node
std::string fun
Definition jkqtpmathparser.h:518
virtual ~jkmpFunctionNode() override
standard destructor, also destroy the children (recursively)
jkmpNode ** child
Definition jkqtpmathparser.h:519
jkmpEvaluateFunc function
Definition jkqtpmathparser.h:521
jkmpFunctionNode(const std::string &name, jkmpNode **c, unsigned char num, JKQTPMathParser *p, jkmpNode *par)
constructor for a jkmpFunctionNode
unsigned char n
Definition jkqtpmathparser.h:520
This class is the abstract base class for nodes. All allowed node types must inherit from jkmpNode.
Definition jkqtpmathparser.h:316
JKQTPMathParser * parser
points to the parser object that is used to evaluate this node
Definition jkqtpmathparser.h:318
jkmpNode * getParent()
returns a pointer to the parent node
void setParent(jkmpNode *par)
sets the parent node
jkmpNode * parent
points to the parent node
Definition jkqtpmathparser.h:319
virtual ~jkmpNode()
virtual class destructor
void setParser(JKQTPMathParser *mp)
set the JKQTPMathParser
virtual jkmpResult evaluate()=0
evaluate this node
jkmpNode(JKQTPMathParser *parser_=nullptr, jkmpNode *parent_=nullptr)
JKQTPMathParser * getParser()
return a pointer to the JKQTPMathParser
This class represents a list of jkmpNode.
Definition jkqtpmathparser.h:544
virtual jkmpResult evaluate() override
evaluate the node
virtual ~jkmpNodeList() override
standard destructor, also destroy the children (recursively)
void add(jkmpNode *n)
add a jkmpNode n to the list
int getCount()
get the number of nodes in the list
std::vector< jkmpNode * > list
Definition jkqtpmathparser.h:546
jkmpNodeList(JKQTPMathParser *p)
constructor for a jkmpNodeList
This class represents a unary operations: ! (bool negation), - (arithmetic negation)
Definition jkqtpmathparser.h:433
virtual ~jkmpUnaryNode() override
standard destructor, also destroy the children (recursively)
jkmpNode * child
Definition jkqtpmathparser.h:435
char operation
Definition jkqtpmathparser.h:436
jkmpUnaryNode(char op, jkmpNode *c, JKQTPMathParser *p, jkmpNode *par)
constructor for a jkmpUnaryNode
virtual jkmpResult evaluate() override
evaluate this node
This class represents a variable assignment (a = expression)
Definition jkqtpmathparser.h:455
virtual ~jkmpVariableAssignNode() override
standard destructor, also destroy the children (recursively)
std::string variable
Definition jkqtpmathparser.h:458
jkmpVariableAssignNode(const std::string &var, jkmpNode *c, JKQTPMathParser *p, jkmpNode *par)
constructor for a jkmpVariableAssignNode
virtual jkmpResult evaluate() override
evaluate this node
jkmpNode * child
Definition jkqtpmathparser.h:457
This class represents a variable.
Definition jkqtpmathparser.h:493
std::string var
Definition jkqtpmathparser.h:495
virtual jkmpResult evaluate() override
evaluate this node
jkmpVariableNode(const std::string &name, JKQTPMathParser *p, jkmpNode *par)
constructor for a jkmpVariableNode
A simple function parser to parse (build memory tree representation) and evaluate simple mathematical...
Definition jkqtpmathparser.h:220
bool variableExists(const std::string &name)
tests whether a variable exists
jkmpResult evaluate(const std::string &prog)
evaluate the given expression
jkmpLOP
internal names for logic operations
Definition jkqtpmathparser.h:368
std::istringstream * program
this stream is used to read in the program. An object is created and assigned (and destroyed) by the ...
Definition jkqtpmathparser.h:696
void addVariableBoolean(const std::string &name, bool *v)
register a new external variable of type boolean
jkmpVariable getVariableDef(const std::string &name)
returns the defining structure of the given variable
void printVariables()
prints a list of all registered variables
void deleteVariable(const std::string &name)
delete the specified variabale and releases its internal memory.
void addVariableBoolean(const std::string &name, bool v)
register a new internal variable of type boolean
void addVariable(const std::string &name, jkmpResult result)
register a new internal variable of type boolean
std::string currenttokentostring()
return the current token as human-readable string
virtual ~JKQTPMathParser()
class destructor
jkmpNode * compExpression(bool get)
recognizes an compExpression while parsing. If get ist true, this function first retrieves a new toke...
void addStandardFunctions()
registers standard functions
jkmpResultType
possible result types
Definition jkqtpmathparser.h:227
@ jkmpString
a string of characters
Definition jkqtpmathparser.h:228
@ jkmpDouble
a floating-point number with double precision. This is also used to deal with integers
Definition jkqtpmathparser.h:227
std::string readDelim(char delimiter)
return a delimited text, i.e. extract the texte between the delimiters "</code> in: of <code>"Hallo!...
jkmpNode * logicalExpression(bool get)
recognizes a logicalExpression while parsing. If get ist true, this function first retrieves a new to...
jkmpEvaluateFunc getFunctionDef(const std::string &name)
returns the defining structure of the given function
std::vector< std::pair< std::string, jkmpVariable > > getVariables()
returns all registered variables
char ** argv
storage for program arguments, used by the standard functions cmdparam and argv
Definition jkqtpmathparser.h:747
void setVariable(const std::string &name, jkmpResult value)
set the defining struct of the given variable
std::string getArgCVParam(const std::string &name, const std::string &defaultResult)
return one of programs command-line arguments, or defaultResult if it is not present,...
jkmpCOMP
jkmpCOMPdefs internal names for compare operations
Definition jkqtpmathparser.h:401
bool functionExists(const std::string &name)
tests whether a function exists
jkmpTokenType
the possible tokens that can be recognized by the tokenizer in JKQTPMathParser::getToken()
Definition jkqtpmathparser.h:634
@ PRINT
a semicolon ';'
Definition jkqtpmathparser.h:636
@ LOGIC_AND
a logical AND operator '&&' / 'and'
Definition jkqtpmathparser.h:652
@ FACTORIAL_LOGIC_NOT
a factorial operator or a logical NOT '!'
Definition jkqtpmathparser.h:650
@ END
end token
Definition jkqtpmathparser.h:635
@ MUL
a multiplication operator '*'
Definition jkqtpmathparser.h:643
@ PARAMETER_DIV
a comma ',' between two function parameters
Definition jkqtpmathparser.h:637
@ LOGIC_NAND
a logical NAND operator 'nand'
Definition jkqtpmathparser.h:656
@ LOGIC_TRUE
'true'
Definition jkqtpmathparser.h:657
@ RBRACKET
right brackets ')'
Definition jkqtpmathparser.h:648
@ LOGIC_FALSE
'false'
Definition jkqtpmathparser.h:658
@ COMP_EQUALT
equals operation '=='
Definition jkqtpmathparser.h:659
@ LOGIC_NOT
a logical NOT '!' / 'not'
Definition jkqtpmathparser.h:651
@ NAME
a name (consisting of characters) of a variable or function
Definition jkqtpmathparser.h:639
@ LOGIC_OR
a logical OR operator '||' / 'or'
Definition jkqtpmathparser.h:653
@ LBRACKET
left brackets '('
Definition jkqtpmathparser.h:647
@ COMP_SEQUAL
smaller than or equal operation '<='
Definition jkqtpmathparser.h:664
@ COMP_GEQUAL
greater than or equal operation '>='
Definition jkqtpmathparser.h:663
@ ASSIGN
a variable assignment =
Definition jkqtpmathparser.h:646
@ POWER
a power operator '^'
Definition jkqtpmathparser.h:649
@ PLUS
a plus operator '+'
Definition jkqtpmathparser.h:641
@ COMP_UNEQUAL
unequal operation '!='
Definition jkqtpmathparser.h:660
@ COMP_GREATER
greater than operation '>'
Definition jkqtpmathparser.h:661
@ MINUS
a minus operator '-'
Definition jkqtpmathparser.h:642
@ LOGIC_XOR
a logical XOR operator 'xor'
Definition jkqtpmathparser.h:654
@ COMP_SMALLER
smaller than operation '<'
Definition jkqtpmathparser.h:662
@ LOGIC_NOR
a logical NOR operator 'nor'
Definition jkqtpmathparser.h:655
@ NUMBER
a number in scientific notation
Definition jkqtpmathparser.h:640
@ MODULO
a modulo operator ''
Definition jkqtpmathparser.h:645
@ DIV
a division operator '/'
Definition jkqtpmathparser.h:644
@ STRING_DELIM
a string delimiter ' or "
Definition jkqtpmathparser.h:638
void addTempVariable(const std::string &name, jkmpResult value)
adds a temporary variable
jkmpNode * mathTerm(bool get)
recognizes a term while parsing. If get ist true, this function first retrieves a new token by callin...
void addVariableDouble(const std::string &name, double *v)
register a new external variable of type double
int argc
storage for program argument cound, used by the standard functions cmdparam and argv
Definition jkqtpmathparser.h:745
jkmpResult getVariableOrInvalid(const std::string &name)
returns the value of the given variable
double NumberValue
the string value of the current token (when applicable) during the parsing step
Definition jkqtpmathparser.h:692
jkmpNode * parse(const std::string &prog)
parses the given expression
jkmpTokenType getToken()
Tokenizer: extract the next token from the input.
void addFunction(const std::string &name, jkmpEvaluateFunc function)
register a new function
bool tempvariableExists(const std::string &name)
tests whether a temporary variable exists
JKQTPMathParser()
class constructor
void setVariableDouble(const std::string &name, double value)
set the defining struct of the given variable
void addVariableString(const std::string &name, const std::string &v)
register a new internal variable of type string
jkmpNode * logicalTerm(bool get)
recognizes a logicalTerm while parsing. If get ist true, this function first retrieves a new token by...
jkmpResult evaluateFunction(const std::string &name, jkmpResult *params, unsigned char n)
evaluates a registered function
std::vector< jkmpTempVariable > tempvariables
vector containing all temporary variables
Definition jkqtpmathparser.h:726
jkmpResult getVariable(const std::string &name)
returns the value of the given variable
void addVariableDouble(const std::string &name, double v)
register a new internal variable of type double
jkmpNode * primary(bool get)
recognizes a primary while parsing. If get ist true, this function first retrieves a new token by cal...
void addStandardVariables()
registers standard variables
std::map< std::string, jkmpFunctionDescriptor > functions
map to manage all currently rtegistered functions
Definition jkqtpmathparser.h:732
void addVariableString(const std::string &name, std::string *v)
register a new external variable of type string
jkmpTokenType CurrentToken
the current token while parsing a string
Definition jkqtpmathparser.h:686
jkmpNode * mathExpression(bool get)
recognizes a mathExpression while parsing. If get ist true, this function first retrieves a new token...
void clearFunctions()
clears the list of internal functions
void clearVariables()
deletes all defined variables. the memory of internal variables will be released. the external memory...
std::string StringValue
the string value of the current token (when applicable) during the parsing step
Definition jkqtpmathparser.h:689
void setArgCV(int argc, char **argv)
store programs command-line arguments, so they are available in the parser, used by the standard func...
std::map< std::string, jkmpVariable > variables
map to manage all currently defined variables
Definition jkqtpmathparser.h:729
std::string tokentostring(jkmpTokenType token)
return the given token as human-readable string
#define jkqtmath_LIB_EXPORT
Definition jkqtmath_imexport.h:87
description of a user registered function
Definition jkqtpmathparser.h:301
jkmpFunctionDescriptor(jkmpEvaluateFunc function_=nullptr)
jkmpEvaluateFunc function
a pointer to the function implementation
Definition jkqtpmathparser.h:303
std::string name
name of the function
Definition jkqtpmathparser.h:304
result of any expression
Definition jkqtpmathparser.h:234
std::string toString()
convert the value this struct representens into a std::string
std::string str
contains result if type==jkmpString
Definition jkqtpmathparser.h:239
jkmpResultType type
type of the result
Definition jkqtpmathparser.h:238
std::string toTypeString()
convert the value this struct representens into a std::string and adds the name of the datatype in [....
bool isValid
Definition jkqtpmathparser.h:237
bool boolean
contains result if type==jkmpBool
Definition jkqtpmathparser.h:241
double num
contains result if type==jkmpDouble
Definition jkqtpmathparser.h:240
This struct is for managing temporary variables. It is generally like jkmpVariable.
Definition jkqtpmathparser.h:263
std::string name
name of the variable
Definition jkqtpmathparser.h:265
bool * boolean
this points to the variable data if type==jkmpBool
Definition jkqtpmathparser.h:270
bool internal
this is an internal variable
Definition jkqtpmathparser.h:267
jkmpResultType type
type of the variable
Definition jkqtpmathparser.h:266
double * num
this points to the variable data if type==jkmpDouble
Definition jkqtpmathparser.h:269
std::string * str
this points to the variable data if type==jkmpString
Definition jkqtpmathparser.h:268
This struct is for managing variables. Unlike jkmpResult this struct only contains pointers to the da...
Definition jkqtpmathparser.h:253
bool * boolean
this points to the variable data if type==jkmpBool
Definition jkqtpmathparser.h:259
double * num
this points to the variable data if type==jkmpDouble
Definition jkqtpmathparser.h:258
jkmpResultType type
type of the variable
Definition jkqtpmathparser.h:255
bool internal
this is an internal variable
Definition jkqtpmathparser.h:256
std::string * str
this points to the variable data if type==jkmpString
Definition jkqtpmathparser.h:257