SpeedCrunch
0.11
|
00001 // This file is part of the SpeedCrunch project 00002 // Copyright (C) 2004 Ariya Hidayat <ariya@kde.org> 00003 // Copyright (C) 2008, 2009, 2010, 2013 Helder Correia <helder.pereira.correia@gmail.com> 00004 // 00005 // This program is free software; you can redistribute it and/or 00006 // modify it under the terms of the GNU General Public License 00007 // as published by the Free Software Foundation; either version 2 00008 // of the License, or (at your option) any later version. 00009 // 00010 // This program is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with this program; see the file COPYING. If not, write to 00017 // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 // Boston, MA 02110-1301, USA. 00019 00020 #ifndef CORE_EVALUATOR_H 00021 #define CORE_EVALUATOR_H 00022 00023 #include "core/functions.h" 00024 #include "math/hmath.h" 00025 00026 #include <QHash> 00027 #include <QObject> 00028 #include <QSet> 00029 #include <QString> 00030 #include <QStringList> 00031 #include <QVector> 00032 00033 class Token { 00034 public: 00035 enum Op { InvalidOp = 0, Plus, Minus, Asterisk, Slash, Backslash, Caret, 00036 Super0, Super1, Super2, Super3, Super4, Super5, Super6, Super7, Super8, Super9, 00037 LeftPar, RightPar, Semicolon, Percent, Exclamation, Equal, Modulo, 00038 LeftShift, RightShift, Ampersand, Pipe }; 00039 enum Type { stxUnknown, stxNumber, stxIdentifier, stxOperator, stxOpenPar, stxClosePar, stxSep }; 00040 00041 static const Token null; 00042 00043 Token(Type type = stxUnknown, const QString& text = QString::null, int pos = -1); 00044 Token(const Token&); 00045 00046 HNumber asNumber() const; 00047 Op asOperator() const; 00048 QString description() const; 00049 bool isNumber() const { return m_type == stxNumber; } 00050 bool isOperator() const { return m_type >= stxOperator; } 00051 bool isIdentifier() const { return m_type == stxIdentifier; } 00052 int pos() const { return m_pos; } 00053 QString text() const { return m_text; } 00054 Type type() const { return m_type; } 00055 00056 Token& operator=(const Token&); 00057 00058 protected: 00059 int m_pos; 00060 QString m_text; 00061 Type m_type; 00062 }; 00063 00064 class Tokens : public QVector<Token> { 00065 public: 00066 Tokens() : QVector<Token>(), m_valid(true) { } 00067 00068 bool valid() const { return m_valid; } 00069 void setValid(bool v) { m_valid = v; } 00070 00071 protected: 00072 bool m_valid; 00073 }; 00074 00075 00076 class Evaluator : public QObject { 00077 Q_OBJECT 00078 00079 public: 00080 struct Variable { 00081 enum Type { BuiltIn, UserDefined }; 00082 Variable() : name(""), value(HNumber(0)) { } 00083 Variable(const QString& n, HNumber v, Type t = UserDefined) : name(n), value(v), type(t) { } 00084 bool operator==(const Variable& other) const { return name == other.name; } 00085 QString name; 00086 HNumber value; 00087 Type type; 00088 }; 00089 00090 struct UserFunctionDescr { 00091 QString name; 00092 QStringList arguments; 00093 QString expression; 00094 00095 UserFunctionDescr(QString name, QStringList arguments, QString expression) 00096 : name(name), arguments(arguments), expression(expression) {} 00097 }; 00098 00099 // Needed only for issue 160 workaround. 00100 enum AutoFixPolicy { AutoFix, NoAutoFix }; 00101 00102 static Evaluator* instance(); 00103 void reset(); 00104 00105 static bool isSeparatorChar(const QChar&); 00106 static bool isRadixChar(const QChar&); 00107 00108 QString autoFix(const QString&); 00109 QString dump(); 00110 QString error() const; 00111 HNumber eval(); 00112 HNumber evalNoAssign(); 00113 HNumber evalUpdateAns(); 00114 QString expression() const; 00115 bool isValid(); 00116 Tokens scan(const QString&, AutoFixPolicy = AutoFix) const; 00117 void setExpression(const QString&); 00118 Tokens tokens() const; 00119 bool isUserFunctionAssign() const; 00120 00121 Variable getVariable(const QString&) const; 00122 QList<Variable> getVariables() const; 00123 QList<Variable> getUserDefinedVariables() const; 00124 QList<Variable> getUserDefinedVariablesPlusAns() const; 00125 void setVariable(const QString&, HNumber, Variable::Type = Variable::UserDefined); 00126 void unsetVariable(const QString&); 00127 void unsetAllUserDefinedVariables(); 00128 bool isBuiltInVariable(const QString&) const; 00129 bool hasVariable(const QString&) const; 00130 00131 //UserFunctionDescr getUserFunction(const QString&) const; 00132 QList<UserFunctionDescr> getUserFunctions() const; 00133 void setUserFunction(const UserFunctionDescr&); 00134 void unsetUserFunction(const QString&); 00135 void unsetAllUserFunctions(); 00136 bool hasUserFunction(const QString&); 00137 00138 protected: 00139 void compile(const Tokens&); 00140 00141 private: 00142 Evaluator(); 00143 Q_DISABLE_COPY(Evaluator) 00144 00145 struct Opcode { 00146 enum { Nop = 0, Load, Ref, Function, Add, Sub, Neg, Mul, Div, Pow, 00147 Fact, Modulo, IntDiv, LSh, RSh, BAnd, BOr }; 00148 00149 unsigned type; 00150 unsigned index; 00151 00152 Opcode() : type(Nop), index(0) {} 00153 Opcode(unsigned t) : type(t), index(0) {} 00154 Opcode(unsigned t, unsigned i): type(t), index(i) {} 00155 }; 00156 00157 struct UserFunction { 00158 UserFunctionDescr descr; 00159 00160 QVector<HNumber> constants; 00161 QStringList identifiers; 00162 QVector<Opcode> opcodes; 00163 00164 bool inUse; 00165 00166 UserFunction(UserFunctionDescr& descr) 00167 : descr(descr), inUse(false) {} 00168 UserFunction(QString name, QStringList arguments, QString expression) 00169 : descr(name, arguments, expression), inUse(false) {} 00170 }; 00171 00172 bool m_dirty; 00173 QString m_error; 00174 QString m_expression; 00175 bool m_valid; 00176 QString m_assignId; 00177 bool m_assignFunc; 00178 QStringList m_assignArg; 00179 QVector<Opcode> m_codes; 00180 QVector<HNumber> m_constants; 00181 QStringList m_identifiers; 00182 QHash<QString, Variable> m_variables; 00183 QHash<QString, UserFunction*> m_userFunctions; 00184 00185 const HNumber& checkOperatorResult(const HNumber&); 00186 static QString stringFromFunctionError(Function*); 00187 void initializeBuiltInVariables(); 00188 HNumber exec(const QVector<Opcode>& opcodes, const QVector<HNumber>& constants, 00189 const QStringList& identifiers); 00190 HNumber execUserFunction(UserFunction* function, QVector<HNumber>& arguments); 00191 UserFunction* getUserFunction(const QString&) const; 00192 }; 00193 00194 #endif