Here is the code I need compiled. I have tried several compilers to no avail...
/*********************************************************************************************
* *
* 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.h>
#include<iostream.h>
#include<fstream.h>
#include<vector.h>
#include<stack.h>
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);
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.clas;
cout<<"\t"<<tokens.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.op<<" type="<<atoms.type
<<" arg1= "<<atoms.arg1.index <<" "<< atoms.arg1.datatype <<" "<< atoms.arg1.whichtable
<<" arg2= "<<atoms.arg2.index <<" "<< atoms.arg2.datatype <<" "<< atoms.arg2.whichtable
<<" result= "<<atoms.result.index <<" "<< atoms.result.datatype <<" "<< atoms.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.binding==func_index)
{
counter+=syn_identifier.datatype==0 ? 2 : 4;
syn_identifier.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.type==29 && atoms.arg1.index==r.index)
{
r=atoms.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.binding==-2 &&
syn_identifier.func_or_not==false)
{
syn_identifier.name="g"+syn_identifier.name;
}
}
void putvariables()
{
for(unsigned int i=0;i<syn_identifier.size();i++)
//OUTPUT only GLOBAL AND MAIN VARIABLES + Temporaries
if((syn_identifier.binding==-2 || syn_identifier.binding==-1)
&& syn_identifier.func_or_not==false)
{
//Deciding Whether it's a LONG or an INTEGER?
if(syn_identifier.datatype==0 ||syn_identifier.datatype==23)
//An INTEGER
code<<syn_identifier.name<<" dw "<<0<<endl;
else
//A LONG
code<<syn_identifier.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_res
/*********************************************************************************************
* *
* 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.h>
#include<iostream.h>
#include<fstream.h>
#include<vector.h>
#include<stack.h>
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);
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.clas;
cout<<"\t"<<tokens.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.op<<" type="<<atoms.type
<<" arg1= "<<atoms.arg1.index <<" "<< atoms.arg1.datatype <<" "<< atoms.arg1.whichtable
<<" arg2= "<<atoms.arg2.index <<" "<< atoms.arg2.datatype <<" "<< atoms.arg2.whichtable
<<" result= "<<atoms.result.index <<" "<< atoms.result.datatype <<" "<< atoms.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.binding==func_index)
{
counter+=syn_identifier.datatype==0 ? 2 : 4;
syn_identifier.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.type==29 && atoms.arg1.index==r.index)
{
r=atoms.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.binding==-2 &&
syn_identifier.func_or_not==false)
{
syn_identifier.name="g"+syn_identifier.name;
}
}
void putvariables()
{
for(unsigned int i=0;i<syn_identifier.size();i++)
//OUTPUT only GLOBAL AND MAIN VARIABLES + Temporaries
if((syn_identifier.binding==-2 || syn_identifier.binding==-1)
&& syn_identifier.func_or_not==false)
{
//Deciding Whether it's a LONG or an INTEGER?
if(syn_identifier.datatype==0 ||syn_identifier.datatype==23)
//An INTEGER
code<<syn_identifier.name<<" dw "<<0<<endl;
else
//A LONG
code<<syn_identifier.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_res