
/************************************************************************************************/
/************************************************************************************************/
/**                                                                                            **/
/**       |--------------------------------------|                                             **/
/**       | JoshJava to MARIE Assembler Compiler |                                             **/
/**       |--------------------------------------|                                             **/
/**                                                                                            **/
/** This is a complier/parser to translate from JoshJava to MARIE.                             **/
/** It has a procedure GetT for each (most) 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.                         **/
/**                                                                                            **/
/** Output:                                                                                    **/
/**   The output consists of the parsing.                                                      **/
/**   For Compile, it is MARIE assembly code that will mirror the actions                      **/
/**   taken in the block of JoshJava code being parsed.                                        **/
/**                                                                                            **/
/** 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.                      **/
/**                                                                                            **/
/** Memory Address m:                                                                          **/
/**   GetExp, GetTerm, and GetFact is passed an address m of physical                          **/
/**   memory. The result of the assembly code produced is to evaluate the                      **/
/**   Exp, Term, or Factor and store the result in this memory cell.                           **/
/**                                                                                            **/
/** nextLabel:                                                                                 **/
/**   The global variable nextLabel is an integer indicating what the next                     **/
/**   label in the assembly code should be. For example, if nextLabel is 5                     **/
/**   then the next label will be "Label5".                                                    **/
/**                                                                                            **/
/** r:                                                                                         **/
/**   A parameter integer r is passed to each routine indicating the depth                     **/
/**   of the parse tree. For example, when GetProgram will have a value of                     **/
/**   0. When it calls GetMainProcedure it will have 1. When it calls List                     **/
/**   Code it will have 2. And so one. The purpose of this is to indent the                    **/
/**   MARIE code based on this value.                                                          **/
/**                                                                                            **/
/** MARIE comments:                                                                            **/
/**   This compiler also comments the MARIE instructions to tell which                         **/
/**   procedure and which rule produced the instruction.                                       **/
/**                                                                                            **/
/************************************************************************************************/
/************************************************************************************************/


import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.io.StreamTokenizer;

public class Compiler {
        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. 
        int token;                                      // Contains the next token to process. 
        int nextL;                                      // The next MARIE label will be L037 when nextL=37
        FileOutputStream fileOutputStream;      // MARIE code streamed out here.
        PrintStream fps;                                                // MARIE code streamed out here.
        boolean debug = true;                           // Whether to output debugging statements.
    boolean ascii = true;                               // Whether to output in ascii or ints.
        String[] ss = new String[16];           // Routines at depth r will be indented by ss[r] = tab + 2r blanks
        String procedureName = new String("globalVars");   // The name of the current routine being compiled.
        // The label for the end will be one bigger.

        public void init(String fileName, boolean a, boolean d) throws IOException {
                ascii=a;
                debug=d;
                HandleFiles(fileName);
                nextToken("Main",' ');                          // GetT requires first token to have been read
                GetProgram(0);
                CompleteCode();
        }

        /************************************************************************************************/
        /** Routine GetProgram produces MARIE code that executes the following JoshJava statements:    **/
        /**                                                                                            **/
        /** Program         ==>    ProgramBlock                                                        **/
        /**                        ProgramBlock                                                        **/
        /**                          ...                                                               **/
        /**                        ProgramBlock                                                        **/
        /**                                                                                            **/
        /** ProgramBlock    ==>    GListVarDec                                     (begins with "int") **/
        /**                 ==>    MainProcedure                                                       **/
        /**                 ==>    Procedure                                                           **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetProgram(int r) throws IOException{
                while( true ) {
                        if(token!=StreamTokenizer.TT_WORD)
                                break;
                        if( code.sval.equals("") ) 
                                GetListVarDec(r,true);
                        else if( code.sval.equals("public") ) 
                                GetProcedure(r);
                        else
                                break;
                }
        }
        
        /************************************************************************************************/
        /** Routine GetProcedure produces MARIE code that executes the following JoshJava statements:  **/
        /**                                                                                            **/
        /** MainProcedure   ==>    public  void main (String[] args) {                                 **/
        /**                          LListVarDec                                                       **/
        /**                          ListCode                                                          **/
        /**                        }                                                                   **/
        /**                                                                                            **/
        /** Procedure       ==>    public  int ProcedureName( int LVarName, int LVarName, ...) {       **/
        /**                          LListVarDec                                                       **/
        /**                          ListCode                                                          **/
        /**                        }                                                                   **/
        /**                                                                                            **/
        /** ProcedureName   ==>    any string starting with a letter                                   **/
        /** LVarName        ==>    any string starting with a small letter                             **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetProcedure(int r) throws IOException{
                nextTokenCheckString("GetProgram","public");
                nextTokenCheckString("GetProgram","static");
                nextToken("GetProgram",'v');                    // void or int
                if( token!=StreamTokenizer.TT_WORD )
                        System.out.format("* Error: GetListVarDec: Expected ProcedureName");
                procedureName = new String(code.sval);  // Save the ProcedureName
                nextToken("GetProgram",'p');
                
                fps.format("%n/**********************************************************************%n");    
                fps.format("/** %s %n",procedureName);                          
                fps.format("/**********************************************************************%n%n");    
                fps.format("%s,","B_"+procedureName);           
                fps.format(ss[r]+"JnS %s       /Mark the beginning of the data to copy to recursive stack %n","B_"+procedureName);
                fps.format(ss[r]+"             /and contains its own address %n");
                fps.format("%s,","J_"+procedureName);                   
                fps.format(ss[r]+"Hex 0        /Beginning of procedure. %n"); 
                fps.format(ss[r]+"             /JnS store here the address to Jump back to %n");
                fps.format(ss[r]+"             /Note this too needs to be copied to the recursive stack %n%n");
                
                nextTokenCheck("GetProgram",'(');
                if( token==StreamTokenizer.TT_WORD && code.sval.equals("String") ) {
                        nextTokenCheckString("GetProgram","String");
                        nextTokenCheck("GetProgram",'[');
                        nextTokenCheck("GetProgram",']');
                        nextTokenCheckString("GetProgram","args");                      
                }
                else
                        GetListVarInputDec(r+1);
                nextTokenCheck("GetProgram",')');
                nextTokenCheck("GetProgram",'{');
                GetListVarDec(r+1,false);
                GetListCode(r+1);
                nextTokenCheck("GetProgram",'}');
                fps.format(ss[r]+"Halt %n");            
        }
        

        
        /************************************************************************************************/
        /** Routine GetListVarInputDec produces MARIE code that executes the following                 **/
        /**    JoshJava statements:                                                                    **/
        /**                                                                                            **/
        /** GetListVarInputDec    ==>    int LVarName, int LVarName, ..., int LVarName                 **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetListVarInputDec(int r) throws IOException{
                fps.format(ss[r]+"/GetListVarInputDec: int VarName %n");
                for( int i=0; i<16; ++i ) {
                        nextTokenCheckString("GetListVarDec","int");
                        if( token!=StreamTokenizer.TT_WORD )
                                System.out.format("* Error: GetListVarDec: Expected string");
                        String varName = new String(code.sval); // Save the variable name
                        varName = GlobalLocalVar(varName);      // Concatenate with procedure name
                        nextToken("GetListVarDec",'v');                 // move token past the VarName

                        fps.format(ss[r]+"Jump L%03d    /Jump over data %n", nextL);                    
                        fps.format("%s,",varName);                      // The varName acts as the label of the memory cell.
                        fps.format(ss[r]+"Dec 0 %n");
                        fps.format("L%03d,",nextL);     
                        fps.format(ss[r]+"Load input%x  /Copy in input %n", i);
                        fps.format(ss[r]+"Store %s %n", varName);
                        ++nextL;                                                        
                        
                        if( token!=',' )
                                break;
                        nextTokenCheck("GetListVarDec",',');
                }
        }

        /************************************************************************************************/
        /** Routine GetListVarDec produces MARIE code that executes the following JoshJava statements: **/
        /**                                                                                            **/
        /** GListVarDec     ==>    GVarDec                                                             **/
        /**                        GVarDec                                                             **/
        /**                          ...                                                               **/
        /**                        GVarDec                                                             **/
        /**                                                                                            **/
        /** GVarDec         ==>     int GVarName;                                                      **/
        /**                 ==>     int GVarName = Int;                                                **/
        /**                 ==>     int[] GVarName = new int[Int];                                     **/
        /**                                                                                            **/
        /** GVarName        ==>    any string starting with a capital letter                           **/
        /**                                                                                            **/
        /** LListVarDec     ==>    LVarDec                                                             **/
        /**                        LVarDec                                                             **/
        /**                          ...                                                               **/
        /**                        LVarDec                                                             **/
        /**                                                                                            **/
        /** LVarDec         ==>    int LVarName;                                                       **/
        /**                 ==>    int LVarName = Int;                                                 **/
        /**                 ==>    int[] LVarName = new int[Int];                                      **/
        /**                                                                                            **/
        /** LVarName        ==>    any string starting with a small letter                             **/
        /**                                                                                            **/
        /**     isGlobal indicates whether processing GlistVarDec or LlistVarDec                       **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetListVarDec(int r, boolean isGlobal) throws IOException{
                boolean isArray;
                int arraySize=0;
                int initialValue=0;
                if( isGlobal ) {
                        fps.format("%n/**********************************************************************%n");    
                        fps.format("/** Global Variable Declarations %n");                      
                        fps.format("/**********************************************************************%n%n");    
                }
                else {
                        fps.format(ss[r]+"/GetListVarDec: int VarName %n");
                        fps.format(ss[r]+"Jump %s   /Jump over data %n", "S_"+procedureName);   
                }
                while( token==StreamTokenizer.TT_WORD && (code.sval.equals("") || code.sval.equals("int") )) {
                        if( isGlobal ) 
                                nextTokenCheckString("GetListVarDec","");
                        nextTokenCheckString("GetListVarDec","int");
                        if( token=='[') {
                                isArray = true;
                                nextTokenCheck("GetListVarDec",'[');
                                nextTokenCheck("GetListVarDec",']');
                        }
                        else
                                isArray = false;
                        if( token!=StreamTokenizer.TT_WORD )
                                System.out.format("* Error: GetListVarDec: Expected string");
                        String varName = new String(code.sval); // Save the variable name
                        nextToken("GetListVarDec",'v');                 // move token past the VarName
                        if( !isArray ) {
                                if( token=='=') {
                                        nextTokenCheck("GetListVarDec",'=');
                                        if( token!=StreamTokenizer.TT_NUMBER )
                                                System.out.format("* Error: GetListVarDec: Expected an integer");
                                        initialValue = (int) code.nval;
                                        nextToken("GetListVarDec",'i');
                                }
                                else
                                        initialValue = 0;
                        }
                        else {                                                                  // isArray
                                nextTokenCheck("GetListVarDec",'=');
                                nextTokenCheckString("GetListVarDec","new");
                                nextTokenCheckString("GetListVarDec","int");
                                nextTokenCheck("GetListVarDec",'[');
                                if( token!=StreamTokenizer.TT_NUMBER )
                                        System.out.format("* Error: GetListVarDec: Expected an integer");
                                arraySize = (int) code.nval;
                                nextToken("GetListVarDec",'i');
                                nextTokenCheck("GetListVarDec",']');
                        }
                        nextTokenCheck("GetListVarDec",';');
                        if( isGlobal && !( varName.charAt(0)>='A' && varName.charAt(0)<='Z') ) 
                                System.out.format("* Error: GetListVarDec: Global variable must start with a capital letter");
                        if( !isGlobal && !( varName.charAt(0)>='a' && varName.charAt(0)<='z') ) 
                                System.out.format("* Error: GetListVarDec: Local variable must start with a small letter");
                        if( !isGlobal )
                                varName = GlobalLocalVar(varName);      // Concatenate with procedure name
                        if( !isArray ) {
                                fps.format("%s,",varName);     // The varName acts as the label of the memory cell.
                                fps.format(ss[r]+"Dec %03d %n", initialValue);
                        }
                        else {
                                fps.format("%s,",varName);     // The varName acts as the label of the memory cell.
                                fps.format(ss[r]+"JnS L%03d    /Address of %s[0] %n", nextL,varName);
                                fps.format("L%03d,",nextL);     // Memory cell for 
                                fps.format(ss[r+1]+"Hex 0     /Memory cell for %s[0] %n", varName);
                                nextL += 1;
                                for( int i=1; i<= arraySize-1; ++i ) 
                                        fps.format(ss[r+1]+"Hex 0 %n");
                        }
                }
                if( !isGlobal ) {
                        fps.format("%s,","E_"+procedureName);                           
                        fps.format(ss[r-1]+"JnS %s        /Mark the end of the ListVarDec and contains its own address %n","E_"+procedureName);
                        fps.format("%s,","L_"+procedureName);                           
                        fps.format(ss[r-1]+"Hex 0         /Lenght of the ListVarDec %n");
                        fps.format("%s,","S_"+procedureName);                           
                        fps.format(ss[r]+"Load %s         /Address one after ListVarDec %n","E_"+procedureName);
                        fps.format(ss[r]+"Subt %s         /Address one before ListVarDec %n","B_"+procedureName);
                        fps.format(ss[r]+"Subt One        /Lenght of ListVarDec %n");
                        fps.format(ss[r]+"Store %s %n","L_"+procedureName);
                        fps.format(ss[r]+"%n/Beginning of Code %n");
                }
        }

        /************************************************************************************************/
        /** Routine GetBlockCode produces MARIE code that executes the following JoshJava statements:  **/
        /**                                                                                            **/
        /** BlockCode       ==>    LineCode                                                            **/
        /**                 ==>    { ListCode }                                                        **/
        /************************************************************************************************/

        public  void GetBlockCode(int r) throws IOException{
                if(token=='{') {
                        nextToken("GetBlockCode",'{'); // move token past the '{' in "{ ListCode }"
                        GetListCode(r);
                        nextTokenCheck("GetBlockCode",'}'); // move token past the '}' in "{ ListCode }"
                }
                else
                        GetLineCode(r);
        }

        /************************************************************************************************/
        /** Routine GetListCode produces MARIE code that executes the following JoshJava statements:  **/
        /**                                                                                            **/
        /** ListCode        ==>    LineCode                                                            **/
        /**                        LineCode                                                            **/
        /**                          ...                                                               **/
        /**                        LineCode                                      (ends with '}')       **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetListCode(int r) throws IOException{
                while( token==StreamTokenizer.TT_WORD ) // Lines beginning with a string and not with a }
                        GetLineCode(r);
        }

        /************************************************************************************************/
        /** Routine GetLineCode produces MARIE code that executes the following JoshJava statements:   **/
        /**                                                                                            **/
        /** LineCode        ==>    Assignmentv                               (begins with 'string')    **/
        /**                 ==>    Assignmenta                               (begins with 'string[')   **/
        /**                 ==>    IfStatement                               (begins with 'if')        **/
        /**                 ==>    WhileStatement                            (begins with 'while')     **/
        /**                 ==>    ProcedureCall                             (begins with "string(")   **/
        /**                 ==>    Return                                    (begins with 'return')    **/
        /**                 ==>    Out                                       (begins with 'System...') **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetLineCode(int r) throws IOException{
                if(code.sval.equals("if"))
                        GetIfStatement(r+1);
                else if(code.sval.equals("while"))
                        GetWhileStatement(r+1);
                else if(code.sval.equals("return"))
                        GetReturn(r+1);
                else if(code.sval.equals("System.out.print") || code.sval.equals("System.out.println"))
                        GetOutPut(r+1);
                else if(code.sval.equals("int"))
                        System.out.format("* Error: GetLineCode: All variable declarations must be at the top of procedure - Sorry");
                else {
                        String varName = new String(code.sval); // Save the variable name
                        nextToken("GetAssignment",'v');                 // move token past the variable in "var = Exp;"
                        if(token=='[') 
                                GetAssignmenta(r+1,varName);
                        else if(token=='(') {
                                GetProcedureCall(0,r+1,varName);
                                nextTokenCheck("GetProcedureCall",';'); // move token past the ';' in "p(2);"
                        }
                        else
                                GetAssignmentv(r+1,varName);
                }
        }

        /************************************************************************************************/
        /** Routine GetAsignmentv produces MARIE code that executes the following JoshJava statements: **/
        /**                                                                                            **/
        /** Assignmentv     ==>    VarName = Exp;                                                      **/
        /**      The VarName is in varName and '=' is in token                                         **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetAssignmentv(int r, String varName) throws IOException{
                fps.format(ss[r]+"/GetAssignmentv: %s = Exp;%n",code.sval);
                varName = GlobalLocalVar(varName);      // Concatenate with procedure name
                nextTokenCheck("GetAssignmentv",'=');   // move token past the '=' in "vi = Exp;"
                GetExp(0,r+1);                                                  // Evaluate Exp and store it in ExpS0
                fps.format(ss[r]+"/GetAssignmentv: %s = ExpS0;%n",varName);
                fps.format(ss[r]+"Load ExpS0%n");
                fps.format(ss[r]+"Store %s%n",varName);
                nextTokenCheck("GetAssignmentv",';'); // move token past the ';' in "vi = Exp;"
        }

        /************************************************************************************************/
        /** Routine GetAssignmenta produces MARIE code that executes the following JoshJava statements:**/
        /**                                                                                            **/
        /** Assignmenta     ==>    VarName[Exp] = Exp;                                                 **/
        /**      The VarName is in varName and '[' is in token                                         **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetAssignmenta(int r, String varName) throws IOException{
                fps.format(ss[r]+"/GetAssignmenta: a[Exp] = Exp;%n");
                varName = GlobalLocalVar(varName);      // Concatenate with procedure name
                nextTokenCheck("GetAssigmenta",'[');    // move token past the '['
                GetExp(0,r+1);                                  // Evaluate first Exp in "a[Exp]=Exp;" and store it in ExpS0
                nextTokenCheck("GetAssignmenta",']');   // move token past the '['
                nextTokenCheck("GetAssignmenta",'=');   // move token past the '='
                GetExp(1,r+1);                                                  // Evaluate second Exp in "a[Exp]=Exp;" and store it in ExpS1
                fps.format(ss[r]+"/GetAssignment: a[ExpS0] = ExpS1;%n");  // a[ExpS0] = ExpS1;
                fps.format(ss[r]+"Load %s %n",varName);       // Load a   (or b)
                fps.format(ss[r]+"JnS StoreInArray");
                nextTokenCheck("GetAssignmenta",';'); // move token past the ';' in "a[Exp] = Exp;"
        }

        /************************************************************************************************/
        /** Routine GlobalLocalVar determines if a variable name is local or global                    **/
        /**       and makes unique if local                                                            **/
        /************************************************************************************************/

        public  String GlobalLocalVar(String varName) {
                if(varName.charAt(0) >= 'a' && varName.charAt(0) <= 'z' )  // Local if begins with small letter
                        return varName.concat("_"+procedureName);
                else
                        return varName;
        }

        /************************************************************************************************/
        /** Routine GetExp produces MARIE code that that evaluates an expression Exp                   **/
        /** and stores it in ExpSm                                                                     **/
        /**                                                                                            **/
        /** Exp             ==>    Term                                                                **/
        /**                 ==>    Term +|- Term +|- ... +|- Term                                      **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetExp(int m, int r) throws IOException{
                fps.format(ss[r]+"/GetExp: ExpS%x = Exp = Term + ... + Term;%n",m);
                GetTerm(m,r+1);                                                                 // Read first Term and put it in ExpSm
                while( true ){
                        if(token=='+' || token== '-') {                         // Token after the term
                                int op = token;
                                fps.format(ss[r]+"/GetExp: ExpS%x = next term;%n",m+1);
                                nextToken("GetExp",'+');                                // move token past the '+'
                                GetTerm(m+1,r+1);                                               // Read next term and put it in Exps(m+1)
                                if(op=='+') {                           // ExpSm = ExpSm + ExpS(m+1)
                                        fps.format(ss[r]+"/GetExp: ExpS%x = ExpS%x + ExpS%x %n",m,m,m+1);
                                        fps.format(ss[r]+"Load ExpS%x %n",m);
                                        fps.format(ss[r]+"Add ExpS%x %n",m+1);
                                }
                                else {
                                        fps.format(ss[r]+"/GetExp: ExpS%x = ExpS%x - ExpS%x %n",m,m,m+1);
                                        fps.format(ss[r]+"Load ExpS%x %n",m);
                                        fps.format(ss[r]+"Subt ExpS%x %n",m+1); 
                                }
                                fps.format(ss[r]+"Store ExpS%x %n",m);
                        }
                        else
                                return;
                }
        }

        /************************************************************************************************/
        /** Routine GetTerm produces MARIE code that that evaluates a term Term                        **/
        /** and stores it in ExpSm                                                                     **/
        /**                                                                                            **/
        /** Term            ==>    Factor                                                              **/
        /**                 ==>    Factor *|/ Factor *|/ ... *|/ Factor                                **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetTerm(int m, int r) throws IOException{
                fps.format(ss[r]+"/GetTerm: ExpS%x = Term = Fact * ... * Fact;%n",m);
                GetFact(m,r+1);                                                                 // Read first Fact and put it in ExpSm
                while( true ){
                        if(token=='*' || token== '/') {                         // Token after the Fact
                                int op = token;
                                fps.format(ss[r]+"/GetTerm: ExpS%x = next Fact;%n",m+1);
                                nextToken("GetTerm",'*');                               // move token past the '*'
                                GetFact(m+1,r+1);                                               // Read next Fact and put it in Exps(m+1)
                                if(op=='*') {                                                   // ExpSm = ExpSm * ExpS(m+1)
                                        fps.format(ss[r]+"/GetTerm: ExpS%x = ExpS%x * ExpS%x %n",m,m,m+1);
                                        fps.format(ss[r]+"Load ExpS%x %n",m);
                                        fps.format(ss[r]+"Store Mx %n");
                                        fps.format(ss[r]+"Load ExpS%x %n",m+1);
                                        fps.format(ss[r]+"Store My %n");
                                        fps.format(ss[r]+"JnS Mult %n");
                                        fps.format(ss[r]+"Load Mz %n");
                                        fps.format(ss[r]+"Store ExpS%x %n",m);
                                }
                                else {
                                        fps.format(ss[r]+"/GetTerm: ExpS%x = ExpS%x / ExpS%x %n",m,m,m+1);
                                        fps.format(ss[r]+"Load ExpS%x %n",m);
                                        fps.format(ss[r]+"Store Mx %n");
                                        fps.format(ss[r]+"Load ExpS%x %n",m+1);
                                        fps.format(ss[r]+"Store My %n");
                                        fps.format(ss[r]+"JnS Div %n");
                                        fps.format(ss[r]+"Load Mz %n");
                                        fps.format(ss[r]+"Store ExpS%x %n",m);
                                }
                                fps.format(ss[r]+"Store ExpS%x %n",m);
                        }
                        else
                                return;
                }
        }


        /************************************************************************************************/
        /** Routine GetFact produces MARIE code that evaluates a factor Factor                         **/
        /** and stores it in ExpSm                                                                     **/
        /**                                                                                            **/
        /** Factor          ==>    Int                                    (begins with '0' .. '9')     **/
        /**                 ==>    ( Exp )                                (begins with '(')            **/
        /**                 ==>    VarName                                (begins with "string")       **/
        /**                 ==>    VarName[Exp]                           (begins with "string[")      **/
        /**                 ==>    in.nextInt                             (begins with "in.nextInt")   **/
        /**                 ==>    ProcedureCall                          (begins with "string(")      **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetFact(int m, int r) throws IOException{
                switch (token) { 
                case StreamTokenizer.TT_NUMBER:                                 // A number was found;                             
                        GetFactInt(m,r);
                        return;
                case '(': 
                        GetFactExp(m,r);
                        return;
                case StreamTokenizer.TT_WORD: 
                        if(code.sval.equals("in.nextInt"))              // in.nextInt
                                GetFactInput(m,r);
                        else {
                                String varName = new String(code.sval); // Save the variable name
                                nextToken("GetAssignment",'v');                 // move token past the variable name
                                if(token=='[')                                                  // a[Exp] 
                                        GetFactArray(m,r,varName);
                                else if(token=='(')                                     // ProcedureCall(5)
                                        GetProcedureCall(m,r,varName);
                                else 
                                        GetFactVar(m,r,varName);
                        }
                        return;
                default:
                        nextTokenCheck("GetFact",'F');                          // Will print an Error (Unless starts with F)
                        return;
                }
        }

        /************************************************************************************************/
        /** Routine GetFactInt produces MARIE code that evaluates a factor Factor that is an integer   **/
        /** and stores it in ExpSm                                                                     **/
        /**                                                                                            **/
        /** Factor          ==>    Int                                                                 **/
        /** Int             ==>    5                                                                   **/
        /**                                                                                            **/
        /************************************************************************************************/
        public  void GetFactInt(int m, int r) throws IOException{
                fps.format(ss[r]+"/GetFactInt: ExpS%x = %d; %n",m,(int) code.nval);
                switch ((int) code.nval) {                      // A number was found; the value is in code.nval; 
                case 0: 
                        fps.format(ss[r]+"Clear %n");
                        break;
                case 1: 
                        fps.format(ss[r]+"Load One %n");
                        break;
                default:
                        fps.format(ss[r]+"Jump L%03d   /Jump over data line %n", nextL+1);
                        fps.format("L%03d,",nextL);
                        fps.format(ss[r]+"Dec %d       /Store constant %n", (int) code.nval);
                        fps.format("L%03d,",nextL+1);
                        fps.format(ss[r]+"Load L%03d   /Save constant %n", nextL);
                        nextL+=2;
                        break;
                }                       
                fps.format(ss[r]+"Store ExpS%x %n", m);
                nextToken("GetFactInt",'i');            // move token past the integer
        }

        /************************************************************************************************/
        /** Routine GetFactExp produces MARIE code that evaluates a factor of the form ( Exp )         **/
        /** and stores it in ExpSm                                                                     **/
        /**                                                                                            **/
        /** Factor          ==>    ( Exp )                                                             **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetFactExp(int m, int r) throws IOException{
                fps.format(ss[r]+"/GetFactExp: ExpS%x = (Exp); \n", m);
                nextToken("GetFactExp",'(');                    // move token past the '('
                GetExp(m,r+1);                                                  // Evaluate Exp and store in ExpSm
                nextTokenCheck("GetFactExp",')');               // move token past the ')'
        }

        /************************************************************************************************/
        /** Routine GetFactInput produces MARIE code that evaluates a factor of the form in.nextInt    **/
        /** and stores it in ExpSm                                                                     **/
        /**                                                                                            **/
        /** Factor          ==>    in.nextInt                                                          **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetFactInput(int m, int r) throws IOException{
                fps.format(ss[r]+"/GetFactInput: ExpS%x = in.nextInt; %n", m);
                fps.format(ss[r]+"Input %n");
                fps.format(ss[r]+"Store ExpS%x /Save it %n", m);
                nextToken("GetFactInput",'i');   // move past the "in.nextInt"
        }       

        /************************************************************************************************/
        /** Routine GetFactArray produces MARIE code that evaluates a factor of the form VarName[Exp]  **/
        /** and stores it in ExpSm                                                                     **/
        /**                                                                                            **/
        /** Factor          ==>    VarName[Exp]                                                        **/
        /**      The VarName is in varName and '[' is in token                                         **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetFactArray(int m, int r, String varName) throws IOException{
                varName = GlobalLocalVar(varName);              // Concatenate with procedure name
                fps.format(ss[r]+"/GetFactArray: ExpS%x = %s[Exp]; %n", m,varName);
                nextTokenCheck("GetFactArray a[Exp]",'[');      // move token past the '[' in "a[Exp]"
                GetExp(m+1,r+1);                                                        // Evaluate the Exp and store in ExpS(m+1)
                nextTokenCheck("GetFactArray a[Exp]",']');      // move token past the ']' in "a[Exp]"
                fps.format(ss[r]+"Load %s      /Load address of a[0] %n",varName);  // ExpSm = a[ExpS(m+1)]  (or b)
                fps.format(ss[r]+"Add ExpS%x   /Add the value i=Exp to address of a[0] for address of a[i] %n", m+1);
                fps.format(ss[r]+"Store Temp0 %n");
                fps.format(ss[r]+"Clear %n");
                fps.format(ss[r]+"AddI Temp0  /Load the value of a[i] %n");
                fps.format(ss[r]+"Store ExpS%x /Save it %n", m);
        }

        /************************************************************************************************/
        /** Routine GetFactVar produces MARIE code that evaluates a factor of the form VarName         **/
        /** and stores it in ExpSm                                                                     **/
        /**                                                                                            **/
        /** Factor          ==>    VarName                                                             **/
        /**      The VarName is in varName and token has moved one past it.                            **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetFactVar(int m, int r, String varName) throws IOException{
                varName = GlobalLocalVar(varName);              // Concatenate with procedure name
                fps.format(ss[r]+"/GetFactVar: ExpS%x = %s; %n", m, code.sval);
                fps.format(ss[r]+"Load %s %n ", varName);
                fps.format(ss[r]+"Store ExpS%x %n", m);
        }

        /************************************************************************************************/
        /** Routine GetBooleanExp produces MARIE code that that evaluates a BooleanExp                 **/
        /** and stores it in ExpSm                                                                     **/
        /**                                                                                            **/
        /** BooleanExp      ==> BooleanTerm                                                            **/
        /**                 ==> BooleanTerm || ... || BooleanTerm                                      **/
        /**                                                                                            **/
        /**  (Note && has higher order of operations just like * does                                  **/
        /**   true || true && false  = true || (true && false)                                         **/
        /**                     not   (true || true) && false  )                                       **/
        /**                                                                                            **/
        /** true            ==>    positive integer                                                    **/
        /** false           ==>    zero                                                                **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetBooleanExp(int m, int r) throws IOException{
                fps.format(ss[r]+"/GetBooleanExp: ExpS%x = BooleanExp = BooleanTerm || ... || BooleanTerm;%n",m);
                GetBooleanTerm(m,r+1);                                                  // Read first Term and put it in ExpSm
                while( true ){
                        if(token=='|') {                                                        // Token after the term
                                fps.format(ss[r]+"/GetBooleanExp: ExpS%x = next BooleanTerm;%n",m+1);
                                nextToken("GetBooleanExp",'|');                 // move token past the '|'
                                nextTokenCheck("GetBooleanExp",'|');    // move token past the second '|'
                                GetBooleanTerm(m+1,r+1);                                // Read next BooleanTerm and put it in Exps(m+1)
                                fps.format(ss[r]+"/GetBooleanExp: ExpS%x = ExpS%x || ExpS%x %n",m,m,m+1);
                                fps.format(ss[r]+"/               Note false iff ExpS%x+ExpS%x = zero %n",m,m+1);
                                fps.format(ss[r]+"Load ExpS%x %n",m);
                                fps.format(ss[r]+"Add ExpS%x %n",m+1);
                                fps.format(ss[r]+"SkipCond 400 %n",m);
                                fps.format(ss[r]+"Jump L%03d   /Jump over data line %n", nextL);
                                fps.format(ss[r]+"Clear %n");
                                fps.format(ss[r]+"Jump L%03d   /Jump over data line %n", nextL+1);
                                fps.format("L%03d,", nextL);
                                fps.format(ss[r]+"Load One %n");
                                fps.format("L%03d,", nextL+1);
                                fps.format(ss[r]+"Store ExpS%x %n",m);
                                nextL+=2;
                        }
                        else
                                return;
                }
        }

        /************************************************************************************************/
        /** Routine GetBooleanTerm produces MARIE code that that evaluates a BooleanTerm               **/
        /** and stores it in ExpSm                                                                     **/
        /**                                                                                            **/
        /** BooleanTerm     ==> BooleanFactor                                                          **/
        /**                 ==> BooleanFactor && ... && BooleanFactor                                  **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetBooleanTerm(int m, int r) throws IOException{
                fps.format(ss[r]+"/GetBooleanTerm: ExpS%x = BooleanTerm = BooleanFact && ... && BooleanFact;%n",m);
                GetBooleanFact(m,r+1);                                                  // Read first Fact and put it in ExpSm
                while( true ){
                        if(token=='&') {                                                        // Token after the Fact
                                fps.format(ss[r]+"/GetBooleanTerm: ExpS%x = next BooleanFact;%n",m+1);
                                nextToken("GetBooleanTerm",'&');                // move token past the '&'
                                nextTokenCheck("GetBooleanTerm",'&');   // move token past the second '&'
                                GetBooleanFact(m+1,r+1);                                // Read next BooleanFact and put it in Exps(m+1)
                                fps.format(ss[r]+"/GetBooleanTerm: ExpS%x = ExpS%x || ExpS%x %n",m,m,m+1);
                                fps.format(ss[r]+"/                Note true iff ExpS%x+ExpS%x-2 = zero %n",m,m+1);
                                fps.format(ss[r]+"Load ExpS%x %n",m);
                                fps.format(ss[r]+"Add ExpS%x %n",m+1);
                                fps.format(ss[r]+"Subt One %n");
                                fps.format(ss[r]+"Subt One %n");
                                fps.format(ss[r]+"SkipCond 400 %n",m);
                                fps.format(ss[r]+"Jump L%03d   /Jump over data line %n", nextL);
                                fps.format(ss[r]+"Load One %n");
                                fps.format(ss[r]+"Jump L%03d   /Jump over data line %n", nextL+1);
                                fps.format("L%03d,", nextL);
                                fps.format(ss[r]+"Clear %n");
                                fps.format("L%03d,", nextL+1);
                                fps.format(ss[r]+"Store ExpS%x %n",m);
                                nextL+=2;
                        }
                        else
                                return;
                }
        }

        /************************************************************************************************/
        /** Routine GetBooleanFactor produces MARIE code that that evaluates a BooleanFactor           **/
        /** and stores it in ExpSm                                                                     **/
        /**                                                                                            **/
        /** BooleanFactor   ==> true|false                                                             **/
        /**                 ==> BooleanStatement                                                       **/
        /**                 ==> (BooleanExp)                                                           **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetBooleanFact(int m, int r) throws IOException{
                switch (token) { 
                case '(': 
                        fps.format(ss[r]+"/GetBooleanFact: ExpS%x = (BooleanExp); \n", m);
                        nextToken("GetBooleanFact (Exp)",'(');                  // move token past the '('
                        GetBooleanExp(m,r+1);                                                   // Evaluate Exp and store in ExpSm
                        nextTokenCheck("GetBooleanFact (Exp)",')');             // move token past the ')'
                        return;
                case StreamTokenizer.TT_WORD: 
                        switch (code.sval.charAt(0)){
                        case 't':                                                                               // code.sval is the token true.
                                fps.format(ss[r]+"/GetBooleanFact: ExpS%x = true; %n",m);
                                fps.format(ss[r]+"Load One %n");
                                fps.format(ss[r]+"Store ExpS%x %n", m);
                                nextTokenCheckString("GetBooleanFact true","true");     // move token past the true
                                return;
                        case 'f':                                                                               // code.sval is the token true.
                                fps.format(ss[r]+"/GetBooleanFact: ExpS%x = false; %n",m);
                                fps.format(ss[r]+"Clear %n");
                                fps.format(ss[r]+"Store ExpS%x %n", m);
                                nextTokenCheckString("GetBooleanFact false","false");   // move token past the true
                                return;
                        default:
                                fps.format(ss[r]+"/GetBooleanFact: ExpS%x = BooleanStatement; %n",m);
                                GetBooleanStatement(m,r+1); 
                                return;
                        }
                default:
                        fps.format(ss[r]+"/GetBooleanFact: ExpS%x = BooleanStatement; %n",m);
                        GetBooleanStatement(m,r+1); 
                        return;
                }
        }

        /************************************************************************************************/
        /** Routine GetBooleanStatement produces MARIE code that that evaluates a BooleanStatement     **/
        /** and stores it in ExpSm                                                                     **/
        /**                                                                                            **/
        /** BooleanStatement  ==> Exp ==|!=|<|<=|>|>=  Exp                                             **/
        /**                                                                                            **/
        /** true            ==>    positive integer                                                    **/
        /** false           ==>    zero                                                                **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetBooleanStatement(int m, int r) throws IOException{
                boolean eq = false;
                fps.format(ss[r]+"/GetBooleanStatement: ExpS%x = Exp ==|!=|<|<=|>|>=  Exp; %n",m);
                GetExp(m, r+1);
                switch (token){
                case '=':
                        nextToken("getBooleanStatement", '=');
                        nextTokenCheck("getBooleanStatement", '=');
                        GetExp(m+1,r+1);
                        fps.format(ss[r]+"Load ExpS%x %n",m);
                        fps.format(ss[r]+"Subt ExpS%x %n",m+1);
                        fps.format(ss[r]+"SkipCond 400 %n",m);
                        fps.format(ss[r]+"Jump L%03d   /Jump over data line %n", nextL);
                        fps.format(ss[r]+"Load One %n");
                        fps.format(ss[r]+"Jump L%03d   /Jump over data line %n", nextL+1);
                        fps.format("L%03d,", nextL);
                        fps.format(ss[r]+"Clear %n");
                        fps.format("L%03d,", nextL+1);
                        fps.format(ss[r]+"Store ExpS%x %n",m);
                        nextL+=2;
                        return;
                case '!':
                        nextToken("getBooleanStatement", '=');
                        nextTokenCheck("getBooleanStatement", '=');
                        GetExp(m+1,r+1);
                        fps.format(ss[r]+"Load ExpS%x  /ExpS%x = Test(ExpS%x - ExpS%x = 0); %n",m,m,m,m+1);
                        fps.format(ss[r]+"Subt ExpS%x %n",m+1);
                        fps.format(ss[r]+"SkipCond 400 %n",m);
                        fps.format(ss[r]+"Jump L%03d   /Jump over data line %n", nextL);
                        fps.format(ss[r]+"Clear %n");
                        fps.format(ss[r]+"Jump L%03d   /Jump over data line %n", nextL+1);
                        fps.format("L%03d,", nextL);
                        fps.format(ss[r]+"Load One %n");
                        fps.format("L%03d,", nextL+1);
                        fps.format(ss[r]+"Store ExpS%x %n",m);
                        nextL+=2;
                        return;
                case '<':
                        nextToken("getBooleanStatement", '<');
                        if (token=='='){
                                eq = true;
                                nextToken("getBooleanStatement", '=');
                        }
                        GetExp(m+1, r+1);
                        if (!eq) {
                                fps.format(ss[r]+"Load ExpS%x   /ExpS%x = Test(ExpS%x - ExpS%x < 0); %n",m,m,m,m+1);
                                fps.format(ss[r]+"Subt ExpS%x %n",m+1);
                        }
                        else {
                                fps.format(ss[r]+"Load ExpS%x   /ExpS%x = Test(ExpS%x - ExpS%x <= 0); %n",m,m,m,m+1);
                                fps.format(ss[r]+"Subt ExpS%x %n",m+1);
                                fps.format(ss[r]+"Subt One %n");                                
                        }               
                        fps.format(ss[r]+"SkipCond 000 %n",m);
                        fps.format(ss[r]+"Jump L%03d   /Jump over data line %n", nextL);
                        fps.format(ss[r]+"Load One %n");
                        fps.format(ss[r]+"Jump L%03d   /Jump over data line %n", nextL+1);
                        fps.format("L%03d,", nextL);
                        fps.format(ss[r]+"Clear %n");
                        fps.format("L%03d,", nextL+1);
                        fps.format(ss[r]+"Store ExpS%x %n",m);
                        nextL+=2;
                        return;
                case '>':
                        nextToken("getBooleanStatement", '>');
                        if (token=='='){
                                eq = true;
                                nextToken("getBooleanStatement", '=');
                        }
                        GetExp(m+1, r+1);
                        if (!eq) {
                                fps.format(ss[r]+"Load ExpS%x   /ExpS%x = Test(ExpS%x - ExpS%x > 0); %n",m,m,m,m+1);
                                fps.format(ss[r]+"Subt ExpS%x %n",m+1);
                        }
                        else {
                                fps.format(ss[r]+"Load ExpS%x   /ExpS%x = Test(ExpS%x - ExpS%x >= 0); %n",m,m,m,m+1);
                                fps.format(ss[r]+"Subt ExpS%x %n",m+1);
                                fps.format(ss[r]+"Add One %n");                         
                        }               
                        fps.format(ss[r]+"SkipCond 800 %n",m);
                        fps.format(ss[r]+"Jump L%03d   /Jump over data line %n", nextL);
                        fps.format(ss[r]+"Load One %n");
                        fps.format(ss[r]+"Jump L%03d   /Jump over data line %n", nextL+1);
                        fps.format("L%03d,", nextL);
                        fps.format(ss[r]+"Clear %n");
                        fps.format("L%03d,", nextL+1);
                        fps.format(ss[r]+"Store ExpS%x %n",m);
                        nextL+=2;
                        return;
                }
        }

        /************************************************************************************************/
        /** Routine GetIfStatement produces MARIE code that                                            **/
        /**     that executes the following JoshJava statements:                                       **/
        /**                                                                                            **/
        /** IfStatement     ==>    if( BooleanExp )                                                    **/
        /**                          BlockCode                                                         **/
        /**                 ==>    if( BooleanExp )                                                    **/
        /**                          BlockCode                                                         **/
        /**                        else                                                                **/
        /**                          BlockCode                                                         **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetIfStatement(int r) throws IOException{
                int currentL = nextL;
                nextL+=2;
                fps.format(ss[r]+"/GetIfStatement:%n");
                nextTokenCheckString("GetIfStatement","if");
                nextTokenCheck("GetIfStatement",'(');
                GetBooleanExp(0,r+1);
                nextTokenCheck("GetIfStatement",')');
                fps.format(ss[r]+"SkipCond 800 /If(true) Skip to 1st block of code %n");
                fps.format(ss[r]+"Jump L%03d   /Else Jump to ElseCode %n", currentL);
                GetBlockCode(r+1);
                fps.format(ss[r]+"Jump L%03d   /Jump to EndIf %n", currentL+1);
                fps.format("L%03d,", currentL);
                fps.format(ss[r]+"Clear        /ElseCode %n");  
                if (token==StreamTokenizer.TT_WORD && code.sval.equals("else")) {
                        nextToken("GetIfStatement",'e'); // Moving past the "else"
                        GetBlockCode(r+1);
                }
                fps.format("L%03d,", currentL+1);
                fps.format(ss[r]+"Clear       /EndIf %n");
        }
        /************************************************************************************************/
        /** Routine GetWhileStatement produces MARIE code                                              **/
        /**     that executes the following JoshJava statements:                                       **/
        /**                                                                                            **/
        /** WhileStatement  ==>    while( BooleanExp )                                                 **/
        /**                          BlockCode                                                         **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetWhileStatement(int r) throws IOException{
                int currentL = nextL;
                nextL+=2;
                fps.format(ss[r]+"/GetWhileStatement:%n");
                nextTokenCheckString("GetWhileStatement","while");
                nextTokenCheck("GetWhileStatement",'(');
                fps.format("L%03d,", currentL+1);
                fps.format(ss[r]+"Clear        /TopWhile %n");  
                GetBooleanExp(0,r+1);
                nextTokenCheck("GetWhileStatement",')');
                fps.format(ss[r]+"SkipCond 800 /If(true) Skip to code in while %n");
                fps.format(ss[r]+"Jump L%03d   /Else Jump to EndWhile %n", currentL);
                fps.format(ss[r]+"/Code in while%n");
                GetBlockCode(r+1);
                fps.format(ss[r]+"Jump L%03d   /Jump back to TopWhile %n", currentL+1);
                fps.format("L%03d,", currentL);
                fps.format(ss[r]+"Clear       /EndWhile %n");  
        }

        /************************************************************************************************/
        /** Routine GetOut produces MARIE code that executes the following JoshJava statements:        **/
        /**                                                                                            **/
        /** OutPut          ==>    System.out.println(Factor+"Hello World"+Factor);                    **/
        /**                 ==>    System.out.print("Hello\nWorld"+Factor);                            **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetOutPut(int r) throws IOException{
                boolean println = false;

                fps.format(ss[r]+"/GetOutPut:%n");
                if(code.sval.equals("System.out.println"))
                        println = true;
                nextToken("GetOutPut",'S');
                nextTokenCheck("GetOutPut",'(');
                while(true) {
                        if (token == '"') {
                                if( ascii ) 
                                        OutPutString(r+1);
                                nextToken("GetOutPut",'"');
                        }
                        else {
                                fps.format(ss[r+1]+"/Output Factor %n");
                                GetFact(0,r+2);
                                fps.format(ss[r+1]+"Load ExpS%x %n",0);
                                if( ascii ) {
                                        fps.format(ss[r+1]+"Store Mx %n");
                                        fps.format(ss[r+1]+"JnS PrintDec %n");
                                }
                                else
                                        fps.format(ss[r+1]+"Output %n");
                        }
                        if(token == ')') 
                                break;
                        nextTokenCheck("GetOutPut",'+');
                        fps.format(ss[r]+"/GetOutPut after +:%n");
                }
                nextTokenCheck("GetOutPut",')');
                nextTokenCheck("GetOutPut",';');
                if(println && ascii) {
                        fps.format(ss[r]+"Load AsciiCR /Output a return character %n");
                        fps.format(ss[r]+"Output %n");
                }
        }

        /************************************************************************************************/
        /** Routine OutPutString produces MARIE code that outputs a string                             **/
        /************************************************************************************************/

        public  void OutPutString(int r) throws IOException{
                fps.format(ss[r]+"/Output string%n");
                fps.format(ss[r]+"Load L%03d   /Get command for loading first char %n",nextL+2);
                fps.format(ss[r]+"Store L%03d  /Store it where it will be executed for loading next char %n",nextL);
                fps.format(ss[r]+"Load L%03d   /Get number of characters to print %n",nextL+3);
                fps.format(ss[r]+"Store L%03d  /Store it in the number left to print %n",nextL+4);
                fps.format(ss[r]+"/Loop printing each char %n");
                fps.format("L%03d,", nextL);
                fps.format(ss[r]+"Hex 0        /Command for loading next char %n");
                fps.format(ss[r]+"Output       /Output next char %n");
                fps.format(ss[r]+"Load L%03d   /Incrementing command, increments the cell address that is being loaded from %n",nextL);
                fps.format(ss[r]+"Add One %n");
                fps.format(ss[r]+"Store L%03d  %n",nextL);
                fps.format(ss[r]+"Load L%03d   /Decrementing number of chars left to print %n",nextL+4);
                fps.format(ss[r]+"Subt One %n");
                fps.format(ss[r]+"Store L%03d  %n",nextL+4);
                fps.format(ss[r]+"Skipcond 400 /Skip if number of chars left to print is zero %n",nextL+4);
                fps.format(ss[r]+"Jump L%03d  %n",nextL);
                fps.format(ss[r]+"/End Loop %n");
                fps.format(ss[r]+"Jump L%03d   /Jump over String Data %n",nextL+5);
                fps.format(ss[r]+"/Data cells containing the chars to output %n");
                fps.format("L%03d,", nextL+1);
                for( int i=0; i< code.sval.length(); i++ ) {
                        int c = (int) code.sval.charAt(i);
                        if( c== 10 )  
                                c= 13; // Change New Line to Carriage Return
                        if( c== 32 )  
                                c= 95; // Change Space to Under Score
                        fps.format(ss[r]+"Hex %x      /%c %n", c, (char) c );
                }
                fps.format("L%03d,", nextL+2);
                fps.format(ss[r]+"Load L%03d   /Give command for loading first char %n",nextL+1);
                fps.format("L%03d,", nextL+3);
                fps.format(ss[r]+"Dec %d       /Number of chars to print %n",code.sval.length());
                fps.format("L%03d,", nextL+4);
                fps.format(ss[r]+"Dec 0       /Number of chars left to print %n",code.sval.length() );
                fps.format("L%03d,", nextL+5);
                fps.format(ss[r]+"Clear       /End of String Data %n");
                nextL += 6;
        }


        /************************************************************************************************/
        /** Routine Procedure produces MARIE code that executes the following JoshJava statements:     **/
        /** and stores it in ExpSm                                                                     **/
        /**                                                                                            **/
        /** Procedure       ==>    ProcedureName( Exp, Exp, Exp, ..., Exp )                            **/
        /**      The VarName is in varName and '(' is in token                                         **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetProcedureCall(int m, int r, String CalledProcedure) throws IOException{
                fps.format(ss[r]+"/GetProcedureCall: %n");
                nextTokenCheck("GetProcedureCall",'('); 
                for( int i=0; token!=')'; ++i ) {
                        GetExp(m,r+1);                                                  // Evaluate Exp and store it in ExpS0
                        fps.format(ss[r]+"Load ExpS%x %n",m);
                        fps.format(ss[r]+"Store input%x  /Copy out to input %n", i);
                        if( token==',' )
                                nextTokenCheck("GetProcedureCall",',');
                }
                nextTokenCheck("GetProcedureCall",')');                 
                PushOnStack(r+1,"B_ExpS","L_ExpS");
                PushOnStack(r+1,"B_"+procedureName,"L_"+procedureName);
                fps.format(ss[r]+"JnS %s   /Jump to routine %n","J_"+CalledProcedure);
                PopOffStack(r+1,"B_"+procedureName,"L_"+procedureName);
                PopOffStack(r+1,"B_ExpS","L_ExpS");
                fps.format(ss[r]+"Load Return %n");
                fps.format(ss[r]+"Store ExpS%x %n",m);
        }
        
        /************************************************************************************************/
        /** Routine PushOnStack produces MARIE code that copies a block of data onto the recursion     **/
        /** stack                                                                                      **/
        /**                                                                                            **/
        /** B_label: label of cell containing the address one before the block to copy                 **/
        /** L_label: label of cell containing length of the block to copy                              **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void PushOnStack( int r, String B_label, String L_label ) throws IOException{
                fps.format(ss[r]+"Load %s         /Address one before block to copy %n",B_label);
                fps.format(ss[r]+"Add One         /Address of beginning of block to copy %n");
                fps.format(ss[r]+"Store CopyA     /Argument for Copy program %n");
                fps.format(ss[r]+"Load %s         /Lenght of the block to copy %n",L_label);
                fps.format(ss[r]+"Store CopyL     /Argument for Copy program %n");
                fps.format(ss[r]+"Load StackP     /End of Stack %n");
                fps.format(ss[r]+"Store CopyB     /Argument for Copy program %n");
                fps.format(ss[r]+"Add CopyL       /Move End of Stack %n");
                fps.format(ss[r]+"Store StackP    /End of Stack %n");
                fps.format(ss[r]+"JnS Copy        /Jump to Copy routine %n");
        }

        /************************************************************************************************/
        /** Routine PopOffStack produces MARIE code that copies a block of data off the recursion      **/
        /** stack                                                                                      **/
        /**                                                                                            **/
        /** B_label: label of cell containing the address one before the block to receive data         **/
        /** L_label: label of cell containing length of the block to copy                              **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void PopOffStack( int r, String B_label, String L_label ) throws IOException{
                fps.format(ss[r]+"Load %s         /Address one before block to copy to %n",B_label);
                fps.format(ss[r]+"Add One         /Address of beginning of block to copy to %n");
                fps.format(ss[r]+"Store CopyB     /Argument for Copy program %n");
                fps.format(ss[r]+"Load %s         /Lenght of the block to copy %n",L_label);
                fps.format(ss[r]+"Store CopyL     /Argument for Copy program %n");
                fps.format(ss[r]+"Load StackP     /End of Stack %n");
                fps.format(ss[r]+"Subt CopyL      /Move End of Stack %n");              
                fps.format(ss[r]+"Store CopyA     /Argument for Copy program %n");
                fps.format(ss[r]+"Store StackP    /End of Stack %n");
                fps.format(ss[r]+"JnS Copy        /Jump to Copy routine %n");
        }
        
        /************************************************************************************************/
        /** Routine GetReturn produces MARIE code that executes the following JoshJava statements:     **/
        /**                                                                                            **/
        /** Return          ==>    return;                                                             **/
        /**                 ==>    return Exp;                                                         **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void GetReturn(int r) throws IOException{
                fps.format(ss[r]+"/GetReturn: return Exp; %n");
                nextTokenCheckString("GetReturn","return"); 
                if( token == ';') 
                        fps.format(ss[r]+"Clear %n");           // Returns zero when not specified
                else {
                        GetExp(0,r+1);                                          // Evaluate Exp and store it in ExpS0
                        fps.format(ss[r]+"Load ExpS0%n");
                }
                fps.format(ss[r]+"Store Return %n");
                fps.format(ss[r]+"JumpI %s   /Return to calling program %n", "J_"+procedureName);               
                nextTokenCheck("GetReturn",';');                // move token past the ';' in "return Exp;"
        }

        /************************************************************************************************/
        /** Routine CompleteCode produces the MARIE code required at the end of the program            **/
        /**    for setting up the Stack Frame Stack                                                    **/
        /**                                                                                            **/
        /************************************************************************************************/

        public  void CompleteCode() throws IOException{
                fps.format("%n/**********************************************************************%n");    
                fps.format("/** Recursion Stack begins here %n");                       
                fps.format("/**********************************************************************%n%n");    
                fps.format("B_Stack, Hex 0        / The address of beginning the recursion stackframe %n");
                fileOutputStream.close();
        }

        /************************************************************************************************/
        /************************************************************************************************/
        /**                                                                                            **/
        /**             File and Error Routines                                                        **/
        /**            -------------------------                                                       **/
        /**                                                                                            **/
        /************************************************************************************************/
        /************************************************************************************************/

        /************************************************************************************************/
        /** Routine nextToken gets the next token                                                      **/
        /**    S = name of GetT procedure                                                              **/
        /**    c = the expected current token                                                          **/
        /**    Gets the next token and puts it in token                                                **/
        /**    If(debugging) Prints string S, previous token, and next token found                     **/
        /************************************************************************************************/
        public  void nextToken(String S, char c) throws IOException{
                token = code.nextToken();
                if( debug ) {
                        System.out.format("%-15s: moving past %c: Token is ",S,c);
                        printToken();
                }
        }

        /************************************************************************************************/
        /** Routine nextTokenCheck checks the current token and gets the next token                    **/
        /**    S = name of GetT procedure                                                              **/
        /**    c = the expected current token                                                          **/
        /**    If( current token is not c ) Gives Error message                                        **/
        /**    Gets the next token and puts it in token                                                **/
        /**    If(debugging) Prints string S, previous token, and next token found                     **/
        /************************************************************************************************/
        public  void nextTokenCheck(String S, char c) throws IOException{
                if(token!=c) {          
                        System.out.format("* Error: %s: Expected %c: Token is ",S,c);
                        printToken();
                        System.in.read();
                        // while( token != StreamTokenizer.TT_EOF && token!=';' ) nextToken("Recover",' '); // move token past non ';'
                        return;
                }
                nextToken(S,c); 
        }       

        /************************************************************************************************/
        /** Routine nextTokenCheckString checks the current token and gets the next token              **/
        /**    S = name of GetT procedure                                                              **/
        /**    T = the expected current token                                                          **/
        /**    If( current token is not T ) Gives Error message                                        **/
        /**    Gets the next token and puts it in token                                                **/
        /**    If(debugging) Prints string S, previous token, and next token found                     **/
        /************************************************************************************************/
        public  void nextTokenCheckString(String S, String T) throws IOException{
                if(!code.sval.equals(T)) {              
                        System.out.format("* Error: %s: Expected %s: Token is ",S,T);
                        printToken();
                        System.in.read();
                        while( token != StreamTokenizer.TT_EOF && token!=';' ) nextToken("Recover",' '); // move token past non ';'
                        return;
                }
                nextToken(S,T.charAt(0));       
        }       

        /************************************************************************************************/
        /** Print token                                                                                                                                                            **/
        /************************************************************************************************/
        public  void printToken() throws IOException{
                switch (token) { 
                case StreamTokenizer.TT_NUMBER: // A number was found; the value is in nval double num = code.nval; 
                        System.out.println(code.nval);
                        break; 
                case StreamTokenizer.TT_WORD:   // A word was found; the value is in sval String word = code.sval; 
                        System.out.println(code.sval);
                        break; 
                case '"': // A string like "Hello World" was found; the value is in sval String word = code.sval; 
                        System.out.println(code.sval);
                        break; 
                default: // A regular character was found; the value is the token itself char ch = (char)code.ttype; 
                        System.out.println((char) token);
                        break; 
                }
        }

        /************************************************************************************************/
        /**    Set up Input and Output Files                                                                                                               **/
        /************************************************************************************************/
        public void HandleFiles(String filename) throws IOException{
                String joshFileName   = filename+".jj";
                String marieFileName  = filename+".mas";
                String memorycodeName = "memorycode.txt";
                String subroutinesName= "subroutines.txt";
                String s;
                BufferedReader fbr;

                // Open MARIE Output file.
                fileOutputStream = new FileOutputStream(marieFileName);
                fps = new PrintStream(fileOutputStream);

                // Copies file memorycode containing all the MARIE data structures into code                    
                fbr = new BufferedReader(new FileReader(memorycodeName));
                while ((s=fbr.readLine()) != null)
                        fps.println(s);
                fbr.close();

                // for(i=0040 to 008F)  Hex i  Used for a,b,Multa,Multb,DecStr
                for(int i=3*16; i<6*16; ++i )
                        fps.format("        Hex %x %n",i);      

                // Copies file subroutines containing all the MARIE subroutines into code               
                fbr = new BufferedReader(new FileReader(subroutinesName));
                while ((s=fbr.readLine()) != null)
                        fps.println(s);
                fbr.close();

                // Copies in a copy of JoshJava code as a comment.
                fps.println("");                
                fps.println("   /********************* JoshJava Code to Compile ****************************/");                
                fbr = new BufferedReader(new FileReader(joshFileName));
                while ((s=fbr.readLine()) != null)
                        fps.println("   /** "+s);
                fps.println("   /***************************************************************************/");                
                fps.println("");                
                fbr.close();

                // Opens JoshJava code to be tokenized.
                FileReader rd = null;
                try {
                        rd = new FileReader(joshFileName);
                } 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 */

                ss[0] = "       ";                                      // Routines at depth r will be indented by ss[r] = tab + 2r blanks
                for(int i=1; i<16; i++ ) 
                        ss[i] = ss[i-1]+"  ";
        }
}

