Cdlab Manual 2020-21 Updated
Cdlab Manual 2020-21 Updated
LABORATORY
To be recognized globally for delivering high quality education in the ever changing field of
computer science & engineering, both of value & relevance to the communities we serve.
PEO 1: Learning: Our graduates to be competent with sound knowledge in field of Computer
Science &Engineering.
PEO 2: Employable: To develop the ability among students to synthesize data and technical
concepts for application to software product Design for successful careers that meet
the needs of Indian and multinationalcompanies.
PEO 3: Innovative: To develop research oriented analytical ability among students to prepare
them for making technical contribution to thesociety.
PROGRAM OUTCOMES(POs)
PO2: Problem analysis: Identify, formulate, review research literature, and analyze
complex engineering problems reaching substantiated conclusions using first principles
of mathematics, natural sciences, and engineeringsciences.
PO5: Modern tool usage: Create, select, and apply appropriate techniques, resources,
a n d modern engineering and IT tools including prediction and modelling to complex
engineering activities with an understanding of thelimitations.
PO6: The engineer and society: Apply reasoning informed by the contextual knowledge
to assess societal, health, safety, legal and cultural issuesand the consequent
responsibilities relevant to the professional engineeringpractice.
PO9: Individual and team work: Function effectively as an individual, and as a member
or leader in diverse teams, and in multidisciplinary settings.
comprehend and write effective reports and Design documentation, make effective
presentations, and give and receive clear instructions.
PO11: Project management and finance: Demonstrate knowledge and understanding
of the engineering and management principles and apply these to one’s own work, as
a member and leader in a team, to manage projects and in multidisciplinaryenvironments.
PO12: Life-long learning: Recognize the need for, and have the preparation and ability
to engage in independent and life-long learning in the broadest context of
technologicalchange.
PSO2: The ability to employ latest computer languages and platforms in creating innovative
career opportunities.
C308.1 Identify patterns, tokens & regular expressions for lexical analysis.
C308.2 Design Lexical analyser for given language using C and LEX /YACC tools
CO-PO MAPPING
PO1 PO2 PO3 PO PO5 PO6 PO7 PO8 PO9 PO10 PO11 PO12
4
C308.1 3 3 2 3 2
C308.2 3 3 3 3 3 2
C308.3 3 2 2 3 2
C308.4 3 2 3 3 2
C308.5 3 2 2 3 2
CO-PSO MAPPING
PSO1 PSO2
C308.1 3 3
C308.2 3 2
C308.3 3 2
C308.4 3 2
C308.5 3 2
Corresponding
Sr. No. Title of Experiment CO
Design and implement a lexical analyzer for given
1 language using C and the lexical analyzer should ignore C308.1
redundant spaces, tabs and new lines.
Implementation of Lexical Analyzer using Lex Tool C308.2
2
Generate YACC specification for a few syntactic categories. a) C308.2
Program to recognize a valid arithmetic expression that uses operator
3 +, – , * and /. b) Program to recognize a valid variable which starts
with a letter followed by any number of letters or digits. c)
Implementation of Calculator using LEX and YACC d) Convert the
BNF rules into YACC form and write code to generate abstract
syntax tree
4 Write program to find ε – closure of all states of any given NFA with C308.1
ε transition.
Write program to convert NFA with ε transition to NFA without ε C308.1
5 transition.
9 Write program to find Simulate First and Follow of any given C308.3
grammar.
INTRODUCTION
The language Processors comprises assemblers, compilers and interpreters. It deals with the recognition the
translation, and the execution of formal languages It is closely related to compiler construction. Compiler
is system software that converts high level language into low level language. We human beings can’t
program in machine language (low level lang.) understood by computers so we program in high level
language and compiler is the software which bridges the gap between user andcomputer.
PREFACE
This lab is as a part of B.Tech. VI semester for CSE students. Compiler Design principles provide an
in-depth view of translation and optimization process. This lab enables the students to practice basic
translation mechanism by Designing complete translator for a mini language and error detection &
recovery. It includes lexical, syntax, and semantic analysis as front end, and code generation and
optimization as back-end with recommended systems/software requirements following the university
prescribed textbooks. The expected outcomes from the studentsare:
1. By this laboratory, students will understand the practical approach of how a compilerworks.
2. This will enable him to work in the development phase of new computer languages inindustry.
We extend our sincere thanks to Department of Computer Science and Engineering, R.K.G.I.T.,
Ghaziabad, for giving us this opportunity to prepare a Compiler Design Lab .
DO’s
DONT’S
1. Know the location of the fire extinguisher and the first aid box and how to use them
in case of anemergency.
While preparing the lab records, the student is required to adhere to the following guidelines:
x 10.
Experiments
⮚ Aim
⮚ Sourcecode
⮚ Input-Output
Name
Roll No.
Section- Batch
Raj Kumar Goel Institute of Technology,Ghaziabad
Department of Computer Science & Engineering
INDEX
Experiment Experiment Name Date of Date of Faculty
No. Conductio Submissio Signatur
n n e
Students are provided with the details of the experiment (Aim, pre-experimental questions,
procedure etc.) to be conducted in next lab and are expected to come prepared for each lab class.
Faculty ensures that students have completed the required pre-experiment questions and they
complete the in-lab programming assignment(s) before the end of class. Given that the lab
programs are meant to be formative in nature, students can ask faculty for help before and during
the lab class.
Students’ performance will be assessed in each lab based on the following Lab Assessment
Components:
Assessment Criteria-1: Performance (Max. marks = 5)
Assessment Criteria-2: VIVA (Max. marks = 5)
Assessment Criteria-3: Record (Max. marks = 5)
In each lab class, students will be awarded marks out of 5 under each component head,
making it total out of 15 marks.
EXPERIMENT#1
Aim: Design and implement a lexical analyzer for given language using C and the lexical analyzer
should ignore redundant spaces, tabs and new lines.
Description:
Lexical analysis or scanning is the process where the stream of characters making up the source
program is read from left-to-right and grouped into tokens. Tokens are sequences of characters with a
collective meaning. There are usually only a small number of tokens for a programming language:
constants (integer, double, char, string, etc.), operators (arithmetic, relational, logical), punctuation,
and reserved words.
PROGRAM CODE:
#include<stdio.h>
#include<conio.h>
#include<ctype.h>
#include<string.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 key word”, 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 te c ptogram”);
f1=fopen(“input”, “w”);
while((c=getchar())!=EOF)
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 : , ; ( ) { }
Compiler Design (KCS-552) (CS, V SEM)
Page 19
Raj Kumar Goel Institute of Technology, Ghaziabad
EXPERIMENT #2
Aim: To write a c program for implementing a lexical analyzer using LEX tool
ALGORITHM:
Step1: Lex program contains three sections: definitions, rules, and user subroutines. Each section must
be separated from the others by a line containing only the delimiter, %%. The format is as
follows: definitions %% rules %% user_subroutines
Step2: In definition section, the variables make up the left column, and their definitions make up the
right column. Any C statements should be enclosed in %{..}%. Identifier is defined such that the first
letter of an identifier is alphabet and remaining letters are alphanumeric.
Step3: In rules section, the left column contains the pattern to be recognized in an input file to yylex().
The right column contains the C program fragment executed when that pattern is recognized. The
various patterns are keywords, operators, new line character, number, string, identifier, beginning and
end of block, comment statements, preprocessor directive statements etc.
Step4: Each pattern may have a corresponding action, that is, a fragment of C source code to execute
when the pattern is matched.
Step5: When yylex() matches a string in the input stream, it copies the matched text to an external
character array, yytext, before it executes any actions in the rules section.
Step6: In user subroutine section, main routine calls yylex(). yywrap() is used to get more input.
Step7: The lex command uses the rules and actions contained in file to generate a program, lex.yy.c,
Compiler Design (KCS-552) (CS, V SEM)
Page 20
Raj Kumar Goel Institute of Technology, Ghaziabad
PROGRAM CODE:
INPUT:
//var.c
#include<stdio.h>
#include<conio.h>
void main()
{
int a,b,c;
a=1;
b=2;
c=a+b;
printf("Sum:%d",c);
}
OUTPUT:
EXPERIMENT #3
Aim: Generate YACC specification for a few syntactic categories:
a) Program to recognize a valid arithmetic expression that uses operator +, – , * and /.
b) Program to recognize a valid variable which starts with a letter followed by any number of letters or digits.
c) Implementation of Calculator using LEX and YACC
d) Convert the BNF rules into YACC form and write code to generate abstract syntax tree
Description:
A parser generator is a program that takes as input a specification of a syntax, and produces as output
a procedure for recognizing that language. Historically, they are also called compiler-compilers.
Program name:arith_id.l
%{
/* 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;
}
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
%{
/* 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);
Compiler Design (KCS-552) (CS, V SEM)
Page 25
Raj Kumar Goel Institute of Technology, Ghaziabad
%{
#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));
}
yyerror(char*s)
{
}
Output:
Identifier is a
Identifier is b[root@localhost]#
Compiler Design (KCS-552) (CS, V SEM)
Page 26
Raj Kumar Goel Institute of Technology, Ghaziabad
Program name:calci.l
%{
#include "y.tab.h" /*defines the tokens*/
#include ,math.h.
%}
%%
/*To recognise a valid number*/
([0-9] + |([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?) {yylval.dval = atof(yytext);
return NUMBER;}
/*For log no | Log no (log base 10)*/
log | LOG {return LOG;}
/*End of input*/
\$ {return 0;}
%{
double memvar;
%}
/*No associativity*/
%nonassoc UMINUS /*Unary Minus*/
Output:
2*2+5/4
Answer = 5.25
mem = cos 45
sin 45/mem
Answer = 1
ln 10
Answer = 2.
EXPERIMENT #4
Aim: Write program to find ε – closure of all states of any given NFA with ε transition.
Description:
A nondeterministic finite automaton (NFA), or nondeterministic finite state machine, does not need to
obey these restrictions. In particular, every DFA is also an NFA.
Using the subset construction algorithm, each NFA can be translated to an equivalent DFA, i.e. a DFA
recognizing the same formal language. Like DFAs, NFAs only recognize regular languages. Sometimes
the term NFA is used in a narrower sense, meaning an automaton that properly violates an above restriction
i.e. that is not a DFA.
ALGORITHM:
Step1: Start the Program.
Step2: Enter the regular expression R over alphabet E.
Step3: Decompose the regular expression R into its primitive components
Step4: For each component construct finite automata.
Step5: To construct components for the basic regular expression way that corresponding to
that way compound regular expression.
Step6: Stop the Program
PROGRAM :
#include<stdio.h>
Compiler Design (KCS-552) (CS, V SEM)
Page 30
Raj Kumar Goel Institute of Technology, Ghaziabad
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& OUTPUT:
q0 0 q0
q0 1 q1
q0 e q1
q1 1 q2
q1 e q2
Epsilon closure of q0 = { q0 q1 q2 }
Epsilon closure of q1 = { q1 q2 }
Epsilon closure of q2 = { q2 }
EXPERIMENT #5
Aim: Write program to convert NFA with ε transition to NFA without ε transition.
PROGRAM CODE:
#include<stdio.h>
#include<stdlib.h>
struct node
{
int st;
struct node *link;
};
void findclosure(int,int);
void insert_trantbl(int ,char, int);
int findalpha(char);
void findfinalstate(void);
void unionclosure(int);
void print_e_closure(int);
static int set[20],nostate,noalpha,s,notransition,nofinal,start,finalstate[20],c,r,buffer[20];
char alphabet[20];
scanf("%d",&nostate);
printf("Enter the start state?\n");
scanf("%d",&start);
printf("Enter the number of final states?\n");
scanf("%d",&nofinal);
printf("Enter the final states?\n");
for(i=0;i<nofinal;i++)
scanf("%d",&finalstate[i]);
printf("Enter no of transition?\n");
scanf("%d",¬ransition);
printf("NOTE:- [Transition is in the form--> qno alphabet qno]\n",notransition);
printf("NOTE:- [States number must be greater than zero]\n");
printf("\nEnter transition?\n");
for(i=0;i<notransition;i++)
{
scanf("%d %c%d",&r,&c,&s);
insert_trantbl(r,c,s);
}
printf("\n");
for(i=1;i<=nostate;i++)
{
c=0;
for(j=0;j<20;j++)
{
buffer[j]=0;
e_closure[i][j]=0;
}
while(temp!=NULL)
unionclosure(temp->st);
temp=temp->link;
}
}
printf("\n");
print_e_closure(i);
printf("%c\t",alphabet[j] );
printf("{");
for(n=1;n<=nostate;n++)
{
if(set[n]!=0)
printf("q%d,",n);
}
printf("}");
}
}
printf("\n Final states:");
findfinalstate();
}
void findclosure(int x,int sta)
{
EXPERIMENT #6
Description:
Step1: q0=2^0=1 , q1=2^1=2, q2=2^2=4
Step2: Similarly union od states will be represented as:
q0q1=2^0+2^1=3, q1q2=2^1+2^2=6, q0q1q2=2^0+2^1+2^2=7
Step3: Do no give any condition for “phi”…….
That case is not handled…….(Coz I M LAZY:P)
Step4: Follow zero based indexing everywhere
Step5: Program assumes that if “Number of states are=n” then they are numbered as
q0,q1,q2,..q(n-1)
Step6: If you find any bug, message me and forgive me for the error.
Program :
#include<string.h>
#include<stdio.h>
#include<math.h>
int ninputs;
int dfa[100][2][100] = {0};
int state[10000] = {0};
char ch[10], str[1000];
int go[10000][2] = {0};
int arr[10000] = {0};
int main()
{
int st, fin, in;
int f[];
int i,j=3,s=0,final=0,flag=0,curr1,curr2,k,l;
int c;
for(i=0;i<st;i++)
state[(int)(pow(2,i))] = 1;
int p,q,r,rel;
in = pow(2,in);
i=0;
if(new==0)
new = go[h][j];
new = new | (go[h][j]);
}
}
if(state[new]==0)
{
arr[x++] = new;
state[new] = 1;
}
}
}
printf("STATE 0 1\n");
for(i=0;i<10000;i++)
{
if(state[i]==1)
for(i=0;i<l;i++)
{
curr1 = go[curr1][str[i]-'0'];
printf("%d-",curr1);
}
for(i=0;i<fin;i++)
{
if(curr1 & (1<<f[i]))
{
flag = 1;
EXPERIMENT #7
ALGORITHM:
Suppose there is a DFA D < Q, Σ, q0, δ, F > which recognizes a language L. Then the minimized DFA D
< Q’, Σ, q0, δ’, F’ > can be constructed for language L as:
Step 1: We will divide Q (set of states) into two sets. One set will contain all final states and other set
will contain non-final states. This partition is called P0.
Step 2: Initialize k = 1
Step 3: Find Pk by partitioning the different sets of Pk-1. In each set of Pk-1, we will take all possible pair
of states. If two states of a set are distinguishable, we will split the sets into different sets in P k.
Step 5: All states of one set are merged into one. No. of states in minimized DFA will be equal to no. of
sets in Pk.
PROGRAM :
#include <stdlib.h>
#include <string.h>
#include<stdio.h>
int **transitionMap; // 2D array which is used to store state transitions. transitionMap[i][j] is the state
reached when state i is given symbol j
int **partitionTransitionMap; // same as transitionMap, except row indices represent partition
numbers,
not state numbers
// If partitions differ, remove the other state and add it to the new partition. Then break, since we are
done with this partition
if (transitionMap[j][l] != transitionMap[k][l] && (staticNext != otherNext)){
P[i] &= ~(1 << k);
newPartition |= (1 << k);
break;
}
}
}
}
break;
}
}
// New partition exists. Add it to P and increment nextPartitionIndex
INPUT:
0
25
0a1
1b2
0b3
3a4
4b5
Compiler Design (KCS-552) (CS, V SEM)
Page 48
Raj Kumar Goel Institute of Technology, Ghaziabad
OUTPUT:
3
0
1b0
2a1
3a1
3b2
EXPERIMENT #8
Aim : Implementation of shift reduce parsing algorithm.
Description:
Shift-reduce parsing attempts to construct a parse tree for an input string beginning at the leaves and
working up towards the root. In other words, it is a process of “reducing” (opposite of deriving a
symbol using a production rule) a string w to the start symbol of a grammar.
ALGORITHM:
PROGRAM CODE:
#include<stdio.h>
#include<conio.h>
#include<string.h>
int k=0,z=0,i=0,j=0,c=0;
char a[16],ac[20],stk[15],act[10];
void check();
void main()
{
clrscr();
puts("GRAMMAR is E->E+E \n E->E*E \n E->(E) \n E->id");
puts("enter input string ");
gets(a);
c=strlen(a);
strcpy(act,"SHIFT->");
puts("stack \t input \t action");
for(k=0,i=0; j<c; k++,i++,j++)
{
if(a[j]=='i' && a[j+1]=='d')
{
stk[i]=a[j];
stk[i+1]=a[j+1];
stk[i+2]='\0';
a[j]=' ';
a[j+1]=' ';
printf("\n$%s\t%s$\t%sid",stk,a,act);
check();
}
else
{
stk[i]=a[j];
stk[i+1]='\0';
Compiler Design (KCS-552) (CS, V SEM)
Page 50
Raj Kumar Goel Institute of Technology, Ghaziabad
EXPERIMENT#9
Compiler Design (KCS-552) (CS, V SEM)
Page 52
Raj Kumar Goel Institute of Technology, Ghaziabad
Description:
First and Follow sets are needed so that the parser can properly apply the needed
production rule at the correct position.
PROGRAM CODE:
// C program to calculate the First and
// Follow sets of a given grammar
#include<stdio.h>
#include<ctype.h>
#include<string.h>
// Functions to calculate Follow
void followfirst(char, int, int);
void follow(char c);
// Function to calculate First
void findfirst(char, int, int);
int count, n = 0;
// Stores the final result
// of the First Sets
char calc_first[10][100];
// Stores the final result
// of the Follow Sets
char calc_follow[10][100];
int m = 0;
// Stores the production rules
char production[10][10];
char f[10], first[10];
int k;
char ck;
int e;
int main(int argc, char **argv)
{
int jm = 0;
int km = 0;
int i, choice;
char c, ch;
count = 8;
// The Input grammar
strcpy(production[0], "E=TR");
strcpy(production[1], "R=+TR");
strcpy(production[2], "R=#");
Compiler Design (KCS-552) (CS, V SEM)
Page 53
Raj Kumar Goel Institute of Technology, Ghaziabad
strcpy(production[3], "T=FY");
strcpy(production[4], "Y=*FY");
strcpy(production[5], "Y=#");
strcpy(production[6], "F=(E)");
strcpy(production[7], "F=i");
int kay;
char done[count];
int ptr = -1;
// Initializing the calc_first array
for(k = 0; k < count; k++) {
for(kay = 0; kay < 100; kay++) {
calc_first[k][kay] = '!';
}
}
int point1 = 0, point2, xxx;
for(k = 0; k < count; k++)
{
c = production[k][0];
point2 = 0;
xxx = 0;
// Checking if First of c has
// already been calculated
for(kay = 0; kay <= ptr; kay++)
if(c == done[kay])
xxx = 1;
if (xxx == 1)
continue;
// Function call
findfirst(c, 0, 0);
ptr += 1;
// Adding c to the calculated list
done[ptr] = c;
printf("\n First(%c) = { ", c);
calc_first[point1][point2++] = c;
// Printing the First Sets of the grammar
for(i = 0 + jm; i < n; i++) {
int lark = 0, chk = 0;
for(lark = 0; lark < point2; lark++) {
if (first[i] == calc_first[point1][lark])
{
chk = 1;
break;
}
}
if(chk == 0)
calc_follow[point1][point2++] = f[i];
}
}
printf(" }\n\n");
km = m;
point1++;
}
}
void follow(char c)
{
int i, j;
// Adding "$" to the follow
// set of the start symbol
if(production[0][0] == c) {
f[m++] = '$';
}
for(i = 0; i < 10; i++)
{
for(j = 2;j < 10; j++)
{
if(production[i][j] == c)
{
if(production[i][j+1] != '\0')
{
// Calculate the first of the next
// Non-Terminal in the production
followfirst(production[i][j+1], i, (j+2));
}
if(production[i][j+1]=='\0' && c!=production[i][0])
{
// Calculate the follow of the Non-Terminal
// in the L.H.S. of the production
follow(production[i][0]);
}
}
if(production[j][0] == c)
{
if(production[j][2] == '#')
{
if(production[q1][q2] == '\0')
first[n++] = '#';
else if(production[q1][q2] != '\0'
&& (q1 != 0 || q2 != 0))
{
// Recursion to calculate First of New
// Non-Terminal we encounter after epsilon
findfirst(production[q1][q2], q1, (q2+1));
}
else
first[n++] = '#';
}
else if(!isupper(production[j][2]))
{
first[n++] = production[j][2];
}
else
{
// Recursion to calculate First of
// New Non-Terminal we encounter
// at the beginning
findfirst(production[j][2], j, 3);
}
}
}
}
void followfirst(char c, int c1, int c2)
{
while(calc_first[i][j] != '!')
{
if(calc_first[i][j] != '#')
{
f[m++] = calc_first[i][j];
}
else
{
if(production[c1][c2] == '\0')
{
// Case where we reach the
// end of a production
follow(production[c1][0]);
}
else
{
// Recursion to the next symbol
// in case we encounter a "#"
followfirst(production[c1][c2], c1, c2+1);
}
}
j++;
}
}
}
INPUT:
Compiler Design (KCS-552) (CS, V SEM)
Page 58
Raj Kumar Goel Institute of Technology, Ghaziabad
E -> TR
R -> +T R| #
T -> F Y
Y -> *F Y | #
F -> (E) | i
OUTPUT:
First(E)= { (, i, }
First(R)= { +, #, }
First(T)= { (, i, }
First(Y)= { *, #, }
First(F)= { (, i, }
-----------------------------------------------
Follow(E) = { $, ), }
Follow(R) = { $, ), }
Follow(T) = { +, $, ), }
Follow(Y) = { +, $, ), }
Follow(F) = { *, +, $, ), }
EXPERIMENT #10
Description:
Recursive descent is a top-down parsing technique that constructs the parse tree from the top and the
input is read from left to right. It uses procedures for every terminal and non-terminal entity. This
parsing technique recursively parses the input to make a parse tree, which may or may not require
back-tracking. But the grammar associated with it (if not left factored) cannot avoid back- tracking.
A form of recursive-descent parsing that does not require any back-tracking is known as predictive
parsing.
Compiler Design (KCS-552) (CS, V SEM)
Page 60
Raj Kumar Goel Institute of Technology, Ghaziabad
ALGORITHM:
Step1:start.
Step2:DeclaretheprototypefunctionsE(),EP(),T(),TP(),F() Step3:
Readthestringtobe parsed.
Step 4: Check the productions
Step 5: Compare the terminals and Non-terminals
PROGRAM CODE:
#include "stdio.h"
#include "conio.h"
char input[100];
char prod[100][100];
int pos=-1,l,st=-1;
char id,num;
void E();
void T();
void F();
void advance();
void Td();
void Ed();
void advance()
{
pos++;
if(pos<l)
{
if(input[pos]>='0'&& input[pos]<='9')
{
num=input[pos];
id='\0';
}
if((input[pos]>='a' || input[pos]>='A')&&(input[pos]<='z' || input[pos]<='Z'))
{id=input[pos];
num='\0';
}
}
}
strcpy(prod[++st],"T->FT'");
F();
Td();
}
void Td()
{
int p=1;
if(input[pos]=='*')
{
p=0;
strcpy(prod[++st],"T'->*FT'");
advance();
F();
scanf("%s",input);
l=strlen(input);
input[l]='$';
advance();
E();
if(pos==l)
{
printf("String Accepted\n");
for(i=0;i<=st;i++)
INPUT:
E-> TE’
E’-> +TE’ | -TE’ | null
T-> FT’
T’-> *FT’| /FT’ | null
F-> id/ (E)/ num
OUTPUT:
EXPERIMENT #11
Aim: - Write a C program to implement operator precedence parsing
ALGORITHM:
Step 1: Push # onto stack
Step 2: Read first input symbol and push it onto stack
Step 3: Do
Obtain OP relation between the top terminal symbol on the stack and the next input symbol If
the OP relation is < or =
i. Pop top of the stack into handle, include non-terminalsymbol ifappropriate.
ii. Obtain the relation between the top terminal symbol on the stack and the leftmostterminal
symbol in the handle.
PROGRAM:
#include<stdio.h>
#include<conio.h>
void main(){
/*OPERATOR PRECEDENCE PARSER*/
char stack[20],ip[20],opt[10][10][1],ter[10];
int i,j,k,n,top=0,col,row;
clrscr();
for(i=0;i<10;i++)
{
for(i=0;i<n;i++)
{
printf("\t%c",ter[i]);
}
printf("\n");
for(i=0;i<n;i++){printf("\n%c",ter[i]);
for(j=0;j<n;j++){printf("\t%c",opt[i][j][0]);}}
stack[top]='$';
printf("\nSTACK\t\t\tINPUT STRING\t\t\tACTION\n");
printf("\n%s\t\t\t%s\t\t\t",stack,ip);
while(i<=strlen(ip))
{
for(k=0;k<n;k++)
{
if(stack[top]==ter[k])
col=k;
if(ip[i]==ter[k])
row=k;
}
if((stack[top]=='$')&&(ip[i]=='$')){
printf("String is accepted\n");
break;}
else if((opt[col][row][0]=='<') ||(opt[col][row][0]=='='))
{ stack[++top]=opt[col][row][0];
stack[++top]=ip[i];
printf("Shift %c",ip[i]);
i++;
}
else{
if(opt[col][row][0]=='>')
{
while(stack[top]!='<'){--top;}
top=top-1;
printf("Reduce");
}
else
Compiler Design (KCS-552) (CS, V SEM)
Page 67
Raj Kumar Goel Institute of Technology, Ghaziabad
$ i*i Shift i
$<i *i Reduce
$ *i Shift *
$<* i Shift i
$<*<i String is not accepted
EXPERIMENT #12
Aim: Write a program to perform loop unrolling.
Description:
Loop unrolling is a loop transformation technique that helps to optimize the execution time of a program. We
basically remove or reduce iterations. Loop unrolling increases the program’s speed by eliminating loop
control instruction and loop test instructions.
PREEXPERIMENT
Q1. Define loopunrolling
Q2. Give example of loop unrolling
ALGORITHM:
Step1: Start
Step2: Declare n
Step3: Enter n value
Step4: Loop rolling display countbit1 or move to next step 5
Step5: Loop unrolling display countbit2
Step6: End
PROGRAM:
Program 1:
Compiler Design (KCS-552) (CS, V SEM)
Page 70
Raj Kumar Goel Institute of Technology, Ghaziabad
int main(void)
{
for (int i=0; i<5; i++)
printf("Hello\n"); //print hello 5 times
return 0;
}
Program 2:
Output:
Hello
Hello
Hello
Hello
Hello
Illustration:
Program 2 is more efficient than program 1 because in program 1 there is a need to check the value of
i andincrement the value of i every time round the loop. So small loops like this or loops where there
is fixednumber of iterations are involved can be unrolled completely to reduce the loop overhead.
Compiler Design (KCS-552) (CS, V SEM)
Page 71
Raj Kumar Goel Institute of Technology, Ghaziabad
EXPERIMENT #13
Aim: Write a Program to implement Code Optimization Techniques (eg. Constant propagation etc)
Description:
The algorithm we shall present basically tries to find for every statement in the program a mapping
between variables, and values of N T ∪⊥ { , } . If a variable is mapped to a constant number, that
number is the variables value in that statement on every execution. If a variable is mapped to T (top),
its value in the statement is not known to be constant, and in the variable is mapped to ⊥ (bottom),
its value is not initialized on every execution, or the statement is unreachable. The algorithm for
assigning the mappings to the statements is an iterative algorithm, that traverses the control flow
graph of the algorithm, and updates each mapping according to the mapping of the previous
statement, and the functionality of the statement. The traversal is iterative, because non- trivial
programs have circles in their control flow graphs, and it ends when a “fixed-point” is reached – i.e.,
further iterations don’t change the mappings.
ALGORITHM:
Step1: Start
Step2: Create an input file which contains three address code
Step3: Open the file in read mode
Step4:If the file pointer returns NULL, exit the program else goto 5
PROGRAM:
#include<stdio.h>
#include<conio.h>
#include<string.h>
struct op{
char 1;
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 *temp;
clrscr();
printf(“Enter the no. of values”);
scanf(“%d”, &n);
for(i=0;i<n;i++)
{
printf(“\tleft\t”);
op[i].l=getche();
printf(“\tright:\t”);
scanf(“%s”,op[i].r);
}
printf(“intermediate code\n”);
for(i=0;i<n;i++)
Compiler Design (KCS-552) (CS, V SEM)
Page 73
Raj Kumar Goel Institute of Technology, Ghaziabad
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;}
}
}
}
}
Compiler Design (KCS-552) (CS, V SEM)
Page 74
Raj Kumar Goel Institute of Technology, Ghaziabad
OUTPUT:
left a right 9
left b right c+d
left e right c+d
left f right b+e
left r right f
intermediate code
a=9
b=c+d
Compiler Design (KCS-552) (CS, V SEM)
Page 75
Raj Kumar Goel Institute of Technology, Ghaziabad
EXPERIMENT #14
Program:
#include<stdio.h>
#include<conio.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 exp{
int pos;
char op;
}
k[15];
void main()
{
clrscr();
printf("\t\tINTERMEDIATE CODE GENERATION\n\n");
printf("Enter the Expression :");
scanf("%s",str);
printf("The intermediate code:\t\tExpression\n");
findopr();
explore();
getch();
}
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]=='*')
{
Output
EXPERIMENT # 15
Aim: 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=10;
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);
Compiler Design (KCS-552) (CS, V SEM)
Page 80
Raj Kumar Goel Institute of Technology, Ghaziabad
OUTPUT:
EXPERIMENT #16
Aim: Write a C program for constructing of LL (1) parsing.
Description:
An LL parser is a top-down parser for a subset of context-free languages. It parses the input from
Left to right, performing Leftmost derivationof the sentence. An LL parser is called an LL(k) parser
if it uses k tokens of look-ahead when parsing a sentence. If such a parser exists for a certain grammar
and it can parse sentences of this grammar without backtracking then it is called an LL(k) grammar.
LL(k) grammars can generate more languages the higher the number k of lookahead tokens.
ALGORITHM:
Step1: If A → α is a production choice, and there is a derivation α
⇒∗ aβ,where a is a token, then we add A → α to the table entry
M[A, a].
Step 2: If A → α is a production choice, and there are derivations α ⇒∗ ε
andS$ ⇒∗ βAaγ, where S is the start symbol and a is a token (or $), then we add A
→ α to the table entry M[A, a]
PROGRAM:
#include<stdio.h>
#include<conio.h>
#include<string.h>
char s[20],stack[20];
void main()
{
char m[5][6][3]={"tb"," "," ","tb"," "," "," ","+tb"," "," ","n","n","fc"," "," ","fc"," "," "," ","n","*fc"," a
","n","n","i"," "," ","(e)"," "," "};
int size[5][6]={2,0,0,2,0,0,0,3,0,0,1,1,2,0,0,2,0,0,0,1,3,0,1,1,1,0,0,3,0,0};
int i,j,k,n,str1,str2;
clrscr();
printf("\n Enter the input string: ");
scanf("%s",s);
strcat(s,"$");
n=strlen(s);
stack[0]='$';
stack[1]='e';
Compiler Design (KCS-552) (CS, V SEM)
Page 82
Raj Kumar Goel Institute of Technology, Ghaziabad
printf("\nStack Input\n");
printf("__________________\n");
while((stack[i]!='$')&&(s[j]!='$'))
{
if(stack[i]==s[j])
{
i--;
j++;
}
switch(stack[i])
{
case 'e': str1=0;
break;
case 'b': str1=1;
break;
case 't': str1=2;
break;
case 'c': str1=3;
break;
case 'f': str1=4;
break;
}
switch(s[j])
{
case 'i': str2=0;
break;
case '+': str2=1;
break;
case '*': str2=2;
break;
case '(': str2=3;
break;
case ')': str2=4;
break;
case '$': str2=5;
break;
}
if(m[str1][str2][0]=='\0')
{
printf("\nERROR");
exit(0);
}
else if(m[str1][str2][0]=='n')
Compiler Design (KCS-552) (CS, V SEM)
Page 83
Raj Kumar Goel Institute of Technology, Ghaziabad
{
stack[i]=m[str1][str2][k];
i++;
}
i--;
}
for(k=0;k<=i;k++)
printf(" %c",stack[k]);
printf(" ");
for(k=j;k<=n;k++)
printf("%c",s[k]);
printf(" \n ");
}
printf("\n SUCCESS");
getch();
}
$bcf i$
$bci i$
$bc $
$b $
$ $
sucess
Compiler Design (KCS-552) (CS, V SEM)
Page 84
Raj Kumar Goel Institute of Technology, Ghaziabad
EXPERIMENT #17
Description:
An LALR parser or Look-Ahead LR parser is a simplified version of a canonical LR parser, to parse
(separate and analyze) a text according to a set of production rules specified by a formal grammar
for a computer language. ("LR" means left-to-right, rightmost derivation.)
ALGORITHM:
STEP1:RepresentIibyitsCLOSURE,thoseitemsthatareeithertheinitialitem[S’🡪
do not have the . at the left end of the RHS
PROGRAM:
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<string.h>
void push(char *,int *,char);
char stacktop(char *);
void isproduct(char,char);
int ister(char);
int isnter(char);
int isstate(char);
void error();
void isreduce(char,char);
char pop(char *,int *);
void printt(char *,int *,char [],int);
void rep(char [],int);
Compiler Design (KCS-552) (CS, V SEM)
Page 85
Raj Kumar Goel Institute of Technology, Ghaziabad
{'F',"i"},
};
void main()
{
char inp[80],x,p,dl[80],y,bl='a';
int i=0,j,k,l,n,m,c,len;
clrscr();
printf(" Enter the input :");
scanf("%s",inp);
len=strlen(inp);
inp[len]='$';
inp[len+1]='\0';
push(stack,&top,bl);
printf("\n stack \t\t\t input");
printt(stack,&top,inp,i);
do
{
x=inp[i];
p=stacktop(stack);
isproduct(x,p);
if(strcmp(temp,"emp")==0)
error();
if(strcmp(temp,"acc")==0)
break;
else
Compiler Design (KCS-552) (CS, V SEM)
Page 87
Raj Kumar Goel Institute of Technology, Ghaziabad
}
}
}
printt(stack,&top,inp,i);
}while(inp[i]!='\0');
if(strcmp(temp,"acc")==0)
printf(" \n accept the input ");
else
printf(" \n do not accept the input ");
getch();
}
void push(char *s,int *sp,char item)
{
if(*sp==100)
printf(" stack is full ");
else
{
*sp=*sp+1;
Compiler Design (KCS-552) (CS, V SEM)
Page 88
Raj Kumar Goel Institute of Technology, Ghaziabad
strcpy(temp,A[l-1].row[k-1]);
}
int ister(char x)
{
int i;
for(i=0;i<6;i++)
if(x==ter[i])
return i+1;
return 0;
}
int isnter(char x)
{
int i;
for(i=0;i<3;i++)
if(x==nter[i])
return i+1;
return 0;
}
int isstate(char p)
{
int i;
for(i=0;i<12;i++)
if(p==states[i])
return i+1;
return 0;
}
void error()
{
printf(" error in the input ");
Compiler Design (KCS-552) (CS, V SEM)
Page 89
Raj Kumar Goel Institute of Technology, Ghaziabad
REFERENCES:
(1) Aho,Ullman,Sethi CompilerConstruction.
(2) AllenI.Holub CompilerConstruction.
APPENDIX-I:
4. Write program to find ε – closure of all states of any given NFA with ε transition.
13. Write a Program to implement Code Optimization Techniques (eg. Constant propagation etc)
14. Implement Intermediate code generation for simple expressions.
15. 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.
**********************