FINAL CS3501 Compiler Design LAB
FINAL CS3501 Compiler Design LAB
ARMCET
(Approved by AICTE & Affiliated to Anna University)
Registration Number :
Department :
Year of Study :
Semester :
ARM COLLEGE OF ENGINEERING AND TECHNOLOGY
SATTAMANGALAM, MARAIMALAI NAGAR, CHENNAI, TAMIL NADU. PIN-603 209.
ARMCET
(Approved by AICTE & Affiliated to Anna University)
BONAFIDE CERTIFICATE
Reg. No.
EX. NO:
DATE:
INTRODUCTION:
ALGORITHM:
#includecstdio.hS
#includecconio.hS
#includecmalloc.hS
#includecstring.hS
#includecmath.hS
#includecctype.hS
void main()
char ch,srch,b[15],d[15],c;
//clrscr();
while((c=getchar())!='$')
b[i]=c; i++;
n=i-1;
printf("given expression:");
i=O;
lOMoAR cPSD| 8002735
while(ic=n)
printf("%c",b[i]); i++;
printf("symbol table\n");
printf("symbol\taddr\ttype\n");
while(jc=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);
else
ch=b[j+1];
if(ch=='+'||ch=='-'||ch=='*'||ch=='=')
p=malloc(c);
add[x]=p;
d[x]=c;
printf("%c\t%d\tidentifier\n",c,p);
x++;
} j++;
}
lOMoAR cPSD| 8002735
srch=getch();
for(i=O;ic=x;i++)
if(srch==d[i])
printf("symbol found\n");
printf("%c%s%d\n",srch,"@address",add[i]);
flag=1;
if(flag==O)
//getch();
lOMoAR cPSD| 8002735
OUTPUT:
RESULT:
Thus the C program to implement the symbol table was executed and the output is verified.
lOMoAR cPSD| 8002735
EX. NO:
DATE:
DEVELOP A LEXICAL ANALYZER TO RECOGNIZE
A FEW PATTERNS IN C
AIM:
INTRODUCTION:
TOKEN
ALGORITHM:
#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");
lOMoAR cPSD| 8002735
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;
lOMoAR cPSD| 8002735
} 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
lOMoAR cPSD| 8002735
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();
}
lOMoAR cPSD| 8002735
OUTPUT:
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.
lOMoAR cPSD| 8002735
EX.NO:
DATE:
AIM:
INTRODUCTION:
THEORY:
LEX SOURCE:
lOMoAR cPSD| 8002735
ALGORITHM:
#includecstdio.hS
#includecctype.hS
#includecconio.hS
#includecstring.hS
char vars[1OO][1OO];
int vcnt;
char input[1OOO],c;
char token[5O],tlen;
int state=O,pos=O,i=O,id;
char *getAddress(char str[])
{
for(i=O;icvcnt;i++)
if(strcmp(str,vars[i])==O)
lOMoAR cPSD| 8002735
return vars[i];
strcpy(vars[vcnt],str);
return vars[vcnt++];
}
int isrelop(char c)
{
if(c=='+'||c=='-'||c=='*'||c=='/'||c=='%'||c=='^')
return 1;
else
return O;
}
int main(void)
{
clrscr();
printf("Enter the Input String:");
gets(input);
do
{
c=input[pos];
putchar(c);
switch(state)
{
case O:
if(isspace(c))
printf("\b");
if(isalpha(c))
{
token[O]=c;
tlen=1;
state=1;
}
if(isdigit(c))
state=2;
if(isrelop(c))
state=3;
if(c==';')
printf("\tc3,3S\n");
if(c=='=')
lOMoAR cPSD| 8002735
printf("\tc4,4S\n");
break;
case 1:
if(!isalnum(c))
{
token[tlen]='\o';
printf("\b\tc1,%pS\n",getAddress(token));
state=O;
pos--;
}
else
token[tlen++]=c;
break;
case 2:
if(!isdigit(c))
{
printf("\b\tc2,%pS\n",&input[pos]);
state=O;
pos--;
}
break;
case 3:
id=input[pos-1];
if(c=='=')
printf("\tc%d,%dS\n",id*1O,id*1O);
else{
printf("\b\tc%d,%dS\n",id,id);
pos--;
}state=O;
break;
}
pos++;
}
while(c!=O);
getch();
return O;
}
lOMoAR cPSD| 8002735
OUTPUT
RESULT:
Thus the program for the exercise on lexical analysis using lex has been successfully
executed and output is verified.
lOMoAR cPSD| 8002735
EX.NO:
DATE:
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 /.
PROGRAM:
#include<stdio.h>
#include<conio.h>
void main()
{ char s[5];
clrscr();
printf("\n Enter any operator:");
gets(s);
switch(s[0])
{
case'>': if(s[1]=='=')
printf("\n Greater than or equal");
else
printf("\n Greater than");
break;
lOMoAR cPSD| 8002735
case'<': if(s[1]=='=')
printf("\n Less than or equal");
else
printf("\nLess than");
break;
case'=': if(s[1]=='=')
printf("\nEqual to");
else
printf("\nAssignment");
break;
case'!': if(s[1]=='=')
printf("\nNot Equal");
else
printf("\n Bit Not");
break;
case'&': if(s[1]=='&')
printf("\nLogical AND");
else
printf("\n Bitwise AND");
break;
case'|': if(s[1]=='|')
printf("\nLogical OR");
else
printf("\nBitwise OR");
break;
case'+': printf("\n Addition");
break;
case'-': printf("\nSubstraction");
break;
case'*': printf("\nMultiplication");
break;
case'/': printf("\nDivision");
break;
case'%': printf("Modulus");
break;
default: printf("\n Not a operator"); } getch(); }
lOMoAR cPSD| 8002735
OUTPUT:
RESULT:
Thus the program for the exercise on the syntax using YACC has been executed
successfully and Output is verified.
lOMoAR cPSD| 8002735
EX.NO:
DATE:
variable_test.l
%{
/* This LEX program returns the tokens for the Expression */
#include "y.tab.h"
%}
%%
"int " {return INT;}
"float" {return FLOAT;}
"double" {return DOUBLE;}
[a-zA-Z]*[O-9]*{
printf("\nIdentifier is %s",yytext);
return ID;
}
return yytext[O];
\n return O;
int yywrap()
{
return 1;
}
variable_test.y
%{
#include
/* This YACC program is for recognising the Expression*/
%}
%token ID INT FLOAT DOUBLE
%%
D;T L
;
L:L,ID
|ID
;
T:INT
|FLOAT
|DOUBLE
;
%%
extern FILE *yyin;
main()
lOMoAR cPSD| 8002735
{
do
{
yyparse();
}while(!feof(yyin));
}
yyerror(char*s)
{
}
OUTPUT:
RESULT:
Thus the program for the exercise on the syntax using YACC has been executed
successfully and Output is verified.
lOMoAR cPSD| 8002735
EX.NO.
DATE:
PROGRAM:
%{
#includecstdio.hS
int op=O,i;
float a,b;
%}
dig[O-9]+|([O-9]*)"."([O-9]+)
add "+"
sub "-"
mul"*"
div "/"
pow "^"
ln \n
%%
{dig}{digi();}
{add}{op=1;}
{sub}{op=2;}
{mul}{op=3;}
{div}{op=4;}
{pow}{op=5;}
%%
digi()
if(op==O)
a=atof(yytext);
lOMoAR cPSD| 8002735
else
b=atof(yytext);
switch(op)
case 1:a=a+b;
break;
case 2:a=a-b;
break;
case 3:a=a*b;
break;
case 4:a=a/b;
break;
case 5:for(i=a;bS1;b--)
a=a*i;
break;
op=O;
yylex();
yywrap()
return 1;
}
lOMoAR cPSD| 8002735
OUTPUT:
Lex cal.l
Cc lex.yy.c-ll
a.out
4*8
The result=32
RESULT:
Thus the program for the exercise on the syntax using YACC has been executed
EX.NO:
DATE:
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
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.
#includecstdio.hS
char str[5O],opstr[75];
int f[2][9]={2,3,4,4,4,O,6,6,O,1,1,3,3,5,5,O,5,O};
int col,col1,col2;
char c;
swt()
{
switch(c)
{
lOMoAR cPSD| 8002735
case'+':col=O;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 O;
}
main()
{
int i=O,j=O,col1,cn,k=O;
int t1=O,foundg=O;
char temp[2O];
clrscr();
printf("\nEnter arithmetic expression:");
scanf("%s",&str);
while(str[i]!='\O')
i++;
str[i]='$';
str[++i]='\O';
printf("%s\n",str);
come:
i=O;
opstr[O]='$';
j=1;
c='$';
swt();
col1=col;
c=str[i];
swt();
col2=col;
lOMoAR cPSD| 8002735
if(f[1][col1]Sf[2][col2])
{
opstr[j]='S';
j++;
}
else if(f[1][col1]cf[2][col2])
{
opstr[j]='c';
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[O][col1]Sf[1][col2])
{
opstr[j]='S';
j++;
}
else if(f[O][col1]cf[1][col2])
{
opstr[j]='c';
j++;
}
else
{
opstr[j]='=';j++;
lOMoAR cPSD| 8002735
}
i++;
}
opstr[j]='$';
opstr[++j]='\O';
printf("\nPrecedence Input:%s\n",opstr);
i=O;
j=O;
while(opstr[i]!='\O')
{
foundg=O;
while(foundg!=1)
{
if(opstr[i]=='\O')goto redone;
if(opstr[i]=='S')foundg=1;
t1=i;
i++;
}
if(foundg==1)
for(i=t1;iSO;i--)
if(opstr[i]=='c')break;
if(i==O){printf("\nERROR\n");exit(1);}
cn=i;
j=O;
i=t1+1;
while(opstr[i]!='\O')
{
temp[j]=opstr[i];
j++;i++;
}
temp[j]='\O';
opstr[cn]='E';
opstr[++cn]='\O';
strcat(opstr,temp);
printf("\n%s",opstr);
i=1;
}
redone:k=O;
lOMoAR cPSD| 8002735
while(opstr[k]!='\O')
{
k++;
if(opstr[k]=='c')
{
Printf("\nError");
exit(1);
}
}
if((opstr[O]=='$')&&(opstr[2]=='$'))goto sue;
i=1
while(opstr[i]!='\O')
{
c=opstr[i];
if(c=='+'||c=='*'||c=='/'||c=='$')
{
temp[j]=c;j++;}
i++;
}
temp[j]='\O';
strcpy(str,temp);
goto come;
sue:
printf("\n success");
return O;
}
lOMoAR cPSD| 8002735
OUTPUT:
lOMoAR cPSD| 8002735
RESULT:
Thus the program has been executed successfully and Output is verified.
lOMoAR cPSD| 8002735
EX.NO:
DATE:
AIM:
INTRODUCTION:
Data flow analysis is a technique for gathering information about the possible set of
value calculated at various points in a computer program.
Control flow analysis can be represent by basic blocks. It depicts how th program
control is being passed among the blocks.
ALGORITHM:
#includecconio.hS
struct stack
{
int no;
struct stack *next;
}
*start=null
typedef struct stack st;
voidpush();
int pop();
voiddisplay();
voidmain()
{
char ch;
int choice, item;
do
{
clrscr();
printf(“\n1:push”);
printf(“\n2:pop”);
printf(“\n3:display”);
printf(“\n enter your choice”);
scanf(“%d”,&choice);
switch(choice)
{
case1:push();
break;
case2:item=pop();
printf(“the delete element in %d”,item);
break;
case3:display();
break;
default:printf(“\nwrong choice”);
};
lOMoAR cPSD| 8002735
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-Sno);
node-Snext=start;
start=node;
}
intpop();
{
st*temp;
temp=start;
if(start==null)
{
printf(“stack is already empty”);
getch();
exit();
}
else
{
start=start-Snext;
free(temp);
}
return(temp-Sno);
}
void display()
{
st*temp;
temp=start;
while(temp-Snext!=null)
{
lOMoAR cPSD| 8002735
printf(“\nno=%d”,temp-Sno);
temp=temp-Snext;
}
printf(“\nno=%d”,temp-Sno);
}
OUTPUT:
lOMoAR cPSD| 8002735
RESULT:
Thus the C program to implement data flow and control flow analysis was
executed successfully.
lOMoAR cPSD| 8002735
EX.NO:
DATE:
IMPLEMENT THE BACK END OF THE COMPILER
AIM:
To implement the back end of the compiler which takes the three address code and produces
the 8086 assembly language instructions that can be assembled and run using a 8086
assembler. The target assembly instructions can be simple move, add, sub, jump. Also
simple addressing modes are used.
INTRODUCTION:
A compiler is a computer program that implements a programming language specification to
“translate” programs, usually as a set of files which constitute the source code written in
source language, into their equivalent machine readable instructions(the target language, often
having a binary form known as object code). This translation process is called compilation.
BACK END:
Some local optimization
Register allocation
Peep-hole optimization
Code generation
Instruction scheduling
The main phases of the back end include the following:
Analysis: This is the gathering of program information from the intermediate
representation derived from the input; data-flow analysis is used to build use-define
chains, together with dependence analysis, alias analysis, pointer analysis, escape
analysis etc.
Optimization: The intermediate language representation is transformed into
functionally equivalent but faster (or smaller) forms. Popular optimizations are
expansion, dead, constant, propagation, loop transformation, register allocation and
even automatic parallelization.
Code generation: The transformed language is translated into the output language,
usually the native machine language of the system. This involves resource and storage
decisions, such as deciding which variables to fit into registers and memory and the
selection and scheduling of appropriate machine instructions along with their
associated modes. Debug data may also need to be generated to facilitate debugging.
lOMoAR cPSD| 8002735
ALGORITHM:
#includecstdio.hS
#includecstdio.hS
//#includecconio.hS
#includecstring.hS
void main()
char icode[1O][3O],str[2O],opr[1O];
int i=O;
//clrscr();
do
scanf("%s",icode[i]);
} while(strcmp(icode[i++],"exit")!=O);
printf("\n************************");
i=O;
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[O]);
}while(strcmp(icode[++i],"exit")!=O);
//getch();
}
lOMoAR cPSD| 8002735
OUTPUT:
RESULT:
Thus the program was implemented to the TAC has been successfully executed.
lOMoAR cPSD| 8002735
EX.NO:
DATE:
INTRODUCTION:
In optimization, high-level general programming constructs are replaced by very efficient low
level programming codes. A code optimizing process must follow the three rules given
below:
The output code must not, in any way, change the meaning of the program.
Optimization should increases the speed of the program and if possible, the program
should demand less number of resources.
Optimization should itself be fast and fast and should not delay the overall compiling
process.
Efforts for an optimized code can be made at various levels of compiling the process.
At the beginning, users can change/rearrange the code or use better algorithms to write
the code.
After generating intermediate code, the compiler can modify the intermediate code by
address calculations and improving loops.
While producing the target machine code, the compiler can make use of memory
hierarchy and cpu registers.
Optimization can be categorized broadly into two types: Machine independent and Machine
dependent.
In this optimization, the compiler takes in the intermediate code and transforms a part of the
code that does not involve any CPU registers and/or absolute memory locations.
For Example:
do
{
item=1O;
value=value+item;
}while(valuec1OO);
lOMoAR cPSD| 8002735
This code involves repeated assignment of the identifier item, which if we put this way:
item=1O;
do
value=value+item;
}while(valuec1OO);
Should not only save the cpu cycles, but can be used on any processor.
Machine dependent optimization is done after the target code has been generated and when
the code is transformed according to the target machine architecture. It involves CPU registers
and may have absolute memory references rather than relative references. Machine-
dependent optimizers put efforts to take maximum advantage of memory hierarchy.
ALGORITHM:
Before:
Using for :
#includeciostream.hS
#include cconio.hS
int main()
int i, n;
int fact=1;
cinSSn;
for(i=n;iS=1;i--)
fact=fact *i;
getch();
return O;
OUTPUT:
lOMoAR cPSD| 8002735
Using do-while:
#includeciostream.hS
#includecconio.hS
void main()
clrscr();
int n,f;
f=1;
cinSSn;
do
f=f*n;
n--;
}while(nSO);
getch();
}
lOMoAR cPSD| 8002735
OUTPUT:
RESULT: