// evaluation routines
#include <mywin.h>
#pragma hdrstop
#include <math.h>
#include <stdio.h>
#include "eval.h"
enum {TERM=-2,NONE=-1,LOR,LAND,REL,EQU,ADDI,MULT,UOP};
enum {BRAK=-1,ADD,SUB,MUL,DIV,LE,LT,GE,GT,EQ,NE,SIN,COS,ATN,ACS,ASN,SQRT,AND,OR,UPL,UMN,MOD};
EvalParse::uOps EvalParse::UnaryOps[]=
{
{"cos",COS,UOP},
{"sin",SIN,UOP},
{"atan",ATN,UOP},
{"acos",ACS,UOP},
{"asin",ASN,UOP},
{"sqrt",SQRT,UOP},
{"+",UPL,UOP},
{"-",UMN,UOP},
{"(",BRAK,NONE},
};
EvalParse::bOps EvalParse::BinaryOps[]=
{
{"+",1,ADD,ADDI},
{"-",1,SUB,ADDI},
{"*",1,MUL,MULT},
{"/",1,DIV,MULT},
{"=",1,EQ,EQU},
{"<=",2,LE,REL}, // put before <
{"<>",2,NE,EQU}, // put before <
{"<",1,LT,REL},
{">=",2,GE,REL}, // put before >
{">",1,GT,REL},
{")",1,BRAK,NONE},
{",",1,BRAK,TERM},
{"and",3,AND,LAND},
{"or",2,OR,LOR},
{"mod",3,MOD,ADDI}
};
BOOL EvalParse::UnaryOp(int &Op,int &Prec)
{
for (int i=0;i<UOPS;i++)
if (stricmp(UnaryOps[i].Name,Com)==0)
{
Op=UnaryOps[i].op;
Prec=UnaryOps[i].Prec;
return TRUE;
}
return FALSE;
}
void EvalParse::BinaryOp(int &Op, int &Prec)
{
SkipSpace();
for (int i=0;i<BOPS;i++)
if (strnicmp(BinaryOps[i].Name,(char*)Ptr,BinaryOps[i].Len)==0)
{
Op=BinaryOps[i].op;
Prec=BinaryOps[i].Prec;
Ptr+=BinaryOps[i].Len;
return;
}
Prec=TERM;
if (c==';' || c<' ') Eol=TRUE;
}
double EvalParse::EvalTerm()
{
double d=0;
if (!ID::EvalDouble(Com,d))
{
int i;
if (ID::EvalInt(Com,i))
d=i;
else if (sscanf(Com,"%lf",&d)!=1) Error=ERR_UNKNOWNID;
}
return d;
}
double EvalParse::Evaluate()
{
int RightOp=NONE,RightPrec=NONE;
double RightTerm=0;
SubEval(RightOp,RightPrec,RightTerm);
return RightTerm;
}
void EvalParse::SubEval(int &LeftOp,int &LeftPrec,double &LeftTerm)
{
int RightOp,RightPrec;
double RightTerm=0;
GetCom(); // get term to delimiter
PutBackC(); // put back delimiter
if (Com.Empty() && strchr("+-(",c)) Com+=GetC();
if (UnaryOp(RightOp,RightPrec))
{
SubEval(RightOp,RightPrec,RightTerm);
if (RightPrec==NONE) BinaryOp(RightOp,RightPrec); // close brak
}
else
{
RightTerm=EvalTerm();
BinaryOp(RightOp,RightPrec);
}
while (LeftPrec<RightPrec) SubEval(RightOp,RightPrec,RightTerm);
switch (LeftOp)
{
case ADD:LeftTerm+=RightTerm;break;
case SUB:LeftTerm-=RightTerm;break;
case MUL:LeftTerm*=RightTerm;break;
case DIV:LeftTerm/=RightTerm;break;
case SIN:LeftTerm=sin(RightTerm);break; //takes radians
case COS:LeftTerm=cos(RightTerm);break;
case ATN:LeftTerm=atan(RightTerm);break; //returns radians
case ACS:LeftTerm=acos(RightTerm);break;
case ASN:LeftTerm=asin(RightTerm);break;
case SQRT:LeftTerm=sqrt(RightTerm);break;
case LE:LeftTerm=(LeftTerm<=RightTerm);break;
case LT:LeftTerm=(LeftTerm<RightTerm);break;
case EQ:LeftTerm=(LeftTerm==RightTerm);break;
case NE:LeftTerm=(LeftTerm!=RightTerm);break;
case GT:LeftTerm=(LeftTerm>RightTerm);break;
case GE:LeftTerm=(LeftTerm>=RightTerm);break;
case AND:LeftTerm=((int) LeftTerm & (int) RightTerm);break;
case OR :LeftTerm=((int) LeftTerm | (int) RightTerm);break;
case UPL:LeftTerm=RightTerm;break;
case UMN:LeftTerm=-RightTerm;break;
case MOD:LeftTerm=((int) LeftTerm % (int) RightTerm);break;
default:
LeftTerm=RightTerm;
}
LeftOp=RightOp;
LeftPrec=RightPrec;
}
int EvalParse::GetInt()
{
Error=ERR_NONE;
return (int) Evaluate();
}
double EvalParse::GetDouble()
{
Error=ERR_NONE;
return Evaluate();
}
// evaluation routines
#include <mywin.h>
#pragma hdrstop
#include <math.h>
#include <stdio.h>
#include "eval.h"
enum {TERM=-2,NONE=-1,LOR,LAND,REL,EQU,ADDI,MULT,UOP};
enum {BRAK=-1,ADD,SUB,MUL,DIV,LE,LT,GE,GT,EQ,NE,SIN,COS,ATN,ACS,ASN,SQRT,AND,OR,UPL,UMN,MOD};
EvalParse::uOps EvalParse::UnaryOps[]=
{
{"cos",COS,UOP},
{"sin",SIN,UOP},
{"atan",ATN,UOP},
{"acos",ACS,UOP},
{"asin",ASN,UOP},
{"sqrt",SQRT,UOP},
{"+",UPL,UOP},
{"-",UMN,UOP},
{"(",BRAK,NONE},
};
EvalParse::bOps EvalParse::BinaryOps[]=
{
{"+",1,ADD,ADDI},
{"-",1,SUB,ADDI},
{"*",1,MUL,MULT},
{"/",1,DIV,MULT},
{"=",1,EQ,EQU},
{"<=",2,LE,REL}, // put before <
{"<>",2,NE,EQU}, // put before <
{"<",1,LT,REL},
{">=",2,GE,REL}, // put before >
{">",1,GT,REL},
{")",1,BRAK,NONE},
{",",1,BRAK,TERM},
{"and",3,AND,LAND},
{"or",2,OR,LOR},
{"mod",3,MOD,ADDI}
};
BOOL EvalParse::UnaryOp(int &Op,int &Prec)
{
for (int i=0;i<UOPS;i++)
if (stricmp(UnaryOps[i].Name,Com)==0)
{
Op=UnaryOps[i].op;
Prec=UnaryOps[i].Prec;
return TRUE;
}
return FALSE;
}
void EvalParse::BinaryOp(int &Op, int &Prec)
{
SkipSpace();
for (int i=0;i<BOPS;i++)
if (strnicmp(BinaryOps[i].Name,(char*)Ptr,BinaryOps[i].Len)==0)
{
Op=BinaryOps[i].op;
Prec=BinaryOps[i].Prec;
Ptr+=BinaryOps[i].Len;
return;
}
Prec=TERM;
if (c==';' || c<' ') Eol=TRUE;
}
double EvalParse::EvalTerm()
{
double d=0;
if (!ID::EvalDouble(Com,d))
{
int i;
if (ID::EvalInt(Com,i))
d=i;
else if (sscanf(Com,"%lf",&d)!=1) Error=ERR_UNKNOWNID;
}
return d;
}
double EvalParse::Evaluate()
{
int RightOp=NONE,RightPrec=NONE;
double RightTerm=0;
SubEval(RightOp,RightPrec,RightTerm);
return RightTerm;
}
void EvalParse::SubEval(int &LeftOp,int &LeftPrec,double &LeftTerm)
{
int RightOp,RightPrec;
double RightTerm=0;
GetCom(); // get term to delimiter
PutBackC(); // put back delimiter
if (Com.Empty() && strchr("+-(",c)) Com+=GetC();
if (UnaryOp(RightOp,RightPrec))
{
SubEval(RightOp,RightPrec,RightTerm);
if (RightPrec==NONE) BinaryOp(RightOp,RightPrec); // close brak
}
else
{
RightTerm=EvalTerm();
BinaryOp(RightOp,RightPrec);
}
while (LeftPrec<RightPrec) SubEval(RightOp,RightPrec,RightTerm);
switch (LeftOp)
{
case ADD:LeftTerm+=RightTerm;break;
case SUB:LeftTerm-=RightTerm;break;
case MUL:LeftTerm*=RightTerm;break;
case DIV:LeftTerm/=RightTerm;break;
case SIN:LeftTerm=sin(RightTerm);break; //takes radians
case COS:LeftTerm=cos(RightTerm);break;
case ATN:LeftTerm=atan(RightTerm);break; //returns radians
case ACS:LeftTerm=acos(RightTerm);break;
case ASN:LeftTerm=asin(RightTerm);break;
case SQRT:LeftTerm=sqrt(RightTerm);break;
case LE:LeftTerm=(LeftTerm<=RightTerm);break;
case LT:LeftTerm=(LeftTerm<RightTerm);break;
case EQ:LeftTerm=(LeftTerm==RightTerm);break;
case NE:LeftTerm=(LeftTerm!=RightTerm);break;
case GT:LeftTerm=(LeftTerm>RightTerm);break;
case GE:LeftTerm=(LeftTerm>=RightTerm);break;
case AND:LeftTerm=((int) LeftTerm & (int) RightTerm);break;
case OR :LeftTerm=((int) LeftTerm | (int) RightTerm);break;
case UPL:LeftTerm=RightTerm;break;
case UMN:LeftTerm=-RightTerm;break;
case MOD:LeftTerm=((int) LeftTerm % (int) RightTerm);break;
default:
LeftTerm=RightTerm;
}
LeftOp=RightOp;
LeftPrec=RightPrec;
}
int EvalParse::GetInt()
{
Error=ERR_NONE;
return (int) Evaluate();
}
double EvalParse::GetDouble()
{
Error=ERR_NONE;
return Evaluate();
}