Java calculator crashing with input of parentheses

Monday, May 5, 2014

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)



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 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 =="(" || 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(); //***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 == "(" || 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()-1) {
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)];
}

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));
}


}







http://ift.tt/1lTEyIi