2 - Lab Manual - Compiler Design

Download as pdf or txt
Download as pdf or txt
You are on page 1of 31

Compiler Lab Manual

Experiment-1: Develop a Lexical Analyzer using C/C++ for a simple grammar/language of your
choice.

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 oper.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, "%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();
}
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:
Experiment-2: Generate a Scientific Calculator using LEX/YACC tools.

Program:

advance_calc.l
%{
#include <math.h>
#include "y.tab.h"
%}

%%
[0-9]+|[0-9]*\.[0-9]+ {
yylval.p = atof(yytext);
return num;
}

sin {return SIN;}


cos {return COS;}
tan {return TAN;}
log {return LOG;}
sqrt {return SQRT;}
[\t] ;
\n {return 0;}
. {return yytext[0];}
%%

advance_calc.y
%{
#include<stdio.h>
#include<math.h>

void yyerror(char *);


int yylex(void);
%}

%union //to define possible symbol types


{ double p;}
%token<p>num
%token SIN COS TAN LOG SQRT

/*Defining the Precedence and Associativity*/


%left '+''-' //lowest precedence
%left '*''/' //highest precedenc
%nonassoc uminu //no associativity
%type<p>exp //Sets the type for non-terminal

%%
/* for storing the answer */
ss: exp {printf("Answer =%g\n",$1);}

/* for binary arithmatic operators */


exp : exp'+'exp { $$=$1+$3; }
|exp'-'exp { $$=$1-$3; }
|exp'*'exp { $$=$1*$3; }
|exp'/'exp {
if($3==0)
{
printf("Divide By Zero");
}
else
$$=$1/$3;
}

|'-'exp {$$=-$2;}
|SIN'('exp')' {$$=sin($3);}
|COS'('exp')' {$$=cos($3);}
|TAN'('exp')' {$$=tan($3);}
|LOG'('exp')' {$$=log($3);}
|SQRT'('exp')' {$$=sqrt($3);}
|num;
|'('exp')' {$$=$2;}

%%

/* extern FILE *yyin; */


int main()
{
do
{
printf("\nEnter Expression: ");
yyparse();
}while(1);

void yyerror(s)
char *s;
{
printf("ERROR");
}

Output:
Experiment-3: Develop a Lexical Analyzer using LEX tool for a simple grammar of your choice
that displays the list of keywords and identifiers present in a given program.

Algorithm:
1. Write program in an editor and save it with .lex or .l extension.
2. Compile the lex program with lex compiler to produce output file as lex.yy.c.
3. Eg. $ lex filename.l
4. $gcc lex.yy.c -ll
5. Compile that file with C compiler and verify the output.

Program:

lexer.l
%{
int COMMENT=0;
%}
identifier[a-z][A-Z0-9]*
digit[0-9]

%%
#.* {printf("\n%s is a peprocessor diective",yytext);}
"int" |
"float" |
"char" |
"double" |
"for" |
"do" |
"if" |
"else" |
"break" |
"continue" |
"void" |
"case" |
"long" |
"struct" |
"typedef" |
"goto" |
"const" |
"while" |
"printf" |
"scanf" |
"switch" |
"main()" |
"return" {printf("\n\t%s is a keyword",yytext);}
"\*" {COMMENT=1;}
"*/" {COMMENT=0;}
\{ {if(!COMMENT) printf("\nblocks starts");}
\} {if(!COMMENT) printf("\n block end");}
{identifier} {if(!COMMENT) printf("\n\t%s is an identifier",yytext);}
\".*\" {if(!COMMENT) printf("\n\t%s is a string",yytext);}
{digit} {if(!COMMENT) printf("\n\t%s is a number",yytext);}
\)(\;)? {if(!COMMENT) printf("\n\t"); ECHO; printf("\n");}
\ECHO;
= {if(!COMMENT) printf("\n\t= is an assignment operator");}
\<= |
\>= |
\< |
== |
\> {if(!COMMENT) printf("\n\t%s is an relational operator",yytext);}
%%

int main(int argc,char **argv)


{
if(argc>1)
{
FILE *f1;
f1=fopen("file.c","r");
if(!f1)
{
printf("could not open%s\n",argv[1]);
exit(0);
}
yyin=f1;
}
yylex();
printf("\n");
return 1;
}

int yywrap()
{
return 0;
}

input.c
#include <stdio.h>

int main()
{
int a,b,c;

printf("enter the value for a,b");

scanf("%d%d",&a,&b);

c=a+b;

printf("the value of c:%d",&c);

return 0;
}
Output:

Experiment-4: Implement Recursive Descent parser for the following grammar:


E->TE'
E'->+TE/@ "@ represents null character"
T->FT'
T'->*FT'/@
F->(E)/ID
Program:
#include<conio.h>
#include<string.h>
char input[100];
int i, l;
void main()
{
clrscr();
printf("\nRecursive descent parsing for the following grammar\n");
printf("\nE->TE'\nE'->+TE'/@\nT->FT'\nT'->*FT'/@\nF->(E)/ID\n");
printf("\nEnter the string to be checked:");
gets(input);

if(E())
{
if(input[i+1]=='\0')
printf("\nString is accepted");
else
printf("\nString is not accepted");
}
else
printf("\nString not accepted");
getch();
}
E()
{
if(T())
{
if(EP())
return(1);
else
return(0);
}
else
return(0);
}

EP()
{
if(input[i]=='+')
{
i++;
if(T())
{
if(EP())
return(1);
else
return(0);
}
else
return(0);
}
else
return(1);
}

T()
{
if(F())
{
if(TP())
return(1);
else
return(0);
}
else
return(0);
}

TP()
{
if(input[i]=='*')
{
i++;
if(F())
{
if(TP())
return(1);
else
return(0);
}
else
return(0);
}
else
return(1);
}

F()
{
if(input[i]=='(')
{
i++;
if(E())
{
if(input[i]==')')
{
i++;
return(1);
}
else
return(0);
}
else
return(0);
}

else if(input[i]>='a'&&input[i]<='z'||input[i]>='A'&&input[i]<='Z')
{
i++;
return(1);
}

else
return(0);
}

Output:
Recursive descent parsing for the following grammar
E->TE'
E'->+TE'/@
T->FT'
T'->*FT'/@
F->(E)/ID

Enter the string to be checked:(a+b)*c


String is accepted
Recursive descent parsing for the following grammar
E->TE'
E'->+TE'/@
T->FT'
T'->*FT'/@
F->(E)/ID

Enter the string to be checked:a/c+d


String is not accepted

Experiment-5: Implement LL(1) parser using C/C++.

Program Logic:
1. Read the input string.
2. Using predictive parsing table parse the given input using stack .
3. If stack[i] matches with token input string pop the token else shift it, repeat the process until
it reaches to $.

Program:
#include<stdio.h>
#include<conio.h>
#include<string.h>
char s[20], stack[20];

void main()
{
char m[5][6][3]={"tb"," "," ","tb"," "," "," ","+tb"," "," ","n","n","fc"," "," ","fc"," "," ","
","n","*fc","a","n","n","i"," "," ","(e)"," "," "};
int size[5][6]={2,0,0,2,0,0,0,3,0,0,1,1,2,0,0,2,0,0,0,1,3,0,1,1,1,0,0,3,0,0};
int i,j,k,n,str1,str2;
clrscr();
printf("\n Enter the input string: ");
scanf("%s",s);
strcat(s,"$");
n=strlen(s);
stack[0]='$';
stack[1]='e';
i=1;
j=0;
printf("\nStack Input\n");
printf("__________________\n");
while((stack[i]!='$')&&(s[j]!='$'))
{
if(stack[i]==s[j])
{
i--;
j++;
}
switch(stack[i])
{
case 'e': str1=0;
break;
case 'b': str1=1;
break;
case 't': str1=2;
break;
case 'c': str1=3;
break;
case 'f': str1=4;
break;
}
switch(s[j])
{
case 'i': str2=0;
break;
case '+': str2=1;
break;
case '*': str2=2;
break;
case '(': str2=3;
break;
case ')': str2=4;
break;
case '$': str2=5;
break;
}
if(m[str1][str2][0]=='\0')
{
printf("\nERROR");
exit(0);
}
else if(m[str1][str2][0]=='n')
i--;
else if(m[str1][str2][0]=='i')
stack[i]='i';
else
{
for(k=size[str1][str2]-1;k>=0;k--)
{
stack[i]=m[str1][str2][k];
i++;
}
i--;
}
for(k=0;k<=i;k++)
printf(" %c",stack[k]);
printf("\n");
for(k=j;k<=n;k++)
printf("%c",s[k]);
printf(" \n ");
}
printf("\n SUCCESS");
getch();
}
Input & Output:
Enter the input string:i*i+i
Stack INPUT
$bt i*i+i$
$bcf i*i+i$
$bci i*i+i$
$bc *i+i$
$bcf* *i+i$
$bcf i+i$
$bci i+i$
$bc +i$
$b +i$
$bt+ +i$
$bt i$
$bcf i$
$ bci i$
$bc $
$b $
$ $
success

Experiment-6: Implement Operator Precedence parser using C/C++.

Program Logic:
1. Read the arithmetic input string.
2. Verify the precedence between terminals and symbols.
3. Find the handle enclosed in < . > and reduce it to production symbol.
4. Repeat the process until we reach the start node.

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;

void 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);
break;
}
}

void 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]='$';
j=1;
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;
}

Input & Output:


Enter the arithmetic expression
(d*d)+d$

Output:
(d*d)+d$
Precedence input:$<(<d>*<d>)>+<d>$
$<(E*<d>)>+<d>$
$<(E*E)>+<E>$
$E+<E>$
$E+E$
Precedence input:$<+>$
$E$
success

Experiment-7: Write a program in C/C++ to design LALR Bottom up Parser.

Program Logic:
1. Read the input string.
2. Push the input symbol with its state symbol into the stack by referring lookaheads
3. Perform shift and reduce actions to parse the grammar.
4. Parsing is completed when we reach $ symbol.

/*Input Grammar
E->E+T
E->T
T->T*F
T->F
F->(E)
F->i
*/

Program:
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<string.h>
void push(char *,int *,char);
char stacktop(char *);
void isproduct(char,char);
int ister(char);
int isnter(char);
int isstate(char);
void error();
void isreduce(char,char);
char pop(char *,int *);
void printt(char *,int *,char [],int);
void rep(char [],int);

struct action
{
char row[6][5];
};
const struct action A[12]={
{"sf","emp","emp","se","emp","emp"},
{"emp","sg","emp","emp","emp","acc"},
{"emp","rc","sh","emp","rc","rc"},
{"emp","re","re","emp","re","re"},
{"sf","emp","emp","se","emp","emp"},
{"emp","rg","rg","emp","rg","rg"},
{"sf","emp","emp","se","emp","emp"},
{"sf","emp","emp","se","emp","emp"},
{"emp","sg","emp","emp","sl","emp"},
{"emp","rb","sh","emp","rb","rb"},
{"emp","rb","rd","emp","rd","rd"},
{"emp","rf","rf","emp","rf","rf"}
};
struct gotol
{
char r[3][4];
};

const struct gotol G[12]={


{"b","c","d"},
{"emp","emp","emp"},
{"emp","emp","emp"},
{"emp","emp","emp"},
{"i","c","d"},
{"emp","emp","emp"},
{"emp","j","d"},
{"emp","emp","k"},
{"emp","emp","emp"},
{"emp","emp","emp"},
};
char ter[6]={'i','+','*',')','(','$'};
char nter[3]={'E','T','F'};
char states[12]={'a','b','c','d','e','f','g','h','m','j','k','l'};
char stack[100];
int top=-1;
char temp[10];

struct grammar
{
char left;
char right[5];
};
const struct grammar rl[6]={
{'E',"e+T"},
{'E',"T"},
{'T',"T*F"},
{'T',"F"},
{'F',"(E)"},
{'F',"i"},
};
void main()
{
char inp[80], x, p, dl[80], y, bl='a';
int i=0, j, k, l, n, m, c, len;
clrscr();
printf(" Enter the input :");
scanf("%s",inp);
len=strlen(inp);
inp[len]='$';
inp[len+1]='\0';
push(stack,&top,bl);
printf("\n stack \t\t\t input");
printt(stack,&top,inp,i);
do
{
x=inp[i];
p=stacktop(stack);
isproduct(x,p);
if(strcmp(temp,"emp")==0)
error();
if(strcmp(temp,"acc")==0)
break;
else
{
if(temp[0]=='s')
{
push(stack,&top,inp[i]);
push(stack,&top,temp[1]);
i++;
}
else
{
if(temp[0]=='r')
{
j=isstate(temp[1]);
strcpy(temp,rl[j-2].right);
dl[0]=rl[j-2].left;
dl[1]='\0';
n=strlen(temp);
for(k=0;k<2*n;k++)
pop(stack,&top);
for(m=0;dl[m]!='\0';m++)
push(stack,&top,dl[m]);
l=top;
y=stack[l-1];
isreduce(y,dl[0]);
for(m=0;temp[m]!='\0';m++)
push(stack,&top,temp[m]);
}
}
}
printt(stack,&top,inp,i);
}while(inp[i]!='\0');

if(strcmp(temp,"acc")==0)
printf(" \n accepts the input ");
else
printf(" \n does not accept the input ");
getch();
}
void push(char *s,int *sp,char item)
{
if(*sp==100)
printf(" stack is full ");
else
{
*sp=*sp+1;
s[*sp]=item;
}
}

char stacktop(char *s)


{
char i;
i=s[top];
return i;
}

void isproduct(char x,char p)


{
int k,l;
k=ister(x);
l=isstate(p);
strcpy(temp,A[l-1].row[k-1]);
}

int ister(char x)
{
int i;
for(i=0;i<6;i++)
if(x==ter[i])
return i+1;
return 0;
}

int isnter(char x)
{
int i;
for(i=0;i<3;i++)
if(x==nter[i])
return i+1;
return 0;
}

int isstate(char p)
{
int i;
for(i=0;i<12;i++)
if(p==states[i])
return i+1;
return 0;
}
void error()
{
printf(" error in the input ");
exit(0);
}

void isreduce(char x,char p)


{
int k,l;
k=isstate(x);
l=isnter(p);
strcpy(temp,G[k-1].r[l-1]);
}

char pop(char *s,int *sp)


{
char item;
if(*sp==-1)
printf(" stack is empty ");
else
{
item=s[*sp];
*sp=*sp-1;
}
return item;
}

void printt(char *t,int *p,char inp[],int i)


{
int r;
printf("\n");
for(r=0;r<=*p;r++)
rep(t,r);
printf("\t\t\t");
for(r=i;inp[r]!='\0';r++)
printf("%c",inp[r]);
}

void rep(char t[],int r)


{
char c;
c=t[r];
switch(c)
{
case 'a': printf("0");
break;
case 'b': printf("1");
break;
case 'c': printf("2");
break;
case 'd': printf("3");
break;
case 'e': printf("4");
break;
case 'f': printf("5");
break;
case 'g': printf("6");
break;
case 'h': printf("7");
break;
case 'm': printf("8");
break;
case 'j': printf("9");
break;
case 'k': printf("10");
break;
case 'l': printf("11");
break;
default :printf("%c",t[r]);
}
}

Input & Output:


Enter the input: i*i+1

Output
Stack input
0 i*i+i$
0i5 *i+i$
0F3 *i+i$
0T2 *i+i$
0T2*7 i+i$
0T2*7i5 +i$
0T2*7i5F10 +i$
0T2 +i$
0E1 +i$
0E1+6 i$
0E1+6i5 $
0E1+6F3 $
0E1+6T9 $
0E1 $
accepts the input
Experiment-8: Implement the Intermediate Code Generator for WHILE construct using LEX &
YACC.

Program:

whilef.l
%%
while return WHILE;
[A-Za-z]([A-Za-z]|[0-9])* return ID;
[0-9]+ return NUM;
[\t] ;
\n yyterminate();
. return yytext[0];
%%

whilef.y
%{
#include "lex.yy.c"
#include <stdio.h>
#include <string.h>
char stack[100][10];
int top = 0;
char temp[3] = "t0";
%}

%token ID NUM WHILE


%right '='
%left '+' '-'
%left '*' '/'
%left MINUS

%%
S : WHILE {L1();} '(' E ')'{Lcond();} E ';' {End();}

E : V '=' {push();} E{codegen_assign();}


| E '+' {push();} E{codegen();}
| E '-' {push();} E{codegen();}
| E '*' {push();} E{codegen();}
| E '/' {push();} E{codegen();}
| '(' E ')'
| '-' {push();} E{codegen_umin();} %prec MINUS
| V
| NUM {push();}
;

V : ID {push();}
;
%%
void main()
{
printf("Enter expression: ");
yyparse();
}

void push() //push into stack (number, ID)


{
strcpy(stack[++top], yytext);
}

void codegen()
{
printf("%s = %s %s %s\n", temp, stack[top - 2], stack [top - 1], stack[top]); //display like t0 = a*b
top -= 2;
strcpy(stack[top], temp);
temp[1]++; //generating new temporary variable
}

void codegen_umin()
{
printf("%s = -%s\n", temp, stack[top]); //display like t0 = -a
top--;
strcpy(stack[top], temp);
temp[1]++; //generating new temporary variable
}

void codegen_assign()
{
printf("%s = %s\n", stack[top-2], stack[top]); //display like c = t0
top -= 2;
}

void L1()
{
printf("\nL1: \n");
}

void Lcond()
{
printf("%s = not %s\n", temp, stack[top]);
printf("if %s goto End\n", temp);
temp[1]++; //generating new temporary variable
}

void End()
{
printf("goto L1\n");
printf("End: end of while loop \n\n");
}
Output:

Experiment-9: Implement a simple code optimization phase of compiler using C/C++.

Program:
#include<stdio.h>
#include<conio.h>
#include<string.h>
char s[20], o[20];
void main()
{
int i = 0, j = 0, k, f1 = 1, f = 1, k1 = 0;
void part();
clrscr();
printf("\n Enter the input string\n");
scanf("%s",o);
strlen(o);
while(o[k1]!='\0')
{
if((o[k1]=='=')==1)
{
break;
}
k1++;
}

for(j=k1+1;j<strlen(o);j++)
{
s[i]=o[j];
i++;
}
s[i]='\0';
i=strlen(s);
j=0;
printf("\n Three address code is\n");
if(i>3)
{
while(s[j]!='\0')
{
if((s[j]=='*')==1||(s[j]=='/')==1)
{
k=j;
if(f1!=0)
{
printf("t1=%c\n",s[k+1]);
printf("t2=%c%ct1",s[k-1],s[k]);
}
else
{
if(k>3)
{
printf("t2=t1%c%c\n",s[k],s[k+1]);
}
else
{
printf("\t2=t1%c%c\n",s[k],s[k-1]);
}
}
f=0;
break;
}
j++;
}
j=0;
while(s[j]!='\0')
{
if((s[j]=='+')==1||(s[j]=='-')==1)
{
k=j;
if(f==0)
{
if(k<3)
{
printf("\nt3=t2%c%c\n",s[k],s[k-1]);
}
else
{
printf("\nt3=t2%c%c\n",s[k],s[k+1])
}
}
else
{
printf("t1=%c%c%c\n",s[k-1],s[k],s[k+1]);
}
f1=0;
}
j++;
}
printf("%c=t3",o[0]);
}
else
{
printf("t1=%s\n",s);
printf("%c=t1",o[0]);
}
part();
getch();
}

void part()
{
int i=0, j=0, k, f1=1, f=1, k1=0;
while(o[k1]!='\0')
{
if((o[k1]=='=')==1)
{
break;
}
k1++;
}
for(j=k1+1;j<strlen(o);j++)
{
s[i]=o[j];
i++;
}
s[i]='\0';
i=strlen(s);
j=0;
printf("\n OPTIMIZED CODE\n");
if(i>3)
{
while(s[j]!='\0')
{
if((s[j]=='*')==1||(s[j]=='/')==1)
{
k=j;
if(f1!=0)
{
printf("t1=%c%c%c\n",s[k-1],s[k],s[k+1]);
}
else
{
if(k>3)
{
printf("t2=t1%c%c\n",s[k],s[k+1]);
}
else
{
printf("\t2=t1%c%c\n",s[k],s[k-1]);
}
}
f=0;
break;
}
j++;
}
j=0;
while(s[j]!='\0')
{
if((s[j]=='+')==1||(s[j]=='-')==1)
{
k=j;
if(f==0)
{
if(k<3)
{
printf("t2=t1%c%c\n",s[k],s[k-1]);
}
else
{
printf("t2=t1%c%c\n",s[k],s[k+1]);
}
}
else
{
printf("t1=%c%c%c\n",s[k-1],s[k],s[k+1]);
}
f1=0;
}
j++;
}
printf("%c=t2",o[0]);
}
else
{
printf("t1=%s\n",s);
printf("%c=t1",o[0]);
}
}
Experiment-10: Implement a simple Code Generator for arithmetic expression using C/C++.

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("\nEnter the set of intermediate codes for any simple arithmetic expression(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);

printf("\n");
//getch();
}
Output:

You might also like