SpeedCrunch  0.11
/usr/src/RPM/BUILD/speedcrunch-0.11/src/core/evaluator.h
Go to the documentation of this file.
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