//
//  NAME
//    expr.cpp
//
//  DESCRIPTION
//    This file contains functions used to implement the Expression
//    module.
//
//    For descriptions of the parameters and return values of 
//    exported (non-static) functions, see expr.h.
//


//
//  Include files.
//

#include <stdlib.h>
#include <iostream.h>
#include "bool.h"
#include "parse.h"
#include "expr.h"


//
//  NAME
//    expr::expr
//
//  DESCRIPTION
//    Default constructor for an expression.
//

expr::expr() {
   oper   = Constant;
   number = 0.0;
   op1    = NULL;
   op2    = NULL;
}


//
//  NAME
//    expr::expr
//
//  DESCRIPTION
//    Constructor for an expression.
//

expr::expr(const char * str) {
   expr * e = parse(str);
   oper   = e->oper;
   number = e->number;

   if (e->op1 == NULL) {
      op1 = NULL;
      }
   else {
      op1 = new expr(*(e->op1));
      }

   if (e->op2 == NULL) {
      op2 = NULL;
      }
   else {
      op2 = new expr(*(e->op2));
      }

   delete e;
}


//
//  NAME
//    expr::expr
//
//  DESCRIPTION
//    Constructor for an expression.
//

expr::expr(const double n) {
   oper   = Constant;
   number = n;
   op1    = NULL;
   op2    = NULL;
}


//
//  NAME
//    expr::expr
//
//  DESCRIPTION
//    Copy constructor for an expression.
//

expr::expr(const expr & e) {
   oper   = e.oper;
   number = e.number;

   if (e.op1 == NULL) {
      op1 = NULL;
      }
   else {
      op1 = new expr(*(e.op1));
      }

   if (e.op2 == NULL) {
      op2 = NULL;
      }
   else {
      op2 = new expr(*(e.op2));
      }

}


//
//  NAME
//    expr::expr
//
//  DESCRIPTION
//    Constructor for an expression.
//

expr::expr(operation o, const expr & e1, const expr & e2) {
   oper   = o;
   number = 0.0;
   op1    = new expr(e1);
   op2    = new expr(e2);
}


//
//  NAME
//    expr::putOperation
//
//  DESCRIPTION
//    This function sets the operation for the expression.
//

void expr::putOperation(const operation o) {
   oper = o;
}


//
//  NAME
//    expr::getOperation
//
//  DESCRIPTION
//    This function gets the operation of the expression.
//

expr::operation expr::getOperation() {
   return oper;
}


//
//  NAME
//    expr::putNumber
//
//  DESCRIPTION
//    This function sets the constant number for the expression.
//

void expr::putNumber(const double n) {
   number = n;
}


//
//  NAME
//    expr::getNumber
//
//  DESCRIPTION
//    This function gets the constant number of the expression.
//

double expr::getNumber() {
   return number;
}


//
//  NAME
//    expr::putOperand1
//
//  DESCRIPTION
//    This function sets the first operation for the expression.
//

void expr::putOperand1(expr * e) {
   delete op1;
   op1 = e;
}


//
//  NAME
//    expr::getOperand1
//
//  DESCRIPTION
//    This function gets the first operand of the expression.
//

expr * expr::getOperand1() {
   return op1;
}


//
//  NAME
//    expr::putOperand2
//
//  DESCRIPTION
//    This function sets the second operation for the expression.
//

void expr::putOperand2(expr * e) {
   delete op2;
   op2 = e;
}


//
//  NAME
//    expr::getOperand2
//
//  DESCRIPTION
//    This function gets the second operand of the expression.
//

expr * expr::getOperand2() {
   return op2;
}


//
//  NAME
//    expr::evaluate
//
//  DESCRIPTION
//    This function evaluates the expression by first
//    recursively evaluating the subexpressions, then applying
//    the operation to the resulting values.
//

double expr::evaluate() {

   if (oper == Constant) {
      return number;
      }

   switch (oper) {

      case Addition: {
         return op1->evaluate() + op2->evaluate();
         }

      case Subtraction: {
         return op1->evaluate() - op2->evaluate();
         }

      case Multiplication: {
         return op1->evaluate() * op2->evaluate();
         }

      case Division: {
         return op1->evaluate() / op2->evaluate();
         }

      }

   return 0.0;   //  This line should never be reached.
}


//
//  NAME
//    expr::display
//
//  DESCRIPTION
//    This function displays the expression.
//

void expr::display() {

   switch (oper) {

      case Constant : {
         cout << number;
         break;
         }

      case Addition: {
         cout << "(+ ";
         op1->display();
         cout << " ";
         op2->display();
         cout << ")";
         break;
         }

      case Subtraction: {
         cout << "(- ";
         op1->display();
         cout << " ";
         op2->display();
         cout << ")";
         break;
         }

      case Multiplication: {
         cout << "(* ";
         op1->display();
         cout << " ";
         op2->display();
         cout << ")";
         break;
         }

      case Division: {
         cout << "(/ ";
         op1->display();
         cout << " ";
         op2->display();
         cout << ")";
         break;
         }

      }

   return;
}


//
//  NAME
//    ~expr
//
//  DESCRIPTION
//    This destructor frees the memory allocated to the two
//    subexpressions.
//

expr::~expr() {
   delete op1;
   delete op2;
}


//
//  End of file.
//