| 
001002
 003
 004
 005
 006
 007
 008
 009
 010
 011
 012
 013
 014
 015
 016
 017
 018
 019
 020
 021
 022
 023
 024
 025
 026
 027
 028
 029
 030
 031
 032
 033
 034
 035
 036
 037
 038
 039
 040
 041
 042
 043
 044
 045
 046
 047
 048
 049
 050
 051
 052
 053
 054
 055
 056
 057
 058
 059
 060
 061
 062
 063
 064
 065
 066
 067
 068
 069
 070
 071
 072
 073
 074
 075
 076
 077
 078
 079
 080
 081
 082
 083
 084
 085
 086
 087
 088
 089
 090
 091
 092
 093
 094
 095
 096
 097
 098
 099
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 
 | package algs13;
import stdlib.*;
import java.util.TreeMap;
/* ***********************************************************************
 *  Compilation:  javac EvaluateDeluxe.java
 *  Execution:    java EvaluateDeluxe
 *  Dependencies: Stack.java
 *
 *  Evaluates arithmetic expressions using Dijkstra's two-stack algorithm.
 *  Handles the following binary operators: +, -, *, / and parentheses.
 *
 *  % echo "3 + 5 * 6 - 7 * ( 8 + 5 )" | java EvaluateDeluxe
 *  -58.0
 *
 *
 *  Limitiations
 *  --------------
 *    -  can easily add additional operators and precedence orders, but they
 *       must be left associative (exponentiation is right associative)
 *    -  assumes whitespace between operators (including parentheses)
 *
 *  Remarks
 *  --------------
 *    -  can eliminate second phase if we enclose input expression
 *       in parentheses (and, then, could also remove the test
 *       for whether the operator stack is empty in the inner while loop)
 *    -  see http://introcs.cs.princeton.edu/java/11precedence/ for
 *       operator precedence in Java
 *
 *************************************************************************/
public class XEvaluateDeluxe {
  // result of applying binary operator op to two operands val1 and val2
  public static double eval(String op, double val1, double val2) {
    if (op.equals("+")) return val1 + val2;
    if (op.equals("-")) return val1 - val2;
    if (op.equals("/")) return val1 / val2;
    if (op.equals("*")) return val1 * val2;
    throw new Error("Invalid operator");
  }
  public static void main(String[] args) {
    StdIn.fromString ("1 + 2 + 3");
    // precedence order of operators
    TreeMap<String, Integer> precedence = new TreeMap<>();
    precedence.put("(", 0);   // for convenience with algorithm
    precedence.put(")", 0);
    precedence.put("+", 1);   // + and - have lower precedence than * and /
    precedence.put("-", 1);
    precedence.put("*", 2);
    precedence.put("/", 2);
    Stack<String> ops  = new Stack<>();
    Stack<Double> vals = new Stack<>();
    while (!StdIn.isEmpty()) {
      // read in next token (operator or value)
      String s = StdIn.readString();
      // token is a value
      if (!precedence.containsKey(s)) {
        vals.push(Double.parseDouble(s));
        continue;
      }
      // token is an operator
      while (true) {
        // the last condition ensures that the operator with higher precedence is evaluated first
        if (ops.isEmpty() || s.equals("(") || (precedence.get(s) > precedence.get(ops.peek()))) {
          ops.push(s);
          break;
        }
        // evaluate expression
        String op = ops.pop();
        // but ignore left parentheses
        if (op.equals("(")) {
          if (!s.equals(")")) throw new Error ();
          break;
        }
        // evaluate operator and two operands and push result onto value stack
        else {
          double val2 = vals.pop();
          double val1 = vals.pop();
          vals.push(eval(op, val1, val2));
        }
      }
    }
    // finished parsing string - evaluate operator and operands remaining on two stacks
    while (!ops.isEmpty()) {
      String op = ops.pop();
      double val2 = vals.pop();
      double val1 = vals.pop();
      vals.push(eval(op, val1, val2));
    }
    // last value on stack is value of expression
    StdOut.println(vals.pop());
    if (!vals.isEmpty()) throw new Error ();
    if (!ops.isEmpty()) throw new Error ();
  }
}
 |