Calculator Assignment Instructions

You are implementing a 4-function calculator. Think of a simple casio or basic calculator app. The display shows the current number you are typing, or an intermediate calculation result. It does not display any operands or other info, except the occasional “error” when appropriate. The skeleton of the program is given to you; you will update the controller and model to add functionality. First you will implement simple left-to-right evaluation using two stacks. Second you will implement operator precedence. Finally you will add extensions of your choice.

Overview of Architecture

This calculator application follows the Model-View-Controller (MVC) design pattern:

  1. Model (CalculatorModel.java): Manages the data and calculation logic, including operand and operator stacks.
  2. View (CalculatorUI.java): Handles the user interface elements including display and buttons.
  3. Controller (CalculatorController.java): Processes user input and coordinates between the model and view.
  4. Main Application (Calculator.java): Entry point that initializes the MVC components.

Supporting classes include: - Operator.java: Constants for calculator operations - DebugStack.java: Extended Stack implementation for debugging

Calculator Interface

Operand and Operator Stacks

The calculator uses two stacks to manage calculations: - Operand Stack: Stores numeric values (operands) for calculations - Operator Stack: Stores operators (+, -, ×, ÷, etc.)

These stacks allow for sequential processing of operations. When operations are performed, values are popped from the stacks, calculations are made, and results are pushed back.

Methods to Complete

In CalculatorController.java:

  1. handleClear(): Reset the calculator state, clear display and stacks.
  2. handleBackspace(): Remove the last character from the display.

In CalculatorModel.java:

  1. appendDecimalPoint(): Add a decimal point to the current display value if not already present.
  2. backspace(): Remove the last character from the display value.
  3. calculate(): Perform one calculation using operands and operators from the stacks.
  4. reduce(String operator): Calls calculate one or more times based on the current stack contents (in phase 1 this is basically a pass-through function, you always call calculate exactly once)
  5. precedence(String operator): Return the precedence level of an operator (for Phase 2).

In DebugStack.java:

Extend the Stack class to print stack contents after push, pop, and clear operations. For example:

@Override
public E push(E item) {
    E result = super.push(item);
    System.out.println("Push: " + item + ", Stack: " + this);
    return result;
}

Implementation Phases

Phase 1: Basic Functionality

Phase 2: Operator Precedence

Phase 3: Extensions (Pick one or more)

Notes

Example: Calculating a Left-to-Right Expression Using Two Stacks

Here’s a simple example of how to calculate the expression 3 + 425 × 2 using the two-stack approach with left-to-right evaluation (Phase 1 approach without operator precedence):

Initial State:

User enters “3”:

User enters “+”:

User enters “4”:

User enters “2”:

User enters “5”:

User enters “×”:

User enters “2”:

User enters “=”:

Note: In Phase 1, operations are performed strictly left-to-right as shown above (3 + 4 × 2 = 14). In Phase 2 with operator precedence, multiplication would be performed before addition, resulting in 3 + (4 × 2) = 11.