Beruflich Dokumente
Kultur Dokumente
h"
/*
* Creates a table for grammar productions.
* Arg1 = Char array of grammar
* Arg2 =
*/
struct prodList **makeGrammarTable(char *grammar, int *errornum,int *nvar)
{
struct prodList **table = NULL; /* An ar
ray of structures for holding the entire grammar */
char **productions ; /* Holds
all productions of a variable */
assert(table == NULL);
assert(*nvar == 0);
}
NEW = (struct prodList*)malloc(sizeof(struct prodList));
*nvar = nvariables;
*errornum = 0;
return table;
}
/* Generate nullable */
int genNullables(struct prodList **table,int var_count,char *tokenSet)
{
int i,j;
_Bool changed ;
char *head = NULL;
int prodcount;
char *body;
/* Find all nullable variables */
#ifdef DEBUG
int runs = 0;
#endif
for(i=0;i<var_count;i++) /* For every variable X */
{
table[i]->nullable = false; /* Initialize nullable[X] to fal
se */
}
changed = true;
for(; changed == true ;) /* Repeat until changed becomes false */
{
changed=false;
#ifdef DEBUG
runs++;
#endif
#ifdef DEBUG
printf("\n***************ITERATION = %d***************",runs);
#endif
for(i=0;i<var_count;i++) /* For every var
iable X */
{
head = table[i]->head;
prodcount = table[i]->prodcount;
#ifdef DEBUG
printf("\nNow examining variable %s",head);
#endif
for(j=0;j<prodcount;j++) /* For every pro
duction of variable X */
{
body = table[i]->productions[j];
#ifdef DEBUG
printf("\nproduction %s",body);
#endif
if(isNullable(body,table,var_count,tokenSet))
/* body is nullable */
{
#ifdef DEBUG
printf("\nProduction body %s is nullable
",body);
#endif
if(table[i]->nullable == false) /* But X
is not marked nullable */
{
table[i]->nullable = true;
/* Mark X as nullable */
changed = true;
#ifdef DEBUG
printf("\nVariable %s was set as
not-nullable",head);
printf(".Updated as nullable");
#endif
}
#ifdef DEBUG
else printf("\nVariable %s is already se
t as nullable",head);
#endif
}
#ifdef DEBUG
else printf("\nProduction body %s is not nullabl
e. Nothing to do.",body);
#endif
return 0;
}
/*
* Generate FIRST set for all symbols
* Arg1 = Grammar table
* Arg2 = Number of variables in grammar
* Arg3 = List of tokens
*/
int genFirst(struct prodList** table,int var_count,char* tokenSet)
{
int i,j,k,l;
_Bool changed ;
char *head = NULL;
int prodcount;
char *body;
char *next;
int test = 0;
} /* for( ; ;) */
/*
* Generate follow set for for each variable;
* Arg1 = grammar table;
* Arg2 = number of variables;
* Arg3 = Set of token strings;
*/
int genFollow(struct prodList** table,int var_count,char* tokenSet)
{
int i,j,k,l,a;
_Bool changed ;
char *head = NULL;
int prodcount;
char *body;
char *next;
char *lookright;
int test = 0;
char *tmp;
changed = true;
table[0]->follow = doUnion(table[0]->follow ,"$",&test); /* Add e
nd of input marker
to FOLLOW of start symbol */
for( ; changed == true ;) /* As long as 'changed' stays true */
{
changed = false;
for(i=0 ; i< var_count ; i++) /* For every variable X */
{
head = table[i]->head;
prodcount = table[i]->prodcount;
for(j=0 ; j< prodcount ;j++) /* For every production
of variable X */
{
body = table[i]->productions[j] ;
int lastseen = 0;
for( ; ;) /* For every symbol in this prod
uction */
{
next = getNextSymbol(body,&lastseen);
#ifdef DEBUG
printf("\nNow examining symbol %s in pro
duction %s",next,body);
#endif
if(next == NULL) break; /* Done processi
ng this production */
else if(isToken(next,tokenSet)) /* If th
is symbol is a terminal */
{
continue; /* Do nothing fo
r terminals */
/* FOLLO
W[terminal] = terminal */
}
else /* Symbol is a variable Y*/
{
int tmplastseen = lastseen;
/* Do not change original last-seen */
k = indexOf(next,table,var_count
); /* Find Y in the grammar table */
for( ; ;) /* For every symbol Z
to the right of Y in this body */
{
lookright = getNextSymbo
l(body,&tmplastseen); /* Get symbol Z to the right of Y
in this production */
if(lookright == NULL) /*
If we have reached the end of this production of X */
{
/* Add FOLLOW[X]
to FOLLOW[Y] */
table[k]->follow
= doUnion(table[k]->follow,table[i]->follow,&test);
if(test)
{
changed
= true;
}
break;
}
else if(isToken(lookrigh
t,tokenSet)) /* Symbol Z is a terminal */
{
table[k]->follow
= doUnion(table[k]->follow,lookright,&test);
if(test)
{
changed
= true;
}
break; /* No sy
mbols after this will contribute to FOLLOW[Y] */
}
else /* Symbol Z is a va
riable */
{
l = indexOf(look
right,table,var_count); /* Find Z in the grammar table */
for(a=0 ; a<tabl
e[l]->prodcount ; a++) /* For every production of Z */
{
/** If f
irst set for this production of Z has an epsilon,
* stri
p off the epsilon.
*/
tmp = re
moveFromSet(table[l]->first[a],"epsilon",NULL);
table[k]
->follow = doUnion(table[k]->follow,tmp,&test);
if(test)
{
changed = true;
}
}
/** If variable
Z is not nullable do not look right of Z. */
if(table[l]->nul
lable == false) break;
}