Could anyone point me in the right direction or provide a step-by-step process to create an expression evaluator in Java using StringTokenizer, Stacks, and Recursion? It would be appreciated. The method I need help with is "public float evaluator()" Here's the current code:
import structures.Stack;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.StringTokenizer;
public class Expression {
/**
* Expression to be evaluated
*/
String expr;
/**
* Scalar symbols in the expression
*/
ArrayList<ScalarSymbol> scalars;
/**
* Array symbols in the expression
*/
ArrayList<ArraySymbol> arrays;
/**
* Positions of opening brackets
*/
ArrayList<Integer> openingBracketIndex;
/**
* Positions of closing brackets
*/
ArrayList<Integer> closingBracketIndex;
/**
* String containing all delimiters (characters other than variables and constants),
* to be used with StringTokenizer
*/
public static final String delims = " \t*+-/()[]";
/**
* Initializes this Expression object with an input expression. Sets all other
* fields to null.
*
* @param expr Expression
*/
public Expression(String expr) {
this.expr = expr;
scalars = null;
arrays = null;
openingBracketIndex = null;
closingBracketIndex = null;
}
/**
* Matches parentheses and square brackets. Populates the openingBracketIndex and
* closingBracketIndex array lists in such a way that closingBracketIndex[i] is
* the position of the bracket in the expression that closes an opening bracket
* at position openingBracketIndex[i]. For example, if the expression is:
* <pre>
* (a+(b-c))*(d+A[4])
* </pre>
* then the method would return true, and the array lists would be set to:
* <pre>
* openingBracketIndex: [0 3 10 14]
* closingBracketIndex: [8 7 17 16]
* </pe>
*
* @return True if brackets are matched correctly, false if not
*/
public boolean isLegallyMatched() {
Stack<String> tag = new Stack<String>();
for(int i = 0; i < expr.length(); i++)
{
if(expr.charAt(i) == '[' || expr.charAt(i) == '(')
{
tag.push(expr.substring(i,i+1));
openingBracketIndex.add(new Integer(i));
}
else if(expr.charAt(i) == ']' || expr.charAt(i) == ')')
{
if(tag.peek().equals(expr.substring(i,i+1)))
{
closingBracketIndex.add(new Integer(i));
tag.pop();
}
else if(tag.peek().equals("") || !tag.peek().equals(expr.substring(i,i+1)))
{
return false;
}
}
}
return true;
/*if (open) {
* count++;
* push onto stack 1 open
* push onto stack 2 count
* add to array @ count the value of i
* }
* if (close) {
* compare
* if (is close to previous) {
* pop stack 1
* pop stack 2
* add to array2 @ value from popped stack 2 value of i
* }
* else {
* return false;
* }}
*/
}
/**
* Populates the scalars and arrays lists with symbols for scalar and array
* variables in the expression. For every variable, a SINGLE symbol is created and stored,
* even if it appears more than once in the expression.
* At this time, values for all variables are set to
* zero - they will be loaded from a file in the loadSymbolValues method.
*/
public void buildSymbols() {
String expression = expr;
for(int i = 0; i < expression.length(); i++)
{
if(!Character.isLetter(expression.charAt(i)) && expression.charAt(i) != '[')
{
ScalarSymbol add = new ScalarSymbol(expression.substring(0,i));
scalars.add(add);
expression = expression.substring(i+1);
}
else if(!Character.isLetter(expression.charAt(i)) && expression.charAt(i) == '[')
{
ArraySymbol add = new ArraySymbol(expression.substring(0,i));
arrays.add(add);
expression = expression.substring(i+1);
}
}
}
/**
* Loads values for symbols in the expression
*
* @param br BufferedReader for values input
* @throws IOException If there is a problem with the input
*/
public void loadSymbolValues(BufferedReader br)
throws IOException {
String line;
while ((line = br.readLine())!= null) {
StringTokenizer st = new StringTokenizer(line);
int numTokens = st.countTokens();
String sym = st.nextToken();
ScalarSymbol ssymbol = new ScalarSymbol(sym);
ArraySymbol asymbol = new ArraySymbol(sym);
int ssi = scalars.indexOf(ssymbol);
int asi = arrays.indexOf(asymbol);
if (ssi == -1 && asi == -1) {
continue;
}
int num = Integer.parseInt(st.nextToken());
if (numTokens == 2) { // scalar symbol
scalars.get(ssi).value = num;
} else { // array symbol
asymbol = arrays.get(asi);
asymbol.values = new int[num];
// following are (index,val) pairs
while (st.hasMoreTokens()) {
String tok = st.nextToken();
StringTokenizer stt = new StringTokenizer(tok," (,)");
int index = Integer.parseInt(stt.nextToken());
int val = Integer.parseInt(stt.nextToken());
asymbol.values[index] = val;
}
}
}
}
/**
* Evaluates the expression, using RECURSION to evaluate subexpressions and to evaluate array
* subscript expressions.
*
* @return Result of evaluation
*/
public float evaluate()
{
StringTokenizer solve = new StringTokenizer(expr,delims);
Stack<String> operator = new Stack<String>();
Stack<String> operand = new Stack<String>();
if(solve.nextToken() == solve.nextToken(delims))
{
operator.push(solve.nextToken());
}
else
{
operand.push(solve.nextToken());
}
//um what now?
return 0;
}
/**
* Prints the symbols in the scalars list
*/
public void printScalars() {
for (ScalarSymbol ss: scalars) {
System.out.println(ss);
}
}
/**
* Prints the symbols in the arrays list
*/
public void printArrays() {
for (ArraySymbol as: arrays) {
System.out.println(as);
}
}