// Author: t.k.prasad@wright.edu (4/14/2008)

// Input: Single arithmetic expression from file "exprEg.dat"

//        Arithmetic expression  containing integer variable (i),
//        and binary infix operator (+).
//        <expr> ::=   <var>  { +  <var> }
//        <var> ::=     i

// Context:  static double f(int i) {...}
// Output : Equivalent MSIL code in file "msil.code"

/* Example input expression:
       i + i
 */


import java.io.*;

public class ExprcEg {
    static BufferedReader in;
    static StreamTokenizer inTok;

 public static void main(String[] args) throws IOException {
      in = new BufferedReader (new FileReader("exprEg.dat"));
      inTok = new StreamTokenizer(in);

      inTok.eolIsSignificant(true);
      inTok.nextToken();  // lookahead token
      // processes a sequence of expressions holding onto the translation of the last expression
      while (inTok.ttype != inTok.TT_EOF) {
         if (inTok.ttype != inTok.TT_EOL) {
               PrintWriter out = new PrintWriter (
                  new FileWriter( "msil.code" ), true );
             try {
               Node ae = expr();
               System.out.print(" \t\t Value => "+ ae.value());
               System.out.println(" \t\t Type => "+ ae.type());
               ae.code(out);
               out.flush();
             } catch (Exception e) {System.out.println(" \t\t Error =>  " + e);}
             finally {while (inTok.ttype != inTok.TT_EOL) inTok.nextToken();}
         }
         inTok.nextToken();
      }
  }

  public static Node expr() throws Exception {
       // PRE: Expects lookahead token.
       // POST: Lookahead token available.
       Node temp = var();
       Node temp1;
       while ( inTok.ttype == '+') {
            inTok.nextToken();
            temp1 = var();
            temp = new OpNode(temp,'+',temp1);
       }
       return temp;
  }

  public static Node var() throws Exception {
       // PRE: Expects lookahead token.
       // POST: Reads in a lookahead token.
       Node temp;
       if ( inTok.ttype == inTok.TT_WORD) {
              char ch = inTok.sval.charAt(0);
              if ( (inTok.sval.length() == 1) && ( ch=='i') ) {
                        temp = new VarNode(ch);
                        inTok.nextToken();
              } else  throw new Exception("Illegal Variable Name");
       } else  throw new Exception("Variable Token Expected");
       return temp;
  }
 }


 interface Node {
    double value();
    String type();
    void code(PrintWriter out);
 }

// Recall that, ideally, OOP avoids switch.

 class VarNode implements Node {
    private char id;
    public VarNode(char _id) {
	       id = _id;
    }
    public double value() {
		// TO BE CHANGED
        return 0;
    };
    public String type() {
		// TO BE CHANGED
         return "int";
    };
    public void code(PrintWriter out) {
		// TO BE CHANGED
         out.print("\tldarg.1\n");
    };
 }

 class OpNode implements Node {
    private Node LNode, RNode;
    private char op;

    public OpNode(Node _LNode, char _op, Node _RNode) {
	      LNode = _LNode;
              op = _op;
	      RNode = _RNode;
    }
    // TO BE CHANGED - IMPLEMENT INTERFACE
    public double value() {
	// TO BE CHANGED
	      return 0;
	};
	public String type() {
    // TO BE CHANGED
	     return "int";
	};
	public void code(PrintWriter out) {
    // TO BE CHANGED
	     out.print("\tldarg.1\n");
    };
 }


