Interpreter Pattern: Calculator : Interpretor Pattern « Design Pattern « Java






Interpreter Pattern: Calculator

Interpreter Pattern: Calculator
/*

Software Architecture Design Patterns in Java
by Partha Kuchana 

Auerbach Publications

*/



import java.util.HashMap;
import java.util.Stack;

public class Calculator {
  private String expression;

  private HashMap operators;

  private Context ctx;

  public static void main(String[] args) {
    Calculator calc = new Calculator();
    //instantiate the context
    Context ctx = new Context();

    //set the expression to evaluate
    calc.setExpression("(a+b)*(c-d)");

    //configure the calculator with the
    // Context
    calc.setContext(ctx);

    //Display the result
    System.out.println(" Variable Values: " + "a=" + ctx.getValue("a")
        + ", b=" + ctx.getValue("b") + ", c=" + ctx.getValue("c")
        + ", d=" + ctx.getValue("d"));
    System.out.println(" Expression = (a+b)*(c-d)");
    System.out.println(" Result = " + calc.evaluate());
  }

  public Calculator() {
    operators = new HashMap();
    operators.put("+", "1");
    operators.put("-", "1");
    operators.put("/", "2");
    operators.put("*", "2");
    operators.put("(", "0");
  }

  public void setContext(Context c) {
    ctx = c;
  }

  public void setExpression(String expr) {
    expression = expr;
  }

  public int evaluate() {
    //infix to Postfix
    String pfExpr = infixToPostFix(expression);

    //build the Binary Tree
    Expression rootNode = buildTree(pfExpr);

    //Evaluate the tree
    return rootNode.evaluate(ctx);
  }

  private NonTerminalExpression getNonTerminalExpression(String operation,
      Expression l, Expression r) {
    if (operation.trim().equals("+")) {
      return new AddExpression(l, r);
    }
    if (operation.trim().equals("-")) {
      return new SubtractExpression(l, r);
    }
    if (operation.trim().equals("*")) {
      return new MultiplyExpression(l, r);
    }

    return null;
  }

  private Expression buildTree(String expr) {
    Stack s = new Stack();

    for (int i = 0; i < expr.length(); i++) {
      String currChar = expr.substring(i, i + 1);

      if (isOperator(currChar) == false) {
        Expression e = new TerminalExpression(currChar);
        s.push(e);
      } else {
        Expression r = (Expression) s.pop();
        Expression l = (Expression) s.pop();
        Expression n = getNonTerminalExpression(currChar, l, r);
        s.push(n);
      }
    }//for
    return (Expression) s.pop();
  }

  private String infixToPostFix(String str) {
    Stack s = new Stack();
    String pfExpr = "";
    String tempStr = "";

    String expr = str.trim();
    for (int i = 0; i < str.length(); i++) {

      String currChar = str.substring(i, i + 1);

      if ((isOperator(currChar) == false) && (!currChar.equals("("))
          && (!currChar.equals(")"))) {
        pfExpr = pfExpr + currChar;
      }
      if (currChar.equals("(")) {
        s.push(currChar);
      }
      //for ')' pop all stack contents until '('
      if (currChar.equals(")")) {
        tempStr = (String) s.pop();
        while (!tempStr.equals("(")) {
          pfExpr = pfExpr + tempStr;
          tempStr = (String) s.pop();
        }
        tempStr = "";
      }
      //if the current character is an
      // operator
      if (isOperator(currChar)) {
        if (s.isEmpty() == false) {
          tempStr = (String) s.pop();
          String strVal1 = (String) operators.get(tempStr);
          int val1 = new Integer(strVal1).intValue();
          String strVal2 = (String) operators.get(currChar);
          int val2 = new Integer(strVal2).intValue();

          while ((val1 >= val2)) {
            pfExpr = pfExpr + tempStr;
            val1 = -100;
            if (s.isEmpty() == false) {
              tempStr = (String) s.pop();
              strVal1 = (String) operators.get(tempStr);
              val1 = new Integer(strVal1).intValue();

            }
          }
          if ((val1 < val2) && (val1 != -100))
            s.push(tempStr);
        }
        s.push(currChar);
      }//if

    }// for
    while (s.isEmpty() == false) {
      tempStr = (String) s.pop();
      pfExpr = pfExpr + tempStr;
    }
    return pfExpr;
  }

  private boolean isOperator(String str) {
    if ((str.equals("+")) || (str.equals("-")) || (str.equals("*"))
        || (str.equals("/")))
      return true;
    return false;
  }
} // End of class

class Context {
  private HashMap varList = new HashMap();

  public void assign(String var, int value) {
    varList.put(var, new Integer(value));
  }

  public int getValue(String var) {
    Integer objInt = (Integer) varList.get(var);
    return objInt.intValue();
  }

  public Context() {
    initialize();
  }

  //Values are hardcoded to keep the example simple
  private void initialize() {
    assign("a", 20);
    assign("b", 40);
    assign("c", 30);
    assign("d", 10);
  }

}

class TerminalExpression implements Expression {
  private String var;

  public TerminalExpression(String v) {
    var = v;
  }

  public int evaluate(Context c) {
    return c.getValue(var);
  }
}

interface Expression {
  public int evaluate(Context c);
}

abstract class NonTerminalExpression implements Expression {
  private Expression leftNode;

  private Expression rightNode;

  public NonTerminalExpression(Expression l, Expression r) {
    setLeftNode(l);
    setRightNode(r);
  }

  public void setLeftNode(Expression node) {
    leftNode = node;
  }

  public void setRightNode(Expression node) {
    rightNode = node;
  }

  public Expression getLeftNode() {
    return leftNode;
  }

  public Expression getRightNode() {
    return rightNode;
  }
}// NonTerminalExpression

class AddExpression extends NonTerminalExpression {
  public int evaluate(Context c) {
    return getLeftNode().evaluate(c) + getRightNode().evaluate(c);
  }

  public AddExpression(Expression l, Expression r) {
    super(l, r);
  }
}// AddExpression

class SubtractExpression extends NonTerminalExpression {
  public int evaluate(Context c) {
    return getLeftNode().evaluate(c) - getRightNode().evaluate(c);
  }

  public SubtractExpression(Expression l, Expression r) {
    super(l, r);
  }
}// SubtractExpression

class MultiplyExpression extends NonTerminalExpression {
  public int evaluate(Context c) {
    return getLeftNode().evaluate(c) * getRightNode().evaluate(c);
  }

  public MultiplyExpression(Expression l, Expression r) {
    super(l, r);
  }

}// MultiplyExpression


//File: Interprepter.properties
/*
a=10
b=20
c=30
d=40

*/


           
       








Related examples in the same category

1.Interpreter pattern in JavaInterpreter pattern in Java
2.Interpreter Pattern 2