#include "./inter.h"

//NAME          : Anand Kumar Chauhan
//        span>:
//COURSE        : 5319(Advanced Compiler)
//HOME WORK     : Project 
//LAST MODIFIED : 04/23/01
//SUMBITTED TO  : Dr. Koh



//Class Labels holds the Lable Table
//Class Symbole holds the Symbole Table
//Class Program holds the program string read form the Disk
//Object Instruction_Queue holds the decoded instructions
//The whole process is executed by Do_It() function, which can be seen
//to find out the exect sequence of Interpretation, like Scanning,Parsing,
//Instruction Queue Formation




class Lable
{
      private :
            String *Name;
            int Index;
      public :
//          Lable(int);//constructer sets all Index to 0, and Name to NULL
            inline void *Constructer(int);
            inline char *Get_Name(void);//Lable_Name Get_Lable_Name(Lable_Index)
            inline void *Set_Name(char *);//Get_Lable_Name(Lable_Index,Lable_Name)
            inline int Get_Value(void);//Lable_Name Get_Lable_Name(Lable_Index)
            inline void *Set_Value(int);//Get_Lable_Name(Lable_Index,Lable_Name)
};


/*
Lable::Lable(int i=MAX)
{
      Name=new String(i);
      Index=0;
}
*/

void *Lable::Constructer(int i=MAX)
{
      Name=new String;
      Name->Constructer(i);
      Index=0;
      return(NULL);
}

char *Lable::Get_Name(void)
{
      return(Name->Get());
}

void *Lable::Set_Name(char *c)
{
      Name->Set(c);
      return(NULL);    
}

int Lable::Get_Value(void)
{
      return Index;
}



void *Lable::Set_Value(int n)
{
      Index=n;
      return(NULL);
}

class Symbole
{
      private :
            String *Name;
            long Value;
           
      public :
//          Symbole(int);
            inline void *Constructer(int);
            inline void *Set_Name(char *);
            inline char *Get_Name(void);
            inline void *Set_Value(long);
            inline long Get_Value(void);
};

/*
Symbole::Symbole(int i=MAX)
{
      Name=new String(i);
      Value=0;
}
*/

void *Symbole::Constructer(int i=MAX)
{
      Name=new String;
      Name->Constructer(i);
      Value=0;
      return(NULL);
}
void *Symbole::Set_Name(char *name)
{
      Name->Set(name);
      return(NULL);
}

char *Symbole::Get_Name(void)
{
      return(Name->Get());
}

void *Symbole::Set_Value(long value)
{
      Value=value;
      return(NULL);
}

long Symbole::Get_Value(void)
{
      return Value;
}

class Interpret
{
      private :
            String *Program;               //HOLDS WHOLE SOURCE PROGRAM
            char *Shell_Command;
            int Trace_Flag;
//          Lable *Lable_Table;
            Symbole *Symbole_Table;
           
            int Print_Index[MAX_INSTRUCTIONS][1];      //HOLDS NUMBER OF WORDS IN EACH PRINT STATEMENT
            int Command_Index[MAX_INSTRUCTIONS][1];
            Lable Lable_Table[MAX_LABLES];
            Integer_Set *Loop_Up_Down;
            Stack *While_Stack;    
            Stack *For_Stack;
            String_Set *Instruction;
            String_Set *Print_List;
            String_Set *Keyword_List;
            int Number_of_Words;
            int Number_of_Symboles;
            int Number_of_Lables;
            int Number_of_Instructions;
            String *Word;                        //EACH WORD
            char Source_Name[12];              //HOLDS THE NAME OF THE C SOURCE FILE NAME
            char Input_Name[12];               //HOLDS THE NAME OF THE EXECUTABLE FILE NAME
            ifstream Source;              //SOURCE FILE OBJECT
            inline void *Init_Str(void);        //MAKES THE STRING STR ALL NUlL
            inline void *Scan_Code(void);       //PUTS THE SOURCE PROGRAM FROM FILE INTO PROGRAM ARRAY P
            inline void *Get_Symbole_Table(void);      //DETECTS AND PUTS THE VARIABLE FROM PROGRAM ARRAY INTO VARIABLE ARRAY
            inline void *Execute_Code(void);      //MAKES CHANGES IN SYMBOLE_TABLE ARRAY AS EACH INSTRUCTION IN PROGRAM ARRAY IS BEING EXECUTED
            inline void *Display_Code(void);      //DISPLAYS THE CONTENTS OF PROGRAM IF DESIRED
            inline int Operator(char *);       //CHECKS IF THE ARGUMENT IS ONE OF THE OPERATORS
            inline void *Operate(char *,char *,char *,char *,char *);//OPERATOR(RESULT STORAGE, OPERAND1,OPERAND2,OPERATOR)
            inline int Lable1(char *);         //CHECKS IF THE PARAMETER IS A LABEl
            inline int Goto(char *);         //CHECKS IF PARAMETER PASSED IS GOTO
            inline int If(char *);               //CHECKS IF THE PARAMETER IF IF
            inline int Int(char *);               //CHECK IF THE PARAMETER IF INT
            inline int Duplicate(char *);            //CHECKS IF THE VARIABLE ALREADY EXISTS IN THE TABLE
            inline int Same(char *,char *);        //CKECKS IF THE PASSED PARAMETERS ARE EQUAl
            inline int Found(char *);         //CHECKS IF ARGUMENT EXISTS IN SYMBOLE_TABLE ARRAY
            inline int Digit(char *);         //CHECKS IF THE ARGUMENT IS A DIGIT
            inline int Decode(char *);         //RETURNS THE NUMERICAL EQUIVALANT OF THE DIGIT
            inline int Variable(char *);       //CHECKS IF ARGUMENT IS A VARIABLE
            inline int Constant(char *);       //CHECKS IF ARGUMENT IS A CONSTANT
            inline void *Set_Instruction_Queue(void);//MAKES THE INSTRUCTION QUE READY FOR EXECUTION
            inline void *Display_Instruction_Queue(void);
            inline void *Display_Instruction_i(int);
            inline void *Display_Lable_Table(void);
            inline int Get_Lable_Value(char *);      //RETURNS THE VALUE OF LABEL ARGUMENT FROM LABLE TABLE
            inline long Get_Symbole_Value(char*);      //RETURNS THE VALUE OF THE SYMBOLE PARAMETER FROM SYMBOLE TABLE
            inline int Get_Lable_Index(char *);      //RETURNS LABLE INDEX
            inline int Get_Symbole_Index(char *);      //RETURNS SYMBOLE INDEX
            inline void *Set_Constants(void);      //MAKES THE VALUE CONSTANTS APPEARING IN THE SYMBOLE TABLE EQUAL TO THEIR NUMERICAL QEUIVALANTS
            inline void *Update_Symbole_Table(char *,char *);//SETS THE VALUE OF FIRST ARGUMENT(A VARIABLE) EQUAL TO VALUE OF SECOND ARGUMENT (CAN BE A CONSTANT ALSO) IN SYMBOLE TABLE
            inline void *Display_Symbole_Table(void);//DISPLAYS THE VARIABLE TABLE
            inline void *Reset_Symbole_Table(void);      //MAKES VALUES OF ALL SYMBOLES = 0, WHICH WERE ALTERED MY THE PRIVIOUS INPUT
            inline long Get_Value(char *);            //TAKES INPUT AN OBJECT OF STRING CLASS AND RETURNS ITS VALUE
            inline int Print(char *);         //CHEKS IF PARAMETER IS PRINT
            inline int Input(char *);         //CHECK IF PARAMETER IS INPUT
            inline int In_Print_List(char *);      //CHECKS IF PARAMETER IS PRINTABLE CHARECTER
            inline int In_Keyword_List(char *);      //CHECKS IF PARAMETER IS A KEYWORD
            inline void *Set_Print_List(void);      //INITIALIZE PRINT LIST
            inline void *Set_Keyword_List(void);      //INITIALIZE KEYWORDS LIST
            inline void *Print_Char(char *,char *);//PRINTS THE STRING TAKING CARE OF FORMATTING CHARS
            inline long Pow(long,long);         //RETURNS X ^ Y
            inline int Condition_True(char *,char *,char *);//OPERAND1,OPERATOR,OPERAND2, RETURNS TRUE IF CONDITION SATISFIED
      public:
            Interpret(char *,char *);              //CONSTRUCTER SCAN(SOURCE,INPUT)
            inline void *Do_It(void);           //INITIATES THE WHOLE PROCESS
            inline void *Terminate(void);
};

Interpret::Interpret(char *Src,char *trace_flag)//constructer
{
      if(strcmp(trace_flag,(char *)"t")==0)
      {
            Trace_Flag=1;
      }
      else
      {
            Trace_Flag=0;
      }    
      int i;
      Shell_Command=new char[COMMAND_STRING_SIZE];
      For_Stack=new Stack;
      While_Stack=new Stack;
      Loop_Up_Down=new Integer_Set;     
      Loop_Up_Down->Constructer(LOOP_STACK_SIZE);
      Word=new String;
      Word->Constructer(FIELD_SIZE);
      Program=new String[PROG_SIZE];
      for(i=0;i<PROG_SIZE;Program[i].Constructer(FIELD_SIZE),i++);
      Instruction=new String_Set[MAX_INSTRUCTIONS];
      for(i=0;i<MAX_INSTRUCTIONS;i++)
      {
            Instruction[i].Constructer(MAX_FIELDS_PER_INSTRUCTION,FIELD_SIZE);
      }
      Symbole_Table=new Symbole[MAX_SYMBOLES];
      for(i=0;i<MAX_SYMBOLES;Symbole_Table[i].Constructer(FIELD_SIZE),i++);
      for(i=0;i<MAX_LABLES;Lable_Table[i].Constructer(FIELD_SIZE),i++);
      strcpy(Source_Name,Src);//class source name =  paramater source name
      Source.open(Src);//open source file
      Print_List=new String_Set;
      Print_List->Constructer(MAX_FORMATTING_CHARS,FORMATTING_CHAR_SIZE);
      Keyword_List=new String_Set;
      Keyword_List->Constructer(MAX_KEYWORDS,KEYWORD_SIZE);
      Number_of_Words=0;
      Number_of_Symboles=0;
      Number_of_Lables=0;
      Number_of_Instructions=0;
      Set_Print_List();
      Set_Keyword_List();
}

void *Interpret::Set_Print_List(void)
{
      Print_List->Set(0,(char *)"CR");          //CARRAGE RETURN
      Print_List->Set(1,(char *)"LF");                //LINE FEED
      Print_List->Set(2,(char *)"SP");                //SPACE
      Print_List->Set(3,(char *)"DP");                //DUPLICATE
      Print_List->Set(4,(char *)"NS");          //NO SPACE beause one space goes by default
      Print_List->Set(5,(char *)"$");                 //END OF STRING
      return(NULL);
}

long Interpret::Pow(long x,long y)
{
      long i;
      long Ans;
      for(i=0,Ans=1;i<y;Ans*=x,i++);
      return(Ans);
}

int Interpret::In_Print_List(char *c)
{
      int Flag;
      int i;
      for(Flag=0,i=0;i<NUMBER_OF_FORMATTING_CHARS;i++)
      {    
            if(strcmp(Print_List->Get(i),c)==0)
            {
                  Flag=1;
            }
      }
      return(Flag);
}

void *Interpret::Set_Keyword_List(void)
{
      Keyword_List->Set(0,(char *)"INT");
      Keyword_List->Set(1,(char *)"PRINT");      
      Keyword_List->Set(2,(char *)"INPUT");
      Keyword_List->Set(3,(char *)"WHILE");
      Keyword_List->Set(4,(char *)"END_WHILE");
      Keyword_List->Set(5,(char *)"SHELL_COMMAND");
      Keyword_List->Set(5,(char *)"PAUSE");
     
      return(NULL);
}
     

int Interpret::In_Keyword_List(char *c)
{
      int Flag;
      int i;
      for(Flag=0,i=0;i<NUMBER_OF_KEYWORDS;i++)
      {    
            if(strcmp(Keyword_List->Get(i),c)==0);
            {
                  Flag=1;
            }
      }
      return(Flag);
}

void *Interpret::Init_Str(void)
{
      Word->Reset();
      return(NULL);
}


void *Interpret::Set_Constants(void)
{
      int i;
      for(i=0;i<Number_of_Symboles;i++)
      {
            if(Digit(Symbole_Table[i].Get_Name()))
            {
                  Symbole_Table[i].Set_Value(Decode(Symbole_Table[i].Get_Name()));
            }
      }
      return(NULL);
}

void *Interpret::Reset_Symbole_Table(void)
{
      int i;
      for(i=0;i<Number_of_Symboles;i++)
      {
            Symbole_Table[i].Set_Value(0);
      }
      Set_Constants();
      return(NULL);
}



int Interpret::Get_Lable_Value(char *c)
{
      int i;
      int Value;
      for(i=0;i<Number_of_Lables;i++)
      {
            if(strcmp(Lable_Table[i].Get_Name(),c)==0)
            {
                  Value=Lable_Table[i].Get_Value();
            }
      }
      return Value;
}

int Interpret::Get_Lable_Index(char *c)
{
      int i;
      int Index;
      for(i=0;i<Number_of_Lables;i++)
      {
            if (strcmp(Lable_Table[i].Get_Name(),c)==0)
            {
                  Index=i;
            }
      }
      return Index;
}

int Interpret::Get_Symbole_Index(char *c)
{
      int i;
      int Index;
      for(i=0;i<Number_of_Symboles;i++)
      {
            if(strcmp(c,Symbole_Table[i].Get_Name())==0)
            {
                  Index=i;
            }
      }
      return Index;
}

long Interpret::Get_Symbole_Value(char *c)
{
      int i;
      long Value;
      for(i=0;i<Number_of_Symboles;i++)
      {
            if(strcmp(c,Symbole_Table[i].Get_Name())==0)
            {
                  Value=Symbole_Table[i].Get_Value();
            }
      }
      return Value;
}

void *Interpret::Display_Lable_Table(void)
{
      int i;
      for(i=0;i<Number_of_Lables;i++)
      {
            cout<<"\n"<<Lable_Table[i].Get_Name()<<" "<<Lable_Table[i].Get_Value();
      }
      return(NULL);
}

void *Interpret::Scan_Code(void)
{
      char str[FIELD_SIZE];
      for(Number_of_Words=0;(Source);Number_of_Words++)
      {
            memset(str,'\0',sizeof(str));
            Source>>str;
            Program[Number_of_Words].Set(str);
      }
      return(NULL);
}


void *Interpret::Set_Instruction_Queue(void)
//also generates Sybole Table and Lable Table apart form Instruction Queue
{
      int p;                                    //INDEX OF PROGRAM TABLE
      int i;                                    //INDEX OF SYMBOLE TABLE
      int l;                                    //INDEX OF LABEL TABLE
      int j;
//    int Flag;
//    char Str[MAX];
//    char Master[MAX];
//    char Sub[MAX];
      String *Token;
      Token=new String;
      Token->Constructer(FIELD_SIZE);
      for(p=0,i=0,l=0;p<Number_of_Words; )            //INSTRUCTION COUNT NOT TO BE INCREMENTED WHEN LABLE IS ENCOUNTRED
      {
            Token->Reset();  
            Token->Set(Program[p].Get());
            if(Lable1(Token->Get()))          //IF TOKEN IS A LABLE
            {
                  Lable_Table[l].Set_Name(Token->Get());
                  Lable_Table[l].Set_Value(i);
                  p++;
                  l++;
            }
            else if(If(Token->Get()))                //IF TOKEN IS AN IF STATEMENT
            {
                  Instruction[i].Set(0,(char *)"IF");
                  Instruction[i].Set(1,Program[p+1].Get());
                  Instruction[i].Set(2,Program[p+2].Get());
                  Instruction[i].Set(3,Program[p+3].Get());
                  Instruction[i].Set(4,Program[p+4].Get());
                  Instruction[i].Set(5,Program[p+5].Get());
                  p+=6;
                  i++;
            }
            else if(Goto(Token->Get()))              //IF TOKEN IS GOTO
            {
                  Instruction[i].Set(0,(char *)"GOTO");
                  Instruction[i].Set(1,Program[p+1].Get());
                  p+=2;
                  i++;
            }
            else if(Int(Token->Get()))               //IF TOKEN IS INT
            {
                  Instruction[i].Set(0,Token->Get());
                  Instruction[i].Set(1,Program[p+1].Get());
                  p+=2;
                  i++; 
            }
            else if(Print(Token->Get()))             //IF TOKEN IS PRINT
            {

                  Instruction[i].Set(0,Token->Get());
                  j=1; 
                  while(strcmp(Program[p+j].Get(),(char *)"$")!=0)
                  {
                        Instruction[i].Set(j,Program[p+j].Get());
                        j++;
                  }
                  Instruction[i].Set(j,Program[p+j].Get());
                  Print_Index[i][0]=j;
                  p+=(j+1);
                  i++;
            }
            else if(strcmp(Token->Get(),(char *)"SHELL_COMMAND")==0)
            {
                  Instruction[i].Set(0,Token->Get());
                  j=1; 
                  while(strcmp(Program[p+j].Get(),(char *)"$")!=0)
                  {
                        Instruction[i].Set(j,Program[p+j].Get());
                        j++;
                  }
                  Instruction[i].Set(j,Program[p+j].Get());
                  Command_Index[i][0]=j;
                  p+=(j+1);
                  i++;
            }
            else if(strcmp(Token->Get(),(char *)"PAUSE")==0)
            {
                  Instruction[i].Set(0,(char *)"PAUSE");
                  p+=1;
                  i++;
            }    
            else if(Input(Token->Get()))             //IF TOKEN IS INPUT
            {
                  Instruction[i].Set(0,(char *)"INPUT");      
                  Instruction[i].Set(1,Program[p+1].Get());
                  p+=2;
                  i++; 
                 
            }
            else if(strcmp(Token->Get(),(char *)"WHILE")==0)//IF TOKEN IS WHILE
            {
                  Instruction[i].Set(0,(char *)"WHILE");
                  Instruction[i].Set(1,Program[p+1].Get());
                  Instruction[i].Set(2,Program[p+2].Get());
                  Instruction[i].Set(3,Program[p+3].Get());
                  p+=4;
                  i++;
            }
            else if(strcmp(Token->Get(),(char *)"END_WHILE")==0)
            {
                  Instruction[i].Set(0,(char *)"END_WHILE");
                  p+=1;
                  i++;
            }
            else if(strcmp(Token->Get(),(char *)"FOR")==0) //IF TOKEN IS FOR     
            {
                  Instruction[i].Set(0,(char *)"FOR");
                  Instruction[i].Set(1,Program[p+1].Get());
                  Instruction[i].Set(2,Program[p+2].Get());
                  Instruction[i].Set(3,Program[p+3].Get());
                  Instruction[i].Set(4,Program[p+4].Get());
                  Instruction[i].Set(5,Program[p+5].Get());
                  Instruction[i].Set(6,Program[p+6].Get());
                  Instruction[i].Set(7,Program[p+7].Get());
                  p+=8;
                  if(Get_Value(Instruction[i].Get(3))<Get_Value(Instruction[i].Get(5)))
                  {
                        Loop_Up_Down->Set_I(i,UP);
                  }
                  else if(Get_Value(Instruction[i].Get(3))>Get_Value(Instruction[i].Get(5)))
                  {
                        Loop_Up_Down->Set_I(i,DOWN);
                  }
                  else
                  {
                        Loop_Up_Down->Set_I(i,BALANCED);
                  }
                  i++;
            }
            else if(strcmp(Token->Get(),(char *)"END_FOR")==0)
            {
                  Instruction[i].Set(0,(char *)"END_FOR");
                  p+=1;
                  i++;
            }
            else if(Variable(Token->Get()))                //IF TOKEN IS A VARIABLE
            {
                  Instruction[i].Set(0,Token->Get());
                  Instruction[i].Set(1,Program[p+1].Get());
                  Instruction[i].Set(2,Program[p+2].Get());
                  if(Operator(Program[p+3].Get()))          //BINARY OPERATOR
                  {
                        Instruction[i].Set(3,Program[p+3].Get());
                        Instruction[i].Set(4,Program[p+4].Get());
                        p+=5;
                  }
                  else//if Token is not operator
                  {
                        p+=3;
                  }
                  i++;
            }

      }//for(p=0,i=0,l=0;p<Number_of_Words;i++)
      Init_Str();
      Word->Set((char *)"E");
      Lable_Table[l].Set_Name(Word->Get());
      Lable_Table[l].Set_Value(END_LABLE);
      i--;
      //thase 2 statements are important because sometimes the code does not
      //include GOTO E always, like the last instrction in the last program is
      //just some instruction.... only way the program can halt is by going to
      //label E, if it does not go we have to force it to go to E, by insterting
      //GOTO E after the last statement....
      Init_Str();
      Word->Set((char *)"GOTO");
      Instruction[i].Set(0,Word->Get());
      Init_Str();
      Word->Set((char *)"E");
      Instruction[i].Set(1,Word->Get());
      i++;
      l++;
      Number_of_Instructions=i;
      Number_of_Lables=l;
      return(NULL);
}


void *Interpret::Display_Instruction_Queue(void)
{
      int i;
      for(i=0;i<Number_of_Instructions;i++)
      {
            Display_Instruction_i(i);
      }
      return(NULL);
}

void *Interpret::Display_Instruction_i(int n)
{
      cout<<endl<<" "<<n<<" : "<<Instruction[n].Get(0);
      cout<<" "<<Instruction[n].Get(1);
      cout<<" "<<Instruction[n].Get(2);
      cout<<" "<<Instruction[n].Get(3);
      cout<<" "<<Instruction[n].Get(4);
      cout<<" "<<Instruction[n].Get(5);
      cout<<" "<<Instruction[n].Get(6);
      cout<<" "<<Instruction[n].Get(7);
      cout<<" "<<Instruction[n].Get(8);
      cout<<" "<<Instruction[n].Get(9);
      cout<<" "<<Instruction[n].Get(10);
      cout<<" "<<Instruction[n].Get(11);
      cout<<" "<<Instruction[n].Get(12);
      cout<<" "<<Instruction[n].Get(13);
      cout<<" "<<Instruction[n].Get(14);
      cout<<" "<<Instruction[n].Get(15);
      cout<<" "<<Instruction[n].Get(16);
      cout<<" "<<Instruction[n].Get(17);
      cout<<" "<<Instruction[n].Get(18);
      cout<<" "<<Instruction[n].Get(19);
      return(NULL);
}

void *Interpret::Get_Symbole_Table(void)
{
      int i;
      int j;
      for(i=0,j=0;i<Number_of_Words;i++)
      {
            if(Int(Program[i].Get()))
            {
                  Symbole_Table[j].Set_Name(Program[i+1].Get());
                  Symbole_Table[j].Set_Value(0);
                  j++;
            }
      }
      Number_of_Symboles=j;
      return(NULL);
}

void *Interpret::Execute_Code(void)
{
      int i;
      int Done;
      char *Input_Variable;
      int Instruction_Pointer;
      Input_Variable=new char;
      int Tmp_IP;
      long Value;
      String *f1;
      String *f2;
      String *f3;
      String *f4;
      String *f5;
      String *f6;
      String *f7;
      String *f8;
      String *f9;
      String *f10;
      String *f11;
      String *f12;
      String *f13;
      String *f14;
      String *f15;
      String *f16;
      String *f17;
      String *f18;
      String *f19;
      String *f20;
      f1=new String;
      f1->Constructer(FIELD_SIZE);    
      f2=new String;
      f2->Constructer(FIELD_SIZE);    
      f3=new String;
      f3->Constructer(FIELD_SIZE);    
      f4=new String;
      f4->Constructer(FIELD_SIZE);    
      f5=new String;
      f5->Constructer(FIELD_SIZE);    
      f6=new String;
      f6->Constructer(FIELD_SIZE);    
      f7=new String;
      f7->Constructer(FIELD_SIZE);    
      f8=new String;
      f8->Constructer(FIELD_SIZE);    
      f9=new String;
      f9->Constructer(FIELD_SIZE);    
      f10=new String;
      f10->Constructer(FIELD_SIZE);    
      f11=new String;
      f11->Constructer(FIELD_SIZE);    
      f12=new String;
      f12->Constructer(FIELD_SIZE);    
      f13=new String;
      f13->Constructer(FIELD_SIZE);    
      f14=new String;
      f14->Constructer(FIELD_SIZE);    
      f15=new String;
      f15->Constructer(FIELD_SIZE);    
      f16=new String;
      f16->Constructer(FIELD_SIZE);    
      f17=new String;
      f17->Constructer(FIELD_SIZE);    
      f18=new String;
      f18->Constructer(FIELD_SIZE);    
      f19=new String;
      f19->Constructer(FIELD_SIZE);    
      f20=new String;
      f20->Constructer(FIELD_SIZE);    
      Instruction_Pointer=0;
      Done=0;
      while(!Done)
      {
            if(Trace_Flag==1)
            {
                  Display_Symbole_Table();
                  Display_Instruction_i(Instruction_Pointer);
                  Wait();
            }    
            f1->Set(Instruction[Instruction_Pointer].Get(0));
            f2->Set(Instruction[Instruction_Pointer].Get(1));
            f3->Set(Instruction[Instruction_Pointer].Get(2));
            f4->Set(Instruction[Instruction_Pointer].Get(3));
            f5->Set(Instruction[Instruction_Pointer].Get(4));
            f6->Set(Instruction[Instruction_Pointer].Get(5));
            f7->Set(Instruction[Instruction_Pointer].Get(6));
            f8->Set(Instruction[Instruction_Pointer].Get(7));
            f9->Set(Instruction[Instruction_Pointer].Get(8));
            f10->Set(Instruction[Instruction_Pointer].Get(9));
            f11->Set(Instruction[Instruction_Pointer].Get(10));
            f12->Set(Instruction[Instruction_Pointer].Get(11));
            f13->Set(Instruction[Instruction_Pointer].Get(12));
            f14->Set(Instruction[Instruction_Pointer].Get(13));
            f15->Set(Instruction[Instruction_Pointer].Get(14));
            f16->Set(Instruction[Instruction_Pointer].Get(15));
            f17->Set(Instruction[Instruction_Pointer].Get(16));
            f18->Set(Instruction[Instruction_Pointer].Get(17));
            f19->Set(Instruction[Instruction_Pointer].Get(18));
            f20->Set(Instruction[Instruction_Pointer].Get(19));
            if(strcmp(f1->Get(),(char *)"GOTO")==0)
            {
                  Instruction_Pointer=Get_Lable_Value(f2->Get());
//                cout<<"\nIP now = "<<Instruction_Pointer;
                  if(Instruction_Pointer==END_LABLE)              //GOTO E GOT EXECUTED
                  {
                              Done=1;
                  }
                  Instruction_Pointer++;
            }
            else if(If(f1->Get()))                                  //IF INSTRUCTION STARTS WITH AN IF
            {
//                cout<<"\nValue1="<<Value1;
//                cout<<"\nValue2="<<Value2;
//                  f2->Get() is Operand 1 , f4->Get() is Operand 2 , f3->Get() is the Operator.....
                  if(Condition_True(f2->Get(),f3->Get(),f4->Get()))
                  {
                        Instruction_Pointer=Get_Lable_Value(f6->Get());
                  }
                  else
                  {
                        Instruction_Pointer++;
                  }
                  if(Instruction_Pointer==END_LABLE)//GOTO E got executed
                  {
                        Done=1;
                  }
            }
            else if(strcmp(f1->Get(),(char *)"PAUSE")==0)
            {
                  cout<<"\nWAS PAUSED....";
                  getchar();
                  Instruction_Pointer++;
            }    
            else if(Input(f1->Get()))                            //IF TOKEN IS INPUT
            {
                  memset(Input_Variable,'\0',sizeof(Input_Variable));
                  cin>>Input_Variable;
                  Update_Symbole_Table(f2->Get(),Input_Variable);            
                  Instruction_Pointer++;
            }
            else if(strcmp(f1->Get(),(char *)"WHILE")==0)
            {
                  Instruction_Pointer++;
                  While_Stack->Push(Instruction_Pointer);
            }
            else if(strcmp(f1->Get(),(char *)"FOR")==0)
            {
                  Instruction_Pointer++;
                  Update_Symbole_Table(f2->Get(),f4->Get());
                  For_Stack->Push(Instruction_Pointer);
            }
            else if(strcmp(f1->Get(),(char *)"END_WHILE")==0)                  //IF TOKEN IS END_WHILE
            {

                  Tmp_IP=While_Stack->Pop();                      //THIS CONTAINS ADDRESS OF INSTRUCTION AFTER WHILE
                  Tmp_IP--;                                 //BRING IT BACK TO WHILE STATEMENT
                  if(Condition_True(Instruction[Tmp_IP].Get(1),Instruction[Tmp_IP].Get(2),Instruction[Tmp_IP].Get(3)))
                  {
                        Tmp_IP++;                           //BRING IT BACK TO FIRST INSTRUCIOTN AFTER WHILE
                        Instruction_Pointer=Tmp_IP;
                        While_Stack->Push(Tmp_IP);
                  }
                  else
                  {
                        Instruction_Pointer++;
                  }
            }
            else if(strcmp(f1->Get(),(char *)"END_FOR")==0)              //IF TOKEN IS END_FOR
            {
                  Tmp_IP=For_Stack->Pop();                       //THIS CONTAINS ADDRESS OF INSTRUCTION AFTER FOR
                  Tmp_IP--;                                 //BRING IT BACK TO FOR STATEMENT
                  if(Loop_Up_Down->Get_I(Tmp_IP)==UP)
                  {

                        if(Condition_True(Instruction[Tmp_IP].Get(1),(char *)"<=",Instruction[Tmp_IP].Get(5)))
                        {
                              Value=Get_Value(Instruction[Tmp_IP].Get(1))+Get_Value(Instruction[Tmp_IP].Get(7));
//                            cout<<"\nValue is : "<<Value;
//                            Wait();
                              Symbole_Table[Get_Symbole_Index(Instruction[Tmp_IP].Get(1))].Set_Value(Value);
                              Tmp_IP++;                           //BRING IT BACK TO FIRST INSTRUCIOTN AFTER WHILE
                              Instruction_Pointer=Tmp_IP;
                              For_Stack->Push(Tmp_IP);
                        }
                        else
                        {
                              Instruction_Pointer++;
                        }
                  }
                  else if(Loop_Up_Down->Get_I(Tmp_IP)==DOWN)
                  {
                        if(Condition_True(Instruction[Tmp_IP].Get(1),(char *)">=",Instruction[Tmp_IP].Get(5)))
                        {
                              Value=Get_Value(Instruction[Tmp_IP].Get(1))+Get_Value(Instruction[Tmp_IP].Get(7));
//                            cout<<"\nValue is : "<<Value;
//                            Wait();
                              Symbole_Table[Get_Symbole_Index(Instruction[Tmp_IP].Get(1))].Set_Value(Value);
                              Tmp_IP++;                           //BRING IT BACK TO FIRST INSTRUCIOTN AFTER WHILE
                              Instruction_Pointer=Tmp_IP;
                              For_Stack->Push(Tmp_IP);
                        }
                        else
                        {
                              Instruction_Pointer++;
                        }
                  }
            }    
            else if(Print(f1->Get()))                            //IF TOKEN IS PRINT
            {
                  if(strcmp(f2->Get(),(char *)"DP")==0)
                  {
                        for(i=0;i<=Get_Value(f4->Get());i++)     
                        {
                              cout<<f3->Get();
                        }
                  }
                  else
                  {
                        if(Print_Index[Instruction_Pointer][0]>1)
                              Print_Char(f2->Get(),f3->Get());   
                        if(Print_Index[Instruction_Pointer][0]>2)
                              Print_Char(f3->Get(),f4->Get());   
                        if(Print_Index[Instruction_Pointer][0]>3)
                              Print_Char(f4->Get(),f5->Get());   
                        if(Print_Index[Instruction_Pointer][0]>4)
                              Print_Char(f5->Get(),f6->Get());   
                        if(Print_Index[Instruction_Pointer][0]>5)
                              Print_Char(f6->Get(),f7->Get());   
                        if(Print_Index[Instruction_Pointer][0]>6)
                              Print_Char(f7->Get(),f8->Get());   
                        if(Print_Index[Instruction_Pointer][0]>7)
                              Print_Char(f8->Get(),f9->Get());   
                        if(Print_Index[Instruction_Pointer][0]>8)
                              Print_Char(f9->Get(),f10->Get());   
                        if(Print_Index[Instruction_Pointer][0]>9)
                              Print_Char(f10->Get(),f11->Get());   
                        if(Print_Index[Instruction_Pointer][0]>10)
                              Print_Char(f11->Get(),f12->Get());   
                        if(Print_Index[Instruction_Pointer][0]>11)
                              Print_Char(f12->Get(),f13->Get());   
                        if(Print_Index[Instruction_Pointer][0]>12)
                              Print_Char(f13->Get(),f14->Get());   
                        if(Print_Index[Instruction_Pointer][0]>13)
                              Print_Char(f14->Get(),f15->Get());   
                        if(Print_Index[Instruction_Pointer][0]>14)
                              Print_Char(f15->Get(),f16->Get());   
                        if(Print_Index[Instruction_Pointer][0]>15)
                              Print_Char(f16->Get(),f17->Get());   
                        if(Print_Index[Instruction_Pointer][0]>16)
                              Print_Char(f17->Get(),f18->Get());   
                        if(Print_Index[Instruction_Pointer][0]>17)
                              Print_Char(f18->Get(),f19->Get());   
                  }
                  Instruction_Pointer++;
            }    
            else if(strcmp(f1->Get(),(char *)"SHELL_COMMAND")==0)
            {
                  memset(Shell_Command,'\0',sizeof(Shell_Command));
                  if(Command_Index[Instruction_Pointer][0]>1)
                  {
                        strcat(Shell_Command,f2->Get());   
                        strcat(Shell_Command,(char *)" ");
                  }    
                  if(Command_Index[Instruction_Pointer][0]>2)
                  {
                        strcat(Shell_Command,f3->Get());   
                        strcat(Shell_Command,(char *)" ");
                  }    
                  if(Command_Index[Instruction_Pointer][0]>3)
                  {
                        strcat(Shell_Command,f4->Get());   
                        strcat(Shell_Command,(char *)" ");
                  }    
                  if(Print_Index[Instruction_Pointer][0]>4)
                  {
                        strcat(Shell_Command,f5->Get());   
                        strcat(Shell_Command,(char *)" ");
                  }    
                  if(Print_Index[Instruction_Pointer][0]>5)
                  {
                        strcat(Shell_Command,f6->Get());   
                        strcat(Shell_Command,(char *)" ");
                  }    
                  if(Print_Index[Instruction_Pointer][0]>6)
                  {
                        strcat(Shell_Command,f7->Get());   
                        strcat(Shell_Command,(char *)" ");
                  }    
                  if(Print_Index[Instruction_Pointer][0]>7)
                  {
                        strcat(Shell_Command,f8->Get());   
                        strcat(Shell_Command,(char *)" ");
                  }    
                  if(Print_Index[Instruction_Pointer][0]>8)
                  {
                        strcat(Shell_Command,f9->Get());   
                        strcat(Shell_Command,(char *)" ");
                  }    
                  if(Print_Index[Instruction_Pointer][0]>9)
                  {
                        strcat(Shell_Command,f10->Get());   
                        strcat(Shell_Command,(char *)" ");
                  }    
                  if(Print_Index[Instruction_Pointer][0]>10)
                  {
                        strcat(Shell_Command,f11->Get());   
                        strcat(Shell_Command,(char *)" ");
                  }    
                  if(Print_Index[Instruction_Pointer][0]>11)
                  {
                        strcat(Shell_Command,f12->Get());   
                        strcat(Shell_Command,(char *)" ");
                  }    
                  if(Print_Index[Instruction_Pointer][0]>12)
                  {
                        strcat(Shell_Command,f13->Get());   
                        strcat(Shell_Command,(char *)" ");
                  }    
                  if(Print_Index[Instruction_Pointer][0]>13)
                  {
                        strcat(Shell_Command,f14->Get());   
                        strcat(Shell_Command,(char *)" ");
                  }    
                  if(Print_Index[Instruction_Pointer][0]>14)
                  {
                        strcat(Shell_Command,f15->Get());   
                        strcat(Shell_Command,(char *)" ");
                  }    
                  if(Print_Index[Instruction_Pointer][0]>15)
                  {
                        strcat(Shell_Command,f16->Get());   
                        strcat(Shell_Command,(char *)" ");
                  }    
                  if(Print_Index[Instruction_Pointer][0]>16)
                  {
                        strcat(Shell_Command,f17->Get());   
                        strcat(Shell_Command,(char *)" ");
                  }    
                  if(Print_Index[Instruction_Pointer][0]>17)
                  {
                        strcat(Shell_Command,f18->Get());   
                        strcat(Shell_Command,(char *)" ");
                  }    
                  system(Shell_Command);
                  Instruction_Pointer++;
            }
            else if(Variable(f1->Get()))
            {
                  Operate(f1->Get(),f2->Get(),f3->Get(),f4->Get(),f5->Get());
                  //like a = b + c

                  Instruction_Pointer++;
            }
            else
            {
                  Instruction_Pointer++;
            }
      }//while(!Done)
      return(NULL);
}

int Interpret::Condition_True(char *c1,char *c2,char *c3)
{
      int Flag;
      long Value1;
      long Value2;
      Flag=0;
      Value1=Get_Value(c1);
      Value2=Get_Value(c3);  
      if(strcmp(c2,(char *)"<")==0)              //LESS THAN
      {
            if(Value1<Value2)
            {
                  Flag=1;
            }
      }
      if(strcmp(c2,(char *)"=")==0)              //EQUAL TO
      {
            if(Value1==Value2)
            {

                  Flag=1;
            }
      }
      if(strcmp(c2,(char *)"<>")==0)             //NOT EQUAL TO
      {
            if(Value1!=Value2)
            {
                  Flag=1;
            }
      }
      if(strcmp(c2,(char *)">")==0)              //GREATER THAN
      {
            if(Value1>Value2)
            {
                  Flag=1;
            }
      }
      if(strcmp(c2,(char *)">=")==0)             //GREATER THAN OR EQUAL TO
      {
            if(Value1>=Value2)
            {
                  Flag=1;
            }
      }
      if(strcmp(c2,(char *)"<=")==0)             //LESS THAN OR EQUAL TO
      {
            if(Value1<=Value2)
            {
                  Flag=1;
            }
      }
      return(Flag);
}

void *Interpret::Print_Char(char *S1,char *S2)
{
      if(!In_Print_List(S1))
      {
            if(Variable(S1))
            {
//                cout<<S1<<" is a variable...";
                  cout<<Get_Value(S1);
            }
            else
            {
//                cout<<S1<<" is NOT a variable...";
                  if(strcmp(S1,(char *)"$")!=0)
                  {
                        cout<<S1;
                  }
            }
      }
      else
      {
            if(strcmp(S1,(char *)"$")!=0)
            {
                  if(strcmp(S1,(char *)"SP")==0)
                  {
                        cout<<" ";
                  }
                  if(strcmp(S1,(char *)"CR")==0)
                  {
                        cout<<"\n";
                  }
                  if(strcmp(S1,(char *)"LF")==0)
                  {
                        cout<<"\n\n";
                  }
            }
      }
      if(strcmp(S2,(char *)"NS")!=0)
      {
            cout<<" ";
      }
      return(NULL);
}


long Interpret::Get_Value(char *S)
{
      long Result;
      if(Variable(S))
      {
            Result=Get_Symbole_Value(S);
      }
      else
      {
            Result=atoi(S);
      }    
      return(Result);
}


int Interpret::Input(char *c)
{
      int Flag;
      if(strcmp(c,(char *)"INPUT")==0)
      {
            Flag=1;
      }
      else
      {
            Flag=0;
      }
      return(Flag);
}

int Interpret::Print(char *c)
{
      int Flag;
      if(strcmp(c,(char *)"PRINT")==0)
      {
            Flag=1;
      }
      else
      {
            Flag=0;
      }
      return(Flag);
}

void *Interpret::Update_Symbole_Table(char *c1,char *c2)
{
      long Value;
      Value=Get_Value(c2);
      Symbole_Table[Get_Symbole_Index(c1)].Set_Value(Value);
      return(NULL);
}

int Interpret::Lable1(char *c)
{
      int flag;
      flag=0;
      if(c[0]=='[')
      {
            flag=1;
      }
      return flag;
}

int Interpret::Goto(char *c)
{
      int flag;
      flag=0;
      if(strcmp(c,"GOTO")==0)
      {
            flag=1;
      }
      return flag;
}

int Interpret::Int(char *c)
{
      int Result;
      if(strcmp(c,(char *)"INT")==0)
      {
            Result=1;
      }
      else
      {
            Result=0;
      }
      return(Result);
}

int Interpret::Variable(char *c)
{
      int flag;
      flag=0;
      flag=Found(c);
      return flag;
}

int Interpret::Constant(char *c)
{
      int Result;
      if(!Found(c))
      {
            if(strcmp(c,(char *)"INT")!=0)
            {
                  Result=1;
            }
      }    
      return(Result);
}

int Interpret::Duplicate(char *c)
{
      int flag;
      int i;
      flag=0;
      for(i=0;i<Number_of_Symboles;i++)
      {
            if(Same(c,Symbole_Table[i].Get_Name()))
            {
                  flag=1;
            }
      }
      return flag;
}

int Interpret::Same(char *c1,char *c2)
{
      int flag;
      int i;
      flag=1;
      for(i=0;i<4;i++)
      {
            if(c1[i]!=c2[i])
            {
                  flag=0;
            }
      }
      return flag;
}

int Interpret::Found(char *c)
{
      int i;
      int flag;
      flag=0;
      for(i=0;i<Number_of_Words;i++)
      {
            if(strcmp(c,Symbole_Table[i].Get_Name())==0)
            {
                  flag=1;
            }
      }
      return flag;
}

int Interpret::If(char *c)
{
      int flag;
      flag=0;
      if(strcmp(c,"IF")==0)
      {
            flag=1;
      }
      return flag;
}

void *Interpret::Display_Code(void)
{
      int i;
      for(i=0;i<Number_of_Words;cout<<endl<<Program[i].Get(),i++);
      return(NULL);
}

void *Interpret::Display_Symbole_Table(void)
{
      int i;
      for(i=0;i<Number_of_Symboles;i++)
      {
            cout<<endl<<Symbole_Table[i].Get_Name()<<" "<<Symbole_Table[i].Get_Value();
      }
      return(NULL);
}

int Interpret::Digit(char *c)
{
      int flag;
      flag=0;
      if((c[0]>='0')&&(c[0]<='9'))
      {
            flag=1;
      }
      return flag;
}

int Interpret::Decode(char *c)
{
      int i;
      i=atoi(c);
      return i;
}

void *Interpret::Terminate(void)
{
      Source.close();
      return(NULL);
}

void *Interpret::Do_It(void)
{
      Scan_Code();//Gets the code from disk to Memory into P array of Program type
      Get_Symbole_Table();//creates the Symbole Table
      Set_Instruction_Queue();
      Execute_Code();
      Reset_Symbole_Table();
      return(NULL);
}


void *Interpret::Operate(char *c1,char *c2,char *c3,char *c4,char *c5)
                  //like a     =        b        +        c
{
      long Ans;
      long Value1;
      long Value2;
      if(Variable(c3))       
      {
            Value1=Symbole_Table[Get_Symbole_Index(c3)].Get_Value();
      }
      else
      {
            Value1=atoi(c3);
      }    
      if(strlen(c5)!=0)
      {
            if(Variable(c5))       
            {
                  Value2=Symbole_Table[Get_Symbole_Index(c5)].Get_Value();
            }
            else
            {
                  Value2=atoi(c5);
            }    
            if(strcmp(c4,(char *)"+")==0)
            {
                  Ans=Value1+Value2;
            }
            else if(strcmp(c4,(char *)"-")==0)
            {
                  Ans=Value1-Value2;
            }
            else if(strcmp(c4,(char *)"/")==0)
            {
                  Ans=Value1/Value2;
            }
            else if(strcmp(c4,(char *)"*")==0)
            {
                  Ans=Value1*Value2;
            }
            else if(strcmp(c4,(char *)"^")==0)
            {
                  Ans=Pow(Value1,Value2);
            }
            else if(strcmp(c4,(char *)"%")==0)
            {
                  Ans=Value1%Value2;
            }
            Symbole_Table[Get_Symbole_Index(c1)].Set_Value(Ans);
      }
      else
      {
            if(Variable(c1)) 
            {
                  Value2=Symbole_Table[Get_Symbole_Index(c1)].Get_Value();
            }
            else
            {
                  Value2=atoi(c1);
            }
            if(strcmp(c2,(char *)"+=")==0)
            {
                  Ans=Value2+Value1;
            }
            else if(strcmp(c2,(char *)"-=")==0)
            {
                  Ans=Value1-Value1;
            }
            else if(strcmp(c2,(char *)"/=")==0)
            {
                  Ans=Value2/Value1;
            }
            else if(strcmp(c2,(char *)"*=")==0)
            {
                  Ans=Value2*Value1;
            }
            else if(strcmp(c2,(char *)"^=")==0)
            {
                  Ans=Pow(Value2,Value1);
            }
            else if(strcmp(c2,(char *)"%=")==0)
            {
                  Ans=Value2%Value1;
            }
            else if(strcmp(c2,(char *)"=")==0)
            {
                  Ans=Value1;
            }
            Symbole_Table[Get_Symbole_Index(c1)].Set_Value(Ans);
      }
      return(NULL);
}


int Interpret::Operator(char *c)
{
      int flag;
      flag=0;
      if(strcmp(c,(char *)"+")==0)
            flag=1;
      else if(strcmp(c,(char *)"-")==0)
            flag=1;
      else if(strcmp(c,(char *)"/")==0)
            flag=1;
      else if(strcmp(c,(char *)"*")==0)
            flag=1;
      else if(strcmp(c,(char *)"^")==0)
            flag=1;
      else if(strcmp(c,(char *)"+=")==0)
            flag=1;
      else if(strcmp(c,(char *)"-=")==0)
            flag=1;
      else if(strcmp(c,(char *)"/=")==0)
            flag=1;
      else if(strcmp(c,(char *)"*=")==0)
            flag=1;
      else if(strcmp(c,(char *)"^=")==0)
            flag=1;
      else if(strcmp(c,(char *)"=")==0)
            flag=1;
      return flag;
}

int main(int argc,char *argv[])
{
      char *Source;
      Source=new char[12];
      ifstream ifile;
      if(argc<2)
      {
            cout<<"\nUSAGE : "<<argv[0]<<" <Source_File_Name> <Optional_Trace_Flag t>\n\n";
            exit(1);
      }
      else
      {
            memset(Source,'\0',12);  
            strcpy(Source,argv[1]);
            ifile.open(Source,ios::in);
            if((argv[1][strlen(argv[1])-1]!='l')&&(argv[1][strlen(argv[1])-1]!='b'))
            {
                  cout<<"\n\nSource Code File Name Should Have a .bl Extension\n\n";  
                  exit(1);
            }
            if(!ifile)
            {
                  cout<<"\nError Opening File : "<<argv[1]<<"\n\n";
                  exit(1);
            }
            else
            {

                  ifile.close();
            }
      }
      char *c;
      c=new char;
      if(argc==3)
      {
            if(strcmp(argv[2],(char *)"t")==0)
            {
                  strcpy(c,argv[2]);
            }
      }    
      else
      {
            strcpy(c,(char *)"n");
      }
      Interpret *I;
      I=new Interpret(Source,c);
      I->Do_It();
      I->Terminate();
      delete I;   
      return 0;
}