Вы находитесь на странице: 1из 54

Ex.

No:
IMPLEMENTATION OF SYMBOL TABLE

Aim:
To write a C program to implement symbol table
Description:
Symbol table is an important data structure created and maintained by compilers in
order to store information about the occurrence of various entities such as variable names,
function names, objects, classes, interfaces, etc. Symbol table is used by both the analysis and
the synthesis parts of a compiler.
A symbol table may serve the following purposes depending upon the language in hand:
 To store the names of all entities in a structured form at one place.
 To verify if a variable has been declared.
 To implement type checking, by verifying assignments and expressions in the source
code are semantically correct.
 To determine the scope of a name
Algorithm:
1. Define a Symbol table with following attributes. <symbol name, type, scope, size>
2. Read the source program from the file.
3. If a symbol is read
a. Check whether the symbol is already in the symbol table using lookup operation.
b. If the symbol is in table then
i. Report Error – Duplicate Symbol
c. If not found
i. Insert the symbol in the symbol table along with its type, scope and size
using Insert Operation.
4. Write the output (Symbol table) in a file.

1
SOURCE CODE

#include<stdio.h>

struct table{

intsno;

char name[100];

char type[100];

char scope[20];

chardt[20];

int size;

};

void strip(char *s) {

char *p2 = s;

while(*s != '\0') {

if(*s != '\t' && *s != '\n' && *s != '&' && *s != '"') {

*p2++ = *s++;

} else {

++s;

*p2 = '\0';

int main()

FILE *fp;

struct table b[100];

inti,flag=0,flag1=0,flag2=0,flag3=-1;

charstr[100][100];

2
char *ch;

char
keywrd[10][100]={"int","float","double","char","long","include","return","printf","scanf","m
ain"};

charincfile[3][100]={"stdio.h","conio.h","string.h"};

charfrmatespec[5][5]={"%d","%s","%c","%f","%d%d"};

fp = fopen("sum.c","r");

while(!feof(fp))

fread(str,sizeof(str),1,fp);

ch = strtok(str," ,;(){}<>#");

while(ch != NULL){

strip(ch);

if(strcmp(ch,"main")==0) {

flag2 = 10;

for(i=0;i<10;i++) {

if(strcmp(ch,keywrd[i])==0) {

flag1 = 1;

flag3 = i;

for(i=0;i<10;i++) {

if(strcmp(ch,"+")==0 || strcmp(ch,"*")==0 || strcmp(ch,"/")==0 || strcmp(ch,"-


")==0 || strcmp(ch,"=")==0 || strcmp(ch,"%")==0 || strcmp(ch,"&")==0)

flag1 = 2;

3
}

for(i=0;i<5;i++) {

if(strcmp(ch,frmatespec[i])==0)

flag1 = 3;

for(i=0;i<3;i++) {

if(strcmp(ch,incfile[i])==0)

flag1 = 4;

if(flag1==1) {

strcpy(b[flag].name,"keyword");

strcpy(b[flag].type,ch);

b[flag].sno = flag + 1;

flag++;

flag1=0;

else if(flag1==2) {

strcpy(b[flag].name,"operators");

strcpy(b[flag].type,ch);

b[flag].sno = flag + 1;

flag++;

flag1=0;

else if(flag1==3) {

strcpy(b[flag].name,"formatspecifier");

strcpy(b[flag].type,ch);

b[flag].sno = flag + 1;

4
flag++;

flag1=0;

} else if(flag1==4) {

strcpy(b[flag].name,"include file");

strcpy(b[flag].type,ch);

b[flag].sno = flag + 1;

flag++;

flag1=0;

} else {

if(flag2 == 10 ) {

strcpy(b[flag].scope,"local");

}else{

strcpy(b[flag].scope,"global");

flag2 = 0;

if(flag3 >= 0) {

if(strcmp(keywrd[flag3],"int")==0) {

strcpy(b[flag].dt,keywrd[flag3]);

b[flag].size = sizeof(int);

else if(strcmp(keywrd[flag3],"float")==0) {

strcpy(b[flag].dt,keywrd[flag3]);

b[flag].size = sizeof(float);

else if(strcmp(keywrd[flag3],"char")==0) {

strcpy(b[flag].dt,keywrd[flag3]);

b[flag].size = sizeof(ch);

5
} else if(strcmp(keywrd[flag3],"long")==0) {

strcpy(b[flag].dt,keywrd[flag3]);

b[flag].size = sizeof(long);

else {

strcpy(b[flag].name,"identifier");

strcpy(b[flag].type,ch);

b[flag].sno = flag + 1;

flag++;

ch = strtok(NULL," ,;(){}<>#");

printf("sno type name scope data types size\n");

int j=0;

for(i=0;i<flag;i++) {

if(strcmp(b[i].name,"identifier")==0) {

j++;

printf("%d\t%s\t\t%s\t\t%s\t\t%s\t\t%d\n",j,b[i].name,b[i].type,b[i].scope,b[i].dt,b[i].size);

} }

return 0;}

6
OUTPUT:
[student@localhost ~]$catsum.c

#include<stdio.h>
#include<stdio.h>
int main()
{
int a,b;
sum = 0;
scanf(“%d%d\n”,a,b);
sum = a+b;
printf(“SUM : %d\n”,sum);
}

[student@localhost ~]$ cc symtab.c

[student@localhost ~]$ ./a.out

sno type name scope data types size

1 identifier sum local int 4

2 identifier a local int 4

3 identifier b local int 4

7
Ex.No:

LEXICAL ANALYZER USING C


Aim:
To write a C program to implement Lexical Analyzer to identify the patterns like
identifiers, keywords, comments, operators and constants.
Description:
The first step of a compiler is lexical analysis. It is the process of converting a sequence
of characters into a sequence of tokens separated by white spaces and punctuation. A program
that performs lexical analysis is calledlexical analyzer.
Algorithm:
1. Read the source program from the file.
2. Read and Separate a token using delimiter (whitespace or semicolon).
3. Check the token
a. If the token starts with “\\” then display the entire line as COMMENTS
b. If the token starts with “/*” then display the lines until “*/” as COMMENTS
c. If the token starts with “#” then display that as PREPROCESSOR DIRECTIVE
d. If the token is any keyword like int, if, else, etc.. display that as KEYWORD
e. If the token is operator (+,-,*, etc..) then display that as OPERATOR.
f. If the token (,),{,} then display that as Special Symbol.
g. If the token is numbers between 0 and 9 then display that as CONSTANT.
h. Else check whether token starts with alphabet or ‘-‘. If so display that as
identifier. Else print invalid identifier.
4. Write the output in a file.

8
SOURCE CODE

#include<stdio.h>

struct table{

intsno;

char name[100];

char type[100];

char scope[20];

chardt[20];

int size;

};

void strip(char *s) {

char *p2 = s;

while(*s != '\0') {

if(*s != '\t' && *s != '\n' && *s != '&' && *s != '"') {

*p2++ = *s++;

} else {

++s;

*p2 = '\0';

int main(){

FILE *fp;

struct table b[100];

inti,flag=0,flag1=0,flag2=0,flag3=-1;

charstr[100][100];

char *ch;

9
char keywrd[10][100]={"int","float","double","char","long","include","return","printf",

"scanf","main"};

charincfile[3][100]={"stdio.h","conio.h","string.h"};

charfrmatespec[5][5]={"%d","%s","%c","%f","%d%d"};

fp = fopen("sum.c","r");

while(!feof(fp)) {

fread(str,sizeof(str),1,fp);

ch = strtok(str," ,;(){}<>#");

while(ch != NULL) {

strip(ch);

if(strcmp(ch,"main")==0) {

flag2 = 10;

for(i=0;i<10;i++) {

if(strcmp(ch,keywrd[i])==0) {

flag1 = 1;

flag3 = i;

for(i=0;i<10;i++) {

if(strcmp(ch,"+")==0 || strcmp(ch,"*")==0 || strcmp(ch,"/")==0 || strcmp(ch,"-")==0 ||


strcmp(ch,"=")==0 || strcmp(ch,"%")==0 || strcmp(ch,"&")==0) {

flag1 = 2;

for(i=0;i<5;i++) {

if(strcmp(ch,frmatespec[i])==0) {

10
flag1 = 3;

for(i=0;i<3;i++) {

if(strcmp(ch,incfile[i])==0)

flag1 = 4;

if(flag1==1) {

strcpy(b[flag].name,"keyword");

strcpy(b[flag].type,ch);

b[flag].sno = flag + 1;

flag++;

flag1=0;

} else if(flag1==2) {

strcpy(b[flag].name,"operators");

strcpy(b[flag].type,ch);

b[flag].sno = flag + 1;

flag++;

flag1=0;

} else if(flag1==3) {

strcpy(b[flag].name,"formatspecifier");

strcpy(b[flag].type,ch);

b[flag].sno = flag + 1;

flag++;

flag1=0;

} else if(flag1==4) {

strcpy(b[flag].name,"include file");

11
strcpy(b[flag].type,ch);

b[flag].sno = flag + 1;

flag++;

flag1=0;

} else {

if(flag2 == 10 ){

strcpy(b[flag].scope,"local");

}else{

strcpy(b[flag].scope,"global");

flag2 = 0;

if(flag3 >= 0) {

if(strcmp(keywrd[flag3],"int")==0) {

strcpy(b[flag].dt,keywrd[flag3]);

b[flag].size = sizeof(int);

else if(strcmp(keywrd[flag3],"float")==0) {

strcpy(b[flag].dt,keywrd[flag3]);

b[flag].size = sizeof(float);

else if(strcmp(keywrd[flag3],"char")==0) {

strcpy(b[flag].dt,keywrd[flag3]);

b[flag].size = sizeof(ch);

else if(strcmp(keywrd[flag3],"long")==0) {

strcpy(b[flag].dt,keywrd[flag3]);

b[flag].size = sizeof(long);

12
} else {

strcpy(b[flag].name,"identifier");

strcpy(b[flag].type,ch);

b[flag].sno = flag + 1;

flag++;

ch = strtok(NULL," ,;(){}<>#");

printf("sno type name\n");

for(i=0;i<flag;i++) {

printf("%d\t%s\t\t%s\n",i+1,b[i].name,b[i].type);

return 0;

OUTPUT:

#include<stdio.h>
int main()
{
int a,b;
sum = 0;
scanf(“%d%d\n”,a,b);
sum = a+b;
printf(“SUM : %d\n”,sum);
}
[student@localhost ~]$ cc toksep.c

[student@localhost ~]$ ./a.out

13
sno type name

1 keyword include

2 include file stdio.h

3 keyword int

4 keyword main

5 identifier

6 keyword int

7 identifier sum

8 identifier a

9 identifier b

10 keyword scanf

11 format specifier %d%d

12 identifier a

13 identifier b

14 identifier sum

15 operators =

16 identifier a

17 operators +

18 identifier b

19 keyword printf

20 identifier Sum

21 operators =

22 format specifier %d

23 identifier sum

14
Ex.No:
LEXICAL ANALYZER USING Lex Tool
Aim:
To write a lex program to implement Lexical Analyzer to identify the patterns like
identifiers, keywords, comments, operators and constants.

Description:
Lex is a software tool used for writing Lexical Analyzers. Lex source is a
specification of tokens in the form of a list of regular expressions together with an action for
each regular expression. The action pass an indication of the token found to the parser and
makes an entry in the symbol table. The Output program generated by the LEX compiler is
the finite automata.
+-------+
Source | Lex | yylex
Input  | yylex |  Output
+-------+
The general format of Lex source is:
{definitions}
%%
{rules}
%%
{user subroutines}
where the definitions and the user subroutines are often omitted. The second %% is optional,
but the first is required to mark the beginning of the rules. The absolute minimum Lex
program is thus
%%

15
SOURCE CODE
%option noyywrap
%{
#include<stdio.h>
%}
KEYWORD "int"|"char"|"float"|"double"
IDENTIFIER [a-z|A-z][0-9|a-z|A-Z]*
CONSTANT [0-9]*[.]?[0-9]*
OPERATOR [+|-|*|%|/]
%%
{KEYWORD} printf("The keyword %s\n",yytext);
{IDENTIFIER} printf("The Identifier %s",yytext);
{CONSTANT} printf("The Constant %s",yytext);
{OPERATOR} printf("The operator %s",yytext);
. printf("Other : %s\n",yytext);
%%
main()
{
yylex();
}

16
OUTPUT
[student@localhost ]$ lex lexnew.l
[student@localhost ]$ cc lex.yy.c
[student@localhost]$ ./a.out
count3
The Identifier count3
345.9
The Constant 345.9
=
Other : =

+
The operator +
float
The keyword float

[student@localhost]$

17
Ex.No:

YACC Programs
Aim:
To write a YACC program
i. to recognize a valid arithmetic expression that usesoperator +, - , * and /.
ii. to recognize a valid variable which starts with a letterfollowed by any
number of letters or digits
iii. Implementation of Calculator using LEX and YACC

Description:
YACC – yet another compiler–compiler converts a context–free grammar and translation
code into a set of tables for an LR (1) parser and translator. The grammar may be ambiguous;
specified precedence rules are used to break ambiguities.

Structure of Source Program

declarations
%%
rules
%%
routines

 The declaration section may be empty. Moreover, if the routines section is omitted,
the second %% mark may be omitted also.

The declarations section may contain the following items.

 Declarations of tokens. Yacc requires token names to be declared as such using the
keyword %token.
 Declaration of the start symbol using the keyword %start
 C declarations: included files, global variables, types.
 C code between %{ and %}.

18
yyparse() calls yylex() when it needs a new token.

LEX YACC
return(TOKEN) %token TOKEN
TOKEN is used in production

Extern variable yylvalis used in a LEX source program to return values of lexemes

19
SOURCE CODE
1. To recognize a valid arithmetic expression that usesoperator +, - , * and /.
exp.l:
====

%{

#include "y.tab.h"

%}

%%

[0-9]+ { return NUMBER;}

[a-zA-Z][a-zA-Z0-9]* {return ID;}

\n {return NL;}

. {returnyytext[0];}

%%

intyywrap()

{return 1;

exp.y
======
%token NUMBER ID NL

%left '+''-'

%left '*''/'

%%

stmt:E NL {printf("valid \n"); exit


(0);}
;

E:E'+'E
|E'-'E
|E'*'E
|E'/'E
|'('E')'

20
|ID
|NUMBER
;
%%
intyyerror(char *msg)
{
printf(“Invalid\n%s",msg);
exit(0);
}

main()
{
yyparse();
}

OUTPUT

[student@localhost 201301084]$ yacc -d exp.y

[student@localhost 201301084]$ cc lex.yy.c y.tab.c

[student@localhost 201301084]$ ./a.out

8+9

valid[student@localhost 201301084]$ ./a.out

89+

invalidsyntax error

[student@localhost 201301084]$

21
2. To recognize a valid variable which starts with a letterfollowed by any number of letters or
digits
%{

#include<stdio.h>

#include<ctype.h>

#include<stdlib.h>

%}

%token let dig

%%

sad: let recld '\n' {printf("accepted\n"); exit(0);}

| let '\n' {printf("accepted\n"); exit(0);}

|error {yyerror("rejected\n");exit(0);}

recld: let recld

| dig recld

| let

| dig

%%

yylex(){

char ch;

while((ch=getchar())==' ');

if(isalpha(ch))

return let;

if(isdigit(ch))

return dig;

22
return ch;

yyerror(char *s){

printf("%s\n",s);

exit(0);

main(){

printf("ENTER A variable : ");

yyparse();

OUTPUT

[student@localhost]$ yacc valid.y

[student@localhost]$ cc y.tab.c

[student@localhost]$ ./a.out

ENTER A variable : count5

accepted

[student@localhost]$ ./a.out

ENTER A variable : 5count

syntax error

[student@localhost 201301084]$

23
3. Implementation of Calculator using LEX and YACC

calc.l:
=====
%{
#include "y.tab.h"
externintyylval;
%}

%%

[0-9]+ { yylval=atoi(yytext);return NUMBER;}

[a-zA-Z][a-zA-Z0-9]* {return ID;}

\n {return NL;}

. {returnyytext[0];}

%%

intyywrap()
{
return 1;
}

calc.y:
=====

%{
#include <stdio.h>
%}
%token NUMBER ID NL
%left '+''-'
%left '*''/'

%%

stmt : E NL { printf("valid=%d\n",$1); exit(0); }


;
E : E '+' E { $$=$1+$3; }

| E '-' E { $$=$1-$3; }

| E '*' E { $$=$1*$3; }

| E '/' E { $$=$1/$3; }

| '(' E ')' { $$=$2; }

24
| ID { $$=$1; }

| NUMBER { $$=$1; }

%%

intyyerror(char *msg)
{
printf("invalid%s\n",msg);
exit(0);
}
main()
{
yyparse();
}

OUTPUT

[student@localhost]$ lex calc.l

[student@localhost]$ yacc -d calc.y

[student@localhost]$ cc lex.yy.c y.tab.c

[student@localhost]$ ./a.out

6+7*2

valid=20

[student@localhost 201301084]$

25
Ex.No:5
ABSTRACT SYNTAX TREE
Aim:
To write a program to Convert the BNF rules into Yacc form and write code to generate
Abstract Syntax Tree

Description

An abstract syntax tree (AST), or just syntax tree, is a tree representation of the abstract
syntactic structure of source code written in a programming language. Each node of the tree
denotes a construct occurring in the source code. The syntax is "abstract" in not representing
every detail appearing in the real syntax. For instance, grouping parentheses are implicit in the
tree structure, and a syntactic construct like an if-condition-then expression may be denoted by
means of a single node with three branches. Abstract syntax trees are also used in program
analysis and program transformation systems.

26
SOURCE CODE

ast.l:
======
%{
#include "y.tab.h"
externintyylval;
%}

%%

[0-9]+ {yylval = (int)yytext; return NUMBER;}


[ \t\n] ;
"+" return(PLUS);
"-" return(MINUS);
"*" return(TIMES);
"(" return(LEFT_PARENTHESIS);
")" return(RIGHT_PARENTHESIS);

";" return(END);
%%
intyywrap ( ) {
return 1;
}

ast.y:
======

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedefstruct node{
struct node *left;
struct node *right;
char *token;
} node;
node *mknode(node *left, node *right, char *token);
voidprinttree(node *tree);
#define YYSTYPE struct node *
%}

%start lines
%token NUMBER PLUS MINUS TIMES LEFT_PARENTHESIS
RIGHT_PARENTHESIS END
%left PLUS MINUS
%left TIMES

%%

27
lines: /* empty */
| lines line /* do nothing */

line: exp END { printtree($1); printf("\n");}


;

exp : term {$$ = $1;}


| exp PLUS term {$$ = mknode($1, $3, "+");}
| exp MINUS term {$$ = mknode($1, $3, "-");}
;

term : factor {$$ = $1;}


| term TIMES factor {$$ = mknode($1, $3, "*");}
;

factor : NUMBER {$$ = mknode(0,0,(char *)yylval);}


| LEFT_PARENTHESIS exp RIGHT_PARENTHESIS {$$ = $2;}
;

%%

int main (){


returnyyparse ( );
}

node *mknode(node *left, node *right, char *token){

node *newnode = (node *)malloc(sizeof(node));


char *newstr = (char *)malloc(strlen(token)+1);

strcpy(newstr, token);
newnode->left = left;
newnode->right = right;
newnode->token = newstr;
return(newnode);
}
voidprinttree(node *tree){

inti;
if (tree->left || tree->right)
printf("(");
printf(" %s ", tree->token);
if (tree->left)
printtree(tree->left);
if (tree->right)
printtree(tree->right);
if (tree->left || tree->right)
printf(")");
}
intyyerror (char *s)

28
{
fprintf (stderr, "%s\n", s);
}

OUTPUT
[student@localhost]$ lex ast.l

[student@localhost]$ yacc -d ast.y

[student@localhost]$ cc lex.yy.c y.tab.c

[student@localhost]$ ./a.out

8+9*2

( + 8 ( * 9 2 ))

3+4

(+ 3 4)

[student@localhost]$

29
Ex.No: TYPE CHECKING
Aim:
To write a program to implement type checking
Algorithm:
1. Define symbol table with following attributes <symbol name, type>
2. Get the expression as the input from the user. It should be in the form
Operand1 <operator> Operand2
3. Read the operand1 and retrieve the corresponding Type information from the
symbol table.
4. Read the operand2 and retrieve the corresponding Type information from the
symbol table.
5. If type of both operands are same then print the Type as output
6. Otherwise print “TYPE MISMATCH”

Source Code:
/*TYPE CHECKING*/
#include<stdio.h>
#include<string.h>

struct symtab{
char symname[25];
char type[25];
}symtab;
struct symtab s1[20];
int findtype(char t, int n){
int i;
for(i=0;i<n;i++){
if(s1[i].symname[0]==t)
return i;
}
return 0;
}
void main() {
char s[20];
char flag[20]="//TypeCheck";
double op1,op2,interrslt;
int flag2=0,n,i;
int tr,top1,top2;
FILE *fp1,*fp2;

printf("Enter the number of identifiers : ");


30
scanf("%d",&n);

for(i=0;i<n;i++){
printf("Enter identifier name and its type : ");
scanf("%s",&s1[i].symname);
scanf("%s",&s1[i].type);
}
fp1 = fopen("input.txt","r");
fp2 = fopen("output.txt","w");
fscanf(fp1,"%s",s);
while(!feof(fp1)) {
if(strcmp(s,flag)==0) {
flag2 = 1;
}
if(flag2==1) {
fscanf(fp1,"%s",s);

tr = findtype(s[0],n);
top1 = findtype(s[2],n);
top2 = findtype(s[4],n);

if(strcmp(s1[tr].type,s1[top1].type)==0 &&
strcmp(s1[tr].type,s1[top2].type)==0) {
fprintf(fp2,"/*VALID EXP*/\n");
else
fprintf(fp2,"/*TYPE MISMATCH*/\n");
flag2=0;
}
fprintf(fp2,"%s\n",s);
fscanf(fp1,"%s",s);
}
fclose(fp1);
fclose(fp2);
}

OUTPUT
[student@localhost ~]$ cc typecheck.c
[student@localhost ~]$ ./a.out
Enter the number of identifiers : 4
Enter identifier name and its type : a in
Enter identifier name and its type : b in
Enter identifier name and its type : c in
Enter identifier name and its type : d float
[student@localhost ~]$cat input.txt
#include<stdio.h>
int main()
{
int a,b,c,d;
//TypeCheck

31
a=b+c;
//TypeCheck
b=c+d;
}
[student@localhost ~]$cat Output.txt
#include<stdio.h>
int
main()
{
int
a,b,c,d;
/*VALID EXP*/
a=b+c;
/*TYPE MISMATCH*/
b=c+d;
}

32
Ex.No:
CONTROL FLOW ANALYSIS AND DATA FLOW ANALYSIS
Aim:
To write a program to implement control flow analysis and Data flow Analysis
Description:
Data-flow analysis is a technique for gathering information about the possible set of
values calculated at various points in a computer program. A program's control flow graph
(CFG) is used to determine those parts of a program to which a particular value assigned to a
variable might propagate.
A simple way to perform data-flow analysis of programs is to set up data-flow equations for
each node of the control flow graph and solve them by repeatedly calculating the output from
the input locally at each node until the whole system stabilize.
There are two ways to do data flow analysis. They are,
1. Forward flow analysis
2. Backward flow analysis

Algorithm:

1. Start the program and read the input file.


2. Check the statement.
i) For unconditional statements, the flow of control is sequential
ii) For unconditional branches, goto the block with labels
3. Identify the control flow through goto statements
4. Print the control flow structure identified.
5. Close the input file and end the program

Source Code:

#include<stdio.h>
#include<string.h>
char atEnd(char a[128])
{
return a[strlen(a)-1];
}
void main()
{
FILE* fp1;
char oneword[128],c;
int i=0;
fp1=fopen("sample.txt","r+");

33
if(fp1==NULL)
{
printf("file not found");
return;
}
do
{
c=fscanf(fp1,"%s",oneword);
//printf("%c ",atEnd(oneword));
if(atEnd(oneword)==':')
{
printf("\n %s goes to ",oneword);

do
{ c=fscanf(fp1,"%s",oneword);
if(strcmp("goto",oneword)==0)
{
c=fscanf(fp1,"%s",oneword);
printf(" %s",oneword);
}
}while(c!=EOF&&atEnd(oneword)!=':');
i++;
}
fseek(fp1,-strlen(oneword),SEEK_CUR);
printf("\n");
}while(c!=EOF);
}

Output:

INPUT FILE: sample.txt:


b1:
a = a+1
b=b+a
if b<a
goto b2
else
goto b1
b2:
b--
goto b1

[student@localhost ~]$ ./a.out

b1: goes to b2 b1

b2: goes to b1

34
Ex.No:
STORAGE ALLOCATION STRATEGIES

Aim:
To write a program to implement storage allocation strategies (Heap,Stack,Static)
Description:

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.

35
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.

Algorithm-Static Allocation
1. Assume some starting address(init_addr=1000).
2. Repeat the following steps until all the variables in the declaration sections are
processed
For each variable compute the address using the following formula,
addr=addr+width(variable)
store the variable in the computed address addr.

Source Code:
storage.c
#include<stdio.h>
//#include<conio.h>
void strip(char *s) {
char *p2 = s;
while(*s != '\0') {
if(*s != '\t' && *s != '\n' && *s != '&' && *s != '"') {
*p2++ = *s++;
} else {
++s;
}
}
*p2 = '\0';
}

void main()
{
FILE *fp;
int addr = 1000,flag1=0,flag=0;
char str[100][100];
char *ch;

36
fp = fopen("strg.txt","r");
while(!feof(fp))
{
fread(str,sizeof(str),1,fp);
ch = strtok(str," ;");
while(ch != NULL)
{
strip(ch);
if(strcmp(ch,"int")==0 )
{
flag1 = 1;
flag++;
}
else if(strcmp(ch,"float")==0 )
{
flag1 = 2;
flag++;
}
else if(strcmp(ch,"long")==0)
{
flag1 = 3;
flag++;
}
else if(strcmp(ch,"char")==0 )
{
flag1 = 4;
flag++;
}
else if(strcmp(ch,"double")==0)
{
flag1 = 5;
flag++;
}
else
37
{
if(flag1>0)
{
if(flag1==1)
{
addr+=sizeof(int);
printf("%s %d\n",ch,addr);
}
else if(flag1==2)
{
addr+=sizeof(float);
//printf("%d",sizeof(double));
printf("%s %d\n",ch,addr);
}
else if(flag1==3)
{
addr+=sizeof(long);
printf("%s %d\n",ch,addr);
}
else if(flag1==4)
{
addr+=sizeof(char);
printf("%s %d\n",ch,addr);
}
else if(flag1==5)
{
addr+=sizeof(double);
printf("%s %d\n",ch,addr);
}
}
}
ch = strtok(NULL," ;");
}
}
38
}
strg.txt
int a;
double b;
long c;

Output:

[student@localhost ~]$ cc storage.c


[student@localhost ~]$ ./a.out
a 1004
b 1012
c 1016

39
Ex.No:9

DAG
Aim:
To write a program to implement DAG
Description:
Input : A Basic Block
Output : A DAG for the basic block containing the following information,
1. A label for each node. For leaves the label is an identifier, and for interior nodes, an
operator symbol.
2. For each node a list of attached identifiers ( constants not permitted here).
Method:
1. If node(y) is undefined, create a leaf labeled y, and let node(y) be this node. In case (i),
if node(z) is undefined, create a leaf labeled z and let that leaf be node(z).
2. In case(i) determine if there is a node labeled op, whose left child is node(y) and whose
right child is node(z).
If not, create such node. In either event, let n be the node found or created. In case (ii),
determine whether there is node labeled op, whose lone child is node(y). If not, create
such a node, and let n be the node found or created. In case(ii), let n be node(y).
3. Delete x from the list of attached identifiers for node(x). Append x to the list of attached
identifiers for the node n found in (2) and set node(x) to n.

Source Code:

#include<stdlib.h>
#include<stdio.h>

/* We will implement DAG as Strictly Binary Tree where each node has zero or two children
*/

struct bin_tree
{
char data;
int label;
struct bin_tree *right, *left;
};
typedef struct bin_tree node;

40
/* R is stack for storing registers */
int R[10];
int top;

/* op will be used for opcode name w.r.t. arithmetic operator e.g. ADD for + */
char *op;

/* insertnode() and insert() functions are for adding nodes to tree(DAG) */

void insertnode(node **tree,char val)


{
node *temp = NULL;

if(!(*tree))
{
temp = (node *)malloc(sizeof(node));
temp->left = temp->right = NULL;
temp->data = val;
temp->label=-1;
*tree = temp;
}
}

void insert(node **tree,char val)


{
char l,r;
int numofchildren;

insertnode(tree, val);

printf("\nEnter number of children of %c:",val);


scanf("%d",&numofchildren);

if(numofchildren==2)
{
printf("\nEnter Left Child of %c:",val);
scanf("%s",&l);
insertnode(&(*tree)->left,l);

printf("\nEnter Right Child of %c:",val);


scanf("%s",&r);
insertnode(&(*tree)->right,r);

insert(&(*tree)->left,l);
insert(&(*tree)->right,r);
}
}

/* findleafnodelabel() will find out the label of leaf nodes of tree(DAG) */

41
void findleafnodelabel(node *tree,int val)
{

if(tree->left != NULL && tree->right !=NULL)


{
findleafnodelabel(tree->left,1);
findleafnodelabel(tree->right,0);
}

else
{
tree->label=val;
}
}

/* findinteriornodelabel() will find out the label of interior nodes of tree(DAG) */

void findinteriornodelabel(node *tree)


{
if(tree->left->label==-1)
{
findinteriornodelabel(tree->left);
}
else if(tree->right->label==-1)
{
findinteriornodelabel(tree->right);
}
else
{
if(tree->left != NULL && tree->right !=NULL)
{

if(tree->left->label == tree->right->label)
{

tree->label=(tree->left->label)+1;
}
else
{

if(tree->left->label > tree->right->label)


{
tree->label=tree->left->label;
}
else
{
tree->label=tree->right->label;
}
}
}

42
}
}

/* function print_inorder() will print inorder of nodes. Here we are also printing label of each
node of tree(DAG) */

void print_inorder(node * tree)


{
if (tree)
{
print_inorder(tree->left);
printf("%c with Label %d\n",tree->data,tree->label);
print_inorder(tree->right);
}
}
/* function swap() will swap the top and second top elements of Register stack R */

void swap()
{
int temp;
temp=R[0];
R[0]=R[1];
R[1]=temp;
}

/* function pop() will remove and return topmost element of stack */

int pop()
{
int temp=R[top];
top--;
return temp;
}

/* function push() will increment top by one and will insert element at top position of
Register stack */

void push(int temp)


{
top++;
R[top]=temp;
}

/* nameofoperation() will return opcode w.r.t. arithmetic operator */

char* nameofoperation(char temp)


{
switch(temp)
{
case '+': return "ADD"; break;

43
case '-': return "SUB"; break;
case '*': return "MUL"; break;
case '/': return "DIV"; break;
}
}

/* gencode() will generate Assembly code w.r.t. labels of tree(DAG) */

void gencode(node * tree)


{
if(tree->left != NULL && tree->right != NULL)
{
if(tree->left->label == 1 && tree->right->label == 0 && tree->left->left==NULL && tree-
>left->right==NULL && tree->right->left==NULL && tree->right->right==NULL)
{
printf("MOV %c,R[%d]\n",tree->left->data,R[top]);
op=nameofoperation(tree->data);
printf("%s %c,R[%d]\n",op,tree->right->data,R[top]);
}
else if(tree->left->label >= 1 && tree->right->label == 0)
{
gencode(tree->left);
op=nameofoperation(tree->data);
printf("%s %c,R[%d]\n",op,tree->right->data,R[top]);
}
else if(tree->left->label < tree->right->label)
{
int temp;
swap();
gencode(tree->right);
temp=pop();
gencode(tree->left);
push(temp);
swap();
op=nameofoperation(tree->data);
printf("%s R[%d],R[%d]\n",op,R[top-1],R[top]);
}
else if(tree->left->label >= tree->right->label)
{
int temp;
gencode(tree->left);
temp=pop();
gencode(tree->right);
push(temp);
op=nameofoperation(tree->data);
printf("%s R[%d],R[%d]\n",op,R[top-1],R[top]);
}
}
else if(tree->left == NULL && tree->right == NULL && tree->label == 1)
{

44
printf("MOV %c,R[%d]\n",tree->data,R[top]);
}
}

/* deltree() will free the memory allocated for tree(DAG) */

void deltree(node * tree)


{
if (tree)
{
deltree(tree->left);
deltree(tree->right);
free(tree);
}
}

/* Program execution will start from main() function */

void main()
{
node *root;
root = NULL;
node *tmp;
char val;
int i,temp;

/* Inserting nodes into tree(DAG) */

printf("\nEnter root of tree:");


scanf("%c",&val);

insert(&root,val);

/* Finding Labels of Leaf nodes */


findleafnodelabel(root,1);

/* Finding Labels of Interior nodes */


while(root->label == -1)
findinteriornodelabel(root);

/* value of top = index of topmost element of stack R = label of Root of tree(DAG) minus
one */
top=root->label - 1;

/* Allocating Stack Registers */


temp=top;
for(i=0;i<=top;i++)
{
R[i]=temp;
temp--;

45
}

/* Printing inorder of nodes of tree(DAG) */


printf("\nInorder Display:\n");
print_inorder(root);

/* Printing assembly code w.r.t. labels of tree(DAG) */


printf("\nAssembly Code:\n");
gencode(root);

/* Deleting all nodes of tree */


deltree(root);
}
Output:

[student@localhost ~]$ ./a.out


Enter root of tree:+
Enter number of children of +:2
Enter Left Child of +:*
Enter Right Child of +:b
Enter number of children of :2
Enter Left Child of :a
Enter Right Child of :c
Enter number of children of :0
Enter number of children of c:0

Enter number of children of b:


0

Inorder Display:
a with Label 1
* with Label 1
c with Label 0
+ with Label 1
b with Label 0

Assembly Code:
MOV a,R[0]
MUL c,R[0]
ADD b,R[0]

46
Ex.No:10

CODE GENERATION
Aim:
To implement the back end of the compiler, this takes the three address code and
produces assembly language instructions.
Description:
GETREG function:
The GETREG function returns the location L to hold the value of A for the assignment
A = B op C
1. If the name B is in a register that holds the value of no other names and B has no next
use and not live after the computation A = B op C, then return the registers of B for L.
Update the address descriptor of B as “B is no longer in L”
2. Failing step (1), return an empty register for L if there is one.
3. Failing step (2), if A has a next-use in the block, or op is an operator such as indexing
that requires register to perform the operation, then find an occupied register R. Store
the value of R into a memory location if it is not already in the proper memory location
M. Update the address descriptor for M and return R.
4. If A is not used in the block, select the memory location of A as L.

Algorithm:
For each three address code A = B op C in the given basic block, do the following
1. Invoke the function GETREG () to determine the location L where the computation
B op C should be performed. L may be either register or memory location
2. Consult the address descriptor for B to determine B. Prefer register for B’, if the
value of B is currently in memory and in register. If the value of B is not in L,
generate the instruction MOV B,L to place a copy of B in L
3. Generate the instruction OP C , L where C is the current location of C. Update the
address descriptor of A to “ A in L”. If L is a register, update its descriptor to “L
contains A”

47
4. If the current values of B and/or C have no next uses or not live on exit from the
block and are in registers, then update the register descriptors that, those registers
no longer will contain B and/or C.
Source Code

#include<stdio.h>

#include<string.h>

#include<ctype.h>

typedef struct

char var[10];

int alive;

regist;

regist preg[10];

void substring(char exp[],int st,int end)

int i,j=0;

char dup[10]="";

for(i=st;i<end;i++)

dup[j++]=exp[i];

dup[j]='0';

strcpy(exp,dup);

int getregister(char var[])

int i;

for(i=0;i<10;i++)
48
{

if(preg[i].alive==0)

strcpy(preg[i].var,var);

break;

return(i);

void getvar(char exp[],char v[])

int i,j=0;

char var[10]="";

for(i=0;exp[i]!='\0';i++)

if(isalpha(exp[i]))

var[j++]=exp[i];

else

break;

strcpy(v,var);

void main()

char basic[10][10],var[10][10],fstr[10],op;

int i,j,k,reg,vc,flag=0;

printf("\nEnter the Three Address Code:\n");

for(i=0;;i++)

49
gets(basic[i]);

if(strcmp(basic[i],"exit")==0)

break;

printf("\nThe Equivalent Assembly Code is:\n");

for(j=0;j<i;j++)

getvar(basic[j],var[vc++]);

strcpy(fstr,var[vc-1]);

substring(basic[j],strlen(var[vc-1])+1,strlen(basic[j]));

getvar(basic[j],var[vc++]);

reg=getregister(var[vc-1]);

if(preg[reg].alive==0)

printf("\nMov R%d,%s",reg,var[vc-1]);

preg[reg].alive=1;

op=basic[j][strlen(var[vc-1])];

substring(basic[j],strlen(var[vc-1])+1,strlen(basic[j]));

getvar(basic[j],var[vc++]);

switch(op)

case '+': printf("\nAdd"); break;

case '-': printf("\nSub"); break;

case '*': printf("\nMul"); break;

case '/': printf("\nDiv"); break;

50
flag=1;

for(k=0;k<=reg;k++)

if(strcmp(preg[k].var,var[vc-1])==0)

printf("R%d, R%d",k,reg);

preg[k].alive=0;

flag=0;

break;

if(flag)

printf(" %s,R%d",var[vc-1],reg);

printf("\nMov %s,R%d",fstr,reg);

strcpy(preg[reg].var,var[vc-3]);

Output:

Enter the Three Address Code:

a=b+c

a=b-c

c=a*b

exit

The Equivalent Assembly Code is:

51
Mov R0,b

Add c,R0

Mov a,R0

Mov R1,b

Sub c,R1

Mov a,R1

Mov R2,a

Mul b,R2

Mov c,R2

52
Ex.No:11

CODE OPTIMIZATION
Aim:
To write a C program to implement Constant Folding (Code optimization Technique).
Description:
Constant folding is the process of recognizing and evaluating constant expressions
at compile time rather than computing them at runtime. This improves the run-time
performance and reduces the code size by avoiding evaluation at compile-time.

/*CODE OPTIMIZATION - CONSTANT FOLDING*/


#include<stdio.h>
#include<string.h>
void main() {
char s[20];
char flag[20]="//Constant";
char result,equal,operator;
double op1,op2,interrslt;
int a,flag2=0;
FILE *fp1,*fp2;

fp1 = fopen("input.txt","r");
fp2 = fopen("output.txt","w");

fscanf(fp1,"%s",s);
while(!feof(fp1)) {
if(strcmp(s,flag)==0) {
flag2 = 1;
}
if(flag2==1) {
fscanf(fp1,"%s",s);
result=s[0];
equal=s[1];
if(isdigit(s[2])&& isdigit(s[4])) {
if(s[3]=='+'||'-'||'*'||'/') {
operator=s[3];
switch(operator) {
case '+':
interrslt=(s[2]-48)+(s[4]-48);
break;
case '-':
interrslt=(s[2]-48)-(s[4]-48);

53
break;
case '*':
interrslt=(s[2]-48)*(s[4]-48);
break;
case '/':
interrslt=(s[2]-48)/(s[4]-48);
break;
default:
interrslt = 0;
break;
}
fprintf(fp2,"/*Constant Folding*/\n");
fprintf(fp2,"%c = %lf\n",result,interrslt);
flag2 = 0;
}
} else {
fprintf(fp2,"Not Optimized\n");
fprintf(fp2,"%s\n",s);
}
} else {
fprintf(fp2,"%s\n",s);
}
fscanf(fp1,"%s",s);
}
fclose(fp1);
fclose(fp2);
}

OUTPUT
[student@localhost ~]$ cc codeopt.c
[student@localhost ~]$ ./a.out
[student@localhost ~]$cat input.txt
#include<stdio.h>
int main()
{
//Constant
a=2+4;
b=a+10;
}
[student@localhost ~]$cat Output.txt
#include<stdio.h>
int
main()
{
/*Constant Folding*/
a = 6.000000
b=a+10;
}

54

Вам также может понравиться