File indexing completed on 2024-06-23 04:27:02

0001 /* This file is part of the KDE project
0002  * SPDX-FileCopyrightText: 2007 Jan Hambrecht <jaham@gmx.net>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 
0007 #ifndef KOENHANCEDPATHFORMULA_H
0008 #define KOENHANCEDPATHFORMULA_H
0009 
0010 #include <QString>
0011 #include <QVariant>
0012 
0013 class EnhancedPathShape;
0014 
0015 class FormulaToken
0016 {
0017 public:
0018     /// token types
0019     enum Type {
0020         TypeUnknown = 0, ///< unknown type
0021         TypeNumber,      ///< 14, 3, 1977, 3.141592, 1e10, 5.9e-7
0022         TypeOperator,    ///< +, *, /, -
0023         TypeReference,   ///< function reference, modifier reference or named variable
0024         TypeFunction     ///< function name
0025     };
0026 
0027     /// operator types
0028     enum Operator {
0029         OperatorInvalid,   ///< invalid operator
0030         OperatorAdd,       ///< + addition
0031         OperatorSub,       ///< - subtraction
0032         OperatorMul,       ///< * multiplication
0033         OperatorDiv,       ///< / division
0034         OperatorLeftPar,   ///< (left parentheses
0035         OperatorRightPar,  ///<) right parentheses
0036         OperatorComma      ///< , comma
0037     };
0038 
0039     /// Constructs token with given type, text and position
0040     explicit FormulaToken(Type type = TypeUnknown, const QString &text = QString(), int position = -1);
0041 
0042     /// copy constructor
0043     FormulaToken(const FormulaToken &token);
0044 
0045     /// assignment operator
0046     FormulaToken &operator=(const FormulaToken &token);
0047 
0048     /// Returns the type of the token
0049     Type type() const
0050     {
0051         return m_type;
0052     }
0053     /// Returns the text representation of the token
0054     QString text() const
0055     {
0056         return m_text;
0057     }
0058     /// Returns the position of the token
0059     int position() const
0060     {
0061         return m_position;
0062     }
0063 
0064     /// Returns if the token is a number
0065     bool isNumber() const
0066     {
0067         return m_type == TypeNumber;
0068     }
0069     /// Returns if the token is a operator, OperatorInvalid if token is no operator
0070     bool isOperator() const
0071     {
0072         return m_type == TypeOperator;
0073     }
0074     /// Returns if token is a function
0075     bool isFunction() const
0076     {
0077         return m_type == TypeFunction;
0078     }
0079     /// Returns  if token is a reference
0080     bool isReference() const
0081     {
0082         return m_type == TypeReference;
0083     }
0084 
0085     /// Returns the token converted to qreal
0086     qreal asNumber() const;
0087     /// Returns the token as operator
0088     Operator asOperator() const;
0089 private:
0090     Type m_type {TypeUnknown};    ///< the token type
0091     QString m_text; ///< the token text representation
0092     int m_position {-1}; ///< the tokens position
0093 };
0094 
0095 typedef QList<FormulaToken> TokenList;
0096 
0097 class Opcode;
0098 
0099 class EnhancedPathFormula
0100 {
0101 public:
0102     /// predefined functions
0103     enum Function {
0104         FunctionUnknown,
0105         // unary functions
0106         FunctionAbs,
0107         FunctionSqrt,
0108         FunctionSin,
0109         FunctionCos,
0110         FunctionTan,
0111         FunctionAtan,
0112         // binary functions
0113         FunctionAtan2,
0114         FunctionMin,
0115         FunctionMax,
0116         // ternary functions
0117         FunctionIf
0118     };
0119 
0120     /// The possible error code returned by error()
0121     enum Error {
0122         ErrorNone,    ///< no error
0123         ErrorValue,   ///< error when converting value
0124         ErrorParse,   ///< parsing error
0125         ErrorCompile, ///< compiling error
0126         ErrorName     ///< invalid function name value
0127     };
0128 
0129     /// Constructs a new formula from the specified string representation
0130     EnhancedPathFormula(const QString &text, EnhancedPathShape *parent);
0131 
0132     /// Destroys the formula
0133     ~EnhancedPathFormula();
0134 
0135     /**
0136      * Evaluates the formula using the given path as possible input.
0137      *
0138      * @param path the path to use as input
0139      * @return the evaluated result
0140      */
0141     qreal evaluate();
0142 
0143     /// Returns the last occurred error
0144     Error error() const
0145     {
0146         return m_error;
0147     }
0148 
0149     /// returns string representation of the formula
0150     QString toString() const;
0151 private:
0152     /// Separates the given formula text into tokens.
0153     TokenList scan(const QString &formula) const;
0154 
0155     /// Compiles the formula tokens into byte code
0156     bool compile(const TokenList &tokens);
0157 
0158     /**
0159      * Evaluates a predefined function.
0160      *
0161      * @param function the identifier of the function to evaluate
0162      * @param arguments the functions arguments
0163      */
0164     qreal evaluateFunction(Function function, const QList<qreal> &arguments) const;
0165 
0166     /// Prints token list
0167     void debugTokens(const TokenList &tokens);
0168     /// Prints byte code
0169     void debugOpcodes();
0170 
0171     bool m_valid;    ///< flag that shows if function is valid, i.e the function was compiled successfully
0172     bool m_compiled; ///< flag that shows if function was compiled
0173     Error m_error;   ///< the last occurred error
0174     QString m_text; ///< the formula text representation
0175     QList<QVariant> m_constants; ///< constant values
0176     QList<Opcode> m_codes; ///< the compiled byte code
0177     EnhancedPathShape *m_parent;
0178 };
0179 
0180 #endif // KOENHANCEDPATHFORMULA_H