/*   class Expression
     Carol Wolf
     Fall 2001

The following is a Java application that uses recursive descent to evaluate an infix expression.  At the same time it generates the corresponding postfix expression.  The Token class is used to store the name and value of each operator and operand in the expression.  The three methods: expression, term, and factor, evaluate the expression and print the symbols in the postfix expression. */

import java.io.*;
import java.util.*;

public class Expressions
{
     public static void main (String [] args)
     {
        System.out.println ("Enter an infix expression:");
        Token token = new Token ();
        token.getToken ();
        Express express = new Express (token);
        int result = express.expression ();
        System.out.println ("= " + result);
     } // main method
} // class Expressions

class Token
{
     private int value = 0;
     private String name, tokenString;
    BufferedReader stdin = new BufferedReader (new InputStreamReader (System.in));
    StringTokenizer tokens;

    Token ()
    {
         try
         {
              tokenString = stdin.readLine ();
              tokens = new StringTokenizer (tokenString, "+-*/() ", true);
         } catch (IOException e) {System.out.println ("Input error");}
    } // constructor
 
     public void getToken ()
     {
          char ch = ' ';
          if (tokens.hasMoreTokens ())
          {
               String token = tokens.nextToken ();
               ch = token.charAt (0);
               while (ch == ' ')
               {
                    token = tokens.nextToken ();
                    ch = token.charAt (0);
               }
               if (('0' <= ch) && (ch <= '9'))
               {
                    name = "digit";
                    try
                    { value = Integer.parseInt (token);
                    } catch (NumberFormatException e) {value = 0;}
               }
               else
               {    switch (ch)
                    {
                         case '+': name = "plus"; break;
                         case '-': name = "minus"; break;
                         case '*': name = "times"; break;
                         case '/': name = "divide"; break;
                         case '(': name = "lparen"; break;
                         case ')': name = "rparen"; break;
                         default: name = "other";
                    } //switch
               } // else
          }
          else name = "other";
     } //method getToken
 
     public String getName () { return name; }
     public int getValue () { return value; }

} // class Token

class Express
{
     private Token token;
 
     Express (Token token) { this.token = token; } // constructor
 
     public int expression ()
     {
          String oper;
          int result;
          result = term ();
          while ((token.getName ().equals ("plus")) || (token.getName ().equals ("minus")))
          {
               oper = token.getName ();
               token.getToken ();
               if (oper.equals ("plus"))
               {
                    result = result + term ();
                    System.out.print ("+ ");
                }
               else
               {
                    result = result - term ();
                    System.out.print ("- ");
               }
          }
          return result;
     } // method expression
 
     public int term ()
     {
          String oper;
          int result;
          result = factor ();
          while ((token.getName ().equals ("times")) || (token.getName ().equals ("divide")))
          {
               oper = token.getName ();
               token.getToken ();
               if (oper.equals ("times"))
               {
                    result = result * factor ();
                    System.out.print ("* ");
               }
               else
               {
                    result = result / factor ();
                    System.out.print ("/ ");
               }
          }
          return result;
     } // method term

     public int factor ()
     {
          int result = 0;
          if (token.getName ().equals ("digit"))
          {
               result = token.getValue ();
               System.out.print ("" + token.getValue () + " ");
               token.getToken ();
          }
          else
          if (token.getName ().equals ("lparen"))
          {
               token.getToken ();
               result = expression ();
               if (token.getName ().equals ("rparen"))
                    token.getToken ();
               else
                    System.out.print ("Error - missing right paren");
          }
          else
               System.out.print ("Error - invalid token");
          return result;
     } // method factor
} // class Express