Compiler Design Lab Manual (2024-25) (23-Aug-2024)
Compiler Design Lab Manual (2024-25) (23-Aug-2024)
Compiler Design Lab Manual (2024-25) (23-Aug-2024)
LAB MANUAL
Session-2024-25
Prepared by:
Shruti Arya
Assistant Professor
Department of
AI&DS
1
Compiler Design Lab Manual
INDEX
PAGE
S.NO CONTENTS
NO.
1 MOTTO of JECRC 4
8 Software Used 11
10 Mapping of CO & PO 13
14 Experiments
Exp:-3 Objectives: -Count total no. of keywords in a file. [Taking file from 23-27
user]
Exp:-4 28-29
Objectives: - Count total no of operators in a file. [Taking file from user]
2
Compiler Design Lab Manual
Exp:-5 Objectives: - Count total occurrence of each character in a given file. 30-32
Objectives: - Write a lex program to count the no. of vowels and consonants 48-49
Exp:-9 in a C file.
Objectives: -Write a YACC program to recognize strings aaab, abbb using 50-52
Exp:-10
a^nb^n, where b>=0.
3
Compiler Design Lab Manual
MOTTO of JECRC
TEACH
TRAIN
&
TRANSFORM
For
4
Compiler Design Lab Manual
Mission:
Focus on evaluation of learning outcomes and motivate students to inculcate research
aptitude by project based learning.
Identify areas of focus and provide platform to gain knowledge and solutions based
on informed perception of Indian, regional and global needs.
Develop human potential to its fullest extent so that intellectually capable and
imaginatively gifted leaders can emerge in a range of professions.
5
Compiler Design Lab Manual
VISION
To prepare students in the field of Artificial Intelligence and Data Science for competing with the
global perspective through outcome based education, research and innovation.
MISSION
6
Compiler Design Lab Manual
1. To provide students with the fundamentals of Engineering Sciences with more emphasis in
Artificial Intelligence & Data Science by way of analyzing and exploiting engineering
challenges.
2. To train students with good scientific and engineering knowledge so as to
comprehend, analyze, design, and create novel products and solutions for the real life
problems.
3. To inculcate professional and ethical attitude, effective communication skills,
teamwork skills, multidisciplinary approach, entrepreneurial thinking and an ability to
relate engineering issues with social issues.
4. To provide students with an academic environment aware of excellence, leadership,
written ethical codes and guidelines, and the self-motivated life-long learning needed
for a successful professional career.
5. To prepare students to excel in Industry and Higher education by Educating Students
along with High moral values and Knowledge
7
Compiler Design Lab Manual
8
PSO of the Department:
PSO 1: Graduates of the program would be able to develop mobile and web based IT
solutions for real time problems.
PSO 2: Graduates of the program would be able to apply the concepts of artificial
intelligence, machine learning and deep learning.
9
Compiler Design Lab Manual
10
Compiler Design Lab Manual
11
Compiler Design Lab Manual
COURSE OUTCOMES
OBJECTIVE: This laboratory course is intended to make the students experiment on the
basic techniques of compiler construction and tools that can used to perform syntax-directed
translation of a high-level programming language into an executable code. Students will
design and implement language processors in C by using tools to automate parts of the
implementation process. This will provide deeper insights into the more advanced semantics
aspects of programming languages, code generation, machine independent optimizations,
dynamic memory allocation, and object orientation.
COURSE OUTCOMES
Graduates would be able:
CO1- Design Lexical analyzer for given language using C and LEX tools.
CO2- Design and convert BNF rules into YACC form to generate various parsers
12
Compiler Design Lab Manual
CO-1 3 3 3 2 3 1 1 2 2
CO-2 3 3 3 2 2 1 1 2 2
CO-3 3 2 2 2 2 1 1 1
CO-4 3 2 3 2 3 2 1 2 1
COURSE
OUTCOMES PSO
CO-1 1 1
CO-2 1 1
13
Compiler Design Lab Manual
INSTRUCTIONAL METHODS:
Direct Instructions:
Interactive Instruction:
I. Programs
Indirect Instructions:
I. Problem solving
LEARNING MATERIALS:
Text/Lab Manual
ASSESSMENT OF OUTCOMES:
INSTRUCTIONS OF LAB
DO’s
1. Please switch off the Mobile/Cell phone before entering Lab.
2. Enter the Lab with complete source code and data.
3. Check whether all peripheral are available at your desktop before proceeding for
program.
14
Compiler Design Lab Manual
4. Intimate the lab In charge whenever you are incompatible in using the system or
in case software get corrupted/ infected by virus.
5. Arrange all the peripheral and seats before leaving the lab.
6. Properly shutdown the system before leaving the lab.
7. Keep the bag outside in the racks.
8. Enter the lab on time and leave at proper time.
9. Maintain the decorum of the lab.
10. Utilize lab hours in the corresponding experiment.
11. Get your CD / Pen drive checked by lab In charge before using it in the lab.
DON’TS
1. No one is allowed to bring storage devices like Pan Drive /Floppy etc. in the
lab.
2. Don’t mishandle the system.
3. Don’t leave the system on standing for long
4. Don’t bring any external material in the lab.
5. Don’t make noise in the lab.
6. Don’t bring the mobile in the lab. If extremely necessary, then keep ringers off.
7. Don’t enter in the lab without permission of lab in charge.
8. Don’t litter in the lab.
9. Don’t delete or make any modification in system files.
10. Don’t carry any lab equipment’s outside the lab.
We need your full support and cooperation for smooth functioning of the
15
INSTRUCTIONS FOR STUDENT
All the students are supposed to prepare the theory regarding the next program.
Students are supposed to bring the practical file and the lab copy.
Previous programs should be written in the practical file.
Any student not following these instructions will be denied entry in the lab.
16
Introduction about Lab:
Compiler is a program that reads a program written in one language – the source language – and
translates it in to an equivalent program in another language – the target language. ANALYSIS-
SYNTHESIS MODEL OF COMPILATION There are two parts to compilation: Analysis and
Synthesis. The analysis part breaks up the source program into constituent pieces and creates an
intermediate representation of source program. The synthesis part constructs the desired target
program from the intermediate representation. Of the two parts, synthesis requires the most
specialize technique. PHASES OF A COMPILER A compiler operates in six phases, each of
which transforms the source program from one representation to another. The first three phases
are forming the bulk of analysis portion of a compiler. Two other activities, symbol table
management and error handling, are also interacting with the six phases of compiler. These six
phases are lexical analysis, syntax analysis, semantic analysis, intermediate code generation,
code optimization and code generation. LEXICAL ANALYSIS In compiler, lexical analysis is
also called linear analysis or scanning. In lexical analysis the stream of characters making up the
source program is read from left to right and grouped into tokens that are sequences of characters
having a collective meaning. SYNTAX ANALYSIS It is also called as Hierarchical analysis or
parsing. It involves grouping the tokens of the source program into grammatical phrases that are
used by the compiler to synthesize output. Usually, a parse tree represents the grammatical
phrases of the source program. SEMANTIC ANALYSIS The semantic analysis phase checks the
source program for semantic errors MKCE-DEPARTMERMATION TECHNOLOGY
A compiler or interpreter for a programming language is often decomposed into
two parts:
1. Read the source program and discover its structure.
2. Process this structure, e.g. to generate the target program.
Lex and Yacc can generate program fragments that solve the first task.
The task of discovering the source structure again is decomposed into subtasks:
1. Split the source file into tokens (Lex).
2. Find the hierarchical structure of the program (Yacc).
Lex - A Lexical Analyzer Generator
Lex is a program generator designed for lexical processing of character input
streams. It accepts a high-level, problem oriented specification for character string matching, and
produces a program in a general purpose language which recognizes
regular expressions. The regular expressions are specified by the user in the source specifications
given to Lex. The Lex written code recognizes these expressions in an input stream and
partitions the input stream into strings matching the expressions. At the boundaries between
strings program sections provided by the user are executed. The Lex source file associates the
regular expressions and the program fragments. As each expression appears in the input to the
program written by Lex, the corresponding fragment is executed.
Lex helps write programs whose control flow is directed by instances of regular
expressions in the input stream. It is well suited for editor-script type transformations and for
segmenting input in preparation for a parsing routine.
Lex source is a table of regular expressions and corresponding program fragments. The table is
translated to a program which reads an input stream, copying it to an output stream and
partitioning the input into strings which match the given expressions. As each such string is
17
recognized the corresponding program fragment is executed. The recognition of the expressions
is performed by a deterministic finite automaton generated by Lex. The program fragments
written by the user are executed in the order in which the corresponding regular expressions
occur in the input stream.
The lexical analysis programs written with Lex accept ambiguous specifications
and choose the longest match possible at each input point. If necessary, substantial look ahead is
performed on the input, but the input stream will be backed up to the end of the current partition,
so that the user has general freedom to manipulate it.
Lex can generate analyzers in either C or Ratfor, a language which can be
translated automatically to portable Fortran. It is available on the PDP-11 UNIX, Honeywell
GCOS, and IBM OS systems. This manual, however, will only discuss generating analyzers in C
on the UNIX system, which is the only supported form of Lex under UNIX Version 7. Lex is
designed to simplify interfacing with Yacc, for those with access to this compiler-compiler
system.
18
Experiment No.1
Aim: - Introduction: Objective, scope and outcome of the course.
Objective: The objective of this course is to explore the principles of compiler. To introduce the
major concept areas of language translation and compiler design.
To enrich the knowledge in various phases of compiler and its use, code optimization
techniques, machine code generation, and use of symbol table.
To extend the knowledge of parser by parsing LL parser and LR parser.
Scope: Experience working with really big data structure and complex interaction
between algorithms.
These scope rules need a more complicated organization of symbol table than a list of
associations between names and attributes. Tables are organized into stack and each
table contains the list of names and their associated attributes. When the declaration is
compiled then the table is searched for a name.
Scope is a source-code level concept, and a property of name bindings, particularly
variable or function name bindings—names in the source code are references to entities
in the program—and is part of the behavior of a compiler or interpreter of a language.
19
Experiment No. 2
Description: Keyword is a predefined or reserved word which is available in C++ library with
a fixed meaning and used to perform an internal operation. C++ Language supports more than 64
keywords. Every Keyword exists in lower case letters like auto, break, case, const, continue, int
etc.32 Keywords in C++ Language which is also available in the C language.
do if static while
Source Code:
#include<stdio.h>
#include<conio.h>
#include<string.h>
void main()
{
char keyword[32][10]={"auto","double","int","struct","break","else","long",
"switch","case","enum","register","typedef","char",
"extern","return","union","const","float","short",
"unsigned","continue","for","signed","void","default",
"goto","sizeof","voltile","do","if","static","while"} ;
char string[10];
int flag=0,i;
printf("enter any string:");
20
gets(string);
for(i=0;i<32;i++)
{
if(strcmp(string,keyword[i])==0)
{
flag=1;
}
}
if(flag==1)
printf("%s is a keyword",string);
else
}
Output:
Viva Questions:
21
Experiment No. 3
Aim: Write a C program to count total no. of keywords in a file. [Taking file from user]
Description: Keywords are reserved words which cannot be used as variable names in
program.
There are 32 keywords in the C programming language.
Compare the string with each keyword if the string is same then string is keyword.
Step 1: Taking a file from user.
Step 2: Check if the given string is a keyword or not.
Step 3: Count the total no. of keyword in given file.
Source Code:
/* write a c program to count total no of keyword in a file */
#include<stdio.h>
#include<conio.h>
#include<ctype.h>
#include<string.h>
void main()
{
Charkeyword[32][10]= {"int","char","double","short","register","void","extern","volatile",
"goto","if","else","while","do","for","break","default","switch","case",
"continue","static","float", "sizeof", "signed","unsigned","string","const",
"struct","union", "auto","enum","long","typedef",”Sizeof”};
int count=0, i;
char key[100];
FILE *fp=fopen("Program1.c","r");
while((fscanf(fp,"%s",key))!=EOF)
{
for(i=0;i<=32;i++)
{
if(strcmp(key, keyword[i])==0)
{
printf("\nkeyword is : %s",key);
count++;
}
}
22
}
printf("\n Total no. of keywords are : %d", count);
fclose(fp);
getch();
}
Output :-
keyword is : void
keyword is : char
keyword is : string
keyword is : string
keyword is : for
keyword is : if
keyword is : if
keyword is : else
Total no. of keywords are : 8
Viva Questions:
23
Experiment No.4
Aim: Write a program to count total no of operators in a file. [Taking file from user].
Tools / Software: Turbo C++ /Code Blocks
Description: An operator is a symbol that tells the compiler to perform specific mathematical
or logical functions. C language is rich in built-in operators and provides the following types of
operators −
Arithmetic Operators - Arithmetic operators are the symbols that represent arithmetic
math operations. Examples include + (addition operator), - (subtraction operator), *
(multiplication operator), and / (division operator).
Relational Operators- A relational operator is a programming language construct or
operator that tests or defines some kind of relation between two entities ..... In languages
such as C, relational operators return the integers 0 or 1, where 0 stands for false and any
non-zero value stands for true.
Logical Operators- A logical operator is a symbol or word used to connect two or more
expressions such that the value of the compound expression produced depends only on
that of the original expressions and on the meaning of the operator. Common logical
operators include AND, OR, and NOT.
Bitwise Operators - The Bitwise Operator in C is a type of operator that operates on bit
arrays, bit strings, and tweaking binary values with individual bits at the bit level. For
handling electronics and IoT-related operations, programmers use bitwise operators. It
can operate faster at a bit level
Assignment Operators - Assignment operators are used to assigning value to a variable.
The left side operand of the assignment operator is a variable and right side operand of
the assignment operator is a value. “=”: This is the simplest assignment operator. This
Operator is used to assign the value on the right to the variable on the left
24
Source Code:
/* write a c program to count total no of Operators in a file */
#include<stdio.h>
#include<conio.h>
#include<ctype.h>
#include<string.h>
int main()
{
char oprtr[20][10]={"=","-","+","/","&&","||","<<",">>","%","*","++","--","=="};
int count=0, i;
char op[100];
FILE *fp=fopen("counting.txt","r");
while((fscanf(fp,"%s",op))!=EOF)
{
for(i=0;i<=32;i++)
{
if(strcmp(op, oprtr[i])==0)
{
printf("\n Operator is : %s",op);
count++;
}
}
}
printf("\n Total no. of Operator are : %d", count);
fclose(fp);
return 0;
getch();
}
Output:
Operator is : * Operator is : ==
Operator is : = Operator is : ||
Operator is : = Operator is : ==
Operator is : == Operator is : ||
Operator is : = Operator is : ==
Operator is : = Operator is : ||
Operator is : = Operator is : ==
Operator is : = Operator is : =
Operator is : == Operator is : =
Operator is : || Operator is : =
Operator is : == Total no. of Operator are : 21
25
Viva Questions:
26
Experiment No. 5
Aim: Write a C Program to Count total occurrence of each character in a given file. [Taking file
from user]
Source Code:
1. #include <stdio.h>
2. #include <string.h>
3.
4. int main()
5. {
6. char string[100];
7. int c = 0, count[26] = {0}, x;
8.
9. printf("Enter a string\n");
10. gets(string);
11.11.
12. while (string[c] != '\0') {
13. /** Considering characters from 'a' to 'z' only and ignoring others. */
14.14.
15. if (string[c] >= 'a' && string[c] <= 'z') {
16. x = string[c] - 'a';
17. count[x]++;
18. }
19.
20. c++;
27
21. }
22.
23. for (c = 0; c < 26; c++)
24. printf("%c occurs %d times in the string.\n", c + 'a', count[c]);
25.
26. return 0;
27. }
Explanation of "count[string[c]-'a']++", suppose input string begins with 'a' so c is 0 initially and
string[0] = 'a' and string[0] - 'a' = 0 and we increment count[0] i.e. 'a' has occurred one time and
repeat this till the complete string is scanned.
Output:
28
`
Viva Questions:
29
Experiment No. 6
Aim: Write a C program to insert, delete and display the entries in Symbol Table.
SYMBOL TABLE
30
Source code:
1. #include<stdio.h>
2. #include<conio.h>
3. #include<alloc.h>
4. #include<string.h>
5. #include<stdlib.h>
6. #define NULL 0
7. int size=0;
8. void Insert();
9. void Display();
10. void Delete();
11. int Search(char lab[]);void Modify();
12. struct SymbTab
13. {
14. char label[10],symbol[10];
15. int addr;
16. struct SymbTab *next;};
17. struct SymbTab *first,*last;
18. void main()
19. {
20. int op,y;
21. char la[10];
22. clrscr();
23. do
24. {
25. printf(“\n\tSYMBOL TABLE IMPLEMENTATION\n”);
26. printf(“\n\t1.INSERT\n\t2.DISPLAY\n\t3.DELETE\n\t4.SEARCH\n\t5.MODIFY\n\t6.END\n”);
27. printf(“\n\tEnter your option : “);
28. scanf(“%d”,&op);
29. switch(op)
30. {
31. case 1:
32. Insert();
33. break;
34. case 2:
35. Display();
36. break;
37. case 3:
38. Delete();
39. break;
40. case 4:
41. printf(“\n\tEnter the label to be searched : “);
42. scanf(“%s”,la);
43. y=Search(la);
44. printf(“\n\tSearch Result:”);
45. if(y==1)
31
46. printf(“\n\tThe label is present in the symbol table\n”);
47. else
48. printf(“\n\tThe label is not present in the symbol table\n”);
49. break;
50. case 5:
51. Modify();
52. break;
53. case 6:
54. exit(0);
55. }
56. }while(op<6);
57. getch();
58. }
59. void Insert()
60. {
61. int n;
62. char l[10];
63. printf(“\n\tEnter the label : “);
64. scanf(“%s”,l);
65. n=Search(l);
66. if(n==1)
67. printf(“\n\tThe label exists already in the symbol table\n\tDuplicate can’t be inserted”);
68. else
69. {
70. struct SymbTab *p;
71. p=malloc(sizeof(struct SymbTab));
72. strcpy(p->label,l);
73. printf(“\n\tEnter the symbol : “);
74. scanf(“%s”,p->symbol);
75. printf(“\n\tEnter the address : “);
76. scanf(“%d”,&p->addr);
77. p->next=NULL;
78. if(size==0)
79. {
80. first=p;
81. last=p;
82. }
83. else
84. {
85. last->next=p;
86. last=p;
87. }
88. size++;
89. }
90. printf(“\n\tLabel inserted\n”);
91. }
92. void Display()
93. {
32
94. int i;
95. struct SymbTab *p;
96. p=first;
97. printf(“\n\tLABEL\t\tSYMBOL\t\tADDRESS\n”);
98. for(i=0;i<size;i++)
99. {
100. printf(“\t%s\t\t%s\t\t%d\n”,p->label,p->symbol,p->addr);
101. p=p->next;
102. }
103. }
104. int Search(char lab[])
105. {
106. int i,flag=0;
107. struct SymbTab *p;
108. p=first;
109. for(i=0;i<size;i++)
110. {
111. if(strcmp(p->label,lab)==0)
112. flag=1;
113. p=p->next;
114. }
115. return flag;
116. }
117. void Modify()
118. {
119. char l[10],nl[10];
120. int add,choice,i,s;
121. struct SymbTab *p;
122. p=first;
123. printf(“\n\tWhat do you want to modify?\n”);
124. printf(“\n\t1.Only the label\n\t2.Only the address\n\t3.Both the label and address\n”);
125. printf(“\tEnter your choice : “);
126. scanf(“%d”,&choice);
127. switch(choice)
128. {
129. case 1:
130. printf(“\n\tEnter the old label : “);
131. scanf(“%s”,l);
132. s=Search(l);
133. if(s==0)
134. printf(“\n\tLabel not found\n”);
135. else
136. {
137. printf(“\n\tEnter the new label : “);
138. scanf(“%s”,nl);
139. for(i=0;i<size;i++)
140. {
141. if(strcmp(p->label,l)==0)
33
142. strcpy(p->label,nl);
143. p=p->next;
144. }
145. printf(“\n\tAfter Modification:\n”);
146. Display();
147. }
148. break;
149. case 2:
150. printf(“\n\tEnter the label where the address is to be modified : “);
151. scanf(“%s”,l);
152. s=Search(l);
153. if(s==0)
154. printf(“\n\tLabel not found\n”);
155. else
156. {
157. printf(“\n\tEnter the new address : “);
158. scanf(“%d”,&add);
159. for(i=0;i<size;i++)
160. {
161. if(strcmp(p->label,l)==0)
162. p->addr=add;
163. p=p->next;
164. }
165. printf(“\n\tAfter Modification:\n”);
166. Display();
167. }
168. break;
169. case 3:
170. printf(“\n\tEnter the old label : “);
171. scanf(“%s”,l);
172. s=Search(l);
173. if(s==0)
174. printf(“\n\tLabel not found\n”);
175. else
176. {
177. printf(“\n\tEnter the new label : “);
178. scanf(“%s”,nl);
179. printf(“\n\tEnter the new address : “);
180. scanf(“%d”,&add);
181. for(i=0;i<size;i++)
182. {
183. if(strcmp(p->label,l)==0)
184. {
185. strcpy(p->label,nl);
186. p->addr=add;
187. }
188. p=p->next;
189. }
34
190. printf(“\n\tAfter Modification:\n”);
191. Display();
192. }
193. break;
194. }
195. }
196. void Delete()
197. {
198. int a;
199. char l[10];
200. struct SymbTab *p,*q;
201. p=first;
202. printf(“\n\tEnter the label to be deleted : “);
203. scanf(“%s”,l);
204. a=Search(l);
205. if(a==0)
206. printf(“\n\tLabel not found\n”);
207. else
208. {
209. if(strcmp(first->label,l)==0)
210. first=first->next;
211. else if(strcmp(last->label,l)==0)
212. {
213. q=p->next;
214. while(strcmp(q->label,l)!=0)
215. {
216. p=p->next;
217. q=q->next;
218. }
219. p->next=NULL;
220. last=p;
221. }
222. else
223. {
224. q=p->next;
225. while(strcmp(q->label,l)!=0)
226. {
227. p=p->next;
228. q=q->next;
229. }
230. p->next=q->next;
231. }
232. size–;
233. printf(“\n\tAfter Deletion:\n”);
234. Display();
235. }
236. }
35
Output:
Viva Questions:
36
Experiment No. 7
Source Code:
37
[1-9][0-9]{9} {printf("\nMobile Number Valid\n");}
.+ {printf("\nMobile Number Invalid\n");}
%%
// driver code
int main()
{
printf("\nEnter Mobile Number : ");
yylex();
printf("\n");
return 0;
}
Output:
Input: 7017175023
Output: Mobile Number Valid
Input: 0001112223
Output: Mobile Number Invalid
38
printf("Accepted");
else
printf("Not Accepted");
}
Output:
Input :
[email protected]
Output :
Valid
Input :
[email protected]
Output :
Not Valid
2. Valid url
%%
((http)|(ftp))s?:\/\/[a-zA-Z0-9]{2, }(\.[a-z]{2, })
+(\/[a-zA-Z0-9+=?]*)* {printf("\nURL Valid\n");}
.+ {printf("\nURL Invalid\n");}
%%
// driver program
void main()
{
printf("\nEnter URL : ");
yylex();
printf("\n");
}
Output:
39
Input: geeksforgeeks
Output: INVALID URL
Input: https://www.geeksforgeeks.org
Output: VALID URL
3. Valid identifier
%{
#include <stdio.h>
%
}
/ rule section % %
// regex for valid identifiers
^[a - z A - Z _][a - z A - Z 0 - 9 _] * printf("Valid Identifier");
// regex for invalid identifiers
^[^a - z A - Z _] printf("Invalid Identifier");
.;
%%
main()
{
yylex();
}
Output:
40
4. Valid date (dd/mm/yyyy)
%{
/* Definition section */
#include<stdio.h>
int i=0, yr=0, valid=0;
%}
/* Rule Section */
%%
([0-2][0-9]|[3][0-1])\/((0(1|3|5|7|8))|(10|12))
\/([1-2][0-9][0-9][-0-9]) {valid=1;}
([0-2][0-9]|30)\/((0(4|6|9))|11)
\/([1-2][0-9][0-9][0-9]) {valid=1;}
([0-1][0-9]|2[0-8])\/02
\/([1-2][0-9][0-9][0-9]) {valid=1;}
29\/02\/([1-2][0-9][0-9][0-9])
{ while(yytext[i]!='/')i++; i++;
while(yytext[i]!='/')i++;i++;
while(i<yyleng)yr=(10*yr)+(yytext[i++]-'0');
if(yr%4==0||(yr%100==0&&yr%400!=0))valid=1;}
%%
// driver code
main()
{
yyin=fopen("vpn.txt", "r");
yylex();
if(valid==1) printf("It is a valid date\n");
else printf("It is not a valid date\n");
}
int yywrap()
{
41
return 1;
}
Output:
Input: 02/05/2019
Output: It is a valid date
Input: 05/20/2019
Output: It is not a valid date
Viva Questions:
42
Experiment No.8
Aim: Write a lex program to count blank spaces, words, lines in a given file.
Source Code:
%{
#include<stdio.h>
int lc=0, sc=0, tc=0, ch=0; /*Global variables*/
%}
/*Rule Section*/
%%
\n lc++; //line counter
[ ] sc++; //space counter
\t tc++; //tab counter
. ch++; //characters counter
%%
main()
{
43
// The function that starts the analysis
yylex();
printf("\nNo. of lines=%d, lc);
printf("\nNo. of spaces=%d, sc);
printf("\nNo. of tabs=%d, tc);
printf("\nNo. of other characters=%d, ch);
}
Output:
Viva Questions:
44
Experiment No. 9
Aim: Write a lex program to count the no. of vowels and consonants in a C file.
Tools / Software: LEX/ Flex Tool.
Description: LEX
Source Code:-
%{
int vow_count=0;
int const_count =0;
%}
%%
[aeiouAEIOU] {vow_count++;}
45
[a-zA-Z] {const_count++;}
%%
main()
{
printf("Enter the string of vowels and consonents:");
yylex();
printf("The number of vowels are: %d\n",vow);
printf("The number of consonants are: %d\n",cons);
return 0;
}
Output:
$$ lex kk.l
$$ gcc kk.c -ll
$$ ./a.out
Enter the string of vowels and consonents
My name is Khan
The number of vowels are: 4
The number of consonants are: 8
Viva Questions:
46
Experiment No. 10
Aim: Write a YACC program to recognize strings aaab, abbb using a^nb^n, where b>=0.
Source Code:
%{
/* Definition section */
#include "y.tab.h"
%}
/* Rule Section */
%%
[aA] {return A;}
[bB] {return B;}
\n {return NL;}
. {return yytext[0];}
%%
int yywrap()
{
return 1;
}
Parser Source Code :
47
%{
/* Definition section */
#include<stdio.h>
#include<stdlib.h>
%}
%token A B NL
/* Rule Section */
%%
stmt: S NL { printf("valid string\n");
exit(0); }
;
S: A S B |
;
%%
int yyerror(char *msg)
{
printf("invalid string\n");
exit(0);
}
//driver code
main()
{
printf("enter the string\n");
yyparse();
}
48
Output:
Viva Questions:
49
Experiment No. 11
YACC program also consists of three sections, "Definitions", "Context Free Grammar
and action for each production", "Subroutines/Functions".
In first section, we can mention C language code which may consist of header
files inclusion, global variables/ Constants definition/declaration. C language code can be
mentioned in between the symbols %{ and %}. Also we can define tokens in the first
section. In above program, NUMBER is the token. We can define the associativity of the
operations (i.e. left associativity or right associativity). In above yacc program, we have
specified left associativity for all operators. Priorities among the operators can also be
specified. It is in the increasing order "from top to bottom". For e.g. in our above yacc
program, round brackets '(',')' has the higher priority than '*', '/', '%' which has higher
priority than '+', '-'. Operators in the same statement have the same priority. For e.g. in
our above program all of the '*', '/', '%' have the same priority.
In second section, we mention the grammar productions and the action for each
production. $$ refer to the top of the stack position while $1 for the first value, $2 for the
second value in the stack.
Third section consists of the subroutines. We have to call yyparse() to initiate the
parsing process. yyerror() function is called when all productions in the grammar in
second section do not match to the input statement.
50
Source Code:
%
{
/* Definition section*/
#include "y.tab.h"
extern yylval;
%
}
%%
[0 - 9]
+
{
yylval = atoi(yytext);
return NUMBER;
}
[a - zA - Z] + { return ID; }
[\t] + ;
\n { return 0; }
. { return yytext[0]; }
%%
Parser Source Code:
%{
/* Definition section */
#include
%
}
% token NUMBER ID
// setting the precedence
// and associativity of operators
51
% left '+' '-'
% left '*' '/'
/* Rule Section */
%
%E:T
{
printf("Result = %d\n", $$);
return 0;
}
T : T '+' T { $$ = $1 + $3; }
| T '-' T { $$ = $1 - $3; }
| T '*' T { $$ = $1 * $3; }
| T '/' T { $$ = $1 / $3; }
| '-' NUMBER { $$ = -$2; }
| '-' ID { $$ = -$2; }
| '(' T ')' { $$ = $2; }
| NUMBER { $$ = $1; }
| ID { $$ = $1; };
%%
int main()
{
printf("Enter the expression\n");
yyparse();
}
/* For printing error messages */
int yyerror(char* s)
{
printf("\nExpression is invalid\n");
}
52
Output:
Viva Questions:
53
Experiment No. 12
Aim: Write a YACC program to recognize string with grammar a^n b^n, n>=0
Tools / Software: YACC Tool.
Description: Yacc (for “yet another compiler compiler.”) is the standard parser generator for
the Unix operating system. An open source program, yacc generates code for the parser
in the C programming language. The acronym is usually rendered in lowercase but is
occasionally seen as YACC or Yacc.
Grammars are used to describe the syntax of a programming language. It specifies the
structure of expression and statements.
stmt -> if (expr) then stmt
Source Code:
YACC PART:
CODE: (gram.y)
%{
#include<stdio.h>
#include<stdlib.h>
%}
%token A B NL
%%
stmt: S NL {printf("valid string\n");
exit(0);}
;
S: A S B |
;
%%
int yyerror(char *msg)
54
{
printf("invalid string\n");
exit(0);
}
main()
{
printf("enter the string\n");
yyparse();
}
LEX PART:
CODE: (gram.l)
%{
#include "y.tab.h"
%}
%%
[aA] {return A;}
[bB] {return B;}
\n {return NL;}
. {return yytext[0];}
%%
OUTPUT :
yacc -d gram.y
lex gram.l
cc y.tab.c lex.yy.c -ly -ll
./a.out
enter the string
ab
valid string
55
./a.out
enter the string
aaabb
invalid string
./a.out
enter the string
aabb
valid string
./a.out
enter the string
a
invalid string
Viva Questions:
56
Experiment No. 13
The functions follow and followfirst are both involved in the calculation of the Follow Set of a
given Non-Terminal. The follow set of the start symbol will always contain “$”. Now the
calculation of Follow falls under three broad cases :
57
Explanation:
Store the grammar on a 2D character array production. findfirst function is for calculating the
first of any non terminal. Calculation of first falls under two broad cases :
If the first symbol in the R.H.S of the production is a Terminal then it can directly be
included in the first set.
If the first symbol in the R.H.S of the production is a Non-Terminal then call the findfirst
function again on that Non-Terminal. To handle these cases like Recursion is the best
possible solution. Here again, if the First of the new Non-Terminal contains an epsilon then
we have to move to the next symbol of the original production which can again be a
Terminal or a Non-Terminal.
Note : For the second case it is very easy to fall prey to an INFINITE LOOP even if the code
looks perfect. So it is important to keep track of all the function calls at all times and never call
the same function again.
Below is the implementation :
Source Code:-
#include<stdio.h>
#include<ctype.h>
#include<string.h>
58
int count, n = 0;
char calc_first[10][100];
char calc_follow[10][100];
int m = 0;
char production[10][10];
int k;
char ck;
int e;
int jm = 0;
int km = 0;
int i, choice;
char c, ch;
59
count = 8;
strcpy(production[0], "E=TR");
strcpy(production[1], "R=+TR");
strcpy(production[2], "R=#");
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];
calc_first[k][kay] = '!';
60
{
c = production[k][0];
point2 = 0;
xxx = 0;
if(c == done[kay])
xxx = 1;
if (xxx == 1)
continue;
// Function call
findfirst(c, 0, 0);
ptr += 1;
done[ptr] = c;
calc_first[point1][point2++] = c;
61
for(lark = 0; lark < point2; lark++) {
if (first[i] == calc_first[point1][lark])
chk = 1;
break;
if(chk == 0)
calc_first[point1][point2++] = first[i];
printf("}\n");
jm = n;
point1++;
printf("\n");
printf(" \n\n");
char donee[count];
ptr = -1;
62
// Initializing the calc_follow array
calc_follow[k][kay] = '!';
point1 = 0;
int land = 0;
ck = production[e][0];
point2 = 0;
xxx = 0;
// Checking if Follow of ck
if(ck == donee[kay])
xxx = 1;
if (xxx == 1)
continue;
63
land += 1;
// Function call
follow(ck);
ptr += 1;
donee[ptr] = ck;
calc_follow[point1][point2++] = ck;
if (f[i] == calc_follow[point1][lark])
chk = 1;
break;
if(chk == 0)
64
printf("%c, ", f[i]);
calc_follow[point1][point2++] = f[i];
printf(" }\n\n");
km = m;
point1++;
void follow(char c)
int i, j;
if(production[0][0] == c) {
f[m++] = '$';
65
if(production[i][j] == c)
if(production[i][j+1] != '\0')
followfirst(production[i][j+1], i, (j+2));
follow(production[i][0]);
int j;
66
// The case where we
// encounter a Terminal
if(!(isupper(c))) {
first[n++] = c;
if(production[j][0] == c)
if(production[j][2] == '#')
if(production[q1][q2] == '\0')
first[n++] = '#';
else
67
first[n++] = '#';
else if(!isupper(production[j][2]))
first[n++] = production[j][2];
else
// at the beginning
findfirst(production[j][2], j, 3);
int k;
// a Terminal
68
if(!(isupper(c)))
f[m++] = c;
else
int i = 0, j = 1;
if(calc_first[i][0] == c)
break;
while(calc_first[i][j] != '!')
if(calc_first[i][j] != '#')
f[m++] = calc_first[i][j];
else
69
if(production[c1][c2] == '\0')
// end of a production
follow(production[c1][0]);
else
j++;
70
Output:
First(E)= { (, i, }
First(R)= { +, #, }
First(T)= { (, i, }
First(Y)= { *, #, }
First(F)= { (, i, }
Follow(E) = { $, ), }
Follow(R) = { $, ), }
Follow(T) = { +, $, ), }
Follow(Y) = { +, $, ), }
Follow(F) = { *, +, $, ), }
Viva Questions:
71
Reference
V.V Das, Compiler Design using FLEX and YACC, PHI
BOOKS:
Text books:
Reference Books:
72