// CS 509 - Advanced Programming II
// Spring 2004
//
// An example interpreter-pattern use.

#include <iostream>

typedef double result_type;

class expression {

  public:

    virtual result_type evaluate() const = 0;
  };


class nilary_expression : public expression {
  };


class unary_expression : public expression {
  protected:
    expression * operand;
  };


class binary_expression : public expression {
  protected:
    expression * left, * right;
  };


class constant : public nilary_expression {
  public:

    constant(result_type v) : value(v) { }

    result_type evaluate() const {
      return value;
      }

  private:
    result_type value;
  };


class variable : public nilary_expression {
  public:

    variable(result_type & v) : var(v) { }

    result_type evaluate() const {
      return var;
      }

  private:
    result_type & var;
  };


class negate : public unary_expression {

  public:

    negate(expression * e) {
      operand = e;
      }

    result_type evaluate() const {
      return ! operand->evaluate();
      }
  };


class or_else : public binary_expression {

  public:

    or_else(expression * const l, expression * const r) {
      left = l;
      right = r;
      }

    result_type evaluate() const {
      return left->evaluate() || right->evaluate();
      }
  };


class less : public binary_expression {

  public:

    less(expression * const l, expression * const r) {
      left = l;
      right = r;
      }

    result_type evaluate() const {
      return left->evaluate() < right->evaluate();
      }
  };


int main() {
  double t = 102.3;
  expression * ep = 
    new or_else(
     new less (
       new variable(t),
       new constant(97.6)
       ),
     new less (
       new constant(99.6),
       new variable(t)
       )
     );

  std::cout << t << " is " << (ep->evaluate() ? "abnormal" : "normal") << "\n";
  }

// $Log: ip1.cc,v $
// Revision 1.1  2004/05/06 19:43:17  rclayton
// Initial revision
//


syntax highlighted by Code2HTML, v. 0.9