0

I am writing a program that evaluates a LISP expression through iteration. LISP expressions are as follows:

Adding two and two would be written in LISP as: (+ 2 2). The LISP expression (* 5 4 3 2 1) would be evaluated to five factorial.

To do this, I am using a Stack of Queues of Doubles. A string is input to the evaluator, I take each item in the string, evaluate whether it is a operator or operand. When I reach a '(' I need to push the current level queue onto the stack and instantiate a new queue to continue evaluating. If I reach a ')' I need to take the operator from the current level queue, and then evaluate each operand within that queue until it is empty, at which point I offer the newly evaluated operand to the queue next in the stack (By popping it, offering the operand, and pushing it back on).

My issue seems to be arising when I reach ')' and try to evaluate a current level operand with the current operator. I have been trying:

operand = operator + opQueue.poll();

but this just adds the double value of the operator to the operand... :( I know I am missing something relatively basic here, but any advice or suggestions would be much appreciated. The full code is below. I believe the problem is towards the end just before main. I included all the code for attempted clarity.

import java.util.Queue;
import java.util.LinkedList;
import java.util.Stack;

public class IterativeEvaluator
{ 
  private ExpressionScanner expression;

  public IterativeEvaluator (String expression)
  {
    this.expression = new ExpressionScanner(expression);
  }

  public double evaluate(Queue<Double> operandQueue)
  {
    Stack<Queue<Double>> myStack = new Stack<Queue<Double>>();

    char operator = ' ';
    double operand = 0.0;

    Queue<Double> opQueue = operandQueue;

    // write your code here to evaluate the LISP expression iteratively
    // you will need to use an explicit stack to push and pop context objects

    while(expression.hasNextOperand() || expression.hasNextOperator())
    {

        if(expression.hasNextOperand())
        {
            operand = expression.nextOperand();
            opQueue.offer((double)operand);
        }

        if(expression.hasNextOperator())
        {
            operator = expression.nextOperator();
            if(operator == '(')
            {
                myStack.push(opQueue);
                opQueue = new LinkedList<Double>();             
            }   
            if(operator != '(' && operator != ')')
                opQueue.offer((double)operator);
            if(operator == ')')
            {
                operator = ((char)(opQueue.remove().intValue()));

                while(opQueue.peek() != null)
                {
                    operand = operator + opQueue.poll();

                }

                opQueue = myStack.pop();
                if(opQueue != null)
                    opQueue.offer(operand);

            }

        }


    }

    return operand;

  }
  public static void main(String [] args)
  {
    String s =  
      "(+\t(- 6)\n\t(/\t(+ 3)\n\t\t(- \t(+ 1 1)\n\t\t\t3\n\t\t\t1)\n\t\t(*))\n\t(* 2 3 4))";  // = 16.5
    IterativeEvaluator myEvaluator = new IterativeEvaluator(s);
    System.out.println("Evaluating LISP Expression:\n" + s);
    System.out.println("Value is: " + myEvaluator.evaluate(null)); 
  }
}  /* 201340 */
Atache
  • 169
  • 1
  • 13

1 Answers1

1

Here is an improved version of your code with some remarks. I hope, it helps. You only have to extend it if you want to have more different operators.

public double evaluate(Queue<Double> operandQueue)
{
    // from http://docs.oracle.com/javase/7/docs/api/java/util/ArrayDeque.html
    // "This class is likely to be faster than Stack when used as a stack, ..."
    ArrayDeque<Queue<Double>> myStack = new ArrayDeque<>();

    char operator; // don't pre-initialize with nonsense value
    double operand = Double.NaN; // not used, NaN indicates if we have an error

    Queue<Double> opQueue = operandQueue;

    if(!expression.hasNextOperand() && !expression.hasNextOperand())
      // carefully decide what to do if the entire expression is empty
      throw new IllegalArgumentException("empty expression");

    // write your code here to evaluate the LISP expression iteratively
    // you will need to use an explicit stack to push and pop context objects
    while(expression.hasNextOperand() || expression.hasNextOperator())
    {
        if(expression.hasNextOperand())
        {
            operand = expression.nextOperand();
            opQueue.offer(operand); // cast unnecessary
        }
        else // expression.hasNextOperator() is implied here
        {
            operator = expression.nextOperator();
            if(operator == '(')
            {
                myStack.push(opQueue);
                opQueue = new LinkedList<Double>();             
            }   
            else if(operator != ')') // using <else> we know operator!='('
                opQueue.offer((double)operator);
            else // using <else> we know operator==')'
            {
                operator = ((char)(opQueue.remove().intValue()));
                // get the first operand, using 0.0 here would be disastrous
                // e.g. for multiplications
                operand = opQueue.poll();
                while(opQueue.peek() != null)
                {
                  switch(operator)
                  {
                    case '+': operand += opQueue.poll(); break;
                    case '*': operand *= opQueue.poll(); break;
                    // you got the idea ...
                  }
                }
                opQueue = myStack.pop();
                if(opQueue != null)
                    opQueue.offer(operand);
            }
        }
    }
    return operand;
}
Holger
  • 285,553
  • 42
  • 434
  • 765