0% found this document useful (0 votes)
113 views56 pages

cs3501 Compiler Design Lab Manual

compiler design lab manual

Uploaded by

ramya.cse
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
113 views56 pages

cs3501 Compiler Design Lab Manual

compiler design lab manual

Uploaded by

ramya.cse
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 56

INDEX

S.NO DATE NAME OF THE EXPERIMENTS PAGE MARKS STAFF


NO SIGN

IMPLEMENTATION OF A LEXICAL ANALYZER TO


1 RECOGNIZE PATTERNS IN C

IMPLEMENTATION OF LEXICAL ANALYZER USING


2 LEX TOOL

GENERATE YACC SPECIFICATION FOR A FEW


SYNTACTIC CATEGORIES

a) PROGRAM TO RECOGNIZE A VALID ARITHMETIC


EXPRESSION

b) PROGRAM TO RECOGNIZE A VALID VARIABLE


3

c) PROGRAM TO RECOGNIZE A VALID CONTROL


STRUCTURES

d) IMPLEMENTATION OF CLACULATOR USING LEX


AND YACC
GENERATE THREE ADDRESS CODE FOR A SIMPLE
4 PROGRAM USING LEX AND YACC.

IMPLEMENTATION OF TYPE CHECKING USING


5 LEX AND YAAC
IMPLEMENTATION OF SIMPLE CODE
6 OPTIMIZATION TECHNIQUES
(CONSTANT FOLDING. ETC.)
IMPLEMENT BACK-END OF THE COMPILER FOR
7 WHICH THE THREE ADDRESS CODE IS GIVEN AS
INPUT AND THE 8086 ASSEMBLY LANGUAGE CODE
IS PRODUCED AS OUTPUT
ADDITIONAL EXPERIMENTS

IMPLEMENTATION OF STORAGE ALLOCATION


8
STRATEGY USING HEAP

9 CONSTRUCTION OF DAG

10 IMPLEMENTATION OF CODE GENERATION


EX.NO:1 IMPLEMENTATION OF A LEXICAL ANALYZER TO
DATE: RECOGNIZE PATTERNS IN C

AIM:

To write a C program to develop a lexical analyzer to recognize a few patterns in c.

INTRODUCTION:
Lexical analysis is the process of converting a sequence of characters (such as in a
computer program or web page) into a sequence of tokens (strings with an identified
"meaning"). A program that performs lexical analysis may be called a lexer, tokenizer, or
scanner.

TOKEN
A token is a structure representing a lexeme that explicitly indicates its categorization
for the purpose of parsing. A category of tokens is what in linguistics might be called a part-
of-speech. Examples of token categories may include "identifier" and "integer literal",
although the set of token categories differ in different programming languages. The process
of forming tokens from an input stream of characters is called tokenization. Consider this
expression in the C programming language:

sum = 3 + 2;

Tokenized and represented by the following table:


Lexeme Token category
sum "Identifier"
= "Assignment operator"
3 "Integer literal"
+ "Addition operator"
2 "Integer literal"
; "End of statement"

2
ALGORITHM:
1. Start the program.
2. Include the header files.
3. Allocate memory for the variable by dynamic memory allocation function.
4. Use the file accessing functions to read the file.
5. Get the input file from the user.
6. Separate all the file contents as tokens and match it with the functions.
7. Define all the keywords in a separate file and name it as input.c.
8. Finally print the output after recognizing all the tokens.
9. Stop the program.

PROGRAM:
#include<stdio.h>
#include<ctype.h>
#include<string.h>
void keyw(char
*p);
int i=0,id=0,kw=0,num=0,op=0;
char keys[32][10]={"auto","break","case","char","const","continue","default",
"do","double","else","enum","extern","float","for","goto",
"if","int","long","register","return","short","signed",
"sizeof","static","struct","switch","typedef","union",
"unsigned","void","volatile","while"};
main()
{
char ch,str[25],seps[15]=" \t\n,;(){}[]#\"<>",oper[]="!%^&*-+=~|.<>/?";
int j;
char fname[50];
FILE *f1;
//clrscr();
printf("enter file path (D:\CD\lex.c)\n");
scanf("%s",fname);
f1 = fopen(fname,"r");
//f1 = fopen("Input","r");
if(f1==NULL)
{
printf("file not found");
exit(0);
}
while((ch=fgetc(f1))!=EOF)
{
for(j=0;j<=14;j++)
{
if(ch==oper[j])
{
printf("%c is an operator\n",ch);
op++;
str[i]='\0';
keyw(str);
}

3
4
}
for(j=0;j<=14;j++)
{
if(i==-1)
break;
if(ch==seps[j])
{
if(ch=='#')
{
while(ch!='>')
{
printf("%c",ch);
ch=fgetc(f1);
}
printf("%c is a header file\
n",ch); i=-1;
break;
}
if(ch=='"')
{
do
{
ch=fgetc(f1);
printf("%c",ch);
}while(ch!='"');
printf("\b is an argument\
n"); i=-1;
break;
}
str[i]='\0';
keyw(str);
}
}
if(i!=-1)
{
str[i]=ch; i+
+;
}
else
i=0;
}
printf("Keywords: %d\nIdentifiers: %d\nOperators: %d\nNumbers: %d\n",kw,id,op,num);
//getch();
}
void keyw(char *p)
{
int k,flag=0;
for(k=0;k<=31;k++)
{
if(strcmp(keys[k],p)==0)

5
{
printf("%s is a keyword\n",p);
kw++;
flag=1;
break;
}
}
if(flag==0)
{
if(isdigit(p[0]))
{
printf("%s is a number\n",p);
num++;
}
else
{
//if(p[0]!=13&&p[0]!=10)
if(p[0]!='\0')
{
printf("%s is an identifier\n",p);
id++;
}
}
}
i=-1;
}

Input.C

#include <stdio.h>
#include
<conio.h> void
main()
{
int a=10,b,c;
a=b*c;
getch();
}

6
OUTPUT:

enter file path (D:CDlex.c)


D:\CD\lex.c
#include <stdio.h> is a header file
#include <conio.h> is a header
file void is a keyword
main is an
identifier int is a
keyword
= is an operator
a is an identifier
10 is a number
b is an identifier
c is an identifier
= is an operator
a is an identifier
* is an operator
b is an identifier
c is an identifier
getch is an identifier
Keywords: 2
Identifiers: 8
Operators: 3
Numbers: 1

Process returned 51 (0x33) execution time : 17.083 s


Press any key to continue.

RESULT:

Thus the above program for developing the lexical analyzer and recognizing the few patterns
in c is executed successfully and the output is verified.

7
EX.NO:2 IMPLEMENTATION OF LEXICAL ANALYZER USING LEX
DATE: TOOL

AIM:
To write a program to implement the Lexical Analyzer using Lex Tool.

INTRODUCTION:

THEORY:

 A language for specifying lexical analyzer.


 There is a wide range of tools for construction of lexical analyzer. The majority of
these tools are based on regular expressions.
 The one of the traditional tools of that kind is lex.We refer to the tool as the lex
compiler and to its input specification as the lex language.

LEX:
 The lex is used in the manner depicted.A specification of the lexical analyzer is
preferred by creating a program lex.l in the lex language.
 Then lex,l is run through the lex compiler to produce a „c‟program lex.yy.c
 The program lex.yy.c consists of a tabular representation of a transition diagram
constructed from the regular expression of lex.l together with a standard routine that
uses the table of recognize leximes.
 Lex.yy.c is run through the „c‟ compiler to produce as object program a.out,which is
the lexical analyzer that transform as input stream into sequence of tokens.
 Creating a lexical analyzer with lex is shown in below.

LEX SOURCE

Lex Source Program Lex Compiler LEX.YY.C


Lex.l

LEX.YY.C C Compiler A.OUT

8
ALGORITHM:

1. Start the program.


2. Lex program consists of three parts.
a. Declaration %%
b. Translation rules %%
c. Auxiliary procedure.
3. The declaration section includes declaration of variables, maintest,
constants and regular definitions.
4. Translation rule of lex program are statements of the form
a. P1 {action}
b. P2 {action}
c. …
d. …
e. Pn {action}
5. Write a program in the vi editor and save it with .l extension.
6. Compile the lex program with lex compiler to produce output file as lex.yy.c.

eg $ lex filename.l
$ gcc lex.yy.c –ll

7. Compile that file with C compiler and verify the output.

PROGRAM:
Program name: lexana.l
%{
int COMMENT=0;
%}
identifier[a-z][A-Z0-9]*
digit[0-9]
%%

#.* {printf("\n%s is a peprocessor diective",yytext);}


"int" |
"float" |
"char" |
"double" |
"for" |
"do" |
"if" |
"else" |
"break" |
"continue" |
"void" |
"case" |

"long" |
"struct" |
"typedef"
|

9
"goto" |
"const" |
"while" |
"printf" |
"scanf" |
"switch" |
"main()" |
"return" {printf("\n\t%s is a keyword",yytext);}
"\*" {COMMENT=1;}
"*/" {COMMENT=0;}

\{ {if(!COMMENT) printf("\nblocks starts");}


\} {if(!COMMENT) printf("\n block end");}

{identifier} {if(!COMMENT) printf("\n\t%s is an identifier",yytext);} \".*\"


{
if(!COMMENT) printf("\n\t%s is a string",yytext);}

{digit} {if(!COMMENT) printf("\n\t%s is a number",yytext);} \)(\;)? {if(!COMMENT) printf("\n\


t"); ECHO; printf("\n");} \ECHO;
={if(!COMMENT) printf("\n\t= is an assignment operator");} \<= | \>= | \< | == |
\> {if(!COMMENT) printf("\n\t%s is an relational operator");
}
%%
int main(int argc,char **argv)
{
if(argc>1)
{

FILE *f1; f1=fopen("file.c","r"); if(!f1)


{

printf("could not open%s\n",argv[1]); exit(0);

}
yyin=f1;
}
yylex();

printf("\n"); return 1;
}
int yywrap()

return 0;

10
INPUT PROGRAM:
#include<stdio.h>
void main()
{
int a,b,c;
printf("enter the value for
a,b"); scanf("%d%d",&a,&b)';
c=a+b;
printf("the value of c:%d",&c);
}

11
OUTPUT:

RESULT:
Thus the above program is compiled and executed successfully using the LEX tool and the
sample output is verified.

12
EX.NO:3
GENERATE YACC SPECIFICATION FOR A FEW
DATE: SYNTACTIC CATEGORIES

a). Program to recognize a valid arithmetic expression that uses operator


+, -, * and /.
AIM:

To write a Yacc program to valid arithmetic expression using Yacc .


ALGORITHM:

1. Start the program.


2. Reading an expression .
3. Checking the validating of the given expression according to the rule using yacc.
4. Using expression rule print the result of the given values.
5. Stop the program.

PROGRAM:

//Program to recognize a valid arithmetic expression that uses operator +, -, * and /

LEX PART:

%{

#include "y.tab.h"

%}

%%

[a-zA-Z_][a-zA-Z_0-9]* return id;

[0-9]+(\.[0-9]*)? return

num; [+/*] return op;

. return yytext[0];

\n return 0;

%%

int yywrap()

13
return 1;

YACC PART:

%{

#include<stdio.h>
int valid=1;
%}

%token num id op

%%

start : id '=' s

';' s : id x

| num x

| '-' num x

| '(' s ')' x

x: op s

| '-' s

%%

int yyerror()

valid=0;

printf("\nInvalid expression!\n");

return 0;

14
int main()

printf("\nEnter the expression:\n");

yyparse();

if(valid)

printf("\nValid expression!\n");

OUTPUT:

15
b). Program
to recognize a valid variable which starts with a letter followed
by any number of letters or digits.
AIM :

To write a yacc program to check valid variable followed by letter or digits .

ALGORITHM:

Step1: Start the program

Step2: Reading an expression

Step3: Checking the validating of the given expression according to the rule using yacc.

Step4: Using expression rule print the result of the given values

Step5: Stop the program

PROGRAM CODE:

//Program to recognize a valid variable

LEX PART:

%{

#include "y.tab.h"

%}

%%

[a-zA-Z_][a-zA-Z_0-9]* return

letter; [0-9] return digit;

. return yytext[0];

\n return 0;

%%

int yywrap()

return 1;

16
YACC PART:

%{

#include<stdio.h>

int valid=1;

%}

%token digit letter

%%

start : letter s

s: letter s

| digit s

%%

int yyerror()

printf("\nIts not a identifier!\n");

valid=0;

return 0;

int main()

printf("\nEnter a name to tested for identifier ");

yyparse();

if(valid)

printf("\nIt is a identifier!\n");

17
}

18
OUTPUT:

19
c). Program to recognize a valid control structures syntax of C language
(For loop, while loop, if-else, if-else-if, switch-case, etc.).

AIM :

To write a to recognize a valid control structures syntax of C language (For loop, while loop, if-
else, if-else-if, switch-case, etc.).

ALGORITHM:

Step1: Start the program

Step2: Recognize For Loop, While Loop, If-Else, If-Else-If, Switch Case.

Step3: Checking the validating of the given Control structures according to the rule using yacc.

Step4: Using control structure syntax print the result of the given values

Step5: Stop the program

PROGRAM:

%{
#include<stdio.h>
#include<stdlib.h>
%}
%token IF ELSE WHILE FOR SWITCH CASE DEFAULT
%token ID INT_CONST FLOAT_CONST CHAR_CONST
%%
Program:control_structure
| program control_structure
:
Control_structure : if_statement
|if_else_statement
|if_else_if_statement
|switch_case_statement
|while_loop
|for_loop
;
If_statement :IF‟(„expression‟)‟ statement
;
If_else_statement :IF‟(„expression‟)‟ statement ELSE statement
;

If_else_if_statement :IF‟(„expression‟)‟ statement ELSE IF „(„EXPRESSION‟)‟statement


|if_else_statement ELSE IF‟(„expression‟)‟ statement
;
Switch_case_statement:SWITCH‟(„expression‟)‟‟{„case_list‟}‟
;
20
Case_list: case_list case
| case
;
Case: CASE INT_CONST‟:‟ statement
|DEFAULT‟:‟statement
;
While_loop :WHILE „(„ expression‟)‟ statement
;
For_loop :FOR „(„ expression_opt‟;‟expression_opt‟;‟expression_opt‟)‟satement
;
Expression_opt:expression
|/*empty*/
;
Expression: ID
|INT_CONST
|FLOAT_CONST
|CHAR_CONST
;
Statement:‟{„program‟}‟
|control_structure
;
%%
Int yyerror(char*s){
Fprintf(stderr,”%s\n”,s);
Return 0 ;
}
Int main() {
Yyparse();
Return 0;
}

RESULT:
Thus the program to implement recognizes a valid control structures was executed and
verified.

21
d.) Implementation of calculator using LEX and YACC

AIM:

To write a Program to implement the calculator using lex and yacc.

ALGORITHM:

1. Start the program.


2. Declare the required variables and methods.
3. Get the input using NUM{DIGIT}+(\.{DIGIT}+)? as two integer value.
4. Then check whether the given number having operator such as + \ - * /
5. After that assign first number to f1 then check if f1==0
6. If it true then op1=atof(yytext)
7. else if assign the second number to f1 then check f2== -1
8. if it true then op2=atof(yytext)
9. By using switch check the operator +,- ,* , / do the corresponding calc operation.
10. Print the result.
11. Stop the program.

PROGRAM:

Program Name: input.l

%{
#include "y.tab.h"
#include<math.h>
%}
NUMBER [0-9]+|([0-9]*"."[0-9]+)
%%
{NUMBER} {yylval.dval=atof(yytext);
return NUMBER;}
sin|SIN {return SIN;} cos|
COS {return COS;} tan|
TAN {return TAN;} sqrt|
SQRT {return SQRT;}

square|SQUARE {return SQUARE;}


exp|EXP {return EXP;}
reci|RECI {return RECI;}
cube|CUBE {return CUBE;}
fact|FACT {return FACT;}
LOG { return LOG;}
ln|LN {return LN;} MOD|
mod {return
MOD;}

22
[\t]+ ;
\n|. return yytext[0];
%%
int yywrap(void)
{ return 1;
}

Program Name: intput.y

%{
#include "y.tab.h"
#include <stdio.h>
#include <math.h>
#define PI 3.141592
int i,j;
%}

%union
{
double dval;
}
%token <dval> NUMBER
%token SIN COS TAN SQRT SQUARE RECI EXP MOD CUBE FACT %left LN LOG
%left '+''-''*''/'
%right '^'
%nonassoc NEG
%type <dval> E

%%

SL : S '\n'
| SL S '\
n'
;

S : E {printf("=%g\n",$1);}
;

E : E '+' E {$$=$1+$3;
printf("Addition is");}
|E '-' E {$$=$1-$3;
printf("substraction is");
}
|E '*' E {$$=$1*$3;
printf("Multiplication
is");
}
|E '/' E {
if($3==0)
printf("Error! Divide by zero!!");

23
else
$$=$1/$3;
printf("Division is");
}

|E '^' E {$$=pow($1,$3);
printf("Power is=");
}
|SIN '(' E ')' {$$=sin($3/180*PI);
printf("SIN is=");
}
|COS '(' E ')' {$$=cos($3/180*PI);
printf("COS is");
}
|TAN '(' E ')' { if($3==90)
printf("Undefined (Infinity)");
else
$$=tan($3/180*PI);
printf("TAN is");
}
|SQRT '(' E ')' {$$=sqrt($3);
printf("Square Root is");
}
|SQUARE '(' E ')' {$$=$3*$3;
printf("square is=");
}
|EXP '(' E ')' {$$=exp($3);
printf("EXPONENTIAL is");
}
|RECI '(' E ')' {$$=1/($3);
printf("Reciprocal is");}

|CUBE '(' E ')' {$$=$3*$3*$3;


printf("Cube is");}
|FACT '(' E ')' {

$$=1; for(j=1;j<=$3;j+
+)
$$=$$*j;
printf("Factorial is");
}
|'(' E ')' {$$=$2;
printf("The simple number is");}
|'-' E %prec NEG {$$=-$2;
printf("The number with Negative sign is ");
}
|LOG E {$$=log($2)/log(10);
printf("LOG of base 10 is");
}
|LN E { $$=log($2);

24
printf("LOG with base 2 is");
}
|MOD '(' E','E')' {$$=fmod($3,$5);
}
|NUMBER
;
%%
extern FILE*yyin;

int main()
{
do{
yyparse();
}while(!feof(yyin));
}

yyerror(char*a)
{
fprintf(stderr,"parse error!!!");
}
OUTPUT:

user@ubuntu:~/Desktop$ flex a3.l


user@ubuntu:~/Desktop$ yacc -d a3.y
user@ubuntu:~/Desktop$ gcc lex.yy.c y.tab.c -ll -lm
user@ubuntu:~/Desktop$ ./a.out
MOD(4,2)
=0
MOD(4,3)
=1
sin(90)
SIN is==1
tan(90)
Undefined (Infinity)TAN is=90
cube(3)
Cube is=27
square(2)
square is==4
sqrt(25)
Square Root is=5
reci(5)
Reciprocal
is=0.2 exp(10)
EXPONENTIAL is=22026.5
LOG10
LOG of base 10 is=1
ln10
LOG with base 2 is=2.30259
5
=5
(9)

25
The simple number is=9
3^2
Power is==9
3*3
Multiplication is=9
3+4
Addition is=7
4-2
substraction is=2
3/0
Error! Divide by zero!!Division is=3
32/2
Division is=16
fact(5)
Factorial is=120

RESULT:
Thus the program for generation of YAAC specification was executed and verified.

26
EX.NO:4 GENERATE THREE ADDRESS CODE FOR A
DATE: SIMPLE PROGRAM USING LEX AND YACC.

AIM:

To write a program to convert BNF rules into YACC form and write code to generate
Abstract Syntax Tree using LEX and YACC.

ALGORITHM:
1. Start a program
2. Declare the declarations as a header file {include<ctype.h>}
3. Token digit
4. Define the translations rules like line, expr, term, factor
Line:exp „\n‟ {print(“\n %d \n”,$1)} Expr:expr‟+‟ term ($$=$1=$3}
Term:term „+‟ factor($$ =$1*$3}
Factor

Factor:‟(„enter‟) „{$$ =$2)


%%
5. Define the supporting C routines
6. Stop the program

PROGRAM:
Program Name : lex.l
%{

%{
#include<stdio.h>
#include"y.tab.h"
int k=1;
%}

%%
[0-9]+ {
yylval.dval=yytext[0];
return NUM;
}

\n {return 0;}
. {return yytext[0];}
%%

void yyerror(char* str)


{
printf("\n%s",str);
}
char *gencode(char word[],char first,char op,char second)
{
char temp[10];

27
sprintf(temp,"%d",k);
strcat(word,temp); k+
+;
printf("%s = %c %c %c\n",word,first,op,second);

return word; //Returns variable name like t1,t2,t3... properly


}
int yywrap()
{
return 1;
}

main()
{
yyparse();
return 0;
}

Program Name : yacc.y


%{
#include<stdio.h>
int aaa;
%}

%union{ ch
ar dval;
}

%token <dval> NUM


%type <dval> E
%left '+' '-'
%left '*' '/' '%'

%%
statement : E {printf("\nt = %c \n",$1);}
;

E : E '+' E
{
char word[]="t";
char *test=gencode(word,$1,'+',$3);
$$=test;

}
| E '-' E
{
char word[]="t";
char *test=gencode(word,$1,'-',$3);
$$=test;
}

28
| E '%' E
{
char word[]="t";
char *test=gencode(word,$1,'%',$3);
$$=test;
}
| E '*' E
{
char word[]="t";
char *test=gencode(word,$1,'*',$3);
$$=test;
}
| E '/' E
{
char word[]="t";
char *test=gencode(word,$1,'/',$3);
$$=test;
}
| '(' E ')'
{
$$=$2;
}
| NUM
{
$$=$1;
}
;
%%

OUTPUT:

[a40@localhost ~]$ lex threee.l


[a40@localhost ~]$ yacc -d threee.y
[a40@localhost ~]$ cc lex.yy.c y.tab.c -ll
[a40@localhost ~]$ ./a.out

Enter Expression x => 1+2-3*3/1+4*5

A = 1+2
B = 3*3
C = B/1
D = A-C
E = 4*5
F = D+E
X=F
[a40@localhost ~]$ ./a.out

Enter Expression x => 1+2*(3+4)/5

29
A = 3+4
B = 2*A
C = B/5
D = 1+C
X=D
[a40@localhost ~]$ ./a.out

Enter Expression x => 1+2*(-3+-6/1)*3

A = -3
B = -6
C = B/1
D = A+C
E = 2*D
F = E*3
G = 1+F
X=G

RESULT:
Thus the program to implement three address code was executed and verified.

30
EX.NO:5 IMPLEMENTATION OF TYPE CHECKING USING LEX
DATE: AND YAAC

AIM:

To write a C program to implement type checking

ALGORITHM:

Step1: Track the global scope type information (e.g. classes and their members)

Step2: Determine the type of expressions recursively, i.e. bottom-up, passing the resulting types
upwards.

Step3: If type found correct, do the operation

Step4: Type mismatches, semantic error will be notified


PROGRAM CODE:
//To implement type checking
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n,i,k,flag=0;
char vari[15],typ[15],b[15],c;
printf("Enter the number of variables:");
scanf(" %d",&n);
for(i=0;i<n;i++)
{
printf("Enter the variable[%d]:",i);
scanf(" %c",&vari[i]);
printf("Enter the variable-type[%d](float-f,int-i):",i);
scanf(" %c",&typ[i]);
if(typ[i]=='f')
flag=1;
}
printf("Enter the Expression(end with $):");
i=0;
getchar();
while((c=getchar())!='$')
{
b[i]=c; i+
+; }
k=i;
for(i=0;i<k;i++)
{
if(b[i]=='/')
{
flag=1;

31
break; } }
for(i=0;i<n;i++)
{
if(b[0]==vari[i])
{
if(flag==1)
{
if(typ[i]=='f')
{ printf("\nthe datatype is correctly defined..!\n");
break; }
else
{ printf("Identifier %c must be a float type..!\n",vari[i]);
break; } }
else
{ printf("\nthe datatype is correctly defined..!\n");
break; } }
}
return 0;
}

OUTPUT:

RESULT:
Thus the program to implement type checking was executed and verified.

32
EX.NO:6 IMPLEMENTATION OF SIMPLE CODE OPTIMIZATION
DATE: TECHNIQUES (CONSTANT FOLDING., ETC.)

AIM:
To write a C program to implement Code Optimization Techniques.

INTRODUCTION:
Optimization is a program transformation technique, which tries to improve the code
by making it consume less resource (i.e. CPU, Memory) and deliver high speed.

In optimization, high-level general programming constructs are replaced by very


efficient low-level programming codes. A code optimizing process must follow the three
rules given below: The output code must not, in any way, change the meaning of the
program.

 Optimization should increase the speed of the program and if possible, the program
should demand less number of resources.
 Optimization should itself be 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.

Machine-Independent Optimization
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:

33
This code involves repeated assignment of the identifier item, which if we put this

Machine-Dependent Optimization
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:

1. Start the program.


2. Declare the variables andfunctions.
3. Enter the expression and state it in the variable a,b,c.
4. Calculate the variables b & c with „temp‟ and store it in f1 and f2.
5. If (f1=null && f2=null) then expression could not be optimized.
6. Assign the results.
7. Print the results.
8. Stop the program.

PROGRAM:
#include<stdio.h>
#include<conio.h>
#include<string.h>
struct op
{ char l;
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 *tem;
clrscr();
printf("Enter the
Number of
Values:");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("left: ");
op[i].l=getche();
printf("\tright: ");
scanf("%s",op[i].r);
}
printf("Intermediate
34
Code\n") ;
for(i=0;i<n;i++)
{
printf("%c=",op[i].l
);
printf("%s\n",op[i].r);
}
for(i=0;i<n-1;i++)
{ temp=op[i].l;
for(j=0;j<n;j++)
{
p=strchr(op[j].r,tem
p);
if(p)
{
pr[z].l=op[i].l;
strcpy(pr[z].r,op[i].
r);
z++; }}}
pr[z].l=op[n-1].l;
strcpy(pr[z].r,op[n-
1].r);
z++;
printf("nAfter Dead
Code
Eliminationn");
for(k=0;k<z;k++) {
printf("%ct=",pr[k].
l);
printf("%sn",pr[k].r
);
}
for(m=0;m<z;m++)
{
tem=pr[m].r;
for(j=m+1;j<z;j++)
{
p=strstr(tem,pr[j].r)
;
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;
}}}}}
printf("Eliminate
Common
Expression\n");
for(i=0;i<z;i++)
{
35
printf("%c\t=",pr[i].l)

36
printf("%s\n",pr[i].r
);
}
for(i=0;i<z;i++)
{
for(j=i+1;j<z;j++)
{
q=strcmp(pr[i].r,pr[ j
].r);
if((pr[i].l==pr[j].l)
&&!q)
{
pr[i].l='\0';
strcpy(pr[i].r,'\0');
}}}
printf("Optimized Code\
n"); for(i=0;i<z;i++)
{ if(pr[i].l!='\0')
{
printf("%c=",pr[i].l
);
printf("%s\n",pr[i].r
);
}
}
getch();
}

37
OUTPUT:

Enter the Number of Values:5


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
e=c+d
f=b+e
r=f
nAfter Dead Code Eliminationnbt=c+dnet=c+dnft=b+enrt=fnpos: 2Eliminate Common
Expression b =c+d
b
=c+d f
=b+b r
=f
Optimized Code
b=c+d
f=b+b
r=f

RESULT:

Thus the implementation of simple code optimization technique e was executed and verified

38
EX.NO:7 IMPLEMENT BACK-END OF THE COMPILER FOR
WHICH THE THREE ADDRESS CODE IS GIVEN AS
DATE: INPUT AND THE 8086 ASSEMBLY LANGUAGE CODE
IS PRODUCED AS OUTPUT

AIM:
To write a program C Program to implement the Back end of the compiler.

ALGORITHM:

1. Start
2. Get the three variables from statements and stored in text file k.txt
3. Compile the program and give the path of the source file.
4. Execute the Program
5. Target code for the given statement was produced
6. Stop.

PROGRAM:

#include<stdio.h>
#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;

39
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();
}

OUTPUT:

Enter the set of intermediate code(terminated by exit):


a=a*b
c=f*h
g=a*h
f=Q+w
t=q-j
exit
target code generated
******************
MOV a, R0
MUL b,R0
MOV R0,a
MOV f,R1
MUL h,R1
MOV R1,c
MOV a,R2
MUL h,R2
MOV R2,g
MOV Q,R3
ADD w, R3
MOV R3, f
MOV q,R4
SUB j,R4
MOV R4,t

Result:
Thus the above program is compiled and executed successfully and output is verified

40
EX.NO:8
IMPLEMENTATION OF STORAGE ALLOCATION
DATE: STRATEGY USING HEAP

AIM:

To write a C program to implement heap storage allocation strategy.

INTRODUCTION:
Storage Allocation
Runtime environment manages runtime memory requirements for the following entities:

Code: It is known as the text part of a program that does not change at runtime. Its memory
requirements are known 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.

Static Allocation

In this allocation scheme, the compilation data is bound to a fixed location in the memory and
it does not change when the program executes. As the memory requirement and storage locations are
known in advance, runtime support package for memory allocation and de-allocation is not required.

Stack Allocation

Procedure calls and their activations are managed by means of stack memory allocation. It
works in last-in-first-out (LIFO) method and this allocation strategy is very useful for recursive
procedure calls.

Heap Allocation

Variables local to a procedure are allocated and de-allocated only at runtime. Heap allocation
is used to dynamically allocate memory to the variables and claim it back when the variables are no
more required.

Except statically allocated memory area, both stack and heap memory can grow and shrink
dynamically and unexpectedly. Therefore, they cannot be provided with a fixed amount of memory
in the system.

41
As shown in the image above, the text part of the code is
allocated a fixed amount of memory.
Stack and heap memory are arranged at the extremes of total
memory allocated to the program. Both shrink and grow against
each other.

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, then call the procedure to return the precedence
among the operands.
4. Assign the operand to exp array and operators to the array.
5. Create the three address code using quadruple structure.
6. Reduce the no of temporary variables.
7. Continue this process until we get an output.
8. Stop the program.

PROGRAM:
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
typedef struct Heap
{
int data;
struct Heap *next;
}node;
node *create();

void main()
{
int choice, val;
char ans;
node *head;
void display(node *);
node *search(node *,int);
node *insert(node *);
void dele(node **);
head=NULL;
do
{

clrscr();
printf("\n Program to perform various operations on heap using dynamic memory management");
printf ("\n1.Create");
printf ("\n2.Display");
printf ("\n3.Insert an element in a list");

42
printf ("\n4.Delete an element from list");
printf ("\n5.Quit");
printf ("\n Enter Your Choice(1-
5)"); scanf("%d",&choice);
switch(choice)
{
case 1:head=create();
break;

case 2:display(head);
break;
case 3:head=insert(head);
break;
case 4:dele(&head);
break;
case 5:exit(0);
default:clrscr();
printf("Invalid Choice,Try again");
getch();
}
}
while(choice!=5);
}
node *create()
{
node *temp,*new1,*head;
int val,flag;
char ans='y';
node *get_node();
temp=NULL;
flag=TRUE;
do
{
printf("\n Enter the Element");
scanf("%d",&val);
/*allocate new node*/
new1=get_node();
if(new1==NULL)
printf("\n Memory is not
allocated"); new1-> data=val;
if (flag==TRUE)/* Executed only for the first time*/ {
head=new1;
temp=head; /*head is the first node in the heap*/
flag=FALSE;}
else
{
temp->next=new1;
temp=new1;
}

printf("\nDo you want to enter more elements?(y/n)"); ans=getch();

43
}
while(ans=='y'); printf("\
nThe list is created");
getch();
clrscr();
return head;
}
node *get_node()
{
node *temp;
temp=(node*)malloc(sizeof(node));
//using the mem. Allocation
function temp->next=NULL;
return temp;
}
void display(node*head)
{
node *temp;
temp=head;
if(temp==NULL)
{
printf("\n The list is empty\n");
getch();
clrscr();
return;
}
while(temp!= NULL)
{
printf("%d->",temp->
data); temp=temp->next;

}
printf("NULL");
getch();
clrscr();
}
node *search(node *head,int key)
{
node *temp;
int found;
temp=head;
if (temp==NULL)
{
printf("The linked list is empty\n");

getch();
clrscr();
return
NULL;
}
found=FALSE;

44
while(temp!=NULL&&found==FALSE)
{
if(temp->data != key)
temp = temp->next;
else
found=TRUE;
}
if(found == TRUE)

{
printf("\n The Elements is present in the list\n");
getch();
return temp;
}
else
printf("\n The Element is not present in the list\n");
getch();
return NULL;
}
node *insert(node *head)
{
int choice;
node *insert_head(node*);
void insert_after(node*);
void insert_last(node*);
printf("\n 1.Insert a node as a head
node"); printf("\n 1.Insert a node as a last
node");
printf("\n 1.Insert a node as at the intermediate position in the list ");
printf("\n 1.Enter your choice for insertion of node ");
scanf("%d",&choice);
switch(choice)
{
case 1:head = insert_head(head);

break;
case 2:insert_last(head);
break;
case 3:insert_after (head);
break;
}
return head;
}
node *insert_head(node*head)
{
node *New,*temp;
New=get_node();
printf ("\n Enter the element which you want to insert ");

scanf("%d",&New->data);
if(head == NULL)
head = New;

45
else
{
temp=head;
New->next = temp;
head= New;
}
return head;
}
void insert_last(node *head)
{

node *New,*temp;
New = get_node();
printf ("\n Enter the element which you want to insert
"); scanf("%d",&New->data);
if(head == NULL)
{
head = New;
}
else
{
temp=head;
while(temp->next!=NULL)
temp=temp->next;
temp->next=New;
New->next=NULL;
}
}
void insert_after(node *head)
{
int key;
node *New,*temp;
New = get_node();
printf("Enter the element after which you want to insert
"); scanf("%d",&key);

temp=head;
do
{
if(temp->data==key)
{
printf ("Enter element which you want to insert
"); scanf("%d",&New->data);
New->next=temp->next;
temp->next=New;
return;
}
else
temp=temp->next;

46
while(temp!=NULL);
}
node *get_prev(node *head,int val)
{
node *temp,*prev;
int flag;
temp = head;
if(temp == NULL)
return NULL;
flag=FALSE;
prev=NULL;
while(temp!=NULL && !flag)

{
if(temp->data!=val)
{
prev = temp;
temp = temp->next;
}
else
flag = TRUE;
}
if(flag) /*if Flag is true*/
return prev;
else
return NULL;
}
void dele(node **head)
{
int key;
node *New,*temp,*prev;
temp=*head;
if (temp== NULL)
{
printf ("\n The list is empty\n ");
getch();
clrscr();
return;
}
clrscr();
printf("\nENTER the Element you want to delete:");
scanf("%d",&key);
temp=search(*head,key);
if(temp!=NULL)
{
prev=get_prev(*head,key); if(prev!
=NULL)
{
prev->next = temp-> next;
free(temp);

47
}
else
{
*head = temp->next;

free(temp); // using the mem. Dellocation function


}
printf("\n The Element is deleted\n");
getch();
clrscr();
}
}

OUTPUT:

Program to perform various operations on heap using dynamic memory management


1.Create
2. Display
3. Insert an element in a list
4. Delete an element from
list 5.Quit
Enter Your Choice(1-5)1

Enter the Element10

Do you want to enter more elements?(y/n)


Enter the Element20

Do you want to enter more elements?(y/n)


Enter the Element30

Do you want to enter more elements?(y/n)


Enter the Element40

Do you want to enter more elements?(y/n)


The list is created
Program to perform various operations on heap using dynamic memory management
1.Create
2. Display
3. Insert an element in a list
4. Delete an element from
list 5.Quit
Enter Your Choice(1-
5)2 10->20->30->40-
>NULL
Program to perform various operations on heap using dynamic memory management
1.Create
2. Display
3. Insert an element in a list
4. Delete an element from
list 5.Quit

48
Enter Your Choice(1-5)4

ENTER the Element you want to delete:30

The Elements is present in the list

The Element is deleted

Program to perform various operations on heap using dynamic memory management


1.Create
2. Display
3. Insert an element in a list
4. Delete an element from
list 5.Quit
Enter Your Choice(1-
5)2 10->20->40->NULL

RESULT:
Thus the above program was successfully executed and output was verified.

49
EX.NO:9
CONSTRUCTION OF DAG
DATE:

AIM:

To write a C program to construct of DAG.


INTRODUCTION:
Given a Weighted Directed Acyclic Graph and a source vertex in the graph, find the shortest
paths from given source to all other vertices.

For a general weighted graph, we can calculate single source shortest distances in O(VE) time
using Bellman–Ford Algorithm. For a graph with no negative weights, we can do better and calculate
single source shortest distances in O(E + VLogV) time using Dijkstra‟s algorithm. Can we do even
better for Directed Acyclic Graph (DAG)? We can calculate single source shortest distances in
O(V+E) time for DAGs. The idea is to use Topological Sorting.

We initialize distances to all vertices as infinite and distance to source as 0, then we find a
topological sorting of the graph. Topological Sorting of a graph represents a linear ordering of the
graph (See below, figure (b) is a linear representation of figure (a) ). Once we have topological order
(or linear representation), we one by one process all vertices in topological order. For every vertex
being processed, we update distances of its adjacent using distance of current vertex.

Following figure is taken from this source. It shows step by step process of finding shortest
paths.

50
ALGORITHM:
1. Start the program.
2. Include all the header files.
3. Check for postfix expression and construct the inorder DAG representation.
4. Print the output.
5. Stop the program.

PROGRAM:
#include<stdio.h>
#include<conio.h>
#include<ctype.h>
#define size 20
typedef struct node
{
char data;
struct node *left;
struct node *right;
}btree;
btree *stack[size];
int top;
void main()
{
btree *root;
char exp[80];
btree *create(char exp[80]);
void dag(btree *root);
clrscr();
printf("\nEnter the postfix expression:\n");
scanf("%s",exp);

top=-1;
root=create(exp);
printf("\nThe tree is created.....\n");
printf("\nInorder DAG is : \n\n");
dag(root);
getch();
}

btree *create(char exp[])


{
btree *temp;
int pos;
char ch;

void push(btree*);
btree *pop();
pos=0;
ch=exp[pos];
while(ch!='\0')
{
temp=((btree*)malloc(sizeof(btree)));

51
temp->left=temp->right=NULL;
temp->data=ch;
if(isalpha(ch))
push(temp);
else if(ch=='+' ||ch=='-' || ch=='*' || ch=='/')
{

temp->right=pop();
temp->left=pop();
push(temp);
}
else
printf("\n Invalid char Expression\n");
pos++;
ch=exp[pos];
}
temp=pop();
return(temp);
}

void push(btree *Node)


{
if(top+1 >=size)
printf("Error:Stack is full\n");
top++;
stack[top]=Node;
}

btree* pop()
{
btree *Node;

if(top==-1)
printf("\nerror: stack is empty..\n");
Node=stack[top];
top--;
return(Node);
}
void dag(btree *root)
{
btree *temp;
temp=root;
if(temp!=NULL)
{
dag(temp->left);
printf("%c",temp->data);
dag(temp->right);
}
}

52
OUTPUT:

Enter the postfix expression:


ab+cd-*

The tree is created.....

Inorder DAG is :

a+b*c-d
Process returned 13 (0xD) execution time : 40.135 s
Press any key to continue.

RESULT:
Thus the above program was successfully executed and output is verified.

53
EX.NO:10
IMPLEMENTATION OF CODE GENERATION
DATE:

AIM:
To write a program to generate the three address code and produces the 8086 assembly
language instructions that can be assembled and run using a 8086 assembler.

INTRODUCTION:

A compiler is a computer program that implements a programming language specification to


"translate" programs, usually as a set of files which constitute the source code written in source
language, into their equivalent machine readable instructions (the target language, often having a
binary form known as object code). This translation process is called compilation.

Back end
 some local optimization
 register allocation
 peep-hole optimization
 code generation
 instruction scheduling

The main phases of the back end include the following:

Analysis: This is the gathering of program information from the intermediate representation
derived from the input; data-flow analysis is used to build use-define chains, together with
dependence analysis, alias analysis, pointer analysis, escape analysis, etc. Accurate analysis is the
basis for any compiler optimization. The call graph and control are usually also built during the
analysis phase.

Optimization: The intermediate language representation is transformed into functionally equivalent


but faster (or smaller) forms. Popular optimizations are expansion, dead, constant propagation, loop
transformation, register allocation and even automatic parallelization.

Code Generation: The transformed intermediate language is translated into the output language,
usually the native machine language of the system. This involves resource and storage decisions,
such as deciding which variables to fit into registers and memory and the selection and scheduling of
appropriate machine instructions along with their associated addressing modes. Debug data may also
need to be generated to facilitate debugging.

54
ALGORITHM:
Input: Set of three address code sequence.
Output: Assembly code sequence for three address codes (opd1=opd2, op, opd3).
Method:
1. Start
2. Get address code sequence.
3. Determine current location of 3 using address (for 1st operand).
4. If current location not already exist generate move (B,O).
5. Update address of A(for 2nd operand).
6. If current value of B and () is null,exist.
7. If they generate operator () A,3 ADPR.
8. Store the move instruction in memory
9. Stop.

PROGRAM:

#include<stdio.h>
#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;
}

55
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();
}

OUTPUT:

Enter the set of intermediate code (terminated by exit):


a=2/3
b=4/5
c=4+3
exit

target code generation


************************
Mov 2,R0
DIV3,R0
Mov R0,a
Mov 4,R1
DIV5,R1
Mov R1,b
Mov 4,R2
ADD3,R2
Mov R2,c
Process returned 0 (0x0) execution time: 80.535 s
Press any key to continue.

RESULT:
Thus the program to 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 a
8086 assembler was executed and output is verified.

56

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