//
//  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 <stdio.h>
#include "bool.h"
#include "expr.h"


//
//  NAME
//    constant::constant
//
//  DESCRIPTION
//    Constructor for a constant expression.
//

constant::constant(const double n) {
   number = n;
}


//
//  NAME
//    constant::constant
//
//  DESCRIPTION
//    Copy constructor for a constant expression.
//

constant::constant(const constant & c) {
   number = c.number;
}


//
//  NAME
//    ~constant
//
//  DESCRIPTION
//    Destructor for a constant expression.
//

constant::~constant() {
}


//
//  NAME
//    constant::evaluate
//
//  DESCRIPTION
//    This function evaluates the constant expression.
//

double constant::evaluate() const {
   return number;
}


//
//  NAME
//    constant::clone
//
//  DESCRIPTION
//    This function clones the constant expression.
//

expr * constant::clone() const {
   return new constant(*this);
}


//
//  NAME
//     display
//
//  DESCRIPTION
//     This function outputs the constant expression.
//

ostream & constant::display(ostream & os) const {
   return (os << number);
}


//
//  NAME
//    composite::composite
//
//  DESCRIPTION
//    Copy constructor for a composite expression.
//

composite::composite(const composite & c) {
   oper = c.oper;
   op1  = (c.op1)->clone();
   op2  = (c.op2)->clone();
}


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

composite::composite(const operation o, expr * e1, expr * e2) {
   oper = o;
   op1 = e1;
   op2 = e2;
}


//
//  NAME
//    ~composite
//
//  DESCRIPTION
//    Destructor for a composite expression.
//

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


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

double composite::evaluate() const {

   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
//     display
//
//  DESCRIPTION
//     This function outputs the composite expression.
//

ostream & composite::display(ostream & os) const {
   switch (oper) {

      case Addition: {
         os << "(+ ";
         break;
         }

      case Subtraction: {
         os << "(- ";
         break;
         }

      case Multiplication: {
         os << "(* ";
         break;
         }

      case Division: {
         os << "(/ ";
         break;
         }

      }

   op1->display(os);
   os << " ";
   op2->display(os);
   os << ")";

   return os;
}


//
//  NAME
//    composite::clone
//
//  DESCRIPTION
//    This function clones a composite expression.
//

expr * composite::clone() const {
   return new composite(*this);
}


//
//  End of file.
//