File indexing completed on 2024-05-12 17:22:31
0001 // This file is part of the SpeedCrunch project 0002 // Copyright (C) 2004 Ariya Hidayat <ariya@kde.org> 0003 // Copyright (C) 2008-2016 @heldercorreia 0004 // 0005 // This program is free software; you can redistribute it and/or 0006 // modify it under the terms of the GNU General Public License 0007 // as published by the Free Software Foundation; either version 2 0008 // of the License, or (at your option) any later version. 0009 // 0010 // This program is distributed in the hope that it will be useful, 0011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 // GNU General Public License for more details. 0014 // 0015 // You should have received a copy of the GNU General Public License 0016 // along with this program; see the file COPYING. If not, write to 0017 // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 // Boston, MA 02110-1301, USA. 0019 0020 #ifndef CORE_EVALUATOR_H 0021 #define CORE_EVALUATOR_H 0022 0023 #include "functions.h" 0024 #include "opcode.h" 0025 0026 #include "hmath.h" 0027 #include "cmath.h" 0028 #include "quantity.h" 0029 0030 #include <QHash> 0031 #include <QObject> 0032 #include <QSet> 0033 #include <QString> 0034 #include <QStringList> 0035 #include <QVector> 0036 0037 class Token { 0038 public: 0039 enum Operator { 0040 Invalid = 0, 0041 Addition, Subtraction, Multiplication, 0042 Division, IntegerDivision, Exponentiation, 0043 Super0, Super1, Super2, Super3, Super4, 0044 Super5, Super6, Super7, Super8, Super9, 0045 AssociationStart, AssociationEnd, 0046 ListSeparator, Factorial, Assignment, Modulo, 0047 ArithmeticLeftShift, ArithmeticRightShift, 0048 BitwiseLogicalAND, BitwiseLogicalOR, 0049 UnitConversion, 0050 Function // For managing shift/reduce conflicts. 0051 }; 0052 enum Type { 0053 stxUnknown, stxNumber, stxIdentifier, stxAbstract, // isOperand 0054 stxOperator, stxOpenPar, stxClosePar, stxSep // isOperator 0055 }; 0056 0057 static const Token null; 0058 0059 Token(Type = stxUnknown, const QString& = QString(), int pos = -1, 0060 int size = -1); 0061 Token(const Token&); 0062 0063 Quantity asNumber() const; 0064 Operator asOperator() const; 0065 QString description() const; 0066 bool isNumber() const { return m_type == stxNumber; } 0067 bool isOperator() const { return m_type >= stxOperator; } 0068 bool isIdentifier() const { return m_type == stxIdentifier; } 0069 bool isAbstract() const { return m_type == stxAbstract; } 0070 bool isOperand() const { return isNumber() || isIdentifier() 0071 || isAbstract(); } 0072 int pos() const { return m_pos; } 0073 void setPos(int pos) { m_pos = pos; } 0074 int size() const { return m_size; } 0075 void setSize(int size) { m_size = size; } 0076 QString text() const { return m_text; } 0077 Type type() const { return m_type; } 0078 int minPrecedence() const { return m_minPrecedence; } 0079 void setMinPrecedence(int value) { m_minPrecedence = value; } 0080 0081 Token& operator=(const Token&); 0082 0083 protected: 0084 // Start position of the text that token represents in the expression 0085 // (might include extra space characters). 0086 int m_pos; 0087 // Size of text that token represents in the expression 0088 // (might include extra space characters). 0089 int m_size; 0090 // Precedence of the operator with the lowest precedence contained 0091 // in this token. 0092 int m_minPrecedence; 0093 // Normalized version of that token text (only valid when the token 0094 // represents a single token). 0095 QString m_text; 0096 Type m_type; 0097 }; 0098 0099 class Tokens : public QVector<Token> { 0100 public: 0101 Tokens() 0102 : QVector<Token>() 0103 , m_valid(true) 0104 { } 0105 0106 bool valid() const { return m_valid; } 0107 void setValid(bool v) { m_valid = v; } 0108 0109 #ifdef EVALUATOR_DEBUG 0110 void append(const Token&); 0111 #endif /* EVALUATOR_DEBUG */ 0112 0113 protected: 0114 bool m_valid; 0115 }; 0116 0117 class Evaluator : public QObject { 0118 Q_OBJECT 0119 using ForceBuiltinVariableErasure = bool; 0120 0121 public: 0122 static Evaluator* instance(); 0123 void reset(); 0124 0125 // void setSession(Session*); 0126 // const Session* session(); 0127 0128 static bool isSeparatorChar(const QChar&); 0129 static bool isRadixChar(const QChar&); 0130 static QString fixNumberRadix(const QString&); 0131 0132 QString autoFix(const QString&); 0133 QString dump(); 0134 QString error() const; 0135 Quantity evalNoAssign(); 0136 QString expression() const; 0137 bool isValid(); 0138 Tokens scan(const QString&) const; 0139 void setExpression(const QString&); 0140 Tokens tokens() const; 0141 0142 void setVariable(const QString&, Quantity); 0143 void unsetVariable(const QString&, ForceBuiltinVariableErasure = false); 0144 bool isBuiltInVariable(const QString&) const; 0145 void initializeBuiltInVariables(); 0146 void initializeAngleUnits(); 0147 0148 protected: 0149 void compile(const Tokens&); 0150 0151 private: 0152 Evaluator(); 0153 Q_DISABLE_COPY(Evaluator) 0154 0155 bool m_dirty; 0156 QString m_error; 0157 QString m_expression; 0158 bool m_valid; 0159 QString m_assignId; 0160 bool m_assignFunc; 0161 QStringList m_assignArg; 0162 QVector<Opcode> m_codes; 0163 QVector<Quantity> m_constants; 0164 QStringList m_identifiers; 0165 QSet<QString> m_functionsInUse; 0166 QHash<QString, QString> m_unitFixups; 0167 QSet<QString> m_allUnits; 0168 QHash<QString, Quantity> m_variables; 0169 0170 const Quantity& checkOperatorResult(const Quantity&); 0171 static QString stringFromFunctionError(Function*); 0172 Quantity exec(const QVector<Opcode>& opcodes, 0173 const QVector<Quantity>& constants, 0174 const QStringList& identifiers); 0175 0176 bool isFunction(Token token) { 0177 return token.isIdentifier() 0178 && (FunctionRepo::instance()->find(token.text())); 0179 } 0180 }; 0181 0182 #endif