#include <stdio.
h>
#include <string.h>
#include <ctype.h>
#define MAX 10 // maximum number of productions
#define LEN 20 // maximum length of a production
char prod[MAX][LEN]; // array to store the productions
char first[MAX][LEN]; // array to store the first sets
char follow[MAX][LEN]; // array to store the follow sets
int nop; // number of productions
// function to find the first set of a symbol
void findfirst(char c, int p, int q)
{
int j;
// if the symbol is a terminal, add it to the first set
if (!isupper(c))
{
first[p][q++] = c;
}
// loop through the productions
for (j = 0; j < nop; j++)
{
// if the symbol is a non-terminal and matches the left-hand side of a
production
if (prod[j][0] == c)
{
// if the right-hand side of the production starts with epsilon, add it
to the first set
if (prod[j][2] == '#')
{
first[p][q++] = '#';
}
// else, find the first set of the next symbol in the production
recursively
else
{
findfirst(prod[j][2], p, q);
}
}
}
}
// function to find the follow set of a symbol
void findfollow(char c, int p, int q)
{
int i, j;
// if the symbol is the start symbol, add $ to the follow set
if (prod[0][0] == c)
{
follow[p][q++] = '$';
}
// loop through the productions
for (i = 0; i < nop; i++)
{
// loop through the right-hand side of each production
for (j = 2; j < strlen(prod[i]); j++)
{
// if the symbol matches the current symbol in the production
if (prod[i][j] == c)
{
// if the symbol is not at the end of the production
if (prod[i][j + 1] != '\0')
{
// find the first set of the next symbol in the production
findfirst(prod[i][j + 1], p, q);
// loop through the first set
for (int k = 0; k < strlen(first[p]); k++)
{
// if the first set contains epsilon, then add the follow
set of the left-hand side symbol to the follow set of the current symbol
if (first[p][k] == '#')
{
// avoid adding the follow set of the same symbol
recursively
if (prod[i][0] != c)
{
findfollow(prod[i][0], p, q);
}
}
// else, add the first set (without epsilon) to the follow
set of the current symbol
else
{
follow[p][q++] = first[p][k];
}
}
}
// if the symbol is at the end of the production, then add the
follow set of the left-hand side symbol to the follow set of the current symbol
else
{
// avoid adding the follow set of the same symbol recursively
if (prod[i][0] != c)
{
findfollow(prod[i][0], p, q);
}
}
}
}
}
}
// function to remove duplicates from a string
void removeduplicates(char *s)
{
int i, j, k;
// loop through the string
for (i = 0; i < strlen(s); i++)
{
// loop through the rest of the string
for (j = i + 1; j < strlen(s); j++)
{
// if a duplicate is found, shift the characters to the left
if (s[i] == s[j])
{
for (k = j; k < strlen(s); k++)
{
s[k] = s[k + 1];
}
j--;
}
}
}
}
// main function
int main()
{
int i, j;
char c;
// input the number of productions
printf("Enter the number of productions: ");
scanf("%d", &nop);
// input the productions
printf("Enter the productions (use # for epsilon):\n");
printf("Exp = S->aB\n S->#\n");
for (i = 0; i < nop; i++)
{
scanf("%s", prod[i]);
}
// loop through the productions
for (i = 0; i < nop; i++)
{
// get the left-hand side symbol of the production
c = prod[i][0];
// find the first set of the symbol
findfirst(c, i, 0);
// remove duplicates from the first set
removeduplicates(first[i]);
}
// loop through the productions
for (i = 0; i < nop; i++)
{
// get the left-hand side symbol of the production
c = prod[i][0];
// find the follow set of the symbol
findfollow(c, i, 0);
// remove duplicates from the follow set
removeduplicates(follow[i]);
}
// print the first sets
printf("\nFirst Sets:\n");
for (i = 0; i < nop; i++)
{
printf("First(%c) = { %s }\n", prod[i][0], first[i]);
}
// print the follow sets
printf("\nFollow Sets:\n");
for (i = 0; i < nop; i++)
{
printf("Follow(%c) = { %s }\n", prod[i][0], follow[i]);
}
return 0;
}