Avatar billede Daniel.E Praktikant
16. december 2004 - 23:11 Der er 26 kommentarer og
1 løsning

udregne 1==1 & 2!=3 osv

hej

if( (a==1 && b==2 ) || (a!=0 || b==9) )

Findes der ikke et bibliotek ude på nettet som kan udregne sådanne regne stykker, hvis man forestiller sig at selve variabelerne bliver erstattet med de korekte tal fra stakken.

Så kunne det blive til
a=1
b=9
if( (1==1 && 9==2 ) || (1!=0 || 9==9) )


Det er denne som jeg spørger til:

(1==1 && 9==2 ) || (1!=0 || 9==9)
Avatar billede arne_v Ekspert
16. december 2004 - 23:13 #1
Du mener en expression evaluator som kan udregne værdien af en string ?
Avatar billede arne_v Ekspert
16. december 2004 - 23:14 #2
Du kan lave en relativt hurtigt med Bison og Flex.
Avatar billede Daniel.E Praktikant
16. december 2004 - 23:14 #3
kunne man gøre sådan...

int a = 1;
    int b = 1;
    bool c = (a==b || a==2);
    cout << c;
Avatar billede Daniel.E Praktikant
16. december 2004 - 23:14 #4
1 er true
0 er false
Avatar billede arne_v Ekspert
16. december 2004 - 23:16 #5
Ellers kan du hvis det er C++ hapse min BoolExpression klasse her:
  http://www.vajhoej.dk/arne/eksperten/EXPR/
Avatar billede Daniel.E Praktikant
16. december 2004 - 23:17 #6
hvis du gider at generer sådan en som kan udregne sådna noget..

kunne det blive sådna at der er en funktion som ligner dette...

int cal_expression(char *exp);

så jeg kunne give en char* som "1==1 && 2==2 || 3!=0"
Avatar billede arne_v Ekspert
16. december 2004 - 23:17 #7
int a = 1;
    int b = 1;
    bool c = (a==b || a==2);
    cout << c;

virker fint.

Men har du det i kode form ?

(udfra tidligere spørgsmål gik jeg ud fra at du bare havde en string)
Avatar billede Daniel.E Praktikant
16. december 2004 - 23:17 #8
arne jeg tror faktisk jeg har den i forvejen... :)  Kan den klare det ?
Avatar billede Daniel.E Praktikant
16. december 2004 - 23:19 #9
int a = 1;
    int b = 1;
    bool c = (a==b || a==2);
    cout << c;

Men det menet jeg bare at...

hvis man havde en expression som "a==1 && b==2", så ville jeg erstatte a og b med de rigtige værdier, og ende med at have en char*, hvori står "a_værdi==1 && b_værdi==2".
Avatar billede arne_v Ekspert
16. december 2004 - 23:20 #10
Hvis ikke så må den nemt kunne laves til så den kan klare det.
Avatar billede Daniel.E Praktikant
16. december 2004 - 23:20 #11
FloatExpression e2(infix2postfix(FloatExpression("(2==0)")));
  cout << e2.Value() << endl;

har prøvet noget som dette
Avatar billede arne_v Ekspert
16. december 2004 - 23:23 #12
Du skal bare over i BoolExpression.

Den har && og || men det ser ud som om at == mangler.
Avatar billede Daniel.E Praktikant
16. december 2004 - 23:26 #13
FloatExpression e2(infix2postfix(BoolExpression("2 && 0")));
  cout << e2.Value() << endl;

noget i den stil
Avatar billede arne_v Ekspert
16. december 2004 - 23:36 #14
#include <iostream>

using namespace std;

#include "expr.h"

int main()
{
  BoolExpression e1("TRUE AND FALSE");
  BoolExpression e1x = infix2postfix(e1);
  cout << e1x.Value() << endl;
  BoolExpression e2("TRUE OR FALSE");
  BoolExpression e2x = infix2postfix(e2);
  cout << e2x.Value() << endl;
  BoolExpression e3("NOT((TRUE OR FALSE) AND (FALSE OR FALSE))");
  BoolExpression e3x = infix2postfix(e3);
  cout << e3x.Value() << endl;
  return 0;
}

giver

0
1
1

hvilket jo er korrekt

så der skal bare tilføjes == operatoren
Avatar billede Daniel.E Praktikant
16. december 2004 - 23:39 #15
ahhh.... :)
Avatar billede arne_v Ekspert
16. december 2004 - 23:41 #16
Jeg prøver lige om jeg kan bikse noget
Avatar billede Daniel.E Praktikant
16. december 2004 - 23:42 #17
ok :)
Avatar billede Daniel.E Praktikant
17. december 2004 - 00:05 #18
jeg kigger i morgen... :) skal trække mig tilbage nu..
Avatar billede arne_v Ekspert
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;
}
Avatar billede arne_v Ekspert
17. december 2004 - 00:26 #20
#include <iostream>

using namespace std;

#include "expr.h"

int main()
{
  BoolExpression e1("TRUE AND FALSE");
  BoolExpression e1x = infix2postfix(e1);
  cout << e1x.Value() << endl;
  BoolExpression e2("TRUE OR FALSE");
  BoolExpression e2x = infix2postfix(e2);
  cout << e2x.Value() << endl;
  BoolExpression e3("NOT((TRUE OR FALSE) AND (FALSE OR FALSE))");
  BoolExpression e3x = infix2postfix(e3);
  cout << e3x.Value() << endl;
  BoolExpression e4("NOT((1 EQUAL 1 OR 1 EQUAL 2) AND (1 EQUAL 3 OR 1 EQUAL 4))");
  BoolExpression e4x = infix2postfix(e4);
  cout << e4x.Value() << endl;
  ExprDefineVariable("a",1);
  ExprDefineVariable("b",9);
  BoolExpression e5("(a EQUAL 1 AND b EQUAL 2) OR (NOT (a EQUAL 0) OR b EQUAL 9)");
  BoolExpression e5x = infix2postfix(e5);
  cout << e5x.Value() << endl;
  return 0;
}
Avatar billede arne_v Ekspert
17. december 2004 - 00:26 #21
0
1
1
1
1
Avatar billede arne_v Ekspert
17. december 2004 - 00:27 #22
Vi nærmer os.

Jeg kan først arbejde lidt videre på den i morgen aften.
Avatar billede Daniel.E Praktikant
17. december 2004 - 15:02 #23
Hej arne...

ExprDefineVariable("b",9);

Hvordan skal den forståes... kan den også dette ??

ExprDefineVariable("test_string","Hej Verden");
Avatar billede arne_v Ekspert
17. december 2004 - 21:47 #24
Ikke umiddelbart.

Koden kan som den er kun regne med tal.
Avatar billede Daniel.E Praktikant
19. december 2004 - 13:30 #25
giv dit svar Arne :)
Avatar billede arne_v Ekspert
19. december 2004 - 14:39 #26
ok
Avatar billede arne_v Ekspert
19. december 2004 - 14:40 #27
Men du kan faktisk få den kode til at lave ret meget  med få ændringer, fordi
hele den grundliggende mekanisme er der.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester