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

UNITED INSTITUTE OF TECHNOLOGY

Periyanaickenpalayam, Coimbatore- 641 020.

CS6612

COMPILER LABORATORY

DEPARTMENT OF COMPUTER SCIENCE AND ENGINEERING

UNITED INSTITUTE OF TECHNOLOGY


Periyanaickenpalayam, Coimbatore- 641 020.
This is to certify that the record work entitled

COMPILER LABORATORY

is the bonafide record of practical work done by

Name : ________________________________________________________

Register No : ________________________________________________________

In VI semester of B.E Computer Science and Engineering

during the academic year 2016-2017.

Staff-in-charge Head of the Department

Submitted for the University Practical Examination held on ____________________

Internal Examiner External Examiner

CONTENTS

S.NO DATE EXPERIMENTS PG.NO MARKS SIGN


1. IMPLEMENTATION OF SYMBOL TABLE

2. IMPLEMENTATION OF A LEXICAL ANALYSER


IN C

3. IMPLEMENTATION OF LEXICAL ANALYSER


USING LEXTOOL

4.a RECOGNIZE A VALID ARITHMETIC


EXPRESSION USING YACC

4.b RECOGNIZE A VALID VARIABLE USING YACC

4.c IMPLEMENTATION OF CALCULATOR USING


LEX AND YACC

5. BNF RULES INTO YAAC AND CODE TO


GENERATE ABSTRACT SYNTAX TREE

6. IMPLEMENTATION OF TYPE CHECKING

7. IMPLEMENT CONTROL FLOW ANALYSIS AND


DATA FLOW ANALYSIS

8. IMPLEMENTATION OF STORAGE ALLOCATION


STRATEGIES

9. CONSTRUCTION OF DAG

10. BACK END COMPILER

11. CODE OPTIMIZATION TECHNIQUES


EX.NO: 1
DATE: IMPLEMENTATION OF SYMBOL TABLE

AIM:
To write a C Program to generate the symbol table of the compiler.

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 in to 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<ctype.h>
#include<alloc.h>
#include<string.h>
#include<math.h>
void main()
{
int i=0,j=0,x=0,n,flag=0;
void *p,*add[5];
char ch,srch,b[15],d[15],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");
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",c,p);
}
else
{
ch=b[j+1];
if(ch=='+'||ch=='-'||ch=='*'||ch=='=')
{
p=malloc(c);
add[x]=p;
d[x]=c;
printf("\n%c\t%d\tIdentifier\n",c,p);
x++;
}
}
}
j++;
}
printf("\n The Symbol is to be searched");
srch=getch();
for(i=0;i<x;i++)
{
if(srch==d[i])
{
printf("\n Symbol Found");
printf("\n%c%s%d\n",srch,"@address",add[i]);
flag=1;
}
}
if(flag==0)
printf("\n Symbol Not Found");
getch();
}
OUTPUT:

RESULT:
Thus the C program to implement the Symbol table was executed and the output is
verified successfully.
Ex.No: 2
Date: IMPLEMENTATION OF A LEXICAL ANALYZER IN C

AIM:
To write a C program for Lexical analyser to separate its Tokens.

ALGORITHM:
1. Start the program.
2. Declare the file pointer and necessary variables.
3. Open the input file in the read mode.
4. Use the analyze function to analyze the input program and store the identifiers, keywords
and operator on input, key, oper files respectively.
5. Increment the line number of each token and its occurrences.
6. Using the show function print the linked lists in a tabular format.
7. Stop the program.

PROGRAM:
#include "stdio.h"
#include "conio.h"
void main()
{
FILE *fi,*fo,*fop,*fk;
int flag=0,i=1;
char c,t,a[15],ch[15],file[20];
clrscr();
printf("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("\t\tLEXICAL ANALYSIS \n");
fscanf(fi,"%s",a);
printf("\nline : %d\n",i++);
while(!feof(fi))
{
if((strcmp(a,"$")==0))
{
printf("\nline : %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,"%s",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();
}

INPUT
key.c
int
void
main
char
if
for
while
else
printf
scanf
FILE
include
stdio.h
conio.h
iostream.h

oper.c
( openpara
) closepara
{ openbrace
} closebrace
< lesser
> greater
" doublequote
' singlequote
: colon
; semicolon
# preprocessor
= equal
== assign
% 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:
RESULT:
Thus the Lexical Analyzer was implemented and the given string separated by the token using
C program.

EX.NO: 3
IMPLEMENTATION OF LEXICAL ANALYSER USING LEXTOOL
DATE:

AIM:
To write a C program for Lexical Analyzer using LEXTOOL to separate Delimiters,
Preprocessor directive, Header file, Identifiers and Keyword.

ALGORITHM:

1. Start the program.


2. Lex program consists of three parts.
a. Declaration %%
b. Translation rules %%
c. Auxilary procedure.
3. The declaration section includes declaration of variables, maintest, constants and regular
definitions.
4. Translation rule of lex program are statements of the form
a. P1 {action}
b. P2 {action}
c.
d.
e. Pn {action}
5. Write a program in the vi editor and save it with .l extension.
6. Compile the lex program with lex compiler to produce output file as lex.yy.c.
eg $ lex filename.l
$ gcc lex.yy.c -ll
7. Compile that file with C compiler and verify the output.
PROGRAM:
%{
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;
}
OUTPUT:
RESULT:
Thus the lexical analyzer is implemented using LEX tool.

EX.NO: 4
DATE: GENERATION OF YACC SPECIFICATION

INTRODUCTION

1. Introduction

The unix utility yacc (Yet Another Compiler Compiler) parses a stream of token, typically
generated by lex, according to a user-specified grammar.
2. Structure of a yacc file
A yacc file looks much like a lex file:
...definitions...
%%
...rules...
%%
...code...
In the example you just saw, all three sections are present:
Definitions All code between %{ and %} is copied to the beginning of the resulting C file.
Rules A number of combinations of pattern and action: if the action is more than a single
command it needs to be in braces.
Code This can be very elaborate, but the main ingredient is the call to yylex, the lexical
Analyzer. If the code segment is left out, a default main is used which only calls yylex.
3. Definitions section

There are three things that can go in the definitions section:


C code Any code between %{ and %} is copied to the C file. This is typically used for defining
file variables, and for prototypes of routines that are defined in the code segment.
Definitions The definitions section of a lex file was concerned with characters; in yacc this is
tokens. These token definitions are written to a .h file when yacc compiles this file.
Associativity Rules These handle associativity and priority of operators.
4. Lex Yacc interaction
Conceptually, lex parses a file of characters and outputs a stream of tokens; yacc accepts
stream of tokens and parses it, performing actions as appropriate. In practice, they are more
tightly coupled.
If your lex program is supplying a tokenizer, the yacc program will repeatedly call
theyylex routine. The lex rules will probably function by calling return every time they have
parsed a token. We will now see the way lex returns information in such a way that yacc can use
it for parsing.
4.1 The shared header file of return codes
If lex is to return tokens that yacc will process, they have to agree on what tokens there
are. This is done as follows.
The yacc file will have token definitions
%token NUMBER
in the definitions section.
When the yacc file is translated with yacc -d, a header file y.tab.h is created that has
definitions like
#define NUMBER 258
This file can then be included in both the lex and yacc program.
The lex file can then call return NUMBER, and the yacc program can match on this
token.
The return codes that are defined from %TOKEN definitions typically start at around 258, so that
single characters can simply be returned as their integer value:
/* in the lex program */
[0-9]+ {return NUMBER}
[-+*/] {return *yytext}
/* in the yacc program */
sum : TERMS + TERM
4.2 Return values
In the above, very sketchy example, lex only returned the information that there was a number,
not the actual number. For this we need a further mechanism. In addition to specifying the return
code, the lex parse can return a symbol that is put on top of the stack, so that yacc can access it.
This symbol is returned in the variable yylval. By default, this is defined as an int, so the lex
program would have
extern int llval;
%%
[0-9]+ {llval=atoi(yytext); return NUMBER;}
If more than just integers need to be returned, the specifications in the yacc code become more
complicated. Suppose we want to return double values, and integer indices in a table.
The following three actions are needed.
1. The possible return values need to be stated:
%union {int ival; double dval;}
2. These types need to be connected to the possible return tokens:

%token <ival> INDEX


%token <dval> NUMBER
3. The types of non-terminals need to be given:
%type <dval> expr
%type <dval> mulex

%type <dval> term


The generated .h file will now have
#define INDEX 258
#define NUMBER 259
typedef union {int ival; double dval;} YYSTYPE;
extern YYSTYPE yylval;
5. Rules section
The rules section contains the grammar of the language you want to parse. This looks like name1
: THING something OTHERTHING {action}
| othersomething THING {other action}
name2 : .....
This is the general form of context-free grammars, with a set of actions associated with each
matching right-hand side. It is a good convention to keep non-terminals (names that can be
expanded further) in lower case and terminals (the symbols that are finally matched) in upper
case.
The terminal symbols get matched with return codes from the lex tokenizer. They are typically
defines coming from %token definitions in the yacc program or character values;
6. User code section
The minimal main program is
int main()
{
yyparse();
return 0;
}
Extensions to more ambitious programs should be self-evident. In addition to the main program,
the code section will usually also contain subroutines, to be used either in the yacc or the lex
program

EX.NO:4.a RECOGNIZE A VALID ARITHMETIC EXPRESSION USING


DATE: YACC

AIM:
To write a program to recognize a valid arithmetic expression using YACC.

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

PROGRAM:
%{
#include<stdio.h>
#include<ctype.h>
%}
%token LETTER DIGIT
%left '+' '-'
%left '*' '/'
%%
st:st expr '\n' {printf("\n valid expression \n");}
| st '\n'
|
;
expr:expr '+' expr
|expr '-' expr
|expr '*' expr
|expr '/' expr
|'(' expr ')'
| NUM
| LETTER
;
NUM: DIGIT
|NUM DIGIT
;
%%
int yylex()
{
char c;
while((c=getchar())==' ');
if(isalpha(c)) return LETTER;
if(isdigit(c)) return DIGIT;
return(c);
}
int main()
{
printf("\n enter an expression\n");
yyparse();
}
int yyerror()
{
printf("invalid\n");
return 0;
}
OUTPUT:
RESULT:

Thus the program to recognize a valid arithmetic expression using YACC is done and
verified successfully.

EX.NO:4.b RECOGNIZE A VALID VARIABLE USING YACC


DATE:

AIM:
To write a program to recognize a valid variable using YACC.

ALGORITHM:
1. Start the program.
2. Declare the required variables and methods.
3. Get the input
4. Then check whether the given string is valid or not
5. Print the result
6. Stop the program

PROGRAM :
%{
#include<stdio.h>
#include<ctype.h>
%}
%token letter digit
%%

var:letter st '\n' {printf("\n string is valid variable");exit(0);}


;
st:letter st
|digit st
|letter
|digit
;
%%

int yylex()
{
char c;
while((c=getchar())==' '||c==' ');
if(isalpha(c)) return letter;
if(isdigit(c)) return digit;
return c;
}
int main()
{
printf("enter string\n");
yyparse();
}
int yyerror()
{
printf("invalid expr");
return 0;
}

OUTPUT
RESULT:

Thus the program has been completed using YACC and verified successfully.

Ex.No: 4.c
IMPLEMENTATION OF CALCULATOR USING LEX AND YACC
Date:

AIM:
To write a shell program to implement Desktop Calculator using YACC.

ALGORITHM:
1. Start the program.

2. Declare the required variables and methods.

3. Get the input using NUM{DIGIT}+(\.{DIGIT}+)? as two integer value.

4. Then check whether the given number having operator such as + \ - * /

5. After that assign first number to f1 then check if f1==0

6. If it true then op1=atof(yytext)

7. else if assign the second number to f1 then check f2== -1

8. if it true then op2=atof(yytext)

9. By using switch check the operator +,- ,* , / do the corresponding calc operation.

10. Print the result.

11. Stop the program.

PROGRAM:
LEX Program
cal.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-z0-9\b] {
c = yytext[0];
return(c);
}
YACC program
cal.y

%{
#include <stdio.h>
int regs[26];
int base;
%}
%start list
%token DIGIT LETTER
%left '|'
%left '&'
%left '+' '-'
%left '*' '/' '%'
%left UMINUS /*supplies precedence for unary minus */
%% /* beginning of rules section */
list: /*empty */
|
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 '|' 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:
RESULT:
Thus the program to implement Calculator using LEX and YACC is done and verified
successfully.

EX.NO: 5 BNF RULES INTO YACC FORM AND WRITE CODE TO


DATE:
GENERATE ABSTRACT SYNTAX TREE

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

ALGORITHM:

1. Start a program
2. declare the declarations as a header file
{include<ctype.h>}
3. token digit
4. define the translations rules like line, expr, term, factor
Line:exp \n {print(\n %d \n,$1)}
Expr:expr+ term ($$=$1=$3}
Term:term + factor($$ =$1*$3}
Factor
Factor:(enter) {$$ =$2)
%%
5. define the supporting C routines
6. Stop the program
LEX Program
<int.l>
%{
#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.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;
%}
%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].result);
}
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()
{
printf("\n Error on line no:%d",LineNo);
}
Input:
$vi 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 to convert BNF rules into Yacc form and write code to generate Abstract
Syntax Tree using LEX and YACC is done and verified successfully.

EX:NO: 6 IMPLEMENTATION OF TYPE CHECKING

DATE:

AIM:
To write a C program for implementing type checking for given expression.

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:

#include<stdio.h>

char str[50],opstr[75];

int f[2][9]={2,3,4,4,4,0,6,6,0,1,1,3,3,5,5,0,5,0};

int col,col1,col2;

char c;

swt()

switch(c)

case'+':col=0;break;

case'-':col=1;break;

case'*':col=2;break;

case'/':col=3;break;

case'^':col=4;break;

case'(':col=5;break;

case')':col=6;break;

case'd':col=7;break;

case'$':col=8;break;

default:printf("\nTERMINAL MISSMATCH\n");
exit(1);

// return 0;

main()

int i=0,j=0,col1,cn,k=0;

int t1=0,foundg=0;

char temp[20];

clrscr();

printf("\nEnter arithmetic expression:");

scanf("%s",&str);

while(str[i]!='\0')

i++;

str[i]='$';

str[++i]='\0';

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

come:

i=0;

opstr[0]='$';

c='$';

swt();

col1=col;

c=str[i];
swt();

col2=col;

if(f[1][col1]>f[2][col2])

opstr[j]='>';

j++;

else if(f[1][col1]<f[2][col2])

opstr[j]='<';

j++;

else

opstr[j]='=';j++;

while(str[i]!='$')

c=str[i];

swt();

col1=col;

c=str[++i];

swt();

col2=col;

opstr[j]=str[--i];
j++;

if(f[0][col1]>f[1][col2])

opstr[j]='>';

j++;

else if(f[0][col1]<f[1][col2])

opstr[j]='<';

j++;

else

opstr[j]='=';

j++;

i++;

opstr[j]='$';

opstr[++j]='\0';

printf("\nPrecedence Input:%s\n",opstr);

i=0;

j=0;

while(opstr[i]!='\0')

{
foundg=0;

while(foundg!=1)

if(opstr[i]=='\0')goto redone;

if(opstr[i]=='>')foundg=1;

t1=i;

i++;

if(foundg==1)

for(i=t1;i>0;i--)

if(opstr[i]=='<')break;

if(i==0){printf("\nERROR\n");exit(1);}

cn=i;

j=0;

i=t1+1;

while(opstr[i]!='\0')

temp[j]=opstr[i];

j++;i++;

temp[j]='\0';

opstr[cn]='E';

opstr[++cn]='\0';

strcat(opstr,temp);

printf("\n%s",opstr);
i=1;

redone:

k=0;

while(opstr[k]!='\0')

k++;

if(opstr[k]=='<')

Printf("\nError");

exit(1);

if((opstr[0]=='$')&&(opstr[2]=='$'))goto sue;

i=1

while(opstr[i]!='\0')

c=opstr[i];

if(c=='+'||c=='*'||c=='/'||c=='$')

temp[j]=c;j++;}

i++;

temp[j]='\0';

strcpy(str,temp);
goto come;

sue:

printf("\n success");

return 0;

OUTPUT:

RESULT:

Thus the program has been executed successfully and Output is verified.

EX.NO:7 IMPLEMENT CONTROL FLOW ANALYSIS AND DATA FLOW


DATE: ANALYSIS

AIM:
To Writs a C program to implement data flow and control flow analysis.

ALGORITHM:

1. Start the program


2. Declare the necessary variables

3. Read the input file

4. Check the statement

a. For unconditional statements, the flow of control is sequential.

b. For unconditional statements, goto the block with lables.

5. Identify the control flow through goto statements

6.Print the control flow structure identified.

7. Close the input file

8. Stop the program.

PROGRAM:

#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+");

if(fp1==NULL){

printf("file not found");

return;}

do{

c=fscanf(fp1,"%s",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,-srlen(oneword),SEEK_CUR);

printf("\n");

}while(c!=EOF);

SAMPLE.TXT:

b1;

a=a+1

b=b+a

if b<a

goto b2

else

goto b1

b2;
b--

goto b1

OUTPUT:

gcc flow.c
./a.out flow.c

B1: goes to b2 to b1
B2: goes to b1

RESULT:
Thus the C program to implement data flow and control flow analysis was executed successfully.

EX.NO:8 IMPLEMENT ANY ONE STORAGE ALLOCATION STRATEGIES


DATE: (HEAP, STACK, STATIC)

AIM:
To write a program to implement storage allocation method using STACK strategy.
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
6. Display the values
7. Stop the program
PROGRAM:

#include<stdio.h>
#include<conio.h>
struct stack
{
int no;
struct stack *next;
}
*start=NULL;
typedef struct stack st;
void push();
int pop();
void display();
void main()
{
char ch;
int choice,item;
do
{
clrscr();
printf("\n 1: push");
printf("\n 2: pop");
printf("\n 3: display");
printf("\n Enter your choice");
scanf("%d",&choice);
switch (choice)
{
case 1: push();
break;
case 2: item=pop();
printf("The delete element in %d",item);
break;
case 3: display();
break;
default : printf("\n Wrong choice");
};
printf("\n do you want to continue(Y/N)");
fflush(stdin);
scanf("%c",&ch);
}
while (ch=='Y'||ch=='y');
}
void push()
{
st *node;
node=(st *)malloc(sizeof(st));
printf("\n Enter the number to be insert");
scanf("%d",&node->no);
node->next=start;
start=node;
}
int pop()
{
st *temp;
temp=start;
if(start==NULL)
{
printf("stack is already empty");
getch();
exit();
}
else
{
start=start->next;
free(temp);
}
return(temp->no);
}
void display()
{
st *temp;
temp=start;
while(temp->next!=NULL)
{
printf("\nno=%d",temp->no);
temp=temp->next;
}
printf("\nno=%d",temp->no);
}

OUTPUT:
RESULT:
Thus the storage allocation program has been completed using stack strategy.
EX:NO: 9 CONSTRUCTION OF DAG

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

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>
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].la
bel);
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 %d
\t\t%d\t\t%d\t\t%c\n",dag[i].ptr,dag[i].left,dag[i].right,dag[i
].label);
getch();
}
OUTPUT:

RESULT:
Thus the program for implementation of DAG has been successfully executed and output is
verified.
EX.NO:10 BACK END COMPILER
DATE:

AIM:
To write a C program to implement the Back End of the Compiler.

ALGORITHM:
1. Start the program.

2. Declare the required variables and methods.

3. Get the input from the user until the usr type the word exit.

4. Check the operator which is present in the given input.

5. If the operator is be +,-,*,/ is present make strcpy to the opr.

6. Print the result.

7. Stop the program.

PROGRAM:
#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:
RESULT:
Thus the C program to implement the Back End of the Compiler is done and verified
successfully.

EX.NO: 11 CODE OPTIMIZATION


DATE:

AIM:
To write a C program for code optimization.

ALGORITHM:

1. Start the program.

2. Declare the variables and classes

3. Enter the expression and state it in the variable a,b,c.

4. Calculate the variables b & c with temp and store it in f1 and f2.

5. If (f1=null && f2=null) then expression could not be optimized.

6. Assign the results.

7. Print the results.

8. Stop the program.

PROGRAM:

#include<stdio.h>
#include<conio.h>
#include<string.h>
void main()
{
char *a,*b,*c,*temp;
int i=0,flag=0,i1=0;
char *f1,*f2;
clrscr();
printf("Enter the expression");
scanf("%s%s%s",a,b,c);
flag=0;
for(i=0;i<strlen(a);i++)
{
if(a[i]=='=')
{
flag=1;
i++;
}
if(flag)
{
*(temp +i1)=*(a+i);
i1++;
}}
*(temp+i1)='\0';
f1=strstr(b,temp);
f2=strstr(c,temp);
if(f1==NULL&&f2==NULL)
{
printf("\n expression couldn't be optimized");
exit(0);
}
printf("\n optimized code for the expression");
printf("\n\n");
printf("t1=%s\n",a);
if(strlen(f1)>0)
{
for(i=0;i<2;i++)
printf("%c",*(b+i));
printf("t1");
for(i=0;i<2;i++)
printf("%c",*(b+strlen(b)+i-2));
}
else
{
printf("%s",b);
}
printf("\n");
if(strlen(f2)>0)
{
printf("%c",*(c+strlen(c)+i-2));
}
else
{
printf("%s",c);
}
getch();
}

OUTPUT:
RESULT:
Thus the C Program for the code optimization was successfully executed and verified.

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