Labmanual Compiler Design
Labmanual Compiler Design
Labmanual Compiler Design
Prepared by,
Ms.R.LAVANYA.M.E
Assistant Professor
Department of Information Technology
EGSPEC, Nagapattinam
IT6612 COMPILER LABORATORY LTPC
0032
OBJECTIVES: The student should be made to:
Be exposed to compiler writing tools.
Learn to implement the different Phases of compiler
Be familiar with control flow and data flow analysis
Learn simple optimization techniques
LIST OF EXPERIMENTS:
1. Implementation of Symbol Table
2. Develop a lexical analyzer to recognize a few patterns in C.
(Ex. identifiers, constants, comments, operators etc.)
3. Implementation of Lexical Analyzer using Lex Tool
4. Generate YACC specification for a few syntactic categories.
a) Program to recognize a valid arithmetic expression that usesoperator +, - , * and /.
b) Program to recognize a valid variable which starts with a letterfollowed by any number of
letters or digits.
c)Implementation of Calculator using LEX and YACC
5. Convert the BNF rules into Yacc form and write code to generate Abstract Syntax Tree.
6. Implement type checking
7. Implement control flow analysis and Data flow Analysis
8. Implement any one storage allocation strategies(Heap,Stack,Static)
9. Construction of DAG
10. 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.
11. Implementation of Simple Code Optimization Techniques (Constant Folding, etc.)
TOTAL: 45 PERIODS
OUTCOMES: At the end of the course, the student should be able to
Implement the different Phases of compiler using tools
Analyze the control flow and data flow of a typical program
Optimize a given program
Generate an assembly language program equivalent to a source language program
AIM:
To write a program in C for implementing Symbol Table.
ALGORITHM
1.Start the program.
2. Declare the variables.Get the character and check it using while Loop.
3.If n value is less than or equal to I then print the symbol address and type.Again check the n
value with j.
4.The C value is changed to ASCII and check it using if statement.Store the C value in P and
print the identifier.
Else check the character is equal to +, -, *, /, (,) using if statement. Store the C value in P and
print the operator.
5. Enter any symbol to find in the Symbol Table.
6.Stop the program.
PROGRAM:
#include<stdio.h>
#include<conio.h>
#include<alloc.h>
#include<ctype.h>
void main()
{
int j=0,i=0,x=0,n;
int flag=0;
int *p,*add[10];
char c,ch='y',srch,b[10],d[10];
clrscr();
printf("\ nEnter an expression and it is terminated by $");
while((c=getchar())!='$')
{
b[i]=c;
i++;
}
n=i-1;
i=0;
printf("Symbol Table \n");
printf(" \nSymbol\t\tAddress\t\ttype");
while(j<=n)
{
c=b[j];
if(isalpha(toascii(c)))
{
p=malloc(c);
add[x]=p;
d[x]=c;
printf(" \n\t%c\t\t%d\t\tidentifier",c,p);
}
if(c=='+'||c=='-'||c=='*'||c=='/'||c=='='||c==')')
{
p=malloc(c);
add[x]=p;
d[x]=c;
printf(" \n\t%c\t\t%d\t\tOperator",c,p);
}
x++;
j++;
}
while(ch=='y')
{
flag=0;
printf(" \nEnter the symbol to search");
fflush(stdin);
srch=getchar();
for(i=0;i<=n;i++)
{
if(srch==d[i])
{
printf(" \nSymbol found\t");
printf("%c \t%s%d\n",srch,"@address",add[i]);
flag=1;
}
}
if(flag==0)
{
printf("Symbol not found");
}
printf("Do you want to continue (y/n): ");
fflush(stdin);
ch=getchar();
}
}
OUTPUT
Viva voce
What are the various data structures used for implementing the symbol table?
1.Linear list 2.binary tree 3. hash table
Ex. No: 2 Develop a lexical analyzer to recognize a few patterns in C.
(Ex. identifiers, constants, comments, operators etc
Date:
Aim:
To write a C program to develop a lexical analyzer to recognize a few patterns in C. (Ex.
identifiers, constants, comments, operators etc.
Algorithm:
1.Start the program.
2.Intialize the symbol table with keywords.
3.Read token by token from the input string.
4.Using finite automation check for keywords, identifiers, constants & thenOperators
successively.
5.If nothing matches print an error message.
6.Until all tokens are over, repeat above three steps.
7.Print token information.
8.Stop.
Program:
Lexical.C:
#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
Result:
The above C program was successfully executed and verified
Ex. No:3 Implementation of Lexical Analyzer using Lex Tool
Date:
Algorithm:
Program:
Lextool.l
%{
%}
identifier[a-zA-Z][a-zA-Z0-9]*
%%
#.* printf("\n%s is PREPROCESSOR DIRECTIVE\n", yytext);
int |
float |
double |
char |
for |
if printf("%s is a keyword\n",yytext);
{identifier}\( printf("\n\n FUNCTION CALL\n %s",yytext);
\{
printf("BLOCK BEGINS\n");
\}
printf("BLOCK ENDS\n");
{identifier}(\[[0-9]*\])? printf("%s is identifier\n",yytext);
= printf("%s is a ASSIGNMENT OPERATOR\n",yytext);
[0-9]+ printf("%s is NUMBER\n",yytext);
\< |
\> |
\== |
\>= |
\<= printf("%s is a RELATIONAL OPERATOR\n",yytext);
\( printf("open para\n");
\) printf("close para\n");
\+ |
\- |
\* printf("%s is a ARITHMETIC OPERATOR \n",yytext);
\++ printf("%s is a INCREMENTAL OPERATOR\n",yytext);
\; { ECHO; printf("\n");}
%%
main()
{
yylex();
}
int yywrap()
{
return 1;
}
Output
Ex.no 4a Program to recognize a valid arithmetic expression that
Date: Usesoperator +, - , * and /.
Aim :To write a yacc and lex program to recognize a valid arithmetic expression that uses
operator+,-,* and /.
Algorithm:
Input: Programming language arithmetic expression
Output: A sequence of tokens.
Tokens have to be identified and its respective attributes have to be printed.
Lex:
1. {Declaration and regular definition]
Define header files to include first section
2. [translation rule]
Tokens generated are used in yacc files
[a-z A-Z] alphabets are returned
0-9 one or more combinations of integers
Yacc:
1. Accept token generated in lex part as input
2. Specify the order of procedure
3. Define rules with end points
4. Parse input string from standard input by calling yyparse() main function.
5. Print the result of any rules defined matches as arithmetic expression as valid
6. If none of the rule defined matches print arithmetic expression is invalid.
Program:
Yacc4a.y(without lex only yacc program)
%{
#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 exoression to validate :");
yyparse();
}
yylex()
{
int ch;
while((ch=getchar())==' ');
if(isdigit(ch))
return num;
if(isalpha(ch))
return let;
return ch;
}
yyerror(char *s)
{
printf("%s",s);
}
Output :
Lex program (with lex and yacc)
%{
#include"y.tab.h"
extern yylval;
%}
%%
[0-9]+ {yylval=atoi(yytext); return NUMBER;}
[a-zA-Z]+ {return ID;}
[\t]+ ;
\n {return 0;}
. {return yytext[0];}
%%
int yywrap()
{
return(1);
}
Yacc program
%{
#include<stdio.h>
%}
%token NUMBER ID
%left '+' '-'
%left '*' '/'
%%expr:
expr '+' expr
|expr '-' expr
|expr '*' expr
|expr '/' expr
|'-'NUMBER|'-'ID
|'('expr')'
|NUMBER
|ID
;
%%
main()
{
printf("Enter the expression\n");
yyparse();
printf("\nExpression is valid\n");
exit(0);
}
int yyerror(char *s)
{
printf("\nExpression is invalid");
exit(0);
}
Output
Ex.no :4b Program to recognize a valid variable which starts with a
letterfollowed by any number of letters or digits
Aim: To write a yacc & lex program to recognize a valid variable which starts with a letter
followed by any number of letters or digits.
Algorithm:
Input: Programming language 'if' statement
Output: A sequence of tokens.
Tokens have to be identified and its respective attributes have to be printed
Output
Program: with lex and yacc
Yacc 4b.l
%{
#include"y.tab.h"
extern yylval;
%}
%%
[0-9]+ {yylval=atoi(yytext); return DIGIT;}
[a-zA-Z]+ {return LETTER;}
[\t] ;
\n return 0;
. {return yytext[0];}
%%
Yacc 4b.y
%{
#include<stdio.h>
%}
%token LETTER DIGIT
%%
variable: LETTER|LETTER rest
;
rest: LETTER rest
|DIGIT rest
|LETTER|DIGIT;
%%
main()
{
yyparse();
printf("The string is a valid variable\n");
}
int yyerror(char *s)
{
printf("this is not a valid variable\n");
exit(0);
}
Output
Ex.no :4c: Implementation of Calculator using LEX and YACC
Date :
Aim: To write a lex and yacc program to implement Calculator.
Algorithm:
1. Start the program.
2.Perform the calculation using both the lex and yacc.
3.In the lex tool, if the given expression contains numbers and letters then they are displayed.
4.In the same way, the digits, letters and uminus are identified and displayed using yacctool.
5.The calculation is performed and the result is displayed.
6.Stop the program
Program: Calci.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);
}
Program:calci.y
%{
#include<stdio.h>
int yylex(void);
%}
%union
{
float dval;
}
%token <dval> NUMBER
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS
%type <dval> exp
%%
state : exp {printf("Answer = %fn",$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
EX.NO:5 Convert the BNF rules into Yacc form and write code to
DATE:Generate abstract syntax tree.
Aim:To convert The BNF rules into Yacc form and write code to generate abstract syntax tree
Algorithm:
Step1: Start the program.
Step2: Declare the declarations as a header file {include}
Step3: Declare the token digit.
Step4: 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) % %
Step5: define the supporting C routines
Step6: Stop
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:
$lex int.l
$yacc d int.y
$gcc lex.yy.c y.tab.c ll lm
$./a.out test.c
Ex.no :6 Implement type checking
Date:
Algorithm:
AIM:
To develop a C program to test whether a given identifier is valid or not.
ALGORITHM:
Read the given input string.
Check the initial character of the string is numerical or any special character
except _ then print it is not a valid identifier.
Otherwise print it as valid identifier if remaining characters of string doesnt
contains any special characters except _
PROGRAM
#include<stdio.h>
#include<conio.h>
#include<ctype.h>
void main()
{
char a[10];
int flag, i=1;
clrscr();
printf("
\
n Enter an identifier:");
gets(a);
if(isalpha(a[0]))
flag=1;
else
printf("
\
n Not a valid identifier");
while(a[i]!='
\
0')
{
if(!isdigit(a[i])&&!isalpha(a[i]))
{
flag=0;
break;
}
i++;
}
if(flag==1)
printf("
\
n Valid identifier");
getch();
}
OUTPUT:
Input
:
Enter an identifier: first
Output:
Valid
identifier
Enter an identifier:1aqw
Not a valid identifier
Ex.no:7 Implement control flow analysis and Data flow Analysis
Algorithm:
Step1:
Program:
# include<stdio.h>
# include<conio.h>
#include<alloc.h>
#include<string.h>
struct Listnode
{
char data[50];
int leader,block,u_goto,c_goto;
struct Listnode *next;
char label[10],target[10];
}*temp,*cur,*first=NULL,*last=NULL,*cur1;
FILE *fpr;
void createnode(char code[50])
{
temp=(struct Listnode *)malloc(sizeof(struct Listnode));
strcpy(temp->data,code);
strcpy(temp->label,'\0');
strcpy(temp->target,'\0');
temp->leader=0;
temp->block=0;
temp->u_goto=0;
temp->c_goto=0;
temp->next=NULL;
if(first==NULL)
{
first=temp;
last=temp;
}
else
{
last->next=temp;
last=temp;
}}
void printlist()
{
cur=first;
printf("\nMIR code is \n\n");
while(cur!=NULL)
{
printf("\ncode:%s",cur->data);
printf("\nleader:%d\t",cur->leader);
printf("block:%d\t",cur->block);
printf("u_goto:%d\t",cur->u_goto);
printf("c_goto:%d\t",cur->c_goto);
printf("label:%s\t",cur->label);
printf("target:%s\n",cur->target);
cur=cur->next;
}}
void main()
{
char codeline[50];
char c,dup[50],target[10];
char *substring,*token;
int i=0,block,block1;
int j=0;
fpr= fopen("input.txt","r");
clrscr();
while((c=getc(fpr))!=EOF)
{
if(c!='\n')
{
codeline[i]=c;
i++;
}
else
{
codeline[i]='\0';
createnode(codeline);
i=0;
}}
//create last node
codeline[i]='\0';
createnode(codeline);
fclose(fpr);
// printlist();
if(strstr(cur->data,":")!=NULL)
{
strcpy(dup,cur->data);
token=strtok(dup,":");
// printf("\ntoken:%s",token);
if(token!=NULL)
strcpy(cur->label,token);
}
cur=cur->next;
}
// printlist();
//to identify blocks
cur=first;
while(cur!= NULL)
{
cur=cur->next;
if((cur->leader)==1)
{
j++;
cur->block=j;
}
else
cur->block=j;
}
// printlist();
if ((cur->block)==j)
{
printf("%s",cur->data);
printf("\n\t");
cur=cur->next;
}
else
{
j++;
printf("\nBlock %d:",j);
}}
//to output the control flow from each block
printf ("\t\t.......Control Flow.......\n\n");
cur=first;
i=0;
while(cur!=NULL)
{
if((cur->block)!=(cur->next)->block)
{
block=cur->block;
if(cur->u_goto==1)
{
strcpy(target,cur->target);
cur1=first;
while(cur1!=NULL)
{
if(strcmp(cur1->label,target)==0)
{
block1=cur1->block;
printf("\t\tBlock%d---------->Block%d\n",block,block1);
}
cur1=cur1->next;
}
}
else if(cur->c_goto==1)
{
strcpy(target,cur->target);
cur1=first;
while(cur1!=NULL)
{
if(strcmp(cur1->label,target)==0)
{
block1=cur1->block;
printf("\t\tBlock%d---TRUE--->Block%d---FALSE--->Block%d\n",block,block1,(block+1));
}
cur1=cur1->next;
}
}
else if(strstr(cur->data,"return")==NULL)
{
printf("\t\tBlock%d---------->Block%d\n",block,(block+1));
}
else
printf("\t\tBlock%d---------->NULL\n",block);
}
cur=cur->next;
}
cur=last;
block= cur->block;
printf("\t\tBlock%d--------->NULL",block);
getch();
}
Program:
#include <stdio.h>
#define MAXNUM 3
void sum_up(void);
int main()
{
int count;
printf("\n*****static storage*****\n");
printf("Key in 3 numbers to be summed ");
for(count = 0; count < MAXNUM; count++)
sum_up();
printf("\n*****COMPLETED*****\n");
return 0;
}
void sum_up(void)
{
/* at compile time, sum is initialized to 0 */
static int sum = 0;
int num;
printf("\nEnter a number: ");
scanf("%d", &num);
sum += num;
printf("\nThe current total is: %d\n", sum);
}
Output:
Ex.no: 9 Construction of DAG
Date:
Case 2: else if Node's left child's label >= 1 && Node's right child's label == 0
{
gencode(Node's left child);
print "op Node's right child's data,R[top]"
}
Case 3: else if Node's left child's label < Node's right child's label
{
int temp;
Swap Register Stack's top and second top element;
gencode(Node's right child);
temp=pop();
gencode(Node's left child);
push(temp);
Swap Register Stack's top and second top element;
print "op R[top-1],R[top]"
}
Case 4: else if Node's left child's label >= Node's right child's label
{
int temp;
gencode(Node's left child);
temp=pop();
gencode(Node's right child);
push(temp);
print "op R[top-1],R[top]"
}
else if Node is leaf node and it is left child of it's immediate parent
{
print "MOV Node's data,R[top]"
}
}
Program:
#include<stdlib.h>
#include<iostream>
using namespace std;
/* We will implement DAG as Strictly Binary Tree where each node has zero or two children */
struct bin_tree
{
char data;
int label;
struct bin_tree *right, *left;
};
typedef bin_tree node;
class dag
{
private:
/* R is stack for storing registers */
int R[10];
int top;
/* op will be used for opcode name w.r.t. arithmetic operator e.g. ADD for + */
char *op;
public:
void initializestack(node *root)
{
/* value of top = index of topmost element of stack R = label of Root of tree(DAG) minus one */
top=root->label - 1;
insert(&(*tree)->left,l);
insert(&(*tree)->right,r);
}
}
/* findleafnodelabel() will find out the label of leaf nodes of tree(DAG) */
void findleafnodelabel(node *tree,int val)
{
if(tree->left != NULL && tree->right !=NULL)
{
findleafnodelabel(tree->left,1);
findleafnodelabel(tree->right,0);
}
else
{
tree->label=val;
}
}
/* findinteriornodelabel() will find out the label of interior nodes of tree(DAG) */
void findinteriornodelabel(node *tree)
{
if(tree->left->label==-1)
{
findinteriornodelabel(tree->left);
}
else if(tree->right->label==-1)
{
findinteriornodelabel(tree->right);
}
else
{
};
int main()
{
node *root;
root = NULL;
node *tmp;
char val;
int i,temp;
dag d;
d.insert(&root,val);
return 0;
}
Output1:
OUTPUT2:
Ex.no: 10 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.
Algorithm:
Input: Set of three address code sequence.
Output: Assembly code sequence for three address codes (opd1=opd2, op, opd3).
Method:
1- Start the program
2- Get address code sequence.
3- Determine current location of 3 using address (for 1st operand).
4- If current location not already exist generate move (B,O).
5- Update address of A(for 2nd operand).
6- If current value of B and () is null, exist.
7- If they generate operator () A,3 ADPR.
8- Store the move instruction in memory.
9- Stop.
Program:
#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
EX.NO:11 IMPLEMENTATION OF CODE OPTIMIZATION TECHNIQUES
AIM:
ALGORITHM:
The code generation algorithm takes as input a sequence of three address statements
constituting a basic block. For each three address statement of the form x := y op z we
perform the following actions:
1. Invoke a function getreg to determine the location L where the result of the computation y op
z should be stored. L will usually be a register, but it could also be a memory location.
2.We shall describe getreg shortly, L to place a copy of y in L. if the value of y is currently both
in memory and a register. If the value of y is not already in L, generate the instruction MOV y,
(one of) the current location(s) of y. prefer the register for y.
3. Consult the address descriptor for y to determine yis a current location of z. Again, prefer a
register to a memory location if z is in both.
4.Update the address descriptor of x to indicate that x is in location L. If L is a register, update its
descriptor to indicate that it contains the value of x, and remove x from all other register
descriptors., L where z.
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("left\t");
op[i].l=getche();
printf("right:\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);
}
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:
Beyond the syllabus
#include<stdlib.h>
#include<conio.h>
#include<string.h>
char ip_sym[15],stack[15];
int ip_ptr=0,st_ptr=0,len,i;
char temp[2],temp2[2];
char act[15];
void check();
void main()
clrscr();
printf("\n GRAMMER\n");
gets(ip_sym);
printf("\n________\t\t____________\t\t____________\n");
printf("\n $\t\t%s$\t\t\t--",ip_sym);
strcpy(act,"shift");
temp[0]=ip_sym[ip_ptr];
temp[1]='\0';
strcat(act,temp);
len=strlen(ip_sym);
for(i=0;i<=len-1;i++)
stack[st_ptr]=ip_sym[ip_ptr];
stack[st_ptr+1]='\0';
ip_sym[ip_ptr]=' ';
ip_ptr++;
printf("\n $%s\t\t%s$\t\t\t%s",stack,ip_sym,act);
strcpy(act,"shift");
temp[0]=ip_sym[ip_ptr];
temp[1]='\0';
strcat(act,temp);
check();
st_ptr++;
st_ptr++;
check(); }
void check()
{int flag=0;
temp2[0]=stack[st_ptr];
temp2[1]='\0';
if((!strcmpi(temp2,"a"))||(!strcmpi(temp2,"b")))
stack[st_ptr]='E';
if(!strcmpi(temp2,"a"))
printf("\n $%s\t\t%s$\t\t\tE->a",stack,ip_sym);
else
printf("\n $%s\t\t%s$\t\t\tE->b",stack,ip_sym);
flag=1;
if((!strcmpi(temp2,"+"))||(strcmpi(temp2,"*"))||(!strcmpi(temp2,"/")))
{flag=1;
if((!strcmpi(stack,"E+E"))||(!strcmpi(stack,"E\E"))||(!strcmpi(stack,"E*E")))
{ strcpy(stack,"E");
st_ptr=0;
if(!strcmpi(stack,"E+E"))
printf("\n $%s\t\t%s$\t\t\tE->E+E",stack,ip_sym);
else
if(!strcmpi(stack,"E\E"))
printf("\n $%s\t\t%s$\t\t\tE->E\E",stack,ip_sym);
else
if(!strcmpi(stack,"E*E"))
printf("\n $%s\t\t%s$\t\t\tE->E*E",stack,ip_sym);
else
printf("\n $%s\t\t%s$\t\t\tE->E+E",stack,ip_sym);
flag=1;
} if(!strcmpi(stack,"E")&&ip_ptr==len)
printf("\n $%s\t\t%s$\t\t\tACCEPT",stack,ip_sym);
getch();
exit(0);
if(flag==0)
printf("\n%s\t\t\t%s\t\t reject",stack,ip_sym);
exit(0); }
return;
GRAMMER
E->E+E
E->E/E
E->E*E
E->a/b
Enter the input symbol: a+b
Stack Implementation Table
$E +b$ E->a
$E+ b$ shift +
$E+b $ shift b
$E+E $ E->b
$E $ E->E+E
$E $ ACCEPT
RESULT:Thus the program for implementation of Shift Reduce parsing algorithm is executed
and verified
Ex.No:13 CONSTRUCTION OF LR-PARSING TABLE
AIM:
To write a program for construction of LR Parsing table using C.
ALGORITHM:
PROGRAM:
#include<stdio.h>
#include<conio.h>
char stack[30];
int top=-1;
void push(char c)
{
top++;
stack[top]=c;
}
char pop()
{
char c;
if(top!=-1)
{
c=stack[top];
top--;
return c;
}
return'x';
}
void printstat()
{
int i;
printf("\n\t\t\t $");
for(i=0;i<=top;i++)
printf("%c",stack[i]);
}
void main()
{
int i,j,k,l;
char s1[20],s2[20],ch1,ch2,ch3;
clrscr();
printf("\n\n\t\t LR PARSING");
printf("\n\t\t ENTER THE EXPRESSION");
scanf("%s",s1);
l=strlen(s1);
j=0;
printf("\n\t\t $");
for(i=0;i<l;i++)
{
if(s1[i]=='i' && s1[i+1]=='d')
{
s1[i]=' ';
s1[i+1]='E';
printstat(); printf("id");
push('E');
printstat();
}
else if(s1[i]=='+'||s1[i]=='-'||s1[i]=='*' ||s1[i]=='/' ||s1[i]=='d')
{
push(s1[i]);
printstat();
}
}
printstat();
l=strlen(s2);
while(l)
{
ch1=pop();
if(ch1=='x')
{
printf("\n\t\t\t $");
break;
}
if(ch1=='+'||ch1=='/'||ch1=='*'||ch1=='-')
{
ch3=pop();
if(ch3!='E')
{
printf("errror");
exit();
}
else
{
push('E');
printstat();
}
}
ch2=ch1;
}
getch();
}
OUTPUT:
LR PARSING
ENTER THE EXPRESSION
id+id*id-id
$
$id
$E
$E+
$E+id
$E+E
$E+E*
$E+E*id
$E+E*E
$E+E*E-
$E+E*E-id
$E+E*E-E
$E+E*E-E
$E+E*E
$E
$
RESULT:
Thus the program for construction of LR Parsing table is executed and verified.