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.