I have in a class the following code...
String processor()
{
Stack<Character> stack = new Stack<>();
while (curr < infixExpr.length())
{
// assigning the current index position of string in infix expression to a variable to reduce amount of repeated code
Character element = infixExpr.charAt(curr);
if (isOperand(element))
{
postfixExpr += "" + element;
}
else if (element == '(')
{
stack.push(element);
}
else if (element == ')')
{
while (!stack.peek().equals('('))
{
postfixExpr += stack.pop(); // adding all items in stack after ( and before )
}
stack.pop(); // this should pop the stack of the waiting pushed ( paren and remove it from our postfix expression, basically ignoring it
// right paren found to trigger this else if statement was never pushed onto the stack nor assigned to the postfix expression, also ignored
}
else //*must be an operator then
{
while (OrdOpsTable.getOperatorPrecedence(stack.peek(), true) > OrdOpsTable.getOperatorPrecedence(element, false)) // flag, 'true' to signify this is from the stack. ALso, compare if it has higher precedence over the current operator
{
postfixExpr += stack.pop(); // placing found operator to end of postfix expression
}
stack.push(element);
}
curr++;
}
while (!stack.isEmpty())
{
postfixExpr += stack.pop();
}
return postfixExpr;
}
In the method "getOperatorPrecedence" parameters, I have a Stack instance called stack, calling the method peek, returning a Character Object. As the field element shows, element is of Character Object type. I created a simple flag boolean in the method parameters to make this simple.
So, the "getOperatorPrecedence" is in another class file called "OrdOpsTable"...
public final class OrdOpsTable<T> extends ArrayList
{
// INITIALIZERS
private static Character[] table = {'(','+','-','*','/','%','^'};
private static ArrayList<OperatorValues> ON_stack = new ArrayList<>();
private static ArrayList<OperatorValues> ON_curr = new ArrayList<>();
private T FROM_stack = null;
private T FROM_curr = null;
// CONSTRUCTOR
private OrdOpsTable(T curr)
{
setOperatorPrecedence();
if (curr.getClass() == Stack.class)
this.FROM_stack = curr;
else
this.FROM_curr = curr;
}
// METHODS
private static void setOperatorPrecedence()
{
// this method just sets the unique values of each operator to two arrays
int i = 0;
for (char op : table)
{
switch(op)
{
case '(':
ON_stack.add(i, new OperatorValues(op, 0));
ON_curr.add(i, new OperatorValues(op, 100));
break;
case '+':
ON_stack.add(i, new OperatorValues(op, 2));
ON_curr.add(i, new OperatorValues(op, 1));
break;
case '-':
ON_stack.add(i, new OperatorValues(op, 2));
ON_curr.add(i, new OperatorValues(op, 1));
break;
case '*':
ON_stack.add(i, new OperatorValues(op, 4));
ON_curr.add(i, new OperatorValues(op, 3));
break;
case '/':
ON_stack.add(i, new OperatorValues(op, 4));
ON_curr.add(i, new OperatorValues(op, 3));
break;
case '%':
ON_stack.add(i, new OperatorValues(op, 4));
ON_curr.add(i, new OperatorValues(op, 3));
break;
case '^':
ON_stack.add(i, new OperatorValues(op, 5));
ON_curr.add(i, new OperatorValues(op, 6));
break;
}
i++;
}
}
public static int getOperatorPrecedence(Object curr, boolean FROM_stack)
{
setOperatorPrecedence();
if (FROM_stack)
{
return ON_stack.get(ON_stack.indexOf(curr)).value;
}
else
{
return ON_curr.get(ON_stack.indexOf(curr)).value;
}
}
/* SUBCLASS */
private static class OperatorValues
{
// FIELDS
private char operator;
private int value;
// CONSTRUCTOR
OperatorValues(char operator, int value)
{
this.operator = operator;
this.value = value;
}
// METHOD
char getOperator()
{
return this.operator;
}
int getValue()
{
return this.value;
}
public String toString()
{
return this.operator;
}
}
What I need help with is finding a way to correctly return the OperatorValue subclass field value for both instances of
return ON_stack.get(ON_stack.indexOf(curr)).value;
and
return ON_curr.get(ON_stack.indexOf(curr)).value;
I'm getting the following error...
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at java.util.ArrayList.elementData(ArrayList.java:418)
at java.util.ArrayList.get(ArrayList.java:431)
at OrdOpsTable.getOperatorPrecedence(OrdOpsTable.java:79)
at PostfixParser.processor(PostfixParser.java:57)
at InfixPostfixTester.main(InfixPostfixTester.java:78)
It appears when I debug and follow this, the issue is in "Character" class "equals". First, when I force step into the first return statement in question, it goes to the indexOf() in ArrayList...
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
When the debugger hits the .equals method in here, it goes into the Character class...
public boolean equals(Object obj) {
if (obj instanceof Character) {
return value == ((Character)obj).charValue();
}
return false;
}
The issue here is that the IF statement in this equals method is failing at this comparison. It seems it's comparing obj as my custom made OperatorValues class's toString() and it is obviously not an instanceof a Character class. So, it's failing because it's comparing "(" as a Character. I need it to compare '(' to trigger 'true' in this method.
For an example, I assigned the char '(' with an int of '0' in one array and '100' in another array as you can see above in my OrdOpsTable class in the method setOperatorPrecedence(). When the Character class equals() method is called here without using OperatorValues class's toString(), my debugger says the inline value for curr's '(' in this equal method shows, "obj: OrdOpsTable$OperatorValues@636.
If there was a way to make my toString() method in OperatorValues return a Character instead of String. This of course would cause an error if I did so. Any suggestions on what you would do here?
*NOTE: Let me know if I need to provide more info for you. This is a homework assignment from a class, I've spent alot of time stuck on this part and I've tried relentlessly. I need some outsourcing help to understand what I'm missing.