Compiler Design Lab Manual
Compiler Design Lab Manual
Register No:
2
DO’S DON’T’S
1. Be regular to the lab. 1. Do not take leave on lab days.
2. Follow proper dress code. 2. Don’ts 1. Do not eat or drink in
3. Know the location of the fire the laboratory.
extinguisher and the first aid box and how 3. Avoid stepping on electrical
to use them in case of an emergency. wires or any other computer
cables.
4. Read and understand how to carry out an
4. Do not open the system unit casing
activity thoroughly before coming to the
or monitor casing particularly
laboratory.
when the power is turned on.
5. Report fires or accidents to your Some internal components hold
lecturer/laboratory technician immediately. electric voltages of up to 30000
6. Report any broken plugs or exposed volts, which can be fatal.
electrical wires to your lecturer/laboratory 5. Do not insert metal objects such as
technician immediately. clips, pins and needles into the
7. Maintain Silence. computer casings. They may cause
fire.
6. Do not remove anything from the
computer laboratory without
permission.
7. Do not touch, connect or disconnect
any plug or cable without your
lecturer/laboratory technician’s
permission.
3
Vision of the Institute Mission of the Institute
Empowering the rural and less privileged IM 1. To enlighten the rural students.
students with value based technical IM 2. To provide quality technical
knowledge, forming them as responsible education of societal development and
citizens. entrepreneurship
IM 3. To instill interpersonal skills and
shape the students to become good
leaders to serve the society.
4
Program Outcomes (POs)
Engineering Graduates will be able to:
1. Engineering knowledge: Apply the knowledge of mathematics, science,
engineering fundamentals and an engineering specialization to the solution of
complex engineering problems.
2. Problem analysis: Identify, formulate, review research literature, and analyze
complex engineering problems reaching substantiated conclusions using first
principles of mathematics, natural sciences, and engineering sciences.
3. Design/development of solutions: Design solutions for complex engineering
problems and design system components or processes that meet the specified
needswith appropriate consideration for the public health and safety, and the
cultural, societal, and environmental considerations.
4. Conduct investigations of complex problems: Use research-based
knowledge and research methods including design of experiments, analysis
and interpretation of data, and synthesis of the information to provide valid
conclusions.
5. Modern tool usage: Create, select, and apply appropriate techniques,
resources, and modern engineering and IT tools including prediction and
modeling to complex engineering activities with an understanding of the
limitations.
6. The engineer and society: Apply reasoning informed by the contextual
knowledge to assess societal, health, safety, legal and cultural issues and the
consequent responsibilities relevant to the professional engineering practice.
7. Environment and sustainability: Understand the impact of the
professional engineering solutions in societal and environmental contexts, and
demonstrate the knowledge of, and need for sustainable development.
8. Ethics: Apply ethical principles and commit to professional ethics and
responsibilities and norms of the engineering practice.
9. Individual and team work: Function effectively as an individual, and as a
member or leader in diverse teams, and in multidisciplinary settings.
10. Communication: Communicate effectively on complex engineering activities
with the engineering community and with society at large, such as, being able
to comprehend and write effective reports and design documentation, make
effective presentations, and give and receive clear instructions.
11. 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 multidisciplinary environments.
5
12. 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 technological change.
6
TABLE OF CONTENTS
AIM:
INTRODUCTION:
TOKEN
ALGORITHM:
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
if (isKeyword(subStr) == true)
printf("'%s' IS A KEYWORD\n", subStr);
int main()
{
char str[100] = "int a = b + 1c; ";
parse(str);
return (0);
}
OUTPUT
‘int’ is a keyword
‘a’ is a valid identifier
‘=’ is a operator
‘b’ is a avalid identifier
‘+’ is a operator
RESULT:Thus the above program for developing the lexical the lexical analyzer and recognizing the few
pattern s in C is executed successfully and the output is verified.
EX.NO:2
DATE:
INTRODUCTION:
THEORY:
LEX SOURCE:
ALGORITHM:
#include<stdio.h>
#include<ctype.h>
#include<conio.h>
#include<string.h> char
vars[100][100]; int vcnt;
char input[1000],c; char
token[50],tlen;
int state=0,pos=0,i=0,id; char
*getAddress(char str[])
{
for(i=0;i<vcnt;i++) if(strcmp(str,vars[i])==0)
return vars[i];
strcpy(vars[vcnt],str); return
vars[vcnt++];
}
int isrelop(char c)
{
if(c=='+'||c=='-'||c=='*'||c=='/'||c=='%'||c=='^') return 1;
else return 0;
}
int main(void)
{
clrscr();
printf("Enter the Input String:"); gets(input);
do
{
c=input[pos]; putchar(c);
switch(state)
{
case 0: if(isspace(c)) printf("\
b"); if(isalpha(c))
{
token[0]=c;
tlen=1; state=1;
}
if(isdigit(c)) state=2;
if(isrelop(c)) state=3;
if(c==';')
printf("\t<3,3>\n");
if(c=='=')
printf("\t<4,4>\n"); break;
case 1:
if(!isalnum(c))
{
token[tlen]='\o'; printf("\b\t<1,%p>\n",getAddress(token));
state=0;
pos--;
}
else token[tlen++]=c;
break;
case 2: if(!isdigit(c))
{
printf("\b\t<2,%p>\n",&input[pos]); state=0;
pos--;
}
break; case
3:
id=input[pos-1]; if(c=='=')
printf("\t<%d,%d>\n",id*10,id*10); else{
printf("\b\t<%d,%d>\n",id,id);
pos--;
}state=0; break;
}
pos++;
}
while(c!=0);
getch(); return 0;
}
OUTPUT:
Enter the string:a+b*c
a <1,08CE>
+ <43,43>
b <1,0432>
*<423,42>
c<1,0996>
RESULT:Thus the program for the exercise on lexical analysis using lex has been successfully executed
and output is verified.
EX.NO:3
DATE:
AIM :
To write a c program to do exercise on syntax analysis using YACC.
INTRODUCTION :
YACC (yet another compiler) is a program designed to produce designed to compile a
LALR (1) grammar and to produce the source code of the synthetically analyses of the
language produced by the grammar.
ALGORITHM :
1. Start the program.
2. Write the code for parser. l in the declaration port.
3. Write the code for the ‘y’ parser.
4. Also write the code for different arithmetical operations.
5. Write additional code to print the result of computation.
6. Execute and verify it.
7. Stop the program.
PROGRAM TO RECOGNIZE A VALID ARITHMETIC EXPRESSION THAT USES OPERATOR +, - , * AND /.
PROGRAM:
#include<stdio.h>
#include<conio.h>
void main()
{
char s[5];
clrscr();
printf("\n Enter any operator:"); gets(s);
switch(s[0])
{
case'>':
if(s[1]=='=')
printf("\n Greater than or equal"); else
printf("\n Greater than");
break;
case'<':
if(s[1]=='=')
printf("\n Less than or equal"); else
printf("\nLess than"); break;
case'=':
if(s[1]=='=')
printf("\nEqual to");
else printf("\nAssignment");
break;
case'!':
if(s[1]=='=')
printf("\nNot Equal");
else
printf("\n Bit Not");
break;
case'&': if(s[1]=='&')
printf("\nLogical AND"); else
printf("\n Bitwise AND");
break;
case'|': if(s[1]=='|')
printf("\nLogical OR"); else
printf("\nBitwise OR");
break;
case'+': printf("\n Addition");
break;
case'-': printf("\nSubstraction");
break;
case'*': printf("\nMultiplication");
break;
case'/': printf("\nDivision");
break;
case'%': printf("Modulus");
break;
default: printf("\n Not a operator");
}
getch();
}
OUTPUT
Multiplication
RESULT:Thus the program for the exercise on the syntax using YACC has been executed
successfully and Output is verified.
b)IMPLEMENTATION OF CALCULATOR USING LEX AND YACC
PROGRAM:
%{
#include<stdio.h> int
op=0,i;
float a,b;
%}
dig[0-9]+|([0-9]*)"."([0-9]+)
add "+"
sub "-"
mul"*"
div "/"
pow "^"
ln \n
%%
{dig}{digi();}
{add}{op=1;}
{sub}{op=2;}
{mul}{op=3;}
{div}{op=4;}
{pow}{op=5;}
%%
digi()
if(op==0) a=atof(yytext);
else
b=atof(yytext); switch(op)
case 1:
a=a+b;
break;
case 2:
a=a-b;
break;
case 3:
a=a*b;
break;
case 4:
a=a/b;
break;
case 5:
for(i=a;b>1;b--)
a=a*i;
break;
op=0;
yylex();
yywrap()
{
return 1;
OUTPUT:
Lex cal.1
Cc lex.yy.c-11
a.out
4*8
The result=32
RESULT:
Thus the program for the exercise on the syntax using YACC has been executed
Successfully and Output is verified.
EX.NO:4
DATE:
Generate three address code for simple program using LEX and YACC
AIM:
INTRODUCTION:
ALGORITHM:
Step1: Begin the program
Step2 : The expression is read from the file using a file pointer
Step3 : Each string is read and the total no. of strings in the file is calculated.
Step4: Each string is compared with an operator; if any operator is seen then the previous string and next
string are concatenated and stored in a first temporary value and the three address code expression is
printed
Step5 : Suppose if another operand is seen then the first temporary value is concatenated to the next
string using the operator and the expression is printed.
Step6 : The final temporary value is replaced to the left operand value.
Step7 : End the program.
PROGRAM:
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<string.h>
struct three
{
char data[10],temp[7];
}s[30];
void main()
{
char d1[7],d2[7]="t";
int i=0,j=1,len=0;
FILE *f1,*f2;
clrscr();
f1=fopen("sum.txt","r");
f2=fopen("out.txt","w");
while(fscanf(f1,"%s",s[len].data)!=EOF)
len++;
itoa(j,d1,7);
strcat(d2,d1);
strcpy(s[j].temp,d2);
strcpy(d1,"");
strcpy(d2,"t");
if(!strcmp(s[3].data,"+"))
{
fprintf(f2,"%s=%s+%s",s[j].temp,s[i+2].data,s[i+4].data);
j++;
}
else if(!strcmp(s[3].data,"-"))
{
fprintf(f2,"%s=%s-%s",s[j].temp,s[i+2].data,s[i+4].data);
j++;
}
for(i=4;i<len-2;i+=2)
{
itoa(j,d1,7);
strcat(d2,d1);
strcpy(s[j].temp,d2);
if(!strcmp(s[i+1].data,"+"))
fprintf(f2,"\n%s=%s+%s",s[j].temp,s[j-1].temp,s[i+2].data);
else if(!strcmp(s[i+1].data,"-"))
fprintf(f2,"\n%s=%s-%s",s[j].temp,s[j-1].temp,s[i+2].data);
strcpy(d1,"");
strcpy(d2,"t");
j++;
}
fprintf(f2,"\n%s=%s",s[0].data,s[j-1].temp);
fclose(f1);
fclose(f2);
getch();
}
Input: sum.txt
Out. tex E
T1 = int 1+int 2
T2=t1=int3
T3=t2-int4
Out=t3
RESULT:
Thus a C program to generate a three address code for a given expression is written,
executed and the output is verified.
EX.NO:5
DATE:
IMPLEMENTATION OF TYPE CHECKING USING Lex and YACC
AIM:
To write a C program for implementing type checking for given expression.
INTRODUCTION:
The type analysis and type checking is an important activity done in the semantic
analysis phase. The need for type checking is
To detect the errors arising in the expression due to incompatible operand.
To generate intermediate code for expressions due to incompatible operand
ALGORITHM:
1. Start a program.
2. Include all the header files.
3. Initialize all the functions and variables.
4. Get the expression from the user and separate into the tokens.
5. After separation, specify the identifiers, operators and number.
6. Print the output.
7. Stop the program.
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
#include
<ctype.h>
// Token
types enum
TokenType {
IDENT
IFIER,
OPERA
TOR,
NUMB
ER
};
// Token
structure
struct Token
{
enum TokenType
type; char
value[50];
};
if (isdigit(token[0])) {
newToken.type =
NUMBER;
} else if (strchr("+-*/()",
token[0])) { newToken.type
= OPERATOR;
} else {
newToken.type = IDENTIFIER;
}
strcpy(newToken.value,
token); tokens[*tokenCount]
= newToken; (*tokenCount)
++;
int main() {
char expression[100];
printf("Enter an arithmetic
expression: "); scanf("%[^\n]",
expression);
struct Token
tokens[50]; int
tokenCount = 0;
tokenizeExpression(expression, tokens,
n");
for (int i = 0; i < tokenCount; i++) {
printf("Token type: %d, Value: %s\n", tokens[i].type, tokens[i].value);
}
return 0;
}
OUTPUT:
RESULT:
Thus the program has been executed successfully and Output is verified
EX.NO:6
DATE:
INTRODUCTION:
The output code must not, in any way, change the meaning of the program.
Optimization should increases the speed of the program and if possible, the program
should demand less number of resources.
Optimization should itself be fast and fast and should not delay the overall compiling
process.
Efforts for an optimized code can be made at various levels of compiling the process.
At the beginning, users can change/rearrange the code or use better algorithms to write
the code.
After generating intermediate code, the compiler can modify the intermediate code by
address calculations and improving loops.
While producing the target machine code, the compiler can make use of memory
hierarchy and cpu registers.
Optimization can be categorized broadly into two types: Machine independent and
Machine dependent.
In this optimization, the compiler takes in the intermediate code and transforms a part
of the code that does not involve any CPU registers and/or absolute memory locations.
For Example:
do
item=10;
value=value+item;
}while(value<100);
This code involves repeated assignment of the identifier item, which if we put this way:
item=10;
do {
value=value+item;
}while(value<100);
Should not only save the cpu cycles, but can be used on any processor.
Machine dependent optimization is done after the target code has been generated and
when the code is transformed according to the target machine architecture. It involves CPU
registers and may have absolute memory references rather than relative references.
Machine- dependent optimizers put efforts to take maximum advantage of memory hierarchy.
ALGORITHM:
int main() {
int n = 10000;
int result = sum_of_natural_numbers_basic(n);
printf("Sum of first %d natural numbers: %d\n", n, result);
return 0;
PROGRAM:
Optimization Technique: Loop Unrolling in C:
Algorithm:
1. Initialize the variable sum to store the sum of natural numbers and i to keep track of
the current number.
2. Run a loop while i is less than or equal to n - 5. In each iteration, add i,
i+1, i+2, i+3, and i+4 to the sum variable. Increment i by 5 in each iteration.
3. After the first loop, if there are remaining numbers (less than 5) to add, use a
second loop to add them individually.
4. Return the final sum value as the result.
Program:
#include <stdio.h>
int sum_of_natural_numbers_optimized(int n) {
int sum = 0;
int i = 1;
while (i <= n - 5) {
sum += i + (i+1) + (i+2) + (i+3) + (i+4);
i += 5;
}
while (i <= n) {
sum += i; i+
+;
}
return sum;
}
int main() {
int n = 10000;
int result = sum_of_natural_numbers_optimized(n);
printf("Sum of first %d natural numbers (optimized): %d\n", n, result);
return 0;
OUTPUT
Implement the back end of the compiler which takes the three address code and produces
the 8086nassembly language instructions that can be assembled and run using a 8086
assembler. The target assembly instructions can be simple move , add, sub, jump. Also
simple addressing modes are used.
AIM:
ALGORITHM:
PROGRAM:
#include
<stdio.h>
#include
<string.h>
int main() {
// Sample three-address code instructions
generateAssembly("MOVE", "10", "", "var1");
generateAssembly("MOVE", "20", "", "var2");
generateAssembly("ADD", "var1", "var2", "result");
generateAssembly("SUB", "result", "var1", "final_result");
return 0;
}
OUTPUT
MOV AX,10
MOV VAR1,AX
MOV AX,20
MOV VAR2,AX
MOV AX,VAR1
MOV AX,VAR2
ADD AX,VAR2
MOV result,AX
MOV AX,result
SBB AX,VAR1
MOV final -result ,AX
RESULT:
Thus the above program is compiled and executed successfully and output is verified.
EX.NO:8
DATE:
INTRODUCTION:
Data flow analysis is a technique for gathering information about the possible set of value
calculated at various points in a computer program.
Control flow analysis can be represent by basic blocks. It depicts how th program control is
being passed among the blocks.
ALGORITHM:
#include<conio.h>
struct stack
{
int no;
struct stack *next;
}
*start=null
typedef struct stack st; voidpush();
int pop(); voiddisplay();
voidmain()
{
char ch;
int choice, item; do
{
clrscr();
printf(“\n1:push”);
printf(“\n2:pop”); printf(“\n3:display”);
printf(“\n enter your choice”);
scanf(“%d”,&choice); switch(choice)
{
case1:push(); break;
case2:item=pop();
printf(“the delete element in %d”,item);
break; case3:display();
break;
default:printf(“\nwrong choice”);
};
printf(“\n do you want to continue(y/n”);
fflush(stdin);
scanf(“%c”,&ch);
}
while(ch==’y’||ch==’y’);
}
voidpush()
{
st*node; node=(st*)malloc(sizeof(st));
printf(“\n enter the number to be insert”);
scanf(“%d”,&node->no);
node->next=start;
start=node;
}
intpop();
{
st*temp; temp=start;
if(start==null)
{
printf(“stack is already empty”);
getch();
exit();
}
else
{
start=start->next;
free(temp);
}
return(temp->no);
}
void display()
{
st*temp;
temp=start;
while(temp->next!=null)
{
printf(“\nno=%d”,temp->no);
temp=temp->next;
}
printf(“\nno=%d”,temp->no);
}
OUTPUT
1.POP
2.PUSH
3.DISPLAY
Enter your choice 2
The delete the element is 20
Do you want to continue (y/n)
1.POP
2.PUSH
3.DISPLAY
Enter your choice 3
N=20 n=10
Do you want to continue (y/n)
1.POP
2.PUSH
3.DISPLAY
Enter your choice 2
The insert the element is 20
Do you want to continue (y/n)
RESULT:
Thus the C program to implement data flow and control flow analysis was executed successfully.
EX.NO:9
DATE:
IMPLEMENT ANY ONE STORAGE ALLOCATION
STRATEGIES (HEAP,STACK,STATIC)
AIM:
To write a C program for Stack to use dynamic storage allocation.
INTRODUCTION:
Storage Allocation
Runtime environment manages runtime memory requirements for the following entities:
Code: It is known as the part of a program that does not change at runtime. Its
memory requirements are at the compile time
Procedures: Their text part is static but they are called in a random manner. That is
why, stack storage is used to manage procedure calls and activations.
Variables: Variables are known at the runtime only, unless they are global or constant.
Heap memory allocation scheme is used for managing allocation and de-allocation of
memory for variables in runtime.
ALGORITHM:
1. Start the program
2. Enter the expression for which intermediate code is to be generated
3. If the length of the string is greater than 3, than call the procedure to return the
precedence
4. Among the operands.
5. Assign the operand to exp array and operators to the array.
6. Create the three address code using quadruples structure.
7. Reduce the no of temporary variables.
8. Continue this process until we get an output.
9. Stop the program.
PROGRAM: (STACK TO USE DYNAMIC STORAGE ALLOCATION)
#include <stdio.h> #include
<conio.h> #include
<process.h> #include
int label;
struct node *next;
};
void main()
int ch = 0; int k;
NULL;
while(1)
>Push ");
printf("2->Pop ");
printf("3->View"); printf("4-
>Exit \n");
switch(ch)
case 1:
h = head;
temp->next = h->next; h-
case 2:
h = head->next;
head->next = h->next;
break; case
3:
head;
while(h->next != NULL)
h = h->next;
case 4: exit(0);
}}
OUTPUT
Stack using linked list
1.push 2.pop 3.view 4.exit
Enter your choice 1
Enter label for few node 23
Stack using linked list
1.push 2.pop 3.view 4.exit
Enter your choice 1
Enter label for few node 45
Stack using linked list
1.push 2.pop 3.view 4.exit
Enter your choice 2
node deleted
RESULT:
Thus the program for implement storage allocation to use dynamic process for
stack has been successfully executed.