title: Java calculator crashing with input of parentheses
body: <p>Help me stackoverflow, you're my only hope. I have been trying to make a simple calculator, and finally I've gotten it to WORK! The problem is that only simply expressions are evaluated. For example: 4*5 would give 20.0. (Awesome!)</p>
  
  <p>Whenever I give it a more complicated expression like 4*(2+3), the program crashes due to an EmptyStackException. I understand the exception, but I am unable to recreate the problem in my mind when I run through the code manually with my brain and a sheet of paper.</p>
  
  <p>Can anyone figure out why it's crashing? Here is the full code. I marked where the code crashes with some bold, all-caps words. (i.e. PROGRAM CRASHES HERE)</p>
  
  <pre><code>/**
   * Human
   * Project 3: SUPER-DUPER JAVA CALCULATOR
   */
  
  import java.util.*;
  import java.util.Stack;
  import java.lang.String;
  import java.util.ArrayList;
  import java.lang.StringBuilder;
  import java.util.HashSet;
  import java.lang.Exception;
  import java.lang.Math;
  
  public class InfixEvaluator {
  
      public static class SyntaxErrorException extends Exception {
          /**
           * Construct a SyntaxErrorException with the specified message.
           *
           * @param message The message
           */
          SyntaxErrorException(String message) {
              super(message);
          }
      }
  
      /**
       * This is the stack of operands:
       * i.e. (doubles/parentheses/brackets/curly braces)
       */
      private static Stack&lt;Double&gt; operandStack = new Stack&lt;Double&gt;();
  
      /**
       * This is the operator stack
       * i.e. (+-/*%^)
       */
      private static Stack&lt;String&gt; operatorStack = new Stack&lt;String&gt;();
  
      /**
       * These are the possible operators
       */
      private static final String OPERATORS = "+-/*%^()[]{}";
      private static final String BRACES = "()[]{}";
      private static final String NONBRACES = "+-/*%^";
      private static final int[] PRECEDENCE = {1, 1, 2, 2, 2, -1, -1, -1, -1, -1, -1};
      /**
       * This is an ArrayList of all the discrete
       * things (operators/operands) making up an input.
       * This is really just getting rid of the spaces,
       * and dividing up the "stuff" into manageable pieces.
       */
      static ArrayList&lt;String&gt; input = new ArrayList&lt;String&gt;();
  
      public static ArrayList inputCleaner(String postfix) {
          StringBuilder sb = new StringBuilder();
          String noSpaces = postfix.replace(" ", "");
          try {
              for (int i = 0; i &lt; noSpaces.length(); i++) {
                  char c = noSpaces.charAt(i);
                  boolean isNum = (c &gt;= '0' &amp;&amp; c &lt;= '9');
  
                  if (isNum) {
                      sb.append(c);
                      if (i == noSpaces.length() - 1) {
                          input.add(sb.toString());
                          sb.delete(0, sb.length());
                      }
                  } else if (c == '.') {
                      for (int j = 0; j &lt; sb.length(); j++) {
                          if (sb.charAt(j) == '.') {
                              throw new SyntaxErrorException("You can't have two decimals in a number.");
                          } else if (j == sb.length() - 1) {
                              sb.append(c);
                              j = (sb.length() + 1);
                          }
                      }
                      if (sb.length() == 0) {
                          sb.append(c);
                      }
                      if (i == noSpaces.length() - 1) {
                          throw new SyntaxErrorException("You can't end your equation with a decimal!");
                      }
                  } else if (OPERATORS.indexOf(c) != -1) {
                      if (sb.length() != 0) {
                          input.add(sb.toString());
                          sb.delete(0, sb.length());
                      }
                      sb.append(c);
                      input.add(sb.toString());
                      sb.delete(0, sb.length());
                  } else {
                      throw new SyntaxErrorException("Make sure your input only contains numbers, operators, or parantheses/brackets/braces.");
                  }
              }
  
              int numLP = 0;
              int numRP = 0;
              int numLB = 0;
              int numRB = 0;
              int numLBr = 0;
              int numRBr = 0;
  
              for (int f = 0; f &lt; input.size(); f++) {
                  String trololol = input.get(f);
  
                  switch (trololol) {
                      case "(":
                          numLP++;
                          break;
                      case "[":
                          numLB++;
                          break;
                      case "{":
                          numLBr++;
                          break;
                      case ")":
                          numRP++;
                          break;
                      case "]":
                          numRB++;
                          break;
                      case "}":
                          numRBr++;
                          break;
                      default: //do nothing
                          break;
                  }
  
              }
              if (numLP != numRP || numLB != numRB || numLBr != numRBr) {
                  throw new SyntaxErrorException("The number of brackets, braces, or parentheses don't match up!");
              }
  
              int doop = 0;
              int scoop = 0;
              int foop = 0;
              for (int f = 0; f &lt; input.size(); f++) {
                  String awesome = input.get(f);
                  switch (awesome) {
                      case "(":
                          doop++;
                          break;
                      case "[":
                          scoop++;
                          break;
                      case "{":
                          foop++;
                          break;
                      case ")":
                          doop--;
                          break;
                      case "]":
                          scoop--;
                          break;
                      case "}":
                          foop--;
                          break;
                      default: //do nothing
                          break;
                  }
                  if (doop &lt; 0 || scoop &lt; 0 || foop &lt; 0) {
                      throw new SyntaxErrorException("The order of your parentheses, brackets, or braces is off.\nMake sure you open a set of parenthesis/brackets/braces before you close them.");
                  }
              }
              if (NONBRACES.indexOf(input.get(input.size() - 1)) != -1) {
                  throw new SyntaxErrorException("The input can't end in an operator");
              }
              return input;
          } catch (SyntaxErrorException ex) {
              System.out.println(ex);
              return input;
          }
      }
  
      /**
       * Method to process operators
       *
       * @param op The operator
       * @throws EmptyStackException
       */
      private static void processOperator(String op) {
          if (operatorStack.empty() || op == "(" || op == "[" || op == "{") {
              operatorStack.push(op);
          } else {
              //peek the operator stack and
              //let topOp be the top operator.
              String topOp = operatorStack.peek();
              if (precedence(op) &gt; precedence(topOp)) {
                  operatorStack.push(op);
              } else {
                  //Pop all stacked operators with equal
                  // or higher precedence than op.
                  while (!operatorStack.empty() &amp;&amp; precedence(op) &lt;= precedence(topOp)) {
                      double r = operandStack.pop();
                      double l = operandStack.pop();
                      String work = operatorStack.pop();
                      switch (work) {
                          case "+":
                              operandStack.push(l + r);
                              break;
                          case "-":
                              operandStack.push(l - r);
                              break;
                          case "*":
                              operandStack.push(l * r);
                              break;
                          case "/":
                              operandStack.push(l / r);
                              break;
                          case "%":
                              operandStack.push(l % r);
                              break;
                          case "^":
                              operandStack.push(Math.pow(l, r));
                              break;
                          default: //do nothing, but this should never happen
                              break;
                      }
  
                      if (topOp == "(" || topOp == "[" || topOp == "{") {
                          //matching '(' popped - exit loop.
                          operandStack.push(l);
                          operandStack.push(r);
                          break;
                      }
  
                      if (!operatorStack.empty()) {
                          //reset topOp
                          topOp = operatorStack.peek();
                      }
                  }
  
                  //assert: Operator stack is empty or
                  // current operator precedence &gt; top of stack operator precedence.
                  if (op != ")" || op != "]" || op != "}") {
                      operatorStack.push(op);
                  }
              }
          }
      }
  
      public static String infixCalculator(ArrayList&lt;String&gt; puke) {
          int p;
          for (p = 0; p &lt; puke.size(); p++) {
              if (OPERATORS.indexOf(puke.get(p)) == -1) {
                  double herp = Double.parseDouble(puke.get(p));
                  operandStack.push(herp);
              } else {
                  processOperator(puke.get(p));
              }
          }
          if (p == puke.size()) {
              while (!operatorStack.empty()) {
                  double r = operandStack.pop();
                  double l = operandStack.pop();
                  String work = operatorStack.pop();
                  switch (work) {
                      case "+":
                          operandStack.push(l + r);
                          break;
                      case "-":
                          operandStack.push(l - r);
                          break;
                      case "*":
                          operandStack.push(l * r);
                          break;
                      case "/":
                          operandStack.push(l / r);
                          break;
                      case "%":
                          operandStack.push(l % r);
                          break;
                      case "^":
                          operandStack.push(Math.pow(l, r));
                          break;
                      default:
                          break;
                  }
              }
          }
          return String.valueOf(operandStack.pop());
      }
  
      private static int precedence(String op) {
          return PRECEDENCE[OPERATORS.indexOf(op)];
      }
  
      public static void main(String[] args) {
  
          do {
              try {
                  ArrayList test = new ArrayList();
                  Scanner f = new Scanner(System.in);
  
  
                  System.out.println("Please insert an argument: \n");
  
  
                  String g = f.nextLine();
  
                  test = inputCleaner(g);
  
                  for (int z = 0; z &lt; test.size(); z++) {
                      System.out.println(test.get(z));
                  }
  
                  System.out.println(infixCalculator(test));
  
                  test.clear();
              } catch (EmptyStackException e) {
                  System.out.println("Make sure you only put in operators and operands.");
              }
          } while (true);
      }
  }
  </code></pre>
  
  <p>Stack trace:</p>
  
  <pre><code>java.util.EmptyStackException at 
      java.util.Stack.peek(Stack.java:102) at
      java.util.Stack.pop(Stack.java:84) at 
      InfixEvaluator.processOperator(InfixEvaluator.java:177) at 
      InfixEvaluator.infixCalculator(InfixEvaluator.java:225) at 
      InfixEvaluator.main(InfixEvaluator.java:276) 
  </code></pre>