1 /************************************************************************************* 2 * Copyright (C) 2007-2010 by Aleix Pol <aleixpol@kde.org> * 3 * * 4 * This program is free software; you can redistribute it and/or * 5 * modify it under the terms of the GNU General Public License * 6 * as published by the Free Software Foundation; either version 2 * 7 * of the License, or (at your option) any later version. * 8 * * 9 * This program is distributed in the hope that it will be useful, * 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 12 * GNU General Public License for more details. * 13 * * 14 * You should have received a copy of the GNU General Public License * 15 * along with this program; if not, write to the Free Software * 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 17 *************************************************************************************/ 18 19 20 #ifndef ANALYZER_H 21 #define ANALYZER_H 22 23 #include <QStringList> 24 #include <QSharedPointer> 25 #include <QStack> 26 27 #include "expression.h" 28 #include "analitzaexport.h" 29 #include "expressiontype.h" 30 #include "builtinmethods.h" 31 #include <analitza/analitzautils.h> 32 33 namespace Analitza 34 { 35 class Polynomial; 36 class Apply; 37 class BoundingIterator; 38 class BuiltinMethods; 39 class Object; 40 class Variables; 41 class Container; 42 class Operator; 43 class Ci; 44 45 /** 46 * \class Analyzer 47 * 48 * \ingroup AnalitzaModule 49 * 50 * \brief The parser: Evaluates and calculates math expressions. 51 * 52 * Is the base Math class, Analyzer can evaluate simple expressions, expressions 53 * that contains any number of variables and lambda expressions. 54 * 55 * If Analyzer is created with a custom Variables module, then calculate() or evaluate() 56 * will be aware of the variables inside the module. 57 */ 58 59 class ANALITZA_EXPORT Analyzer 60 { 61 public: 62 /** Constructor. Creates an empty Analyzer module with a Variables module. */ 63 Analyzer(); 64 65 /** Constructor. Creates an empty Analyzer module. 66 @param v: Sets a custom variables module. This module will _not_ be deleted along with Analyzer 67 */ 68 explicit Analyzer(Variables* v); 69 explicit Analyzer(const QSharedPointer<Variables> &v); 70 71 /** Copy constructor. Creates a copy of the @p a Analyzer instance. Inherits its Variable structure. */ 72 Analyzer(const Analyzer& a); 73 74 /** Destructor. */ 75 ~Analyzer(); 76 77 /** sets the @p v Variables tuple we are going to use */ 78 void setVariables(const QSharedPointer<Variables> &v); 79 80 /** Sets an expression to calculate. */ 81 void setExpression(const Expression &e); 82 83 /** Returns the expression in display. */ expression()84 const Expression& expression() const { return m_exp; } 85 86 /** Calculates the expression and returns a value alone. */ 87 Expression calculate(); 88 89 /** 90 * Calculates the expression and returns a value alone. 91 * The parameters need to be set by passing a stack instance 92 */ 93 Expression calculateLambda(); 94 95 /** Evaluates an expression, like calculate() but returns a tree. */ 96 Expression evaluate(); 97 98 /** Evaluates the derivative of an expression expression, like expression() but sorrounded with a diff(). */ 99 Expression derivative(const QString& var); 100 101 /** Evaluates the derivative of an expression expression. */ 102 double derivative(const QVector<Object*>& values ); 103 104 /** Returns whether there has been a problem in the last calculation. */ isCorrect()105 bool isCorrect() const { return m_err.isEmpty() && m_exp.isCorrect(); } 106 107 /** Empties the error list. */ flushErrors()108 void flushErrors() { m_err.clear(); } 109 110 /** simplifies the expression. */ 111 void simplify(); //FIXME: Should return an Expression 112 113 /** @returns Return an error list. */ errors()114 QStringList errors() const { return m_exp.error() + m_err; } 115 116 /** @returns Returns a way to query variables. */ variables()117 QSharedPointer<Variables> variables() const { return m_vars; } 118 119 /** 120 Adds a variable entry. It is the proper way to do it because tracks some possible errors. 121 May change the error in case we're trying to represent something wrong. 122 @returns Returns if it was actually inserted. 123 */ 124 bool insertVariable(const QString& name, const Expression& value); 125 126 /** 127 Adds a variable entry. It is the proper way to do it because tracks some possible errors. 128 May change the error in case we're trying to represent something wrong. 129 @returns Returns if it was actually inserted. 130 */ 131 bool insertVariable(const QString& name, const Object* value); 132 133 /** 134 Adds a variable entry named @p name with @p value value. 135 @returns Returns the added object 136 */ 137 Cn* insertValueVariable(const QString& name, double value); 138 139 /** Returns whether the current expression has all data it needs to be calculated.*/ hasDependencies()140 bool hasDependencies() const { return m_hasdeps; } 141 142 /** This method is useful if you want to work programatically on functions with undefined variables. 143 @returns the same expression set but with explicit dependencies. 144 145 e.g. x+2 would return x->x+2 146 */ 147 Expression dependenciesToLambda() const; 148 149 /** This method lets you retrieve the current type in use. 150 @returns the type of the current expression. 151 */ type()152 ExpressionType type() const { return m_currentType; } 153 setStack(const QVector<Object * > & stack)154 void setStack(const QVector<Object*>& stack) { m_runStack = stack; } 155 runStack()156 QVector<Object*> runStack() const { return m_runStack; } 157 158 BuiltinMethods* builtinMethods(); 159 160 /** Makes it possible to easily enter a bunch of code to execute it */ 161 void importScript(QTextStream* stream); 162 163 /** @returns the type for any variable that depends on the last executed procedure */ variableTypes()164 QMap<QString, ExpressionType> variableTypes() const { return m_variablesTypes; } 165 private: 166 typedef Object* (Analyzer::*funcContainer)(const Container*); 167 static funcContainer operateContainer[]; 168 169 Expression m_exp; 170 QSharedPointer<Variables> m_vars; 171 QStringList m_err; 172 QVector<Object*> m_runStack; 173 int m_runStackTop; 174 BuiltinMethods m_builtin; 175 176 bool m_hasdeps; 177 ExpressionType m_currentType; 178 QMap<QString, ExpressionType> m_variablesTypes; 179 180 void registerBuiltinMethods(); //util to be called in each ctr 181 182 Object* calc(const Object* e); 183 Object* operate(const Container*); 184 Object* operate(const Apply*); 185 Object* eval(const Object* e, bool vars, const QSet<QString>& unscoped); 186 187 Object* sum(const Apply& c); 188 Object* product(const Apply& c); 189 Object* exists(const Apply& c); 190 Object* forall(const Apply& c); 191 Object* func(const Apply& c); 192 Object* calcDiff(const Apply* c); 193 Object* calcMap(const Apply* c); 194 Object* calcFilter(const Apply* c); 195 196 Object* calcPiecewise(const Container* c); 197 Object* calcDeclare(const Container* c); 198 Object* calcMath(const Container* c); 199 Object* calcLambda(const Container* c); 200 Object* calcCallFunction(Analitza::Container* function, const QVector<Analitza::Object* >& args, const Analitza::Object* op); 201 202 Object* simp(Object* root); 203 Object* simpPolynomials(Apply* c); 204 Object* simpSum(Apply* c); 205 Object* simpApply(Apply* c); 206 Object* simpPiecewise(Container* c); 207 208 QList<Object*> findRoots(const QString& dep, const Analitza::Object* o); 209 QList<Object*> findRootsApply(const QString& dep, const Analitza::Apply* a); 210 211 Object* derivative(const QString &var, const Object*); 212 Object* boundedOperation(const Apply & n, const Operator & t, Object* initial); 213 214 BoundingIterator* initializeBVars(const Apply* n, int base); 215 BoundingIterator* initBVarsContainer(const Apply* n, int base, Object* domain); 216 BoundingIterator* initBVarsRange(const Apply* n, int base, Object* dlimit, Object* ulimit); 217 218 template <class T, class Tcontained = Object> 219 void iterateAndSimp(T* v); 220 221 Object* variableValue(Ci* var); 222 Object* testResult(const Analitza::Object* o, const QString& var, const Analitza::Object* val); 223 224 template <class T, class Tcontained = Object> 225 void alphaConversion(T* o, int min); 226 void alphaConversion(Apply* a, int min); 227 void alphaConversion(Container* a, int min); 228 Object* applyAlpha(Analitza::Object* o, int min); 229 230 template<class T, class Tcontained = Object> 231 Object* calcElements(const Analitza::Object* root, T* nv); 232 233 template<class T, class Tcontained = Object> 234 Object* evalElements(const Analitza::Object* root, T* nv, bool resolve, const QSet<QString>& unscoped); 235 }; 236 237 } 238 #endif 239