import java.util.Stack;
import java.util.Scanner;
/**
* Main driver class for the Postfix Expression Evaluator.
*/
public class PostfixTester {
public static void main(String[] args) {
// Use try-with-resources to ensure the Scanner is closed automatically
try (Scanner in = new Scanner(System.in)) {
String again;
System.out.println("========================================");
System.out.println(" Postfix Expression Evaluator Pro");
System.out.println("========================================");
do {
PostfixEvaluator evaluator = new PostfixEvaluator();
System.out.println("\nEnter a valid postfix expression (Supports: + - * / ^ %):");
System.out.println("Example: 5 4 + 3 2 ^ * (Calculates (5+4)*(3^2))");
System.out.print("> ");
String expression = in.nextLine();
try {
int result = evaluator.evaluate(expression);
System.out.println("----------------------------------------");
System.out.println("Calculation Successful!");
System.out.println("Result: " + result);
System.out.println("----------------------------------------");
} catch (Exception e) {
System.err.println("Error: Invalid expression or calculation fault (" + e.getMessage() + ")");
}
System.out.print("Evaluate another expression [Y/N]? ");
again = in.nextLine();
} while (again.equalsIgnoreCase("y"));
System.out.println("\nProgram terminated. Thank you!");
}
}
}
/**
* Handles the logic of evaluating postfix mathematical expressions using a
* Stack.
*/
class PostfixEvaluator {
private final static char ADD = '+', SUBTRACT = '-', MULTIPLY = '*', DIVIDE = '/', EXP = '^', MOD = '%';
// Using Generics Stack<Integer> to ensure type safety
private Stack<Integer> stack = new Stack<>();
/**
* Parses the string and performs stack-based evaluation.
*/
public int evaluate(String expr) {
// Nested try-with-resources for the string parser
try (Scanner parser = new Scanner(expr)) {
while (parser.hasNext()) {
String token = parser.next();
if (isOperator(token)) {
// Pop order: op2 is the second operand, op1 is the first
int op2 = stack.pop();
int op1 = stack.pop();
stack.push(evaluateSingleOperator(token.charAt(0), op1, op2));
} else {
// Parse numeric tokens and push onto the stack
stack.push(Integer.parseInt(token));
}
}
}
// The final remaining value on the stack is the result
return stack.pop();
}
private boolean isOperator(String token) {
return (token.equals("+") || token.equals("-") || token.equals("*") ||
token.equals("/") || token.equals("^") || token.equals("%"));
}
/**
* Performs the specific arithmetic operation based on the operator.
* Uses the modern Switch Expression with '->', blocks '{}', and 'yield'.
*/
private int evaluateSingleOperator(char operation, int op1, int op2) {
return switch (operation) {
case ADD -> {
yield op1 + op2;
}
case SUBTRACT -> {
yield op1 - op2;
}
case MULTIPLY -> {
yield op1 * op2;
}
case DIVIDE -> {
if (op2 == 0)
throw new ArithmeticException("Division by zero");
yield op1 / op2;
}
case EXP -> {
// Calculate power and cast back to int
yield (int) Math.pow(op1, op2);
}
case MOD -> {
if (op2 == 0)
throw new ArithmeticException("Modulo by zero");
yield op1 % op2;
}
default -> {
throw new IllegalArgumentException("Unexpected operator: " + operation);
}
};
}
}