0% found this document useful (0 votes)
40 views

Compiler Design Lab

The document outlines a compiler design lab for the academic year 2022-2023 at BIET Jhansi. It contains an index listing 10 practical assignments related to compiler design topics like lexical analysis, parsing, intermediate code generation, and code optimization. The document is submitted by Akhilesh Tyagi, a student with roll number 2004310012.

Uploaded by

abyefinalhai
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)
40 views

Compiler Design Lab

The document outlines a compiler design lab for the academic year 2022-2023 at BIET Jhansi. It contains an index listing 10 practical assignments related to compiler design topics like lexical analysis, parsing, intermediate code generation, and code optimization. The document is submitted by Akhilesh Tyagi, a student with roll number 2004310012.

Uploaded by

abyefinalhai
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/ 26

Compiler Design Lab [KCS -552]

FOR
ACADEMIC YEAR 2022-2023

BUNDELKHAND INSTITUTE OF ENGINEERING AND


TECHNOLOGY, JHANSI
(BIET JHANSI)-284128

Submitted to: - Submitted by: -


Er. Hemant Kushwaha Akhilesh Tyagi
Roll No. 2004310012
INDEX

Name: Akhilesh Tyagi Roll No.:2004310012

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 C and
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);
}

Input:
Enter Program $ for termination:
{
int a[3],t1,t2;
t1=2; a[0]=1; a[1]=2; a[t1]=3;
t2=-(a[2]+t1*6)/(a[2]-t1);
if t2>5 then
print(t2);
else {
int t3;
t3=99;
t2=-25;
print(-t1+t2*t3); /* this is a comment on 2 lines */
} endif
}

Output:
Variables : a[3] t1 t2 t3
Operator : - + * / >
Constants : 2 1 3 6 5 99 -25
Keywords : int if then else endif
Special Symbols : , ; ( ) { }
Comments : this is a comment on 2 lines
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 IDENTIFIER
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,ID
|ID
;
T:INT
|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 instructions that 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