001package edu.pdx.cs410J.whitlock; 002 003import com.google.common.annotations.VisibleForTesting; 004 005import java.util.ArrayList; 006import java.util.List; 007import java.util.Stack; 008import java.util.function.BinaryOperator; 009 010/** 011 * This class is represents a <code>Student</code>. 012 */ 013public class RPNCalculator { 014 015 @VisibleForTesting 016 List<Object> parseExpression(String expression) { 017 List<Object> list = new ArrayList<>(); 018 019 if (expression.equals("")) { 020 return list; 021 } 022 023 for (String token : expression.split(" ")) { 024 list.add(parseToken(token)); 025 } 026 027 return list; 028 } 029 030 private Object parseToken(String token) { 031 Object value; 032 033 switch (token) { 034 case "+": 035 return Operation.ADDITION; 036 037 case "-": 038 return Operation.SUBTRACT; 039 040 case "*": 041 return Operation.MULTIPLY; 042 043 case "/": 044 return Operation.DIVIDE; 045 } 046 047 try { 048 value = Integer.parseInt(token); 049 } catch (NumberFormatException ex) { 050 throw new InvalidRPNExpressionException("Invalid expression: " + token); 051 } 052 return value; 053 } 054 055 int evaluate(String expression) { 056 List lexemes = parseExpression(expression); 057 if (lexemes.isEmpty()) { 058 return 0; 059 } 060 061 Stack<Object> stack = new Stack<>(); 062 063 for (Object lexeme : lexemes) { 064 if (lexeme instanceof Integer) { 065 stack.push(lexeme); 066 067 } else if (lexeme instanceof Operation) { 068 Operation operation = (Operation) lexeme; 069 int right = popInt(stack); 070 int left = popInt(stack); 071 int result = operation.evaluate(left, right); 072 stack.push(result); 073 } 074 } 075 076 return (Integer) stack.pop(); 077 } 078 079 private int popInt(Stack stack) { 080 return (Integer) stack.pop(); 081 } 082 083 public static void main(String[] args) { 084 System.err.println("Missing command line arguments"); 085 System.exit(1); 086 } 087 088 enum Operation { 089 SUBTRACT((l, r) -> l - r), 090 MULTIPLY((l, r) -> l * r), 091 DIVIDE((l, r) -> l / r), 092 ADDITION((l, r) -> l + r); 093 094 private final BinaryOperator<Integer> operation; 095 096 Operation(BinaryOperator<Integer> operation) { 097 this.operation = operation; 098 } 099 100 public int evaluate(int left, int right) { 101 return this.operation.apply(left, right); 102 } 103 } 104}