17. december 2004 - 00:26
#19
#include <iostream>
using namespace std;
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "sym.h"
#include "list.h"
#include "expr.h"
// stack size
const int STACKSIZE = 100;
// precedence
const int token_precedence[17] = { 0,0,
6,
2,2,3,3,3,4,
2,3,6,6,
5,
7,0,1 };
// string representation
const char token_string[17][8] = { "","",
"-",
"+","-","*","/","%","^",
" OR "," AND "," NOT ", " EQUAL ",
"",
"(",")","," };
// functions
const int NFUNC = 9;
const char func_string[NFUNC][16] = { "EXP","LOG","SQRT",
"COS","SIN","TAN",
"ACOS","ASIN","ATAN" };
void expr_error(char *s)
{
throw s;
}
//**********************************************************************
//
// Class ExprSymbolTable
//
//**********************************************************************
void ExprDel(void *p)
{
delete ((struct ExprSymbol *)p)->s;
return;
}
void ExprValDel(void *valp)
{
return;
}
ExprSymbolTable::ExprSymbolTable(int size):SymbolTable(size)
{
double z;
z = PI;
InsertSymbol("PI",&z);
z = EE;
InsertSymbol("E",&z);
}
ExprSymbolTable::~ExprSymbolTable()
{
DoForAll(ExprDel,ExprValDel);
}
#define _p ((struct ExprSymbol *)p)
UINT ExprSymbolTable::HashValue(void *p)
{
return (SymbolTable::StandardHashValue(_p->s));
}
int ExprSymbolTable::Length(void *p)
{
return sizeof(char *);
}
#define _p1 ((struct ExprSymbol *)p1)
#define _p2 ((struct ExprSymbol *)p2)
void ExprSymbolTable::Copy(void *p1,void *p2)
{
_p1->s = new char[strlen(_p2->s)+1];
strcpy(_p1->s,_p2->s);
return;
}
BOOL ExprSymbolTable::Compare(void *p1,void *p2)
{
return ((strcmp(_p1->s,_p2->s)==0));
}
int ExprSymbolTable::ValLength(void *valp)
{
return sizeof(struct ExprValue);
}
#define _valp1 ((struct ExprValue *)valp1)
#define _valp2 ((struct ExprValue *)valp2)
void ExprSymbolTable::ValCopy(void *valp1,void *valp2)
{
(*_valp1) = (*_valp2);
return;
}
void ExprSymbolTable::InsertSymbol(char *s,double *val)
{
struct ExprSymbol tmp1;
tmp1.s = s;
struct ExprValue tmp2;
tmp2.floatval = *val;
SymbolTable::InsertSymbol(&tmp1,&tmp2);
return;
}
void ExprSymbolTable::InsertSymbol(char *s,long int *val)
{
struct ExprSymbol tmp1;
tmp1.s = s;
struct ExprValue tmp2;
tmp2.intval = *val;
SymbolTable::InsertSymbol(&tmp1,&tmp2);
return;
}
void ExprSymbolTable::InsertSymbol(char *s,BOOL *val)
{
struct ExprSymbol tmp1;
tmp1.s = s;
struct ExprValue tmp2;
tmp2.boolval = *val;
SymbolTable::InsertSymbol(&tmp1,&tmp2);
return;
}
BOOL ExprSymbolTable::FindSymbol(char *s,double *val)
{
struct ExprSymbol tmp1;
tmp1.s = s;
struct ExprValue tmp2;
BOOL res = SymbolTable::FindSymbol(&tmp1,&tmp2);
*val = tmp2.floatval;
return res;
}
BOOL ExprSymbolTable::FindSymbol(char *s,long int *val)
{
struct ExprSymbol tmp1;
tmp1.s = s;
struct ExprValue tmp2;
BOOL res = SymbolTable::FindSymbol(&tmp1,&tmp2);
*val = tmp2.intval;
return res;
}
BOOL ExprSymbolTable::FindSymbol(char *s,BOOL *val)
{
struct ExprSymbol tmp1;
tmp1.s = s;
struct ExprValue tmp2;
BOOL res = SymbolTable::FindSymbol(&tmp1,&tmp2);
*val = tmp2.boolval;
return res;
}
class ExprSymbolTable *ExprVariables = NULL;
void ExprDefineVariable(char *name,double value)
{
if(ExprVariables==NULL) {
ExprVariables = new class ExprSymbolTable(1000);
}
ExprVariables->InsertSymbol(name,&value);
return;
}
void ExprDefineVariable(char *name,long int value)
{
if(ExprVariables==NULL) {
ExprVariables = new class ExprSymbolTable(1000);
}
ExprVariables->InsertSymbol(name,&value);
return;
}
void ExprDefineVariable(char *name,BOOL value)
{
if(ExprVariables==NULL) {
ExprVariables = new class ExprSymbolTable(1000);
}
ExprVariables->InsertSymbol(name,&value);
return;
}
void ExprClearSymbols()
{
delete ExprVariables;
ExprVariables = NULL;
return;
}
//**********************************************************************
//
// Class Expression
//
//**********************************************************************
typedef struct Token struct_Token;
// push token
void Expression::Push(enum token_type t,char *v)
{
struct Token *tmp = new struct_Token;
tmp->Typ = t;
tmp->Val = new char[strlen(v)+1];
strcpy(tmp->Val,v);
Tokens->Push(tmp);
return;
}
void Expression::Push(enum token_type t,double v)
{
char tmp[17];
sprintf(tmp,"%f",v);
if(strchr(tmp,'.')!=NULL) {
int ix = strlen(tmp) - 1;
while(tmp[ix]=='0') {
tmp[ix]='\0';
ix--;
}
if(tmp[ix]=='.') tmp[ix]='\0';
}
Push(t,tmp);
return;
}
void Expression::Push(enum token_type t,long int v)
{
char tmp[11];
sprintf(tmp,"%d",v);
Push(t,tmp);
return;
}
void Expression::Push(enum token_type t,BOOL v)
{
if(v)
Push(t,"TRUE");
else
Push(t,"FALSE");
return;
}
// pop token
void Expression::Pop(enum token_type *t,char *v)
{
struct Token *tmp = (struct Token *)Tokens->Pop();
if(t!=NULL) *t = tmp->Typ;
if(v!=NULL) strcpy(v,tmp->Val);
delete tmp->Val;
delete tmp;
return;
}
// save token
void Expression::SaveToken(char *tok)
{
char tmp[256];
strcpy(tmp,tok);
if(BoolConst) {
if(EQUAL(tmp,"T")||
EQUAL(tmp,"TRUE")||
EQUAL(tmp,"Y")||
EQUAL(tmp,"YES")) {
Push(CONSTANT,"TRUE");
} else if(EQUAL(tmp,"F")||
EQUAL(tmp,"FALSE")||
EQUAL(tmp,"N")||
EQUAL(tmp,"NO")) {
Push(CONSTANT,"FALSE");
} else {
if(strchr("0123456789",tmp[0])==NULL) {
Push(VARIABLE,tmp);
} else {
Push(CONSTANT,tmp);
}
}
} else {
for(int i=0;i<NFUNC;i++) {
if(EQUAL(tmp,func_string[i])) {
Push(FUNCTION,(char *)func_string[i]);
return;
}
}
if(strchr("0123456789",tmp[0])==NULL) {
Push(VARIABLE,tmp);
} else {
Push(CONSTANT,tmp);
}
}
return;
}
#define SAVEIFTMP if(tmplen>0) { \
tmp[tmplen] = '\0'; \
tmpp = tmp; \
if(EQUAL(tmpp,"OR")||EQUAL(tmpp,"UNION")) { \
Push(OR,""); \
} else if(EQUAL(tmpp,"AND")||EQUAL(tmpp,"INTERSECT")) { \
Push(AND,""); \
} else if(EQUAL(tmpp,"NOT")||EQUAL(tmpp,"MINUS")) { \
Push(NOT,""); \
} else if(EQUAL(tmpp,"EQUAL")) { \
Push(XEQUAL,""); \
} else { \
SaveToken(tmp); \
} \
tmplen = 0; \
}
// constructor
Expression::Expression(char *s,BOOL bc)
{
BoolConst = bc;
ConvPostFix = FALSE;
Tokens = new class Stack();
char *tmpp;
char tmp[256];
int tmplen = 0;
for(int i=0;i<strlen(s);i++) {
switch(s[i]) {
case ' ':
SAVEIFTMP;
break;
case ',':
SAVEIFTMP;
Push(COMMA,"");
break;
case '+':
SAVEIFTMP;
Push(PLUS,"");
break;
case '-':
if(i==0) {
Push(UNARYMINUS,"");
} else {
SAVEIFTMP;
if((GetTop()->Typ!=CONSTANT)&&
(GetTop()->Typ!=VARIABLE)&&
(GetTop()->Typ!=RIGHTBRACKET)) {
Push(UNARYMINUS,"");
} else {
Push(MINUS,"");
}
}
break;
case '*':
SAVEIFTMP;
Push(MULTIPLY,"");
break;
case '/':
SAVEIFTMP;
Push(DIVIDE,"");
break;
case '%':
SAVEIFTMP;
Push(REMAINDER,"");
break;
case '^':
SAVEIFTMP;
Push(POWER,"");
break;
case '(':
SAVEIFTMP;
Push(LEFTBRACKET,"");
break;
case ')':
SAVEIFTMP;
Push(RIGHTBRACKET,"");
break;
default:
tmp[tmplen] = s[i];
tmplen++;
break;
}
}
SAVEIFTMP;
Tokens->Turn();
}
Expression::Expression(const class Expression& e)
{
BoolConst = e.BoolConst;
ConvPostFix = e.ConvPostFix;
Tokens = new class Stack();
class Expression *e2 = (class Expression *)&e;
enum token_type tt;
char val[256];
while(e2->More()) {
e2->Pop(&tt,val);
Push(tt,val);
}
Tokens->Turn();
}
void Expression::operator=(const class Expression& e)
{
BoolConst = e.BoolConst;
ConvPostFix = e.ConvPostFix;
while(More()) Pop();
class Expression *e2 = (class Expression *)&e;
enum token_type tt;
char val[256];
while(e2->More()) {
e2->Pop(&tt,val);
Push(tt,val);
}
Tokens->Turn();
}
// desctructor
Expression::~Expression()
{
while(More()) Pop();
delete Tokens;
}
int expr_bufix = 0;
char expr_buf[2][256];
// get string
char *Expression::String()
{
expr_bufix = (expr_bufix+1)%2;
strcpy(expr_buf[expr_bufix],"");
struct Token *current;
for(int i=0;i<Tokens->GetNElm();i++) {
current = (struct Token *)((*Tokens)[i]);
switch(current->Typ) {
case CONSTANT:
case VARIABLE:
case FUNCTION:
strcat(expr_buf[expr_bufix],current->Val);
break;
case UNARYMINUS:
case PLUS:
case MINUS:
case MULTIPLY:
case DIVIDE:
case REMAINDER:
case POWER:
case OR:
case AND:
case NOT:
case XEQUAL:
case LEFTBRACKET:
case RIGHTBRACKET:
case COMMA:
strcat(expr_buf[expr_bufix],token_string[current->Typ]);
break;
}
}
return expr_buf[expr_bufix];
}
// convert from infix to postfix
class Expression infix2postfix(class Expression e)
{
if(e.ConvPostFix) expr_error(EM_EXPR_ACTP);
enum token_type tt,tt2;
char val[256],val2[256];
class Expression e2 = e;
class Expression result("",e.BoolConst);
class Expression work("",e.BoolConst);
while(e2.More()) {
e2.Pop(&tt,val);
switch(tt) {
case CONSTANT:
case VARIABLE:
result.Push(tt,val);
break;
case UNARYMINUS:
case PLUS:
case MINUS:
case MULTIPLY:
case DIVIDE:
case REMAINDER:
case POWER:
case OR:
case AND:
case NOT:
case XEQUAL:
case FUNCTION:
case LEFTBRACKET:
case COMMA:
while(work.More()?
((work.GetTop()->Typ!=LEFTBRACKET)&&
(token_precedence[work.GetTop()->Typ]>=token_precedence[tt])):
FALSE) {
work.Pop(&tt2,val2);
result.Push(tt2,val2);
}
work.Push(tt,val);
break;
case RIGHTBRACKET:
while(work.GetTop()->Typ!=LEFTBRACKET) {
work.Pop(&tt2,val2);
result.Push(tt2,val2);
}
work.Pop(&tt2,val2);
break;
}
}
while(work.More()) {
work.Pop(&tt2,val2);
result.Push(tt2,val2);
}
result.Tokens->Turn();
result.ConvPostFix = TRUE;
return result;
}
// convert from postfix to infix
class Expression postfix2infix(class Expression e)
{
if(!e.ConvPostFix) expr_error(EM_EXPR_NCTP);
enum token_type tt,tt2;
char val[256],val2[256];
BOOL flag;
class Expression e2 = e;
class Expression result("",e.BoolConst);
class Expression work("",e.BoolConst);
enum token_type lasttt = CONSTANT;
int n_leftbracket = 0;
e2.Tokens->Turn();
while(e2.More()) {
e2.Pop(&tt,val);
switch(tt) {
case CONSTANT:
case VARIABLE:
while(n_leftbracket>0) {
result.Push(RIGHTBRACKET,"");
n_leftbracket--;
}
result.Push(tt,val);
flag = TRUE;
while(work.More()&&flag) {
work.Pop(&tt2,val2);
result.Push(tt2,val2);
flag = (tt2==UNARYMINUS)||(tt2==NOT)||(tt2==FUNCTION)||
(tt2==LEFTBRACKET)||(tt2==RIGHTBRACKET);
lasttt = tt2;
}
break;
case UNARYMINUS:
case NOT:
if((e2.GetTop()->Typ==CONSTANT)||(e2.GetTop()->Typ==VARIABLE)||
(token_precedence[e2.GetTop()->Typ]>=token_precedence[FUNCTION])) {
work.Push(LEFTBRACKET,"");
n_leftbracket++;
}
work.Push(tt,val);
lasttt = tt;
break;
case PLUS:
case MINUS:
case MULTIPLY:
case DIVIDE:
case REMAINDER:
case POWER:
case OR:
case AND:
case XEQUAL:
case COMMA:
if((token_precedence[tt]<token_precedence[lasttt])||
((tt==MULTIPLY)&&(lasttt==DIVIDE))) {
work.Push(LEFTBRACKET,"");
n_leftbracket++;
}
work.Push(tt,val);
lasttt = tt;
break;
case FUNCTION:
work.Push(tt,val);
lasttt = tt;
if((e2.GetTop()->Typ==CONSTANT)||(e2.GetTop()->Typ==VARIABLE)||
(token_precedence[e2.GetTop()->Typ]>=token_precedence[FUNCTION])) {
work.Push(LEFTBRACKET,"");
n_leftbracket++;
}
break;
case LEFTBRACKET:
case RIGHTBRACKET:
expr_error(EM_GII);
break;
}
}
result.ConvPostFix = FALSE;
return result;
}
// append
void append(class Expression *e1,class Expression *e2)
{
e2->Tokens->Turn();
struct Token *current;
for(int i=0;i<e2->Tokens->GetNElm();i++) {
current = (struct Token *)((*e2->Tokens)[i]);
e1->Push(current->Typ,current->Val);
}
e2->Tokens->Turn();
return;
}
#define NEEDARG(n) \
if(stackptr<n) expr_error(EM_SE)
//**********************************************************************
//
// Class FloatExpression
//
//**********************************************************************
// simplify on top
BOOL FloatExpression::TopSimplify()
{
double v;
enum token_type tt;
char val[256];
struct Token *curr = (struct Token *)(*Tokens)[0];
struct Token *prev = (struct Token *)(*Tokens)[1];
struct Token *prev2 = (struct Token *)(*Tokens)[2];
struct Token *prev3 = (struct Token *)(*Tokens)[3];
if(prev3!=NULL) {
// C + C + => C +
// C - C + => C +
// C + C - => C -
// C - C - => C -
if((prev3->Typ==CONSTANT)&&
((prev2->Typ==PLUS)||(prev2->Typ==MINUS))&&
(prev->Typ==CONSTANT)&&
((curr->Typ==PLUS)||(curr->Typ==MINUS))) {
if(curr->Typ==prev2->Typ)
v = atof(prev->Val) + atof(prev3->Val);
else
v = atof(prev->Val) - atof(prev3->Val);
tt = curr->Typ;
Pop();
Pop();
Pop();
Pop();
Push(CONSTANT,v);
Push(tt,"");
return TRUE;
}
// C * C * => C *
// C / C * => C *
// C * C / => C /
// C / C / => C /
if((prev3->Typ==CONSTANT)&&
((prev2->Typ==MULTIPLY)||(prev2->Typ==DIVIDE))&&
(prev->Typ==CONSTANT)&&
((curr->Typ==MULTIPLY)||(curr->Typ==DIVIDE))) {
if(curr->Typ==prev2->Typ)
v = atof(prev->Val) * atof(prev3->Val);
else
v = atof(prev->Val) / atof(prev3->Val);
tt = curr->Typ;
Pop();
Pop();
Pop();
Pop();
Push(CONSTANT,v);
Push(tt,"");
return TRUE;
}
// C ^ C ^ => C ^
if((prev3->Typ==CONSTANT)&&
(prev2->Typ==POWER)&&
(prev->Typ==CONSTANT)&&
(curr->Typ==POWER)) {
v = atof(prev->Val) * atof(prev3->Val);
tt = curr->Typ;
Pop();
Pop();
Pop();
Pop();
Push(CONSTANT,v);
Push(tt,"");
return TRUE;
}
}
if(prev2!=NULL) {
// C C + => C
if((prev2->Typ==CONSTANT)&&
(prev->Typ==CONSTANT)&&
(curr->Typ==PLUS)) {
v = atof(prev2->Val) + atof(prev->Val);
Pop();
Pop();
Pop();
Push(CONSTANT,v);
return TRUE;
}
// C C - => C
if((prev2->Typ==CONSTANT)&&
(prev->Typ==CONSTANT)&&
(curr->Typ==MINUS)) {
v = atof(prev2->Val) - atof(prev->Val);
Pop();
Pop();
Pop();
Push(CONSTANT,v);
return TRUE;
}
// C C * => C
if((prev2->Typ==CONSTANT)&&
(prev->Typ==CONSTANT)&&
(curr->Typ==MULTIPLY)) {
v = atof(prev2->Val) * atof(prev->Val);
Pop();
Pop();
Pop();
Push(CONSTANT,v);
return TRUE;
}
// C C / => C
if((prev2->Typ==CONSTANT)&&
(prev->Typ==CONSTANT)&&
(curr->Typ==DIVIDE)) {
v = atof(prev2->Val) / atof(prev->Val);
Pop();
Pop();
Pop();
Push(CONSTANT,v);
return TRUE;
}
// C C % => C
if((prev2->Typ==CONSTANT)&&
(prev->Typ==CONSTANT)&&
(curr->Typ==REMAINDER)) {
v = fmod(atof(prev2->Val),atof(prev->Val));
Pop();
Pop();
Pop();
Push(CONSTANT,v);
return TRUE;
}
// C C ^ => C
if((prev2->Typ==CONSTANT)&&
(prev->Typ==CONSTANT)&&
(curr->Typ==POWER)) {
v = pow(atof(prev2->Val),atof(prev->Val));
Pop();
Pop();
Pop();
Push(CONSTANT,v);
return TRUE;
}
// 0 z + => z
// 0 z - => z
if((prev2->Typ==CONSTANT)&&
(atof(prev2->Val)==0)&&
((prev->Typ==CONSTANT)||(prev->Typ==VARIABLE))&&
((curr->Typ==PLUS)||curr->Typ==MINUS)) {
Pop();
Pop(&tt,val);
Pop();
Push(tt,val);
return TRUE;
}
// 0 z * => 0
// 0 z / => 0
// 0 z % => 0
if((prev2->Typ==CONSTANT)&&
(atof(prev2->Val)==0)&&
((prev->Typ==CONSTANT)||(prev->Typ==VARIABLE))&&
((curr->Typ==MULTIPLY)||(curr->Typ==DIVIDE)||(curr->Typ==REMAINDER))) {
Pop();
Pop();
Pop();
Push(CONSTANT,0.0);
return TRUE;
}
// 0 z ^ => 1
if((prev2->Typ==CONSTANT)&&
(atof(prev2->Val)==0)&&
((prev->Typ==CONSTANT)||(prev->Typ==VARIABLE))&&
(curr->Typ==POWER)) {
Pop();
Pop();
Pop();
Push(CONSTANT,1.0);
return TRUE;
}
// 1 z * => z
if((prev2->Typ==CONSTANT)&&
(atof(prev2->Val)==1)&&
((prev->Typ==CONSTANT)||(prev->Typ==VARIABLE))&&
(curr->Typ==MULTIPLY)) {
Pop();
Pop(&tt,val);
Pop();
Push(tt,val);
return TRUE;
}
// 1 z ^ => 1
if((prev2->Typ==CONSTANT)&&
(atof(prev2->Val)==1)&&
((prev->Typ==CONSTANT)||(prev->Typ==VARIABLE))&&
(curr->Typ==POWER)) {
Pop();
Pop();
Pop();
Push(CONSTANT,1.0);
return TRUE;
}
// z 0 * => 0
if(((prev2->Typ==CONSTANT)||(prev2->Typ==VARIABLE))&&
(prev->Typ==CONSTANT)&&
(atof(prev->Val)==0)&&
(curr->Typ==MULTIPLY)) {
Pop();
Pop();
Pop();
Push(CONSTANT,0.0);
return TRUE;
}
}
if(prev!=NULL) {
// 0 + =>
// 0 - =>
if((prev->Typ==CONSTANT)&&
(atof(prev->Val)==0)&&
((curr->Typ==PLUS)||(curr->Typ==MINUS))) {
Pop();
Pop();
return TRUE;
}
// 1 * =>
// 1 / =>
// 1 ^ =>
if((prev->Typ==CONSTANT)&&
(atof(prev->Val)==1)&&
((curr->Typ==MULTIPLY)||(curr->Typ==DIVIDE)||(curr->Typ==POWER))) {
Pop();
Pop();
return TRUE;
}
// C F => C
if((prev->Typ==CONSTANT)&&
(curr->Typ==FUNCTION)) {
if(EQUAL(curr->Val,"EXP"))
v = exp(atof(prev->Val));
else if(EQUAL(curr->Val,"LOG"))
v = log(atof(prev->Val));
else if(EQUAL(curr->Val,"SQRT"))
v = sqrt(atof(prev->Val));
else if(EQUAL(curr->Val,"COS"))
v = cos(atof(prev->Val));
else if(EQUAL(curr->Val,"SIN"))
v = sin(atof(prev->Val));
else if(EQUAL(curr->Val,"TAN"))
v = tan(atof(prev->Val));
else if(EQUAL(curr->Val,"ACOS"))
v = acos(atof(prev->Val));
else if(EQUAL(curr->Val,"ASIN"))
v = asin(atof(prev->Val));
else if(EQUAL(curr->Val,"ATAN"))
v = atan(atof(prev->Val));
else
return FALSE;
Pop();
Pop();
Push(CONSTANT,v);
return TRUE;
}
// F INVF =>
if((prev->Typ==FUNCTION)&&
(curr->Typ==FUNCTION)) {
if((EQUAL(prev->Val,"EXP")&&EQUAL(curr->Val,"LOG"))||
(EQUAL(prev->Val,"LOG")&&EQUAL(curr->Val,"EXP"))||
(EQUAL(prev->Val,"COS")&&EQUAL(curr->Val,"ACOS"))||
(EQUAL(prev->Val,"SIN")&&EQUAL(curr->Val,"ASIN"))||
(EQUAL(prev->Val,"TAN")&&EQUAL(curr->Val,"ATAN"))||
(EQUAL(prev->Val,"ACOS")&&EQUAL(curr->Val,"COS"))||
(EQUAL(prev->Val,"ASIN")&&EQUAL(curr->Val,"SIN"))||
(EQUAL(prev->Val,"ATAN")&&EQUAL(curr->Val,"TAN"))) {
Pop();
Pop();
return TRUE;
}
}
}
return FALSE;
}
// constructor
FloatExpression::FloatExpression(char *s) : Expression(s,FALSE)
{
}
FloatExpression::FloatExpression(const class Expression& e) : Expression(e)
{
}
// desctructor
FloatExpression::~FloatExpression()
{
}
// get value
double FloatExpression::Value()
{
if(!ConvPostFix) expr_error(EM_EXPR_NCTP);
double stack[STACKSIZE];
int stackptr = 0;
struct Token *current;
for(int i=0;i<Tokens->GetNElm();i++) {
current = (struct Token *)((*Tokens)[i]);
if((stackptr<0)||(stackptr>=STACKSIZE))
expr_error(EM_SE);
switch(current->Typ) {
case CONSTANT:
stack[stackptr] = atof(current->Val);
stackptr++;
break;
case VARIABLE:
if(!ExprVariables->FindSymbol(current->Val,&stack[stackptr]))
expr_error(EM_EXPR_NSV);
stackptr++;
break;
case UNARYMINUS:
NEEDARG(1);
stack[stackptr-1] = -stack[stackptr-1];
break;
case PLUS:
NEEDARG(2);
stack[stackptr-2] = stack[stackptr-2] + stack[stackptr-1];
stackptr--;
break;
case MINUS:
NEEDARG(2);
stack[stackptr-2] = stack[stackptr-2] - stack[stackptr-1];
stackptr--;
break;
case MULTIPLY:
NEEDARG(2);
stack[stackptr-2] = stack[stackptr-2] * stack[stackptr-1];
stackptr--;
break;
case DIVIDE:
NEEDARG(2);
stack[stackptr-2] = stack[stackptr-2] / stack[stackptr-1];
stackptr--;
break;
case REMAINDER:
NEEDARG(2);
stack[stackptr-2] = fmod(stack[stackptr-2],stack[stackptr-1]);
stackptr--;
break;
case POWER:
NEEDARG(2);
stack[stackptr-2] = pow(stack[stackptr-2],stack[stackptr-1]);
stackptr--;
break;
case FUNCTION:
if(EQUAL(current->Val,"EXP")) {
NEEDARG(1);
stack[stackptr-1] = exp(stack[stackptr-1]);
} else if(EQUAL(current->Val,"LOG")) {
NEEDARG(1);
stack[stackptr-1] = log(stack[stackptr-1]);
} else if(EQUAL(current->Val,"SQRT")) {
NEEDARG(1);
stack[stackptr-1] = sqrt(stack[stackptr-1]);
} else if(EQUAL(current->Val,"COS")) {
NEEDARG(1);
stack[stackptr-1] = cos(stack[stackptr-1]);
} else if(EQUAL(current->Val,"SIN")) {
NEEDARG(1);
stack[stackptr-1] = sin(stack[stackptr-1]);
} else if(EQUAL(current->Val,"TAN")) {
NEEDARG(1);
stack[stackptr-1] = tan(stack[stackptr-1]);
} else if(EQUAL(current->Val,"ACOS")) {
NEEDARG(1);
stack[stackptr-1] = acos(stack[stackptr-1]);
} else if(EQUAL(current->Val,"ASIN")) {
NEEDARG(1);
stack[stackptr-1] = asin(stack[stackptr-1]);
} else if(EQUAL(current->Val,"ATAN")) {
NEEDARG(1);
stack[stackptr-1] = atan(stack[stackptr-1]);
} else {
expr_error(EM_UF);
}
break;
case LEFTBRACKET:
case RIGHTBRACKET:
expr_error(EM_GII);
break;
case OR:
case AND:
case NOT:
case XEQUAL:
expr_error(EM_ND);
break;
case COMMA:
expr_error(EM_GII);
break;
}
}
if(stackptr!=1) expr_error(EM_SE);
return stack[0];
}
// simplify
class FloatExpression FloatExpression::Simplify()
{
if(!ConvPostFix) expr_error(EM_EXPR_NCTP);
class FloatExpression result("");
class FloatExpression work = *this;
enum token_type tt;
char val[256];
while(work.More()) {
work.Pop(&tt,val);
result.Push(tt,val);
while(result.TopSimplify());
}
result.Tokens->Turn();
result.ConvPostFix = TRUE;
return result;
}
// derive
class FloatExpression FloatExpression::Derive(char *var)
{
if(!ConvPostFix) expr_error(EM_EXPR_NCTP);
enum token_type tt;
char val[256];
class FloatExpression *expr[STACKSIZE];
class FloatExpression *deriv_expr[STACKSIZE];
int stackptr = 0;
BOOL cv1,cv2;
struct Token *current;
for(int i=0;i<Tokens->GetNElm();i++) {
current = (struct Token *)((*Tokens)[i]);
if((stackptr<0)||(stackptr>=STACKSIZE))
expr_error(EM_SE);
switch(current->Typ) {
case CONSTANT:
deriv_expr[stackptr] = new class FloatExpression("0");
expr[stackptr] = new class FloatExpression(current->Val);
stackptr++;
break;
case VARIABLE:
if(EQUAL(current->Val,var)) {
deriv_expr[stackptr] = new class FloatExpression("1");
} else {
deriv_expr[stackptr] = new class FloatExpression("0");
}
expr[stackptr] = new class FloatExpression(current->Val);
stackptr++;
break;
case UNARYMINUS:
deriv_expr[stackptr-1]->Push(UNARYMINUS,"");
expr[stackptr-1]->Push(UNARYMINUS,"");
break;
case PLUS:
append(deriv_expr[stackptr-2],deriv_expr[stackptr-1]);
deriv_expr[stackptr-2]->Push(PLUS,"");
append(expr[stackptr-2],expr[stackptr-1]);
expr[stackptr-2]->Push(PLUS,"");
delete expr[stackptr-1];
delete deriv_expr[stackptr-1];
stackptr--;
break;
case MINUS:
append(deriv_expr[stackptr-2],deriv_expr[stackptr-1]);
deriv_expr[stackptr-2]->Push(MINUS,"");
append(expr[stackptr-2],expr[stackptr-1]);
expr[stackptr-2]->Push(MINUS,"");
delete expr[stackptr-1];
delete deriv_expr[stackptr-1];
stackptr--;
break;
case MULTIPLY:
append(deriv_expr[stackptr-2],expr[stackptr-1]);
deriv_expr[stackptr-2]->Push(MULTIPLY,"");
append(deriv_expr[stackptr-2],expr[stackptr-2]);
append(deriv_expr[stackptr-2],deriv_expr[stackptr-1]);
deriv_expr[stackptr-2]->Push(MULTIPLY,"");
deriv_expr[stackptr-2]->Push(PLUS,"");
append(expr[stackptr-2],expr[stackptr-1]);
expr[stackptr-2]->Push(MULTIPLY,"");
delete expr[stackptr-1];
delete deriv_expr[stackptr-1];
stackptr--;
break;
case DIVIDE:
append(deriv_expr[stackptr-2],expr[stackptr-1]);
deriv_expr[stackptr-2]->Push(MULTIPLY,"");
append(deriv_expr[stackptr-2],expr[stackptr-2]);
append(deriv_expr[stackptr-2],deriv_expr[stackptr-1]);
deriv_expr[stackptr-2]->Push(MULTIPLY,"");
deriv_expr[stackptr-2]->Push(MINUS,"");
append(deriv_expr[stackptr-2],expr[stackptr-1]);
append(deriv_expr[stackptr-2],expr[stackptr-1]);
deriv_expr[stackptr-2]->Push(MULTIPLY,"");
deriv_expr[stackptr-2]->Push(DIVIDE,"");
append(expr[stackptr-2],expr[stackptr-1]);
expr[stackptr-2]->Push(DIVIDE,"");
delete expr[stackptr-1];
delete deriv_expr[stackptr-1];
stackptr--;
break;
case REMAINDER:
expr_error(EM_EXPR_CND);
break;
case POWER:
cv1 = strstr(expr[stackptr-2]->String(),var) != NULL;
cv2 = strstr(expr[stackptr-1]->String(),var) != NULL;
if(cv1) {
if(cv2) {
expr_error(EM_EXPR_CND);
} else {
append(deriv_expr[stackptr-2],expr[stackptr-2]);
append(deriv_expr[stackptr-2],expr[stackptr-1]);
deriv_expr[stackptr-2]->Push(CONSTANT,"1");
deriv_expr[stackptr-2]->Push(MINUS,"");
deriv_expr[stackptr-2]->Push(POWER,"");
deriv_expr[stackptr-2]->Push(MULTIPLY,"");
append(deriv_expr[stackptr-2],expr[stackptr-1]);
deriv_expr[stackptr-2]->Push(MULTIPLY,"");
}
} else {
if(cv2) {
while(deriv_expr[stackptr-2]->More()) deriv_expr[stackptr-2]->Pop();
append(deriv_expr[stackptr-2],deriv_expr[stackptr-1]);
append(deriv_expr[stackptr-2],expr[stackptr-2]);
append(deriv_expr[stackptr-2],expr[stackptr-1]);
deriv_expr[stackptr-2]->Push(POWER,"");
deriv_expr[stackptr-2]->Push(MULTIPLY,"");
append(deriv_expr[stackptr-2],expr[stackptr-2]);
deriv_expr[stackptr-2]->Push(FUNCTION,"LOG");
deriv_expr[stackptr-2]->Push(MULTIPLY,"");
} else {
// deriv_expr[stackptr-2] should be 0 and no need to change
}
}
append(expr[stackptr-2],expr[stackptr-1]);
expr[stackptr-2]->Push(POWER,"");
delete expr[stackptr-1];
delete deriv_expr[stackptr-1];
stackptr--;
break;
case FUNCTION:
if(EQUAL(current->Val,"EXP")) {
append(deriv_expr[stackptr-1],expr[stackptr-1]);
deriv_expr[stackptr-1]->Push(FUNCTION,"EXP");
deriv_expr[stackptr-1]->Push(MULTIPLY,"");
} else if(EQUAL(current->Val,"LOG")) {
append(deriv_expr[stackptr-1],expr[stackptr-1]);
deriv_expr[stackptr-1]->Push(DIVIDE,"");
} else if(EQUAL(current->Val,"SQRT")) {
deriv_expr[stackptr-1]->Push(CONSTANT,"2");
append(deriv_expr[stackptr-1],expr[stackptr-1]);
deriv_expr[stackptr-1]->Push(FUNCTION,"SQRT");
deriv_expr[stackptr-1]->Push(MULTIPLY,"");
deriv_expr[stackptr-1]->Push(DIVIDE,"");
} else if(EQUAL(current->Val,"COS")) {
append(deriv_expr[stackptr-1],expr[stackptr-1]);
deriv_expr[stackptr-1]->Push(FUNCTION,"SIN");
deriv_expr[stackptr-1]->Push(UNARYMINUS,"");
deriv_expr[stackptr-1]->Push(MULTIPLY,"");
} else if(EQUAL(current->Val,"SIN")) {
append(deriv_expr[stackptr-1],expr[stackptr-1]);
deriv_expr[stackptr-1]->Push(FUNCTION,"COS");
deriv_expr[stackptr-1]->Push(MULTIPLY,"");
} else if(EQUAL(current->Val,"TAN")) {
append(deriv_expr[stackptr-1],expr[stackptr-1]);
deriv_expr[stackptr-1]->Push(FUNCTION,"COS");
deriv_expr[stackptr-1]->Push(CONSTANT,"2");
deriv_expr[stackptr-1]->Push(POWER,"");
deriv_expr[stackptr-1]->Push(DIVIDE,"");
} else if(EQUAL(current->Val,"ACOS")) {
deriv_expr[stackptr-1]->Push(CONSTANT,"1");
append(deriv_expr[stackptr-1],expr[stackptr-1]);
deriv_expr[stackptr-1]->Push(CONSTANT,"2");
deriv_expr[stackptr-1]->Push(POWER,"");
deriv_expr[stackptr-1]->Push(MINUS,"");
deriv_expr[stackptr-1]->Push(FUNCTION,"SQRT");
deriv_expr[stackptr-1]->Push(UNARYMINUS,"");
deriv_expr[stackptr-1]->Push(DIVIDE,"");
} else if(EQUAL(current->Val,"ASIN")) {
deriv_expr[stackptr-1]->Push(CONSTANT,"1");
append(deriv_expr[stackptr-1],expr[stackptr-1]);
deriv_expr[stackptr-1]->Push(CONSTANT,"2");
deriv_expr[stackptr-1]->Push(POWER,"");
deriv_expr[stackptr-1]->Push(MINUS,"");
deriv_expr[stackptr-1]->Push(FUNCTION,"SQRT");
deriv_expr[stackptr-1]->Push(DIVIDE,"");
} else if(EQUAL(current->Val,"ATAN")) {
deriv_expr[stackptr-1]->Push(CONSTANT,"1");
append(deriv_expr[stackptr-1],expr[stackptr-1]);
deriv_expr[stackptr-1]->Push(CONSTANT,"2");
deriv_expr[stackptr-1]->Push(POWER,"");
deriv_expr[stackptr-1]->Push(PLUS,"");
deriv_expr[stackptr-1]->Push(DIVIDE,"");
} else {
expr_error(EM_EXPR_CND);
}
expr[stackptr-1]->Push(FUNCTION,current->Val);
break;
case LEFTBRACKET:
case RIGHTBRACKET:
expr_error(EM_GII);
break;
case COMMA:
;
}
}
deriv_expr[0]->Tokens->Turn();
deriv_expr[0]->ConvPostFix = TRUE;
class FloatExpression result = deriv_expr[0]->Simplify();
delete expr[0];
delete deriv_expr[0];
return result;
}
//**********************************************************************
//
// Class IntExpression
//
//**********************************************************************
// simplify on top
BOOL IntExpression::TopSimplify()
{
long int v;
enum token_type tt;
char val[256];
struct Token *curr = (struct Token *)(*Tokens)[0];
struct Token *prev = (struct Token *)(*Tokens)[1];
struct Token *prev2 = (struct Token *)(*Tokens)[2];
struct Token *prev3 = (struct Token *)(*Tokens)[3];
if(prev3!=NULL) {
// C + C + => C +
// C - C + => C +
// C + C - => C -
// C - C - => C -
if((prev3->Typ==CONSTANT)&&
((prev2->Typ==PLUS)||(prev2->Typ==MINUS))&&
(prev->Typ==CONSTANT)&&
((curr->Typ==PLUS)||(curr->Typ==MINUS))) {
if(curr->Typ==prev2->Typ)
v = atoi(prev->Val) + atoi(prev3->Val);
else
v = atoi(prev->Val) - atoi(prev3->Val);
tt = curr->Typ;
Pop();
Pop();
Pop();
Pop();
Push(CONSTANT,v);
Push(tt,"");
return TRUE;
}
// C * C * => C *
// C / C * => C *
// C * C / => C /
// C / C / => C /
if((prev3->Typ==CONSTANT)&&
((prev2->Typ==MULTIPLY)||(prev2->Typ==DIVIDE))&&
(prev->Typ==CONSTANT)&&
((curr->Typ==MULTIPLY)||(curr->Typ==DIVIDE))) {
if(curr->Typ==prev2->Typ)
v = atoi(prev->Val) * atoi(prev3->Val);
else
v = atoi(prev->Val) / atoi(prev3->Val);
tt = curr->Typ;
Pop();
Pop();
Pop();
Pop();
Push(CONSTANT,v);
Push(tt,"");
return TRUE;
}
}
if(prev2!=NULL) {
// C C + => C
if((prev2->Typ==CONSTANT)&&
(prev->Typ==CONSTANT)&&
(curr->Typ==PLUS)) {
v = atoi(prev2->Val) + atoi(prev->Val);
Pop();
Pop();
Pop();
Push(CONSTANT,v);
return TRUE;
}
// C C - => C
if((prev2->Typ==CONSTANT)&&
(prev->Typ==CONSTANT)&&
(curr->Typ==MINUS)) {
v = atoi(prev2->Val) - atoi(prev->Val);
Pop();
Pop();
Pop();
Push(CONSTANT,v);
return TRUE;
}
// C C * => C
if((prev2->Typ==CONSTANT)&&
(prev->Typ==CONSTANT)&&
(curr->Typ==MULTIPLY)) {
v = atoi(prev2->Val) * atoi(prev->Val);
Pop();
Pop();
Pop();
Push(CONSTANT,v);
return TRUE;
}
// C C / => C
if((prev2->Typ==CONSTANT)&&
(prev->Typ==CONSTANT)&&
(curr->Typ==DIVIDE)) {
v = atoi(prev2->Val) / atoi(prev->Val);
Pop();
Pop();
Pop();
Push(CONSTANT,v);
return TRUE;
}
// C C % => C
if((prev2->Typ==CONSTANT)&&
(prev->Typ==CONSTANT)&&
(curr->Typ==REMAINDER)) {
v = atoi(prev2->Val) % atoi(prev->Val);
Pop();
Pop();
Pop();
Push(CONSTANT,v);
return TRUE;
}
// 0 z + => z
// 0 z - => z
if((prev2->Typ==CONSTANT)&&
(atoi(prev2->Val)==0)&&
((prev->Typ==CONSTANT)||(prev->Typ==VARIABLE))&&
((curr->Typ==PLUS)||curr->Typ==MINUS)) {
Pop();
Pop(&tt,val);
Pop();
Push(tt,val);
return TRUE;
}
// 0 z * => 0
// 0 z / => 0
// 0 z % => 0
if((prev2->Typ==CONSTANT)&&
(atoi(prev2->Val)==0)&&
((prev->Typ==CONSTANT)||(prev->Typ==VARIABLE))&&
((curr->Typ==MULTIPLY)||(curr->Typ==DIVIDE)||(curr->Typ==REMAINDER))) {
Pop();
Pop();
Pop();
Push(CONSTANT,0);
return TRUE;
}
// 1 z * => z
if((prev2->Typ==CONSTANT)&&
(atoi(prev2->Val)==1)&&
((prev->Typ==CONSTANT)||(prev->Typ==VARIABLE))&&
(curr->Typ==MULTIPLY)) {
Pop();
Pop(&tt,val);
Pop();
Push(tt,val);
return TRUE;
}
// z 0 * => 0
if(((prev2->Typ==CONSTANT)||(prev2->Typ==VARIABLE))&&
(prev->Typ==CONSTANT)&&
(atoi(prev->Val)==0)&&
(curr->Typ==MULTIPLY)) {
Pop();
Pop();
Pop();
Push(CONSTANT,0.0);
return TRUE;
}
}
if(prev!=NULL) {
// 0 + =>
// 0 - =>
if((prev->Typ==CONSTANT)&&
(atoi(prev->Val)==0)&&
((curr->Typ==PLUS)||(curr->Typ==MINUS))) {
Pop();
Pop();
return TRUE;
}
// 1 * =>
// 1 / =>
if((prev->Typ==CONSTANT)&&
(atoi(prev->Val)==1)&&
((curr->Typ==MULTIPLY)||(curr->Typ==DIVIDE))) {
Pop();
Pop();
return TRUE;
}
}
return FALSE;
}
// constructor
IntExpression::IntExpression(char *s) : Expression(s,FALSE)
{
}
IntExpression::IntExpression(const class Expression& e) : Expression(e)
{
}
// desctructor
IntExpression::~IntExpression()
{
}
// get value
long int IntExpression::Value()
{
if(!ConvPostFix) expr_error(EM_EXPR_NCTP);
long int stack[STACKSIZE];
int stackptr = 0;
struct Token *current;
for(int i=0;i<Tokens->GetNElm();i++) {
current = (struct Token *)((*Tokens)[i]);
if((stackptr<0)||(stackptr>=STACKSIZE))
expr_error(EM_SE);
switch(current->Typ) {
case CONSTANT:
stack[stackptr] = atoi(current->Val);
stackptr++;
break;
case VARIABLE:
if(!ExprVariables->FindSymbol(current->Val,&stack[stackptr]))
expr_error(EM_EXPR_NSV);
stackptr++;
break;
case UNARYMINUS:
NEEDARG(1);
stack[stackptr-1] = -stack[stackptr-1];
break;
case PLUS:
NEEDARG(2);
stack[stackptr-2] = stack[stackptr-2] + stack[stackptr-1];
stackptr--;
break;
case MINUS:
NEEDARG(2);
stack[stackptr-2] = stack[stackptr-2] - stack[stackptr-1];
stackptr--;
break;
case MULTIPLY:
NEEDARG(2);
stack[stackptr-2] = stack[stackptr-2] * stack[stackptr-1];
stackptr--;
break;
case DIVIDE:
NEEDARG(2);
stack[stackptr-2] = stack[stackptr-2] / stack[stackptr-1];
stackptr--;
break;
case REMAINDER:
NEEDARG(2);
stack[stackptr-2] = stack[stackptr-2] % stack[stackptr-1];
stackptr--;
break;
case POWER:
expr_error(EM_ND);
break;
case FUNCTION:
expr_error(EM_ND);
break;
case LEFTBRACKET:
case RIGHTBRACKET:
expr_error(EM_GII);
break;
case OR:
case AND:
case NOT:
case XEQUAL:
expr_error(EM_ND);
break;
case COMMA:
expr_error(EM_GII);
break;
}
}
if(stackptr!=1) expr_error(EM_SE);
return stack[0];
}
// simplify
class IntExpression IntExpression::Simplify()
{
if(!ConvPostFix) expr_error(EM_EXPR_NCTP);
class IntExpression result("");
class IntExpression work = *this;
enum token_type tt;
char val[256];
while(work.More()) {
work.Pop(&tt,val);
result.Push(tt,val);
while(result.TopSimplify());
}
result.Tokens->Turn();
result.ConvPostFix = TRUE;
return result;
}
//**********************************************************************
//
// Class BoolExpression
//
//**********************************************************************
// simplify on top
BOOL BoolExpression::TopSimplify()
{
return FALSE;
}
// constructor
BoolExpression::BoolExpression(char *s) : Expression(s,TRUE)
{
}
BoolExpression::BoolExpression(const class Expression& e) : Expression(e)
{
}
// desctructor
BoolExpression::~BoolExpression()
{
}
// get value
BOOL BoolExpression::Value()
{
if(!ConvPostFix) expr_error(EM_EXPR_NCTP);
BOOL stack[STACKSIZE];
int stackptr = 0;
struct Token *current;
for(int i=0;i<Tokens->GetNElm();i++) {
current = (struct Token *)((*Tokens)[i]);
if((stackptr<0)||(stackptr>=STACKSIZE))
expr_error(EM_SE);
switch(current->Typ) {
case CONSTANT:
if(EQUAL(current->Val,"TRUE")) {
stack[stackptr] = 1;
} else if(EQUAL(current->Val,"FALSE")) {
stack[stackptr] = 0;
} else {
stack[stackptr] = atoi(current->Val);
}
stackptr++;
break;
case VARIABLE:
if(!ExprVariables->FindSymbol(current->Val,&stack[stackptr]))
expr_error(EM_EXPR_NSV);
stackptr++;
break;
case UNARYMINUS:
case PLUS:
case MINUS:
case MULTIPLY:
case DIVIDE:
case REMAINDER:
case POWER:
expr_error(EM_ND);
break;
case FUNCTION:
expr_error(EM_ND);
break;
case LEFTBRACKET:
case RIGHTBRACKET:
expr_error(EM_GII);
break;
case OR:
NEEDARG(2);
stack[stackptr-2] = stack[stackptr-2] || stack[stackptr-1];
stackptr--;
break;
case AND:
NEEDARG(2);
stack[stackptr-2] = stack[stackptr-2] && stack[stackptr-1];
stackptr--;
break;
case NOT:
NEEDARG(1);
stack[stackptr-1] = !stack[stackptr-1];
break;
case XEQUAL:
NEEDARG(2);
stack[stackptr-2] = (stack[stackptr-2] == stack[stackptr-1]);
stackptr--;
break;
case COMMA:
expr_error(EM_GII);
break;
}
}
if(stackptr!=1) expr_error(EM_SE);
return stack[0];
}
// simplify
class BoolExpression BoolExpression::Simplify()
{
if(!ConvPostFix) expr_error(EM_EXPR_NCTP);
class BoolExpression result("");
class BoolExpression work = *this;
enum token_type tt;
char val[256];
while(work.More()) {
work.Pop(&tt,val);
result.Push(tt,val);
while(result.TopSimplify());
}
result.Tokens->Turn();
result.ConvPostFix = TRUE;
return result;
}
//**********************************************************************
//
// Class ListExpression
//
//**********************************************************************
// classic set operations
#define NOMEM(ln) ln[0]
long int *expr_list_union(long int *lstp1,long int *lstp2)
{
int n = NOMEM(lstp1) + NOMEM(lstp2);
long int *wrk = new long[1+n];
int ix1 = 0;
int ix2 = 0;
int wrkix = 0;
while ( (ix1<NOMEM(lstp1)) || (ix2<NOMEM(lstp2)) ) {
if( (ix1<NOMEM(lstp1)) && (ix2<NOMEM(lstp2)) ) {
if(lstp1[1+ix1]==lstp2[1+ix2]) {
wrk[1+wrkix] = lstp1[1+ix1];
wrkix++;
ix1++;
ix2++;
} else if(lstp1[1+ix1]<lstp2[1+ix2]) {
wrk[1+wrkix] = lstp1[1+ix1];
wrkix++;
ix1++;
} else if(lstp1[1+ix1]>lstp2[1+ix2]) {
wrk[1+wrkix] = lstp2[1+ix2];
wrkix++;
ix2++;
}
} else {
while(ix1<NOMEM(lstp1)) {
wrk[1+wrkix] = lstp1[1+ix1];
wrkix++;
ix1++;
}
while(ix2<NOMEM(lstp2)) {
wrk[1+wrkix] = lstp2[1+ix2];
wrkix++;
ix2++;
}
}
}
NOMEM(wrk) = wrkix;
delete lstp1;
delete lstp2;
long int *res = new long[1+NOMEM(wrk)] ;
NOMEM(res) = NOMEM(wrk);
for(int i=0;i<NOMEM(res);i++) res[1+i] = wrk[1+i];
delete wrk;
return res;
}
long int *expr_list_intersect(long int *lstp1,long int *lstp2)
{
int n = NOMEM(lstp1) + NOMEM(lstp2);
long int *wrk = new long[1+n];
int ix1 = 0;
int ix2 = 0;
int wrkix = 0;
while ( (ix1<NOMEM(lstp1)) || (ix2<NOMEM(lstp2)) ) {
if( (ix1<NOMEM(lstp1)) && (ix2<NOMEM(lstp2)) ) {
if(lstp1[1+ix1]==lstp2[1+ix2]) {
wrk[1+wrkix] = lstp1[1+ix1];
wrkix++;
ix1++;
ix2++;
} else if(lstp1[1+ix1]<lstp2[1+ix2]) {
ix1++;
} else if(lstp1[1+ix1]>lstp2[1+ix2]) {
ix2++;
}
} else {
while(ix1<NOMEM(lstp1)) {
ix1++;
}
while(ix2<NOMEM(lstp2)) {
ix2++;
}
}
}
NOMEM(wrk) = wrkix;
delete lstp1;
delete lstp2;
long int *res = new long[1+NOMEM(wrk)] ;
NOMEM(res) = NOMEM(wrk);
for(int i=0;i<NOMEM(res);i++) res[1+i] = wrk[1+i];
delete wrk;
return res;
}
long int *expr_list_minus(long int *lstp1,long int *lstp2)
{
int n = NOMEM(lstp1) + NOMEM(lstp2);
long int *wrk = new long[1+n];
int ix1 = 0;
int ix2 = 0;
int wrkix = 0;
while ( (ix1<NOMEM(lstp1)) || (ix2<NOMEM(lstp2)) ) {
if( (ix1<NOMEM(lstp1)) && (ix2<NOMEM(lstp2)) ) {
if(lstp1[1+ix1]==lstp2[1+ix2]) {
ix1++;
ix2++;
} else if(lstp1[1+ix1]<lstp2[1+ix2]) {
wrk[1+wrkix] = lstp1[1+ix1];
wrkix++;
ix1++;
} else if(lstp1[1+ix1]>lstp2[1+ix2]) {
ix2++;
}
} else {
while(ix1<NOMEM(lstp1)) {
wrk[1+wrkix] = lstp1[1+ix1];
wrkix++;
ix1++;
}
while(ix2<NOMEM(lstp2)) {
ix2++;
}
}
}
NOMEM(wrk) = wrkix;
delete lstp1;
delete lstp2;
long int *res = new long[1+NOMEM(wrk)] ;
NOMEM(res) = NOMEM(wrk);
for(int i=0;i<NOMEM(res);i++) res[1+i] = wrk[1+i];
delete wrk;
return res;
}
// simplify on top
BOOL ListExpression::TopSimplify()
{
return FALSE;
}
// constructor
ListExpression::ListExpression(char *s) : Expression(s,FALSE)
{
}
ListExpression::ListExpression(const class Expression& e) : Expression(e)
{
}
// desctructor
ListExpression::~ListExpression()
{
}
// get value
long int *ListExpression::Value(long int *(*GetList)(char *name))
{
if(!ConvPostFix) expr_error(EM_EXPR_NCTP);
long int *stack[STACKSIZE];
int stackptr = 0;
struct Token *current;
for(int i=0;i<Tokens->GetNElm();i++) {
current = (struct Token *)((*Tokens)[i]);
if((stackptr<0)||(stackptr>=STACKSIZE))
expr_error(EM_SE);
switch(current->Typ) {
case CONSTANT:
expr_error(EM_NIY);
break;
case VARIABLE:
stack[stackptr] = GetList(current->Val);
if(stack[stackptr]==NULL) expr_error(EM_EXPR_NSV);
stackptr++;
break;
case UNARYMINUS:
case PLUS:
case MINUS:
case MULTIPLY:
case DIVIDE:
case REMAINDER:
case POWER:
expr_error(EM_ND);
break;
case FUNCTION:
expr_error(EM_ND);
break;
case LEFTBRACKET:
case RIGHTBRACKET:
expr_error(EM_GII);
break;
case OR:
NEEDARG(2);
stack[stackptr-2] = expr_list_union(stack[stackptr-2],
stack[stackptr-1]);
stackptr--;
break;
case AND:
NEEDARG(2);
stack[stackptr-2] = expr_list_intersect(stack[stackptr-2],
stack[stackptr-1]);
stackptr--;
break;
case NOT:
NEEDARG(2);
stack[stackptr-2] = expr_list_minus(stack[stackptr-2],
stack[stackptr-1]);
stackptr--;
break;
case XEQUAL:
case COMMA:
expr_error(EM_GII);
break;
}
}
if(stackptr!=1) expr_error(EM_SE);
return stack[0];
}
// simplify
class ListExpression ListExpression::Simplify()
{
if(!ConvPostFix) expr_error(EM_EXPR_NCTP);
class ListExpression result("");
class ListExpression work = *this;
enum token_type tt;
char val[256];
while(work.More()) {
work.Pop(&tt,val);
result.Push(tt,val);
while(result.TopSimplify());
}
result.Tokens->Turn();
result.ConvPostFix = TRUE;
return result;
}