--- /dev/null
+TODO for ELAM
+================
+
+
+Engine
+---------
+
+* Expression ordering and execution
+* function overloading
+
+Default Library
+------------------
+
+int: abs(...)
+
+float: abs, round, comparison operators
+
+bool
+
+string
<h2>Calling It</h2>
+<h2>Default Libray</h2>
+
+The default library defines functions and operators for integers, floats, booleans and strings. It uses exactly the operator precedence used in the <a href="syntax.html#oper_prece">Syntax</a> documentation.<p/>
+
+The type "any" is used below to denote any type that is supported by the current engine. Constraints are noted in the description. The following types are used in the default library:<br/>
+<table frame="1" border="1">
+<tr><td><b>ELAM type</b></td><td><b>QVariant</b></td><td><b>Description</b></td></tr>
+
+<tr><td>any</td><td>ELAM::AnyType</td><td>cannot be used directly, but tells the engine that any type is allowed</td></tr>
+
+<tr><td>exception</td><td>ELAM::Exception</td><td>thrown when something goes wrong (parser errors, syntactic errors, operational/conversion errors</td></tr>
+
+<tr><td>int</td><td>qlonglong</td><td>integer mathematics</td></tr>
+<tr><td>float</td><td>qreal/double</td><td>floating point mathematics</td></tr>
+<tr><td>bool</td><td>bool</td><td>boolean mathematics and logic</td></tr>
+<tr><td>string</td><td>QString</td><td>character strings</td></tr>
+</table><p/>
+
+Optional arguments are marked with [ and ].
+
+<h3>Integer Library</h3>
+
+The integer library defines some very basic integer functionality:
+<table frame="1" border="1">
+<tr><td><b>Function</b></td><td><b>Description</b></td></tr>
+<tr><td>int(any)</td><td>tries to convert the argument to integer</td><tr>
+<tr><td>int + int</td><td>adds two integers</td></tr>
+<tr><td>int - int</td><td>subtracts two integers</td></tr>
+<tr><td>int * int</td><td>multiplies two integers</td></tr>
+<tr><td>int / int</td><td>divides two integers</td></tr>
+<tr><td>int % int</td><td>calculates the modulo of two integers</td></tr>
+<tr><td>int & int</td><td>calculates the bitwis AND of two integers</td></tr>
+<tr><td>int | int</td><td>calculates the bitwis OR of two integers</td></tr>
+<tr><td>int ^ int</td><td>calculates the bitwis XOR of two integers</td></tr>
+<tr><td>+ int</td><td>returns the value as is</td></tr>
+<tr><td>- int</td><td>returns the integer negative of the number</td></tr>
+<tr><td>~ int</td><td>returns the bitwise negative of the integers</td></tr>
+</table>
+
+<h3>Floating Point Library</h3>
+
+The floating point library defines some very basic floating point functionality:
+<table frame="1" border="1">
+<tr><td><b>Function</b></td><td><b>Description</b></td></tr>
+<tr><td>float(any)</td><td>tries to convert the argument to floating point</td><tr>
+<tr><td>float + float</td><td>adds two floating points</td></tr>
+<tr><td>float - float</td><td>subtracts two floating points</td></tr>
+<tr><td>float * float</td><td>multiplies two floating points</td></tr>
+<tr><td>float / float</td><td>divides two floating points</td></tr>
+<tr><td>+ float</td><td>returns the value as is</td></tr>
+<tr><td>- float</td><td>returns the floating point negative of the number</td></tr>
+</table>
+
<h2>Basic Types, Operators, Functions and Variables</h2>
-<h1>Extending The ElAM Libray</h1>
+<h1>Extending The ELAM Libray</h1>
<h2>Redirecting Variables and Constants</h2>
<html>
-<title>ELAM</title>
+<title>ELAM Syntax</title>
<body>
<h1>The ELAM Syntax</h1>
The equals sign ("=") has a special meaning when used in operators. In the normal mode the direct assignment operator "=" cannot be overloaded with a user specific function. If an operator ends in "=" and there is no overloaded operator, then the remainder is interpreted as a binary operator and the result assigned to the left side of the operator, for example "a+=b" is interpreted as a short form of "a=a+b".
+<a name="oper_prece"/>
<h3>Operator Precedence</h3>
Operators are interpreted in a specific order of precedence. First the highest precedence operators are evaluated, then the next lower precedence level, etc. with assignments being executed last. Consecutive operations with the same precedence level are executed from left to right.<p>
<table frame="1" border="1">
<tr><td><b>Operator Class</b><td><b>Operators</b><td><b>Precedence Value</b></tr>
<tr><td>Parentheses<td>(parentheses), functions(...)<td>1000</tr>
-<tr><td>All Unary Operators<td> ++, --, ~, !, -, +<td>100</tr>
+<tr><td>All Unary Operators<td> ~, !, -, +<td>100</tr>
<tr><td>Maximum usable Precedence<td> <td>99</tr>
<tr><td>Multiplicative<td> *, /, %<td>90</tr>
<tr><td>Additive<td> +, -<td>80</tr>
<tr><td>bitwise XOR<td> ^<td>45</tr>
<tr><td>bitwise OR<td> |<td>40</tr>
<tr><td>logical AND<td> &&<td>30</tr>
-<tr><td>logical OR<td>||<td>25</tr>
+<tr><td>logical XOR<td>^^<td>25</tr>
+<tr><td>logical OR<td>||<td>20</tr>
<tr><td>Lowest usable Precedence<td> <td>1</tr>
<tr><td>assignments<td>=, +=, -=, ...<td>0</tr>
</table><p>
#include "elamengine.h"
#include "elamintengine.h"
#include "elamfloatengine.h"
+#include "elamboolengine.h"
/** \mainpage ELAM - Elementary Logic and Arithmetic Machine
elamexpression.h \
elamvalue.h \
elamintengine.h \
- elamfloatengine.h
+ elamfloatengine.h \
+ elamboolengine.h
SOURCES += \
elamvalue.cpp \
elamengine.cpp \
elamintengine.cpp \
elamexpression.cpp \
- elamfloatengine.cpp
+ elamfloatengine.cpp \
+ elamboolengine.cpp
INCLUDEPATH += .
DEPENDPATH += .
--- /dev/null
+// ELAM int engine definition implementation
+//
+// (c) Konrad Rosenbaum, 2010
+// protected under the GNU LGPL v3 or at your option any newer
+
+#include "elamboolengine.h"
+
+#include<QDebug>
+
+using namespace ELAM;
+
+BoolEngine::BoolEngine()
+{
+ configureBoolEngine(*this);
+ configureLogicEngine(*this);
+}
+
+
+static QVariant boolFunc(const QList<QVariant>&lf)
+{
+ if(lf.size()!=1)
+ return Exception(Exception::ArgumentListError, "expecting exactly one argument");
+ if(!lf[0].canConvert<bool>())
+ return Exception(Exception::TypeMismatchError,"cannot convert to bool");
+ return lf[0].toBool();
+}
+
+//unary
+static QVariant boolNot(const QVariant&o)
+{
+ return !o.toBool();
+}
+
+//bitwise
+static QVariant boolAnd(const QVariant&o1,const QVariant&o2)
+{
+ return o1.toBool()&&o2.toBool();
+}
+static QVariant boolOr(const QVariant&o1,const QVariant&o2)
+{
+ return o1.toBool()||o2.toBool();
+}
+static QVariant boolXor(const QVariant&o1,const QVariant&o2)
+{
+ return o1.toBool()^o2.toBool();
+}
+
+
+void BoolEngine::configureBoolEngine(Engine&eng)
+{
+ int iid=QVariant::LongLong;
+ int bid=QVariant::Bool;
+ //cast
+ eng.setFunction("bool",boolFunc);
+ //constants
+ eng.setConstant("null",QVariant());
+ eng.setConstant("true",true);
+ eng.setConstant("false",false);
+ //unaries
+ eng.unaryOperator("!").setCallback(boolNot,iid);
+ eng.unaryOperator("!").setCallback(boolNot,bid);
+ eng.unaryOperator("~").setCallback(boolNot,bid);
+ //binaries adapted
+ eng.binaryOperator("&",50).setCallback(boolAnd,iid,bid);
+ eng.binaryOperator("&",50).setCallback(boolAnd,bid,iid);
+ eng.binaryOperator("&",50).setCallback(boolAnd,bid,bid);
+ eng.binaryOperator("|",40).setCallback(boolOr,bid,iid);
+ eng.binaryOperator("|",40).setCallback(boolOr,iid,bid);
+ eng.binaryOperator("|",40).setCallback(boolOr,bid,bid);
+ eng.binaryOperator("^",45).setCallback(boolXor,bid,iid);
+ eng.binaryOperator("^",45).setCallback(boolXor,iid,bid);
+ eng.binaryOperator("^",45).setCallback(boolXor,bid,bid);
+ //booleans
+ eng.binaryOperator("&&",30).setCallback(boolAnd,iid,iid);
+ eng.binaryOperator("&&",30).setCallback(boolAnd,iid,bid);
+ eng.binaryOperator("&&",30).setCallback(boolAnd,bid,iid);
+ eng.binaryOperator("&&",30).setCallback(boolAnd,bid,bid);
+ eng.binaryOperator("||",20).setCallback(boolOr,iid,iid);
+ eng.binaryOperator("||",20).setCallback(boolOr,bid,iid);
+ eng.binaryOperator("||",20).setCallback(boolOr,iid,bid);
+ eng.binaryOperator("||",20).setCallback(boolOr,bid,bid);
+ eng.binaryOperator("^^",25).setCallback(boolXor,iid,iid);
+ eng.binaryOperator("^^",25).setCallback(boolXor,bid,iid);
+ eng.binaryOperator("^^",25).setCallback(boolXor,iid,bid);
+ eng.binaryOperator("^^",25).setCallback(boolXor,bid,bid);
+}
+
+static QVariant ifFunc(const QList<QVariant>&lf)
+{
+ if(lf.size()<2 || lf.size()>3)
+ return Exception(Exception::ArgumentListError, "expecting 2 or 3 arguments");
+ if(!lf[0].canConvert<bool>())
+ return Exception(Exception::TypeMismatchError,"cannot convert argument 1 to bool");
+ if(lf[0].toBool())
+ return lf[1];
+ else
+ if(lf.size()>2)return lf[2];
+ return QVariant();
+}
+
+static QVariant isNullFunc(const QList<QVariant>&lf)
+{
+ if(lf.size()!=1)
+ return Exception(Exception::ArgumentListError, "expecting exactly one argument");
+ return lf[0].isNull();
+}
+
+static QVariant isExceptionFunc(const QList<QVariant>&lf)
+{
+ if(lf.size()!=1)
+ return Exception(Exception::ArgumentListError, "expecting exactly one argument");
+ return lf[0].type()==Exception::metaTypeId();
+}
+
+static QVariant isExceptionOrNullFunc(const QList<QVariant>&lf)
+{
+ if(lf.size()!=1)
+ return Exception(Exception::ArgumentListError, "expecting exactly one argument");
+ return lf[0].isNull() || lf[0].type()==Exception::metaTypeId();
+}
+
+static QVariant catchFunc(const QList<QVariant>&lf)
+{
+ if(lf.size()<1||lf.size()>3)
+ return Exception(Exception::ArgumentListError, "expecting 1-3 arguments");
+ if(lf[0].type()==Exception::metaTypeId()){
+ if(lf.size()>1)return lf[1];
+ else return true;
+ }else{
+ if(lf.size()>2)return lf[2];
+ else return false;
+ }
+}
+
+
+void BoolEngine::configureLogicEngine(Engine& eng)
+{
+ eng.setFunction("if",ifFunc);
+ eng.setFunction("isNull",isNullFunc);
+ eng.setFunction("isException",isExceptionFunc);
+ eng.setFunction("isExceptionOrNull",isExceptionOrNullFunc);
+ eng.setFunction("catch",catchFunc);
+}
--- /dev/null
+//ELAM integer engine header
+//
+// (c) Konrad Rosenbaum, 2010
+// protected under the GNU LGPL v3 or at your option any newer
+
+#ifndef ELAM_BOOLENGINE_H
+#define ELAM_BOOLENGINE_H
+
+#include "elamengine.h"
+
+namespace ELAM {
+
+/**A boolean and logic math enabled engine.
+
+This engine type plays nicely with ELAM::IntEngine
+*/
+class BoolEngine:public Engine
+{
+ public:
+ ///instantiates a pre-configured engine
+ BoolEngine();
+
+ ///configures any engine to support basic boolean math
+ static void configureBoolEngine(Engine&);
+
+ ///configures any engine to support logic functions
+ static void configureLogicEngine(Engine&);
+};
+
+};
+
+#endif
#include "elamexpression.h"
#include <QDebug>
+#include <QPointer>
+#include "elamengine.h"
namespace ELAM {
///////////////////////////////////////////////////////////////////////////////
// Token
-class DPTR_CLASS_NAME(Token):public DPtr
+class DPTR_CLASS_NAME(Token):public SharedDPtr
{
public:
+ DPTR_NAME(){type=Invalid;subtype=None;}
QString cont;
Type type;
+ SubType subtype;
QVariant val;
Position pos;
+ QList<Token>subtok;
};
-DEFINE_DPTR(Token)
+DEFINE_SHARED_DPTR(Token)
Token::Token(Position pos)
QVariant Token::literalValue()const{return d->val;}
Position Token::position()const{return d->pos;}
-QDebug&operator<<(QDebug&dbg,const Token&tok)
+QList< Token > Token::subTokens() const{return d->subtok;}
+Token::SubType Token::subType() const{return d->subtype;}
+void Token::setSubType(Token::SubType s){d->subtype=s;}
+void Token::addSubToken(const ELAM::Token& t)
+{
+ d->subtok<<t;
+}
+void Token::setSubTokens(const QList< Token >& t)
+{
+ d->subtok=t;
+}
+
+static void printspaces(QDebug&dbg,int level)
+{
+ for(int i=0;i<level;i++)dbg<<" ";
+}
+
+static void printtoken(QDebug&dbg,const Token&tok,int level);
+static void printtokenlist(QDebug&dbg,const QList<Token>&tok,int llevel,int tlevel)
+{
+ printspaces(dbg,llevel);
+ dbg<<"TokenList(";
+ for(int i=0;i<tok.size();i++){
+ dbg<<"\n";
+ printtoken(dbg,tok[i],tlevel+1);
+ }
+ dbg<<")";
+}
+static void printtoken(QDebug&dbg,const Token&tok,int level)
{
- dbg.nospace()<<"Token(str="<<tok.content()<<",type=";
+ printspaces(dbg,level);
+ dbg<<"Token(str="<<tok.content()<<",type=";
switch(tok.type()){
case Token::Invalid:dbg<<"Invalid";break;
case Token::Name:dbg<<"Name";break;
case Token::ParClose:dbg<<"ClosingParenthesis";break;
case Token::ParOpen:dbg<<"OpeningParenthesis";break;
case Token::Comma:dbg<<"Comma";break;
- case Token::Literal:dbg<<"LiteralValue"<<",value="<<tok.literalValue();break;
+ case Token::Literal:dbg<<"LiteralValue,value="<<tok.literalValue();break;
case Token::Whitespace:dbg<<"WhiteSpace";break;
+ case Token::Parentheses:dbg<<"Parentheses";break;
}
- dbg<<",pos="<<tok.position()<<")";
+ if(tok.subType()!=Token::None){
+ dbg<<",subtype=";
+ switch(tok.subType()){
+ case Token::Function:dbg<<"Function";break;
+ case Token::Constant:dbg<<"Constant";break;
+ case Token::Variable:dbg<<"Variable";break;
+ case Token::UnaryOp:dbg<<"Unary";break;
+ case Token::BinaryOp:dbg<<"Binary";break;
+ default:break;
+ }
+ }
+ dbg<<",pos="<<tok.position();
+ QList<Token> sub=tok.subTokens();
+ if(sub.size()>0){
+ dbg<<",sub-tokens:";
+ printtokenlist(dbg,sub,0,level);
+ }
+ dbg<<")";
+}
+QDebug&operator<<(QDebug&dbg,const Token&tok)
+{
+ dbg.nospace();
+ printtoken(dbg,tok,0);
return dbg.space();
}
+QDebug&operator<<(QDebug&dbg,const QList<Token>&tok)
+{
+ dbg.nospace();
+ printtokenlist(dbg,tok,0,0);
+ return dbg.space();
+}
+///////////////////////////////////////////////////////////////////////////////
+// TokenBundle
+
+class TokenBundle
+{
+ public:
+ TokenBundle(const Token&);
+ TokenBundle(const TokenBundle&);
+ TokenBundle(const QList<Token>&);
+ private:
+ QList<TokenBundle>&mtoks;
+};
+
///////////////////////////////////////////////////////////////////////////////
// Expression
class DPTR_CLASS_NAME(Expression):public SharedDPtr
{
+ public:
+ DPTR_NAME(){type=Exception;}
+ QPointer<Engine>parent;
+ QList<Token>tokens;
+ Type type;
+ QVariant value;
};
DEFINE_SHARED_DPTR(Expression);
{
}
-Expression::Expression(Engine* parent, const QList< Token >& tokens)
+
+//reduce surrounding parentheses and whitespace
+static inline QList<Token>simplifyTokens(Engine*eng,QList<Token> toks)
{
+ Q_UNUSED(eng);
+ QList<Token>ret;
+ int min=0,max=toks.size()-1;
+ //eliminate redundant parentheses
+ while(toks[min].type()==Token::ParOpen && toks[max].type()==Token::ParClose){
+ min++;max--;
+ }
+ //reduce whitespace
+ for(int i=min;i<=max;i++){
+ //eliminate whitespace
+ if(toks[i].type()==Token::Whitespace)
+ continue;
+ ret<<toks[i];
+ }
+ return ret;
+}
+//reduce surrounding parentheses and whitespace
+static inline QList<Token>classifyTokens(Engine*eng,QList<Token> toks)
+{
+ QList<Token>ret;
+ if(toks.size()<1)return toks;
+ //check token 0
+ Token t=toks[0];
+ if(t.type()==Token::Name){
+ if(eng->hasFunction(t.content()))t.setSubType(Token::Function);else
+ if(eng->hasConstant(t.content()))t.setSubType(Token::Constant);
+ else t.setSubType(Token::Variable);
+ }else if(t.type()==Token::Operator)t.setSubType(Token::UnaryOp);
+ ret<<t;
+ //check remaining tokens
+ for(int i=1;i<toks.size();i++){
+ t=toks[i];
+ //define names
+ if(t.type()==Token::Name){
+ if(eng->hasFunction(t.content()))t.setSubType(Token::Function);else
+ if(eng->hasConstant(t.content()))t.setSubType(Token::Constant);
+ else t.setSubType(Token::Variable);
+ }else
+ //define operators
+ if(t.type()==Token::Operator){
+ switch(toks[i-1].type()){
+ case Token::ParOpen:
+ case Token::Operator:
+ t.setSubType(Token::UnaryOp);
+ break;
+ default:
+ t.setSubType(Token::BinaryOp);
+ break;
+ }
+ }
+ //add
+ ret<<t;
+ }
+ return ret;
+}
+//reduce surrounding parentheses and whitespace
+static inline QList<Token>reduceTokens(Engine*eng,QList<Token> toks)
+{
+ toks=classifyTokens(eng,simplifyTokens(eng,toks));
+ QList<Token>ret,sub;
+ //copy and create hierarchy
+ int pcnt=0;
+ for(int i=0;i<toks.size();i++){
+ //count parentheses
+ if(toks[i].type()==Token::ParOpen){
+ if(!pcnt){
+ if(i==0 || toks.value(i-1).subType()!=Token::Function)
+ ret<<Token("",Token::Parentheses,toks[i].position());
+ sub.clear();
+ }
+ pcnt++;
+ continue;
+ }else
+ if(toks[i].type()==Token::ParClose){
+ pcnt--;
+ if(!pcnt){
+ ret[ret.size()-1].setSubTokens(sub);
+ sub.clear();
+ }
+ continue;
+ }
+ //collect tokens
+ if(pcnt)
+ sub<<toks[i];
+ else
+ ret<<toks[i];
+ }
+ return ret;
+}
+//scan for simple errors, return exception (NoError if no error found)
+static inline Exception scanForError(const QList< Token >& toks)
+{
+ //check for invalid tokens
+ for(int i=0;i<toks.size();i++)
+ if(toks[i].type()==Token::Invalid){
+ return Exception(Exception::ParserError, "invalid token", toks[i].position());
+ }
+ //scan for parentheses mismatch
+ int pcnt=0;
+ for(int i=0;i<toks.size();i++){
+ //check parentheses
+ if(toks[i].type()==Token::ParOpen)pcnt++;else
+ if(toks[i].type()==Token::ParClose)pcnt--;
+ if(pcnt<0){
+ return Exception(Exception::ParserError, "parentheses mismatch", toks[i].position());
+ }
+ }
+ if(pcnt!=0){
+ return Exception(Exception::ParserError, "parentheses mismatch", toks[0].position());
+ }
+ //nothing found
+ return Exception(Exception::NoError);
+}
+
+Expression::Expression(Engine* parent, const QList< Token >& toks)
+{
+ //check for simple errors
+ ELAM::Exception ex=scanForError(toks);
+ if(ex.errorType()!=ELAM::Exception::NoError){
+ d->type=Exception;
+ d->value=ex;
+ d->tokens=toks;
+ return;
+ }
+ d->parent=parent;
+ d->tokens=reduceTokens(parent,toks);
+ qDebug()<<"expression:"<<d->tokens;
+ //check for nothing and complain
+ if(d->tokens.size()==0){
+ d->type=Exception;
+ d->value=ELAM::Exception(ELAM::Exception::ParserError,"no tokens", (toks.size()>0?toks[0].position():Position()));
+ return;
+ }
+ //check for simplicity (literals, vars, consts)
+ if(d->tokens.size()==1){
+ switch(d->tokens[0].type()){
+ case Token::Name:
+ if(parent->hasFunction(d->tokens[0].content())){
+ d->type=Exception;
+ d->value=ELAM::Exception(ELAM::Exception::ParserError, "function call incomplete", d->tokens[0].position());
+ }else if(parent->hasConstant(d->tokens[0].content())){
+ d->type=Constant;
+ d->value=parent->getConstant(d->tokens[0].content());
+ }else{
+ d->type=Variable;
+ }
+ break;
+ case Token::Literal:
+ d->type=Literal;
+ d->value=d->tokens[0].literalValue();
+ break;
+ default:
+ d->type=Exception;
+ d->value=ELAM::Exception(ELAM::Exception::ParserError, "unexpected token", d->tokens[0].position());
+ break;
+ }
+ return;
+ }
}
QVariant Expression::evaluate()
Tokens are pretty stupid themselves - they just know their type, position, their original piece of text and an optional value (literals). They are used by the engine and expressions to transform text into executable expressions.*/
class Token
{
- DECLARE_DPTR(d)
+ DECLARE_SHARED_DPTR(d)
public:
///The type of token
enum Type {
///invalid token
- Invalid,
+ Invalid=0,
///a name: function, variable, or constant
- Name,
+ Name=7,
///an operator (unary or binary)
- Operator,
+ Operator=24,
+ ///meta-type used for parsed sub-tokens
+ Parentheses=96,
///opening parenthese
- ParOpen,
+ ParOpen=32,
///closing parenthese
- ParClose,
+ ParClose=64,
///a comma - separating expressions in function calls
- Comma,
+ Comma=128,
///a literal value
- Literal,
+ Literal=256,
///white space chars, this is actually not used for tokens, but for parsing
- Whitespace,
+ Whitespace=512,
+ };
+ enum SubType{
+ None = 0,
+ Function = 1,
+ Constant = 2,
+ Variable = 4,
+ UnaryOp = 8,
+ BinaryOp = 16,
};
///creates an empty/invalid token
Token(Position pos=Position(-1,-1));
QVariant literalValue()const;
///returns the original position of the token
Position position()const;
+ SubType subType()const;
+ void setSubType(SubType);
+ QList<Token>subTokens()const;
+ void addSubToken(const Token&);
+ void setSubTokens(const QList<Token>&);
};
QDebug& operator<<(QDebug&,const Token&);
DECLARE_SHARED_DPTR(d)
public:
enum Type {
- Literal,
- Variable,
- Constant,
- Function,
- Parentheses,
- UnaryOp,
- BinaryOp,
- Exception,
+ Literal=Token::Literal,
+ Variable=Token::Variable,
+ Constant=Token::Constant,
+ Function=Token::Function,
+ Parentheses=96,
+ UnaryOp=Token::UnaryOp,
+ BinaryOp=Token::BinaryOp,
+ Exception=0x8000,
};
Expression();
Expression(Engine*parent,const QList<Token>&tokens);
--- /dev/null
+#include "elam.h"
+
+#include "eval.h"
+
+#include <QtCore>
+#include <QtTest>
+#include <QDebug>
+
+using namespace ELAM;
+
+
+void ElamTest::evaltest()
+{
+ IntEngine ie;
+ FloatEngine::configureFloatEngine(ie);
+ QString ex="a= 345*(65.3/(5))";
+ QVariant v=ie.evaluate(ex);
+}
+
+
+QTEST_MAIN(ElamTest)
\ No newline at end of file
--- /dev/null
+#include <QObject>
+
+class ElamTest:public QObject
+{
+ Q_OBJECT
+ private slots:
+ void evaltest();
+};
--- /dev/null
+TEMPLATE = app
+TARGET = evaltest
+QT -= gui
+CONFIG += qtestlib debug link_prl
+INCLUDEPATH += . ../../src
+DEPENDPATH += $$INCLUDEPATH ../..
+LIBS += -L../.. -lelam
+
+SOURCES += eval.cpp
+HEADERS += eval.h
\ No newline at end of file