0% found this document useful (0 votes)
25 views33 pages

CD Rec 2

The document outlines various exercises related to the development of a lexical analyzer, arithmetic calculator, code optimization techniques, and the back end of a compiler using C programming. Each exercise includes an aim, algorithm, and program code, demonstrating the implementation of different programming concepts such as lexical analysis, parsing, and code generation. The results confirm the successful execution and verification of each implemented program.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
25 views33 pages

CD Rec 2

The document outlines various exercises related to the development of a lexical analyzer, arithmetic calculator, code optimization techniques, and the back end of a compiler using C programming. Each exercise includes an aim, algorithm, and program code, demonstrating the implementation of different programming concepts such as lexical analysis, parsing, and code generation. The results confirm the successful execution and verification of each implemented program.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 33

Ex.

no: 1
Develop a lexical analyzer to recognize few patterns in C
Date: (Ex. Identifiers, Constants, Comments, Operators etc.) and
Implementation of a symbol table

AIM:
To develop a lexical analyzer to recognize a few patterns in C and implement a
symbol table.

ALGORITHM:
Step 1: Start the program.
Step 2: Create some character arrays to store and manipulate the characters.
Step 3: Create a file pointer and get the name of the input file to read the
input from.
Step 4: Open the input file using the read category.
Step 5: Copy the content of the file into a string and then copy it to a
character array for processing.
Step 6: Use a while loop and browse the content of the file till the end.
Step 7: Using a if condition, Separate some symbols like ;<>{}()#,& and
print them as Special Characters.
Step 8: Using a if condition, print the letters/words following the int, char or
float as the Variables.
Step 8.1: Find and store the memory address of the variable in the symbol
table and print the symbol table after printing lexeme tokens.
Step 9: Using a if condition, print the words printf, scanf, main, void etc as
the keywords.
Step 10: Terminate the program.
PROGRAM:

#include<stdio.h>
#include<string.h>
void main(){
char a[100],temp[100];
char *word;
char delim[]=";><{}+)(&%#,= ";
char variable[10][20],datatype[10][20];
int k,noofvar=0;
void *i;
FILE *p;
p=fopen("add.c","r");
//FILE OPEN READ MODE
fscanf(p,"%s",a);
strcpy(temp,"Null");
printf("\nLexeme\tToken\n\n");
while(strcmp(a,"END")!=0){
for(k=0;k<strlen(a);k++){
if
(a[k]==';'||a[k]=='<'||a[k]=='{'||a[k]=='>'||a[k]==')'||a[k]=='}'||a[k]=='#'||a[k]=='>'||a[k]==
',' ||a[k]=='&'||a[k]=='+'||a[k]=='='||a[k]=='(')
{
printf("\033[0;37m");
printf("\n%c\tSpecial Character",a[k]);
}
}
word=strtok(a,delim);
while(word!=NULL){
if((strcmp(word,"scanf")==0)||(strcmp(word,"printf")==0)||(strcmp(word,"main")==0))
{
printf("\033[0;36m");
printf("\n%s\t",word);
printf("BUILT IN FUNCTION\t");
}
else
if((strcmp(word,"int")==0)||(strcmp(word,"float")==0)||(strcmp(word,"char")==0)||
(strcmp(word," void")==0))
{
printf("\033[0;32m");
printf("\n%s\t",word);
printf("KEYWORD\t");
}
else if((strcmp(word,"include")==0))
{
printf("\033[0;32m");
printf("\n%s\t",word);
printf("PREPROCESSOR\t");
}
else if((strcmp(word,"stdio.h")==0)||(strcmp(word,"conio.h")==0)){
printf("\033[0;33m");
printf("\n%s\t",word);
printf("HEADER FILE\t");
}
else
if((strcmp(temp,"int")==0)||(strcmp(temp,"float")==0)||(strcmp(temp,"char")==0))
{
printf("\033[0;36m");
printf("\n%s\t",word);
printf("VARIABLE\t");
strcpy(variable[noofvar], word);
strcpy(datatype[noofvar], temp);
noofvar++;
}
word = strtok(NULL, delim);
}
strcpy(temp,a);
fscanf(p,"%s",a); }
fclose(p);
//file close
//SYMBOL TABLE PGRM
printf("\n\nSYMBOL TABLE \n");
printf("------------------------------\n");
printf("symbol\taddr\t\ttype\n");
for(k=0;k<noofvar;k++){
i=malloc(variable[k][0]);
printf("\033[0;31m");
printf("%s\t%d\t%s\n",variable[k],i,datatype[k]);
}
}

ADD.c
#include<stdio.h>
#include<string.h>
void main(){
int a,b,sum;
printf("Enter number");
scanf("%d",&a);
printf("Enter number");
scanf("%d",&b);
sum=a+b;
printf("sum=%d",sum);
}
END
OUTPUT:

RESULT:
Thus the C program to implement the Lexical Analyzer is done and the required
Lexemes are obtained and the implementation of a symbol table is verified.
Ex.no: 2
IMPLEMENT A LEXICAL ANALYZER USING LEX
Date: TOOL

AIM:
To implement a Lexical Analyzer using a Lex Tool to divide the lexemes into
various categories.

ALGORITHM:
Step 1: Start the program.
Step 2: Include the header files needed.
Step 3: Use a if condition for separating the keywords like int,char,float,return.
Step 4: Use another if condition for separating the preprocessor directives like #.*
Step 5: Use another if condition for separating the function names like
main, printf, scanf.
Step 6: Use another if condition for separating the letters and words as identifiers.
Step 7: Use another if condition for separating the operators like +-/*%
Step 8: Use another if condition for separating the Special characters like ,;&{}()
Step 9: Terminate the program.
PROGRAM:

%{

#include<stdio.h>

%}

%%

int|char|float|return { printf("\n%s=> Keywords",yytext);}

#.* { printf("\n%s=>Preprocessor Directive",yytext);}

printf|scanf|main { printf("\n%s=>functions",yytext);}

["][a-z]+["] { printf("\n%s=>Strings",yytext);}

[[a-z]|[A-Z]][[a-z]|[A-Z]|[0-9]]+ { printf("\n%s=>Identifiers",yytext);}

[0-9] { printf("\n%s=>Numbers",yytext);}

"+"|"-"|"*"|"/"|"%" { printf("\n%s=>Operators",yytext);}

","|";"|"&"|"("|")"|”["|”]”|"{"|"}" { printf("\n%s=>Special Characters",yytext);}

%%

int main()

FILE *fp;

fp=fopen("input.txt","r");

yyin=fp;

yylex();

return 0;

int yywrap()

return 1;

}
input.txt:

int main()
{
int a,b;
printf("hello");
float c;
char d;
return 0;
}
OUTPUT:

RESULT:

Thus the required Lexical Analyzer is designed and the required output is
obtained and verified.
Ex.no: 3
IMPLEMENT AN ARITHMETIC CALCULATOR
Date: USING LEX AND YACC

AIM:
To create a calculator using Lex and Yacc programs.

ALGORITHM:
Step 1: Start the program.
Step 2: Include the necessary header files.
Step 3: Use a function for printing the error message.
Step 4: Get the input from the user and parse it.
Step 5: Check the input is a valid expression or not.
Step 6: Write separate operations for addition, subtraction, multiplication and division
using the expr and matching it with the operators in the in the input.
Step 7: Print the error messages for the invalid operators.
Step 8: Print the output of the expression.
Step 9: Terminate the program.
PROGRAM:
3d.l
%{
#include <stdlib.h>
#include <stdio.h>
#include "y.tab.h"
void yyerror(char*);
extern int yylval;
%}
%%
[ \t]+ ;
[0-9]+ {yylval = atoi(yytext);
return INTEGER;}
[-+*/] {return *yytext;}
"(" {return *yytext;}
")" {return *yytext;}
\n {return *yytext;}
. {char msg[25];
sprintf(msg,"%s <%s>","invalid character",yytext);
yyerror(msg);
}

3d.y
%{
#include <stdlib.h>
#include <stdio.h>
int yylex(void);
#include "y.tab.h"
%}
%token INTEGER
%%
expr:
expr '\n' { printf("%d\n",$1); }
| 'n'
expr:
expr '+' mulex { $$ = $1 + $3; }
| expr '-' mulex { $$ = $1 - $3; }
| mulex { $$ = $1; }
mulex:
mulex '*' term { $$ = $1 * $3; }
| mulex '/' term { $$ = $1 / $3; }
| term { $$ = $1; }
term:
'(' expr ')' { $$ = $2; }
| INTEGER { $$ = $1; }
%%
void yyerror(char *s)
{
fprintf(stderr,"%s\n",s);
return;
}
yywrap()
{
return(1);
}
int main(void)
{
/*yydebug=1;*/
yyparse();
return 0;
}
OUTPUT:

RESULT:
Thus a calculator is formed using Yacc and the expressions are checked and the
output of the valid expressions are obtained and verified successfully.
Ex.no: 4
IMPLEMENT SIMPLE CODE OPTIMIZATION
Date: TECHNIQUES

AIM:
To write a C program to implement Code Optimization Techniques.

ALGORITHM:
Step 1: Start the program.
Step 2: Include the necessary header files.
Step 3: Declare necessary character arrays for input and output and also a structure to
include it.
Step 4: Get the Input: Set of ‘L’ values with corresponding ‘R’ values and
Step 5: Implement the principle source of optimization techniques.
Step 6: The Output should be of Intermediate code and Optimized code after
eliminating common expressions. .
Step 7: Terminate the program.
PROGRAM:
#include<stdio.h>
#include<conio.h>
#include<string.h>
struct op
{
char l;
char r[20];
}
op[10],pr[10];
void main()
{
int a,i,k,j,n,z=0,m,q;
char *p,*l;
char temp,t;
char *tem;
clrscr();
printf("Enter the Number of Values:");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("left: ");
op[i].l=getche();
printf("\tright: ");
scanf("%s",op[i].r);
}
printf("Intermediate Code\n") ;
for(i=0;i<n;i++)
{
printf("%c=",op[i].l);
printf("%s\n",op[i].r);
}
for(i=0;i<n-1;i++)
{
temp=op[i].l;
for(j=0;j<n;j++)
{
p=strchr(op[j].r,temp);
if(p)
{
pr[z].l=op[i].l;
strcpy(pr[z].r,op[i].r);
z++;
}
}
}
pr[z].l=op[n-1].l;
strcpy(pr[z].r,op[n-1].r);
z++;
printf("\nAfter Dead Code Elimination\n");
for(k=0;k<z;k++)
{
printf("%c\t=",pr[k].l);
printf("%s\n",pr[k].r);
}
for(m=0;m<z;m++)
{
tem=pr[m].r;
for(j=m+1;j<z;j++)
{
p=strstr(tem,pr[j].r);
if(p)
{
t=pr[j].l;
pr[j].l=pr[m].l;
for(i=0;i<z;i++)
{
l=strchr(pr[i].r,t) ;
if(l)
{
a=l-pr[i].r;
printf("pos: %d",a);
pr[i].r[a]=pr[m].l;
}
}
}
}
}
printf("Eliminate Common Expression\n");
for(i=0;i<z;i++)
{
printf("%c\t=",pr[i].l);
printf("%s\n",pr[i].r);
}
for(i=0;i<z;i++)
{
for(j=i+1;j<z;j++)
{
q=strcmp(pr[i].r,pr[j].r);
if((pr[i].l==pr[j].l)&&!q)
{
pr[i].l='\0';
strcpy(pr[i].r,'\0');
}
}
}
printf("Optimized Code\n");
for(i=0;i<z;i++)
{
if(pr[i].l!='\0')
{
printf("%c=",pr[i].l);
printf("%s\n",pr[i].r);
}
}
getch();
OUTPUT:

RESULT:
Thus the required C program for implementation of code optimization
techniques is done and the required output is obtained and verified.
Ex.no: 5
IMPLEMENTING THE BACK END OF THE
Date: COMPILER

AIM:
To implement the back end of a compiler which takes the three address code
and produces the 8086 assembly language instructions using a C program.

ALGORITHM:
Step 1: Start the program.
Step 2: Include the necessary header files.
Step 3: Declare necessary character arrays for input and output and also a structure to
include it.
Step 4: Get the Intermediate Code as the input.
Step 5: Display the options to do the various operations and use a switch case to
implement that operation.
Step 6: Terminate the program.
PROGRAM:
#include<stdio.h>
#include<stdio.h>
#include<conio.h>
#include<string.h>
void main()
{
char icode[10][30],str[20],opr[10];
int i=0;
clrscr();
printf("\n Enter the set of intermediate code (terminated by exit):\n");
do
{
scanf("%s",icode[i]);
} while(strcmp(icode[i++],"exit")!=0);
printf("\n target code generation");
printf("\n************************");
i=0;
do
{
strcpy(str,icode[i]);
switch(str[3])
{
case '+':
strcpy(opr,"ADD");
break;
case '-':
strcpy(opr,"SUB");
break;
case '*':
strcpy(opr,"MUL");
break;
case '/':
strcpy(opr,"DIV");
break;
}
printf("\n\tMov %c,R%d",str[2],i);
printf("\n\t%s%c,R%d",opr,str[4],i);
printf("\n\tMov R%d,%c",i,str[0]);
}while(strcmp(icode[++i],"exit")!=0);
getch();
}
OUTPUT:

RESULT:
Thus the required C program to implement the back end of the compiler is done
and the required output is obtained and verified.
Ex.no: 6
GENERATE THREE ADDRESS CODE FOR A SIMPLE
Date: PROGRAM USING LEX AND YACC

AIM:
To convert the given input of BNF rules into Yacc form and to generate a
abstract syntax tree.

ALGORITHM:
Step 1: Start the program.
Step 2: Include the necessary header files.
Step 3: Separate the identifier and the numbers.
Step 4: Use conditions to print the keywords using the lex file.
Step 5: Create a structure and use the variables separately for operands, arguments and
results.
Step 6: Use a stack top push and pop all the contents of the input file to the output
screen,
Step 7: Use the file functions to read the input from a file.
Step 8: Use string functions to operate on the input.
Step 9: Terminate the program.
PROGRAM:
Ex6.l
%{
#include"y.tab.h"
#include<stdio.h>
#include<string.h>
int LineNo=1;
%}
identifier [a-zA-Z][_a-zA-Z0-9]*
number [0-9]+|([0-9]*\.[0-9]+)
%%
main\(\) return MAIN;
if return IF;
else return ELSE;
while return WHILE;
int|char|float return TYPE;
{identifier} {strcpy(yylval.var,yytext);
return VAR;}
{number} {strcpy(yylval.var,yytext);
return NUM;}
\<|\>|\>=|\<=|== {strcpy(yylval.var,yytext);
return RELOP;}
[ \t] ;
\n LineNo++;
. return yytext[0];
%%
Ex6.y
%{
#include<string.h>
#include<stdio.h>
struct quad
{
char op[5];
char arg1[10];
char arg2[10];
char result[10];
}QUAD[30];
struct stack
{
int items[100];
int top;
}stk;
int Index=0,tIndex=0,StNo,Ind,tInd;
extern int LineNo;
%}
%union
{
char var[10];
}
%token <var> NUM VAR RELOP
%token MAIN IF ELSE WHILE TYPE
%type <var> EXPR ASSIGNMENT CONDITION IFST ELSEST WHILELOOP
%left '-' '+'
%left '*' '/'
%%
PROGRAM : MAIN BLOCK
;
BLOCK: '{' CODE '}'
;
CODE: BLOCK
| STATEMENT CODE
| STATEMENT
;
STATEMENT: DESCT ';'
| ASSIGNMENT ';'
| CONDST
| WHILEST
;
DESCT: TYPE VARLIST
;
VARLIST: VAR ',' VARLIST
| VAR
;
ASSIGNMENT: VAR '=' EXPR{
strcpy(QUAD[Index].op,"=");
strcpy(QUAD[Index].arg1,$3);
strcpy(QUAD[Index].arg2,"");
strcpy(QUAD[Index].result,$1);
strcpy($$,QUAD[Index++].result);
}
;
EXPR: EXPR '+' EXPR {AddQuadruple("+",$1,$3,$$);}
| EXPR '-' EXPR {AddQuadruple("-",$1,$3,$$);}
| EXPR '*' EXPR {AddQuadruple("*",$1,$3,$$);}
| EXPR '/' EXPR {AddQuadruple("/",$1,$3,$$);}
| '-' EXPR {AddQuadruple("UMIN",$2,"",$$);}
| '(' EXPR ')' {strcpy($$,$2);}
| VAR
| NUM
;
CONDST: IFST{
Ind=pop();
sprintf(QUAD[Ind].result,"%d",Index);
Ind=pop();
sprintf(QUAD[Ind].result,"%d",Index);
}
| IFST ELSEST
;
IFST: IF '(' CONDITION ')' {
strcpy(QUAD[Index].op,"==");
strcpy(QUAD[Index].arg1,$3);
strcpy(QUAD[Index].arg2,"FALSE");
strcpy(QUAD[Index].result,"-1");
push(Index);
Index++;
}
BLOCK {
strcpy(QUAD[Index].op,"GOTO");
strcpy(QUAD[Index].arg1,"");
strcpy(QUAD[Index].arg2,"");
strcpy(QUAD[Index].result,"-1");
push(Index);
Index++;
};
tInd=pop();
Ind=pop();
push(tInd);
sprintf(QUAD[Ind].result,"%d",Index);
}
BLOCK{
Ind=pop();
sprintf(QUAD[Ind].result,"%d",Index);
};
CONDITION: VAR RELOP VAR {AddQuadruple($2,$1,$3,$$);
StNo=Index-1;
}
| VAR
| NUM
;
WHILEST: WHILELOOP{
Ind=pop();
sprintf(QUAD[Ind].result,"%d",StNo);
Ind=pop();
sprintf(QUAD[Ind].result,"%d",Index);
}
;
WHILELOOP: WHILE '(' CONDITION ')' {
strcpy(QUAD[Index].op,"==");
strcpy(QUAD[Index].arg1,$3);
strcpy(QUAD[Index].arg2,"FALSE");
strcpy(QUAD[Index].result,"-1");
push(Index);
Index++;
}
BLOCK {
strcpy(QUAD[Index].op,"GOTO");
strcpy(QUAD[Index].arg1,"");
strcpy(QUAD[Index].arg2,"");
strcpy(QUAD[Index].result,"-1");
push(Index);
Index++;
}
;
%%
extern FILE *yyin;
int main(int argc,char *argv[])
{
FILE *fp;
int i;
if(argc>1)
{
fp=fopen(argv[1],"r");
if(!fp)
{
printf("\n File not found");
exit(0);
}
yyin=fp;
}
yyparse();
printf("\n\n\t\t ----------------------------""\n\t\t Pos Operator Arg1 Arg2 Result" "\n\t\t---
-----------------");
for(i=0;i<Index;i++)
{
printf("\n\t\t %d\t %s\t %s\t
%s\t%s",i,QUAD[i].op,QUAD[i].arg1,QUAD[i].arg2,QUAD[i].result);
}
printf("\n\t\t -----------------------");
printf("\n\n");
return 0;
}
void push(int data)
{
stk.top++;
if(stk.top==100)
{
printf("\n Stack overflow\n");
exit(0);
}
stk.items[stk.top]=data;
}
int pop()
{
int data;
if(stk.top==-1)
{
printf("\n Stack underflow\n");
exit(0);
}
data=stk.items[stk.top--];
return data;
}
void AddQuadruple(char op[5],char arg1[10],char arg2[10],char result[10])
{
strcpy(QUAD[Index].op,op);
strcpy(QUAD[Index].arg1,arg1);
strcpy(QUAD[Index].arg2,arg2);
sprintf(QUAD[Index].result,"t%d",tIndex++);
strcpy(result,QUAD[Index++].result);
}
yyerror()
{
printf("\n Error on line no:%d",LineNo);
}
input.c
main()
{
int a,b,c;
if(a<b)
{
a=a+b;
}
while(a<b)
{
a=a+b;
}
if(a<=b)
{
c=a-b;
}
else
{
c=a+b;
}
}
OUTPUT:

RESULT:
Thus the three address code for a simple program is created and the output is
verified successfully.

You might also like