0% found this document useful (0 votes)
11 views84 pages

Compiler Lab Manual

The document outlines a Compiler Laboratory course at Mahendra Institute of Technology, detailing various experiments related to compiler design and implementation. It includes specific experiments such as creating a symbol table, developing a lexical analyzer, and implementing a lexical analyzer using the Lex tool. Each experiment is accompanied by an aim, algorithm, and example code in C, demonstrating practical applications of compiler concepts.

Uploaded by

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

Compiler Lab Manual

The document outlines a Compiler Laboratory course at Mahendra Institute of Technology, detailing various experiments related to compiler design and implementation. It includes specific experiments such as creating a symbol table, developing a lexical analyzer, and implementing a lexical analyzer using the Lex tool. Each experiment is accompanied by an aim, algorithm, and example code in C, demonstrating practical applications of compiler concepts.

Uploaded by

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

MAHENDRA INSTITUDE OF TECHNOLOGY

(Autonomous)

DEPARTMENT OF COMPUTER SCENCE AND


ENGINEERING

CS2224502- COMPILER LABARATORY


YEAR/SEM : III/ V

PREPARED BY
Mrs.C.GAYATHRI AP/CSE
Mrs.C.ANUSUYA AP/CSE
INDEX
SIGNATURE
S.NO DATE NAME OF THE EXPERIMENT OF THE
STAFF

1 SYMBOL TABLE

2 LEXICAL ANALYSIS RECOGNIZE IN C

3 LEXICAL ANALYZER USING LEX TOOL

GENERATE YACC SPECIFICATION FOR A


FEW SYNTACTIC CATEGORIES:
4a ARITHMETIC EXPRESSION THAT USES
OPERATOR +,-,* AND /.

LETTER FOLLOWED BY ANY NUMBER OF


4b LETTERS OR DIGITS

4c CALCULATOR USING LEX AND YACC

CONVERT THE BNF RULES INTO YACC FORM


5 AND WRITE CODE TO GENERATE ABSTRACT
SYNTAX TREE

6 TYPE CHECKING

IMPLEMENTATION OF ANY ONE


8 STORAGE ALLOCATION
STRATEGIES(HEAP, STACK, STATIC)

9 CONSTRUCTION OF DAG

IMPLEMENT THE BACK END OF THE


10 COMPILER

11 SIMPLE CODE OPTIMIZATION


Ex. No: 1
DATE:
IMPLEMENTATION OF SYMBOL TABLE
Date:

AIM:
To write a C program to implement a 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

#include<stdio.h>

#include<conio.h>

#include<malloc.h>

#include<string.h>

#include<math.h>

#include<ctype.h>

void main()

int i=0,j=0,x=0,n,flag=0; void *p,*add[15];

char ch,srch,b[15],d[15],g[10],c;

clrscr();

printf("Expression terminated by $:");

while((c=getchar())!='$')

b[i]=c; i++;

n=i-1;

printf("Given expression:::");

i=0;

while(i<=n)

printf("%c",b[i]); i++;

}
printf("\n.....symbol table. . .\n");

printf("symbol\taddr\ttype\n");

while(j<=n)

c=b[j];

if(isalpha(toascii(c)))

if(j<=n)

p=malloc(c); add[x]=p;

d[x]=c;

printf("%c\t%d\tidentifier\n",c,p); goto b;

else

b:

ch=b[j+1];

if(ch=='+'||ch=='-'||ch=='*'||ch=='='||ch==’/’)

p=malloc(c);

add[x]=p;

g[x]=ch;

printf("%c\t%p\t Operator \n",g[x],p);

x++;
}

} j++;

printf("the symbol is to be searched\n");

scanf("%s",&srch);

//srch=getch();

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

if(srch==d[i]||srch==g[i])

printf("symbol found..."); printf("%c%s

%p\n",srch,"@address",d[i]); flag=1;

if(flag==0)

printf("symbol not found\n");

}
═══════════ Output ═════════════════════════════

║Expression terminated by $:C=A*B+C-D/H$

║Given expression:::C=A*B+C-D/H

║.....symbol table....

║symbol addr type

║C 2034 identifier

║= 083A Operator

║A 2178 identifier

║* 08C8 Operator

║B 2318 identifier

║+ 0954 Operator

║C 2458 identifier

║- 09E2 Operator

║D 2602 identifier

║H 2674 identifier

║the symbol is to be searched

║+

║symbol found. .+@address0042

RESULT:

Thus the C program to implement the symbol table was executed and the output is verified.
Ex. No: 02 DEVELOP A LEXICAL ANALYZER TO RECOGNIZE A FEW
PATTERNS IN C
Date:

AIM:
To Write a C program to develop a lexical analyzer to recognize a few patterns in C.

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

#include<stdio.h>

#include<conio.h>

#include<ctype.h>

#include<string.h>

void main()

FILE *fi,*fo,*fop,*fk;

int flag=0,i=1;

char c,t,a[15],ch[15],file[20];

clrscr();

printf("\n Enter the File Name:");

scanf("%s",&file);

fi=fopen(file,"r");

fo=fopen("inter.c","w");

fop=fopen("Oper.c","r");

fk=fopen("key.c","r");

c=getc(fi); while(!

feof(fi))

if(isalpha(c)||isdigit(c)||(c=='['||c==']'||c=='.'==1))

fputc(c,fo);
else

if(c=='\n') fprintf(fo,"\t$\

t");

else fprintf(fo,"\t%c\t",c);

c=getc(fi);

fclose(fi);

fclose(fo);

fi=fopen("inter.c","r");

printf("\n Lexical Analysis");

fscanf(fi,"%s",a);

printf("\n Line: %d\n",i++);

while(!feof(fi))

if(strcmp(a,"$")==0)

printf("\n Line: %d \n",i++);

fscanf(fi,"%s",a);

fscanf(fop,"%s",ch);
while(!feof(fop))

if(strcmp(ch,a)==0)

fscanf(fop,"%s",ch); printf("\t\t

%s\t:\t%s\n",a,ch); flag=1;

fscanf(fop,"%s",ch);

rewind(fop);

fscanf(fk,"%s",ch);

while(!feof(fk))

if(strcmp(ch,a)==0)

fscanf(fk,"%k",ch); printf("\t\t

%s\t:\tKeyword\n",a); flag=1;

fscanf(fk,"%s",ch);
}

rewind(fk);

if(flag==0)

if(isdigit(a[0])) printf("\t\t%s\t:\tConstant\

n",a);

else

printf("\t\t%s\t:\tIdentifier\n",a);

flag=0;

fscanf(fi,"%s",a);

getch();

Key.c

int

void

main

char

if

for
while

else

printf

scanf

FILE

include

stdio.h

conio.h

iostream.h

Oper.c

( open para

) closepara

{ openbrace

} closebrace

< lesser

> greater

" doublequote ' singlequote

: colon

; semicolon

# preprocessor

= equal
== asign

% percentage

^ bitwise

& reference

* star

+ add

- sub

\ backslash

/ slash

INPUT.c

#include "stdio.h"

#include "conio.h"

void main()

int a=10,b,c;

a=b*c;

getch();

}
OUTPUT:

Line:1

# : preprocessor

include : Identifier

&quot; : doublequote

stdio.h : Keyword

&quot; : doublequote

Line: 2

# : preprocessor

include : Identifier

&quot; : doublequote

conio.h : Keyword

&quot; : doublequote

Line: 3

void : Keyword

main : Keyword

( : open

) : closepara
Line: 4

{ : openbrace

Line: 5

int : Keyword

a : Identifier

= : equal

10 : Constant

, : Identifier

b : Identifier

, : Identifier

c : Identifier

; : semicolon

Line: 6

a : Identifier

= : equal

b : Identifier

* : star

c : Identifier
; : semicolon

Line: 7

getch : Identifier

( : open

) : closepara

; : semicolon

Line: 8

} : closebrace

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 ANALYSER USING LEX TOOL
Date:

AIM:
To write a lex program to implement the lexical analyzer

INTRODUCTION

Lex is officially known as a "Lexical Analyzer". It’s main job is to break up an input

stream into more into meaningful units, or tokens. For example, consider breaking a text

file up into individual words. More pragmatically, Lex is a tool for automatically

generating a lexer ( also known as scanner) starting from a lex specification.

Lex specifications:

A Lex program (the .l file ) consists of three parts:

declarations

%%

translation rules

%%
auxiliary procedures

1. The declarations section includes declarations of variables, manifest constants (A

manifest constant is an identifier that is declared to represent a constant. e.g. # define PIE

3.14), and regular definitions.

2. The translation rules of a Lex program are statements of the form

: p1 {action 1}

p2 {action 2}

p3 {action 3}

……

……

where each p is a regular expression and each action is a program fragment describing

what action the lexical analyzer should take when a pattern p matches a lexeme. In Lex the

actions are written in C.

3. The third section holds whatever auxiliary procedures are needed by the actions.

Alternatively, these procedures can be compiled separately and loaded with the lexical

analyzer.

A Lex program has the following

form: declarations

%%

translation rules

%%

auxiliary functions
The declarations section includes declarations of variables, manifest constants and regular

definitions.

The translation rules each have the form Pattern { Action }

Each pattern is a regular expression, which may use the regular definitions of the

declaration section. The actions are fragments of code, typically written in C, although

many variants of Lex using other languages have been created.

STEP BY STEP PROCEDURE FOR RUNNING A LEX AND


YACC PROGRAM
For compiling a lex program

1. write the lex program in a file and save it as file.l (where file is the name of the file).

2. open the terminal and navigate to the directory where you have saved the file.l

3. type - lex file.l

4. then type - cc lex.yy.c

5. then type - ./a.out or a.exe

For compiling lex and yacc together

1. write lex program in a file file.l and yacc in a file file.y

2. open the terminal and navigate to the directory where you have saved the files.

3. type lex file.l

4. type yacc file.y


5. type cc lex.yy.c y.tab.h

6. type ./a.out or a.exe

ALGORITHM:

1. Start the program

2. Pass file.c via command line arguments as Input file and include the yylex() tool

for input scanning.

3. Define the alphabets and numbers

4. Print the preprocessor, function, keyword using yytext.lex tool

5. Print the relational, assignment and all the operator using yytext()

tool 6.Also scan and print where the loop ends and begins.

7.Use yywrap() to enter an error.

8.Stop the program.


PROGRAM

CDP3.l (Save the following code snippets in CDP3.l)


%{

int COMMENT=0;

%}

identifier [a-zA-Z][a-zA-Z0-9]*

%%

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

int |

float |

char |

double |

while |

for |

do |

if |

break |

continue |

void |

switch |

case |

long |

struct |

const |
typedef |

return |

else |

goto {printf("\n\t%s is a KEYWORD",yytext);}

"/*" {COMMENT = 1;}

"*/" {COMMENT = 0;}

{identifier}\( {if(!COMMENT)printf("\n\nFUNCTION\n\t%s",yytext);}

\{ {if(!COMMENT) printf("\n BLOCK BEGINS");}

\} {if(!COMMENT) printf("\n BLOCK ENDS");}

{identifier}(\[[0-9]*\])? {if(!COMMENT) printf("\n %s IDENTIFIER",yytext);}

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

[0-9]+ {if(!COMMENT) printf("\n\t%s is a

NUMBER",yytext);}

\)(\;)? {if(!COMMENT) printf("\n\t");ECHO;printf("\n");}

\( ECHO;

= {if(!COMMENT)printf("\n\t%s is an ASSIGNMENT OPERATOR",yytext);}

\<= |

\>= |

\< |

== |

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

%%

int main(int argc,char **argv)

if (argc > 1)
{

FILE *file;

file = fopen(argv[1],"r");

if(!file)

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

exit(0);

yyin = file;

yylex();

printf("\n\n");

return 0;

} int yywrap()

return 0;

ODDREVEN.C

#include <stdio.h>

int main()

int number;

printf("Enter an integer: ");


scanf("%d", &number);

if(number % 2 == 0)

printf("%d is even.", number);

else

printf("%d is odd.", number);

return 0;

═══════════=============Output ═════════════════════════

D:\Mohanraj\CS6612 COMPILER LAB\lex_yacc>flex CDP3.l

D: \Mohanraj \CS6612 COMPILER LAB\lex_yacc>gcc lex.yy.c

D: \Mohanraj \CS6612 COMPILER LAB\lex_yacc>a.exe ODDREVEN.c

#include <stdio.h> is a PREPROCESSOR DIRECTIVE

int is a KEYWORD

FUNCTION

main(

)
BLOCK BEGINS

int is a KEYWORD

number IDENTIFIER;

FUNCTION

printf(

"Enter an integer: " is a STRING

);

FUNCTION

scanf(

"%d" is a STRING, &

number IDENTIFIER

);

FUNCTION

if(

number IDENTIFIER %

2 is a NUMBER

== is a RELATIONAL OPERATOR

0 is a NUMBER

FUNCTION

printf(

"%d is even." is a STRING,


number IDENTIFIER

);

else is a KEYWORD

FUNCTION

printf(

"%d is odd." is a STRING,

number IDENTIFIER

);

return is a KEYWORD

0 is a NUMBER;

BLOCK ENDS

( Ctl+C to Stop Program Execution)

RESULT:

Thus the C program to implement the lexical analyzer using LEX tool was executed and the
output is verified.
Ex. No: 4.A
PROGRAM TO RECOGNIZE A VALID ARITHMETIC EXPRESSION
Date:
THAT USESOPERATOR +, - , * AND / USING YACC

AIM:

To write a Yacc program to valid arithmetic expression using Yacc


ALGORITHM:

Step-1:Reading an expression

Step-2: Checking the validating of the given expression according to the rule

using yacc.

Step-3:Using expression rule print the result of the given values

PROGRAM

vae.l
%{
#include"y.tab.h"
#include<math.h>
extern yylval;
%}
%%
[0-9]+ {yylval=atoi(yytext);return NUM;}
[+] {return '+';}
[-] {return '-';}
[*] {return '*';}
[/] {return '/';}
[\t]+;
[\n] {return 0;}
%%

vae.y

%{
#include<stdio.h>
%}
%token NUM
%left '-''+'
%right '*''/'
%%
start: exp {printf("%d\n",$$);}
exp:exp'+'exp {$$=$1+$3;}
|exp'-'exp {$$=$1-$3;}
|exp'*'exp {$$=$1*$3;}
|exp'/'exp
{
if($3==0)
yyerror("error");
else
{
$$=$1/$3;
}
}
|'('exp')' {$$=$2;}
|NUM {$$=$1;}
;
%%
main()
{
printf("Enter the Expr. in terms of integers\n");
if(yyparse()==0)
printf("Success\n");
}
yywrap(){}
yyerror()
{
printf("Error\n");
}
OUTPUT:
D:\MOHANRAJ\CS6612 COMPILER LAB\lex_yacc\YACC\CD4A>lex vae.l

D: \MOHANRAJ\\CS6612 COMPILER LAB\lex_yacc\YACC\CD4A>yacc -d vae.y

D: \MOHANRAJ\\CS6612 COMPILER LAB\lex_yacc\YACC\CD4A>cc lex.yy.c


y.tab.c

D: \MOHANRAJ\\CS6612 COMPILER LAB\lex_yacc\YACC\CD4A>a.exe


Enter the Expr. in terms of integers
1+2*3-4/2
5
Success

D: \MOHANRAJ\\CS6612 COMPILER LAB\lex_yacc\YACC\CD4A>a.exe


Enter the Expr. in terms of integers
m+3-4
mError

RESULT:

Thus the program for validating arithmetic expression was done.


Ex. No: 4.B PROGRAM TO RECOGNIZE A VALID VARIABLE WHICH STARTS
WITH A LETTER FOLLOWED BY ANY NUMBER OF LETTERS OR
Date:
DIGITS

AIM:

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


digits by using YACC

ALGORITHM:

Step-1:Reading an expression

Step-2: Checking the validating of the given expression according to the rule

using yacc.

Step-3:Using expression rule print the result of the given values

PROGRAM

vid.l
%{
#include "y.tab.h"
%}
%%
[a-zA-z_] {return ALPHA;}
[0-9]+ {return NUMBER;}
"\n" { return ENTER;}
. {return ER;}
%%
yywrap()
{}
vid.y

%{
#include <stdio.h>
#include<stdlib.h>
%}
%token ALPHA NUMBER ENTER ER
%%
var:v ENTER {printf("Valid Variable\n");exit(0);}
v:ALPHA exp1
exp1:ALPHA exp1
|NUMBER exp1
|;
%%
yyerror()
{
printf("Invalid Variable\n");
}
main()
{
printf("Enter the expression:");
yyparse();
}
OUTPUT:

D:\MOHANRAJ\CS6612 COMPILER LAB\lex_yacc\YACC\CD4B>lex vid.l

D: \MOHANRAJ \CS6612 COMPILER LAB\lex_yacc\YACC\CD4B>yacc -d vid.y

D: \MOHANRAJ \CS6612 COMPILER LAB\lex_yacc\YACC\CD4B>cc lex.yy.c


y.tab.c

D: \MOHANRAJ \CS6612 COMPILER LAB\lex_yacc\YACC\CD4B>a.exe


Enter the expression:a1111
Valid Variable

D: \MOHANRAJ \CS6612 COMPILER LAB\lex_yacc\YACC\CD4B>a.exe


Enter the expression:12asda
Invalid Variable

D: \MOHANRAJ \CS6612 COMPILER LAB\lex_yacc\YACC\CD4B>a.exe


Enter the expression:abc1234df
Valid Variable

RESULT:

Thus the program for checking letter followed by letter or digits


were done
Ex. No: 4.C

Date: IMPLEMENTATION OF A CALCULATOR USING LEX AND YACC

AIM:

To implement a calculator to compute the given expression using semantic


rules of the yacc program.

ALGORITHM:

1. A Yacc source program has three parts as


follows. Declarations
%%
translation rules
%%
supporting C routines
2. Declarations Section
This section contains entries that:
□ Include standard I/O header file.
□ Define global variables.
□ Define the list rule as the place to start processing.
□ Define the tokens used by the parser.
□ Define the operators and their precedence.
3. Rules Section

The rules section defines the rules that parse the input stream. Each rule consists of a
grammar production and the associated semantic action.
Programs Section

4. The programs section


It contains the following subroutines. Because these subroutines are included in this file, it is
not necessary to use the yacc library when processing this file.
Main The required main program that calls the yyparse subroutine to start the program.
yyerror(s) This error-handling subroutine only prints a syntax error message. yywrap The
wrap-up subroutine that returns a value of 1 when the end of input occurs.

5. The calc.lex file contains include statements for standard input and output, as well as for
the y.tab.h file. The yacc program generates that file from the yacc grammar file information
if we use the -d flag with the yacc command. The y.tab.h file contains definitions for the
tokens that the parser program uses.

6. calc.lex contains the rules to generate these tokens from the input stream.

PROGRAM

calc.l
%{
#include<stdio.h>
#include"y.tab.h"
int c;
extern int yylval;
%}
%%
"";
[a-z] {
c=yytext[0];
yylval=c-'a';
return(LETTER);
}
[0-9] {
c=yytext[0];
yylval=c-'0';
return(DIGIT);
}
[^a-z 0-9\b] {
c=yytext[0];
return(c);
}

calc.y

%{
#include<stdio.h>
int regs[26];
int base;
%}
%start list
%token DIGIT LETTER
%left '|'
%left '&'
%left '+''-'
%left '*''/''%'
%left UMINUS
%%
list:
|
list stat '\n'
|
list error '\n'
{
yyerrok;
}
;

stat: expr
{
printf("%d\n",$1);
}
|
LETTER '=' expr
{
regs[$1]=$3;
}
;
expr: '(' expr ')'
{
$$=$2;
}
|
expr '*' expr
{
$$=$1*$3;
}
|
expr '/' expr
{
$$=$1/$3;
}
|
expr '%' expr
{
$$=$1%$3;
}
|
expr '+' expr
{
$$=$1+$3;
}
|
expr '-' expr
{
$$=$1-$3;
}
|
expr '&' expr
{
$$=$1&$3;
}
|
'-'expr %prec UMINUS
{
$$=-$2;
}
|
LETTER
{
$$=regs[$1];
}
|

number
;
number: DIGIT
{
$$=$1; base=($1==0)?
8:10;
}
|
number DIGIT
{
$$=base * $1+$2;
}
;
%%
main()
{
return(yyparse());
}
yyerror(s)
char *s;
{
fprintf(stderr,"%s\n",s);
}
yywrap()
{
return(1);
}

OUTPUT:
D:\MOHANRAJ\CS6612 COMPILER LAB\lex_yacc\yacc\calc>lex calc.l D:\

MOHANRAJ\CS6612 COMPILER LAB\lex_yacc\yacc\calc>yacc -d calc.y D:\

MOHANRAJ\CS6612 COMPILER LAB\lex_yacc\yacc\calc>cc lex.yy.c y.tab.c

D:\MOHANRAJ\CS6612 COMPILER LAB\lex_yacc\yacc\calc>a.exe


4+5
9
-4+5
1
5-20
-15
m=8
m+3
11

^C
D:\MOHANRAJ\CS6612 COMPILER LAB\lex_yacc\yacc\calc>

RESULT:

Thus the calculator is implemented using Lex and Yacc.


Ex. No: 5 CONVERT THE BNF RULES INTO YACC FORM AND WRITE
CODE TO GENERATE ABSTRACT SYNTAX TREE USING AND YACC.
Date:

AIM:

To convert the bnf rules into yacc form and write code to generate
abstract syntax tree using and yacc.

ALGORITHM:

1. Start the Program

2. Reading an input file line by line.

3. Convert it in to abstract syntax tree using three address code.

4. Represent three address code in the form of quadruple tabular form.

5. Stop the Program


PROGRAM

BNF.l
%{
#include"y.tab.h"
#include<stdio.h>
#include<string.h>
#define yywrap() 1
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];
%%
BNF.y

%{
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
void AddQuadruple(char op[5],char arg1[10],char arg2[10],char
result[10]);
int pop();
void push(int data);
int Index=0,tIndex=0,StNo,Ind,tInd;
extern int LineNo;
struct quad
{
char op[5];
char arg1[10];
char arg2[10];
char result[10];
}QUAD[30];
struct stack
{
int items[100];
int top;
}stk;

%}
%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");
push(Index);
Index++;
}
BLOCK
{
strcpy(QUAD[Index].op,"GOTO");
strcpy(QUAD[Index].arg1,"");
strcpy(QUAD[Index].arg2,"");
strcpy(QUAD[Index].result,"-1");
push(Index);
Index++;
};
ELSEST: ELSE{
tInd=pop();
Ind=pop();
push(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");
push(Index);
Index++;
}
BLOCK
{
strcpy(QUAD[Index].op,"GOTO");
strcpy(QUAD[Index].arg1,"");
strcpy(QUAD[Index].arg2,"");
strcpy(QUAD[Index].result,"-1");
push(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].resu
lt);
}
printf("\n\t\t-----------------------");
printf("\n\n");
return 0;
}
void push(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 (char const *s)
{
fprintf (stderr, "%s\n", s);
}
TEST.c
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:

RESULT:

Thus the program for the exercise on the syntax using YACC
has been executed successfully and output is verified.
Ex. No: 06
IMPLEMENTATION OF TYPE CHECKING
Date:
Date

AIM:

To write a C program to implement type checking

ALGORITHM:

Step-1: Track the global scope type information (e.g. classes and their

members)

Step-2: Determine the type of expressions recursively, i.e. bottom-up, passing

the resulting types upwards.

Step-3: If type found correct, do the operation

Step-4: Type mismatches, semantic error will be notified Start


PROGRAM

#include<stdio.h>
#include<string.h>
struct symTable
{
int type;
char var[10];
}sT[50];
int c = 0;
void sep(char a[])
{
int len = strlen(a);
int i,j=0;
char temp[50],tp[50];
for(i = 0; i < len;++i)
{
if(a[i] != 32)
tp[i] = a[i];
else
break;
}
tp[i] = '\0';
temp[0]='\0';
++i;
for(;i < len;++i)
{
if(a[i] != ',' && a[i] != 32 && a[i] != ';')
temp[j++] = a[i];
else
{
if(strcmp(tp,"int") == 0)
sT[c].type = 1;
else if(strcmp(tp,"float") == 0)
sT[c].type = 2; strcpy(sT[c+
+].var,temp); temp[0] = '\0';
j=0;
}
}
}
int check(char a[])
{
int len = strlen(a);
int i, j = 0,key = 0,k;
char temp[50];
for(i = 0;i < len;++i)
{
if(a[i] != 32 && a[i] != '+' && a[i] != '=' && a[i] != ';')
temp[j++] = a[i];
else
{
temp[j]='\0';
for(k = 0;k < c;++k)
{
if(strcmp(sT[k].var,temp) == 0)
{
if(key == 0)
key = sT[k].type;
else if(sT[k].type != key)
return 0;
}
}
j = 0;
}
}
return 1;
}
void main()
{
int N,ans,i;
char s[50];
printf("\n Enter the total lines of declaration\n");
scanf("%d",&N);
while(N--)
{
scanf(" %[^\n]",s);
sep(s);
}
printf("Enter the expression:\n");
scanf(" %[^\n]",s);
if(check(s))
printf("Correct\n");
else
printf("Semantic error\n");

OUTPUT:

Enter the total lines of declaration


2
int a,b;
float e;
Enter the expression:
e=a+b;
Semantic error

RESULT:

Thus the above program is compiled and executed successfully and


output is verified.
Ex. No: 08
IMPLEMENT ANY ONE STORAGE ALLOCATION
Date: STRATEGIES(HEAP,STACK,STATIC)
Date

MEMORY IN C – THE STACK, THE HEAP, AND STATIC


The great thing about C is that it is so intertwined with memory – and by that I mean that the
programmer has quite a good understanding of “what goes where“. C has three different pools of
memory.

– static: global variable storage, permanent for the entire run of the program.
– stack: local variable storage (automatic, continuous memory).
– heap: dynamic storage (large pool of memory, not allocated in contiguous order).

STATIC MEMORY

Static memory persists throughout the entire life of the program, and is usually used to store things
like global variables, or variables created with the static clause. For example:

int theforce;
On many systems this variable uses 4 bytes of memory. This memory can come from one of two
places. If a variable is declared outside of a function, it is considered global, meaning it is
accessible anywhere in the program. Global variables are static, and there is only one copy for the
entire program. Inside a function the variable is allocated on the stack. It is also possible to force a
variable to be static using the static clause. For example, the same variable created inside a
function using the static clause would allow it to be stored in static memory.

static int theforce;

STACK MEMORY

The stack is used to store variables used on the inside of a function (including the main()function).
It’s a LIFO, “Last-In,-First-Out”, structure. Every time a function declares a new variable it is
“pushed” onto the stack. Then when a function finishes running, all the variables associated with
that function on the stack are deleted, and the memory they use is freed up. This leads to the
“local” scope of function variables. The stack is a special region of memory, and automatically
managed by the CPU – so you don’t have to allocate or deallocate memory. Stack memory is
divided into successive frames where each time a function is called, it allocates itself a fresh stack
frame.

Note that there is generally a limit on the size of the stack – which can vary with the operating
system (for example OSX currently has a default stack size of 8MB). If a program tries to put too
much information on the stack, stack overflow will occur. Stack overflow happens when all the
memory in the stack has been allocated, and further allocations begin overflowing into other
sections of memory. Stack overflow also occurs in situations where recursion is incorrectly used.

A summary of the stack:

 the stack is managed by the CPU, there is no ability to modify it

 variables are allocated and freed automatically

 the stack it not limitless – most have an upper bound

 the stack grows and shrinks as variables are created and destroyed

 stack variables only exist whilst the function that created them exists

HEAP MEMORY

The heap is the diametrical opposite of the stack. The heap is a large pool of memory that can be
used dynamically – it is also known as the “free store”. This is memory that is not automatically
managed – you have to explicitly allocate (using functions such as malloc), and deallocate (e.g.
free) the memory. Failure to free the memory when you are finished with it will result in what is
known as a memory leak – memory that is still “being used”, and not available to other processes.
Unlike the stack, there are generally no restrictions on the size of the heap (or the variables it
creates), other than the physical size of memory in the machine. Variables created on the heap are
accessible anywhere in the program.

Oh, and heap memory requires you to use pointers.

A summary of the heap:

 the heap is managed by the programmer, the ability to modify it is somewhat boundless

 in C, variables are allocated and freed using functions like malloc() and free()

 the heap is large, and is usually limited by the physical memory available

 the heap requires pointers to access it

AN EXAMPLE OF MEMORY USE

Consider the following example of a program containing all three forms of memory:

#include <stdio.h>

#include <stdlib.h>

int x;

int main(void)

int y;

char *str;

y = 4;

printf("stack memory: %d\n", y);

str = malloc(100*sizeof(char));

str[0] = 'm';
printf("heap memory: %c\n", str[0]);

free(str);

return 0;

The variable x is static storage, because of its global nature. Both y and str are dynamic stack
storage which is deallocated when the program ends. The function malloc() is used to allocate 100
pieces of of dynamic heap storage, each the size of char, to str. Conversely, the function free(),
deallocates the memory associated with str.
Ex. No: 08
IMPLEMENT ANY ONE STORAGE ALLOCATION
Date: STRATEGIES(HEAP,STACK,STATIC)
Date

AIM:

To implement Stack storage allocation strategies using C program.

ALGORITHM:

Step-1: Initially check whether the stack is empty

Step-2: Insert an element into the stack using push operation

Step-3: Insert more elements onto the stack until stack becomes

full Step-4: Delete an element from the stack using pop operation

Step-5: Display the elements in the

stack Step-6:Stop the program by exit


PROGRAM

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#define size 5
struct stack
{
int s[size];
int top;
} st;
int stfull()
{
if (st.top >= size - 1)
return 1;
else
return 0;
}
void push(int item)
{
st.top++;
st.s[st.top] = item;
}
int stempty()
{
if (st.top == -1)
return 1;
else
return 0;
}
int pop()
{
int item;
item = st.s[st.top];
st.top--;
return (item);
}
void display()
{
int i;
if (stempty()) printf("\
nStack Is Empty!"); else
{
for (i = st.top; i >= 0; i--)
printf("\n%d", st.s[i]);
}
}
int main()
{
int item, choice;
char ans;
st.top = -1;
printf("\n\tImplementation Of Stack");
do {
printf("\nMain Menu");
printf("\n1.Push \n2.Pop \n3.Display \n4.exit");
printf("\nEnter Your Choice");
scanf("%d", &choice);
switch (choice)
{
case 1:
printf("\nEnter The item to be pushed");
scanf("%d", &item);
if (stfull())
printf("\nStack is Full!");
else
push(item);
break;
case 2:
if (stempty())
printf("\nEmpty stack!Underflow !!");
else
{
item = pop();
printf("\nThe popped element is %d", item);
}
break;
case 3:
display();
break;
case 4:
goto halt;
}
printf("\nDo You want To Continue?");
ans = getche();
} while (ans == 'Y' || ans == 'y');
halt:
return 0;
}
OUTPUT:

Implementation Of Stack
Main Menu
1.Push
2.Pop
3.Display
4.exit
Enter Your Choice 1

Enter The item to be pushed 10

Do You want To Continue?y


Main Menu
1.Push
2.Pop
3.Display
4.exit
Enter Your Choice 1

Enter The item to be pushed 20

Do You want To Continue?y


Main Menu
1.Push
2.Pop
3.Display
4.exit
Enter Your Choice1

Enter The item to be pushed 30


Do You want To Continue?y
Main Menu
1. Push
2. Pop
3.Display
4.exit
Do You want To Continue?y
Main Menu
1.Push
2.Pop
3.Display
4.exit
Enter Your Choice 2

The popped element is 30


Do You want To Continue?
y Main Menu
1. Push
2.Pop
3.Display
4.exit
Enter Your Choice3

20
10
Do You want To Continue?n

RESULT:

Thus the above program is compiled and executed successfully and output is verified.
Ex. No: 06
CONSTRUCTION OF DAG (DIRECTED ACYCLIC GRAPH)
Date:
Date

AIM:

To write a C program to construct of DAG(Directed Acyclic Graph)

INTRODUCTION:

The code optimization is required to produce an efficient target code. These are two important
issues that used to be considered while applying the techniques for code optimization.
They are:
The semantics equivalences of the source program must not be changed.
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

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<conio.h>
void main()
{
struct da
{
int ptr,left,right;
char label;
}dag[25];
int ptr,l,j,change,n=0,i=0,state=1,x,y,k;
char store,*input1,input[25],var;
clrscr();
for(i=0;i<25;i++)
{
dag[i].ptr=NULL;
dag[i].left=NULL;
dag[i].right=NULL;
dag[i].label=NULL;
}
printf("\n\nENTER THE EXPRESSION\n\n");
scanf("%s",input1);
/*EX:((a*b-c))+((b-c)*d)) like this give with paranthesis.limit
is 25 char ucan change that*/
for(i=0;i<25;i++)
input[i]=NULL;
l=strlen(input1);
a:
for(i=0;input1[i]!=')';i++);
for(j=i;input1[j]!='(';j--);
for(x=j+1;x<i;x++)
if(isalpha(input1[x]))
input[n++]=input1[x];
else
if(input1[x]!='0')
store=input1[x];
input[n++]=store;
for(x=j;x<=i;x++)
input1[x]='0';
if(input1[0]!='0')goto a;
for(i=0;i<n;i++)
{
dag[i].label=input[i];
dag[i].ptr=i;
if(!isalpha(input[i])&&!isdigit(input[i]))
{
dag[i].right=i-1;
ptr=i;
var=input[i-1];
if(isalpha(var))
ptr=ptr-2;
else
{
ptr=i-1;
b:
if(!isalpha(var)&&!isdigit(var))
{
ptr=dag[ptr].left;
var=input[ptr];
goto b;
}
else
ptr=ptr-1;
}
dag[i].left=ptr;
}
}
printf("\n SYNTAX TREE FOR GIVEN EXPRESSION\n\n");
printf("\n\n PTR \t\t LEFT PTR \t\t RIGHT PTR \t\t LABEL\n\n");
for(i=0;i<n;i++)/* draw the syntax tree for the following
output with pointer value*/ printf("\n%d\t%d\t%d\t%c\
n",dag[i].ptr,dag[i].left,dag[i].right,dag[i].label); getch();
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if((dag[i].label==dag[j].label&&dag[i].left==dag[j].left)&&dag[i].right==dag[j].right)
{
for(k=0;k<n;k++)
{
if(dag[k].left==dag[j].ptr)dag[k].left=dag[i].ptr;
if(dag[k].right==dag[j].ptr)dag[k].right=dag[i].ptr;
}
dag[j].ptr=dag[i].ptr;
}
}
}
printf("\n DAG FOR GIVEN EXPRESSION\n\n");
printf("\n\n PTR \t LEFT PTR \t RIGHT PTR \t LABEL \n\n");
for(i=0;i<n;i++)/*draw DAG for the following output with
pointer value*/
printf("\n %dt\t%d\t\t%d\t\t%c\n",dag[i].ptr,dag[i].left,dag[i].right,dag[i].label);
getch();
}
OUTPUT:
ENTER THE EXPRESSION
((a*b-c))+((b-c)*d))

SYNTAX TREE FOR GIVEN EXPRESSION

PTR LEFT PTR RIGHT PTR LABEL

0 0 0 a

1 0 0 b

2 0 0 c

3 1 2 -

4 0 3 -

DAG FOR GIVEN EXPRESSION

PTR LEFT PTR RIGHT PTR LABEL

0 0 0 a

1 0 0 b

2 0 0 c

3 1 2 -

4 0 3 -

RESULT:

Thus the program for implementation of DAG has been successfully executed and output is
verified.
Ex. No: 10

Date: IMPLEMENTATION OF BACK END OF COMPILER

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

#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;
}
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 generation
************************
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.
Ex. No: 11

Date: IMPLEMENTATION OF CODE OPTIMIZATION TECHNIQUES

AIM:

To write a C program to implement the code optimization techniques.

ALGORITHM:

1. Start
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 go to 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 from the input file.
9. Perform these steps 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 in the three address code.
13. If the operand is not used, then eliminate the complete expression from the three address
code else go to 14.
14. Perform steps 11 to 13 for all the operands in the three address code till end of file is
reached.
15.Stop..
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 no of values");
scanf("%d", & n);
for (i = 0; i < n; i++)
{
printf("\tleft\t");
op[i].l = getche();
printf("\tright:\t");
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\n");
for (k = 0; k < z; k++)
{
printf("%c\t=", pr[k].l);
printf("%s\n", pr[k].r);
}

//sub expression elimination


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);
}
// duplicate production elimination

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");
for (i = 0; i < z; i++)
{
if (pr[i].l != '\0') {
printf("%c=", pr[i].l);
printf("%s\n", pr[i].r);
} } getch();
}

OUTPUT:
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
eliminate common expression
b =c+d
b =c+d
f =b+b
r =f
optimized codeb=c+d
f=b+b
r=f

RESULT:

Thus the above program is compiled and executed successfully and output is verified.

1 of 15

You might also like