Warning, file /education/kmplot/kmplot/parser.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 KmPlot - a math. function plotter for the KDE-Desktop 0003 0004 SPDX-FileCopyrightText: 1998, 1999, 2000, 2002 Klaus-Dieter Möller <kd.moeller@t-online.de> 0005 SPDX-FileCopyrightText: 2006 David Saxton <david@bluehaze.org> 0006 0007 This file is part of the KDE Project. 0008 KmPlot is part of the KDE-EDU Project. 0009 0010 SPDX-License-Identifier: GPL-2.0-or-later 0011 0012 */ 0013 0014 /** @file parser.h 0015 * \brief Contains the parser core class Parser. */ 0016 0017 #ifndef parser_included 0018 #define parser_included 0019 0020 #include <QMap> 0021 #include <QObject> 0022 #include <QVector> 0023 0024 #include "constants.h" 0025 #include "function.h" 0026 #include "vector.h" 0027 0028 // Various mathematical symbols 0029 #define PiSymbol QChar(0x3c0) 0030 #define InfinitySymbol QChar(0x221e) 0031 #define PmSymbol QChar(0xb1) 0032 #define AbsSymbol QChar(0x2223) 0033 #define SqrtSymbol QChar(0x221a) 0034 #define MinusSymbol QChar(0x2212) 0035 #define SubscriptZeroSymbol QChar(0x2080) 0036 #define GeSymbol QChar(0x2265) 0037 #define LeSymbol QChar(0x2264) 0038 0039 class Parser; 0040 0041 // Voreinstellungen bei Verwendung des Standardkonstruktors : 0042 0043 #define STACKSIZE 1000 ///< stack depth 0044 0045 //@{ 0046 /** Token type. */ 0047 enum Token { 0048 KONST, // 0 - double value follows 0049 VAR, // 1 - get a parameter (e.g. x or k) 0050 PUSH, // 2 - push value to stack 0051 PLUS, // 3 - add 0052 MINUS, // 4 - subtract 0053 PM, // 5 - plus-minus; add or subtract depending on the current signature 0054 MULT, // 6 - multiply 0055 DIV, // 7 - divide 0056 POW, // 8 - exponentiate 0057 NEG, // 9 - negate 0058 FKT_1, // 10 - address to function with 1 argument follows 0059 FKT_N, // 11 - address to functions with an indefinite number of arguments follows 0060 UFKT, // 12 - address to user defined function follows 0061 SQRT, // 13 - take square root 0062 FACT, // 14 - take factorial 0063 GT, // 15 - greater than 0064 GE, // 16 - greater than or equal 0065 LT, // 17 - less than 0066 LE, // 18 - less than or equal 0067 ENDE, // 19 - end of function 0068 ERROR // 20 - error in function 0069 }; 0070 0071 const int legendreCount = 7; // number of legendre polynomials we allow for 0072 const int ScalarCount = 40 + legendreCount; // number of mathematical scalar functions 0073 const int VectorCount = 3; // number of vector functions 0074 //@} 0075 0076 //@{ 0077 /** Predefined mathematical function with one variable. */ 0078 double sign(double x); 0079 double heaviside(double x); 0080 double sqr(double x); 0081 0082 double lsec(double x); 0083 double lcosec(double x); 0084 double lcot(double x); 0085 double larcsec(double x); 0086 double larccosec(double x); 0087 double larccot(double x); 0088 0089 double sech(double x); 0090 double cosech(double x); 0091 double coth(double x); 0092 double arsech(double x); 0093 double arcosech(double x); 0094 double arcoth(double x); 0095 0096 double lcos(double x); 0097 double lsin(double x); 0098 double ltan(double x); 0099 0100 double larccos(double x); 0101 double larcsin(double x); 0102 double larctan(double x); 0103 0104 double legendre0(double x); 0105 double legendre1(double x); 0106 double legendre2(double x); 0107 double legendre3(double x); 0108 double legendre4(double x); 0109 double legendre5(double x); 0110 double legendre6(double x); 0111 0112 double factorial(double x); 0113 double lerf(double x); 0114 double lerfc(double x); 0115 0116 /** Predefined mathematical functions with an indefinite number of variables. */ 0117 double min(const Vector &x); 0118 double max(const Vector &x); 0119 double mod(const Vector &x); 0120 0121 struct ScalarFunction { 0122 QString name1; 0123 QString name2; 0124 double (*mfadr)(double); 0125 }; 0126 0127 struct VectorFunction { 0128 QString name; 0129 double (*mfadr)(const Vector &); 0130 }; 0131 0132 /** 0133 * Fixes user-entered expressions into a form that can be handled by the 0134 * parser. Also keeps track of how the string was modified, so that if an error 0135 * occurs, then the correct position can be reported to the user. 0136 * \note The convention used here is that the first letter in a string 0137 * is at position zero. 0138 */ 0139 class ExpressionSanitizer 0140 { 0141 public: 0142 explicit ExpressionSanitizer(Parser *parent); 0143 0144 /** 0145 * Lots of changes to make it happy for the parser (e.g. adding extra 0146 * *-characters, remove spaces, replace the locale .-character with '.', 0147 * etc). This function will initialize m_evalMap. 0148 * \param str The string to be fixed. 0149 */ 0150 void fixExpression(QString *str); 0151 /** 0152 * \return the position in the input string (as given to fixExpression) 0153 * that corresponds to the outputted string. 0154 */ 0155 int realPos(int evalPos); 0156 0157 protected: 0158 /** 0159 * Maps the position of the string returned by fixExpression to that 0160 * passed to it. This is so that if the parser comes across an error in the 0161 * sanitized expression, this gives the corresponding position in the user 0162 * string. 0163 */ 0164 QVector<int> m_map; 0165 0166 void remove(const QString &str); 0167 void remove(const QChar &str); 0168 void replace(QChar before, QChar after); 0169 void replace(QChar before, const QString &after); 0170 void replace(int pos, int len, const QString &after); 0171 void replace(const QString &before, const QString &after); 0172 void insert(int i, QChar ch); 0173 void append(QChar str); 0174 void stripWhiteSpace(); 0175 0176 /** 0177 * Prints the map and str to stdout; for debugging purposes. 0178 */ 0179 void displayMap(); 0180 0181 QString *m_str; 0182 0183 QString m_decimalSymbol; 0184 Parser *m_parser; 0185 }; 0186 0187 /** @short Parser. 0188 * 0189 * Tokenizes a function equation to be evaluated. 0190 */ 0191 class Parser : public QObject 0192 { 0193 Q_OBJECT 0194 public: 0195 enum Error { 0196 ParseSuccess, 0197 SyntaxError, 0198 MissingBracket, 0199 StackOverflow, 0200 FunctionNameReused, ///< function name already used 0201 RecursiveFunctionCall, 0202 EmptyFunction, 0203 NoSuchFunction, 0204 ZeroOrder, ///< zero-order differential 0205 TooManyPM, ///< too many plus-minus symbols 0206 InvalidPM, ///< Not allowed to have a plus-minus symbol, e.g. in a constant expression 0207 TooManyArguments, ///< Too many arguments in a function, e.g. "f(x,a,b,c)" 0208 IncorrectArgumentCount ///< wrong number of arguments being passed to a function 0209 }; 0210 0211 ~Parser(); 0212 0213 /** 0214 * \param includeAliases whether to return function aliases (e.g. 0215 * arsinh for arcsinh). 0216 * \return the list of predefined function names. 0217 */ 0218 QStringList predefinedFunctions(bool includeAliases) const; 0219 /** 0220 * \return the list of user defined function names. 0221 */ 0222 QStringList userFunctions() const; 0223 /** 0224 * @return A string that is safe to use as a number in a string to be 0225 * parsed. This is needed as e.g. "1.2e-3" is not allowed (e is a 0226 * constant) - so cannot use the QString::number. 0227 */ 0228 static QString number(double value); 0229 /** 0230 * Calls the array version of this function, after inserting the value 0231 * of the equation's parameter into x. 0232 */ 0233 double fkt(Equation *it, double x); 0234 double fkt(uint id, int eq, double x); 0235 /** 0236 * Returns the result of a calculation. \p x are parameters for the 0237 * function (which are not necessarily all used). 0238 */ 0239 double fkt(Equation *it, const Vector &x); 0240 /** 0241 * Evaluates the given expression. 0242 * \param str the given expression. 0243 * \param error if non-null, then will be set to the parser error (or 0244 * ParserSuccess if no errors). 0245 * \param errorPosition will be set to the position of the error (if 0246 * there is one). 0247 */ 0248 double eval(const QString &str, Error *error = 0, int *errorPosition = 0); 0249 /** 0250 * Adds a user defined function with the given equation. The new 0251 * function's ID-number is returned. \p force is used to force use of 0252 * \p str1, \p str2, even if they cannot be parsed. 0253 */ 0254 int addFunction(const QString &str1, const QString &str2, Function::Type type, bool force = false); 0255 /** 0256 * Removes the function with the given id. 0257 */ 0258 bool removeFunction(uint id); 0259 bool removeFunction(Function *item); 0260 /** 0261 * Removes all functions. 0262 */ 0263 void removeAllFunctions(); 0264 /** 0265 * Returns the ID-number of the function "name". If the function 0266 * couldn't be found, -1 is returned. 0267 */ 0268 int fnameToID(const QString &name); 0269 /** 0270 * \return An error string appropriate for the given error. 0271 */ 0272 static QString errorString(Error error); 0273 /** 0274 * Displays an error dialog appropriate to \p error. 0275 */ 0276 void displayErrorDialog(Error error); 0277 /** 0278 * \return the number of radians per angle-unit that the user has 0279 * selected (i.e. this will return 1.0 if the user has selected 0280 * radians; and PI/180 if the user has selected degrees). 0281 */ 0282 static double radiansPerAngleUnit() 0283 { 0284 return m_radiansPerAngleUnit; 0285 } 0286 0287 enum AngleMode { Radians = 0, Degrees = 1 }; 0288 /** 0289 * Sets the angle mode (in which the calculations are performed). 0290 */ 0291 void setAngleMode(AngleMode mode); 0292 /** 0293 * Initializes the function for evaluation. Called after the functions 0294 * fstr is set. 0295 */ 0296 void initEquation(Equation *equation, Error *error = 0, int *errorPosition = 0); 0297 0298 uint getNewId(); /// Returns the next ID-number 0299 uint countFunctions(); /// Returns how many functions there are 0300 0301 /// The constants used by the parser 0302 Constants *constants() const 0303 { 0304 return m_constants; 0305 } 0306 0307 /// @return the function with the given id 0308 Function *functionWithID(int id) const; 0309 0310 /// Points to the array of user defined functions, index by their IDs. 0311 QMap<int, Function *> m_ufkt; 0312 0313 /// Reparses all functions, e.g. for when the value of a constant changes 0314 void reparseAllFunctions(); 0315 0316 signals: 0317 /// emitted when a function is deleted 0318 void functionRemoved(int id); 0319 /// emitted when a function is added 0320 void functionAdded(int id); 0321 0322 private: 0323 /** Mathematical function. */ 0324 static ScalarFunction scalarFunctions[ScalarCount]; 0325 static VectorFunction vectorFunctions[VectorCount]; 0326 0327 void heir0(); 0328 void heir1(); 0329 void heir2(); 0330 void heir3(); 0331 void heir4(); 0332 void heir5(); 0333 void primary(); 0334 bool tryFunction(); 0335 bool tryPredefinedFunction(); 0336 bool tryUserFunction(); 0337 bool tryVariable(); 0338 bool tryConstant(); 0339 bool tryNumber(); 0340 void addToken(Token token); 0341 void addConstant(double); 0342 void adduint(uint); 0343 void addfptr(double (*)(double)); 0344 void addfptr(double (*)(const Vector &), int argCount); 0345 /** 0346 * \p id Id of the function 0347 * \p eq_id Which equation of the function to use 0348 * \p args The number of variables being passed to the function 0349 */ 0350 void addfptr(uint id, uint eq_id, uint args); 0351 /** 0352 * Attempts to \p string to the current evaluation text. If the text at 0353 * the current evaluation position is matched, then the evaluation 0354 * position is incremented past the length of the string and true is 0355 * returned. Else the evaluation position remains unchanged, and false 0356 * is returned. 0357 */ 0358 bool match(const QString &string); 0359 /** 0360 * Continues to read the expression inside a brackets of a vector 0361 * function until get to the end of the argument list. 0362 * \return the number of arguments 0363 */ 0364 int readFunctionArguments(); 0365 0366 void growEqMem(int growth); 0367 QByteArray *mem; ///< Pointer to the array of tokens for the current equation being parsed 0368 char *mptr; ///< Pointer to the next position of insertion for the parsed equation data 0369 double *m_stack; 0370 double *stkptr; 0371 QString m_eval; 0372 int m_evalPos; 0373 int m_nextFunctionID; 0374 /// @return the m_eval starting at m_evalPos 0375 QString evalRemaining(); 0376 QString m_evalRemaining; 0377 Equation *m_currentEquation; // Pointer to the current function 0378 Equation *m_ownEquation; ///< used for parsing constants, etc, and ensures that m_currentEquation is never null 0379 static double m_radiansPerAngleUnit; 0380 Constants *m_constants; 0381 ExpressionSanitizer m_sanitizer; 0382 int m_pmAt; ///< When parsing an expression, which plus-minus symbol at 0383 Error *m_error; 0384 0385 private: 0386 friend class XParser; 0387 friend class ExpressionSanitizer; 0388 Parser(); 0389 }; 0390 0391 #endif // parser_included