package freegraph; /** * Instances of ExpressionItem are used internally by the package. * The base class ExpressionItem's getAction() is used polymorphically * when converting from infix to RPN. The method returns an integer * corresponding to the operation code to perform when converting from * infix to RPN. Each implementation is a simple * class to hold an operator, number, variable, or parenthesis. *
* Although the base class is used polymorphically by ExpressionStack for * conversion to RPN, the various ExpressionItems are downcast when evaluated * by ExpressionEvaluator. *
* This class is used internally by the package. It was exposed as public * so that classes outside of the package can use ExpressionStack, and so * Applets such as ExpressionParsingApplet could be made outside the * package. *
* The algorithm used is from: Tanenbaum, Andrew S. 1990. * Structured Computer Organization, 3rd ed., * New Jersey: Prentice Hall. (pp. 268-272) * @see ExpressionStack * @see ExpressionEvaluator */ public abstract class ExpressionItem { public abstract int getAction(ExpressionItem exprItem); /** * NumberExpressionItem is * an ExpressionItem to represent a literal Number. All numbers are * represented as doubles. */ static public class Number extends ExpressionItem { private double value; public Number(double value) {this.value = value;} public double getNumber() {return value;} public int getAction(ExpressionItem exprItem) {return ExpressionStack.ACTION_INFIX_TO_RPN_STACK;} public String toString() { return "NumberExpressionItem: " + Double.toString(value); } } /** * A VariableExpressionItem is an ExpressionItem used to hold a * single character variable. */ static public class Variable extends ExpressionItem { private char value; public Variable(char value) {this.value = value;} /** * returns the character for this variable */ public char getVariable() {return value;} /** * always moves this to RPN stack. */ public int getAction(ExpressionItem exprItem) {return ExpressionStack.ACTION_INFIX_TO_RPN_STACK;} public String toString() {return "VariableExpressionItem: " + value;} } /** * A Parenthesis is an ExpressionItem used to hold a * single parenthesis. */ static public class Parenthesis extends ExpressionItem { /** * indicats Left parenthesis */ public static final int LEFT = 0; /** * indicats Right parenthesis */ public static final int RIGHT = 1; private int kind; public Parenthesis(int kind) {this.kind = kind;} /** * returns the kind of parenthesis (LEFT or RIGHT) */ public int getKind() {return kind;} /** * If this is a LEFT parenthesis, this is moved to the hold stack; If * it this is a RIGHT the hold stack is moved to the RPN stack, except * if exprItem is a Parenthesis (delete hold stack) or null (error). */ public int getAction(ExpressionItem exprItem) { if (kind == LEFT) return ExpressionStack.ACTION_INFIX_TO_HOLD_STACK; else { //kind == RIGHT if (exprItem == null) return ExpressionStack.ACTION_ERROR; if (exprItem instanceof Parenthesis) return ExpressionStack.ACTION_DELETE_HOLD; return ExpressionStack.ACTION_HOLD_TO_RPN_STACK; } } public String toString() { return "ParenthesisExpressionItem: " + (kind==LEFT?")":"("); } } /** * A BiOperator is an ExpressionItem used to hold a * all binary operators. (Operators with two operands.) The * doOperation() method is used by the ExpressionEvaluator, and * the getOrderOfOperationsLevel() method is used by ExpressionStack. * */ static public class BiOperator extends ExpressionItem { public static final int ADD = 0; public static final int SUBTR = 1; public static final int MULT = 2; public static final int DIV = 3; public static final int POW = 4; public static final int ROOT = 5; public static final String[] OPERATORS = {"+", "-", "*", "/", "^", "~"}; private int kind; public BiOperator(int kind) {this.kind = kind;} int getKind() {return kind;} /** * used by ExpressionEvaluator to perform an the operation on 2 * operands * @param x the right operand * @param y the left operand */ double doOperation(double x, double y) { switch (kind) { case ADD: x = x + y; break; case SUBTR: x = y - x; break; case MULT: x = x * y; break; case DIV: x = y / x; break; case POW: x = Math.pow(y, x); break; case ROOT: x = Math.pow(y, 1/x); break; } return x; } /** * used by ExpressionStack to determine the order of * binary operators */ int getOrderOfOperationsLevel () { switch (kind) { case ADD: case SUBTR: return 1; case MULT: case DIV: return 2; case POW: case ROOT: return 3; } return 0; } /** * If exprItem is null or Parenthesis or if exprItem is a BiOperator * with order of operations less than this, this item is moved to the * hold stack. If exprItem is an UnOperator or a BiOperator with * order of operation greater than or equal to this, the * item on the hold stack is moved to the RPN stack. */ public int getAction(ExpressionItem exprItem) { if (exprItem == null || exprItem instanceof Parenthesis) return ExpressionStack.ACTION_INFIX_TO_HOLD_STACK; else if (exprItem instanceof BiOperator) { BiOperator topOfHold = (BiOperator)exprItem; if (topOfHold.getOrderOfOperationsLevel() < getOrderOfOperationsLevel()) return ExpressionStack.ACTION_INFIX_TO_HOLD_STACK; else return ExpressionStack.ACTION_HOLD_TO_RPN_STACK; } else if (exprItem instanceof UnOperator) return ExpressionStack.ACTION_HOLD_TO_RPN_STACK; else return ExpressionStack.ACTION_ERROR; } public String toString() {return "BiOperatorExpressionItem: " + OPERATORS[kind];} } /** * A UnOperator is an ExpressionItem used to hold a * all unary operators. (Operators with one operand.) The doOperation * method is used by ExpressionEvaluator */ static public class UnOperator extends ExpressionItem { public static final int SIN = 0; public static final int COS = 1; public static final int TAN = 2; public static final int NEG = 3; public static final int SQRT = 4; public static final int SQR = 5; public static final int LOG = 6; public static final int LN = 7; public static final int EXP = 8; public static final int ABS = 9; public static final String[] OPERATORS = {"SIN", "COS", "TAN", "_", "SQRT", "SQR", "LOG", "LN", "EXP", "ABS"}; private int kind; public UnOperator(int kind) {this.kind = kind;} /** * Always moves this to the RPN stack. */ public int getAction(ExpressionItem exprItem) { return ExpressionStack.ACTION_INFIX_TO_HOLD_STACK; } public double doOperation(double x) { switch (kind) { case SIN: x = Math.sin(x); break; case COS: x = Math.cos(x); break; case TAN: x = Math.tan(x); break; case NEG: x = -x; break; case SQRT: x = Math.sqrt(x); break; case SQR: x = x * x; break; case LOG: x = Math.log(x); break; case LN: x = Math.log(x); break; case EXP: x = Math.exp(x); break; case ABS: x = Math.abs(x); } return x; } public String toString() {return "UnOperatorExpressionItem: " + OPERATORS[kind];} } }