Sei sulla pagina 1di 16

/* C program for NFA to DFA conversion */

/* Author: Ahmad Farhan <farhanhubble@gmail.com> */


/* Date 2010-AUG-10 */
/* Versio 0.0 */
/* This program does not perform epsilon-NFA to DFA conversion */

/** Important:
Dependencies: requires NFA2DFA.c (this file) and NFAparse.c
Compilation: use gcc NFA2DFA.c -o <output_file_name> -std=c99
Input: file NFA2DFA.txt is required at runtime. This file holds t
he transition table,list of input sy
mbols and list of final states in a special format.
*/

#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include"NFAparse.c"

int* _union(int* ,int* );


int candidateFinal(int *,int **,int);
int*** convert(int ***,int ***,int ,int *,char*);
void displayTable(int*** ,char *,int **,int , int);
int duplicate(int**,int,int*);
int exists(int *,int ,int);
int* getStateList(char* ,int* );
void Isort(int *);
void prt(int *);
int readNum(char *, int* );

int main(int argc, char** argv)


{
const char filename[] = "NFA2DFA.txt";
char *buffer = NULL;
int ***transition = NULL; /* Function delata:(Q,si
gma) --> P(Q) ; P = powerset */
char *input = NULL; /* Set sigma */
int **final = NULL; /* Set F */
int **states = NULL; /* Set Q */
int nInput;
int nFinal;
int nState;
int nbytes,ntries;
buffer = readFile(filename,&nbytes,&ntries);

puts("\n");
printf("%d bytes read from file %s in %d reads.",nbytes,filename
,ntries);
puts("\n----------Buffer dump----------");
puts(buffer);
puts("\n----------End of dump----------");

/* Read the input symbols */


int i = 0;
nInput = 0;
int EOLflag = 0;
while(1)
{
switch(buffer[i])
{
case EOF:
{
printf("\nUnexpe
cted end of file at index %d\n",i);
exit(1);
}
case ' ':
{
break;
}
case ',':
{
break;
}
case '\n':
{
EOLflag = 1;
break;
}
default:
{
if(!isalpha(buff
er[i]))
{
printf("\nUnexpected character %c encoutered, while scanning for input symbols\n
",buffer[i]);
exit(1);
}
input = (char*)r
ealloc(input,sizeof(char)*(nInput +1 ));
input[nInput] =
buffer[i];
nInput++;
}
}
if(EOLflag)
{
break;
}
++i;
}

printf("\n%d input symbols found: ",nInput);

/* Print all input symbols */


for(int j=0;j<nInput;j++)
{
printf(" %c ",input[j]);
}
printf("\n");

/* read all transitions */


nState = 0;
int col;
int hashFlag = 0;
while(1)
{
/* printf(" %c ",buffer[i]); */
switch(buffer[i])
{
case EOF:
{
printf("\nUnexpe
cted end-of-file while reading transition table\n");
exit(1);
}
case '#':
{
hashFlag = 1;
break;
}
case ' ':
{
break;
}
case ',':
{
break;
}
case ':':
{
transition = (in
t***)realloc(transition,sizeof(int**)*(nState+1));
transition[nStat
e] = (int**)malloc(sizeof(int*)*(nInput));
col=0;
nState++;
break;
}
case '\n':
{
break;
}
default :
{
if( !(isdigit(bu
ffer[i]) || buffer[i] == '-' ) )
{
printf("\nUnexpected character %c ",buffer[i]);
exit(1);
}

/* Extract the l
ist of states */
transition[nStat
e-1][col] = getStateList(buffer,&i);
col++;
}

} /* End of switch() */
if(hashFlag)
{
break;
}
++i;
} /* End of while() */

/* Read list of final states */


int endFlag = 0;
nFinal = 0;
while(1)
{
switch(buffer[i])
{
case ' ':
{
break;
}
case ',':
{
break;
}
case '#':
{
break;
}
case '\n':
{
endFlag = 1;
break;
}
case EOF:
{
endFlag = 1;
break;
}
default:
{
if(!isdigit(buff
er[i]))
{
printf("\nWarning: Unexpected symbol %c",buffer[i]);
break;
}
final = (int**)r
ealloc(final,sizeof(int*)*(nFinal+1));
final[nFinal] =
(int*)malloc(sizeof(int)*2);
final[nFinal][0]
= 1;
final [nFinal][1
] = readNum(buffer,&i);
nFinal++;
}
}
if(endFlag)
{
break;
}
i++;
} /* end of while() */
printf("\nFinal state(s) ");
for(int i=0;i<nFinal;i++)
{
printf("[");
for(int j=1;j<=final[i][0];j++)
{
printf(" %d ",final[i][j]);
}
printf("]");
}
printf("\n");

/* Store all states present in the NFA, in a 2-D array


* Each row stores state(s), part of a single\multi-state.
* First element in each row is the count of states on that row.
* follwed by the member state(s) *
*/
states = (int**)realloc(states,sizeof(int*)*nState);
for(int i=0;i<nState;i++)
{
states[i] = (int*)malloc(sizeof(int)*2);
states[i][0] = 1;
states[i][1] = i;
}

/* Print the NFA transition table */


printf("--------------------------------");
printf("\n NFA Transition Table ");
printf("\n--------------------------------\n");
displayTable(transition,input,states,nInput,nState);

int tmp1 = nState;


/* Convert to DFA */
transition = convert(transition,&states,nInput,&nState,input);

/* Update list of final states */


int tmp2 = nFinal;
for(int i=tmp1;i<nState;i++)
{
if( candidateFinal(states[i],final,tmp2) )
{
final = (int**)realloc(final,siz
eof(int*)*(nFinal+1));
final[nFinal] = (int*)malloc(siz
eof(int)*states[i][0]);
for(int j=0;j<=states[i][0];j++)
{
final[nFinal][j]
= states[i][j];
}
nFinal++;
}
}

/* Print DFA transition table */


printf("--------------------------------");
printf("\n DFA Transition Table ");
printf("\n--------------------------------\n");
displayTable(transition,input,states,nInput,nState);
printf("\nFinal state(s) ");
for(int i=0;i<nFinal;i++)
{
printf("[");
for(int j=1;j<=final[i][0];j++)
{
printf(" %d ",final[i][j]);
}
printf("]");
}
printf("\n");
return 0;
}

/* Convert a list of '/' separated strings into signed numbers */


int *getStateList(char* buf,int *indexPtr)
{
int *returnVector = (int*)malloc(sizeof(int));
int count = 1;

while(1)
{
if( isdigit(buf[*indexPtr]) || buf[*indexPtr
] == '-' )
{
returnVector = (int*)realloc(
returnVector,sizeof(int)*(count+1) );
returnVector[count] = readNum(bu
f,indexPtr);
count++;
}
else if( buf[*indexPtr] == ' ' || buf[*in
dexPtr] == '\n' || buf[*indexPtr] == ',' )
{
(*indexPtr)--;
break;
}

else if( buf[*indexPtr] == '/' )


{
/* Skip over any forward slashes
*/
}
else
{
printf("\nWarning. getStateList(
):Unexpected character %c will be skipped\n",buf[*indexPtr]);
}
(*indexPtr)++;
}
/* Store number of states as first element */
returnVector[0] = count-1;

#ifdef __DEBUG
printf("\n%d states are ",count-1);
for(int i =1;i<count;i++)
{
printf (" %d ",returnVector[i]);
}
printf("\n");
#endif
return returnVector;
}

/* Converts a string to signed integer */


int readNum(char *array,int *indexPtr)
{
int sign = 1;
int magnitude;
/* Detect sign */
if(array[*indexPtr] == '-')
{
sign = -1;
(*indexPtr)++;

}
/* Detect magnitude */
magnitude = 0;
while(array[*indexPtr] >= 48 && array[*indexPtr]<= 57)
{
magnitude = magnitude * 10 + array[*indexPtr] - 48;
(*indexPtr)++;
}
(*indexPtr)--; /* Unget last character read from buffer */

return (sign*magnitude);
}

/* Print transition table */


void displayTable(int ***table,char *symArray,int **states,int ncols, int nrows)
{
for(int i=0;i<ncols;i++)
{
printf("\t %c",symArray[i]);
}
printf("\n");
int count;
for(int i=0;i<nrows;i++)
{
for(int o=1;o<=states[i][0];o++)
{
printf("%d ",states[i][o]);
}
for(int j=0;j<ncols;j++)
{
count = table[i][j][0];

printf("\t");
for(int k=1;k<=count;k++)
{
printf(" %d ",ta
ble[i][j][k]);
}

}
printf("\n");
}
}
/* Convert an NFA to equivalent DFA */
int*** convert(int ***table,int ***ptrStates,int nsymbol,int *ptrNstate,char *in
)
{
int i,j,k;
int *uarray ;
int a;
int b;

for(i=0;i<*ptrNstate;i++)
{
for(j=0;j<nsymbol;j++)
{
/* If a multi-state is found */
int count = table[i][j][0];
if( count > 1
)
{
if(duplicate(*pt
rStates,*ptrNstate,table[i][j])) continue;
/* Add a row to
transition table and state list */
table = (int***)
realloc( table,sizeof(int**)*(*ptrNstate + 1));
table[*ptrNstate
] = (int**)malloc(sizeof(int*)*(nsymbol));
(*ptrStates) = (
int**)realloc ( (*ptrStates),sizeof(int*)*(*ptrNstate + 1));
(*ptrStates)[*pt
rNstate] = (int*)malloc(sizeof(int)*(*ptrNstate));

/*Copy multistat
e to state list */
for(k=0;k<=nsymb
ol;k++)
{
(*ptrStates)[*ptrNstate][k] = table[i][j][k];
}

/* Compute trans
itions for new multi-state */

for(a=0;a<nsymb
ol;a++) /* for every input symbol */
{
uarray = NULL;

for(b=1;b<=count;b++) /* for every state in this multi-state */


{
int s = (*ptrStates)[*ptrNstate][b];

#ifdef __DEBUG
printf("\n---------------------------------------");
printf("\nSending array 1>>>>");
prt(uarray);
printf("\n");
printf("Sending array 2>>>> ");
prt(table[s][a]);
printf("\n");
#endif

uarray = _union(uarray,table[s][a]);

#ifdef __DEBUG
printf("Got Union array>>>> ");
prt(uarray);
printf("\n-----------------------------------------\n");
#endif

Isort(uarray);
table[*ptrNstate][a] = uarray;
}

#ifdef __DEBUG
displayTable(tab
le,in,*ptrStates,nsymbol,*ptrNstate);
printf("\nPress
any key to continue");
getchar();
#endif
(*ptrNstate)++;
} /* end of if() */
} /* end of for() */
} /* end of far */

/* Update list of final states */

return table;
}

/* Perform union on two vectors*/


int *_union(int* arr1,int* arr2)
{
int *result;
if(arr1 == NULL)
{
result = (int*)malloc(sizeof(int)*(arr2[0]+1));
result[0] = arr2[0] ;
for(int i=1;i<=arr2[0];i++)
{
result[i] = arr2[i];
}
}
else if(arr2 == NULL)
{
result = (int*)malloc(sizeof(int)*(arr1[0]+1));
result[0] = arr1[0];
for(int i=1;i<=arr1[0];i++)
{
result[i] = arr1[i];
}
}

else
{
result = (int*)malloc(sizeof(int)*(arr1[0] + arr
2[0] + 1 ));
result[0] = arr1[0] + arr2[0];
int i;
/* copy all elements from arr1[] */
for(i=1;i<=arr1[0];i++)
{
result[i] = arr1[i];
}

/* copy elements from arr2[], not already copied


from arr1[] */
for(int j=1;j<=arr2[0];j++)
{
if(!exists(arr1,arr2[j],arr1[0])
)
{
result[i] = arr2
[j];
i++;
}
else
{
result[0]--;
}
}

if(result[0] > 1)
{
for(int c= result[1] ;c<=result[
0];c++)
{
if(result[c] ==
-1)
{
for(int d = c;d<result[0];d++)
{
result[d] = result[d+1];
}

result[0]--;
}
}
}

}
return result;
}

/* Look for a value in a vector */


int exists(int *a,int v,int max)
{
int r = 0;
for(int i=1;i<=max;i++)
{
if(a[i] == v)
{
r = 1;
break;
}
}
return r;
}

/* Print a vector */
void prt(int *a)
{
if(a==NULL) {
printf(" = NULL");
return;
}
int count = a[0];
int i = 1;
while(i<=count)
{
printf(" %d ",a[i]);
i++;
}
}

/* Look for state 'b' in list 'a' */


int duplicate(int **a,int max,int *b)
{
int ret = 0;
int i,j;
int diff;
for(i=0;i<max;i++)
{
diff = 0;
for(j=0;j<=a[i][0];j++)
{
if(a[i][j] != b[j])
{
diff = 1;
break;
}
}
if(diff == 0)
{
ret = 1 ;
break;
}
}
return ret;
}

/* Insertion sort a vector */


void Isort(int *l)
{
int i;
int j;
int k;
int count = l[0];
int tmp;

for(i=1;i<=count;i++)
{
tmp = l[i];
j=i-1;
while(l[j] > tmp && j>0 )
{
j--;
}
for(k=i-1;k>j;k--)
{
l[k+1] = l[k];
}
l[j+1] = tmp;

}
}

/* Test if a state is a valid final state */


int candidateFinal(int *testV,int **list,int max)
{
int ret = 0;
int i,j;
int lookfor;

for(i=0;i<max;i++)
{
lookfor = list[i][1]; /* The only element */
for(j=1;j<=testV[0];j++)
{
if(testV[j] == lookfor)
{
ret = 1;
break;
}
}
}
return ret;
}

Potrebbero piacerti anche