/************************************************************************************************/
/*       |----------------------|                                                               */
/*       | Expression Evaluator |                                                               */
/*       |----------------------|                                                               */
/*                                                                                              */
/* This program parses a sequence of expressions and returns an integer evaluation for each.    */
/* It has a procedure GetT for each non-terminal T.                                             */
/* The pre-condition/post-condition contract for these will be as follows.                      */
/*                                                                                              */
/* Parse:                                                                                       */
/*   For each nonterminal T, the routine getT parses the longest substring                      */
/*   of the code from the indicated starting point that is a valid T.                           */
/*                                                                                              */
/* token:                                                                                       */
/*   The global variable token initially contains the next token                                */
/*   to be processed, ie the first token in T.                                                  */
/*   When GetT returns the global variable token will be changed to the next                    */
/*   token to be processes which is the first token after this parsed T.                        */
/*                                                                                              */
/* Output:                                                                                      */
/*   The output consists of and integer evaluation of the T.                                    */
/*                                                                                              */
/*                                                                                              */
/* Variables: Initial values are v0=0; v1=1; v2=2; v3=3; v4=4; v5=5; v6=6; v7=7; v8=8; v9=9;    */
/*                                                                                              */
/************************************************************************************************/

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.StreamTokenizer;

public class Evaluate {
	static StreamTokenizer code; /* This Java object keeps track of where in the file the tokenizer is
	 * and the command code.nextToken() returns the next token,
	 * converting it to an string, character, or real as needed. */
	static int token;            // Contains the next token to process. 
	static int v[];              // The values of the variables v0,v1,..,v9.

	public static void main (String[] args) throws IOException{

		v = new int[10];  v[0]=0; v[1]=1; v[2]=2; v[3]=3; v[4]=4; v[5]=5; v[6]=6; v[7]=7; v[8]=8; v[9]=9; 

		FileReader rd = null;
		try {
			rd = new FileReader("c:/Users/Jeff/Documents/Josh/compiler/test.exp");
		} catch (FileNotFoundException e1) {
			System.out.println("file not found");
		} 
		code = new StreamTokenizer(rd);
		code.ordinaryChar('-');        // Tells tokenizer to parse -3 as two tokens.
		code.ordinaryChar('/');        // Tells tokenizer to parse 5/10 as three tokens.
		code.eolIsSignificant(false);  // Tells tokenizer to ignore the end of the line
		code.slashSlashComments(true); // Tells tokenizer to ignore // comments 
		code.slashStarComments(true);  // Tells tokenizer to ignore /* comments */
		token = code.nextToken();      // GetExp requires token to be the first token of the expression
		while (token != StreamTokenizer.TT_EOF){
			System.out.println( "Main " + GetExp() );
			token = code.nextToken();  // Again GetExp requires token to be the first token of the expression
		}
	}

	
	/************************************************************************************************/
	/* Routine GetExp evaluates an expression Exp                                                   */
	/*                                                                                              */
	/* Exp             ==>    Term                                                                  */
	/*                 ==>    Term +|- Term +|- ... +|- Term                                        */
	/*                                                                                              */
	/************************************************************************************************/
	 	
	public static int GetExp() throws IOException{
		int total;
		boolean b = true;
		total = GetTerm(); 
		while( b ){
			switch (token) { 
			case '+': 
				token = code.nextToken(); // move token past the '+'
				total += GetTerm(); 
				break; 
			case '-': 
				token = code.nextToken(); // move token past the '-'
				total -= GetTerm(); 
				break; 
			default: 
				b=false;
			}
		}
		return total;
	}


	/************************************************************************************************/
	/* Routine GetTerm evaluates a term Term                                                        */
	/*                                                                                              */
	/* Term            ==>    Factor                                                                */
	/*                 ==>    Factor *|/ Factor *|/ ... *|/ Factor                                  */
	/*                                                                                              */
	/************************************************************************************************/
 	
	public static int GetTerm() throws IOException{
		int total; 
		total = GetFact( ); 
		while( true ){
			switch (token) { 
			case '*': 
				token = code.nextToken(); // move token past the '*'
				total *= GetFact(); 
				break; 
			case '/': 
				token = code.nextToken(); // move token past the '/'
				total /= GetFact(); 
				break; 
			default: 
				return total;
			}
		}
	}


	/************************************************************************************************/
	/* Routine GetFact evaluates a factor Factor                                                    */
	/*                                                                                              */
	/* Factor          ==>    Int                                    (begins with '0' .. '9')       */
	/*                 ==>    ( Exp )                                       (begins with '(')       */
	/*                 ==>    v0 | v1 | ... | v9                            (begins with 'v')       */
	/*                                                                                              */
	/************************************************************************************************/
 
	public static int GetFact() throws IOException{
		int total;
		switch (token) { 
		case StreamTokenizer.TT_NUMBER: // A number was found; the value is in code.nval; 
			total = (int) code.nval;
			token = code.nextToken();   // move token past the integer
			return( total );
		case '(': 
			token = code.nextToken();   // move token past the '('
			total = GetExp(); 
			if(token!=')') {
				System.out.println("Error: Expected ) "+token+", "+code.nval);
				Recover();
				return(0);
			}
			token = code.nextToken();   // move token past the ')'
			return(total);
		case StreamTokenizer.TT_WORD:
			/* code.sval is the token v3.
			 * code.sval.charAt(1) is character c=3
			 * c-'0' give the integer 3. */		
			if(code.sval.charAt(0)!='v') {
				System.out.println("Error: Expected vi");
				Recover();
				return(0);
			}
	          
			int i = code.sval.charAt(1)-'0'; 
			total = v[i];
			token = code.nextToken();   // move token past the 'v3'
			return(total);
		default:
			System.out.println("Error: Bad Factor " + token);
			Recover();
			return(0);
		}
	}

	/************************************************************************************************/
	/* Tries to recover after errors																*/
	/* Gets tokens to the next ';' character        												*/
	/************************************************************************************************/
	public static void Recover() throws IOException{
		while( token!=';' ) token = code.nextToken(); // move token past non ';'
	}
}

