0% found this document useful (0 votes)
38 views82 pages

Record Contents

The program implements an algorithm to convert an NFA with epsilon transitions to an equivalent NFA without epsilon transitions. It takes the number of states, alphabets, transitions, and final states as input. It uses epsilon closure and transition tables to calculate the epsilon closures of each state and generate the transitions of the converted NFA without epsilon.

Uploaded by

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

Record Contents

The program implements an algorithm to convert an NFA with epsilon transitions to an equivalent NFA without epsilon transitions. It takes the number of states, alphabets, transitions, and final states as input. It uses epsilon closure and transition tables to calculate the epsilon closures of each state and generate the transitions of the converted NFA without epsilon.

Uploaded by

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

EXPERIMENT - 1

Program to find ԑ - Closure of all states of any given NFA with ԑ


transitions

AIM: To implement a program to find the ԑ closure of all states of any given NFA with
ԑ transitions.

ALGORITHM:

Step 0: Start
Step 1: Declare arrays result, copy and states to store immediate and final
results.
Step 2: Declare the variables to hold state information and take input n which is
number of states from user.
Step 3: Open the file using fopen function and store its pointer in INPUT.
Step 4: Give state names for the inputted number of states.
Step 5: For each state in the states array,
5.1:- Initialise I to 0 and copy current state to state variable.
5.2:- Call add-state function to add current state to result array at index i.
5.3:- Enter a loop that reads transitions from input file until EOF is reached.
5.3.1:- if current state matches ‘state1’ and input symbol is epsilon(“ ԑ”),
call add_state function to add ‘state2’ to ‘result’ array at index I and
update ‘state’ with value of ‘state2’.
5.4:- Increment i for next iteration.
5.5:- Call the display function to print epsilon closure of current state.
5.6:- Rewind input file to its beginning using rewind function.
Step 6: Close the input file using fclose function.
Step 7: Stop

PROGRAM:

#include<stdio.h>
#include<string.h>
char result[20][20],copy[3],states[20][20];

void add_state(char a[3],int i){


strcpy(result[i],a);
}

3
void display(int n){
int k=0;
printf("\n\n\n Epsilon closure of %s = { ",copy);
while(k < n){
printf(" %s",result[k]);
k++;
}
printf(" } \n\n\n");
}

int main(){
FILE *INPUT;
INPUT=fopen("input.txt","r");
char state[3];
int end,i=0,n,k=0;
char state1[3],input[3],state2[3];
printf("\n Enter the no of states: ");
scanf("%d",&n);
printf("\n Enter the states n");
for(k=0;k<3;k++){
scanf("%s",states[k]);

for( k=0;k<n;k++){
i=0;
strcpy(state,states[k]);

4
strcpy(copy,state);
add_state(state,i++);
while(1){
end = fscanf(INPUT,"%s%s%s",state1,input,state2);
if (end == EOF ){
break;
}

if( strcmp(state,state1) == 0 ){
if( strcmp(input,"e") == 0 ) {
add_state(state2,i++);
strcpy(state, state2);
}
}

}
display(i);
rewind(INPUT);
}

return 0;
}

OUTPUT:
Enter the no of states: 3

Enter the states n


q0
q1
q2

5
Epsilon closure of q0 = { q0 q1 q2 }

Epsilon closure of q1 = { q1 q2 }

Epsilon closure of q2 = { q2 }

RESULT: Program to find the epsilon closure of all states of an epsilon


NFA was successfully implemented

6
EXPERIMENT - 2

Program to convert NFA with ԑ transition to NFA without ԑ transitions

AIM: To implement a program to convert NFA with ԑ transition to NFA without ԑ


transitions.

ALGORITHM:

Step 0: Start the program.


Step 1: Read the number of alphabets, states, final states and transitions and take
input for the same from user.
Step 2: Initialise ԑ-closure matrix to store ԑ-closure for each state and a buffer array
to track visited states during ԑ-closure calculation.
Step 3: Compute ԑ-closure for each state.
3.1:- For each state i, initialise i to 0 and clear the buffer array.
3.2:- Call findclosure( i,i) to compute ԑ-closure of state I and store it in ԑ-
closure[][].
Step 4: Print equivalent NFA without epsilon.
4.1:- Print start state’s ԑ-closure.
4.2:- Print alphabet symbols.
4.3:- For each state i, print ԑ-closure of state i.
Step 5: Generate transitions for equivalent NFA.
5.1:- For each state i inside which for each alphabet j, initialise an empty set
to track reachable states from ԑ-closure of state i.
5.2:- For each state k in ԑ-closure of i, traverse transitions for state ‘k’ on
alphabet symbol and add reachable states to set.
5.3:- Print transitions from ԑ-closure of state I to set of reachable states on
alphabet symbol.
Step 6: Identify final states for equivalent NFA.
6.1:- For each final state index i in finalState[], for each state ‘j’, for each
state ‘k’ in ԑ-closure of state ‘j’; if k matches current final state index ‘i’, print ԑ-
closure of state j.
Step 7: Stop the program.

PROGRAM:

#include<stdio.h>
#include<stdlib.h>
struct node
{
int st;

7
struct node *link;
};

void findclosure(int,int);
void insert_trantbl(int ,char, int);
int findalpha(char);
void findfinalstate(void);
void unionclosure(int);
void print_e_closure(int);
static int
set[20],nostate,noalpha,s,notransition,nofinal,start,finalstate[20],r,buffer[20];
static char c;
char alphabet[20];
static int e_closure[20][20]={0};
struct node * transition[20][20]={NULL};
void main()
{
int i,j,k,m,t,n;

struct node *temp;


printf("enter the number of alphabets?\n");
scanf("%d",&noalpha);
getchar();
printf("NOTE:- [ use letter e as epsilon]\n");

printf("NOTE:- [e must be last character ,if it is present]\n");

printf("\nEnter alphabets?\n");
for(i=0;i<noalpha;i++)
{

alphabet[i]=getchar();
getchar();
}
printf("Enter the number of states?\n");
scanf("%d",&nostate);
printf("Enter the start state?\n");
scanf("%d",&start);
printf("Enter the number of final states?\n");
scanf("%d",&nofinal);
printf("Enter the final states?\n");
for(i=0;i<nofinal;i++)

8
scanf("%d",&finalstate[i]);
printf("Enter no of transition?\n");
scanf("%d",&notransition);
printf("NOTE:- [Transition is in the form--> qno alphabet qno]\n");
printf("NOTE:- [States number must be greater than zero]\n");
printf("\nEnter transition?\n");
for(i=0;i<notransition;i++)
{

scanf("%d %c%d",&r,&c,&s);
insert_trantbl(r,c,s);

printf("\n");

for(i=1;i<=nostate;i++)
{
c=0;
for(j=0;j<20;j++)

{
buffer[j]=0;
e_closure[i][j]=0;
}
findclosure(i,i);
}
printf("Equivalent NFA without epsilon\n");
printf("-----------------------------------\n");
printf("start state:");
print_e_closure(start);
printf("\nAlphabets:");
for(i=0;i<noalpha;i++)
printf("%c ",alphabet[i]);
printf("\nStates :" );
for(i=1;i<=nostate;i++)
print_e_closure(i);

printf("\nTransitions are...:\n");

for(i=1;i<=nostate;i++)

9
{

for(j=0;j<noalpha-1;j++)
{
for(m=1;m<=nostate;m++)
set[m]=0;
for(k=0;e_closure[i][k]!=0;k++)
{

t=e_closure[i][k];
temp=transition[t][j];
while(temp!=NULL)
{

unionclosure(temp->st);
temp=temp->link;
}
}
printf("\n");
print_e_closure(i);
printf("%c\t",alphabet[j] );
printf("{");
for(n=1;n<=nostate;n++)
{
if(set[n]!=0)
printf("q%d,",n);
}
printf("}");
}
}
printf("\nFinal states:");
findfinalstate();

void findclosure(int x,int sta)


{
struct node *temp;
int i;

10
if(buffer[x])
return;
e_closure[sta][c++]=x;
buffer[x]=1;
if(alphabet[noalpha-1]=='e' && transition[x][noalpha-1]!=NULL)
{
temp=transition[x][noalpha-1];
while(temp!=NULL)
{
findclosure(temp->st,sta);
temp=temp->link;
}
}
}

void insert_trantbl(int r,char c,int s)


{
int j;
struct node *temp;
j=findalpha(c);
if(j==999)
{
printf("error\n");
exit(0);
}
temp=(struct node *) malloc(sizeof(struct node));
temp->st=s;
temp->link=transition[r][j];
transition[r][j]=temp;
}

int findalpha(char c)
{
int i;
for(i=0;i<noalpha;i++)
if(alphabet[i]==c)
return i;

return(999);

11
void unionclosure(int i)
{
int j=0,k;
while(e_closure[i][j]!=0)
{
k=e_closure[i][j];
set[k]=1;
j++;
}
}
void findfinalstate()
{
int i,j,k,t;
for(i=0;i<nofinal;i++)
{
for(j=1;j<=nostate;j++)
{
for(k=0;e_closure[j][k]!=0;k++)
{
if(e_closure[j][k]==finalstate[i])
{

print_e_closure(j);
}
}
}
}

void print_e_closure(int i)
{
int j=0;
printf("{");
if(e_closure[i][j]!=0)
printf("q%d,",e_closure[i][0]);
printf("}\t");
}

12
OUTPUT:

enter the number of alphabets?


3
NOTE:- [ use letter e as epsilon]
NOTE:- [e must be last character ,if it is present]

Enter alphabets?
a
b
e
Enter the number of states?
5
Enter the start state?
1
Enter the number of final states?
1
Enter the final states?
3
Enter no of transition?
7
NOTE:- [Transition is in the form--> qno alphabet qno]
NOTE:- [States number must be greater than zero]

Enter transition?
1a2
1e3
2a1
3b4
4b3
3a5
5b3

Equivalent NFA without epsilon


-----------------------------------
start state:{q1,}
Alphabets:a b e
States :{q1,} {q2,} {q3,} {q4,} {q5,}
Transitions are...:

{q1,} a {q2,q5,}
{q1,} b {q4,}

13
{q2,} a {q1,q3,}
{q2,} b {}
{q3,} a {q5,}
{q3,} b {q4,}
{q4,} a {}
{q4,} b {q3,}
{q5,} a {}
{q5,} b {q3,}
Final states:{q1,} {q3,}

RESULT: Program to convert ԑ-NFA to NFA was successfully


implemented.

14
EXPERIMENT - 3

Program to convert NFA to DFA

AIM: To implement a program to convert NFA to DFA.

ALGORITHM:

Step 0: Start the program.


Step 1: Read the number of alphabets, states, final states and transitions and get
the input for same from user.
Step 2: Initialise the transition table to store NFA transitions, ԑ-closure matrix to
store ԑ-closure sets for each state, DFA state hash table. Initialise ‘complete’ to -1
and ‘i’ to -1.
Step 3: Perform initialisation for subset construction.
3.1:- Create an empty DFA state ‘newstate’ with start state.
3.2:- Call ‘insertdfastate()’ to insert newstate into DFA state hash table.
Step 4: In the loop of subset construction, increment i while i is not equal to
complete and get next DFA state ‘newstate’ from hash table.
Step 5: For each alphabet symbol k:-
5.1:- Create an empty set to track NFA states in DFA state.
5.2:- For each NFA state j, if newstate contains NFA state ‘j’, traverse
transitions for NFA state j using current alphabet symbol ‘k’ and add reachable
states to set using ԑ-closure.
5.3:- if set is not empty, create a new DFA state using states in ‘set[]’. Call
insertdfastate() to insert tmpstate into DFA state hash table.
5.3.1:- Print transitions from newstate to tmpstate on alphabet symbol
‘alphabet[k]’.
Step 6: identify DFA accepting states.
6.1:- In each DFA state in hash table, for each NFA final state, if DFA state
contains an NFA final state, mark it as DFA accepting state.
Step 7: Print the resultant DFA details.
Step 8: Stop the program.

PROGRAM:

#include<stdio.h>
#include<stdlib.h>
struct node
{
int st;
struct node *link;

15
};
struct node1
{

int nst[20];
};

void insert(int ,char, int);


int findalpha(char);
void findfinalstate(void);
int insertdfastate(struct node1);
int compare(struct node1,struct node1);
void printnewstate(struct node1);
static int
set[20],nostate,noalpha,s,notransition,nofinal,start,finalstate[20],r,buffer[20];
static char c;
int complete=-1;
char alphabet[20];
static int eclosure[20][20]={0};
struct node1 hash[20];
struct node * transition[20][20]={NULL};
void main()
{
int i,j,k,m,t,n,l;
struct node *temp;
struct node1 newstate={0},tmpstate={0};

printf("Enter the number of alphabets?\n");


printf("NOTE:- [ use letter e as epsilon]\n");
printf("NOTE:- [e must be last character ,if it is present]\n");
printf("\nEnter No of alphabets and alphabets?\n");
scanf("%d",&noalpha);
getchar();
for(i=0;i<noalpha;i++)
{
alphabet[i]=getchar();
getchar();
}
printf("Enter the number of states?\n");
scanf("%d",&nostate);
printf("Enter the start state?\n");
scanf("%d",&start);

16
printf("Enter the number of final states?\n");
scanf("%d",&nofinal);
printf("Enter the final states?\n");
for(i=0;i<nofinal;i++)
scanf("%d",&finalstate[i]);
printf("Enter no of transition?\n");

scanf("%d",&notransition);
printf("NOTE:- [Transition is in the form–> qno alphabet qno]\n");
printf("NOTE:- [States number must be greater than zero]\n");
printf("\nEnter transition?\n");
for(i=0;i<notransition;i++)
{
scanf("%d %c %d",&r,&c,&s);
insert(r,c,s);

}
for(i=0;i<20;i++)
{
for(j=0;j<20;j++)
hash[i].nst[j]=0;
}
complete=-1;
i=-1;
printf("\nEquivalent DFA.....\n");
printf("Trnsitions of DFA\n");

newstate.nst[start]=start;
insertdfastate(newstate);
while(i!=complete)
{
i++;
newstate=hash[i];
for(k=0;k<noalpha;k++)
{
c=0;
for(j=1;j<=nostate;j++)
set[j]=0;
for(j=1;j<=nostate;j++)
{
l=newstate.nst[j];
if(l!=0)

17
{
temp=transition[l][k];
while(temp!=NULL)
{
if(set[temp->st]==0)
{
c++;
set[temp->st]=temp->st;
}
temp=temp->link;
}
}
}
printf("\n");
if(c!=0)
{
for(m=1;m<=nostate;m++)
tmpstate.nst[m]=set[m];

insertdfastate(tmpstate);

printnewstate(newstate);
printf("%c\t",alphabet[k]);
printnewstate(tmpstate);
printf("\n");
}
else
{
printnewstate(newstate);
printf("%c\t", alphabet[k]);
printf("NULL\n");
}

}
}
printf("\nStates of DFA:\n");
for(i=0;i<=complete;i++)
printnewstate(hash[i]);
printf("\n Alphabets:\n");
for(i=0;i<noalpha;i++)
printf("%c\t",alphabet[i]);
printf("\n Start State:\n");

18
printf("q%d",start);
printf("\nFinal states:\n");
findfinalstate();

}
int insertdfastate(struct node1 newstate)
{
int i;
for(i=0;i<=complete;i++)
{
if(compare(hash[i],newstate))
return 0;
}
complete++;
hash[complete]=newstate;
return 1;
}
int compare(struct node1 a,struct node1 b)
{
int i;

for(i=1;i<=nostate;i++)
{
if(a.nst[i]!=b.nst[i])
return 0;
}
return 1;

void insert(int r,char c,int s)


{
int j;
struct node *temp;
j=findalpha(c);
if(j==999)
{
printf("error\n");
exit(0);
}

19
temp=(struct node *) malloc(sizeof(struct node));
temp->st=s;
temp->link=transition[r][j];
transition[r][j]=temp;
}

int findalpha(char c)
{
int i;
for(i=0;i<noalpha;i++)
if(alphabet[i]==c)
return i;

return(999);

void findfinalstate()
{
int i,j,k,t;

for(i=0;i<=complete;i++)
{
for(j=1;j<=nostate;j++)
{
for(k=0;k<nofinal;k++)
{
if(hash[i].nst[j]==finalstate[k])
{
printnewstate(hash[i]);
printf("\t");
j=nostate;
break;
}
}
}
}
}

void printnewstate(struct node1 state)

20
{
int j;
printf("{");
for(j=1;j<=nostate;j++)
{
if(state.nst[j]!=0)
printf("q%d,",state.nst[j]);
}
printf("}\t");

OUTPUT:

Enter the number of alphabets?


NOTE:- [ use letter e as epsilon]
NOTE:- [e must be last character ,if it is present]

Enter No of alphabets and alphabets?


2
a
b
Enter the number of states?
4
Enter the start state?
1
Enter the number of final states?
2
Enter the final states?
3
4
Enter no of transition?
8
NOTE:- [Transition is in the form–> qno alphabet qno]
NOTE:- [States number must be greater than zero]

Enter transition?
1a1
1b1
1a2
2b2
2a3

21
3a4
3b4
4b3

Equivalent DFA.....
Trnsitions of DFA

{q1,} a {q1,q2,}

{q1,} b {q1,}

{q1,q2,} a {q1,q2,q3,}

{q1,q2,} b {q1,q2,}

{q1,q2,q3,} a {q1,q2,q3,q4,}

{q1,q2,q3,} b {q1,q2,q4,}

{q1,q2,q3,q4,} a {q1,q2,q3,q4,}

{q1,q2,q3,q4,} b {q1,q2,q3,q4,}

{q1,q2,q4,} a {q1,q2,q3,}

{q1,q2,q4,} b {q1,q2,q3,}

States of DFA:
{q1,} {q1,q2,} {q1,q2,q3,} {q1,q2,q3,q4,} {q1,q2,q4,}
Alphabets:
a b
Start State:
q1
Final states:
{q1,q2,q3,} {q1,q2,q3,q4,} {q1,q2,q4,}

RESULT: Program to convert NFA to DFA was successfully implemented.

22
EXPERIMENT - 4

Program to minimize any given DFA

AIM: To implement a program to minimize any given DFA.

ALGORITHM:

Step 0: Start the program.


Step 1: Initialise the DFA table including number of states, symbols and final states.
Step 2: Create an array to represent state names and initialise it.
Step 3: Initialise variables for the number of optimised DFA states and new final
states.
Step 4: Print the original DFA table for reference.
Step 5: Initialise equivalence classes of states based on final and non-final states.
Step 6: Enter the main loop for state minimisation.
6.1:- Print the current equivalence classes.
6.2:- Generate the optimised DFA table based on current equivalence
classes.
6.3:- Check if any state can be further divided into new equivalence classes.
6.4:- If there are new equivalence classes, update state names table and go
back to step 6.1.
6.5:- If no new equivalence classes are found, exit the loop.
Step 7: Calculate new final states for minimised DFA.
Step 8: Print the minimised final DFA.
Step 9: Stop the program.

PROGRAM:

#include <stdio.h>
#include <string.h>

#define STATES 99
#define SYMBOLS 20

int N_symbols; /* number of input symbols */


int N_DFA_states; /* number of DFA states */
char *DFA_finals; /* final-state string */
int DFAtab[STATES][SYMBOLS];

char StateName[STATES][STATES+1]; /* state-name table */

int N_optDFA_states; /* number of optimized DFA states */

23
int OptDFA[STATES][SYMBOLS];
char NEW_finals[STATES+1];

/*
Print state-transition table.
State names: 'A', 'B', 'C', ...
*/
void print_dfa_table(
int tab[][SYMBOLS], /* DFA table */
int nstates, /* number of states */
int nsymbols, /* number of input symbols */
char *finals)
{
int i, j;

puts("\nDFA: STATE TRANSITION TABLE");

/* input symbols: '0', '1', ... */


printf(" | ");
for (i = 0; i < nsymbols; i++) printf(" %c ", '0'+i);

printf("\n-----+--");
for (i = 0; i < nsymbols; i++) printf("-----");
printf("\n");

for (i = 0; i < nstates; i++) {


printf(" %c | ", 'A'+i); /* state */
for (j = 0; j < nsymbols; j++)
printf(" %c ", tab[i][j]); /* next state */
printf("\n");
}
printf("Final states = %s\n", finals);
}

/*
Initialize NFA table.
*/
void load_DFA_table()
{

DFAtab[0][0] = 'B'; DFAtab[0][1] = 'C';


DFAtab[1][0] = 'E'; DFAtab[1][1] = 'F';

24
DFAtab[2][0] = 'A'; DFAtab[2][1] = 'A';
DFAtab[3][0] = 'F'; DFAtab[3][1] = 'E';
DFAtab[4][0] = 'D'; DFAtab[4][1] = 'F';
DFAtab[5][0] = 'D'; DFAtab[5][1] = 'E';

DFA_finals = "EF";
N_DFA_states = 6;
N_symbols = 2;
}

/*
Get next-state string for current-state string.
*/
void get_next_state(char *nextstates, char *cur_states,
int dfa[STATES][SYMBOLS], int symbol)
{
int i, ch;

for (i = 0; i < strlen(cur_states); i++)


*nextstates++ = dfa[cur_states[i]-'A'][symbol];
*nextstates = '\0';
}

/*
Get index of the equivalence states for state 'ch'.
Equiv. class id's are '0', '1', '2', ...
*/
char equiv_class_ndx(char ch, char stnt[][STATES+1], int n)
{
int i;

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


if (strchr(stnt[i], ch)) return i+'0';
return -1; /* next state is NOT defined */
}

/*
Check if all the next states belongs to same equivalence class.
Return value:
If next state is NOT unique, return 0.
If next state is unique, return next state --> 'A/B/C/...'
's' is a '0/1' string: state-id's

25
*/
char is_one_nextstate(char *s)
{
char equiv_class; /* first equiv. class */

while (*s == '@') s++;


equiv_class = *s++; /* index of equiv. class */

while (*s) {
if (*s != '@' && *s != equiv_class) return 0;
s++;
}

return equiv_class; /* next state: char type */


}

int state_index(char *state, char stnt[][STATES+1], int n, int *pn,


int cur) /* 'cur' is added only for 'printf()' */
{
int i;
char state_flags[STATES+1]; /* next state info. */

if (!*state) return -1; /* no next state */

for (i = 0; i < strlen(state); i++)


state_flags[i] = equiv_class_ndx(state[i], stnt, n);
state_flags[i] = '\0';

printf(" %d:[%s]\t--> [%s] (%s)\n",


cur, stnt[cur], state, state_flags);

if (i=is_one_nextstate(state_flags))
return i-'0'; /* deterministic next states */
else {
strcpy(stnt[*pn], state_flags); /* state-division info */
return (*pn)++;
}
}

/*
Divide DFA states into finals and non-finals.
*/

26
int init_equiv_class(char statename[][STATES+1], int n, char *finals)
{
int i, j;

if (strlen(finals) == n) { /* all states are final states */


strcpy(statename[0], finals);
return 1;
}

strcpy(statename[1], finals); /* final state group */

for (i=j=0; i < n; i++) {


if (i == *finals-'A') {
finals++;
} else statename[0][j++] = i+'A';
}
statename[0][j] = '\0';

return 2;
}

/*
Get optimized DFA 'newdfa' for equiv. class 'stnt'.
*/
int get_optimized_DFA(char stnt[][STATES+1], int n,
int dfa[][SYMBOLS], int n_sym, int newdfa[][SYMBOLS])
{
int n2=n; /* 'n' + <num. of state-division info> */
int i, j;
char nextstate[STATES+1];

for (i = 0; i < n; i++) { /* for each pseudo-DFA state */


for (j = 0; j < n_sym; j++) { /* for each input symbol */
get_next_state(nextstate, stnt[i], dfa, j);
newdfa[i][j] = state_index(nextstate, stnt, n, &n2, i)+'A';
}
}

return n2;
}

/*

27
char 'ch' is appended at the end of 's'.
*/
void chr_append(char *s, char ch)
{
int n=strlen(s);

*(s+n) = ch;
*(s+n+1) = '\0';
}

void sort(char stnt[][STATES+1], int n)


{
int i, j;
char temp[STATES+1];

for (i = 0; i < n-1; i++)


for (j = i+1; j < n; j++)
if (stnt[i][0] > stnt[j][0]) {
strcpy(temp, stnt[i]);
strcpy(stnt[i], stnt[j]);
strcpy(stnt[j], temp);
}
}

/*
Divide first equivalent class into subclasses.
stnt[i1] : equiv. class to be segmented
stnt[i2] : equiv. vector for next state of stnt[i1]
Algorithm:
- stnt[i1] is splitted into 2 or more classes 's1/s2/...'
- old equiv. classes are NOT changed, except stnt[i1]
- stnt[i1]=s1, stnt[n]=s2, stnt[n+1]=s3, ...
Return value: number of NEW equiv. classses in 'stnt'.
*/
int split_equiv_class(char stnt[][STATES+1],
int i1, /* index of 'i1'-th equiv. class */
int i2, /* index of equiv. vector for 'i1'-th class */
int n, /* number of entries in 'stnt' */
int n_dfa) /* number of source DFA entries */
{
char *old=stnt[i1], *vec=stnt[i2];
int i, n2, flag=0;

28
char newstates[STATES][STATES+1]; /* max. 'n' subclasses */

for (i=0; i < STATES; i++) newstates[i][0] = '\0';

for (i=0; vec[i]; i++)


chr_append(newstates[vec[i]-'0'], old[i]);

for (i=0, n2=n; i < n_dfa; i++) {


if (newstates[i][0]) {
if (!flag) { /* stnt[i1] = s1 */
strcpy(stnt[i1], newstates[i]);
flag = 1; /* overwrite parent class */
} else /* newstate is appended in 'stnt' */
strcpy(stnt[n2++], newstates[i]);
}
}

sort(stnt, n2); /* sort equiv. classes */

return n2; /* number of NEW states(equiv. classes) */


}

/*
Equiv. classes are segmented and get NEW equiv. classes.
*/
int set_new_equiv_class(char stnt[][STATES+1], int n,
int newdfa[][SYMBOLS], int n_sym, int n_dfa)
{
int i, j, k;

for (i = 0; i < n; i++) {


for (j = 0; j < n_sym; j++) {
k = newdfa[i][j]-'A'; /* index of equiv. vector */
if (k >= n) /* equiv. class 'i' should be segmented */
return split_equiv_class(stnt, i, k, n, n_dfa);
}
}

return n;
}

void print_equiv_classes(char stnt[][STATES+1], int n)

29
{
int i;

printf("\nEQUIV. CLASS CANDIDATE ==>");


for (i = 0; i < n; i++)
printf(" %d:[%s]", i, stnt[i]);
printf("\n");
}

/*
State-minimization of DFA: 'dfa' --> 'newdfa'
Return value: number of DFA states.
*/
int optimize_DFA(
int dfa[][SYMBOLS], /* DFA state-transition table */
int n_dfa, /* number of DFA states */
int n_sym, /* number of input symbols */
char *finals, /* final states of DFA */
char stnt[][STATES+1], /* state name table */
int newdfa[][SYMBOLS]) /* reduced DFA table */
{
char nextstate[STATES+1];
int n; /* number of new DFA states */
int n2; /* 'n' + <num. of state-dividing info> */

n = init_equiv_class(stnt, n_dfa, finals);

while (1) {
print_equiv_classes(stnt, n);
n2 = get_optimized_DFA(stnt, n, dfa, n_sym, newdfa);
if (n != n2)
n = set_new_equiv_class(stnt, n, newdfa, n_sym, n_dfa);
else break; /* equiv. class segmentation ended!!! */
}

return n; /* number of DFA states */


}

/*
Check if 't' is a subset of 's'.
*/
int is_subset(char *s, char *t)

30
{
int i;

for (i = 0; *t; i++)


if (!strchr(s, *t++)) return 0;
return 1;
}

/*
New finals states of reduced DFA.
*/
void get_NEW_finals(
char *newfinals, /* new DFA finals */
char *oldfinals, /* source DFA finals */
char stnt[][STATES+1], /* state name table */
int n) /* number of states in 'stnt' */
{
int i;

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


if (is_subset(oldfinals, stnt[i])) *newfinals++ = i+'A';
*newfinals++ = '\0';
}

void main()
{
load_DFA_table();
print_dfa_table(DFAtab, N_DFA_states, N_symbols, DFA_finals);

N_optDFA_states = optimize_DFA(DFAtab, N_DFA_states,


N_symbols, DFA_finals, StateName, OptDFA);
get_NEW_finals(NEW_finals, DFA_finals, StateName, N_optDFA_states);

print_dfa_table(OptDFA, N_optDFA_states, N_symbols, NEW_finals);


}

OUTPUT:

DFA: STATE TRANSITION TABLE


| 0 1
-----+------------
A | B C

31
B | E F
C | A A
D | F E
E | D F
F | D E
Final states = EF

EQUIV. CLASS CANDIDATE ==> 0:[ABCD] 1:[EF]


0:[ABCD] --> [BEAF] (0101)
0:[ABCD] --> [CFAE] (0101)
1:[EF] --> [DD] (00)
1:[EF] --> [FE] (11)

EQUIV. CLASS CANDIDATE ==> 0:[AC] 1:[BD] 2:[EF]


0:[AC] --> [BA] (10)
0:[AC] --> [CA] (00)
1:[BD] --> [EF] (22)
1:[BD] --> [FE] (22)
2:[EF] --> [DD] (11)
2:[EF] --> [FE] (22)

EQUIV. CLASS CANDIDATE ==> 0:[A] 1:[BD] 2:[C] 3:[EF]


0:[A] --> [B] (1)
0:[A] --> [C] (2)
1:[BD] --> [EF] (33)
1:[BD] --> [FE] (33)
2:[C] --> [A] (0)
2:[C] --> [A] (0)
3:[EF] --> [DD] (11)
3:[EF] --> [FE] (33)

DFA: STATE TRANSITION TABLE


| 0 1
-----+------------
A | B C
B | D D
C | A A
D | B D
Final states = D

RESULT: Program to minimise DFA was successfully implemented.

32
Introduction to Lex

Lex is a tool or a computer program that generates Lexical Analyzers (converts the
stream of characters into tokens). The Lex tool itself is a compiler. The Lex
compiler takes the input and transforms that input into input patterns. It is
commonly used with YACC(Yet Another Compiler Compiler).

The function of Lex is as follows:


1)Lexical Analyzer Creation: The process begins by creating a program called lex.1
using Lex's language. This program defines the rules and patterns for recognizing
tokens in the source code.
2)Lex Compiler Execution: The lex.1 program is then executed using the Lex
compiler. This step generates a C program named lex.yy.c
3)C Compiler Execution: The C compiler is then used to compile the generated
lex.yy.c program. The result is an object program referred to as a.out
4)Lexical Analysis: The a.out object program is essentially a lexical analyzer. When
this program is run, it takes an input stream of source code and transforms it into a
sequence of tokens based on the rules defined in the original lex.1 program

Any lex file consists of the following three parts-


1)Definitions: This section of lex files contains declarations of constant, variable,
and regular definitions.
2)Rules: This section of the lex files defines the rules in the form of the regular
expressions and corresponding actions that the lexer should take to identify tokens
in the input stream. Each rule consists of a regular expression followed by a code
block that specifies the action to take when the regular expression matches. The
rule is in the form of- p1 {action1} p2 {action2} ... pn {action}. Where Pi is the ith
Regular expression and action is the action that must be taken when the regular
expression matches.
3)User Subroutines: This section contains the user-defined functions that can be
used by the action code block in the rules section of the lex file.

The formal lex file has the following format-

{ definitions }
%%
{ rules }
%%
{ user subroutines }

33
Introduction to YACC

Each translation rule input to YACC has a string specification that resembles a
production of a grammar-it has a nonterminal on the LHS and a few alternatives on
the RHS. For simplicity, we will refer to a string specification as a production. YACC
generates an LALR(1) parser for language L from the productions, which is a
bottom-up parser. The parser would operate as follows: For a shift action, it would
invoke the scanner to obtain the next token and continue the parse by using that
token. While performing a reduced action in accordance with production, it would
perform the semantic action associated with that production.

A parser generator is a program that takes as input a specification of a syntax and


produces as output a procedure for recognizing that language. Historically, they
are also called compiler compilers. YACC (yet another compiler-compiler) is an
LALR(1) (LookAhead, Left-to-right, Rightmost derivation producer with 1 lookahead
token) parser generator. YACC was originally designed for being complemented by
Lex.

Input File: YACC input file is divided into three parts:-


Definitions: these include the header files and any token information used in the
syntax. These are located at the top of the input file. Here, the tokens are defined
using a modulus sign. In the YACC, numbers are automatically assigned for tokens.
Rules: The rules are defined between %% and %%. These rules define the actions
for when the token is scanned and are executed when a token matches the
grammar.
Auxiliary Routines: Auxiliary routines contain the function required in the rules
section. This Auxiliary section includes the main() function, where the yyparse()
function is always called. This yyparse() function plays the role of reading the
token, performing actions and then returning to the main() after the execution or
in the case of an error. 0 is returned after successful parsing and 1 is returned after
an unsuccessful parsing.

34
EXPERIMENT - 5

Lexical Analyser using C to remove redundant spaces, tabs and


newlines

AIM: To implement a lexical analyser for given language using C and lexical
analyser should ignore redundant spaces, tabs and newlines.

ALGORITHM:

Step 0: Start the program


Step 1: Include the necessary C libraries.
Step 2: Define token type for lexical analyser including keywords, identifiers and
operators, etc for input language.
Step 3: Create a state machine to recognize different lexical elements. Define
states for each type of token & transitions between states based on input
characters.
Step 4: Initialise variables to store the current state, lexeme, etc being processed.
Step 5: Read the input source code.
Step 6: Implement a loop to iterate through each character in source code.
Step 7: Build the lexeme by appending characters to it.
Step 8: Check for spaces, tabs, etc and ignore them.
Step 9: When a token is recognised, determine its type based on the final state in
state machine.
Step 10: Output the recognised tokens along with their lexeme.
Step 11: Stop the program.

PROGRAM:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int kwd(char buffer[]);

int main()
{
char ch, buffer[15], buf[15], operators[] = "+-*/%=,;()";
FILE *fp;
int i, j = 0;
int ido = 0;

35
fp = fopen("inputfile.txt", "r");
if (fp == NULL)
{
printf("error while opening the file\n");
exit(0);
}
while ((ch = fgetc(fp)) != EOF)
{
for (i = 0; i < 10; i++)
{
if (ch == operators[i] && kwd(buffer) == 0)
printf("id ");
}

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


{
if (ch == operators[i])
if (operators[i] == '+')
printf("op-plus ");
else if (operators[i] == '-')
printf("op-sub ");
else if (operators[i] == '*')
printf("op-mul ");
else if (operators[i] == '/')
printf("op-div ");
else if (operators[i] == '%')
printf("op-mod ");
else if (operators[i] == '=')
printf("op-equ ");
else if (operators[i] == ';')
printf(";");
else if (operators[i] == ',')
printf(",");
else if (operators[i] == '(')
printf(".");
}

if (isalnum(ch))
{

buffer[j++] = ch;
}

36
else if ((ch == ' ' || ch == '\n') && (j != 0))
{

buffer[j] = '\0';

j = 0;

if (kwd(buffer) == 1)
printf("kwd ");
}
}
fclose(fp);
return 0;
}
int kwd(char buffer[])
{
char keywords[32][10] = {"auto", "break", "case", "char", "const", "continue",
"default",
"do", "double", "else", "enum", "extern", "float", "for", "goto",
"if", "int", "long", "register", "return", "short", "signed",
"sizeof", "static", "struct", "switch", "typedef", "union",
"unsigned", "void", "volatile", "while"};
int i, flag = 0;
// returns 1 if the buffer is a keyword
for (i = 0; i < 32; ++i)
{
if (strcmp(keywords[i], buffer) == 0)
{
flag = 1;
break;
}
}
return flag;
}

OUTPUT:

Input.txt

int a=b+c;

kwd id op-equ id op-plus id ;

37
RESULT: Program to implement lexical analyser using C by ignoring redundant
spaces, tabs and newline was successfully implemented.

38
EXPERIMENT - 6

Lexical Program to recognize all strings which does not first four
characters of your name as substring

AIM: To implement a lexical program to recognize all strings which does not first
four characters of your name as substring.

ALGORITHM:

Step 0: Start the program.


Step 1: Include the necessary C libraries.
Step 2: Define the first four characters of the name that needs to be excluded from
the strings.
Step 3: Define the lexical rules to recognise strings that do not contain specified
substring.
Step 4: Check if the particular yytext contains first four letters as substring by
specifying the corresponding rule and it would print the words that do not contain
the substring
Step 5: Define the main function to invoke the lex scanner.
Step 6: Stop the program.

PROGRAM:

%{
#include<stdio.h>
#include<math.h>
FILE *file;
%}

%%
[a-zA-Z]*"nand"[a-zA-Z]* {}
[a-zA-Z]* {printf("%s\n",yytext);}
%%
int main()
{
file = fopen("input.txt", "r");
if (!file)
{
printf("could not open the file");
exit(0);
}

39
yyin = file;
yylex();
printf("\n");
return (0);
}
int yywrap()
{
return (1);
}

OUTPUT:

Input.txt
my name is nandini

lex pgm.l
gcc lex.yy.c
./a.out
my
name
is

RESULT: Lexical program to recognize all strings which does not first four
characters of your name as substring was successfully implemented.

40
EXPERIMENT - 7

YACC Program to recognize a valid variable which starts with a letter


followed by any number of letters or digits

AIM: To implement a YACC Program to recognize a valid variable which starts with
a letter followed by any number of letters or digits.

ALGORITHM:

Step 0: Start the program


Step 1: Specify the tokens needed to represent the components of a valid variable.
Step 2: Create grammar rules that define the structure of a valid variable. It should
satisfy the condition that a variable starts with a letter followed by letters or digits.
Step 3: Write your rules corresponding to grammar rules, capturing syntax of a
valid variable.
Step 4: Specify actions to be taken when a valid variable is recognized or not.
Step 5: Print the output.
Step 6: Stop the program.

PROGRAM:

Yacc program:

%{
#include<stdio.h>
#include<stdlib.h>
%}
%token LET DIG
%%
variable:var
;
var:var DIG
|var LET
|LET
;
%%
int main() {
printf("Enter the variable:\n");
yyparse();
printf("Valid variable\n");
return 0;
}

41
int yyerror()
{
printf("Invalid variable \n");
exit(0);
}

Lex Program:

%{
#include "y.tab.h"
%}
%%
[a-zA-Z] {return LET;}
[0-9] {return DIG;}
. {return yytext[0];}
\n {return 0;}
%%
int yywrap() {
return 1;
}

OUTPUT:

lex pgm.l
yacc -d pgm.y
gcc lex.yy.c y.tab.c
./a.out

Enter the variable:


add1
Valid variable
Enter the variable:
1add
Invalid variable

RESULT: YACC Program to recognize a valid variable which starts with a letter
followed by any number of letters or digits was successfully implemented.

42
EXPERIMENT - 8

Implementation of calculator using Lex and Yacc

AIM: To implement a calculator using lex and yacc.

ALGORITHM:

Step 0: Start the program.


Step 1: Define tokens such as numbers, operators and parenthesis.
Step 2: Use lex to define regular expressions matching the pattern of tokens.
Step 3: Define the grammar rules f calculator considering precedence &
associativity of operators.
Step 4: Write yacc rules & define action for each rule.
Step 5: In yacc actions, builds an AST that represents structure of input expression.
Step 6: Extend yacc actions to perform actual calculations using AST.
Step 7: Print output/result of calculation.
Step 8: Stop the program.

PROGRAM:

Yacc Program

%{

#include<stdio.h>

int flag=0;

%}

%token NUMBER

%left '+' '-'

%left '*' '/' '%'

%left '(' ')'

%%

43
ArithmeticExpression: E{

printf("\nResult=%d\n",$$);

return 0;

};

E:E'+'E {$$=$1+$3;}

|E'-'E {$$=$1-$3;}

|E'*'E {$$=$1*$3;}

|E'/'E {$$=$1/$3;}

|E'%'E {$$=$1%$3;}

|'('E')' {$$=$2;}

| NUMBER {$$=$1;}

%%

void main()

printf("\nEnter Any Arithmetic Expression which can have operations Addition,


Subtraction, Multiplication, Divison, Modulus and Round brackets:\n");

yyparse();

if(flag==0)

printf("\nEntered arithmetic expression is Valid\n\n");

44
}

void yyerror()

printf("\nEntered arithmetic expression is Invalid\n\n");

flag=1;

Lex Program

%{

#include<stdio.h>

#include "y.tab.h"

extern int yylval;

%}

%%

[0-9]+ {

yylval=atoi(yytext);

return NUMBER;

[\t] ;

[\n] return 0;

. return yytext[0];

45
%%

int yywrap()

return 1;

OUTPUT:

lex pgm.l
yacc -d pgm.y
gcc lex.yy.c y.tab.c -w
./a.out

Enter Any Arithmetic Expression which can have operations Addition, Subtraction,
Multiplication, Divison, Modulus and Round brackets:
((5+6+10+4+5)/5)%2

Result=0

Entered arithmetic expression is Valid

Enter Any Arithmetic Expression which can have operations Addition, Subtraction,
Multiplication, Divison, Modulus and Round brackets:
(9=0)

Entered arithmetic expression is Invalid

RESULT: Implementation of calculator using lex and yacc was successfully done.

46
EXPERIMENT - 9

Yacc program to change BNF into Abstract Syntax Tree

AIM: To convert BNF rules into YACC form and write code to generate abstract
syntax tree.

ALGORITHM:

Step 0: Start the program


Step 1: Identify types of nodes in abstract syntax tree.
Step 2: Define C structures in YACC file to represent the different types of nodes.
Step 3: For each production rule in grammar, modify yacc action to create and link
nodes of AST.
Step 4: In yacc actions, instantiate the structure for the corresponding AST.
Step 5: Establish the parent-child relationships between nodes by updating points
to AST nodes.
Step 6: Return root of AST.
Step 7: Print the root node value.
Step 8: Stop the program.

PROGRAM:

Yacc Program

%{
#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;
%}

47
%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);}

48
| 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

49
;
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();

50
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()
{

51
printf("\n Error on line no:%d",LineNo);
}

Lex Program

%{
#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 yywrap()
{
return 1;
}

52
OUTPUT:

lex pgm.l
yacc -d pgm.y
gcc lex.yy.c y.tab.c -w
./a.out
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;
}
}

-----------------------------------
Pos Operator Arg1 Arg2 Result
-----------------------------------
0 < a b t0
1 == t0 FALSE 5
2 + a b t1
3 = t1 a
4 GOTO 5
5 < a b t2
6 == t2 FALSE 10
7 + a b t3
8 = t3 a
9 GOTO 5
10 <= a b t4
11 == t4 FALSE 15

53
12 - a b t5
13 = t5 c
14 GOTO 17
15 + a b t6
16 = t6 c
-----------------------------------

RESULT: Conversion of BNF rules into Yacc form to generate abstract syntax tree
was successfully implemented.

54
EXPERIMENT - 10

Yacc program to check syntax of For statement in C

AIM: To convert BNF rules into YACC form and write code to generate abstract
syntax tree.

ALGORITHM:

Step 0: Start the program.


Step 1: Identify the structure of a for loop in C & define grammar rules.
Step 2: Write yacc rules based on the grammar.
Step 3: Define the tokens needed for the for loop in lex file including keywords,
identifiers, etc.
Step 4: In the yacc actions, perform checks to ensure that the for loop follows
correct syntax.
Step 5: Print the output.
Step 6: Stop the program.

PROGRAM:

Yacc Program

%{
#include<stdio.h>
int valid=1;
%}
%token FOR LPAREN TYPE ID EQ NUMBER COMMA COMP RPAREN UPD
%%
FORSTMT:FOR LPAREN TYPE ID EQ NUMBER COMMA ID COMP NUMBER COMMA
ID UPD RPAREN
%%
int yyerror()
{
printf("Not Valid For Syntax");
valid=0;
return 0;
}
int main()
{
yyparse();
if(valid)
{

55
printf("Valid Syntax");
}
return 0;
}

Lex Program

%{
#include<stdio.h>
#include "y.tab.h"
%}
%%
for {return FOR;}
[(] {return LPAREN;}
int|double|float {return TYPE;}
[a-zA-Z_][a-zA-Z0-9_]* {return ID;}
[=] {return EQ;}
[0-9]+ {return NUMBER;}
[;] {return COMMA;}
[<>] {return COMP;}
[<>][=] {return COMP;}
[)] {return RPAREN;}
[+][+] {return UPD;}
[-][-] {return UPD;}
[ ] {}
[\n] {return 0;}
%%
int yywrap()
{
return 1;
}

OUTPUT:

lex pgm.l
yacc -d pgm.y
gcc lex.yy.c y.tab.c -w
./a.out
for(int i=0;i<10;i++)
Valid Syntax
for(int =0

56
Not Valid For Syntax

RESULT: Yacc program to check the syntax of for statement in C was successfully
implemented.

57
EXPERIMENT - 11

Operator Precedence Parser

AIM: To develop an operator precedence parser for a given language.

ALGORITHM:

Algo(Grammar G, input string w, Parsing Table T)


{
set p to point to the first symbol of w$;
repeat forever
if($ is on top of stack and p points to $)
Then return; //success
else
{
let a be the topmost terminal symbol on stack;
let b be the symbol pointed to by p;
1. if(a<b or a=.b) then {/*SHIFT*/
push b onto stack;
advance p to next input symbol;
}
2. else if(a>b) then /*REDUCE*/
repeat pop stack
until(top of stack terminal is related by < to terminal most recently
popped);
3. else error(); /*ERROR*/
}
}

PROGRAM:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

char *input;
int i=0;
char lasthandle[6],stack[50],handles[][5]={")E(","E*E","E+E","i","E^E"};

int top=0,l;

58
char prec[9][9]={

/*input*/

/*stack + - * / ^ i ( ) $ */

/* + */ '>', '>','<','<','<','<','<','>','>',

/* - */ '>', '>','<','<','<','<','<','>','>',

/* * */ '>', '>','>','>','<','<','<','>','>',

/* / */ '>', '>','>','>','<','<','<','>','>',

/* ^ */ '>', '>','>','>','<','<','<','>','>',

/* i */ '>', '>','>','>','>','e','e','>','>',

/* ( */ '<', '<','<','<','<','<','<','>','e',

/* ) */ '>', '>','>','>','>','e','e','>','>',

/* $ */ '<', '<','<','<','<','<','<','<','>',

};

int getindex(char c)
{
switch(c)
{
case '+':return 0;
case '-':return 1;
case '*':return 2;
case '/':return 3;
case '^':return 4;
case 'i':return 5;
case '(':return 6;
case ')':return 7;
case '$':return 8;
}
}

59
int shift()
{
stack[++top]=*(input+i++);
stack[top+1]='\0';
}

int reduce()
{
int i,len,found,t;
for(i=0;i<5;i++)//selecting handles
{
len=strlen(handles[i]);
if(stack[top]==handles[i][0]&&top+1>=len)
{
found=1;
for(t=0;t<len;t++)
{
if(stack[top-t]!=handles[i][t])
{
found=0;
break;
}
}
if(found==1)
{
stack[top-t+1]='E';
top=top-t+1;
strcpy(lasthandle,handles[i]);
stack[top+1]='\0';
return 1;//successful reduction
}
}
}
return 0;
}

void dispstack()
{

60
int j;
for(j=0;j<=top;j++)
printf("%c",stack[j]);
}

void dispinput()
{
int j;
for(j=i;j<l;j++)
printf("%c",*(input+j));
}

void main()
{
int j;

input=(char*)malloc(50*sizeof(char));
printf("\nEnter the string\n");
scanf("%s",input);
input=strcat(input,"$");
l=strlen(input);
strcpy(stack,"$");
printf("\nSTACK\tINPUT\tACTION");
while(i<=l)
{
shift();
printf("\n");
dispstack();
printf("\t");
dispinput();
printf("\tShift");
if(prec[getindex(stack[top])][getindex(input[i])]=='>')
{
while(reduce())
{
printf("\n");
dispstack();
printf("\t");

61
dispinput();
printf("\tReduced: E->%s",lasthandle);
}
}
}

if(strcmp(stack,"$E$")==0)
printf("\nAccepted;");
else
printf("\nNot Accepted;");
}

OUTPUT:

Enter the string


i*(i+i)*i

STACK INPUT ACTION


$i *(i+i)*i$ Shift
$E *(i+i)*i$ Reduced: E->i
$E* (i+i)*i$ Shift
$E*( i+i)*i$ Shift
$E*(i +i)*i$ Shift
$E*(E +i)*i$ Reduced: E->i
$E*(E+ i)*i$ Shift
$E*(E+i )*i$ Shift
$E*(E+E )*i$ Reduced: E->i
$E*(E )*i$ Reduced: E->E+E
$E*(E) *i$ Shift
$E*E *i$ Reduced: E->)E(
$E *i$ Reduced: E->E*E
$E* i$ Shift
$E*i $ Shift
$E*E $ Reduced: E->i
$E $ Reduced: E->E*E
$E$ Shift
$E$ Shift
Accepted;

RESULT: Program to develop an operator precedence parser for a given language


was successfully implemented.

62
EXPERIMENT - 12

Simulation of First and Follow of a Grammar

AIM: To develop a program to simulate first and follow of any given grammar.

ALGORITHM:

First():-

if x is a terminal, then FIRST(x) = {‘x’}


if x→epsilon is a production rule, then add epsilon to FIRST(x)
if x→Y1Y2Y3…Yn is a production,
FIRST(x) = FIRST(Y1)
if FIRST(Y1) contains epsilon then FIRST(x) = {FIRST(Y1)-epsilon} U {FIRST(Y2)}
if FIRST(Yi) contains epsilon for all i=1 to n, then add epsilon to FIRST(x).

Follow():-

FOLLOW(S)={$} // where S is non-terminal


if a→pBq is a production, where p,B and q are any grammar symbols;
then everything in FIRST(q) except epsilon is in FOLLOW(B)
if A→pB is a production, then everything in FOLLOW(A) is in FOLLOW(B).
if A→pBq is a production and FIRST(q) contains epsilon,
then FOLLOW(B) contains {FIRST(q)-epsilon} U FOLLOW(A);

PROGRAM:

#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// Functions to calculate Follow


void followfirst(char, int, int);
void follow(char c);

// Function to calculate First


void findfirst(char, int, int);

int count, n = 0;

63
// Stores the final result
// of the First Sets
char calc_first[10][100];

// Stores the final result


// of the Follow Sets
char calc_follow[10][100];
int m = 0;

// Stores the production rules


char production[10][10];
char f[10], first[10];
int k;
char ck;
int e;

int main(int argc, char** argv)


{
int jm = 0;
int km = 0;
int i, choice;
char c, ch;
count = 8;

// The Input grammar


strcpy(production[0], "X=TnS");
strcpy(production[1], "X=Rm");
strcpy(production[2], "T=q");
strcpy(production[3], "T=#");
strcpy(production[4], "S=p");
strcpy(production[5], "S=#");
strcpy(production[6], "R=om");
strcpy(production[7], "R=ST");

int kay;
char done[count];
int ptr = -1;

// Initializing the calc_first array


for (k = 0; k < count; k++) {
for (kay = 0; kay < 100; kay++) {
calc_first[k][kay] = '!';

64
}
}
int point1 = 0, point2, xxx;

for (k = 0; k < count; k++) {


c = production[k][0];
point2 = 0;
xxx = 0;

// Checking if First of c has


// already been calculated
for (kay = 0; kay <= ptr; kay++)
if (c == done[kay])
xxx = 1;

if (xxx == 1)
continue;

// Function call
findfirst(c, 0, 0);
ptr += 1;

// Adding c to the calculated list


done[ptr] = c;
printf("\n First(%c) = { ", c);
calc_first[point1][point2++] = c;

// Printing the First Sets of the grammar


for (i = 0 + jm; i < n; i++) {
int lark = 0, chk = 0;

for (lark = 0; lark < point2; lark++) {

if (first[i] == calc_first[point1][lark]) {
chk = 1;
break;
}
}
if (chk == 0) {
printf("%c, ", first[i]);
calc_first[point1][point2++] = first[i];
}

65
}
printf("}\n");
jm = n;
point1++;
}
printf("\n");
printf("-----------------------------------------------"
"\n\n");
char donee[count];
ptr = -1;

// Initializing the calc_follow array


for (k = 0; k < count; k++) {
for (kay = 0; kay < 100; kay++) {
calc_follow[k][kay] = '!';
}
}
point1 = 0;
int land = 0;
for (e = 0; e < count; e++) {
ck = production[e][0];
point2 = 0;
xxx = 0;

// Checking if Follow of ck
// has already been calculated
for (kay = 0; kay <= ptr; kay++)
if (ck == donee[kay])
xxx = 1;

if (xxx == 1)
continue;
land += 1;

// Function call
follow(ck);
ptr += 1;

// Adding ck to the calculated list


donee[ptr] = ck;
printf(" Follow(%c) = { ", ck);
calc_follow[point1][point2++] = ck;

66
// Printing the Follow Sets of the grammar
for (i = 0 + km; i < m; i++) {
int lark = 0, chk = 0;
for (lark = 0; lark < point2; lark++) {
if (f[i] == calc_follow[point1][lark]) {
chk = 1;
break;
}
}
if (chk == 0) {
printf("%c, ", f[i]);
calc_follow[point1][point2++] = f[i];
}
}
printf(" }\n\n");
km = m;
point1++;
}
}

void follow(char c)
{
int i, j;

// Adding "$" to the follow


// set of the start symbol
if (production[0][0] == c) {
f[m++] = '$';
}
for (i = 0; i < 10; i++) {
for (j = 2; j < 10; j++) {
if (production[i][j] == c) {
if (production[i][j + 1] != '\0') {
// Calculate the first of the next
// Non-Terminal in the production
followfirst(production[i][j + 1], i,
(j + 2));
}

if (production[i][j + 1] == '\0'
&& c != production[i][0]) {

67
// Calculate the follow of the
// Non-Terminal in the L.H.S. of the
// production
follow(production[i][0]);
}
}
}
}
}

void findfirst(char c, int q1, int q2)


{
int j;

// The case where we


// encounter a Terminal
if (!(isupper(c))) {
first[n++] = c;
}
for (j = 0; j < count; j++) {
if (production[j][0] == c) {
if (production[j][2] == '#') {
if (production[q1][q2] == '\0')
first[n++] = '#';
else if (production[q1][q2] != '\0'
&& (q1 != 0 || q2 != 0)) {
// Recursion to calculate First of New
// Non-Terminal we encounter after
// epsilon
findfirst(production[q1][q2], q1,
(q2 + 1));
}
else
first[n++] = '#';
}
else if (!isupper(production[j][2])) {
first[n++] = production[j][2];
}
else {
// Recursion to calculate First of
// New Non-Terminal we encounter
// at the beginning

68
findfirst(production[j][2], j, 3);
}
}
}
}

void followfirst(char c, int c1, int c2)


{
int k;

// The case where we encounter


// a Terminal
if (!(isupper(c)))
f[m++] = c;
else {
int i = 0, j = 1;
for (i = 0; i < count; i++) {
if (calc_first[i][0] == c)
break;
}

// Including the First set of the


// Non-Terminal in the Follow of
// the original query
while (calc_first[i][j] != '!') {
if (calc_first[i][j] != '#') {
f[m++] = calc_first[i][j];
}
else {
if (production[c1][c2] == '\0') {
// Case where we reach the
// end of a production
follow(production[c1][0]);
}
else {
// Recursion to the next symbol
// in case we encounter a "#"
followfirst(production[c1][c2], c1,
c2 + 1);
}
}
j++;

69
}
}
}

OUTPUT:

First(X) = { q, n, o, p, #, }

First(T) = { q, #, }

First(S) = { p, #, }

First(R) = { o, p, q, #, }

-----------------------------------------------

Follow(X) = { $, }

Follow(T) = { n, m, }

Follow(S) = { $, q, m, }

Follow(R) = { m, }

RESULT: Program to simulate first and follow of a grammar was successfully


implemented.

70
EXPERIMENT - 13

Recursive Descent Parser

AIM: To construct a recursive descent parser for an expression.

ALGORITHM:

Step 0: Start the program


Step 1: Define the context free grammar for expressions, including terminals and
non-terminal symbols and production rules.
Step 2: For each non terminal symbol in grammar, create a corresponding function
that implements production rule.
Step 3: Implement a tokenizer or lexical analyser to break input expression into
tokens.
Step 4: Create a main parsing function that initialises the parsing process.
Step 5: For each non terminal in the grammar, create a parsing function. These
functions should examine current token and choose appropriate production rule to
apply, call parsing functions for non-terminals or terminals that appear in
production rule.
Step 6: In each parsing function, consume tokens as they are matched by
production rules.
Step 7: Stop the program.

PROGRAM:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define SUCCESS 1
#define FAILED 0

int E(), Edash(), T(), Tdash(), F();

const char *cursor;


char string[64];

int main()
{
//puts("Enter the string");
// scanf("%s", string);
sscanf("i+(i+i)*i", "%s", string);

71
cursor = string;
puts("");
puts("Input Action");
puts("--------------------------------");

if (E() && *cursor == '\0') {


puts("--------------------------------");
puts("String is successfully parsed");
return 0;
} else {
puts("--------------------------------");
puts("Error in parsing String");
return 1;
}
}

int E()
{
printf("%-16s E -> T E'\n", cursor);
if (T()) {
if (Edash())
return SUCCESS;
else
return FAILED;
} else
return FAILED;
}

int Edash()
{
if (*cursor == '+') {
printf("%-16s E' -> + T E'\n", cursor);
cursor++;
if (T()) {
if (Edash())
return SUCCESS;
else
return FAILED;
} else
return FAILED;
} else {
printf("%-16s E' -> $\n", cursor);

72
return SUCCESS;
}
}

int T()
{
printf("%-16s T -> F T'\n", cursor);
if (F()) {
if (Tdash())
return SUCCESS;
else
return FAILED;
} else
return FAILED;
}

int Tdash()
{
if (*cursor == '*') {
printf("%-16s T' -> * F T'\n", cursor);
cursor++;
if (F()) {
if (Tdash())
return SUCCESS;
else
return FAILED;
} else
return FAILED;
} else {
printf("%-16s T' -> $\n", cursor);
return SUCCESS;
}
}

int F()
{
if (*cursor == '(') {
printf("%-16s F -> ( E )\n", cursor);
cursor++;
if (E()) {
if (*cursor == ')') {
cursor++;

73
return SUCCESS;
} else
return FAILED;
} else
return FAILED;
} else if (*cursor == 'i') {
cursor++;
printf("%-16s F ->i\n", cursor);
return SUCCESS;
} else
return FAILED;
}

OUTPUT:

Input Action
--------------------------------
i+(i+i)*i E -> T E'
i+(i+i)*i T -> F T'
+(i+i)*i F ->i
+(i+i)*i T' -> $
+(i+i)*i E' -> + T E'
(i+i)*i T -> F T'
(i+i)*i F -> ( E )
i+i)*i E -> T E'
i+i)*i T -> F T'
+i)*i F ->i
+i)*i T' -> $
+i)*i E' -> + T E'
i)*i T -> F T'
)*i F ->i
)*i T' -> $
)*i E' -> $
*i T' -> * F T'
F ->i
T' -> $
E' -> $
--------------------------------
String is successfully parsed

RESULT: Program to construct recursive descent parser for a grammar was


successfully implemented.

74
EXPERIMENT - 14

Shift Reduce Parser

AIM: To construct a shift reduce parser for a given language.

ALGORITHM:

Step 0: Start the program


Step 1: Define context free grammar for given language, including terminals, non-
terminals and production rules.
Step 2: Construct a parsing table that maps parsing states and lookahead tokens to
parsing actions or error handling.
Step 3: Initialise a stack to represent parser’s state and an input buffer with
sequence of tokens to be parsed.
Step 4: Start with an initial parsing state.
4.1:- Read current token from input buffer.
4.2:- Lookup the current state at top of stack and current token in parsing
table. Determine parsing action based on table entry.
4.3:- Repeat steps 4.1 & 4.2 until one of condition is met. If stack contains
only start symbol and input buffer is empty, input is accepted.
Step 5: Display stack implementation table.
Step 6: Stop the program

PROGRAM:

#include<stdio.h>
#include<stdlib.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()
{
printf("\n\t\t SHIFT REDUCE PARSER\n");
printf("\n GRAMMER\n");
printf("\n E->E+E\n E->E/E");
printf("\n E->E*E\n E->a/b");
printf("\n enter the input symbol:\t");

75
gets(ip_sym);
printf("\n\t stack implementation table");
printf("\n stack \t\t input symbol\t\t action");
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((!strcmp(temp2,"a"))||(!strcmp(temp2,"b")))
{
stack[st_ptr]='E';
if(!strcmp(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((!strcmp(temp2,"+"))||(strcmp(temp2,"*"))||(!strcmp(temp2,"/"))) { flag=1;

76
}
if((!strcmp(stack,"E+E"))||(!strcmp(stack,"E\E"))||(!strcmp(stack,"E*E")))
{
strcpy(stack,"E");
st_ptr=0;
if(!strcmp(stack,"E+E"))
printf("\n $%s\t\t%s$\t\t\tE->E+E",stack,ip_sym);
else
if(!strcmp(stack,"E\E"))
printf("\n $%s\t\t%s$\t\t\tE->E\E",stack,ip_sym);
else if(!strcmp(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(!strcmp(stack,"E")&&ip_ptr==len)
{
printf("\n $%s\t\t%s$\t\t\tACCEPT",stack,ip_sym);
exit(0);
}
if(flag==0)
{
printf("\n%s\t\t\t%s\t\t reject",stack,ip_sym);
exit(0);
}
return;
}

OUTPUT:

SHIFT REDUCE PARSER

GRAMMER

E->E+E
E->E/E
E->E*E
E->a/b
enter the input symbol: a+b

stack implementation table


stack input symbol action

77
________ ____________ ____________

$ a+b$ --
$a +b$ shifta
$E +b$ E->a
$E+ b$ shift+
$E+b $ shiftb
$E+E $ E->b
$E $ E->E+E
$E $ ACCEPT

RESULT: Program to construct shift reduce parser for a given language was
successfully implemented.

78
EXPERIMENT – 15

Intermediate Code Generation

AIM: To implement intermediate code generation for simple expressions.

ALGORITHM:

Step 0: Start the program


Step 1: Open the input file in read mode.
Step 2: Open the output file in write mode.
Step 3: If the operator is ‘+’
3.1:- Move arg1 to R0.
3.2:- Add arg2 and 0.
3.2:- Move R0 to result.
Step 4: If the operator is ‘-’
4.1:- Move arg1 to R0.
4.2:- Subtract arg2 and 0.
4.2:- Move R0 to result.
Step 5: If the operator is ‘*’
4.1:- Move arg1 to R0.
4.2:- Multiply arg2 and 0.
4.2:- Move R0 to result.
Step 6: If the operator is ‘/’
4.1:- Move arg1 to R0.
4.2:- Divide arg2 and 0.
4.2:- Move R0 to result.
Step 7: If the operator is ‘=’
4.1:- Move arg1 to R0.
4.2:- Move R0 to result.
Step 8: Close both the files.
Step 9: Stop the program.

PROGRAM:

#include<stdio.h>
#include<string.h>
char op[2],arg1[5],arg2[5],result[5];
void main()
{
FILE *fp1,*fp2;
fp1=fopen("input.txt","r");

79
fp2=fopen("output.txt","w");
while(!feof(fp1))
{

fscanf(fp1,"%s%s%s%s",op,arg1,arg2,result);
if(strcmp(op,"+")==0)
{
fprintf(fp2,"\nMOV R0,%s",arg1);
fprintf(fp2,"\nADD R0,%s",arg2);
fprintf(fp2,"\nMOV %s,R0",result);
}
if(strcmp(op,"*")==0)
{
fprintf(fp2,"\nMOV R0,%s",arg1);
fprintf(fp2,"\nMUL R0,%s",arg2);
fprintf(fp2,"\nMOV %s,R0",result);
}
if(strcmp(op,"-")==0)
{
fprintf(fp2,"\nMOV R0,%s",arg1);
fprintf(fp2,"\nSUB R0,%s",arg2);
fprintf(fp2,"\nMOV %s,R0",result);
}
if(strcmp(op,"/")==0)
{
fprintf(fp2,"\nMOV R0,%s",arg1);
fprintf(fp2,"\nDIV R0,%s",arg2);
fprintf(fp2,"\nMOV %s,R0",result);
}
if(strcmp(op,"=")==0)
{
fprintf(fp2,"\nMOV R0,%s",arg1);
fprintf(fp2,"\nMOV %s,R0",result);
}
}
fclose(fp1);
fclose(fp2);

80
OUTPUT:

MOV R0,a
ADD R0,b
MOV t1,R0
MOV R0,c
MUL R0,d
MOV t2,R0
MOV R0,t1
SUB R0,t2
MOV t,R0
MOV R0,t
MOV x,R0
MOV R0,t
MOV x,R0

RESULT: Program to implement intermediate code generation for simple


expressions was successfully done.

81
EXPERIMENT – 16

Implementation of Backend 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 an 8086 assembler. The target assembly instructions can
be simple move, add, sub, jump etc.

ALGORITHM:

Step 1: Start the program.


Step 2: Open the source file and store the contents as quadruples.
Step 3: Check for operators, in quadruples, if it is an arithmetic operator generator
it or if assignment operator generates it, else perform unary minus on register C.
Step 4: Write the generated code to output definition of the file.
Step 5: Print the output.
Step 6: Stop the program.

PROGRAM:

#include<stdio.h>
#include<string.h>
void main(){
char icode[10][30], str[20], opr[10];
int i=0;
printf("\nEnter the set of intermediate code (terminated by exit):\n");
do{
scanf("%s", icode[i]);
}
while(strcmp(icode[i++],"exit")!=0);
printf("\nTarget code generation");
printf("\n*******************");
i=0;
do{
strcpy(str,icode[i]);
switch(str[3]){
case '+':
strcpy(opr,"ADD");
break;
case '-':
strcpy(opr,"SUB");

82
break;
case '*':
strcpy(opr,"MUL");
break;
case '/':
strcpy(opr,"DIV");
break;

printf("\n\tMov %c,R%d", str[2],i);


printf("\n\%s%c,,R%d", opr,str[4],i);
printf("\n\tMov R%d%c", i,str[0]);
}while(strcmp(icode[++i],"exit")!=0); }

OUTPUT:

Enter the set of intermediate code (terminated by exit):


MOV R0,a
ADD R0,b
MOV t1,R0
exit

Target code generation


*******************
Mov V,R0
,,R0
Mov R0M
Mov ,,R1
,,R1
Mov R1R
Mov D,R2
,,R2
Mov R2A
Mov ,,R3
,,R3
Mov R3R
Mov V,R4
,,R4
Mov R4M
Mov ,,R5

83
0,,R5
Mov R5t

RESULT: Program to implement the back end of the compiler which takes the
three address code and produces the 8086 assembly language instructions was
successfully done.

84

You might also like