1

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!)

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.

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)

/**
 * 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<Double> operandStack = new Stack<Double>();

    /**
     * This is the operator stack
     * i.e. (+-/*%^)
     */
    private static Stack<String> operatorStack = new Stack<String>();

    /**
     * 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<String> input = new ArrayList<String>();

    public static ArrayList inputCleaner(String postfix) {
        StringBuilder sb = new StringBuilder();
        String noSpaces = postfix.replace(" ", "");
        try {
            for (int i = 0; i < noSpaces.length(); i++) {
                char c = noSpaces.charAt(i);
                boolean isNum = (c >= '0' && c <= '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 < 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 < 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 < 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 < 0 || scoop < 0 || foop < 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) > precedence(topOp)) {
                operatorStack.push(op);
            } else {
                //Pop all stacked operators with equal
                // or higher precedence than op.
                while (!operatorStack.empty() && precedence(op) <= 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 > top of stack operator precedence.
                if (op != ")" || op != "]" || op != "}") {
                    operatorStack.push(op);
                }
            }
        }
    }

    public static String infixCalculator(ArrayList<String> puke) {
        int p;
        for (p = 0; p < 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 < 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);
    }
}

Stack trace:

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) 
FelixTheNub
  • 181
  • 2
  • 10
  • 7
    You should get out of the habit of using stupid variable names. Use descriptive names. – Blorgbeard May 06 '14 at 04:06
  • There was a slight error with the code, but I just fixed it. Simple expressions should work again. I am sorry about the names, but I wasn't planning on having anyone look at it. Still, like you said, it's a habit that may bleed into my future work, so I'll try to reign it in. – FelixTheNub May 06 '14 at 04:14
  • Any Stack traces yet ? – Sanjeev May 06 '14 at 04:15
  • Not a solution to your problem but there is a great algorithm for evaluating arithmetic called the Shunting yard algorithm. Heres a link http://en.wikipedia.org/wiki/Shunting-yard_algorithm you might find it interesting. – ug_ May 06 '14 at 04:19
  • I'm not clear on what exactly a stack trace is, but I copied the error. 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) – FelixTheNub May 06 '14 at 04:20
  • 2
    Yup - that's a stack trace allright. And I agree with Blorgbeard: I doubt your instructor (or anybody older than a 7th grader) will be impressed by variable names like "poop" and "doody". IMHO... – FoggyDay May 06 '14 at 04:24
  • Like I said, I didn't plan on showing it off. – FelixTheNub May 06 '14 at 04:26
  • 1
    @FelixTheNub, "I wasn't planning on having anyone look at it." The truth is, using an IDE to do a simple variable rename would have taken you 5 seconds. – ryvantage May 06 '14 at 04:26
  • 1
    Also, @Blorgbeard's main point was not your naming conventions _for our sake_. **You**, for your own sake, for God's sake, should learn to use meaningful variable names. – ryvantage May 06 '14 at 04:28
  • There guys, I changed the names to be descriptive. – FelixTheNub May 06 '14 at 04:53

2 Answers2

4

Your error comes from poping an element off the stack when the stack is empty. Hence the name EmptyStackException.

I noticed in your loops you say something like while(!operatorStack.empty()) but then inside the while loop you pop 2 or sometimes 3 elements off the stack. If you want to pop more elements off an array than one you should test for that in your while loop.

So if you pop 2 elements off then do while (operatorStack.size() > 2 ). I edited your code changing all your while loops to be correct and it worked fine for these inputs

(2+3) and (2+3)+5

Here is what I did:

  • Moved boilerplate code into new methods
  • Added method signatures comments
  • Fixed your operator precedence, pow operator had the wrong precedence.
  • Changed String comparison in a bunch of places from str1 == str2 to str1.equals(str2). You should look at How do I compare strings in Java? to see why I did that.
  • Added in System.out.println statements to debug your application. I left them in so you can see the output and check it for yourself. You should look through and see what I did to help you debug in the future.

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<Double> operandStack = new Stack<Double>();

    /** This is the operator stack
     *  i.e. (+-/*%^)
     */
    private static Stack<String> operatorStack = new Stack<String>();

    /** 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, 3, 3, -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<String> input = new ArrayList<String>();

    /**
     * TODO: write this
     * @param postfix
     * @return
     */
    public static ArrayList inputCleaner(String postfix){
      StringBuilder sb = new StringBuilder();
      String noSpaces = postfix.replace(" ", "");
      try {
        for (int i = 0; i < noSpaces.length(); i++) {
            char c = noSpaces.charAt(i);
            boolean isNum = (c >= '0' && c <= '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 < 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 < input.size(); f++) {
            switch (input.get(f)) {
                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 < 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 < 0 || scoop < 0 || foop < 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 SyntaxErrorException 
     * @throws EmptyStackException
     */
    private static void processOperator(String op) throws SyntaxErrorException {
        if (operatorStack.empty() || op.equals("(") || op.equals("[") || op.equals("{")) {
            operatorStack.push(op);
        } else {
            //peek the operator stack and
            //let topOp be the top operator.
            String topOp = operatorStack.peek();
            if (precedence(op) > precedence(topOp)) {
                topOp = op;
                operatorStack.push(op);
            } else {
                System.out.println(operatorStack);
                System.out.println(operandStack);
                System.out.println("--------------");
                //Pop all stacked operators with equal
                // or higher precedence than op.
                while (operandStack.size() >= 2 && !operatorStack.isEmpty()) {
                    double r = operandStack.pop();
                    double l = operandStack.pop();
                    String work = getNextNonBracerOperator();
                    System.out.println("L:" + l + " R:" + r + " W:" + work);

                    doOperandWork(work, l, r);

                    if(op.equals("(") || op.equals("[") || op.equals("{")) {
                        //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 > top of stack operator precedence.
                if(!op.equals(")") || !op.equals("}") || !op.equals("}")) {
                    operatorStack.push(op);
                }
            }
        }
    }

    /**
     * TODO: write this
     * @param expressions
     * @return
     * @throws SyntaxErrorException
     */
    public static String infixCalculator(ArrayList<String> expressions) throws SyntaxErrorException {
        for (String expression : expressions) {
            if (OPERATORS.indexOf(expression) == -1) {
                operandStack.push(Double.parseDouble(expression));
            } else {
                processOperator(expression);
            } 
        } 
        while (operandStack.size() >= 2 && !operatorStack.isEmpty()) {
            System.out.println("--------------");
            System.out.println(operandStack);
            System.out.println(operatorStack);

            double r = operandStack.pop();
            double l = operandStack.pop();
            String work = getNextNonBracerOperator();
            System.out.println("L:" + l + " R:" + r + " W:" + work);

            doOperandWork(work, l, r);
        }
        if(operandStack.isEmpty())
            return null;
        return String.valueOf(operandStack.pop());
    }

    /**
     * goes through the stack and pops off all non operatable operations until it gets to one that is in the NONBRACES String
     * @return The next operatable string
     */
    private static String getNextNonBracerOperator() {
        String work = "\0"; // \0 is null, 
        while(!operatorStack.isEmpty() && NONBRACES.indexOf(work) == -1)
            work = operatorStack.pop();
        return work;
    }

    /**
     * 
     * @param work The operator you want to work. This really should be a character but its still a string
     * @param l Left side number
     * @param r Right side number
     * @throws SyntaxErrorException If the operator could not be found
     */
    private static void doOperandWork(String work, double l, double r) throws SyntaxErrorException {
        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: 
                throw new SyntaxErrorException("Invalid operand " + work);
        }
    }

    /**
     * @param op The operator
     * @return the precedence
     */
    private static int precedence(String op) {
        return PRECEDENCE[OPERATORS.indexOf(op)];
    }

    public static void main(String[] args) {
        try {
            ArrayList test = new ArrayList();
            Scanner f = new Scanner(System.in);

            //System.out.println("Please insert an argument: ");

            //String g = f.nextLine();
            //String g = "(1+1)^(3+1)";
            String g = "(1+3)*3^2+2*4-1";
            test = inputCleaner(g);

            for (int z = 0; z < test.size(); z++) {
                System.out.println(test.get(z));
            }

            System.out.println(infixCalculator(test));

            test.clear();
       } catch (SyntaxErrorException e) {
            System.out.println("Make sure you only put in operators and operands.");
            e.printStackTrace();
       }
    }
}
Community
  • 1
  • 1
ug_
  • 11,267
  • 2
  • 35
  • 52
  • I tried your modification but the program won't even compile. Could you go into more detail on how you changed it? – FelixTheNub May 06 '14 at 04:38
  • I got it to compile, sorry I meant to say it's crashing. – FelixTheNub May 06 '14 at 04:42
  • @FelixTheNub The problem is that you have a loop where your going until its empty. How if inside the loop you remove 2 from the loop but theres say only 1 left the 2nd `pop` call you make will cause an `EmptyStackException`. You likely have an bug somewhere else that is adding in something it should be but because you have non descript variable names I don't really wanna try looking into it. EDIT: you also have lots of string comparison using `==`. You should be using `.equals`. – ug_ May 06 '14 at 04:45
  • @FelixTheNub Nope it worked for those inputs I placed in and mentioned in my answer.... however I guarantee that it doesnt work for more complex equations. That part is for you to debug and work out. – ug_ May 06 '14 at 05:23
  • @FelixTheNub I updated my answer, it is working but you should definitely look through the code and especially look at the println statements and take something away from it. – ug_ May 06 '14 at 06:35
1

You are trying to compare a String with ==. Instead use String.equals(String)

if(!op.equals(")") || !op.equals("]") || !op.equals("}")) {
   operatorStack.push(op);
}

...

if (operatorStack.empty() || op.equals("(") || op.equals("[") || op.equals("{")) {
   operatorStack.push(op);
} else {

...

if (topOp.equals("(") || topOp.equals("[") || topOp.equals("(")) {
  //matching '(' popped - exit loop.
  operandStack.push(l);
  operandStack.push(r);
  break;
}

If you then trace through you code, you will see that you are trying to use "(" as an operator

You have already pushed ")" back onto the stack before you check. You should move the check up.

if (precedence(op) > precedence(topOp)) {
   if(!op.equals(")") || !op.equals("]") || !op.equals("}")) {
     operatorStack.push(op);
   }
}

Final Code

import java.util.*;

public class InfixEvaluator
{

    public static void main(String[] args) {
    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 < test.size(); z++) {
        System.out.println(test.get(z));
    }

    System.out.println(infixCalculator(test));
}


 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<Double> operandStack = new Stack<Double>();

/** This is the operator stack
 *  i.e. (+-/*%^)
 */
private static Stack<String> operatorStack = new Stack<String>();

/** 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<String> input = new ArrayList<String>();

public static ArrayList inputCleaner(String postfix){
  StringBuilder poop = new StringBuilder();
  String doody = postfix.replace(" ", "");
  try {
    for (int i = 0; i < doody.length(); i++) {
        char c = doody.charAt(i);
        boolean isNum = (c >= '0' && c <= '9');

        if (isNum) {
            poop.append(c);
            if (i == doody.length()-1) {
                input.add(poop.toString());
                poop.delete(0, poop.length());
            }
        } else if (c == '.') {
            for (int j = 0; j < poop.length(); j++) {
                if (poop.charAt(j) == '.') {
                    throw new SyntaxErrorException("You can't have two decimals in a number.");
                } else if (j == poop.length() - 1) {
                    poop.append(c);
                    j = (poop.length() + 1);
                } 
            } 
            if (poop.length() == 0) {
                poop.append(c);
            }
            if (i == doody.length()-1) {
                throw new SyntaxErrorException("You can't end your equation with a decimal!");
            }
        } else if (OPERATORS.indexOf(c)!= -1) {
            if (poop.length() != 0) {
                input.add(poop.toString());
                poop.delete(0, poop.length()); 
            }
            poop.append(c);
            input.add(poop.toString());
            poop.delete(0, poop.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 < 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 < 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 < 0 || scoop < 0 || foop < 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.equals("(") || op.equals("[") || op.equals("{")) {
        operatorStack.push(op);
    } else {
        //peek the operator stack and
        //let topOp be the top operator.
        String topOp = operatorStack.peek();
        if (precedence(op) > precedence(topOp)) {
           if(!op.equals(")") || !op.equals("]") || !op.equals("}")) {
                operatorStack.push(op);
            }
        }
        else {
            //Pop all stacked operators with equal
            // or higher precedence than op.
            while (!operatorStack.empty() && precedence(op) <= precedence(topOp)) {
                double r = operandStack.pop();
                double l = operandStack.pop(); //***THE PROGRAM CRASHES HERE***
                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.equals("(") || topOp.equals("[") || topOp.equals("(")) {
                    //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 > top of stack operator precedence.

        }
    }
}

public static String infixCalculator(ArrayList<String> puke) {
    int p;
    for (p = 0; p < 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: //do nothing, but this should never happen
                        break;
                }
        }
    }
    return String.valueOf(operandStack.pop());
}

private static int precedence(String op) {
    return PRECEDENCE[OPERATORS.indexOf(op)];
}


}
SethB
  • 2,060
  • 1
  • 14
  • 18