/*********************************************************************************************
*																							 *						
* Program Name:C2ASM,Ver 1.0,9th July,2003.													 *	
*																							 *
* Category:Cross Compiler(From "C" to "Assembly Language").									 *
*																							 *
* Input:c_code.txt(Place the "C" code u want to convert into "ASSEMBLY" Language)			 * 
*																							 *
* Output:asm_code.txt("ASSEMBLY" code for INPUT "C" program)								 *
*																							 *
* Requirements:Microsoft Windows(95/98/Me/2000/XP)/DOS.										 * 
*			 Microsoft Visual C++(Ver 6.0)/Microsoft Visual C++ .NET						 *
*			 Microsoft MASM(Ver 6.11)														 *	
*																							 *
*		NOTE:All Names Mentioned in "Requirements" Section are Registered trade marks of	 *
*			 Microsoft Corporation.															 *
*																							 *
* Programmed By:Muhammad Owais Khan Afridi.													 *
*			  BS(Computer Science),8th Semester,Department Of Computer Science,				 *
*			  Karachi University,Pakistan.													 *
*																							 *
* Notes for Readers:																		 *
*	1)Sure to read documentation supplied with this code.It'll clear many confusions.		 *
*	2)Reader Shld know programming in C,Assembly,Use of <Vectors> and <Stack> of STL(C++),	 *
*	  to understand this code.																 *
*	3)This program doesn't use any Object Code Optimization,Register Allocation Algorithms.  *
*	4)It converts STANDARD "C",See Sample Programs supplied to get some idea.				 *
*	5)It doesn't Convert all the "C" statements like Switch-Case.It uses a Sub-Part of "C"   *
*	  Language,See GRAMMAR,TOKEN SET of Language in Documentation Supplied to get idea abt it*
*																							 *	
* Disclaimer:																				 *
*			The Author of this PROGRAM shall not be liable in any event for incidental or    *
*			consequential damages in connection with,or arising out of,the furnishing,       *
*			performance,or use of this program.												 *
*********************************************************************************************/
#pragma warning (disable:4786)
#include<conio.h>
#include<string>
#include<iostream>
#include<fstream>
#include<vector>
#include<stack>
using namespace std;

#define LEXEME_SIZE 30			
#define FILE_READ "c_code.txt"	//This is the INPUT "C" file,which is to be converted into 
								//Assembly. 

#define FILE_WRITE "asm_code.txt"  //This is the OUTPUT "ASSEMBLY" file For the input "C" file

//Globals Used By Lexical Box,Syntax Box,Code Generator.
vector<long> number_long;	//This vector will hold Long Constants occuring in the Program
vector<long> number_int;	//This vector will hold Int Constants occuring in the Program

//////////////////////////////
//
//Globals Used By Lexical Box.
//
/////////////////////////////

//This Vector is used to hold IDENTIFIER(s) for Lexical Box ONLY!
vector<string> lex_identifier;	

#define TOTAL_KEYWORDS 10
string keywrd[TOTAL_KEYWORDS]={"void","main","int","long","if","else","for","while","do","return"};

//This Vector will Pick Keywords from the above Array. 
vector<string> keywords;

//Structure Of a Token
struct to{
	string clas;	//Stores Class part of Token
	int index;		//Stores Value part of Token
}tok;				//tok is used to PUSH values on "tokens" Vector.

//This Vector will hold ALL Tokens Generated by Lexical Box.
vector<to> tokens;

///////////////////////////////////
//
//Lexical Box Fucntion Declaration
//
///////////////////////////////////

//Lexemer will break input stream into LEXEMES using D.F.A approach as discussed in ULMAN's
//Compiler Construction Book
void lexemer(ifstream& input,int &line);

//If we follow a particular D.F.A to recognize input stream,In case that FAILS we need to check
//Some Other D.F.A,"lexemer_fail" will provide this fuctionality.
int lexemer_fail(ifstream& input,char& faulty_character,int& line,int& starting_state,streampos& lexeme_begining);

//If we're unable to identify a Lexeme as a particular TOKEN of Our Language,Then we need to 
//Show some error message."lexemer_error" will do this.
void lexemer_error(char& faulty_character,int &line);

//It makes Token for a LEXEME
void tokenizer(char* lexeme_buffer,int& starting_state);

void syntax_box();		//Syntax Box Declaration
void code_generator();	//Code Generator Declaration

int main()
{

	//Loading KEYWORDS LIST.It's used in Differentiating Kewords From Identifiers.
	for(unsigned int i=0;i<TOTAL_KEYWORDS;i++)
		keywords.push_back(keywrd[i]);		
		
	char file_read='\0';
	int linecount=1;
	ifstream input(FILE_READ);

//Start Reading INPUT File.
while(input.get(file_read))
{
	if(file_read=='\n') linecount++;
	if(file_read!='\n'&&file_read!='\t'&&file_read!=' ')
	{
		input.seekg(-1,ios::cur);
		lexemer(input,linecount);	//Start Making Lexemes
	}//end of if
	
}//end reading file

	input.close();

	//If u wanna See Which TOKENs are generated,Remove Comments From the Following Code,It'll 
	//Show u ALL TOKENs on CONSOLE.
	/*
    for(unsigned int i=0;i<tokens.size();i++)
	{
		cout<<"\n";
		cout<<tokens[i].clas;
		cout<<"\t"<<tokens[i].index;
	}
	*/
	
	//Pushing An Error Token At the END of TOKEN STREAM.
	//So that we've an "End Marker"
		tok.clas="error";
		tok.index=-10;
		tokens.push_back(tok);

		//Start Parsing,Type Checking,Intermediate Code Generation
		syntax_box();
		
	//If u wanna See What Intermediate Code is generated,Remove Comments From the Following 
	//Code,It'll Show u ALL ATOMS on CONSOLE.

/*		cout<<"\n\nFollowing Intermediate Code is Generated\n";

		cout<<"INDEX----DATATYPE----TABLE";
		for(i=0;i<atoms.size();i++)
			cout<<endl<<atoms[i].op<<" type="<<atoms[i].type
			    <<"  arg1= "<<atoms[i].arg1.index <<" "<< atoms[i].arg1.datatype <<" "<< atoms[i].arg1.whichtable
				<<"  arg2= "<<atoms[i].arg2.index <<" "<< atoms[i].arg2.datatype <<" "<< atoms[i].arg2.whichtable
				<<"  result= "<<atoms[i].result.index <<" "<< atoms[i].result.datatype <<" "<< atoms[i].result.whichtable;
*/				

	//Start CODE GENERATION.
		code_generator();

		cout<<"\n\n\"C2ASM\" has sucessfully converted \"C\" code(c_code.txt)"
			<<endl<<"to \"ASSEMBLY\" code(asm_code.txt)";
		
	cout<<"\n";
    getch();
	return(0);
}


///**********************///
///**********************///
///						 ///
/// LEXICAL BOX STARTED. ///
///						 ///
///**********************///
///**********************///

void lexemer(ifstream& input,int& line)
{
	char character_read='\0';
	char lexeme_buffer[LEXEME_SIZE];
	memset(lexeme_buffer,'\0',LEXEME_SIZE);
	int counter=0;
	int current_state=0,starting_state=0;
	bool read_flag=true;
	streampos lexeme_begining=input.tellg();
	while(read_flag){
			switch(current_state)
			{
			//D.F.A for Identifier And Keyword
			case 0:input.get(character_read);
				if(isalpha(character_read)||character_read=='_') {current_state=1;lexeme_buffer[counter]=character_read;counter++;starting_state=0;}
				else current_state=lexemer_fail(input,character_read,line,starting_state,lexeme_begining);
				break;
			case 1:input.get(character_read);
				if(isalpha(character_read)||character_read=='_'||isdigit(character_read)) {current_state=1;lexeme_buffer[counter]=character_read;counter++;}
				else current_state=2;
				break;
			case 2:
				input.seekg(-1,ios::cur);
				read_flag=false;
				break;
			//D.F.A for Relational And Assignment Operators
			case 3:input.get(character_read);
				if(character_read=='=') {current_state=4;lexeme_buffer[counter]=character_read;counter++;starting_state=3;}
				else if(character_read=='<') {current_state=7;lexeme_buffer[counter]=character_read;counter++;starting_state=3;}
				else if(character_read=='>') {current_state=11;lexeme_buffer[counter]=character_read;counter++;starting_state=3;}
				else current_state=lexemer_fail(input,character_read,line,starting_state,lexeme_begining);				
				break;
			case 4:input.get(character_read);
				if(character_read=='=') {current_state=5;lexeme_buffer[counter]=character_read;counter++;}
				else current_state=6;
				break;
			case 5:
				read_flag=false;
				break;
			case 6:
				input.seekg(-1,ios::cur);
				read_flag=false;
				break;
			case 7:input.get(character_read);
				if(character_read=='=') {current_state=8;lexeme_buffer[counter]=character_read;counter++;}
				else if(character_read=='>') {current_state=9;lexeme_buffer[counter]=character_read;counter++;}
				else current_state=10;
				break;
			case 8:
				read_flag=false;
				break;
			case 9:
				read_flag=false;
				break;
			case 10:
				input.seekg(-1,ios::cur);
				read_flag=false;
				break;
			case 11:input.get(character_read);
				if(character_read=='=') {current_state=12;lexeme_buffer[counter]=character_read;counter++;}
				else current_state=13;
				break;
			case 12:
				read_flag=false;
				break;
			case 13:
				input.seekg(-1,ios::cur);
				read_flag=false;
				break;
			//D.F.A for Arithmetic Operators
			case 14:
				//MAULA ALI!
				input.get(character_read);
				if(character_read=='+'|| character_read=='-'||character_read=='*'||character_read=='/'||character_read=='%') 
				{current_state=15;lexeme_buffer[counter]=character_read;counter++;starting_state=14;}
				else current_state=lexemer_fail(input,character_read,line,starting_state,lexeme_begining);				
				break;
			case 15:
				read_flag=false;
				break;
			//D.F.A for Punctuations
			case 16:
				input.get(character_read);
				if(character_read=='('||character_read==')'||character_read=='{'||character_read=='}'||character_read==','||character_read==';'||character_read=='['||character_read==']')
				{current_state=17;lexeme_buffer[counter]=character_read;counter++;starting_state=16;}
				else current_state=lexemer_fail(input,character_read,line,starting_state,lexeme_begining);
				break;
			case 17:
				read_flag=false;								
				break;
			//D.F.A for LONG Numbers
			case 18:
				input.get(character_read);
				if(isdigit(character_read)) {current_state=19;lexeme_buffer[counter]=character_read;counter++;starting_state=18;}
				else current_state=lexemer_fail(input,character_read,line,starting_state,lexeme_begining);
				break;
			case 19:
				input.get(character_read);
				if(isdigit(character_read)) {current_state=19;lexeme_buffer[counter]=character_read;counter++;}
				else if(character_read=='L'||character_read=='l') {current_state=20;lexeme_buffer[counter]=character_read;counter++;}
				else current_state=21;				
				break;
			case 20:
				read_flag=false;								
				break;
			case 21:
				input.seekg(-1,ios::cur);
				read_flag=false;								
				break;
			//Error TOKEN
			case 100:
				input.get(character_read);
				{current_state=100;lexeme_buffer[counter]=character_read;counter++;starting_state=100;}
				read_flag=false;	
				break;

			}//End of switch
				}//End Reading One LEXEME
		lexeme_buffer[counter]='\0';

		//A Lexeme Is Made Sucessfully,Call Tokenizer to Make It's Coresponding TOKEN
		tokenizer(lexeme_buffer,starting_state);
}

int lexemer_fail(ifstream& input,char& faulty_character,int& line,int& starting_state,streampos& lexeme_begining)
{
	switch(starting_state)
	{
	case 0:
	input.seekg(lexeme_begining);starting_state=3;break;
	case 3:
	input.seekg(lexeme_begining);starting_state=14;break;
	case 14:
	input.seekg(lexeme_begining);starting_state=16;break;
	case 16:
	input.seekg(lexeme_begining);starting_state=18;break;
	case 18:
	
	//We're Generating ERROR token for those things which are NOT part of OUR LANGUAGE.If U 
	//wanna stop this ERROR code generation,Remove Comments From the Following Line and DO 
	//COMMENT Line AFTER IT!.

	//input.seekg(lexeme_begining);lexemer_error(faulty_character,line);break;

	input.seekg(lexeme_begining);starting_state=100;break;
	//default:
	//	cout<<"\nNo More States";exit(-1);
	}
	return starting_state;
}

void lexemer_error(char& faulty_character,int &line)
{
	cout<<"\nSome Ir-Recoverable Error Occured in LEXICAL ANALYZER!---Possibly"
		<<"\nAn Invalid Lexeme Caused it,Which is Not Part Of Our Language"
		<<"The Starting SYMBOL Of Lexeme is "<<faulty_character<<" Line Number Is "<<line<<endl; 
	getch();
	exit(-1);
}

void tokenizer(char* lexeme_buffer,int& starting_state)
{
	tok.clas=" ";
	tok.index=-10;

	string lexeme;
	lexeme.assign(lexeme_buffer);

	unsigned int j=0,k=0;
	

	long num;

	switch(starting_state)
	{
	//Lexeme is a KEYWORD/IDENTIFIER
	case 0:
		//If LEXEME is a KEYWORD
		for(k=0;k<keywords.size();k++)
		{
			if(lexeme==keywords[k])
			{
				if(lexeme=="int"||lexeme=="long")
				{
					tok.clas="dt";
					tok.index=(lexeme=="int")?0:1;
				}
				else{
					tok.clas=lexeme;
					tok.index=-10;
				}
			tokens.push_back(tok);
			return;
			}
		}
		
		//If LEXEME is an IDENTIFIER
		for(j=0;j<lex_identifier.size();j++)
			//If identifier is already THERE!		
			if(lex_identifier[j]==lexeme)
			{
			tok.clas="id";
			tok.index=j;
			tokens.push_back(tok);
			return;
			}

			//If Identifier is NOT THERE!
			if(lex_identifier.size()==0||lex_identifier.size()==j)
			{
			//Enter into IDENTIFIER SYMBOL TABLE!
			lex_identifier.push_back(lexeme);
			//Enter into TOKEN's TABLE!
			tok.clas="id";
			tok.index=j;
			tokens.push_back(tok);
			return;
			}
		break;
	
		//Lexeme is a RELATIONAL/ASSIGNMENT OPERATOR
	case 3:
		if(lexeme=="=")	//An Assignment Operator
			tok.clas="assignop";
		else	//A Relational Operator
			tok.clas="relop";
	
		if(lexeme=="==")
			tok.index=8;
		else if(lexeme=="<>")	
			tok.index=9;
		else if(lexeme==">=")	
		tok.index=10;
		else if(lexeme=="<=")	
		tok.index=11;
		else if(lexeme==">")	
		tok.index=12;
		else if(lexeme=="<")	
		tok.index=13;
		else if(lexeme=="=")	
		tok.index=14;

		//Enter into TOKEN's TABLE!
			tokens.push_back(tok);
		break;
	
	//Lexeme is an ARITHMENTIC OPERATOR
	case 14:

		tok.clas=(lexeme=="+" ||lexeme=="-") ? "add_sub" : "mul_div_mod"; 
		
		if(lexeme=="+")
		tok.index=15;
		else if(lexeme=="-")	
		tok.index=16;
		else if(lexeme=="*")	
		tok.index=17;
		else if(lexeme=="/")	
		tok.index=18;
		else if(lexeme=="%")	
		tok.index=19;
		//Enter into TOKEN's TABLE!
			tokens.push_back(tok);
		break;

	//Lexeme is a PUNCTUATION CHARACTIER
	case 16:
		if(lexeme=="{")
		{
			//Enter into TOKEN's TABLE!
			tok.clas="braces_open";
			tok.index=2;
			tokens.push_back(tok);
		}
		
		else if(lexeme=="}")
		{
			//Enter into TOKEN's TABLE!
			tok.clas="braces_close";
			tok.index=3;
			tokens.push_back(tok);
		}
	
		else if(lexeme=="(")
		{
			//Enter into TOKEN's TABLE!
			tok.clas="parenthesis_open";
			tok.index=4;
			tokens.push_back(tok);
		}	

		else if(lexeme==")")
		{
			//Enter into TOKEN's TABLE!
			tok.clas="parenthesis_close";
			tok.index=5;
			tokens.push_back(tok);
		}	
	
		else if(lexeme==",")
		{
			//Enter into TOKEN's TABLE!
			tok.clas="comma";
			tok.index=6;
			tokens.push_back(tok);
		}	
			
		else if(lexeme==";")
		{
			//Enter into TOKEN's TABLE!
			tok.clas="semicolon";
			tok.index=7;
			tokens.push_back(tok);
		}

		else if(lexeme=="[")
		{
			//Enter into TOKEN's TABLE!
			tok.clas="square_open";
			tok.index=20;
			tokens.push_back(tok);
		}

		else if(lexeme=="]")
		{
			//Enter into TOKEN's TABLE!
			tok.clas="square_close";
			tok.index=21;
			tokens.push_back(tok);
		}
		break;

		//Lexeme is a NUMBER,It may be an INTEGER or a LONG 
	case 18:
		
		//Checking Whehter the GIVEN NUM is a LONG?
		num=lexeme.find('L');
		if (num==-1) num=lexeme.find('l');
		
		//IF GIVEN NUM is a LONG!
		if(num!=-1)
		{
			//Convert String To LONG INTEGER!...
			lexeme.erase(num,1);	//Remove 'L' or 'l' from the END
			num=0;
			const char *temp=lexeme.c_str();
			num=atol(temp);

		for(unsigned int m=0;m<number_long.size();m++)
			//Number is already there!
			if(number_long[m]==num)
			{
			tok.clas="long_const";
			tok.index=m;
			tokens.push_back(tok);
			return;
			}
			//Number is NOT there!
			if(number_long.size()==0||number_long.size()==m)
			{
			//Enter into NUMBER's SYMBOL TABLE!
			number_long.push_back(num);
			//Enter into TOKEN's TABLE!
			tok.clas="long_const";
			tok.index=m;
			tokens.push_back(tok);
			return;
			}
		}
		//IF GIVEN NUM is an INTEGER!
		else
		{
			int num=0;
			num=atoi(lexeme_buffer);

		for(unsigned int m=0;m<number_int.size();m++)
			//Number is already there!
			if(number_int[m]==num)
			{
			tok.clas="int_const";
			tok.index=m;
			tokens.push_back(tok);
			return;
			}
			//Number is NOT there!
			if(number_int.size()==0||number_int.size()==m)
			{
			//Enter into NUMBER's SYMBOL TABLE!
			number_int.push_back(num);
			//Enter into TOKEN's TABLE!
			tok.clas="int_const";
			tok.index=m;
			tokens.push_back(tok);
			return;
			}
		}
		break;
		
		//Lexeme is an ERROR CHARACTIER
	case 100:
			//Enter into TOKEN's TABLE!
			tok.clas="error";
			tok.index=-10;
			tokens.push_back(tok);
			break;
	}//End Switch
}

///**********************///
///**********************///
///						 ///
/// SYNTAX BOX STARTED.	 ///
///						 ///
///**********************///
///**********************///

//////////////////////
//
//Syntax Box's Globals
//
//////////////////////

to input;	//Used To read in Token Generated by LEXICAL BOX

//Structure Of Identifier Table,For Details Of FIELDs CONSULT the DOCUMETATION of C2ASM,
//Provided with it.

struct id{
	string name;
	int datatype;
	int scope;
	int binding;
	bool func_or_not;
	int type;
	int offset;
	int xtra;
}ident;

//This Vector will hold Main()/Fucntion/Temporary Variables and Function Names Also.
vector<id> syn_identifier;	

//This Vector will hold Fucntion's Parameters
vector<id> args_identifier;

int syn_index=0;	//Counter to Iterate through TOKEN's Vector

ofstream error("parser_log.txt");	//Parser Log File

int scopecount=-10;
stack <int> scopestack;		// Stack For Scope Handling

int func_index=-10;
bool main_func=false;
bool isreturn=false;

//Used in Making ATOMS or INTERMEDIATE CODE
struct expr{
	int index;
	int datatype;
	int whichtable;
}dump;

int table=-10;		// 0 for syn_identifier
					// 1 for args_identifier

//Each ATOM has following structure.
struct atom{
	string op;
	int type;
	expr arg1;
	expr arg2;
	expr result;
}atm;

vector<atom> atoms;	//This Vector will hold All ATOMS or INTERMEDIATE CODE generated

vector<string> labels;	//This Vector will Hold all LABELS generated

long init_arg=-10,fin_arg=-10;

/////////////////////////////////////
//
//Syntax Box's Fucntions Declaration
//
/////////////////////////////////////

//Helper Functions

///////////////////////////////
//
// Recursive Descend Functions
//
///////////////////////////////

//Used to Advance Like u see in Recursive Descend Method's Discussed in Compiler Books
void advanc();

//Used to Reject Like u see in Recursive Descend Method's Discussed in Compiler Books
void reject();

///////////////////////////////
//
// Type System's Functions
//
///////////////////////////////

//Used to Set the Datatype of Main()/Function's/Temporary Variables/Function's Return Type
void settype(int index,int type);

//Used to Set the Datatype of Function's Parameters
void settype_args(int index,int type);

//Generates New Temporary Variables
expr newtemp(int type);

//Generates New Temporary Variables Names Used by "newtemp"
string newtempname(void);

//Check whether an Identifier is DECLARED before it's used
long chk_ident(long index);

//Check whether Two Identifiers or Numbers are of same Type
bool chk_types(expr v1,expr v2);

//Makes ATOM of a Particular Type on the basis of it's Arguments
void setatom(int op,expr arg1,expr arg2,expr result);

//Generates New Labels
int newlabel(void);

//Check whether a Function is DECLARED before it's used
long chk_func(long index);

//Gived Arguments Info. of a Particular Function
void args_info(long index,long &init_arg,long &fin_arg);

//Calculates Paramters Offset,When they're on STACK
int calc_param_offset();

//Calculates Locals Offset,When they're on STACK
int calc_local_offset();

////////////////////
//
//Grammar Functions
//
////////////////////

//Read the Supplied Document For a Better Understanding

void program();
void data_or_function(int type);
void function_or_main();
void function_body();
void variable_declarations();
void variable_list(int type);
void argument_list();
void argument();
void compound_statement();
void statements();
void statement();
void optional_else();
void right_hand_side(expr &r);
void function_call(expr &f);
void optional_expression_list();
void expression_listf();
void expression_list_element();
void expression(expr &k);
void relational(expr &k,expr &t1);
void arithmetic(expr &p);
void subtract(expr p,expr &q);
void t(expr &p);
void add(expr p,expr &q);
void u(expr &p);
void multiply(expr p,expr &q);
void v(expr &p);
void divide(expr p,expr &q);
void w(expr &p);
void mod(expr p,expr &q);
void x(expr &p);


void advanc()
{	
	//Updating "parser_log.txt" File.
	error<<syn_index+1<<'\t'<<input.clas<<'\t'<<input.index<<'\t'<<scopestack.top()<<endl;

	//Picking Up Next Token
	if(syn_index!=(tokens.size()-1))
	{
	syn_index++;
	input=tokens[syn_index];
	}
}

void reject()
{
	//Updating "parser_log.txt" File.
	error<<syn_index+1<<'\t'<<input.clas<<'\t'<<input.index<<'\t'<<scopestack.top()<<endl;
	error.close();

    cout<<"\nParser Failed";
	cout<<"\nParser has parsed "<< syn_index+1 <<" Tokens\n";
	cout<<"See \"parser_log.txt\" For Details\n";
	getch();
	exit(-1);
}

void settype(int index,int type)
{
string name=lex_identifier[index];

for(unsigned int j=0;j<syn_identifier.size();j++)
{
	if(syn_identifier[j].name==name
		&& syn_identifier[j].scope==scopestack.top())
			{
				cout<<"Variable name->"<< name<<" with scope "<< scopestack.top()<<" and datatype "<< type <<endl
					<<"Already exists With name->"<< syn_identifier[j].name<<" ,scope "<<syn_identifier[j].scope <<" and datatype "<< syn_identifier[j].datatype<<endl;
				reject();			
			}
}
//Chk for the name clashing of FORMAL PARAMETERS and LOCAL VARIABLES.
if(func_index!=-10)
{
	for(unsigned int j=0;j<args_identifier.size();j++)
	{
	if(args_identifier[j].name==name
		&& args_identifier[j].binding==func_index)
			{
			cout<<endl<<"Redifinition of formal parameter "<< name
				<<" in "<<syn_identifier[func_index].name;
			reject();			
			}
	}
}

ident.name=name;
ident.datatype=type;
ident.scope=scopestack.top();
ident.func_or_not=false;
ident.xtra=-10;

//It's a Global Variable
if(func_index==-10 && main_func==false)
{
ident.binding=-2;	//-2 for a global
ident.type=0;		//0 for a global
ident.offset=-10;	//No Need To calculate this
}
//It's a Main Variable
else if(func_index==-10 && main_func==true)
{
ident.binding=-1;	//-1 for a main
ident.type=1;		//1 for main
ident.offset=-10;	//No Need To calculate this
}
//It's a Local Variable
else if(func_index!=-10 && main_func==false)
{
ident.binding=func_index;	
ident.type=2;		//2 for Local
ident.offset=-10;	//WE'LL CALCULATE THIS AFTER SOMETIME!!!!
}

syn_identifier.push_back(ident);
}

//For Arguments
void settype_args(int index,int type)
{
string name=lex_identifier[index];
int binding=syn_identifier.size()-1;

for(unsigned int j=0;j<args_identifier.size();j++)
{
	if(args_identifier[j].name==name
		&& args_identifier[j].binding==binding)
			{
				cout<<"Variable name->"<< name<<" with binding "<< binding <<" and datatype "<< type <<endl
					<<"Already exists With name->"<< args_identifier[j].name<<" ,binding "
					<<args_identifier[j].binding<<" and datatype "<< args_identifier[j].datatype<<endl;
				reject();			
			}
}
//Updating ARGUMENTS SYMBOL TABLE
ident.name=name;
ident.datatype=type;
ident.scope=-10;
ident.binding=binding;
ident.func_or_not=false;
ident.type=3;
ident.offset=-10;	//We'll Calculate this LATER on.
ident.xtra=-10;
args_identifier.push_back(ident);

}

expr newtemp(int type)
{
	if(type==23) type=0;
	if(type==24) type=1;

	expr temp;

	ident.name=newtempname();
	ident.datatype=type;
	ident.scope=scopestack.top();
	ident.func_or_not=false;
	ident.type=4;	//For Temporaries
	ident.offset=-10;	//Will CALCULATE afterwards
	ident.xtra=-10;
	
	//Deciding Whose Temporary is this! Main or an Ordinary Function
	if(main_func==true)
		ident.binding=-1;
	else
		ident.binding=func_index;

	syn_identifier.push_back(ident);
	 
	temp.index=syn_identifier.size()-1;
	temp.datatype=type;
	temp.whichtable=0;
	
	return temp;
}

string newtempname(void)
{
	static long count=1;
	
	char name[10];
	char temp[5];

	ltoa(count,temp,10);
	strcpy(name,"t");
	strcat(name,temp);
	
	count++;
	return string(name);
	
}

long chk_ident(long index)
{
table=-10;
string name=lex_identifier[index];
unsigned int j=0;

//Check in Local Scope
for(j=0;j<syn_identifier.size();j++)
{
	if(syn_identifier[j].name==name
		&& syn_identifier[j].scope==scopestack.top()
		&& syn_identifier[j].func_or_not==false)
			{
			table=0;	//For syn_identifier
			return j;
			}
}

//Check in if it's a Formal Parameter
if(func_index!=10)
{
for(j=0;j<args_identifier.size();j++)
{
	if(args_identifier[j].name==name
		&& args_identifier[j].binding==func_index)
			{
			table=1;	//For args_identifier
			return j;
			}
}

}

//Check in Global Scope
for(j=0;j<syn_identifier.size();j++)
{
	if(syn_identifier[j].name==name
		&& syn_identifier[j].scope==0
		&& syn_identifier[j].func_or_not==false)
			{
			table=0;	//For syn_identifier
			return j;
			}
}

return -10;
}

bool chk_types(expr v1,expr v2)
{
	v1.datatype=v1.datatype==23 ? 0 : v1.datatype;
	v1.datatype=v1.datatype==24 ? 1 : v1.datatype;

	v2.datatype=v2.datatype==23 ? 0 : v2.datatype;
	v2.datatype=v2.datatype==24 ? 1 : v2.datatype;

	return(v1.datatype==v2.datatype);
}

void setatom(int op,expr arg1,expr arg2,expr result)
{
	atm.type=op;
	atm.arg1=arg1;
	atm.arg2=arg2;
	atm.result=result;

	switch(op)
	{
	//Addition
	case 15:
		atm.op="ADD";
		break;

		//Subtraction
	case 16:
		atm.op="SUB";
		break;

		//Multiply
	case 17:
		atm.op="MUL";
		break;

		//Division
	case 18:
		atm.op="DIV";
		break;

		//Remainder
	case 19:
		atm.op="MOD";
		break;
		
		//Assign
	case 26:
		atm.op="ASSIGN";
		break;

		//Label
	case 25:
		atm.op="LABEL";
		break;

		//Conditional Jump
	case 27:
		atm.op="CONDJUMP";
		break;

		//Jump
	case 28:
		atm.op="JUMP";
		break;

		//Return
	case 29:
		atm.op="RETURN";
		break;

		//Param
	case 30:
		atm.op="PARAM";
		break;

			//CALL
	case 31:
		atm.op="CALL";
		break;
		
			//PROC_MARKER
	case 34:
		atm.op="PROC_MARKER";
		break;

			//JUMPF
	case 8:
	case 9:
	case 10:
	case 11:
	case 12:
	case 13:
		atm.op="JUMPF";
		break;

		//CMP
	case 108:
	case 109:
	case 110:
	case 111:
	case 112:
	case 113:
		atm.op="CMP";
		//atm.type=op-100;
		break;
	default:
		cout<<"\nNo Matching Found";
	}
	atoms.push_back(atm);
}

int newlabel(void)
{
	static long count=1;
	
	char name[10];
	char temp[5];

	ltoa(count,temp,10);
	strcpy(name,"L");
	strcat(name,temp);
	
	string s1=name;
	labels.push_back(s1);

	count++;
	return(labels.size()-1);
}

long chk_func(long index)
{
string name=lex_identifier[index];

for(unsigned int j=0;j<syn_identifier.size();j++)
{
	if(syn_identifier[j].name==name
		&& syn_identifier[j].func_or_not==true)
			{
			table=0;
			return j;
			}
}
return -10;
}

void args_info(long index,long &init_arg,long &fin_arg)
{
init_arg=-10;
fin_arg=-10;
vector<int> temp;
	for(unsigned int j=0;j<args_identifier.size();j++)
		if(args_identifier[j].binding==index)
			temp.push_back(j);
	if(temp.size()!=0)
	{
	init_arg=temp[0];
	fin_arg=temp[temp.size()-1];
	}
}

int calc_param_offset()
{
	int index=func_index;	//Get FUNCTION's INDEX
	bool flag=false;
	int counter=0;
	int k=args_identifier.size()-1;
	int tot_len=0;
	while(index==func_index)
	{
		//If It's the LAST parameter
		if(flag==false){
			counter=6;
			args_identifier[k].offset=counter;
			counter+=args_identifier[k].datatype==0 ? 2 : 4;
			tot_len+=args_identifier[k].datatype==0 ? 2 : 4;
			flag=true;
		}
		//If It's OTHER THAN last parameter
		else{
			args_identifier[k].offset=counter;
			counter+=args_identifier[k].datatype==0 ? 2 : 4;
			tot_len+=args_identifier[k].datatype==0 ? 2 : 4;
		}
		k--;
		//It sometimes Happens that even -ve INDICES also points 
		//to some array element causing PROBLEMS
		if(k<0) break;	
		index=args_identifier[k].binding;
	}
	return tot_len;
}

int calc_local_offset()
{
	int counter=0;
	//Chk For LOCAL's which are BINDED to LATEST "func_index"
	for(unsigned int i=0;i<syn_identifier.size();i++)
		if(syn_identifier[i].binding==func_index)
		{
		counter+=syn_identifier[i].datatype==0 ? 2 : 4;
		syn_identifier[i].offset=counter;
		}
return counter;
}

void syntax_box()
{
	//Doing Initializations
	syn_index=0;
	input=tokens[syn_index];
	scopecount=0;
	scopestack.push(scopecount);
	dump.index=-10;
	dump.datatype=-10;
	dump.whichtable=-10;
	
	program();
	
	//Check whether we've got our End Of Marker
	//Yes,End Marker has Arrived,ACCEPT INPUT PROGRAM!
	if(input.clas=="error")
	{
	error<<syn_index+1<<'\t'<<input.clas<<'\t'<<input.index<<'\t'<<scopestack.top()<<endl;
	error.close();
	//cout<<"\nParser Succeeded";
	//cout<<"\nSee \"parser_log.txt\" For Details";
	}
	//No,End Marker hasn't Arrived,REJECT INPUT PROGRAM!
	else
	{
	error<<syn_index+1<<'\t'<<input.clas<<'\t'<<input.index<<'\t'<<scopestack.top()<<endl;
	error.close();
    cout<<"\nParser Failed";
	cout<<"\nParser has parsed "<< syn_index+1 <<" Tokens\n";
	cout<<"See \"parser_log.txt\" For Details\n";
	}
	
	//If u wanna See IDENTIFERs LIST with ALL details,Remove Comments from the following Lines
	/*
	cout<<"\n\nIDENTIFIERS";
	cout<<endl<<" name "<<" "<<"datatype"
		<<" "<<"scope"<<" "<<"binding"<<" "<<"f_or_not"
		<<" "<<"type"<<" "<<"offset ";
	for(unsigned int j=0;j<syn_identifier.size();j++)
	cout<<endl<<j<<" "<<syn_identifier[j].name<<'\t'
		  <<syn_identifier[j].datatype
    <<'\t'<<syn_identifier[j].scope
	<<'\t'<<syn_identifier[j].binding
	<<'\t'<<syn_identifier[j].func_or_not
	<<'\t'<<syn_identifier[j].type
	<<'\t'<<syn_identifier[j].offset
	<<'\t'<<syn_identifier[j].xtra;
	*/

	//If u wanna See What Paramters are Binded to Which Fucntion,Remove Comments from the 
	//following Lines
	/*
	cout<<"\n\nBINDINGS";
	for(j=0;j<args_identifier.size();j++)
	cout<<endl<<j<<" "<<args_identifier[j].name<<'\t'
		  <<args_identifier[j].datatype
    <<'\t'<<args_identifier[j].scope
	<<'\t'<<args_identifier[j].binding
	<<'\t'<<args_identifier[j].func_or_not
	<<'\t'<<args_identifier[j].type
	<<'\t'<<args_identifier[j].offset
	<<'\t'<<args_identifier[j].xtra;
	*/
	
	
}

void program()
{
	if(input.clas=="dt")
	{
		int type=input.index;
		advanc();
		
		if(input.clas=="id")
		{
			int index=input.index;
			settype(index,type);
			advanc();
		}
		else reject();
		
		data_or_function(type);
		program();
	}
	else if(input.clas=="void")
	{
		advanc();
		function_or_main();
	}
	else reject();
}

void data_or_function(int type)
{
	if(input.clas=="comma")
	{
		advanc();
		if(input.clas=="id")
		{
			int index=input.index;
            settype(index,type);			
			advanc();
		}
		else reject();
		data_or_function(type);
	}
	else if(input.clas=="semicolon")
		advanc();
	else if(input.clas=="parenthesis_open")
	{
		/*Since This Fucntion Shld've a RETURN statement in it's 
		body,Therefore Setting "isreturn=false",To LET IT BE TURNED
		to TRUE by a STATEMENT in Fucntion's body*/
		isreturn=false;

		advanc();
		argument_list();
		if(input.clas=="parenthesis_close")
			advanc();
		else reject();

		function_body();
	}
	else reject();
}

void function_or_main()
{
	if(input.clas=="main")
	{
		// Set FLAG to true,Since it's main STARTING
		main_func=true;

		advanc();
		if(input.clas=="parenthesis_open")
			advanc();
		else reject();
		
		if(input.clas=="void")
			advanc();
		else reject();

		if(input.clas=="parenthesis_close")
			advanc();
		else reject();

		function_body();
	}
	else if(input.clas=="id")
	{
		settype(input.index,22);
		advanc();

		if(input.clas=="parenthesis_open")
			advanc();
		else reject();

		argument_list();

		if(input.clas=="parenthesis_close")
			advanc();
		else reject();

		function_body();
		program();
	}
	else reject();
}

void function_body()
{
	int start_atom,end_atom,total;
	start_atom=end_atom=total=-10;

	if(input.clas=="braces_open")
	{
		//
		//Marking Begining Of Function
		//
		
		//Is it a main() function?
		if(main_func==true)
		{
		expr temp;
		temp.index=-1;	    //-1 For main() OR func_index For others
		temp.datatype=1;    //1 Shows Starting,0 Shows Ending
		temp.whichtable=-10; 

		setatom(34,temp,dump,dump);
		}
		//It's an ORDINARY function
		else
		{
		expr temp;
		temp.index=func_index;	    //-1 For main() OR func_index For others
		temp.datatype=1;    //1 Shows Starting,0 Shows Ending
		temp.whichtable=-10;

		setatom(34,temp,dump,dump);
		start_atom=atoms.size()-1;	//Storing Index Of Starting ATOM
		}

		//Update scope_or_binding.
		scopecount++;
		scopestack.push(scopecount);

			advanc();
			
			variable_declarations();
			statements();
			
			if(input.clas=="braces_close")
			{
				if((scopestack.size()-1)>0)
							scopestack.pop();
				else
					reject();
			advanc();
			}
			else
			reject();

		//
		//Marking Ending Of Function
		//
		
		//Is it a main() function?
		if(main_func==true)
		{
		expr temp;
		temp.index=-1;	    //-1 For main() OR func_index For others
		temp.datatype=0;    //1 Shows Starting,0 Shows Ending
		temp.whichtable=-10;
		
		setatom(34,temp,dump,dump);
		}
		//It's an ORDINARY function
		else
		{
		expr temp;
		temp.index=func_index;	    //-1 For main() OR func_index For others
		temp.datatype=0;    //1 Shows Starting,0 Shows Ending
		temp.whichtable=-10;
				
		setatom(34,temp,dump,dump);
		end_atom=atoms.size()-1;	//Storing Index Of Ending ATOM
		}
		
		//Setting LOCAL VARIABLES+TEMPoRARIES' OFFSETS.
		if(func_index!=-10)
		{
			total=calc_local_offset();
			//Now,Saving The TOTAL LENGTH of OFFSETS into the Starting 
			//and Ending PROC_MARKER ATOMS Of this Particular Fucntion
			atoms[start_atom].arg1.whichtable=total;
			atoms[end_atom].arg1.whichtable=total;
		}


		/*If this Fucntion has to return something,ASSURING that it
		has done this ATLEAST one time!*/
		if(func_index!=-10)
		{
			if(isreturn!=true&& syn_identifier[func_index].datatype!=22/*Shldn't Be void*/)
			{
				cout<<endl<<"Fucntion named "<< syn_identifier[func_index].name 
				<<" Shld return "<< syn_identifier[func_index].datatype <<endl;
				reject();
			}
		}
	
		main_func=false;	//Main Fucntion Ended
		func_index=-10;	//De-Registering Fucntion if it was local
		isreturn=false;	//Re-Setting the Return Flag
	}
	else
		reject();
}

void variable_declarations()
{
	if(input.clas=="dt")
	{
		int type=input.index;
			advanc();
			
			if(input.clas=="id")
			{
				int index=input.index;
				settype(index,type);
				advanc();
			}
			else reject();
			
			variable_list(type);

			if(input.clas=="semicolon")
				advanc();
			else reject();

			variable_declarations();
	}
	else if(input.clas=="id" || input.clas=="braces_open" || input.clas=="while" ||
		input.clas=="for" || input.clas=="do" || input.clas=="return" || 
		input.clas=="if" || input.clas=="square_open" || input.clas=="braces_close" )
	{
	
	}
	else reject();
}

void variable_list(int type)
{
	if(input.clas=="comma")
	{
		advanc();
		
		if(input.clas=="id")
		{
			int index=input.index;
			settype(index,type);
			advanc();
		}
		else reject();

		variable_list(type);
	}
	else if(input.clas=="semicolon")
	{ 
	
	}
	else reject();
}

void argument_list()
{
	if(input.clas=="void")
	{
		ident.name="void";
		ident.datatype=22;
		ident.scope=-10;
		ident.binding=syn_identifier.size()-1;
		ident.func_or_not=false;
		ident.type=3;	//For Parameters 3!.
		ident.offset=-10;	//We'll calculate it LATER
		ident.xtra=-10;

		args_identifier.push_back(ident);

		//Since we got argument list for our recently entered identifier,
		//therefore we need to recognize that as a FUNCTION NAME EXPLICITLY.
		//Updating IDENTIFIER SYMBOL TABLE
		int ind=syn_identifier.size()-1;
		ident=syn_identifier[ind];
		ident.func_or_not=true;
		syn_identifier[ind]=ident;

		//Registering This Fucntion's Start
		func_index=ind;

		advanc();
	}
    else if(input.clas=="dt")
	{
		int type=input.index;
		advanc();
		if(input.clas=="id")
		{
			int index=input.index;
            settype_args(index,type);
			advanc();
		}
		else reject();
		argument();

		//Since we got argument list for our recently entered identifier,
		//therefore we need to recognize that as a FUNCTION NAME EXPLICITLY.
		//Updating IDENTIFIER SYMBOL TABLE
		int ind=syn_identifier.size()-1;
		ident=syn_identifier[ind];
		ident.func_or_not=true;
		syn_identifier[ind]=ident;

		//Registering This Fucntion's Start
		func_index=ind;

		//Caculating Fucntion Parameter's Offsets
		int ret=calc_param_offset();

		//Storing the Total SIZE of PARAMETERS
		syn_identifier[ind].xtra=ret;
	}
	else reject();
}

void argument()
{
	if(input.clas=="comma")
	{
		int type;
		advanc();
		
		if(input.clas=="dt")
		{
			type=input.index;
			advanc();
		}
		else reject();

		if(input.clas=="id")
		{
			int index=input.index;
			settype_args(index,type);
			advanc();
		}
		else reject();

		argument();
	}
	else if(input.clas=="parenthesis_close")
	{
	
	}
	else reject();
}

void compound_statement()
{
	if(input.clas=="braces_open")
	{
		advanc();
		
		statements();
		
		if(input.clas=="braces_close")
			advanc();
		else reject();
	}
	else reject();
}

void statements()
{
	if(input.clas=="id"||input.clas=="braces_open"||input.clas=="while"||
		input.clas=="for"||input.clas=="do"||input.clas=="return"||
		input.clas=="if"||input.clas=="square_open")
	{
		statement();
		statements();
	}
	else if(input.clas=="braces_close")
	{
	
	}
	else reject();
}

void statement()
{
	if(input.clas=="id")
	{
		long ind=chk_ident(long(input.index));
		if(ind==-10)
		{
			cout<<"\nFailed in <Statement>-->id=<right_hand_side>;";
			cout<<"\nVariable Not Found ";
			reject();
		}
		expr t;
		t.index=ind;
		t.whichtable=table;
		if(table==0)
		t.datatype=syn_identifier[ind].datatype;
		else if(table==1)
		t.datatype=args_identifier[ind].datatype;

		advanc();

		if(input.clas=="assignop")
			advanc();
		else reject();
		
		expr r;
		right_hand_side(r);

		if(input.clas=="semicolon")
		advanc();
		else reject();
		
		if(chk_types(t,r)==true)
		{
		setatom(26,r,dump,t);
		}
		else
		{
				cout<<"\nType of id != <right_hand_side>";
				reject();
		}
	}
	else if(input.clas=="braces_open")
	{
		compound_statement();
	}
	else if(input.clas=="while")
	{
		expr temp;
		
		int start=newlabel();
		int end=newlabel();

		temp.datatype=25;
		temp.index=start;
		temp.whichtable=4;	// For Labels;

		setatom(25,dump,dump,temp);

		advanc();
		
		if(input.clas=="parenthesis_open")
			advanc();
		else reject();
		expr k;
		expression(k);
	
		if(input.clas=="parenthesis_close")
			advanc();
		else reject();

		temp.datatype=25;
		temp.index=end;
		temp.whichtable=4;

		expr temp1;
		temp1.datatype=0;
		temp1.index=-10;
		temp1.whichtable=-10;

		setatom(27,k,temp1,temp);

		statement();

		temp.datatype=25;
		temp.index=start;
		temp.whichtable=4;
		setatom(28,dump,dump,temp);

		temp.datatype=25;
		temp.index=end;
		temp.whichtable=4;

		setatom(25,dump,dump,temp);
	}
	else if(input.clas=="for")
	{
		int start=newlabel();
		int end=newlabel();
		int t_1=newlabel();
		int t_2=newlabel();
		
		expr i,e,s,i2,e2,ed,t1,t2,i4,e4;
		int r;

		s.index=start;
		s.datatype=25;
		s.whichtable=4;

		ed.index=end;
		ed.datatype=25;
		ed.whichtable=4;

		t1.index=t_1;
		t1.datatype=25;
		t1.whichtable=4;

		t2.index=t_2;
		t2.datatype=25;
		t2.whichtable=4;

		advanc();

		if(input.clas=="parenthesis_open")
			advanc();
		else reject();

		if(input.clas=="id")
		{
			long ind=chk_ident(long(input.index));
			if(ind==-10)
			{
			cout<<"\nFailed in <Statement>-->for(id=<expression>.......;";
			cout<<"\nVariable Not Found ";
			reject();
			}
			i.index=ind;
			i.whichtable=table;
			if(table==0)
			i.datatype=syn_identifier[ind].datatype;
			else if(table==1)
			i.datatype=args_identifier[ind].datatype;

			advanc();
		}
		else reject();

		if(input.clas=="assignop")
			advanc();
		else reject();
		
		expression(e);

		if(chk_types(i,e)==true)
			setatom(26,e,dump,i);
		else
		{
			cout<<"\nType of id!!!!!!!======<right_hand_side>";
			reject();
		}
								
		if(input.clas=="semicolon")
			advanc();
		else reject();

		setatom(25,dump,dump,s);

		if(input.clas=="id")
		{
			long ind=chk_ident(long(input.index));
			if(ind==-10)
			{
			cout<<"\nFailed in <Statement>-->for(id=<expression>.......;";
			cout<<"\nVariable Not Found ";
			reject();
			}
			i2.index=ind;
			i2.whichtable=table;
			if(table==0)
			i2.datatype=syn_identifier[ind].datatype;
			else if(table==1)
			i2.datatype=args_identifier[ind].datatype;
			advanc();
		}
		else reject();

		if(input.clas=="relop")
		{
			r=input.index;
			advanc();
		}
		else reject();
		
		expression(e2);

		if(chk_types(i2,e2)!=true)
		{
           		cout<<"\nType of id!!!!!!!======<right_hand_side>";
				reject();
		}

		setatom(r,i2,e2,ed);
		setatom(28,dump,dump,t1);
		
		if(input.clas=="semicolon")
			advanc();
		else reject();

		setatom(25,dump,dump,t2);

		if(input.clas=="id")
		{
			long ind=chk_ident(long(input.index));
			if(ind==-10)
			{
			cout<<"\nFailed in <Statement>-->for(id=<expression>.......;";
			cout<<"\nVariable Not Found ";
			reject();
			}
			i4.index=ind;
			i4.whichtable=table;
			if(table==0)
			i4.datatype=syn_identifier[ind].datatype;
			else if(table==1)
			i4.datatype=args_identifier[ind].datatype;
			advanc();
		}
		else reject();

		if(input.clas=="assignop")
			advanc();
		else reject();

		expression(e4);

		if(chk_types(i4,e4)==true)
			setatom(26,e4,dump,i4);
		else
		{
			cout<<"\nType of id!!!!!!!======<right_hand_side>";
			reject();
		}

		setatom(28,dump,dump,s);

		if(input.clas=="parenthesis_close")
			advanc();
		else reject();
		
		setatom(25,dump,dump,t1);

		statement();

		setatom(28,dump,dump,t2);
		
		setatom(25,dump,dump,ed);
	}
	else if(input.clas=="do")
	{
		int start=newlabel();
		expr temp;

		temp.datatype=25;
		temp.index=start;
		temp.whichtable=4;
		
		setatom(25,dump,dump,temp);

		advanc();

		compound_statement();

		if(input.clas=="while")
			advanc();
		else reject();

		if(input.clas=="parenthesis_open")
			advanc();
		else reject();

		expr k; expression(k);

		if(input.clas=="parenthesis_close")
			advanc();
		else reject();

		if(input.clas=="semicolon")
			advanc();
		else reject();

		expr temp1;
		temp1.datatype=1;
		temp1.index=-10;
		temp1.whichtable=-10;

		setatom(27,k,temp1,temp);
	}
	else if(input.clas=="return")
	{
		/*Since This Fucntion Shld've a RETURN statement in it's 
		body,Therefore Setting "isreturn=true",Since We Found a 
		RETURN Statement*/
		isreturn=true;

		advanc();
		expr r;
		right_hand_side(r);
		
		//t takes the index of Function Name which is binded to this 
		//particular return statement
		int t=args_identifier[args_identifier.size()-1].binding;
		
		expr temp;
		temp.datatype=syn_identifier[t].datatype;
		temp.index=t;		
		temp.whichtable=0;

		if(chk_types(temp,r)!=true)
		{
		if(func_index!=-10)
			cout<<"\nFunction "<<syn_identifier[t].name <<
				" is trying to Return mismatching datatype "<<
				r.datatype;
		else 
			cout<<"\nFunction void main(void) is trying to Return a Value";
			reject();
		}
		
		if(input.clas=="semicolon")
			advanc();
		else reject();

		setatom(29,temp,dump,r);
	}
	else if(input.clas=="if")
	{
		int end=newlabel();
		int end2=newlabel();

		advanc();
		
		if(input.clas=="parenthesis_open")
			advanc();
		else reject();
		
		expr k; expression(k);

		if(input.clas=="parenthesis_close")
			advanc();
		else reject();

		expr temp1;
		temp1.datatype=0;
		temp1.index=-10;
		temp1.whichtable=-10;

		expr temp;
		temp.datatype=25;
		temp.index=end;
		temp.whichtable=4;

		setatom(27,k,temp1,temp);

		statement();

		temp.datatype=25;
		temp.index=end2;
		temp.whichtable=4;

		setatom(28,dump,dump,temp);

		temp.datatype=25;
		temp.index=end;
		temp.whichtable=4;

		setatom(25,dump,dump,temp);

		optional_else();

		temp.datatype=25;
		temp.index=end2;
		temp.whichtable=4;

		setatom(25,dump,dump,temp);

	}
	else if(input.clas=="square_open")
	{
		advanc();
		expr f;
		function_call(f);

		if(input.clas=="square_close")
			advanc();
		else reject();

		if(input.clas=="semicolon")
			advanc();
		else reject();
		//Chking Whether This Fucntion Can Return a Value or NOT?
		//Place an ERROR if it can RETURN a value other than Void
		if(f.datatype!=22)//If it's not void
		{
			cout<<endl<<"Fucntion named "<<syn_identifier[f.index].name
				<<" is returning a value,Which is Not being CAUGHT";
			reject();
		}
	}
	else reject();
}

void optional_else()
{
	if(input.clas=="else")
	{
		advanc();
		statement();
	}
	else if(input.clas=="id"||input.clas=="while"||input.clas=="braces_open"||
		input.clas=="for"||input.clas=="do"||input.clas=="return"||
		input.clas=="if"||input.clas=="braces_close"||input.clas=="square_open")
	{

	}
	else reject();
}

void right_hand_side(expr &r)
{
	if(input.clas=="parenthesis_open" ||input.clas=="id" ||input.clas=="int_const"
		|| input.clas=="long_const")
	{
		 expression(r);
	}
	else if(input.clas=="square_open")
	{
		advanc();
		function_call(r);
		if(input.clas=="square_close")
			advanc();
		else reject();
		//Assuring that a function with void as return type 
		//doesn't appear as RIGHT HAND SIDE.
		if(r.datatype!=22)	
		{
			/*Locating the 1st RETURN statement of this particular 
			function and assigning that return value to r*/
            for(unsigned int i=0;i<atoms.size();i++)
				if(atoms[i].type==29 && atoms[i].arg1.index==r.index)
				{
					r=atoms[i].result;
					break;
				}
		}
		else{
			cout<<endl<<"Fucntion named "<<syn_identifier[r.index].name
				<<"is returning a void,Therefore It can't APPEAR as an R.H.S";
			reject();
		}
	}
	else reject();
}

void function_call(expr &f)
{
	if(input.clas=="id")
	{
		expr temp;
		long indx=chk_func(input.index);
		int no_args=-10;
		if(indx==-10)
		{
			cout<<"\nFailed in <function_call>-->id=(<optional_expression_list>)";
			cout<<"\nUsing Undefined Fuction--> "<< lex_identifier[input.index];
			reject();
		}
		f.index=indx;
		f.datatype=syn_identifier[indx].datatype;
		f.whichtable=table;

		args_info(indx,init_arg,fin_arg);
		
		/*If the Fucntion is expecting a VOID type then SET No. Of
          Arguments to 0*/
		if(args_identifier[init_arg].datatype!=22)
			no_args=(fin_arg-init_arg)+1;
		else 
			no_args=0;
		//cout<<"\nArguments "<<no_args << init_arg<< fin_arg;
		temp.datatype=-10;
		temp.index=no_args;
		temp.whichtable=-10;

		advanc();
		
		if(input.clas=="parenthesis_open")
			advanc();
		else reject();

		optional_expression_list();

		if(input.clas=="parenthesis_close")
			advanc();
		else reject();

		/*If the Fucntion is expecting a VOID type then SKIP 
		Argument PASSING STEPS*/
		if(args_identifier[init_arg].datatype!=22)
		{
			if(init_arg <= fin_arg)
			{
			cout<<"\nLess arguments are passed to function "
				<< syn_identifier[indx].name;
			reject();
			}
			if((init_arg-1) > fin_arg)
			{
			cout<<"\nMore arguments are passed to function "
				<< syn_identifier[indx].name;
			reject();
			}
		}
		setatom(31,temp,dump,f);
	}
	else reject();
}

void optional_expression_list()
{
	if(input.clas=="parenthesis_close")
	{

	}
	else if(input.clas=="parenthesis_open" || input.clas=="id" || input.clas=="int_const" ||
		input.clas=="long_const" ||	input.clas=="square_open" )
	{
		expression_list_element();
		expression_listf();
	}
	else reject();
}

void expression_listf()
{
	if(input.clas=="comma")
	{
		advanc();
		expression_list_element();
		expression_listf();
	}
	else if(input.clas=="parenthesis_close")
	{
	
	}
	else reject();
}

void expression_list_element()
{
	if(input.clas=="parenthesis_open" || input.clas=="id" || input.clas=="int_const" || 
		input.clas=="long_const")
	{
		expr k;
		expr temp;
			temp.index=init_arg;
			temp.datatype=args_identifier[init_arg].datatype;
			temp.whichtable=1;
	
			expression(k);
			
			//if((init_arg-1) > fin_arg) //OLD one
			if(init_arg > fin_arg)
			{
				cout<<"\nvoid expression_list_element() More arguments are passed to function "
					<< syn_identifier[args_identifier[fin_arg].binding].name;
					reject();
			}

            if(chk_types(k,temp)==true)
				{
				setatom(30,dump,dump,k);
				//cout<<"\nArgument List "<<k.index;
				}
			else
				{
				cout<<"Type mismatched in passing arguments to Fucntion "
					<< syn_identifier[args_identifier[fin_arg].binding].name;
				reject();
				}
		init_arg++;
	}
	else if(input.clas=="square_open")
	{
		advanc();
		expr f;
		function_call(f);
		if(input.clas=="square_close")
			advanc();
		else reject();
	}
	else reject();
}

void expression(expr &k)
{
	if(input.clas=="parenthesis_open" || input.clas=="id" || input.clas=="int_const" || 
		input.clas=="long_const")
	{
		expr t1;
		arithmetic(t1);
		relational(k,t1);
	}
	else reject();
}

void relational(expr &k,expr &t1)
{
	if(input.clas=="relop")
	{
		int op=input.index;
		advanc();
		expr t2;
		arithmetic(t2);
		if(chk_types(t1,t2)==true)
		{
		k=newtemp(t2.datatype);
		setatom(op+100,t1,t2,k);
		}
		else
		{
		cout<<"\nFailed in <Relational>--->.... "<<t1.index <<" is different from "<<t2.index;
		reject();
		}
	}
	else if(input.clas=="parenthesis_close" ||input.clas=="semicolon" ||input.clas=="comma")
	{
		k=t1;
	}
	else reject();
}

void arithmetic(expr &p)
{
	if(input.clas=="parenthesis_open" || input.clas=="id" || input.clas=="int_const" 
	  || input.clas=="long_const")
	{
		expr p1;
		t(p1);
		subtract(p1,p);
	}
	else reject();
}

void subtract(expr p,expr &q)
{
	if(input.clas=="add_sub"
		&& input.index==16)
	{
		advanc();
		expr q1;
		t(q1);
		if(chk_types(p,q1)==true)
		{
		expr r1=newtemp(p.datatype);
		setatom(16,p,q1,r1);
		subtract(r1,q);
		}
		else
		{
			cout<<"\nFailed in <Subract>--->"<< p.index<<" is different from "<<q1.index;
			reject();
		}
	}
	else if(input.clas=="relop" || input.clas=="parenthesis_close" || input.clas=="semicolon" || 
		input.clas=="comma")
	{
	q=p;
	}
	else reject();
}

void t(expr &p)
{
	if(input.clas=="parenthesis_open" || input.clas=="id" || input.clas=="int_const" || 
		input.clas=="long_const" )
	{
		expr p1;
		u(p1);
		add(p1,p);
	}
	else reject();
}

void add(expr p,expr &q)
{
	if(input.clas=="add_sub"
		&& input.index==15)
	{
		advanc();
		expr q1;
		u(q1);
		if(chk_types(p,q1)==true)
		{
		expr r1=newtemp(p.datatype);
		setatom(15,p,q1,r1);
		add(r1,q);
		}
		else
		{
		cout<<"\nFailed in <Add>--->"<< p.index<<" is different from "<<q1.index;
		reject();
		}
	}
	else if(input.clas=="add_sub" || input.clas=="relop" || input.clas=="parenthesis_close" || input.clas=="semicolon" || 
		input.clas=="comma")
	{
		q=p;
	}
	else reject();
}

void u(expr &p)
{
	if(input.clas=="parenthesis_open" || input.clas=="id" || input.clas=="int_const" ||
			input.clas=="long_const" )
	{
		expr p1;
		v(p1);
		multiply(p1,p);
	}
	else reject();
}

void multiply(expr p,expr &q)
{
	if(input.clas=="mul_div_mod"
		&& input.index==17 )
	{
		advanc();
		expr q1;
		v(q1);
		if(chk_types(p,q1)==true)
		{
		expr r1=newtemp(p.datatype);
		setatom(17,p,q1,r1);
		multiply(r1,q);
		}
		else
		{
		cout<<"\nFailed in <Multiply>--->"<<p.index<<" is different from "<<q1.index;
		reject();
		}
	}
	else if(input.clas=="add_sub" || input.clas=="add_sub" || input.clas=="relop" || input.clas=="parenthesis_close" || 
		input.clas=="semicolon" || input.clas=="comma" )
	{
		q=p;
	}
	else reject();
}

void v(expr &p)
{
	if(input.clas=="parenthesis_open" || input.clas=="id" || input.clas=="int_const" || input.clas=="long_const") 
	{
		expr p1;
		w(p1);
		divide(p1,p);
	}
	else reject();
}

void divide(expr p,expr &q)
{
	if(input.clas=="mul_div_mod"
		&& input.index==18)
	{
		advanc();
		expr q1;
		w(q1);
		if(chk_types(p,q1)==true)
		{
		expr r1=newtemp(p.datatype);
		setatom(18,p,q1,r1);
		divide(r1,q);
		}
		else
		{
		cout<<"\nFailed in <Divide>--->"<<p.index<<" is different from "<<q1.index;
		reject();
		}
	}
	else if(input.clas=="mul_div_mod" || input.clas=="add_sub" || input.clas=="add_sub" || input.clas=="relop" || 
		input.clas=="parenthesis_close" || input.clas=="semicolon" || input.clas=="comma")
	{
	q=p;
	}
	else reject();
}

void w(expr &p)
{
	if(input.clas=="parenthesis_open" || input.clas=="id" || input.clas=="int_const" || input.clas=="long_const")
	{
		expr p1;
		x(p1);
		mod(p1,p);
	}
	else reject();
	        
}

void mod(expr p,expr &q)
{
	if(input.clas=="mul_div_mod"
		&& input.index==19)
	{
		advanc();
		expr q1;
		x(q1);
		if(chk_types(p,q1)==true)
		{
		expr r1=newtemp(p.datatype);
		setatom(19,p,q1,r1);
		mod(r1,q);
		}
		else
		{
		cout<<"\nFailed in <Mod>---> "<< p.index<<"is different from "<< q1.index;
		reject();
		}
	}
	else if(input.clas=="mul_div_mod" || input.clas=="mul_div_mod" || input.clas=="add_sub" || input.clas=="add_sub" || 
		input.clas=="relop" || input.clas=="parenthesis_close" || input.clas=="semicolon" || input.clas=="comma")
	{
		q=p;
	}
	else reject();
}

void x(expr &p)
{
	if(input.clas=="parenthesis_open")
	{
		advanc();
		expression(p);
		if(input.clas=="parenthesis_close")
			advanc();
		else reject();
	}
	else if(input.clas=="id")
	{	
		long indx=chk_ident(input.index);
		if(indx!=-10) 
		{
			p.index=indx;
			p.whichtable=table;
			if(table==0)
			p.datatype=syn_identifier[indx].datatype;
			else if(table==1)
			p.datatype=args_identifier[indx].datatype;
		}
		else
		{
			cout<<"\nFailed in <X>-->...."
				<<" Variable "<<lex_identifier[input.index]<<" Not Found ";
			reject();
		}
		advanc();
	}
	else if(input.clas=="int_const")
	{
		p.datatype=23;
		p.index=input.index;
		p.whichtable=3;

		advanc();
	}
	else if(input.clas=="long_const")
	{
		p.datatype=24;
		p.index=input.index;
		p.whichtable=2;
		advanc();
	}
	else reject();
}

///**********************///
///**********************///
///						 ///
///   CODE GENERATOR	 ///
///		 STARTED		 ///	
///**********************///
///**********************///


//
//Code Generator's Globals
//
ofstream code(FILE_WRITE);
//ofstream code("C2ASM.txt");
bool collect_ebx=false;

///////////////////////////////////////////////
//
//Code Generator's Helper Fucntion Declarations
//
///////////////////////////////////////////////

//Used to ATTACH "g" to Global Variables.So,that they don't CLASH with Main()'s variables,Since
//I used to PUT all the Global And Main() Variables in .Data Segment of Assembly
void mangle_globals();

//If a Variable Appears inside some User Defined Function.It must be addressed by using [BP+..]
//In Short These and other situations,Where Name_Resolving is IMPORTANT this Function is called
string name_resolve(expr& e);

//It places All Global/Main() Variables in the Data Segment of Assembly Code.
void putvariables();

//It Converts a Long Number into String Object
string number2string(long count);

//It returns correct Jump condition for a Particular Relational Operator.
//Used By "CMP" ATOM only
string jcond4cmps(int& indx);

//It returns correct Jump condition for a Particular Relational Operator.
//Used By "JUMPF" ATOM only
string jcond4jumpf(int& indx);

//Following Functions are respective Mappings of ATOMS into Functions.
//Each of them get Called whenever ATOM of their respective type is seen.

void proc_marker(atom& atm);
void adds(atom& atm);
void assign(atom& atm);
void subs(atom& atm);
void mul(atom& atm);
void divs(atom& atm);
void label(atom& atm);
void jump(atom& atm);
void cmps(atom& atm);
void condjump(atom& atm);
void jumpf(atom& atm);
void call(atom& atm);
void param(atom& atm);
void returns(atom& atm);

//
//Code Generator's Helper Fucntion Definitions
//
void mangle_globals()
{
	for(unsigned int i=0;i<syn_identifier.size();i++)
		//Find only GLOBAL VARIABLES
		if(syn_identifier[i].binding==-2 &&
			syn_identifier[i].func_or_not==false)
		{
			syn_identifier[i].name="g"+syn_identifier[i].name;
		}
}

void putvariables()
{
	for(unsigned int i=0;i<syn_identifier.size();i++)
		//OUTPUT only GLOBAL AND MAIN VARIABLES + Temporaries
	if((syn_identifier[i].binding==-2 || syn_identifier[i].binding==-1)
		&& syn_identifier[i].func_or_not==false)
		{
		//Deciding Whether it's a LONG or an INTEGER?
		if(syn_identifier[i].datatype==0 ||syn_identifier[i].datatype==23)
		//An INTEGER
			code<<syn_identifier[i].name<<" dw "<<0<<endl;
		else
			//A LONG
			code<<syn_identifier[i].name<<" dd "<<0<<endl;
		}
}

void proc_marker(atom& atm)
{
	switch(atm.arg1.datatype)
	{
	
	//For Start Of Fucntion
	case 1:
		{
			switch(atm.arg1.index)
			{
				//It's main()
				case -1:
					code<<"main proc"<<endl
						<<"mov eax,@data"<<endl
						<<"mov ds,ax"<<endl;
					break;
				
				//It's an Ordinary Function
				default:
					code<<syn_identifier[atm.arg1.index].name
						<<" proc"<<endl
						<<"push bp"<<endl
						<<"mov bp,sp"<<endl
						<<"sub sp,"<<atm.arg1.whichtable<<endl;
			}
		}
		break;

	//For End Of Fucntion
	case 0:
		{
			switch(atm.arg1.index)
			{
				//It's main()
				case -1:
					code<<"mov ax,4c00h"<<endl
						<<"int 21h"<<endl
						<<"main endp"<<endl;
					break;
				
				//It's an Ordinary Function
				default:
					code<<"add sp,"<<atm.arg1.whichtable<<endl
						<<"pop bp"<<endl
						<<"ret"<<endl
						<<syn_identifier[atm.arg1.index].name
						<<" endp"<<endl;
			}
		}
		break;
	default:
		cout<<endl<<"Error in Fucntion Tagging";
		exit(-1);
	}

}

string name_resolve(expr& e)
{
	string name;
	switch(e.whichtable)
	{
	//Belongs to number_long
	case 2:
		name+=number2string(number_long[e.index]);
		break;

	//Belongs to number_int
	case 3:
		name+=number2string(number_int[e.index]);
		break;

	//Belongs to syn_identifier
	case 0:
		//If it Belongs to an Ordinary Fucntion
		if(syn_identifier[e.index].offset!=-10)
		{
			name+="[bp-";
			name+=number2string(syn_identifier[e.index].offset);
			name+="]";
		}
		//else it Belongs to a main() or a global variable
		else
			name=syn_identifier[e.index].name;	
		break;

		//Belongs to args_identifier
	case 1:
			name+="[bp+";
			name+=number2string(args_identifier[e.index].offset);
			name+="]";
			break;
	}
	return name;
}

string number2string(long count)
{	
	char name[40];
	char temp[40];

	ltoa(count,temp,10);
	strcpy(name,temp);

	return string(name);
}

void adds(atom& atm)
{
	//If its an INTEGER ADDITION use 16-Bit Registers
	if(atm.result.datatype==0)
	{
		code<<"push cx"<<endl
			<<"mov cx,0"<<endl
			<<"mov cx,word ptr "<<name_resolve(atm.arg1)<<endl
			<<"add cx,word ptr "<<name_resolve(atm.arg2)<<endl
			<<"mov "<<name_resolve(atm.result)<<",cx"<<endl
			<<"pop cx"<<endl;
	}
	//If its a LONG ADDITION use 32-Bit Registers
	else
	{
		code<<"push ecx"<<endl
			<<"mov ecx,0"<<endl
			<<"mov ecx,dword ptr "<<name_resolve(atm.arg1)<<endl
			<<"add ecx,dword ptr "<<name_resolve(atm.arg2)<<endl
			<<"mov "<<name_resolve(atm.result)<<",ecx"<<endl
			<<"pop ecx"<<endl;
	}
}
void assign(atom& atm)
{
	//If its an INTEGER ASSIGNMENT use 16-Bit Registers
	if(atm.result.datatype==0)
	{
		/*If The assignment is taking PLACE immediately after FUNCTION
		call,Then USE BX register from where data is to be copied*/
		if(collect_ebx==true)
		{
			code<<"mov "<<name_resolve(atm.result)<<",bx"<<endl;
			collect_ebx=false;
		}
		else
		{
		code<<"push cx"<<endl
			<<"mov cx,0"<<endl
			<<"mov cx,word ptr "<<name_resolve(atm.arg1)<<endl
			<<"mov "<<name_resolve(atm.result)<<",cx"<<endl
			<<"pop cx"<<endl;
		}
	}
	//If its a LONG ASSIGNMENT use 32-Bit Registers
	else
	{
		/*If The assignment is taking PLACE immediately after FUNCTION
		call,Then USE EBX register from where data is to be copied*/
		if(collect_ebx==true)
		{
			code<<"mov "<<name_resolve(atm.result)<<",ebx"<<endl;
			collect_ebx=false;
		}
		else
		{
		code<<"push ecx"<<endl
			<<"mov ecx,0"<<endl
			<<"mov ecx,dword ptr "<<name_resolve(atm.arg1)<<endl
			<<"mov "<<name_resolve(atm.result)<<",ecx"<<endl
			<<"pop ecx"<<endl;
		}
	}
}

void subs(atom& atm)
{
	//If its an INTEGER SUBTRACTION use 16-Bit Registers
	if(atm.result.datatype==0)
	{
		code<<"push cx"<<endl
			<<"mov cx,0"<<endl
			<<"mov cx,word ptr "<<name_resolve(atm.arg1)<<endl
			<<"sub cx,word ptr "<<name_resolve(atm.arg2)<<endl
			<<"mov "<<name_resolve(atm.result)<<",cx"<<endl
			<<"pop cx"<<endl;
	}
	//If its a LONG SUBTRACTION use 32-Bit Registers
	else
	{
		code<<"push ecx"<<endl
			<<"mov ecx,0"<<endl
			<<"mov ecx,dword ptr "<<name_resolve(atm.arg1)<<endl
			<<"sub ecx,dword ptr "<<name_resolve(atm.arg2)<<endl
			<<"mov "<<name_resolve(atm.result)<<",ecx"<<endl
			<<"pop ecx"<<endl;
	}
}

void mul(atom& atm)
{
	//If its an INTEGER MULTIPLICATION use 16-Bit Registers
	if(atm.result.datatype==0)
	{
	code<<"push cx"<<endl
		<<"mov cx,0"<<endl
		<<"mov cx,word ptr "<<name_resolve(atm.arg1)<<endl
		<<"mov "<<name_resolve(atm.result)<<",cx"<<endl
		<<"mov cx,"<<name_resolve(atm.arg2)<<endl
		<<"imul cx,word ptr "<<name_resolve(atm.result)<<endl
		<<"mov "<<name_resolve(atm.result)<<",cx"<<endl
		<<"pop cx"<<endl;
	}
	//If its a LONG MULTIPLICATION use 32-Bit Registers
	else
	{
	code<<"push ecx"<<endl
		<<"mov ecx,0"<<endl
		<<"mov ecx,dword ptr "<<name_resolve(atm.arg1)<<endl
		<<"mov "<<name_resolve(atm.result)<<",ecx"<<endl
		<<"mov ecx,dword ptr "<<name_resolve(atm.arg2)<<endl
		<<"imul ecx,"<<name_resolve(atm.result)<<endl
		<<"mov "<<name_resolve(atm.result)<<",ecx"<<endl
		<<"pop ecx"<<endl;
	}
}

void divs(atom& atm)
{
	//If its an INTEGER DIVISION use 16-Bit Registers
	if(atm.result.datatype==0)
	{
	code<<"push ax"<<endl
		<<"push cx"<<endl
		<<"push dx"<<endl
		<<"mov ax,0"<<endl
		<<"mov cx,0"<<endl
		<<"mov dx,0"<<endl
		<<"mov ax,word ptr "<<name_resolve(atm.arg1)<<endl
		<<"mov cx,word ptr "<<name_resolve(atm.arg2)<<endl
		<<"div cx"<<endl
		<<"mov "<<name_resolve(atm.result)<<",ax"<<endl
		<<"pop dx"<<endl
		<<"pop cx"<<endl
		<<"pop ax"<<endl;
	}
	//If its a LONG DIVISION use 32-Bit Registers
	else
	{
	code<<";Warning: Long Division is LOGICALLY FLAWED due to EAX"<<endl
		<<"push eax"<<endl
		<<"push ecx"<<endl
		<<"push edx"<<endl
		<<"mov eax,0"<<endl
		<<"mov ecx,0"<<endl
		<<"mov edx,0"<<endl
		<<"mov eax,dword ptr "<<name_resolve(atm.arg1)<<endl
		<<"mov ecx,dword ptr "<<name_resolve(atm.arg2)<<endl
		<<"div ecx"<<endl
		<<"mov "<<name_resolve(atm.result)<<",eax"<<endl
		<<"pop edx"<<endl
		<<"pop ecx"<<endl
		<<"pop eax"<<endl;
	}
}

void mods(atom& atm)
{
	//If its an INTEGER MOD use 16-Bit Registers
	if(atm.result.datatype==0)
	{
	code<<"push ax"<<endl
		<<"push cx"<<endl
		<<"push dx"<<endl
		<<"mov ax,0"<<endl
		<<"mov cx,0"<<endl
		<<"mov dx,0"<<endl
		<<"mov ax,word ptr "<<name_resolve(atm.arg1)<<endl
		<<"mov cx,word ptr "<<name_resolve(atm.arg2)<<endl
		<<"div cx"<<endl
		<<"mov "<<name_resolve(atm.result)<<",dx"<<endl
		<<"pop dx"<<endl
		<<"pop cx"<<endl
		<<"pop ax"<<endl;
	}
	//If its a LONG MOD use 32-Bit Registers
	else
	{
	code<<";Warning: Long MOD is LOGICALLY FLAWED due to EAX"<<endl
		<<"push eax"<<endl
		<<"push ecx"<<endl
		<<"push edx"<<endl
		<<"mov eax,0"<<endl
		<<"mov ecx,0"<<endl
		<<"mov edx,0"<<endl
		<<"mov eax,dword ptr "<<name_resolve(atm.arg1)<<endl
		<<"mov ecx,dword ptr "<<name_resolve(atm.arg2)<<endl
		<<"div ecx"<<endl
		<<"mov "<<name_resolve(atm.result)<<",edx"<<endl
		<<"pop edx"<<endl
		<<"pop ecx"<<endl
		<<"pop eax"<<endl;
	}
}

void label(atom& atm)
{
	code<<labels[atm.result.index]<<":"<<'\t'<<";It's a Label"<<endl;
}

void jump(atom& atm)
{
	code<<"jmp "<<labels[atm.result.index]<<endl;
}

void cmps(atom& atm)
{
	//Generate 2 Labels
	int i=newlabel();
	string set=labels[i];
	i=newlabel();
	string notset=labels[i];

	//Decides Which Operator To USE.
	string jcond=jcond4cmps(atm.type);

	//If its an INTEGER COMPARISION use 16-Bit Registers
	if(atm.result.datatype==0)
	{
	code<<"push cx"<<endl
		<<"mov cx,0"<<endl
		<<"mov cx,word ptr "<<name_resolve(atm.arg1)<<endl
		<<"cmp cx,word ptr "<<name_resolve(atm.arg2)<<endl
		<<jcond<<" "<<set<<endl
		<<"mov "<<name_resolve(atm.result)<<",word ptr 0"<<endl
		<<"jmp "<<notset<<endl
		<<set<<":"<<endl
		<<"mov "<<name_resolve(atm.result)<<",word ptr 1"<<endl
		<<notset<<":"<<endl
		<<"pop cx"<<endl;
	}
	//If its a LONG COMPARISION use 32-Bit Registers
	else
	{
	code<<"push ecx"<<endl
		<<"mov ecx,0"<<endl
		<<"mov ecx,dword ptr "<<name_resolve(atm.arg1)<<endl
		<<"cmp ecx,dword ptr "<<name_resolve(atm.arg2)<<endl
		<<jcond<<" "<<set<<endl
		<<"mov "<<name_resolve(atm.result)<<",dword ptr 0"<<endl
		<<"jmp "<<notset<<endl
		<<set<<":"<<endl
		<<"mov "<<name_resolve(atm.result)<<",dword ptr 1"<<endl
		<<notset<<":"<<endl
		<<"pop ecx"<<endl;
	}
}

string jcond4cmps(int& indx)
{
	string op;
	switch(indx)
	{
	case 8:
		op="je";
		break;		
		
	case 9:
		op="jne";
		break;

	case 10:
		op="jge";
		break;
		
	case 11:
		op="jle";
		break;
		
	case 12:
		op="jg";
		break;

	case 13:
		op="jl";
		break;
	}
	return op;
}

void condjump(atom& atm)
{
	//If It's an INTEGER COMPARISION
	if(atm.arg1.datatype==0)
	code<<"cmp "<<name_resolve(atm.arg1)<<",word ptr "<<atm.arg2.datatype<<endl
		<<"je "<<labels[atm.result.index]<<endl;
	else
	//If It's a LONG COMPARISION
	code<<"cmp "<<name_resolve(atm.arg1)<<",dword ptr "<<atm.arg2.datatype<<endl
		<<"je "<<labels[atm.result.index]<<endl;
}

void jumpf(atom& atm)
{
	//Decides Which Operator To USE.
	string jcond=jcond4jumpf(atm.type);

	//If its a INT COMPARISION use 16-Bit Registers
	if(atm.arg1.datatype==0)
	{
	code<<"mov cx,0"<<endl
		<<"mov cx,word ptr "<<name_resolve(atm.arg1)<<endl
		<<"cmp cx,word ptr "<<name_resolve(atm.arg2)<<endl
		<<jcond<<" "<<labels[atm.result.index]<<endl;
	}
	//If its a LONG COMPARISION use 32-Bit Registers
	else
	{
	code<<"mov ecx,0"<<endl
		<<"mov ecx,dword ptr "<<name_resolve(atm.arg1)<<endl
		<<"cmp ecx,dword ptr "<<name_resolve(atm.arg2)<<endl
		<<jcond<<" "<<labels[atm.result.index]<<endl;
	}
}

string jcond4jumpf(int& indx)
{
	string op;
	switch(indx)
	{
	case 8:
		op="jne";
		break;		
		
	case 9:
		op="je";
		break;

	case 10:
		op="jnge";
		break;
		
	case 11:
		op="jnle";
		break;
		
	case 12:
		op="jng";
		break;

	case 13:
		op="jnl";
		break;
	}
	return op;
}

void call(atom& atm)
{
	int data_type=atm.result.datatype;
	int pushed_values=syn_identifier[atm.result.index].xtra;

	code<<"call "<<syn_identifier[atm.result.index].name<<endl;

	//If Function has PUSHED PARAMETERS on STACK,Then Remove THEM!
	if(pushed_values!=-10)
	{
	for(int i=0;i<pushed_values;i+=2)
		code<<"pop ax"<<endl;
	}

	/*If Function has a return value,Then MAKE AN ANNOUNCEMENT that
	RETURN VALUE must be collected from bx or ebx.Since,If the function
	has a return value,it must appear on the R.H.S and ASSINGMENT 
	immediately takes place after fuction's execution.
		It can be seen that "assign(atoms& atm)" takes advantage of this
	ANNOUNCEMENT*/

	if(data_type!=22)
		collect_ebx=true;
}

void param(atom& atm)
{
	switch(atm.result.datatype)
	{
	//It can be an INTEGER VARIABLE or an INTEGER CONSTANT use CX
	case 0:
	case 23:
			code<<"mov cx,word ptr "<<name_resolve(atm.result)<<endl
				<<"push cx"<<endl;
			
			break;
	
	//It can be an LONG VARIABLE or an LONG CONSTANT use ECX
	case 1:
	case 24:
			code<<"mov ecx,dword ptr "<<name_resolve(atm.result)<<endl
				<<"push ecx"<<endl;
			break;
	}
}

void returns(atom& atm)
{
	switch(atm.result.datatype)
	{
	//It can be an INTEGER VARIABLE or an INTEGER CONSTANT use BX
	case 0:
	case 23:
			code<<"mov bx,word ptr "<<name_resolve(atm.result)<<endl;	
			break;
	
	//It can be an LONG VARIABLE or an LONG CONSTANT use EBX
	case 1:
	case 24:
			code<<"mov ebx,dword ptr "<<name_resolve(atm.result)<<endl;
			break;
	}
}

//Code Generator
void code_generator()
{
	int atmtype;

	//Doing NAME MANGLING of GLOBAL VARIABLES only
	mangle_globals();
	//Placing INITIAL STARTUP CODE
	code<<"page ,"<<132<<endl
		<<"TITLE *** Assembly Generated By C2ASM *** "<<endl
		<<".model medium"<<endl
		<<".stack 200h"<<endl
		<<".386"<<endl
		<<".code"<<endl;

	//Start Processing ATOMS.
	for(unsigned int k=0;k<atoms.size();k++)
	{
		atmtype=atoms[k].type;
		
		switch(atmtype)
		{
		//PROC_MARKER
		case 34:
				 proc_marker(atoms[k]);
				 break;
		
		//ADD
		case 15:
			 
				adds(atoms[k]);				
				break;
		
		//ASSIGN
		case 26:
				assign(atoms[k]);
				break;
		
		//SUB
		case 16:
				subs(atoms[k]);
				break;
		
		//MUL
		case 17:
				mul(atoms[k]);
				break;
		
		//DIV
		case 18:
				divs(atoms[k]);
				break;

		//DIV
		case 19:
				mods(atoms[k]);
				break;

		//LABEL
		case 25:
				label(atoms[k]);
				break;

		//JUMP
		case 28:
				jump(atoms[k]);
				break;

			//CMP
		case 108:
		case 109:
		case 110:
		case 111:
		case 112:
		case 113:
			atoms[k].type=atoms[k].type-100;	//Restore Orignal Index
			cmps(atoms[k]);
			break;

		//CONDJUMP
		case 27:
			condjump(atoms[k]);
			break;

		//JUMPF
		case 8:
		case 9:
		case 10:
		case 11:
		case 12:
		case 13:
			jumpf(atoms[k]);
			break;

		//CALL
		case 31:
			call(atoms[k]);
			break;

		//PARAM
		case 30:
			param(atoms[k]);
			break;

		//RETURN
		case 29:
			returns(atoms[k]);
			break;
		}//End Switch
	
	}//End Processing ATOMS.

	//Placing FINAL CLOSING CODE
	code<<".data"<<endl;
	putvariables();
	code<<"end main"<<endl;
	code.close();
}