elamvalue.h
SOURCES += \
- elamvalue.cpp
+ elamvalue.cpp \
+ elamengine.cpp
INCLUDEPATH += .
DEPENDPATH += .
--- /dev/null
+// ELAM engine definition implementation
+//
+// (c) Konrad Rosenbaum, 2010
+// protected under the GNU LGPL v3 or at your option any newer
+
+#include "elamengine.h"
+#include "elamvalue.h"
+
+ELAMEngine::ELAMEngine(QObject* parent): QObject(parent)
+{
+
+}
+
+QVariant ELAMEngine::evaluate(QString ex)
+{
+ return evaluate(parseExpression(ex));
+}
+
+QVariant ELAMEngine::evaluate(ELAMExpression ex)
+{
+ //TODO: implement
+ return QVariant();
+}
+
+ELAMExpression ELAMEngine::parseExpression(QString )
+{
+ //TODO: implement parser
+ return ELAMExpression();
+}
+
+/////////////////////////////////////////////////////////////////
+// Unary Operator
+
+class ELAMUnaryOperator::Private
+{
+ public:
+ //memory management
+ int ctr;
+ Private(){ctr=1;}
+ void detach(){ctr--;if(ctr<=0)delete this;}
+ void attach(){ctr++;}
+ //callback mapping
+ QMap<int,ELAMUnaryOperatorCall>callmap;
+};
+
+ELAMUnaryOperator::ELAMUnaryOperator(const ELAMUnaryOperator& op)
+{
+ d=0;
+ operator=(op);
+}
+
+ELAMUnaryOperator::ELAMUnaryOperator()
+{
+ d=new Private();
+}
+
+ELAMUnaryOperator::~ELAMUnaryOperator()
+{
+ if(d)d->detach();
+ d=0;
+}
+
+
+ELAMUnaryOperator& ELAMUnaryOperator::operator=(const ELAMUnaryOperator& op)
+{
+ if(d)d->detach();
+ d=op.d;
+ if(d)d->attach();
+ return *this;
+}
+
+QVariant ELAMUnaryOperator::execute(const QVariant& op) const
+{
+ if(d->callmap.size()==0)
+ return qVariantFromValue<ELAMException>(ELAMException(ELAMException::UnknownOperatorError));
+ //search for direct match
+ if(d->callmap.contains(op.type()))
+ return d->callmap[op.type()](op);
+ //search for fallback
+ int any=ELAMAnyType::metaTypeId();
+ if(d->callmap.contains(any))
+ return d->callmap[any](op);
+ return qVariantFromValue<ELAMException>(ELAMException(ELAMException::TypeMismatchError));
+}
+
+QList< int > ELAMUnaryOperator::getTypeIds() const
+{
+ return d->callmap.keys();
+}
+
+QStringList ELAMUnaryOperator::getTypeNames() const
+{
+ QStringList ret;
+ QList<int>ti=d->callmap.keys();
+ for(int i=0;i<ti.size();i++)
+ ret<<QVariant::typeToName((QVariant::Type)ti[i]);
+ return ret;
+}
+
+ELAMUnaryOperatorCall ELAMUnaryOperator::getCallback(QString type) const
+{
+ return getCallback(QVariant::nameToType(type.toAscii().data()));
+}
+
+ELAMUnaryOperatorCall ELAMUnaryOperator::getCallback(int type) const
+{
+ if(d->callmap.contains(type))
+ return d->callmap[type];
+ if(d->callmap.contains(ELAMAnyType::metaTypeId()))
+ return d->callmap[ELAMAnyType::metaTypeId()];
+ return 0;
+}
+
+void ELAMUnaryOperator::setCallback(ELAMUnaryOperatorCall callback, int type)
+{
+ if(type==QVariant::Invalid)return;
+ if(callback==0){
+ d->callmap.remove(type);
+ return;
+ }
+ d->callmap.insert(type,callback);
+}
+
+void ELAMUnaryOperator::setCallback(ELAMUnaryOperatorCall callback, QString type)
+{
+ setCallback(callback,QVariant::nameToType(type.toAscii().data()));
+}
+
+void ELAMUnaryOperator::removeCallback(ELAMUnaryOperatorCall cb)
+{
+ if(cb==0)return;
+ QList<int>k=d->callmap.keys(cb);
+ for(int i=0;i<k.size();i++)
+ d->callmap.remove(k[i]);
+}
+
+void ELAMUnaryOperator::removeCallback(QString t)
+{
+ removeCallback(QVariant::nameToType(t.toAscii().data()));
+}
+
+void ELAMUnaryOperator::removeCallback(int t)
+{
+ d->callmap.remove(t);
+}
#ifndef ELAM_ENGINE_H
#define ELAM_ENGINE_H
-#include <QString>
+#include <QStringList>
#include <QObject>
+#include <QVariant>
#include "elamexpression.h"
+/**pointer to a function wrapping an unary operator
+\param op the operand to be worked on
+\returns the result of the operation*/
+typedef QVariant (*ELAMUnaryOperatorCall)(const QVariant&op);
+
+class ELAMUnaryOperator
+{
+ public:
+ ELAMUnaryOperator(const ELAMUnaryOperator&);
+ ELAMUnaryOperator();
+ ~ELAMUnaryOperator();
+
+ ELAMUnaryOperator& operator=(const ELAMUnaryOperator&);
+
+ /**sets a callback function for the operator and a specific typ
+ \param callback the function to call, if it is null the type is deleted from this operators type list
+ \param type the type of variable to work on, this must be a type registered with QVariant, if this type is already known to the operator its callback is replaced
+ */
+ void setCallback(ELAMUnaryOperatorCall callback,QString type);
+ /**sets a callback function for the operator and a specific typ
+ \param callback the function to call, if it is null the type is deleted from this operators type list
+ \param type the type of variable to work on, this must be a type registered with QVariant, if this type is already known to the operator its callback is replaced
+ */
+ void setCallback(ELAMUnaryOperatorCall callback,int type);
+ /**returns the callback function attached to the type or NULL if there is none*/
+ ELAMUnaryOperatorCall getCallback(QString type)const;
+ /**returns the callback function attached to the type or NULL if there is none*/
+ ELAMUnaryOperatorCall getCallback(int type)const;
+
+ /**removes all types attached to this callback from the operator*/
+ void removeCallback(ELAMUnaryOperatorCall);
+ ///removes the type from this operators list
+ void removeCallback(QString);
+ ///removes the type from this operators list
+ void removeCallback(int);
+
+ ///returns all type names that have a valid callback in this operator
+ QStringList getTypeNames()const;
+ ///returns all type IDs that have a valid callback in this operator
+ QList<int> getTypeIds()const;
+
+ ///calls the callback function associated with the type of the argument, throws an exception if there is no callback
+ QVariant execute(const QVariant&)const;
+ private:
+ class Private;
+ Private *d;
+};
+
+/**pointer to a function wrapping a binary operator
+\param op1 the left operand
+\param op2 the right operand
+\returns the result of the operation*/
+typedef QVariant (*ELAMBinaryOperatorCall)(const QVariant&op1,const QVariant&op2);
+
+/**pointer to a function wrapping a mathematical function
+\param args the list of arguments
+\returns the result of the function*/
+typedef QVariant (*ELAMFunction)(const QList<QVariant>&args);
+
+
+/**The calculation engine of ELAM.
+
+Instances of this class can be configured to represent a specific system of functions and operators.
+
+Methods of this class are used to evaluate expressions into final values.
+*/
class ELAMEngine:public QObject
{
Q_OBJECT
public:
+ ///instantiates an engine object
ELAMEngine(QObject*parent=0);
+
public slots:
+ ///simply parses an expression string into an ELAM object
ELAMExpression parseExpression(QString);
- ELAMValue evaluate(QString);
- ELAMValue evaluate(ELAMExpression);
+ ///parses and evaluates an expression string into a final value
+ QVariant evaluate(QString);
+ ///evaluates a parsed expression into a final value
+ QVariant evaluate(ELAMExpression);
+
+
private:
class Private;
Private *d;
#include "elamvalue.h"
-ELAMValue::ELAMValue()
+ELAMException::ELAMException()
{
- m_exc=false;
- m_exline=m_excol=-1;
+ mline=mcol=-1;
}
-
-ELAMValue::ELAMValue(long long l)
-{
- m_exc=false;
- m_exline=m_excol=-1;
- m_val=l;
-}
-
-ELAMValue::ELAMValue(double d)
-{
- m_exc=false;
- m_exline=m_excol=-1;
- m_val=d;
-}
-
-ELAMValue::ELAMValue(QString s)
+ELAMException::ELAMException(const ELAMException& e)
{
- m_exc=false;
- m_exline=m_excol=-1;
- m_val=s;
+ operator=(e);
}
-
-ELAMValue::ELAMValue(QVariant v)
+ELAMException::ELAMException(ErrorType tp,QString errText, int line, int column)
{
- m_exc=false;
- m_exline=m_excol=-1;
- //TODO: registered type?
- m_val=v;
+ mtype=tp;
+ merr=errText;
+ mline=line;
+ mcol=column;
}
-
-ELAMValue& ELAMValue::operator=(const ELAMValue&e)
+static int ELAMException_metaid=qRegisterMetaType<ELAMException>();
+int ELAMException::metaTypeId()
{
- m_exc=e.m_exc;
- m_exstr=e.m_exstr;
- m_exline=e.m_exline;
- m_excol=e.m_excol;
- m_val=e.m_val;
- return *this;
+ return ELAMException_metaid;
}
-
-ELAMValue& ELAMValue::operator=(long long v)
+ELAMException& ELAMException::operator=(const ELAMException& e)
{
- m_exc=false;m_excol=m_exline=-1;m_exstr=QString();
- m_val=v;
+ merr=e.merr;
+ mline=e.mline;
+ mcol=e.mcol;
return *this;
}
-ELAMValue& ELAMValue::operator=(int v)
-{
- m_exc=false;m_excol=m_exline=-1;m_exstr=QString();
- m_val=v;
- return *this;
-}
-
-ELAMValue& ELAMValue::operator=(const QString&v)
-{
- m_exc=false;m_excol=m_exline=-1;m_exstr=QString();
- m_val=v;
- return *this;
-}
-
-ELAMValue& ELAMValue::operator=(const QVariant&v)
-{
- m_exc=false;m_excol=m_exline=-1;m_exstr=QString();
- m_val=v;
- return *this;
-}
-
-
-void ELAMValue::setException(QString s,int l,int c)
-{
- m_exc=true;
- m_exline=l;m_excol=c;
- m_exstr=s;
-}
-
-QPair<int,int> ELAMValue::exceptionPos()const
+static int ELAMAnyType_metaid=qRegisterMetaType<ELAMAnyType>();
+int ELAMAnyType::metaTypeId()
{
- if(m_exc)
- return QPair<int,int>(m_exline,m_excol);
- else
- return QPair<int,int>(-1,-1);
+ return ELAMAnyType_metaid;
}
#include <QString>
#include <QPair>
-class ELAMValue
+/**Objects of this class represent an exception in the evaluation of an ELAM expression.*/
+class ELAMException
{
public:
- ELAMValue();
- ELAMValue(long long);
- ELAMValue(double);
- ELAMValue(QString);
- ELAMValue(QVariant);
- ELAMValue& operator=(const ELAMValue&);
- ELAMValue& operator=(long long);
- ELAMValue& operator=(int);
- ELAMValue& operator=(const QString&);
- ELAMValue& operator=(const QVariant&);
+ enum ErrorType{
+ NoError=0,
+ ParserError,
+ UnknownOperatorError,
+ UnknownFunctionError,
+ TypeMismatchError,
+ };
- bool isNull()const{return m_val.isNull();}
+ ELAMException();
+ ELAMException(const ELAMException&);
+ ELAMException(ErrorType type,QString errorText=QString(),int line=-1,int column=-1);
- void setException(QString,int,int);
+ ELAMException& operator=(const ELAMException&);
- bool hasException()const{return m_exc;}
- QString exceptionString()const{return m_exc?m_exstr:QString();}
- QPair<int,int> exceptionPos()const;
+ QString errorText()const{return merr;}
+ int errorLine()const{return mline;}
+ int errorColumn()const{return mcol;}
+ QPair<int,int> errorPos()const{return QPair<int,int>(mline,mcol);}
- QVariant toVariant()const{return m_val;}
- long long toInt()const{return m_val.toInt();}
- QString toString()const{return m_val.toString();}
+ static int metaTypeId();
private:
- QVariant m_val;
- bool m_exc;
- QString m_exstr;
- int m_exline,m_excol;
+ ErrorType mtype;
+ QString merr;
+ int mline,mcol;
};
+Q_DECLARE_METATYPE(ELAMException);
+
+/**this type is not actually used, its ID is used as a fallback to tell operators, functions and engines that any supported type can be used*/
+class ELAMAnyType
+{
+ public:
+ ///returns the meta type ID of the ANY type
+ static int metaTypeId();
+};
+Q_DECLARE_METATYPE(ELAMAnyType);
#endif