package dxnCalc; /** * Copyright (C) 1998 Dung X. Nguyen. All rights Reserved. */ public class Calculator { private interface ICalcState { /** * Appends c to the string of digit collected so far. */ public abstract void enterDigit(char c); /** * Performs the pending operation, and set op as the next pending operation * on whatever is computed so far to the operand that will be entered next. */ public abstract void enterOp(IBinOp op); /** * Computes the pending operation. */ public abstract void enterEqual(); }; private int _acc; // accumulated computation private String _display; // current display private IBinOp _pendingOp; // pending operation private final IBinOp _noOp = new IBinOp() { public int compute(int n1, int n2) { return Integer.parseInt(_display); } }; private int _curState; // current state /** * The states do all the work! */ private ICalcState[] _states = { new ICalcState() { // state 0 is start state public void enterDigit(char c) { _display = "" + c; _curState = 1; } public void enterOp(IBinOp op) { try { _acc = _pendingOp.compute(_acc, Integer.parseInt(_display)); _display = "" + _acc; _pendingOp = op; _curState = 2; } catch (Exception e) { _display = e.getMessage(); _curState = 3; }; } public void enterEqual() { // do nothing } }, new ICalcState() { // state 1 is accumulate state public void enterDigit(char c) { _display = _display + c; } public void enterOp(IBinOp op) { try { _acc = _pendingOp.compute(_acc, Integer.parseInt(_display)); _display = "" + _acc; _pendingOp = op; _curState = 2; } catch (Exception e) { _display = e.getMessage(); _curState = 3; }; } public void enterEqual() { try { _acc = _pendingOp.compute(_acc, Integer.parseInt(_display)); _display = "" + _acc; _pendingOp = _noOp; _curState = 2; } catch (Exception e) { _display = e.getMessage(); _curState = 3; }; } }, new ICalcState() { // state 2 is compute state public void enterDigit(char c) { _display = "" + c; _curState = 1; } public void enterOp(IBinOp op) { try { _acc = _pendingOp.compute(_acc, Integer.parseInt(_display)); _display = "" + _acc; _pendingOp = op; } catch (Exception e) { _display = e.getMessage(); _curState = 3; }; } public void enterEqual() { _display = "Syntax Error!"; _curState = 3; } }, new ICalcState() { // state 3 is error state: null-object pattern, does nothing! public void enterDigit(char c) { } public void enterOp(IBinOp op) { } public void enterEqual() { } } }; /** * Inialize this Calculator to the "clear" state. */ public Calculator() { clear(); } /** * @param c '0' <= c <= '9'. * @return accumulated input. */ public final String enterDigit(char c) { _states[_curState].enterDigit(c); return _display; } /** * Perform the pending operation, and prepare to add whatever is computed so * far to the operand that will be entered next and return the resulting String. */ public final String enterOp(IBinOp op) { _states[_curState].enterOp(op); return _display; } /** * Compute the current operation and return the result String. */ public final String enterEqual() { _states[_curState].enterEqual(); return _display; } /** * Set this Calculator to the "clear" state where all internal memories are * set to zero. */ public final String clear() { _acc = 0; _curState = 0; _pendingOp = _noOp; _display = "0"; return _display; } }