CS3501-Compiler Design Manual

You might also like

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 71

CS3501 – Compiler Design

LIST OF EXPERIMENTS:
1. Using the LEX tool, Develop a lexical analyzer to recognize a few patterns in C. (Ex.
identifiers, constants, comments, operators etc.). Create a symbol table, while recognizing
identifiers.
2. Implement a Lexical Analyzer using LEX Tool
3. Generate YACC specification for a few syntactic categories.
a. Program to recognize a valid arithmetic expression that uses operator +, -, * and /.
b. Program to recognize a valid variable which starts with a letter followed by any
number
of letters or digits.
c. Program to recognize a valid control structures syntax of C language (For loop, while
loop, if-else, if-else-if, switch-case, etc.).
d. Implementation of calculator using LEX and YACC
4. Generate three address code for a simple program using LEX and YACC.
5. Implement type checking using Lex and Yacc.
6. Implement simple code optimization techniques (Constant folding, Strength reduction and
Algebraic transformation)
7. Implement back-end of the compiler for which the three-address code is given as input
and
the 8086-assembly language code is produced as output.
EX. NO: 1
DATE:
IMPLEMENTATION OF SYMBOL TABLE
AIM:
To write a C program to implement a symbol table.
INTRODUCTION:
A Symbol table is a data structure used by a language translator such as a compiler or
interpreter, where each identifier in a program’s source code is associated with information
relating to its declaration or appearance in the source Possible entries in a symbol table:

▪ Name : a string

▪ Attribute:

● Reserved word

● Variable name

● Type Name

● Procedure name

● Constant name

▪ Data type

▪ Scope information: where it can be used.

▪ Storage allocation

SYMBOL TABLE
ALGORITHM:
1. Start the Program.
2. Get the input from the user with the terminating symbol ‘$’.
3. Allocate memory for the variable by dynamic memory allocation function.
4. If the next character of the symbol is an operator, then only the memory is
allocated.
5. While reading, the input symbol is inserted into symbol table along with its
memory address.
6. The steps are repeated till”$”is reached.
7. To reach a variable, enter the variable to the searched and symbol table has been
checked for corresponding variable, the variable along its address is displayed as
result.
8. Stop the program.
PROGRAM: (IMPLEMENTATION OF SYMBOL TABLE)
# include <stdio.h>
# include <conio.h>
# include <alloc.h>
# include <string.h>
# define null 0
int size=0;
void insert();
void del();
int search(char lab[]);
void modify();
void display();
struct symbtab
{
char label[10];
int addr;
struct symtab *next;
};
struct symbtab *first,*last;
void main()
{
int op;
int y;
char la[10];
clrscr();
do
{
printf("\nSYMBOL TABLE IMPLEMENTATION\n");
printf("1. INSERT\n");
printf("2. DISPLAY\n");
printf("3. DELETE\n");
printf("4. SEARCH\n");
printf("5. MODIFY\n");
printf("6. END\n");
printf("Enter your option : ");
scanf("%d",&op);
switch(op)
{
case 1: insert();
display();
break;
case 2: display();
break;
case 3:del();
display();
break;
case 4: printf("Enter the label to be searched : ");
scanf("%s",la);
y=search(la);
if(y==1)
{ printf("The label is already in the symbol Table");
}
else
{ printf("The label is not found in the symbol table");
}
break;
case 5: modify();
display();
break;
case 6:
break;
}
}
while(op<6);
getch();
}
void insert()
{
int n;
char l[10];
printf("Enter the label : ");
scanf("%s",l);
n=search(l);
if(n==1)
{ printf("The label already exists. Duplicate cant be inserted\n");
}
else
{ struct symbtab *p;
p=malloc(sizeof(struct symbtab));
strcpy(p->label,l);
printf("Enter the address : ");
scanf("%d",&p->addr);
p->next=null;
if(size==0)
{ first=p;
last=p;
}
else
{ last->next=p;
last=p;
}
size++;
}}
void display()
{ int i;
struct symbtab *p;
p=first;
printf("LABEL\tADDRESS\n");
for(i=0;i<size;i++)
{ printf("%s\t%d\n",p->label,p->addr);
p=p->next;
}}
int search(char lab[])
{
int i,flag=0;
struct symbtab *p;
p=first;
for(i=0;i<size;i++)
{ if(strcmp(p->label,lab)==0)
{ flag=1;
}
p=p->next;
}
return flag;
}
void modify()
{
char l[10],nl[10];
int add, choice, i, s;
struct symbtab *p;
p=first;
printf("What do you want to modify?\n");
printf("1. Only the label\n");
printf("2. Only the address of a particular label\n");
printf("3. Both the label and address\n");
printf("Enter your choice : ");
scanf("%d",&choice);
switch(choice)
{
case 1: printf("Enter the old label\n");
scanf("%s",l);
printf("Enter the new label\n");
scanf("%s",nl);
s=search(l);
if(s==0)
{ printf("NO such label"); }
else
{ for(i=0;i<size;i++)
{ if(strcmp(p->label,l)==0)
{ strcpy(p->label,nl); }
p=p->next;
}}
break;
case 2: printf("Enter the label whose address is to modified\n");
scanf("%s",l);
printf("Enter the new address\n");
scanf("%d",&add);
s=search(l);
if(s==0)
{ printf("NO such label");
}
else
{ for(i=0;i<size;i++)
{ if(strcmp(p->label,l)==0)
{ p->addr=add; }
p=p->next;
}}
break;
case 3: printf("Enter the old label : ");
scanf("%s",l);
printf("Enter the new label : ");
scanf("%s",nl);
printf("Enter the new address : ");
scanf("%d",&add);
s=search(l);
if(s==0)
{ printf("NO such label");
}
else
{ for(i=0;i<size;i++)
{
if(strcmp(p->label,l)==0)
{ strcpy(p->label,nl);
p->addr=add;
}
p=p->next;
}}
break;
}}
void del()
{
int a;
char l[10];
struct symbtab *p,*q;
p=first;
printf("Enter the label to be deleted\n");
scanf("%s",l);
a=search(l);
if(a==0)
{ printf("Label not found\n");
}
else
{ if(strcmp(first->label,l)==0)
{ first=first->next;
}
else if(strcmp(last->label,l)==0)
{ q=p->next;
while(strcmp(q->label,l)!=0)
{ p=p->next;
q=q->next;
}
p->next=null;
last=p;
}
else
{ q=p->next;
while(strcmp(q->label,l)!=0)
{ p=p->next;
q=q->next;
}
p->next=q->next;
}
size--;
}}

OUTPUT:
SYMBOL TABLE IMPLEMENTATION
1.INSERT
2.DISPLAY
3.DELETE
4.SEARCH
5.MODIFY
6.END

Enter your option:1


Enter the label: A
Enter the address: 10
LABEL ADDRESS
A 10

SYMBOL TABLE IMPLEMENTATION


1.INSERT
2.DISPLAY
3.DELETE
4.SEARCH
5.MODIFY
6.END

Enter your option:1


Enter the label: B
Enter the address: 11
LABEL ADDRESS
A 10
B 11

SYMBOL TABLE IMPLEMENTATION


1.INSERT
2.DISPLAY
3.DELETE
4.SEARCH
5.MODIFY
6.END

Enter your option:2


LABEL ADDRESS
A 10
B 11

SYMBOL TABLE IMPLEMENTATION


1.INSERT
2.DISPLAY
3.DELETE
4.SEARCH
5.MODIFY
6.END

Enter your option:3


Enter the label to be deleted: A
LABEL ADDRESS
B 11

SYMBOL TABLE IMPLEMENTATION


1.INSERT
2.DISPLAY
3.DELETE
4.SEARCH
5.MODIFY
6.END

Enter your option:4


Enter the label to be searched: A
The label is not found in the symbol table.

SYMBOL TABLE IMPLEMENTATION


1.INSERT
2.DISPLAY
3.DELETE
4.SEARCH
5.MODIFY
6.END

Enter your option:4


Enter the label to be searched: B
The label is already in the symbol table.

SYMBOL TABLE IMPLEMENTATION


1.INSERT
2.DISPLAY
3.DELETE
4.SEARCH
5.MODIFY
6.END

Enter your option:5


what do you want to modify?
1.only the label
2.only the address of a particular label
3.both the label and address
Enter your choice:1
Enter the old label
B
Enter the new label
A
LABEL ADDRESS
a 11
RESULT:
Thus, the C program to implement the symbol table was executed and the output is
verified.
EX. NO:2
DATE:
DEVELOP A LEXICAL ANALYZER TO RECOGNIZE A FEW 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 of web page) into a sequence of tokens (strings with an identified
“meaning”). A program that perform lexical analysis may be called a lexer, tokenize or scanner.

TOKEN
A token is a structure representing a lexeme that explicitly indicates its categorization
for the Purpose of parsing. A category of token 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 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 the statement

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 key.c
8. Define all the operators in a separate file and name it as open.c
9. Give the input program in a file and name it as input.c
10. Finally print the output after recognizing all the tokens.
11. Stop the program.
PROGRAM: (DEVELOP A LEXICAL ANALYZER TO RECOGNIZE A FEW PATTERNS IN C)
#include<stdio.h>
#include<conio.h>
void main()
{
int i=0,j=0,k,l,t;
char expr1[190],expr[40][10],num[10];
char keyword[12][10] = {"if", "else", "then", "while", "do", "for", "int", "float",
"char",
"long","douoble"};
clrscr();
fflush(stdin);
printf("\nEnter the expression:");
gets(expr1);
while(1)
{ k = 0;
t = expr1[i];
while( (t>96 && t<123) || (t>64 && t<91) || (t>47 && t<58) )
{ expr[j][k] = expr1[i];
i++;
k++;
t = expr1[i];
if(!( (t>96 && t<123) || (t>64 && t<91) || (t>47 && t<58) ))
expr[j++][k] = NULL;
} k=0;
if(t == 42 || t == 43 || t == 45 || t == 47 || t == 61)
{ expr[j][k] = expr1[i];
expr[j++][1] = NULL;
}
if(t == 59)
break;
else if(j > 80 || t == 0)
{ printf("\nStatement Missing.");
exit(0);
getch();
getch();
} i++;
t = expr1[i];
} i = j;
printf("\n\nTotal No. of tokens: %d",j);
printf("\nSigns: ");
for(j=0;j<i;j++)
if(!strcmp(expr[j],"+") || !strcmp(expr[j],"-") || !strcmp(expr[j],"*") || !
strcmp(expr[j],"/") ||
!strcmp(expr[j],";"))
{ printf("%s\t",expr[j]);
for(l=j;l<i;l++)
sprintf(expr[l],"%s",expr[l+1]);
i--;
}
printf("\nAssignment operator: ");
for(j=0;j<i;j++)
if(!strcmp(expr[j],"="))
{
printf("%s\t",expr[j]);
for(l=j;l<i;l++)
sprintf(expr[l],"%s",expr[l+1]);
i--;
}
printf("\nNumbers: ");
for(j=0;j<i;j++)
for(k=0;k<32767;k++)
{
sprintf(num,"%d",k);

if(!strcmp(expr[j],num))
{
printf("%d\t",k);
for(l=j;l<i;l++)
sprintf(expr[l],"%s",expr[l+1]);
j--;
i--;
} }
printf("\nKeywords: ");
for(j=0;j<i;j++)
for(k=0;k<11;k++)

if(!strcmp(expr[j],keyword[k]))
{
printf("%s\t",expr[j]);
for(l=j;l<i;l++)
sprintf(expr[l],"%s",expr[l+1]);
i--;
}
printf("\nIdentifiers: ");
for(j=0;j<i;j++)
printf("%s\t",expr[j]);
getch();
}

OUTPUT:

Enter the expression: if a=10 then b=2+a*5;


Total No. of tokens: 12
Signs: + *
Assignment operator: = =
Numbers: 10 2 5
Keywords: if then
Identifiers: a b a

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:3
DATE:
IMPLEMENTATION OF LEXICAL ANALYZER USING LEX 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.
LEX:
 The lex is used in the manner depicted. A specification of the lexical analyzer is
preferred by creating a program lex.1 in the lex language.
 Then lex.1 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.1 together with a standard routine that
uses 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.
ALGORITHM:
1. Start the program
2. Lex program consists of three parts.
3. Declaration %%
4. Translation rules %%
5. Auxiliary procedure.
6. The declaration section includes declaration of variables, main test, constants
and regular
7. Definitions.
8. Translation rule of lex program are statements of the form
9. P1{action}
10.P2{action}
11.…..
12.…..
13.Pn{action}
14.Write program in the vi editor and save it with .1 extension.
15.Compile the lex program with lex compiler to produce output file as lex.yy.c.
16.Eg. $ lex filename.1
17.$gcc lex.yy.c-11
18.Compile that file with C compiler and verify the output.
PROGRAM: (LEXICAL ANALYZER USING LEX TOOL)
lex.l
digits[0-9]
letters[a-zA-Z]
delimiters[\,\:\;]
relational[\==\!=\<\>\<=\>=]
arithmetic[\+\-\*\/\%]
%{
int line=0;
%}
%%
#.* {printf("\n%s is a preprocessor directive",yytext);}
"/*".*"*/" {printf("\n%s is a comment statement",yytext);}
\".*\" {printf("\n%s is a control string",yytext);}
int|float|char|double|while|for|do|if|break|continue|void|switch|case|long|struct|const|
typedef|return|else|return|goto {printf("\n%s is a keyword",yytext);}
{letters}({letters}|{digits})* {printf("\n %s is a identifier",yytext);}
{digits}+ {printf("\n %s is a number",yytext);}
{delimiters}? {printf("\n %s is a special symbol - delimiters",yytext);}
\{ {printf("\n %s is a opening brace",yytext);}
\} {printf("\n %s is a closing brace",yytext);}
\( {printf("\n %s is a left paranthesis",yytext);}
\) {printf("\n %s is a right paranthesis",yytext);}
{arithmetic}? {printf("\n %s is an arithmetic operators",yytext);}
{relational}? {printf("\n %s is a relational operators",yytext);}
\n {line++;}
%%
int main(int argc,char**argv)
{
yyin=fopen(argv[1],"r");
yylex();
printf("\n\n\n no of lines scanned:%d",line);
fclose(yyin);
return 0;
}
int yywrap()
{
return 0;
}

test.c
main()
{
int a,b,c;
if(a<b)
{
a=a+b;
}
else
{
c=a+b;
}
}
OUTPUT:
C:\GnuWin32\bin> flex lex.l
C:\GnuWin32\bin> gcc lex.yy.c
C:\GnuWin32\bin> a.exe test1.c
main is a identifier
( is a left paranthesis
) is a right paranthesis
{ is a opening brace
int is a keyword
a is a identifier
, is a special symbol - delimiters
b is a identifier
, is a special symbol - delimiters
c is a identifier
; is a special symbol - delimiters

RESULT:
Thus, the program for the exercise on lexical analysis using lex has been successfully
executed and output is verified.
EX.NO:4
DATE:
GENERATE YACC SPECIFICATION FOR A FEW SYNTACTIC CATEGORIES.
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 /.
4a. Program to recognize a valid arithmetic expression that uses operator +, - , *
and /.
prog4.y
%{ #include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
%}
%token num let
%left '+' '-'
%left '*' '/'
%%
Stmt : Stmt '\n' { printf ("\n.. Valid Expression.. \n"); exit(0); }
| expr
| error '\n' { printf ("\n..Invalid ..\n"); exit(0); }
;
expr : num
| let
| expr '+' expr
| expr '-' expr
| expr '*' expr
| expr '/' expr
| '(' expr ')'
;
%%

main ( )
{printf ("Enter an expression to validate : ");
yyparse ( );}
yylex()
{
int ch;
while ( ( ch = getchar() ) == ' ' );
if ( isdigit(ch) )
return num; // return token num
if ( isalpha(ch) )
return let; // return token let
return ch; }

yyerror (char *s)


{
printf ( "%s", s ); }
OUTPUT:

C:\GnuWin32\bin> bison –dy prog4.y

C:\GnuWin32\bin> gcc y.tab.c


C:\GnuWin32\bin> a.exe

Enter an expression to validate: 5+6

. Valid Expression..

C:\GnuWin32\bin> a.exe

Enter an expression to validate: 5++6

syntax error

..Invalid .
Ex.No: 4 a Yacc program to Evaluate an arithmetic expression for operators (+,-,*, / )

eval.y
%{ /* Evaluate simple arithmetic expression */
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#define YYSTYPE double
%}
%token num
%left '+' '-'
%left '*' '/'
%%
Stmt : Stmt '\n' { printf ( "Value is %f \n", $1); exit(0); }
| Expr
|
| error '\n' { printf ("INVALID"); exit(0); }
;
Expr : num { $$ = $1; }
| Expr '+' Expr { $$ = $1 + $3; }
| Expr '-' Expr { $$ = $1 - $3; }
| Expr '*' Expr { $$ = $1 * $3; }
| Expr '/' Expr {
if ( $3 == 0 )
{ printf ( "division by zero \n");
exit (0);
}
else
$$ = $1 / $3;
}
| '(' Expr ')' { $$ = $2; }
;
%%
main ( )
{
printf ( "ENTER AN EXPRESSION TO EVALUATE : \n" );
yyparse ( );
}
yyerror (char *s)
{
printf ( "%s", s );
}
yylex ( )
{
char ch;
while ( (ch = getchar() ) == ' ' ) ;
if ( isdigit(ch) | ch == '.' )
{
ungetc ( ch, stdin );
scanf ( "%lf", &yylval );
return num;
}
return ch;
}

OUTPUT:

C:\GnuWin32\bin>bison -dy eval.y


C:\GnuWin32\bin>gcc y.tab.c
C:\GnuWin32\bin>a.exe
ENTER AN EXPRESSION TO EVALUATE:
4+8
Value is 12.000000
Ex: No: 4b Yacc program to recognize a valid variable, which starts with a letter
followed by any number of digits and letters.
pro.y
%{ #include <stdio.h>
#include <ctype.h>
%}
%token let dig
%%
TERM : XTERM '\n' { printf ( "\nAccepted\n" ); exit(0); }
| error { yyerror ("Rejected\n" ); }
;
XTERM : XTERM let
| XTERM dig
| let
;
%%
yylex()
{
char ch;
while ( ( ch = getchar ( ) ) == ' ' ) ;
if ( isalpha (ch) )
return let;
if ( isdigit (ch) )
return dig;
return ch;
}

main()
{
printf ("Enter a variable : ");
yyparse ();
}
yyerror(char *s)
{
printf ("%s", s);}
OUTPUT:

C:\GnuWin32\bin>bison -dy pro.y


C:\GnuWin32\bin>gcc y.tab.c
C:\GnuWin32\bin>a.exe
Enter a variable: 5hjjkkjd
syntax error Rejected
C:\GnuWin32\bin>a.exe
Enter a variable: number
Accepted
EX. NO: 4 C Implementation of Calculator using LEX and YACC
cal.l
%{
#include<stdio.h>
#include<math.h>
#include "y.tab.h"
%}
%%
[0-9]+ {
yylval.dval=atoi(yytext);
return NUMBER;
}
[t];
n return 0;
. {return yytext[0];}
%%
void yyerror(char *str)
{
printf("\n Invalid Character");
}
int main()
{
printf("Enter Expression => ");
yyparse();
return(0);
}
int yywrap()
{
return 0;
}
cal.y
%{
#include<stdio.h>
int yylex(void);
%}
%union
{
float dval;
}
%token <dval> NUMBER
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS
%type <dval> exp
%%
state : exp {printf("Answer = %f",$1);}
;
exp : NUMBER
| exp '+' exp {$$=$1+$3;}
| exp '-' exp {$$=$1-$3;}
| exp '*' exp {$$=$1*$3;}
| exp '/' exp {$$=$1/$3;}
| '('exp')' {$$=$2;}
| '-' exp %prec UMINUS {$$=-$2;}
;
%%

OUTPUT:
C:\GnuWin32\bin>flex cal.l
C:\GnuWin32\bin>bison -dy cal.y
C:\GnuWin32\bin>gcc lex.yy.c y.tab.c
c:\GnuWin32\bin>a.exe
Enter Expression => 5+6$
Answer = 11.000000

RESULT:
Thus, the program for the exercise on the syntax using YACC has been executed
successfully and Output is verified.
EX.NO:5
DATE:
CONVERT THE BNF RULES INTO YACC FORM AND WRITE CODE TO GENERATE
ABSTRACT SYNTAX TREE USING AND YACC.
AIM:
To write a program to convert the BNF rules into YACC
INTRODUCTION:
BNF-Backus Naur form is formal notation for encoding grammars intended for human
Consumption. Many programming languages, protocol or formats have BNF description in their
Specification.
ALGORITHM:
1. Start the program.
2. Declare the declarations as a header file. {include<ctype.h>}
3. Token digit
4. Define the translations rule 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. Execute and verify it.
7. Stop the program.
PROGRAM: (CONVERT THE BNF RULES INTO YACC)
%{
#include"y.tab.h"
#include<stdio.h>
#include<string.h>
int LineNo=1;
%}
identifier [a-zA-Z][_a-zA-Z0-9]*
number [0-9]+|([0-9]*\.[0-9]+)
%%
main\(\) return MAIN;
if return IF;
else return ELSE;
while return WHILE;
int |
char |
float return TYPE;
{identifier} {strcpy(yylval.var,yytext);
return VAR;}
{number} {strcpy(yylval.var,yytext);
return NUM;}
\< |
\> |
\>= |
\<= |
== {strcpy(yylval.var,yytext);
return RELOP;}
[ \t] ;
\n LineNo++;
. return yytext[0];
%%
int yywrap()
{
return 1;
}
bnf.y
%{
#include<string.h>
#include<stdio.h>
struct quad
{
char op[5];
char arg1[10];
char arg2[10];
char result[10];
}QUAD[30];
struct stack
{
int items[100];
int top;
}stk;
int Index=0,tIndex=0,StNo,Ind,tInd;
extern int LineNo;
void Addquadruple(char op[5],char arg1[10],char arg2[10],char result[10]);
void puss(int data);
int pop();
%}
%union
{
char var[10];
}
%token <var> NUM VAR RELOP
%token MAIN IF ELSE WHILE TYPE
%type <var> EXPR ASSIGNMENT CONDITION IFST ELSEST WHILELOOP
%left '-' '+'
%left '*' '/'
%%
PROGRAM : MAIN BLOCK
;
BLOCK: '{' CODE '}'
;
CODE: BLOCK
| STATEMENT CODE
| STATEMENT
;

STATEMENT: DESCT ';'


| ASSIGNMENT ';'
| CONDST
| WHILEST
;
DESCT: TYPE VARLIST
;
VARLIST: VAR ',' VARLIST
| VAR
;
ASSIGNMENT: VAR '=' EXPR{
strcpy(QUAD[Index].op,"=");
strcpy(QUAD[Index].arg1,$3);
strcpy(QUAD[Index].arg2,"");
strcpy(QUAD[Index].result,$1);
strcpy($$,QUAD[Index++].result);
}
;
EXPR: EXPR '+' EXPR {Addquadruple("+",$1,$3,$$);}
| EXPR '-' EXPR {Addquadruple("-",$1,$3,$$);}
| EXPR '*' EXPR {Addquadruple("*",$1,$3,$$);}
| EXPR '/' EXPR {Addquadruple("/",$1,$3,$$);}
| '-' EXPR {Addquadruple("UMIN",$2,"",$$);}
| '(' EXPR ')' {strcpy($$,$2);}
| VAR
| NUM
;
CONDST: IFST{
Ind=pop();
sprintf(QUAD[Ind].result,"%d",Index);
Ind=pop();
sprintf(QUAD[Ind].result,"%d",Index);
}
| IFST ELSEST
;
IFST: IF '(' CONDITION ')' {
strcpy(QUAD[Index].op,"==");
strcpy(QUAD[Index].arg1,$3);
strcpy(QUAD[Index].arg2,"FALSE");
strcpy(QUAD[Index].result,"-1");
puss(Index);
Index++;
}
BLOCK {
strcpy(QUAD[Index].op,"GOTO");
strcpy(QUAD[Index].arg1,"");
strcpy(QUAD[Index].arg2,"");
strcpy(QUAD[Index].result,"-1");
puss(Index);
Index++;
};
ELSEST: ELSE{
tInd=pop();
Ind=pop();
puss(tInd);
sprintf(QUAD[Ind].result,"%d",Index);
}
BLOCK{
Ind=pop();
sprintf(QUAD[Ind].result,"%d",Index);
};
CONDITION: VAR RELOP VAR {Addquadruple($2,$1,$3,$$);
StNo=Index-1;
}
| VAR
| NUM
;
WHILEST: WHILELOOP{
Ind=pop();
sprintf(QUAD[Ind].result,"%d",StNo);
Ind=pop();
sprintf(QUAD[Ind].result,"%d",Index);
}
;
WHILELOOP: WHILE '(' CONDITION ')' {
strcpy(QUAD[Index].op,"==");
strcpy(QUAD[Index].arg1,$3);
strcpy(QUAD[Index].arg2,"FALSE");
strcpy(QUAD[Index].result,"-1");
puss(Index);
Index++;
}
BLOCK {
strcpy(QUAD[Index].op,"GOTO");
strcpy(QUAD[Index].arg1,"");
strcpy(QUAD[Index].arg2,"");
strcpy(QUAD[Index].result,"-1");
puss(Index);
Index++;
}
;
%%
extern FILE *yyin;
int main(int argc,char *argv[])
{
FILE *fp;
int i;
if(argc>1)
{
fp=fopen(argv[1],"r");
if(!fp)
{
printf("\n File not found");
exit(0);
}
yyin=fp;
}
yyparse();
printf("\n\n\t\t ----------------------------\n\t\t Pos Operator Arg1 Arg2 Result\n\t\
t--------------------");
for(i=0;i<Index;i++)
{
printf("\n\t\t %d\t %s\t %s\t %s\t
%s",i,QUAD[i].op,QUAD[i].arg1,QUAD[i].arg2,QUAD[i].result);
}
printf("\n\t\t -----------------------");
printf("\n\n");
return 0;
}
void puss(int data)
{
stk.top++;
if(stk.top==100)
{
printf("\n Stack overflow\n");
exit(0);
}
stk.items[stk.top]=data;
}

int pop()
{
int data;
if(stk.top==-1)
{
printf("\n Stack underflow\n");
exit(0);
}
data=stk.items[stk.top--];
return data; }
void Addquadruple(char op[5],char arg1[10],char arg2[10],char result[10])
{
strcpy(QUAD[Index].op,op);
strcpy(QUAD[Index].arg1,arg1);
strcpy(QUAD[Index].arg2,arg2);
sprintf(QUAD[Index].result,"t%d",tIndex++);
strcpy(result,QUAD[Index++].result);
}
yyerror()
{
printf("\n Error on line no:%d",LineNo);
}
main()
{
int a,b,c;
if(a<b)
{ a=a+b; }
while(a<b)
{ a=a+b; }
if(a<=b)
{
c=a-b;
}
else
{
c=a+b;
}
}
OUTPUT:
C:\GnuWin32\bin>flex bnf.l
C:\GnuWin32\bin>bison -dy bnf.y
C:\GnuWin32\bin>gcc lex.yy.c y.tab.c
C:\GnuWin32\bin>a.exe test.c
Pos Operator Arg1 Arg2 Result

0 < a b t0
1 == t0 FALSE 5
2 + a b t1
3 = t1 a
4 GOTO 5
5 < a b t2
6 == t2 FALSE 10
7 + a b t3
8 = t3 a
9 GOTO 5
10 <= a b t4
11 == t4 FALSE 15
12 - a b t5
13 = t5 c
14 GOTO 17
15 + a b t6
16 = t6 c

RESULT:
Thus, the program for the exercise on the syntax using YACC has been executed
successfully and output is verified.
EX.NO:6
DATE:
IMPLEMENTATION OF TYPE CHECKING
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
1. To detect the errors arising in the expression due to incompatible operand.
2. To generate intermediate code for expressions due to incompatible operand

Role of type checker

Sourc parse parse


e tree tree
Type Intermediat
parser checker e

progr code
am

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.
PROGRAM: (TYPE CHECKING)
Type.c
#include<stdio.h>
#include<conio.h>
#include<string.h>
struct symbol{
char name[10],type[10];
}s[10];
void main(){
int i=0,k=0,l=0,m=0,flag=0;
char temp[50],temp1[50],t1[50],b[10],c[10],str[50],buf[50];
char *a[10]={"int","float","char","double"};
char *op[10]={"+","-","*","/","<",">"};
FILE *fp;
clrscr();
fp=fopen("sample.c","r");
while(!feof(fp))
{ fscanf(fp,"%s",str);
//printf("%s\n",str);
for(i=0;i<4;i++)
{
if(strcmp(str,a[i])==0)
{
strcpy(s[k].type,str);
fscanf(fp,"%s",buf);
strcpy(s[k].name,buf);
k++;
/*if(buf!=","||buf!=";")
{
strcpy(s[k].name,buf);
k++;
} */
}
}
}
printf("symbol table\n");
for(k=0;k<10;k++)
{ printf("%s\t%s\t\n",s[k].type,s[k].name);
}
fclose(fp);
fp=fopen("sample.c","r");
while(!feof(fp))
{ fscanf(fp,"%s",temp);
//printf("%s\n",temp);
strcpy(t1,temp);
fscanf(fp,"%s",temp);
//printf("%s\n",temp);
//getch();
for(l=0;l<10;l++)
{ if(strcmp(temp,op[l])==0)
{ //printf("\n%s\n",t1);
//printf("%s\n",temp);
fscanf(fp,"%s",temp1);
//printf("%s\n",temp1);
for(m=0;m<10;m++)
{
if(strcmp(t1,s[m].name)==0)
strcpy(b,s[m].type);
if(strcmp(temp1,s[m].name)==0)
strcpy(c,s[m].type);
flag=1;
} }
//printf("\nFlag=%d",flag);
if(flag==1)
{
if(strcmp(b,c)==0)
printf("valid");
else
printf("invalid");
flag=0;
} } }
getch();
}

INPUT:
Sample.c
main ()
{
int a ;
float b ;
if ( a < b )
}
OUTPUT:
invalid

RESULT:
Thus, the program for the implementation of Type Checking has been executed
successfully and Output is verified.
EX.NO:7A
DATE:
IMPLEMENT CONTROL FLOW ANALYSIS
AIM:
To Writs a C program to implement control flow analysis.
INTRODUCTION:
 Control flow analysis can be represent by basic blocks. It depicts how th program
control is being passed among the blocks.
ALGORITHM:
1. Start the program
2. Declare the necessary variables
3. Get the choice to insert, delete and display the values in stack
4. Perform PUSH() operation
t = newnode()
Enter info to be inserted
Read n
t ->info= n
t ->next=top
top = t
Return
5. Perform POP() operation
If (top=NULL)
Print”underflow”
Return
X=top
Top=top->next
Delnode(x)
Return
5. Display the values
6. Stop the program.
PROGRAM: (CONTROL FLOW ANALYSIS)
Controlflow.c
#include<stdio.h>
#include<conio.h>
#include<string.h>
void main()
{
int i,flag,count=0;
char *a[2]={"for","while"}; /* loop keywords */
char c,str[10],temp[10],index[10];
FILE *fp;
clrscr();
fp=fopen("file2.c","r");
do
{
fscanf(fp,"%s",str);
for(i=0;i<2;i++)
{
if(strcmp(str,a[i])==0)
{ fscanf(fp,"%s",temp);
fscanf(fp,"%s",temp);
strcpy(index,temp);
}
}
}while(strcmp(str,"{")!=0);
printf("%s",str);
printf("%s",index);
while(!feof(fp))
{
flag=0;
fscanf(fp,"%s",str);
if(strcmp(str,"}")==0) break;
count++;
do
{
if(strcmp(str,index)==0)
flag++;
fscanf(fp,"%s",str);
}while(strcmp(str,";")!=0);
if(flag!=0)
printf("%d has a variant variable\n",count);
else
printf("%d has a invariant variable\n",count);
}
getch();
}

Input
file2.c
While ( i < 3 )
{ j = i ++ ;
k = 10 ;
}

Output
1 has a variant variable
2 has a invariant variable

RESULT:
Thus, the C program to implement control flow analysis has been executed and verified
successfully.
EX.NO:7B
DATE:
IMPLEMENT DATA FLOW ANALYSIS
AIM:
To Writs a C program to implement data flow analysis.
INTRODUCTION:
 Data flow analysis is a technique for gathering information about the possible set of
value calculated at various points in a computer program.
ALGORITHM:
1. Start the program
2. Declare the necessary variables
3. Get the choice to insert, delete and display the values in stack
4. Perform PUSH() operation
a. t = newnode()
b. Enter info to be inserted
c. Read n
d. t ->info= n
e. t ->next=top
f. top = t
g. Return
5. Perform POP() operation
a. If (top=NULL)
b. Print”underflow”
c. Return
d. X=top
e. Top=top->next
f. Delnode(x)
g. Return
6. Display the values
7. Stop the program.
PROGRAM: (DATA FLOW ANALYSIS)
Dataflow.c
#include<stdio.h>
#include<conio.h>
void main()
{
FILE *fp;
int count,k;
char c,ch;
clrscr();
count=1;
fp = fopen("file.c","r");
for(c=getc(fp);c!=EOF;c=getc(fp))
{
if(c=='\n')
{
count=count+1;
printf("\nline: %d\t",count);
}
else
{
printf("%c",c);
}
}
fclose(fp);
fp=fopen("fileee.c","r");
printf("\n enter the variable to check for Liveness:\n");
scanf("%c",&ch);
count=1;
for(c=getc(fp);c!=EOF;c=getc(fp))
{
if(c=='\n'&&c!=ch)
{
count=count+1;
}
else if(strcmp(c,ch)==0)
{
printf("%d\t",count);
}
}
fclose(fp);
getch();
}

Input
file.c
{
int a , b ;
a=0;
b=a+1;
a=3;
a=a+b;
}

Output
enter the variable to check for Liveness: b
246

RESULT:
Thus, the C program to implement data flow analysis has been executed and verified
successfully.
EX.NO:8
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:
Heap.c
#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()
{
/*local declarations*/
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 heapusing dynamic memory
management");
printf("\n1.Create");
printf("\n2.Display");
printf("\n3.Insert an element in a list");
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;
/*flag to indicate whether a new node is created for the first time or not*/
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 keeps track of the most recently created node*/
temp->next=new1;
temp=new1;
}
printf("\nDo you want to enter more elements?(y/n)");
ans=getch();
}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;
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("\nInsert a node as a head node");
printf("\nInsert a node as a last node");
printf("\nInsert a node as at the intermediate position in the list ");
printf("\nEnter 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; }
/*Insertion of node at first position*/
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;
else
{ temp=head;
New->next = temp;
head= New;
}
return head; }
/*Insertion of node at last position*/
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;
}}
/*Insertion of node at intermediate position*/
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;
}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); }
else
{ *head = temp->next;
free(temp); // using the mem. Dellocation function
}
printf("\nThe 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 element: 10
Do you want to enter more elements? (y/n) y
Enter the element:20
Do you want to enter more elements?(y/n)y
Enter the element:30
Do you want to enter more elements?(y/n)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) 4
Enter the element you want to delete: 20
The element 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-> 30-> NULL

RESULT:
Thus, the C program to implementing heap storage allocation strategy has been
executed and verified successfully.
Ex.No: 9
DATE:
GENERATION OF DAG
AIM:
To write a C program to construct of DAG (Directed Acyclic Graph).
INTRODUCTION:
The code optimization is required t produce an efficient target code. These are two
important issues that used to be considered while applying the techniques for code
optimization. They are:
1. The semantics equivalenced of the source program must not be
changed.
2. The improvement over the program efficiency must be achieved
without changing the algorithm.
ALGORITHM:
1. Start the program.
2. Include all the header files.
3. Check for postfix expression and construct the in order DAG representation.
4. Print the output.
5. Stop the Program.
PROGRAM:
Dag.c
#include<stdio.h>
#include<conio.h>
#include<alloc.h>
int node_gen_number=0;
struct node
{ int node_no;
char label; /* id : i, num : n */
int l_child; /* 0 : No entry */
int r_child; /* 0 : No entry */
char entry;
int disp;
struct node *next;
};
struct node* mkleafnode(char type,char entry)
{ struct node *n;
n=malloc(sizeof(struct node));
n->label=type;
n->entry=entry;
n->l_child=0;
n->r_child=0;
n->next=NULL;
n->disp=0;
return(n); }
struct node* mknode(char type,int l,int r)
{ struct node *n;
n=malloc(sizeof(struct node));
n->label=type;
n->l_child=l;
n->r_child=r;
n->entry='!';
n->next=NULL;
n->disp=0;
return(n); }
struct node* comparenode(struct node *first,struct node *second)
{ while(first!=NULL)
{ if(first->label==second->label&&first->l_child==second->l_child&&first-r_child==
second->r_child&&first->entry=='!'&&second->entry=='!')
{ free(second);
return(first); }
else
if(first->l_child==0&&second->l_child==0&&first->label==second->label&&first-
>entry==second->entry)
{ free(second);
return(first); }
first=first->next; }
second->node_no=++node_gen_number;
return(second); }
struct node* findnode(struct node *first,char check)
{ while(first!=NULL)
if(first->entry==check)
return(first);
else
first=first->next;
return(NULL); }
struct node* find_node(struct node *first,int no)
{ while(first!=NULL)
if(first->node_no==no)
return(first);
else
first=first->next;
return(NULL); }
void display(struct node *tree,struct node *curr)
{ struct node *temp;
if(curr->entry=='!')
printf("\t\t%d\t%c\t%d\t\t%d\n",curr->node_no,curr->label,curr->l_child,curr-
>r_child);
else
printf("\t\t%d\t%c\t%c\t\t-\n",curr->node_no,curr->label,curr->entry);
if(curr->l_child!=0&&curr->r_child!=0)
{ temp=find_node(tree,curr->l_child);
if(temp->disp!=1)
{ temp->disp=1;
display(tree,temp); }
temp=find_node(tree,curr->r_child);
if(temp->disp!=1)
{ temp->disp=1;
display(tree,temp); } } }
void main()
{
int i,j,ip=0;
char input[30];
struct node *head=NULL,*temp,*check,*tail;
struct node *tree=NULL;
clrscr();
printf("\t\tConstruction of Directed Acyclic Graph.\n\n");
printf("Enter the Input String: ");
scanf("%s",input);
while(input[ip]!='\0')
{
if(input[ip]!='+'&&input[ip]!='-'&&input[ip]!='*'&&input[ip]!='/')
{ if(isalpha(input[ip]))
temp=mkleafnode('i',input[ip]);
else
temp=mkleafnode('n',input[ip]);
check=comparenode(head,temp);
if(head==NULL)
{ head=temp;
tail=temp; }
else
if(temp==check)
{ tail->next=temp;
tail=temp; } }
ip++;
} ip=0;
while(input[ip]!='\0')
{ if(input[ip]=='+'||input[ip]=='-'||input[ip]=='*'||input[ip]=='/')
{
if(tree==NULL)
{ temp=findnode(head,input[ip-1]);
check=findnode(head,input[ip+1]);
temp=mknode(input[ip],temp->node_no,check- >node_no); }
else {
temp=findnode(head,input[ip+1]);
temp=mknode(input[ip],tail->node_no,temp->node_no); }
check=comparenode(tree,temp);
if(tree==NULL)
{ tree=temp;
tail=temp; }
else
if(temp==check)
{ tail->next=temp;
tail=temp; }
} ip++; }
temp=head;
while(temp!=NULL)
{ check=temp;
temp=temp->next; }
check->next=tree;
printf("\n\n\t\tNode\tLabel\tl_Child|Entry\tR_child\n\n");
display(head,tail);
getch();
}

OUTPUT:
Construction of Directed Acyclic Graph.
Enter the Input String: a+b*a+b

Node 1_Child|
R_child
Label Entry
5 + 4 2
4 * 3 1
3 + 1 2
1 i a -
2 i b -

RESULT:
Thus, the C program for the construction of DAG has been executed and verified
successfully.
Ex. No: 10
DATE:
IMPLEMENT THE BACK END OF THE COMPILER (OR) IMPLEMENTATION OF CODE
GENERATOR
AIM:
To write a C program to implement the back end of the Compiler.
ALGORITHM:
1. Start the program.
2. Get the three variables from statements and stored in the 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 the program.
PROGRAM:
Code.c
#include<stdio.h>
#include<conio.h>
#include<string.h>
#include<ctype.h>
#include<graphics.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++)
{ 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;
clrscr();
printf("\nEnter the Three Address Code:\n");
for(i=0;;i++)
{ 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; }
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]);
getch();
}
}
OUTPUT:
Enter the Three Address Code:
a=b+c
c=a*c
exit
The Equivalent Assembly Code is:
Mov R0,b
Add c,R0
Mov a,R0
Mov R1,a
Mul c,R1
Mov c,R1
RESULT:
Thus, the program for the implementation of the Back end compiler has been executed and
verified successfully.
Ex. No: 11
DATE:
IMPLEMENTATION OF SIMPLE CODE OPTIMIZATION TECHNIQUES
AIM:
To write a C program to implement the code optimization technique.
ALGORITHM:
1. Start the program.
2. Create an input file which contains three address code.
3. Open the file in read mode.
4. If the file pointer returns NULL, exit the program else goto 5.
5. Scan the input symbol from the left to right.
Common sub expression elimination
6. Store the first expression in a string.
7. Compare the string with the other expressions in the file.
8. If there is a match, remove the expression form the input file.
9. Perform the step 5 to 8 for all the input symbols in the file.
Dead code Elimination
10. Scan the input symbol from the file from left to right.
11. Get the operand before the operator from the three-address code.
12. Check whether the operand is used in any other expression from the three-address
code.
13. If the operand is not used, then eliminate the complete expression from the three-
address code else goto 14.
14. Perform step 11 to 13 for all the operand in the three address code till end of file is
reached.
15. 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 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,temp);
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 Elimination");
for(k=0;k<z;k++)
{ printf("%c\t=",pr[k].l);
printf("%s\n",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++)
{
printf("%c\t=",pr[i].l);
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(); }
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
After Dead Code Elimination
b=c+d
e=c+d
f=b+e
r=f
pos: 2
Eliminate 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 program for the implementation of simple code optimization techniques has been
executed and verified successfully.

You might also like