#if !defined( __PARSE_HPP )
#define __PARSE_HPP

// This block was taken from owldefs.h
#if defined(__cplusplus)
typedef int	    &		Rint;
typedef int	    *		Pint;
typedef void	    *		Pvoid;
typedef void	    *  &	RPvoid;
typedef char	    *		Pchar;
typedef const char  *		PCchar;
typedef const void  *		PCvoid;
#endif


int level;

/*-----------------------------------------------*/
enum PS_state           // Parse & Search States
{
  PS_null,
  PS_have_left_operand,
  PS_search_end,
  PS_search_more,
  PS_search_closed,
  PS_peeking_ahead,
  PS_stop_peeking

};

PS_state result;

extern PS_state search(PS_state);
extern PS_state parse(PS_state);
extern void db_error(int );

enum classType
{
  token_Class,
  BOPH_Class,
  BOPL_Class,
  UOP_Class,
  FOP_Class,
  variable_Class,
  function_Class,
  open_parenthesis_Class,
  closed_parenthesis_Class,
  null_token_Class
};

enum token_types
{
  TT_operand,
  TT_unary_operator,
  TT_binary_operator,
  TT_post_unary,
  TT_parenthesis
};

class token;
token *the_array[100];
token *the_stack[100];
token *function_list[100];
token *variable_list[100];
double numeric_stack[100];
int token_index=0,t1=0,stack_index=0,numeric_stack_index=0;
int number_of_functions, number_of_variables;


//------------------
// The "token" class is the base class for all of the objects.
//
// variables:
//    token_types    
// Member Functions:
//    get_type()     an in-line function that returns the value 

class token 
{
public:
  token_types type;   // Keeps track of the type of the tokens that are derived from this class.
  token_types get_type(void) { return type;}

  virtual classType isA() const { return token_Class; }
  virtual char * nameOf() const { return "token"; }

  //  virtual int isEqual( RCObject Atoken ) const { return 1;}
  //virtual void printOn(Rostream outputStream) const { outputStream << "()"; }
  virtual void printOn() const { cout << "()"; }

  void numeric_push(double v) {numeric_stack[numeric_stack_index++] = v;}
  double numeric_pop(void) { return(numeric_stack[--numeric_stack_index]);}
  virtual void execute(void) { numeric_stack[99] = 99; }
  virtual void push(void)
    {  the_stack[stack_index++] = this;}

  virtual PS_state  a_search(PS_state state)
  {
    push();
    if(state == PS_peeking_ahead)
      return(PS_peeking_ahead);
    else
      return(PS_have_left_operand);
  }

};


class null_token : public token
{
public:
  virtual classType isA() const { return null_token_Class; }
  virtual char * nameOf() const { return "null_token"; }
  //virtual int isEqual( RCObject Anull_token ) const  { return 1; }
  //virtual void printOn(Rostream outputStream) const 
  //  { outputStream << ' '; }
  virtual void printOn() const  { cout << ' '; }


  virtual PS_state  a_search(PS_state state)
  {
      return(PS_search_end);
  }
};


class function : public token
{
public:
  function(void) { type = TT_unary_operator; }
  virtual classType isA() const { return function_Class; }
  virtual char * nameOf() const { return "function"; }
  //virtual int isEqual( RCObject Afunction ) const
  //  { return strcmp(nameOf(), Afunction.nameOf()) == 0; }
  //virtual void printOn(Rostream outputStream) const 
  //  { outputStream << nameOf(); }
  virtual void printOn() const  { cout << nameOf(); }


  virtual PS_state  a_search(PS_state state)
  {
    the_array[t1++]->a_search(PS_null);

    push();
    if(state == PS_peeking_ahead)
      return(PS_peeking_ahead);
    else
      return(PS_have_left_operand);
  }
};


class BOPH : public token
{
public:
  BOPH(void) { type = TT_binary_operator; }
  virtual char get_ASCII(void) const { return ' '; }
  virtual classType isA() const { return BOPH_Class; }
  virtual Pchar nameOf() const { return "BOPH"; }
  //virtual int isEqual( RCObject ABOPH ) const
  //  { return get_ASCII() == ((RBOPH)ABOPH).get_ASCII(); }
  //virtual void printOn(Rostream outputStream) const 
  //  { outputStream << get_ASCII(); }
  virtual void printOn() const  { cout << get_ASCII(); }

  virtual PS_state  a_search(PS_state state)
  {
    result = the_array[t1++]->a_search(state);
    push();
    if(state == PS_peeking_ahead)
      return(PS_peeking_ahead);
    else
      return(result);
  }
};

class UOP : public token
{
public:
  UOP(void) { type = TT_unary_operator; }
  virtual char get_ASCII(void) const { return ' '; }
  virtual classType isA() const { return UOP_Class; }
  virtual char * nameOf() const { return "UOP"; }
  //virtual int isEqual( RCObject AUOP ) const
  //  { return get_ASCII() == ((RUOP)AUOP).get_ASCII(); }
  //virtual void printOn(Rostream outputStream) const 
  //  { outputStream << get_ASCII() << 'U'; }
  virtual void printOn() const  { cout << get_ASCII() << 'U'; }

  virtual PS_state  a_search(PS_state state)
  {
    result = the_array[t1++]->a_search(state);
    push();
    return(result);
  }
};


class BOPL : public token
{
public:
  BOPL(void) { type = TT_binary_operator; }
  virtual char get_ASCII(void) const { return ' '; }
  virtual classType isA() const { return BOPL_Class; }
  virtual char * nameOf() const { return "BOPL"; }
  //virtual int isEqual( RCObject ABOPL ) const
  //  { return get_ASCII() == ((RBOPL)ABOPL).get_ASCII(); }
  //virtual void printOn(Rostream outputStream) const 
  //  { outputStream << get_ASCII(); }
  virtual void printOn() const   { cout << get_ASCII(); }

  virtual PS_state  a_search(PS_state state)
  {
    if(state == PS_have_left_operand)
    {
      do
      {
	result = the_array[t1++]->a_search(PS_peeking_ahead);
      } while(result == PS_peeking_ahead);

      push();
    }
    else if (state == PS_peeking_ahead)
    {
      t1--;
      return(PS_have_left_operand);
    }
    else
    {
      db_error(5);
    }
    return(result);
  }
};

class FOP : public token
{
public:
  double t;
  FOP(double new_t=0) { t = new_t;  type = TT_operand; }
  FOP(char* str);
  virtual classType isA() const { return FOP_Class; }
  virtual char * nameOf() const { return "FOP"; }
  //virtual int isEqual( RCObject AFOP ) const
  //  { return t == ((RFOP)AFOP).t; }
  //virtual void printOn(Rostream outputStream) const 
  //  { outputStream << t; }
  virtual void printOn() const  { cout << t; }

  virtual void execute(void) { numeric_push(t); }
  virtual PS_state  a_search(PS_state state)
  {
    push();
    if(state == PS_peeking_ahead)
      return(PS_peeking_ahead);
    else
      return(PS_have_left_operand);
  }

};


class variable : public token
{
public:
  double value;
  char length;
  char *name_ptr;
  variable(char * new_val_ptr);
  virtual classType isA() const { return variable_Class; }
  virtual char * nameOf() const { return name_ptr; }
  /*  virtual int isEqual( RCObject Avariable ) const
    { if (name_ptr)
	return length == strspn(((Rvariable)Avariable).name_ptr, name_ptr);
      else
	return length == *((Rvariable)Avariable).name_ptr;
    }
  */
  virtual void printOn() const 
    { if (name_ptr)
	cout << name_ptr;
      else
	cout << length;
    }


  virtual PS_state  a_search(PS_state state)
  {
    push();
    if(state == PS_peeking_ahead)
      return(PS_peeking_ahead);
    else
      return(PS_have_left_operand);
  }
  virtual void execute(void) { numeric_push(value); }
};


class open_parenthesis : public token
{
public:
  char p;
  open_parenthesis(char ch) { p = ch; type = TT_parenthesis; }
  virtual classType isA() const { return open_parenthesis_Class; }
  virtual char * nameOf() const { return "open_parenthesis"; }
  /*  virtual int isEqual( RCObject Aopen_parenthesis ) const
    { return p == ((Ropen_parenthesis)Aopen_parenthesis).p; }
  */
  virtual void printOn() const  { cout <<  p; }

  virtual PS_state  a_search(PS_state state)
  {
    level++;
    parse(PS_null);
    if(state == PS_peeking_ahead)
      return(PS_peeking_ahead);
    else
      return(PS_have_left_operand);
  }

};


class closed_parenthesis : public token
{
public:
  char p;
  closed_parenthesis(char ch) { p = ch; type = TT_parenthesis; }
  virtual classType isA() const { return closed_parenthesis_Class; }
  virtual char * nameOf() const { return "closed_parenthesis"; }
  /*  virtual int isEqual( RCObject Aclosed_parenthesis ) const
    { return p == ((Rclosed_parenthesis)Aclosed_parenthesis).p; }
  */
  virtual void printOn() const  { cout <<  p; }

  virtual PS_state  a_search(PS_state state)
  {
    level--;
    if((state != PS_have_left_operand) &&
       (state != PS_peeking_ahead))
          db_error(6);
    return(PS_search_closed);
  }

};

#endif    //  __PARSE_HPP