//------------------------------------------------------------------------------
// express.h - Expression Evaluator Objects
//------------------------------------------------------------------------------

#ifndef _EXPRESS_
#define _EXPRESS_

#include <stdio.h>
#include <iostream.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <fstream.h>

enum obj_type {NONE,OPERAND_TYPE, EXPRESSION_TYPE, BINARY_OPERATOR_TYPE,
                    UNARY_OPERATOR_TYPE, OPEN_PAREN_TYPE, CLOSE_PAREN_TYPE,
                    START_TYPE, STOP_TYPE };
enum token_types {START, STOP, LITERAL, BIN_ADD, BIN_SUB,
                     UNARY_ADD, UNARY_SUB, MUL, DIV, OPEN_PAREN, CLOSE_PAREN,
                     RELATIONAL_AND, RELATIONAL_OR, EQUAL,
                     NOT_EQUAL,GREATER,LESS,GREATER_EQUAL,LESS_EQUAL,NOT,VARIABLE};
enum error_codes {VALID, INVALID_TOKEN, INVALID, MISMATCH_PAREN, INVALID_NUMBER};
enum priorities { CLOSE_PAREN_PRIORITY, OR_PRIORITY, AND_PRIORITY,
                        EQUAL_NOT_EQUAL_PRIORITY, GREATER_LESS_PRIORITY,
                        ADD_SUB_PRIORITY, MUL_DIV_PRIORITY,
                        UNARY_SUB_PRIORITY, NOT_PRIORITY, OPEN_PAREN_PRIORITY };
//------------------------------------------------------------------------------
// Symbol Table class used to implement the Variable data objects.

class Symbol_Table
    {
    private:
        struct entry { char name[25];    float value; entry *next;    };
        entry *head;
    public:
        Symbol_Table( void ) { head=NULL; };
        ~Symbol_Table( void )
            {
            entry *temp;
            while (head!=NULL) { temp=head; head=head->next; delete temp; };
            }
        entry *Is_In( char *name )
            {
            entry *temp=head;
            while (temp!=NULL)
                if (strcmp(name,temp->name)==0) return temp; else temp=temp->next;
            return NULL;
            }
        void Set( char *name, float value )
            {
            entry *temp=Is_In( name );
            if (temp==NULL)
                  {
                  entry *new_head=new entry;
                  strcpy(new_head->name,name);    new_head->value=value;
                  new_head->next=head; head=new_head;
                  }
            else temp->value=value;
            }
        float Get( char *name )
            {
            entry *temp=Is_In(name);
            if (temp!=NULL) return temp->value; else return 0;
            }
    };
//------------------------------------------------------------------------------
// Base Expression Object

class Exp_Obj
    {
    public:
        virtual float GetValue( Symbol_Table &sym ){return 0.0;};
        virtual int GetType( void ){return NONE;};
        virtual int GetPriority( void ){return 0;};
    };
//------------------------------------------------------------------------------
// Base Binary Object

class Binary_Obj : public Exp_Obj
    {
    protected:
            Exp_Obj *left, *right;
    public:
            Binary_Obj( void ) {    left=NULL;     right=NULL;    }
            Binary_Obj( Exp_Obj *l, Exp_Obj *r ) {    left=l; right=r; }
            ~Binary_Obj( void ) { if (left!=NULL) delete left;
                                         if (right!=NULL) delete right;    }
            virtual void SetLeft( Exp_Obj *l ) { left=l;    }
            virtual void SetRight( Exp_Obj *r )    { right=r; }
            virtual float GetValue( Symbol_Table &sym )=0;
            virtual int GetType( void ) { return BINARY_OPERATOR_TYPE; }
    };
//------------------------------------------------------------------------------
// Base Unary Object

class Unary_Obj : public Exp_Obj
    {
    protected:
            Exp_Obj *obj;
    public:
            Unary_Obj( void )    { obj=NULL; }
            Unary_Obj( Exp_Obj *o  ) {    obj=o; }
            ~Unary_Obj( void )    { if (obj!=NULL) delete obj; }
            virtual void SetObj( Exp_Obj *o ) {    obj=o; }
            virtual float GetValue( Symbol_Table &sym )=0;
            virtual int GetType( void ) { return UNARY_OPERATOR_TYPE; }
    };
//------------------------------------------------------------------------------
// Control Objects

class Start_Obj : public Exp_Obj
    {
    public:
        virtual int GetPriority( void ) { return 0; }
        virtual int GetType( void ) { return START_TYPE; }
    };
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class Stop_Obj : public Exp_Obj
    {
    public:
        virtual int GetType( void ) { return STOP_TYPE; }
    };
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class Open_Paren_Obj : public Exp_Obj
    {
    public:
        virtual int GetPriority( void ) { return OPEN_PAREN_PRIORITY; }
        virtual int GetType( void ) { return OPEN_PAREN_TYPE; }
    };
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class Close_Paren_Obj : public Exp_Obj
    {
    public:
        virtual int GetPriority( void ) { return CLOSE_PAREN_PRIORITY; }
        virtual int GetType( void ) { return CLOSE_PAREN_TYPE; }
    };
//------------------------------------------------------------------------------
class Literal_Obj : public Exp_Obj
    {
    private:
        float value;
    public:
        Literal_Obj( float v ) { value=v; }
        virtual float GetValue( Symbol_Table &sym ) { return value;    }
        virtual int GetType( void ) { return OPERAND_TYPE; }
    };
//------------------------------------------------------------------------------
// Arithmetic Operators

class Unary_Minus : public Unary_Obj
    {
    public:
        Unary_Minus( Exp_Obj *o ): Unary_Obj( o ){};
        Unary_Minus( void ) : Unary_Obj() {};
        virtual float GetValue( Symbol_Table &sym ){return -(obj->GetValue(sym));}
        virtual GetPriority( void ) { return UNARY_SUB_PRIORITY; }
    };
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class Binary_Add_Obj : public Binary_Obj
    {
    public:
        Binary_Add_Obj( Exp_Obj *l, Exp_Obj *r ): Binary_Obj( l, r ){};
        Binary_Add_Obj( void ) : Binary_Obj() {};
        virtual float GetValue( Symbol_Table &sym )
            { return left->GetValue(sym) + right->GetValue(sym); }
        virtual int GetPriority( void ) { return ADD_SUB_PRIORITY;}
    };
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class Binary_Sub_Obj : public Binary_Obj
    {
    public:
        Binary_Sub_Obj( Exp_Obj *l, Exp_Obj *r ): Binary_Obj( l, r ){};
        Binary_Sub_Obj( void ) : Binary_Obj() {};
        virtual float GetValue( Symbol_Table &sym )
            { return left->GetValue(sym) - right->GetValue(sym); }
        virtual int GetPriority( void ) { return ADD_SUB_PRIORITY; }
    };
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class Mul_Obj : public Binary_Obj
    {
    public:
        Mul_Obj( Exp_Obj *l, Exp_Obj *r ): Binary_Obj( l, r ){};
        Mul_Obj( void ) : Binary_Obj() {};
        virtual float GetValue( Symbol_Table &sym )
            { return left->GetValue(sym) * right->GetValue(sym); }
        virtual int GetPriority( void ) { return MUL_DIV_PRIORITY; }
    };
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class Div_Obj : public Binary_Obj
    {
    public:
        Div_Obj( Exp_Obj *l, Exp_Obj *r ): Binary_Obj( l, r ){};
        Div_Obj( void ) : Binary_Obj() {};
        virtual float GetValue( Symbol_Table &sym )
            {
            float divisor=right->GetValue(sym);
            if (divisor==0)
                    {
                    cout << "\n<<< Runtime Error - Division by zero >>>\n";
                    return 0;
                    }
                return left->GetValue(sym) / divisor;
            }
        virtual int GetPriority( void ) { return MUL_DIV_PRIORITY; }
    };
//------------------------------------------------------------------------------
// Boolean Operators

class And_Obj : public Binary_Obj
    {
    public:
        And_Obj( Exp_Obj *l, Exp_Obj *r ): Binary_Obj( l, r ){};
        And_Obj( void ) : Binary_Obj() {};
        virtual float GetValue( Symbol_Table &sym )
            { return left->GetValue(sym) && right->GetValue(sym); }
        virtual int GetPriority( void ) { return AND_PRIORITY; }
    };
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class Or_Obj : public Binary_Obj
    {
    public:
        Or_Obj( Exp_Obj *l, Exp_Obj *r ): Binary_Obj( l, r ){};
        Or_Obj( void ) : Binary_Obj() {};
        virtual float GetValue( Symbol_Table &sym )
            { return left->GetValue(sym) || right->GetValue(sym); }
        virtual int GetPriority(  ) { return OR_PRIORITY; }
    };
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class Not_Obj : public Unary_Obj
    {
    public:
        Not_Obj( Exp_Obj *o ): Unary_Obj( o ){};
        Not_Obj( void ) : Unary_Obj() {};
        virtual float GetValue( Symbol_Table &sym ){return !(obj->GetValue(sym));}
        virtual GetPriority( void ) { return NOT_PRIORITY; }
    };
//------------------------------------------------------------------------------
// Relational Operators

class Equal_Obj : public Binary_Obj
    {
    public:
        Equal_Obj( Exp_Obj *l, Exp_Obj *r ): Binary_Obj( l, r ){};
        Equal_Obj( void ) : Binary_Obj() {};
        virtual float GetValue( Symbol_Table &sym )
            { return left->GetValue(sym) == right->GetValue(sym); }
        virtual int GetPriority( void ) { return EQUAL_NOT_EQUAL_PRIORITY; }
    };
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class Not_Equal_Obj : public Binary_Obj
    {
    public:
        Not_Equal_Obj( Exp_Obj *l, Exp_Obj *r ): Binary_Obj( l, r ){};
        Not_Equal_Obj( void ) : Binary_Obj() {};
        virtual float GetValue( Symbol_Table &sym )
            { return left->GetValue(sym) != right->GetValue(sym); }
        virtual int GetPriority( void ) { return EQUAL_NOT_EQUAL_PRIORITY; }
    };
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class Greater_Obj : public Binary_Obj
    {
    public:
        Greater_Obj( Exp_Obj *l, Exp_Obj *r ): Binary_Obj( l, r ){};
        Greater_Obj( void ) : Binary_Obj() {};
        virtual float GetValue( Symbol_Table &sym )
            { return left->GetValue(sym) > right->GetValue(sym); }
        virtual int GetPriority( void ) { return GREATER_LESS_PRIORITY; }
    };
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class Greater_Equal_Obj : public Binary_Obj
    {
    public:
        Greater_Equal_Obj( Exp_Obj *l, Exp_Obj *r ): Binary_Obj( l, r ){};
        Greater_Equal_Obj( void ) : Binary_Obj() {};
        virtual float GetValue( Symbol_Table &sym )
            { return left->GetValue(sym) >= right->GetValue(sym); }
        virtual int GetPriority( void ) { return GREATER_LESS_PRIORITY; }
    };
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class Less_Obj : public Binary_Obj
    {
    public:
        Less_Obj( Exp_Obj *l, Exp_Obj *r ): Binary_Obj( l, r ){};
        Less_Obj( void ) : Binary_Obj() {};
        virtual float GetValue( Symbol_Table &sym )
            { return left->GetValue(sym) < right->GetValue(sym); }
        virtual int GetPriority( void ) { return GREATER_LESS_PRIORITY; }
    };
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class Less_Equal_Obj : public Binary_Obj
    {
    public:
        Less_Equal_Obj( Exp_Obj *l, Exp_Obj *r ): Binary_Obj( l, r ){};
        Less_Equal_Obj( void ) : Binary_Obj() {};
        virtual float GetValue( Symbol_Table &sym )
            { return left->GetValue(sym) <= right->GetValue(sym); }
        virtual int GetPriority( void ) { return GREATER_LESS_PRIORITY; }
    };
//------------------------------------------------------------------------------
// Variable Data Object

class Variable_Obj : public Exp_Obj
    {
    private:
        char name[25];
    public:
        Variable_Obj( char *var_name ) { strcpy(name,var_name); }
        virtual float GetValue( Symbol_Table &sym ) { return sym.Get(name); }
        virtual int GetType( void ) { return OPERAND_TYPE; }
    };
//------------------------------------------------------------------------------
// Stack to hold expression objects

class ExpStack
    {
    private:
        struct node
            {
            Exp_Obj *data;
            node *next;
            };
        node *head;
    public:
        ExpStack( void ) { head=NULL; };
        ~ExpStack( void )
            {
            node *temp;
            while (head!=NULL)
                { temp=head;     head=head->next;    delete temp; }
            }

        void Push(Exp_Obj *obj)
            {
            node *temp=new node;
            temp->data=obj;  temp->next=head;
            head=temp;
            };

        Exp_Obj *Pop( void )
            {
            if (head==NULL)
                {
                cout << "Stack Underflow...\n";
                exit(1);
                }
            node *temp=head;
            head=head->next;
            Exp_Obj *tempData=temp->data;
            delete temp;
            return tempData;
            };

        int Empty( void ) { if (head==NULL) return 1; else return 0; }
    };
//------------------------------------------------------------------------------
// Base Expression Object

class Base_Expression : Exp_Obj
    {
    protected:
        Exp_Obj *exp;
        ExpStack exp_stack, op_stack;
        char *exp_str;
        int error_flag;
    public:
        Base_Expression( void ) { exp=NULL; exp_str=NULL; error_flag=VALID;}
        ~Base_Expression( void ) { delete exp; delete exp_str;}
        virtual void GetToken(char *str,int &pos,char *buffer,
                                     int &type, int &error)=0;
        virtual char *GetExp( void ) { return exp_str; }
        virtual int GetType( void ) { return EXPRESSION_TYPE; }
        virtual float GetValue( Symbol_Table &sym )
            { if (!error_flag) return exp->GetValue(sym); else return 0;}
        virtual float GetValue(void)
            {Symbol_Table sym;
             if (!error_flag)return exp->GetValue(sym);else return 0;}
        int GetError( void ) { return error_flag; };
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        virtual void Push_Tree(Exp_Obj *obj)
            {
            if (obj->GetType()==BINARY_OPERATOR_TYPE)
                {
                if (exp_stack.Empty()) error_flag=INVALID;
                else ((Binary_Obj *)obj)->SetRight(exp_stack.Pop());
                if (exp_stack.Empty()) error_flag=INVALID;
                else ((Binary_Obj *)obj)->SetLeft(exp_stack.Pop());
                }
            else if (obj->GetType()==UNARY_OPERATOR_TYPE)
                    if (exp_stack.Empty()) error_flag=INVALID;
                    else ((Unary_Obj *)obj)->SetObj(exp_stack.Pop());
            exp_stack.Push( obj );
            };
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        virtual void Build( Exp_Obj *obj )
            {
            if (obj->GetType()==OPERAND_TYPE || obj->GetType()==EXPRESSION_TYPE)
                Push_Tree(obj);
            else if (obj->GetType()==BINARY_OPERATOR_TYPE ||
                        obj->GetType()==UNARY_OPERATOR_TYPE ||
                        obj->GetType()==OPEN_PAREN_TYPE)
                        {
                        if (op_stack.Empty()) error_flag=INVALID;
                        else
                            {
                            Exp_Obj *temp=op_stack.Pop();
                            int priority1,priority2;
                            if (temp->GetType()==OPEN_PAREN_TYPE) priority1=0;
                            else if (temp->GetType()==CLOSE_PAREN_TYPE) priority1=-1;
                            else priority1=temp->GetPriority();
                            priority2=obj->GetPriority();
                            while (priority1>=priority2)
                                {
                                Push_Tree(temp);
                                if (op_stack.Empty()) error_flag=INVALID;
                                else
                                    {
                                    temp=op_stack.Pop();
                                    if (temp->GetType()==OPEN_PAREN_TYPE) priority1=0;
                                    else if (temp->GetType()==CLOSE_PAREN_TYPE) priority1=-1;
                                    else priority1=temp->GetPriority();
                                    }
                                }
                            op_stack.Push(temp);    op_stack.Push(obj);
                            }
                        }
                else if (obj->GetType()==CLOSE_PAREN_TYPE)
                        {
                        if (op_stack.Empty()) error_flag=INVALID;
                            {
                            Exp_Obj *temp=op_stack.Pop();
                            while (temp->GetType()!=OPEN_PAREN_TYPE)
                                {
                                Push_Tree(temp);
                                if (op_stack.Empty()) {error_flag=INVALID; break;}
                                else temp=op_stack.Pop();
                                }
                            }
                        }
                else if (obj->GetType()==STOP_TYPE)
                        {
                        if (op_stack.Empty()) error_flag=INVALID;
                        else
                            {
                            Exp_Obj *temp=op_stack.Pop();
                            while (temp->GetType()!=START_TYPE)
                                {
                                Push_Tree(temp);
                                if (op_stack.Empty())
                                    { error_flag=INVALID; break; }
                                else temp=op_stack.Pop();
                                }
                            }
                        }
            }
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        virtual Exp_Obj *Build_Expression( char *str )
            {
            op_stack.Push(new Start_Obj);
            Exp_Obj *temp;
            char buffer[256]={""};
            int pos=0, type=START, error=VALID;
            int obj_cnt=0;
            while (type != STOP && error_flag==VALID)
                {
                GetToken(str,pos,buffer,type,error);
                if (error!=VALID) { error_flag=error; break; };
                switch (type)
                      {
                      case LITERAL: Build(new Literal_Obj(atof(buffer)));
                                 break;
                      case STOP:    Build(new Stop_Obj);
                                 break;
                      case BIN_ADD: Build(new Binary_Add_Obj);
                                 break;
                      case BIN_SUB: Build(new Binary_Sub_Obj);
                                 break;
                      case UNARY_SUB: Build(new Unary_Minus);
                                    break;
                      case UNARY_ADD: break;  // do nothing

                      case MUL:       Build(new Mul_Obj);
                                    break;
                      case DIV:       Build(new Div_Obj);
                                    break;
                      case OPEN_PAREN: Build(new Open_Paren_Obj);
                                     break;
                      case CLOSE_PAREN: Build(new Close_Paren_Obj);
                                    break;
                      case RELATIONAL_AND: Build(new And_Obj);
                                        break;
                      case RELATIONAL_OR: Build(new Or_Obj);
                                      break;
                      case EQUAL: Build(new Equal_Obj);
                                 break;
                      case NOT_EQUAL: Build(new Not_Equal_Obj);
                                    break;
                      case GREATER: Build(new Greater_Obj);
                                 break;
                      case GREATER_EQUAL: Build(new Greater_Equal_Obj);
                                      break;
                      case LESS: Build(new Less_Obj);
                                break;
                      case LESS_EQUAL: Build(new Less_Equal_Obj);
                                    break;
                      case NOT: Build(new Not_Obj);
                              break;
                      case VARIABLE: Build(new Variable_Obj( buffer ));
                                  break;
                      default: error=INVALID_TOKEN;
                      }
                obj_cnt++;
                }
            if (exp_stack.Empty()) error_flag=INVALID;
            if (!error_flag) return exp_stack.Pop(); else return NULL;
            }
    };

//------------------------------------------------------------------------------
// clike.h - C-Like Expression Object
//------------------------------------------------------------------------------

#include "express.h"

class C_Like_Expression : public Base_Expression
    {
    public:
    C_Like_Expression( char *str ) : Base_Expression()
        {
        int p_cnt=0;
        for (int i=0; i<strlen(str); i++)
            if (str[i]=='(') p_cnt++; else if (str[i]==')') p_cnt--;
        if (p_cnt) error_flag=MISMATCH_PAREN;
        else
            {
            exp=Build_Expression(str);
            exp_str=new char[strlen(str)+1];
            strcpy(exp_str,str);
            }
        };

    void GetToken(char *str,int &pos,char *buffer,int &type, int &error)
                {
                int last_token=type,buffer_pos=0;
                error=VALID;
                while (isspace(str[pos])) pos++;
                if (str[pos]=='\0') type=STOP;
                else
                    {
                    if (strchr("+-*/&|><=!", str[pos])!=NULL)
                        {
                        switch (str[pos])
                            {
                            case '+': if (last_token==BIN_ADD || last_token==BIN_SUB ||
                                              last_token==UNARY_ADD || last_token==UNARY_SUB ||
                                              last_token==MUL || last_token==DIV ||
                                              last_token==START) type=UNARY_ADD;
                                          else type=BIN_ADD;
                                         break;
                            case '-': if (last_token==BIN_ADD || last_token==BIN_SUB ||
                                              last_token==UNARY_ADD || last_token==UNARY_SUB ||
                                              last_token==MUL || last_token==DIV ||
                                              last_token==START) type=UNARY_SUB;
                                          else type=BIN_SUB;
                                         break;
                            case '*': type=MUL; break;
                            case '/': type=DIV; break;
                            case '&': if (str[pos+1]=='&'){type=RELATIONAL_AND; pos++;}
                                         break;
                            case '|': if (str[pos+1]=='|'){type=RELATIONAL_OR; pos++;}
                                         break;
                            case '>': if (str[pos+1]=='='){type=GREATER_EQUAL; pos++;}
                                         else type=GREATER;
                                         break;
                            case '<': if (str[pos+1]=='='){type=LESS_EQUAL; pos++;}
                                         else type=LESS;
                                         break;
                            case '=': if (str[pos+1]=='='){ type=EQUAL; pos++;    }
                                         break;
                            case '!': if (str[pos+1]=='='){ type=NOT_EQUAL; pos++;}
                                         else type=NOT;
                                         break;
                            }
                        pos++;
                        }
                    else if (isdigit(str[pos]) || str[pos]=='.')
                        {
                        int point_cnt=0;
                        while (isdigit(str[pos]) || str[pos]=='.')
                                {
                                buffer[buffer_pos]=str[pos];
                                if (str[pos]=='.') point_cnt++;
                                buffer_pos++; pos++;
                                }
                        buffer[buffer_pos]='\0';
                        if (point_cnt<=1)    type=LITERAL; else error=INVALID_NUMBER;
                        }
                    else if (isalpha(str[pos]))
                        {
                        while (isalpha(str[pos]) || isdigit(str[pos])|| str[pos]=='_')
                                {
                                buffer[buffer_pos]=str[pos];
                                buffer_pos++; pos++;
                                }
                        buffer[buffer_pos]='\0';
                        type=VARIABLE;
                        }
                    else if (str[pos]=='(')    { type=OPEN_PAREN;  pos++;    }
                    else if (str[pos]==')')    { type=CLOSE_PAREN; pos++; }
                    }
            }
    };

#endif

//------------------------------------------------------------------------------
// paslike.h - Pascal-Like Expression Object
//------------------------------------------------------------------------------

#include "express.h"

class Pascal_Like_Expression : public Base_Expression
    {
    public:
    Pascal_Like_Expression( char *str ) : Base_Expression()
        {
        int p_cnt=0;
        for (int i=0; i<strlen(str); i++)
            if (str[i]=='(') p_cnt++; else if (str[i]==')') p_cnt--;
        if (p_cnt) error_flag=MISMATCH_PAREN;
        else    {
                exp=Build_Expression(str);
                exp_str=new char[strlen(str)+1];
                strcpy(exp_str,str);
                }
        };

    void GetToken(char *str,int &pos,char *buffer,int &type, int &error)
                {
                char buffer1[256];
                int last_token=type,buffer_pos=0;
                error=VALID;
                while (isspace(str[pos])) pos++;
                if (str[pos]=='\0') type=STOP;
                else
                    {
                    if (strchr("+-*/><=", str[pos])!=NULL)
                        {
                        switch (str[pos])
                            {
                            case '+': if (last_token==BIN_ADD || last_token==BIN_SUB ||
                                              last_token==UNARY_ADD || last_token==UNARY_SUB ||
                                              last_token==MUL || last_token==DIV ||
                                              last_token==START) type=UNARY_ADD;
                                          else type=BIN_ADD;
                                         break;
                            case '-': if (last_token==BIN_ADD || last_token==BIN_SUB ||
                                              last_token==UNARY_ADD || last_token==UNARY_SUB ||
                                              last_token==MUL || last_token==DIV ||
                                              last_token==START) type=UNARY_SUB;
                                          else type=BIN_SUB;
                                         break;
                            case '*': type=MUL; break;
                            case '/': type=DIV; break;
                            case '>': if (str[pos+1]=='='){type=GREATER_EQUAL; pos++;}
                                         else type=GREATER;
                                         break;
                            case '<': if (str[pos+1]=='='){ type=LESS_EQUAL; pos++; }
                                         else if (str[pos+1]=='>'){type=NOT_EQUAL; pos++;}
                                         else type=LESS;
                                         break;
                            case '=': type=EQUAL; break;
                            }
                        pos++;
                        }
                    else if (isdigit(str[pos]) || str[pos]=='.')
                        {
                        int point_cnt=0;
                        while (isdigit(str[pos]) || str[pos]=='.')
                                {
                                buffer[buffer_pos]=str[pos];
                                if (str[pos]=='.') point_cnt++;
                                buffer_pos++; pos++;
                                }
                        buffer[buffer_pos]='\0';
                        if (point_cnt<=1)    type=LITERAL; else error=INVALID_NUMBER;
                        }
                    else if (isalpha(str[pos]))
                        {
                        while (isalpha(str[pos]) || isdigit(str[pos]) ||str[pos]=='_')
                                {buffer[buffer_pos]=str[pos]; buffer_pos++; pos++;}
                        buffer[buffer_pos]='\0';
                        strcpy(buffer1,buffer);
                        for (int i=0; i<strlen(buffer1); i++)
                             buffer1[i]=toupper(buffer1[i]);
                        if (strcmp(buffer1,"AND")==0) type=RELATIONAL_AND;
                        else if (strcmp(buffer1,"OR")==0) type=RELATIONAL_OR;
                        else if (strcmp(buffer1,"NOT")==0) type=NOT;
                        else type=VARIABLE;
                        }
                    else if (str[pos]=='(')    { type=OPEN_PAREN;  pos++;    }
                    else if (str[pos]==')')    { type=CLOSE_PAREN; pos++; }
                    }
                }
    };

//------------------------------------------------------------------------------
// eval.cpp - This program uses the C_Like_Expression class to implement
// a simple command line expression evaluator.  Remember to put the expression
// in quotes if it contains symbols that are used by the operating system 
// like > and <.
//-------------------------------------------------------------------------------

#include <stdio.h>
#include <iostream.h>
#include "clike.h"

void main( int argc, char *argv[]  )
    {
    if (argc < 2)
        {
        cout << "Usage: " << argv[0] << " <expression>" << endl;
        exit(0);
        }

    char buffer[256];  // if the command line has spaces in it
    strcpy(buffer,""); // put the pieces back together

    for (int i=1; i<argc; i++)
        {
        strcat(buffer,argv[i]);
        strcat(buffer," ");
        }

    C_Like_Expression exp(buffer);
    if (exp.GetError()) cout << "Error in expression..." << endl;
    else    cout << exp.GetExp() << " => " << exp.GetValue() << endl;

    }


