Compiler Design Lab

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 29

Compiler Design Lab [KCS -552]

FOR
ACADEMIC YEAR 2023-2024

BUNDELKHAND INSTITUTE OF ENGINEERING


AND TECHNOLOGY, JHANSI
(BIET JHANSI)-284128

Submitted to: - Submitted by: -


Er. SWETA RAJPOOT NIKHIL KUMAR
Roll No. 2100430100033
INDEX

S.No. Date Aim/Objective T. Sign

1 Design and implement a lexical analyzer for given language


using C and the lexical analyzer should ignore redundant
spaces, tabs, and new lines.

2 Implementation of Lexical Analyzer using Lex Tool

3(a) Program to recognize a valid arithmetic expression that uses


operator +, - , * and /.

3(b) Program to recognize a valid variable which starts with a letter


followed by any number of letters or digits.

4 Write program to find ε – closure of all states of any given NFA


with ε transition.

5 Develop an operator precedence parser for a given language

6 Construct a Shift Reduce Parser for a given language.

7 Write a program to perform loop unrolling

8 Write a program to perform constant propagation.

9 Implement Intermediate code generation for simple


expressions.

10 Implement the back end of the compiler which takes the


three address code and produces the 8086-assembly language
instructions that can be assembled and run using an 8086
assembler. The target assembly instructions can be simple
move, add, sub, jump etc.
Practical -1
Design and implement a lexical analyzer for given language using Cand
the lexical analyzer should ignore redundant spaces, tabs, and new
lines.

PROGRAM:
#include<string.h
>
#include<ctype.h
>
#include<stdio.h>
void keyword(char str[10])
{
if(strcmp("for",str)==0||strcmp("while",str)==0||strcmp("do",str)==0|| strcmp("int",str)==0||
strcmp("float",str)==0||strcmp("char",str)==0||strcmp("double",str)== 0||

strcmp("static",str)==0||strcmp("switch",str)==0||strcmp("case",str)==0)
printf("\n%s is a keyword",str);
else
printf("\n%s is an identifier",str);
}

main()
{
FILE *f1,*f2,*f3;
char c,str[10],st1[10];
int
num[100],lineno=0,tokenvalue=0,i=0,j=0,k=0;
printf("\nEnter the c program");/*gets(st1);*/
f1=fopen("input","w"); while((c=getchar())!
=EOF)
putc(c,f1)
;
fclose(f1)
;
f1=fopen("input","r");
f2=fopen("identifier","w");
f3=fopen("specialchar","w")
; while((c=getc(f1))!=EOF)
{ if(isdigit(c))
{
tokenvalue=c-'0';
c=getc(f1);
while(isdigit(c)){
tokenvalue*=10+c-'0'
; c=getc(f1);
}
num[i+
+]=tokenvalue;
ungetc(c,f1);
}
else if(isalpha(c))
{
putc(c,f2);
c=getc(f1)
;
while(isdigit(c)||isalpha(c)||c=='_'||c=='$')
{
putc(c,f2);
c=getc(f1)
;
}
putc(' ',f2);
ungetc(c,f1)
;
}
else if(c==' '||c=='\t')
printf(" ");
else
if(c=='\n')
lineno++;
else
putc(c,f3)
;
}
fclose(f2)
;
fclose(f3)
;
fclose(f1)
;
printf("\nThe no's in the program are");
for(j=0;j<i;j++)
printf("%d",num[j]);
printf("\n");
f2=fopen("identifier","r")
; k=0;
printf("The keywords and
identifiersare:"); while((c=getc(f2))!
=EOF){
if(c!=' ')
str[k+
+]=c; else
{
str[k]='\0';
keyword(str)
; k=0;
}
}
fclose(f2);
f3=fopen("specialchar","r");
printf("\nSpecial characters are");
while((c=getc(f3))!=EOF)
printf("%c",c);
printf("\n");
fclose(f3);
printf("Total no. of lines are:
%d",lineno);
}
Practical -2
Implementation of Lexical Analyzer using Lex
Tool Program-
/* program name is lexp.l */
%{
/* program to recognize a c program */
int COMMENT=0;
int cnt=0;
%}
identifier [a-zA-Z][a-zA-Z0-9]*
%%
#.* { printf("\n%s is a PREPROCESSOR
DIRECTIVE",yytext);} int |
float |
char |
double |
while |
for |
do |
if |
break |
continue |
void |
switch |
case |
long |
struct |
const |
typedef |
return |
else |
goto {printf("\n\t%s is a
KEYWORD",yytext);} "/*" {COMMENT
= 1;}
"*/" {COMMENT = 0; cnt++;}
{identifier}\( {if(!COMMENT)printf("\n\nFUNCTION\n\t%s",yytext);}
\{ {if(!COMMENT) printf("\n BLOCK BEGINS");}
\} {if(!COMMENT) printf("\n BLOCK ENDS");}
{identifier}(\[[0-9]*\])? {if(!COMMENT) printf("\n %s IDENTIFIER",yytext);}
\".*\" {if(!COMMENT) printf("\n\t%s is a
STRING",yytext);} [0-9]+ {if(!COMMENT) printf("\n\t%s
is a NUMBER",yytext);}
\)(\;)? {if(!COMMENT) printf("\n\t");ECHO;printf("\n");}
\( ECHO;
= {if(!COMMENT)printf("\n\t%s is an ASSIGNMENT OPERATOR",yytext);}
\<= |
\>= |
\< |
== |
\> {if(!COMMENT) printf("\n\t%s is a RELATIONAL OPERATOR",yytext);}
%%
int main(int argc,char **argv)
{
if (argc > 1)
{
FILE *file;
file =
fopen(argv[1],"r"); if(!
file)
{
printf("could not open %s \
n",argv[1]); exit(0);
}
yyin = file;
}
yylex();
printf("\n\n Total No.Of comments are
%d",cnt); return 0;
}
int yywrap()
{
return 1;

Input:
#include<stdio.h
> main()
{
int a,b;
}
Output:
#include<stdio.h> is a PREPROCESSOR DIRECTIVE
FUNCTION
main (
)
BLOCK BEGINS
int is a
KEYWORD a
IDENTIFIER
b
IDENTIFIE
R BLOCK
ENDS
Practical -3(a)
Program to recognize a valid arithmetic expression that uses
operator +, - , * and /.

Program:-
%{
/* This LEX program returns the tokens for the expression */
#include “y.tab.h”
%}

%%
“=” {printf(“\n Operator is
EQUAL”);} “+” {printf(“\n
Operator is PLUS”);}
“-“ {printf(“\n Operator is MINUS”);}
“/” {printf(“\n Operator is
DIVISION”);}
“*” {printf(“\n Operator is MULTIPLICATION”);}

[a-z A-Z]*[0-9]* {
printf(“\n Identifier is %s”,yytext);
return ID;
}
return yytext[0];
\n return 0;
%%

int yywrap()
{
return 1;
}

Program Name : arith_id.y

%{
#include
/* This YYAC program is for recognizing the Expression */
%}
%%
statement: A’=’E
|E{
printf(“\n Valid arithmetic expression”);
$$ = $1;
};

E: E’+’ID
| E’-’ID
| E’*’ID
| E’/’ID
| ID
;
%%
extern FILE
*yyin; main()
{
do
{
yyparse();
}while(!feof(yyin));
}

yyerror(char*s)
{
}

Output:

[root@localhost]# lex arith_id.1


[root@localhost]# yacc –d arith_id.y
[root@localhost]# gcc lex.yy.c
y.tab.c [root@localhost]# ./a.out
x=a+b;

Identifier is x
Operator is
EQUAL Identifier
is a Operator is
PLUS Identifier is
b

Practical -3(b)
Program to recognize a valid variable which starts with a letter
followed by any number of letters or digits.
Program name: variable_test.l

%{
/* This LEX program returns the tokens for the Expression
*/ #include "y.tab.h"
%}
%%
"int " {return INT;}
"float" {return
FLOAT;}
"double" {return
DOUBLE;} [a-zA-Z]*[0-
9]*{
printf("\nIdentifier is
%s",yytext); return ID;
}
return yytext[0];
\n return 0;
int yywrap()
{
return 1;
}

Program name: variable_test.y

%{
#include
/* This YACC program is for recognising the Expression*/
%}
%token ID INT FLOAT DOUBLE
%%
D;T
L
;
L:L,I
D
|ID
;
T:IN
T
|FLOAT
|DOUBLE
;
%%
extern FILE
*yyin; main()
{
do
{
yyparse();
}while(!feof(yyin));
}
Practical -4
Write program to find ε – closure of all states of any given NFA with
ε transition.
Program: -
#include<stdio.h>
#include<string.h
>
char result[20][20], copy[3], states[20]
[20]; void add_state(char a[3], int i) {
strcpy(result[i], a);
}
void display(int n)
{ int k = 0;
printf("nnn Epsilon closure of %s = { ",
copy); while (k < n) {
printf(" %s",
result[k]); k++;
}
printf(" } nnn");
}
int main() {
FILE *
INPUT;
INPUT = fopen("input.dat",
"r"); char state[3];
int end, i = 0, n, k = 0;
char state1[3], input[3], state2[3];
printf("n Enter the no of states: ");
scanf("%d", & n);
printf("n Enter the states n");
for (k = 0; k < 3; k++) {
scanf("%s", states[k]);
}
for (k = 0; k < n; k+
+) { i = 0;
strcpy(state, states[k]);
strcpy(copy, state);
add_state(state, i++);
while (1) {
end = fscanf(INPUT, "%s%s%s", state1, input,
state2); if (end == EOF) {
break;
}
if (strcmp(state, state1) == 0)
{ if (strcmp(input, "e") == 0)
{ add_state(state2, i++);
strcpy(state, state2);
}
}
}
display(i);
rewind(INPUT
);
}
return 0;
}
Input-
q0 0 q0
q0 1 q1
q0 e q1
q1 1 q2
q1 e q2
Output-
Enter the no of states: 3
Enter the states
q0
q1
q2
Epsilon closure of q0 = { q0 q1 q2
} Epsilon closure of q1 = { q1
q2 } Epsilon closure of q2 = { q2
}

Practical -5
Develop an operator precedence parser for a given language
Program: -
#include<stdlib.h
>
#include<stdio.h>
#include<string.h
>
// function f to exit from the loop
// if given condition is not true
void f()
{
printf("Not operator grammar");
exit(0);
}
void main()
{
char grm[20][20], c;
// Here using flag variable,
// considering grammar is not operator grammar
int i, n, j = 2, flag = 0;
// taking number of productions from user
scanf("%d", &n);
for (i = 0; i < n; i++)
scanf("%s", grm[i]);
for (i = 0; i < n; i++) {
c = grm[i][2];
while (c != '\0') {
if (grm[i][3] == '+' || grm[i][3] == '-'
|| grm[i][3] == '*' || grm[i][3] == '/')
flag = 1;
else {

flag =
0; f();
}
if (c == '$') {
flag =
0; f();
}
c = grm[i][++j];
}
}

if (flag == 1)
printf("Operator grammar");
}
Practical -6
Construct a Shift Reduce Parser for a given language.
Program: -
// Including Libraries
#include <bits/stdc+
+.h> using namespace
std;

// Global Variables
int z = 0, i = 0, j = 0, c = 0;

// Modify array size to increase


// length of string to be parsed
char a[16], ac[20], stk[15],
act[10];

// This Function will check whether


// the stack contain a production rule
// which is to be Reduce.
// Rules can be E->2E2 , E->3E3 , E-
>4 void check()
{
// Copying string to be printed as action
strcpy(ac,"REDUCE TO E -> ");

// c=length of input string


for(z = 0; z < c; z++)
{
// checking for producing rule E-
>4 if(stk[z] == '4')
{
printf("%s4", ac);
stk[z] = 'E';
stk[z + 1] = '\0';

//printing action printf("\n$


%s\t%s$\t", stk, a);
}
}

for(z = 0; z < c - 2; z++)


{
// checking for another production
if(stk[z] == '2' && stk[z + 1] == 'E'
&& stk[z + 2] == '2')

{
printf("%s2E2", ac);
stk[z] = 'E';
stk[z + 1] = '\0';
stk[z + 2] = '\0'; printf("\n$
%s\t%s$\t", stk, a); i = i - 2;
}

for (z = 0; z < c - 2; z++)


{
//checking for E->3E3
if(stk[z] == '3' && stk[z + 1] == 'E' && stk[z + 2] == '3')
{
printf("%s3E3", ac);
stk[z]='E';
stk[z + 1]='\0';
stk[z + 1]='\0'; printf("\n$%s\
t%s$\t", stk, a); i = i - 2;
}
}
return; // return to main
}

// Driver
Function int main
()
{
printf("GRAMMAR is -\nE->2E2 \nE->3E3 \nE->4\n");

// a is input string
strcpy(a,"32423")
;

// strlen(a) will return the length of a to c


c=strlen(a);

// "SHIFT" is copied to act to be


printed strcpy(act,"SHIFT");

// This will print Labels (column


name) printf("\nstack \t input \t
action");

// This will print the initial


// values of stack and input
printf("\n$\t%s$\t", a);

// This will Run upto length of input


string for (i = 0; j < c; i++, j++)
{
// Printing action
printf("%s",
act);

// Pushing into stack


stk[i] = a[j];
stk[i + 1] = '\0';

// Moving the pointer


a[j]=' ';
// Printing action printf("\n$
%s\t%s$\t", stk, a);

// Call check function ..which will


// check the stack whether its contain
// any production or not
check();
}
// Rechecking last time if contain
// any valid production then it will
// replace otherwise invalid
check();

// if top of the stack is E(starting symbol)


// then it will accept the input
if(stk[0] == 'E' && stk[1] == '\
0')
printf("Accept\
n"); else //else reject
printf("Reject\n");
}
Practical -7
Write a program to perform loop unrolling
Program 1:
// This program does not use loop unrolling.
#include<stdio.h>

int main(void)
{
for (int i=0; i<5; i++)
printf("Hello\n"); //print hello 5 times

return 0;
}

Program 2:
// This program uses loop
unrolling. #include<stdio.h>

int main(void)
{
// unrolled the for loop in program 1
printf("Hello\n");
printf("Hello\
n");
printf("Hello\
n");
printf("Hello\
n");
printf("Hello\
n");

return 0;
}
Practical -8
Write a program to perform constant propagation.
Program: -

#include <stdio.h>
int main ()
{
int c;
float r, pi = floor((22.0 / 7.0)*100)/100;//pi value is calculated by 22/7 and assigned to pi variable
do
{
printf ("\nMENU");
printf
("\n1. Find perimeter and area of circle without constant propagation");
printf
("\n2. Find perimeter and area of circle with constant propagation Code optimization");
printf ("\n3. Exit");
printf ("\nEnter your Option : ");
scanf ("%d", &c);
switch (c)
{
case 1:

printf ("Enter the radius of circle :");


scanf ("%f", &r);
printf ("Perimeter = %0.2f", 2 * pi * r);
printf ("\nArea = %0.2f", pi * r * r);
break;
case 2:
printf ("Enter the radius of circle :");
scanf ("%f", &r);
printf ("Perimeter = %0.2f", 2 * 3.14 * r);
printf ("\nArea = %0.2f", 3.14 * r * r);

break;
}

}
Practical -9
Implement Intermediate code generation for simple expressions.
Program: -
#include <stdio.h>
#include <string.h>
int i = 1, j = 0, no = 0, tmpch =
90; char str[100], left[15],
right[15];

void findopr();
void explore();
void fleft(int);
void
fright(int);
struct ex
{
int pos;
char op;
} k[15];
void main()
{
printf("\t\tINTERMEDIATE CODE
GENERATION\n\n"); printf("Enter the
Expression :");
scanf("%s", str);
printf("The intermediate code:\n");
findopr();
explore();
}
void findopr()

{
for (i = 0; str[i] != '\0'; i++)
if (str[i] == ':')
{
k[j].pos = i;
k[j++].op = ':';
}
for (i = 0; str[i] != '\0'; i+
+) if (str[i] == '/')
{
k[j].pos = i;
k[j++].op = '/';
}
for (i = 0; str[i] != '\0'; i+
+) if (str[i] == '*')
{
k[j].pos = i;
k[j++].op = '*';
}
for (i = 0; str[i] != '\0'; i+
+) if (str[i] == '+')
{ k[j].pos = i;
k[j++].op = '+';
}
for (i = 0; str[i] != '\0'; i++)
if (str[i] == '-')
{
k[j].pos = i;
k[j++].op = '-';
}
}
void explore()
{
i = 1;
while (k[i].op != '\0')
{
fleft(k[i].pos);
fright(k[i].pos);
str[k[i].pos] = tmpch--;
printf("\t%c := %s%c%s\t\t", str[k[i].pos], left, k[i].op,
right); printf("\n");
i++;
}
fright(-1);
if (no ==
0)
{ fleft(strlen(str));
printf("\t%s := %s", right,
left); exit(0);
}
printf("\t%s := %c", right, str[k[--i].pos]);
}
void fleft(int x)
{
int w = 0, flag =
0; x--;
while (x != -1 && str[x] != '+' && str[x] != '*' && str[x] != '=' && str[x] != '\0' &&
str[x] != '-' && str[x] != '/' && str[x] != ':')
{ if (str[x] != '$' && flag == 0)
{ left[w++] = str[x];
left[w] = '\0';
str[x] =
'$'; flag =
1;
}
x--;
}
}
void fright(int x)
{ int w = 0, flag =
0; x++;
while (x != -1 && str[x] != '+' && str[x] != '*' && str[x] != '\0' && str[x] != '=' &&
str[x] != ':' && str[x] != '-' && str[x] != '/')
{
if (str[x] != '$' && flag == 0)
{right[w++] = str[x];
right[w] = '\0';
str[x] =
'$'; flag =
1;
}
x+
+;
}
}
Practical -10
Implement the back end of the compiler which takes the three- address
code and produces the 8086-assembly language instructionsthat can be
assembled and run using an 8086 assembler. The target assembly
instructions can be simple move, add, sub, jump etc.
Program: -
#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();
}

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy