File indexing completed on 2024-04-28 03:40:41

0001 /*************************************************************************************
0002  *  Copyright (C) 2007 by Aleix Pol <aleixpol@kde.org>                               *
0003  *                                                                                   *
0004  *  This program is free software; you can redistribute it and/or                    *
0005  *  modify it under the terms of the GNU General Public License                      *
0006  *  as published by the Free Software Foundation; either version 2                   *
0007  *  of the License, or (at your option) any later version.                           *
0008  *                                                                                   *
0009  *  This program is distributed in the hope that it will be useful,                  *
0010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of                   *
0011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                    *
0012  *  GNU General Public License for more details.                                     *
0013  *                                                                                   *
0014  *  You should have received a copy of the GNU General Public License                *
0015  *  along with this program; if not, write to the Free Software                      *
0016  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA   *
0017  *************************************************************************************/
0018 
0019 #ifndef EXPRESSION_H
0020 #define EXPRESSION_H
0021 
0022 #include <QStringList>
0023 #include <QSharedDataPointer>
0024 
0025 #include "analitzaexport.h"
0026 #include "object.h"
0027 
0028 namespace Analitza
0029 {
0030 class Ci;
0031 class Cn;
0032 
0033 /**
0034  * \class Expression
0035  * 
0036  * \ingroup AnalitzaModule
0037  *
0038  * \brief Represents a mathematical expression.
0039  *
0040  * Expression let to convert it to string, MathML and make some little queries 
0041  * to it, without calculating anything.
0042  */
0043 
0044 class ANALITZA_EXPORT Expression
0045 {
0046     Q_GADGET
0047     public:
0048         typedef void (*CustomObjectDestructor)(const QVariant&);
0049         /**
0050          *    Constructs an empty Expression.
0051          */
0052         Expression();
0053         
0054         /**
0055          *    Copy constructor, copies the whole object to the constructed one.
0056          */
0057         Expression(const Expression& e);
0058         
0059         /**
0060          *    Creates an expression from a value
0061          */
0062         explicit Expression(const Cn& e);
0063         
0064         explicit Expression(Object* o);
0065         
0066         /**
0067          *    Constructor. Parses an expression and creates the object.
0068          *    @param exp expression to be assigned
0069          *    @param mathml format of the expression
0070          */
0071         explicit Expression(const QString& exp, bool mathml=false);
0072         
0073         /** Destructor */
0074         ~Expression();
0075         
0076         /**
0077          *    Sets an expression @p exp which is not in MathML format. Returns whether it was correctly assigned or not.
0078          */
0079         bool setText(const QString &exp);
0080         
0081         /**
0082          *    Sets an expression @p exp which is in MathML format. Returns whether it was correctly assigned or not.
0083          */
0084         bool setMathML(const QString &exp);
0085         
0086         /**
0087          *    Returns the list of errors that had experienced while building the expression.
0088          */
0089         QStringList error() const;
0090         
0091         /** Adds a new error @p error to the expression, to be reported afterwards. */
0092         void addError(const QString& error);
0093         
0094         /**
0095          *    Returns whether this is a correct expression.
0096          */
0097         bool isCorrect() const;
0098         
0099         /**
0100          *    Returns whether the @p e is equal.
0101          */
0102         bool operator==(const Expression& e) const;
0103         
0104         bool operator!=(const Expression& e) const;
0105         
0106         /**
0107          *    Copy assignment. Copies the @p e expression here.
0108          */
0109         Expression operator=(const Expression& e);
0110         
0111         /**
0112          *    Returns whether it is a lambda-expression.
0113          */
0114         bool isLambda() const;
0115         
0116         /**
0117          *    Returns the expression of the lambda body (without resolving the dependencies)
0118          */
0119         Expression lambdaBody() const /*Q_REQUIRED_RESULT*/;
0120         
0121         /**
0122          *    Returns whether it is a vector expression.
0123          */
0124         bool isVector() const;
0125         
0126         /**
0127          *    Returns whether it is a matrix expression.
0128          */
0129         bool isMatrix() const;
0130         
0131         /**
0132          *    Returns whether it is a list expression.
0133          */
0134         bool isList() const;
0135         
0136         /**
0137          *    Returns whether it is a string expression (a list of chars).
0138          */
0139         bool isString() const;
0140         
0141         /**
0142          *    Returns the element at @p position in a vector
0143          */
0144         Expression elementAt(int position) const;
0145         
0146         /**
0147          *    sets an expression value @p value to a @p position
0148          */
0149         void setElementAt(int position, const Analitza::Expression& exp);
0150         
0151         /**
0152          *    Returns the tree associated to this object.
0153          */
0154         const Object* tree() const;
0155         
0156         /**
0157          *    Returns the tree associated to this object.
0158          */
0159         Object* tree();
0160 
0161         /**
0162          *    Returns the tree associated to this object and clears the object,
0163          *    so the ownership of the tree is acquired by the caller.
0164          */
0165         Object* takeTree();
0166         
0167         void setTree(Object* o);
0168         /**
0169          *    Converts the expression to a string expression.
0170          */
0171         Q_SCRIPTABLE QString toString() const;
0172         
0173         /**
0174          *    Converts the expression to MathML.
0175          */
0176         QString toMathML() const;
0177         
0178         /**
0179          *    Exports the expression to HTML.
0180          */
0181         QString toHtml() const;
0182         
0183         /**
0184          *    Converts the expression to MathML Presentation Markup.
0185          */
0186         QString toMathMLPresentation() const;
0187         
0188         /** @returns the contained string value */
0189         QString stringValue() const;
0190         
0191         /**
0192          * Invalidates the data of the expression.
0193          */
0194         void clear();
0195         
0196         /**
0197          * @returns Lists the global bounded variables in the expression
0198          */
0199         QStringList bvarList() const;
0200         
0201         /** @returns Value representation of the expression. */
0202         Cn toReal() const;
0203         
0204         /** @returns true if the expression is a value, false otherwise. */
0205         bool isReal() const;
0206         
0207         /** @returns true if the expression is a custom object, false otherwise. */
0208         bool isCustomObject() const;
0209         
0210         /** @returns a list of the parameters in case this expression represents
0211             a lambda construction. */
0212         QList<Ci*> parameters() const;
0213         
0214         /** In case it was a vector or list, it returns a list of each expression on the vector. */
0215         QList<Expression> toExpressionList() const;
0216         
0217         /** In case it contains a custom object it returns its value. */
0218         QVariant customObjectValue() const;
0219         
0220         /** renames the @p depth -th variable into @p newName */
0221         void renameArgument(int depth, const QString& newName);
0222         
0223         /** @returns whether it's an equation */
0224         bool isEquation() const;
0225         
0226         /** @returns whether it's a declaration */
0227         bool isDeclaration() const;
0228         
0229         /** @returns the name of the expression. If it's not a declaration
0230          * then an empty string it's returned.
0231          */
0232         QString name() const;
0233         
0234         /** @returns the value of the declaration. If it's not a declaration
0235          * then an expression it's returned.
0236          */
0237         Expression declarationValue() const;
0238         
0239         /** @returns the expression that evaluates the current equation to equal 0 */
0240         Expression equationToFunction() const;
0241         
0242         QStringList comments() const;
0243         
0244         /**
0245          *    Converts a @p tag to an object type.
0246          */
0247         static enum Object::ObjectType whatType(const QString& tag);
0248         
0249         /**
0250          *    @returns whether @p s is MathML or not. Very simple.
0251          */
0252         static bool isMathML(const QString& s) {
0253             return !s.isEmpty() && s[0] == QLatin1Char('<');
0254         }
0255         
0256         static void computeDepth(Object* o);
0257         
0258         /**
0259          * @returns an expression containing a list of every expression passed on @p exps on the form:
0260          *    list { exps[0], exps[1], ... }
0261          */
0262         static Expression constructList(const QList<Expression> & exps);
0263         
0264         /** creates an expression filled with just a custom object */
0265         static Expression constructCustomObject(const QVariant& custom, Analitza::Expression::CustomObjectDestructor d);
0266         
0267         /** creates an expression filled with just a string */
0268         static Expression constructString(const QString& str);
0269         
0270         /** @returns if a non-mathml expression is fully introduced (e.g. has closed all parentheses).
0271             @param exp the expression to analyze
0272             @param justempty tells if it's an expression with just spaces and comments
0273          */
0274         static bool isCompleteExpression(const QString& exp, bool justempty=false);
0275     private:
0276         class ExpressionPrivate;
0277         QSharedDataPointer<ExpressionPrivate> d;
0278         QStringList m_comments;
0279 };
0280 
0281 }
0282 
0283 Q_DECLARE_METATYPE(Analitza::Expression)
0284 
0285 #endif