#include <stdio.
h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_NON_TERMINALS 26
#define MAX_PRODUCTIONS 100
#define MAX_SYMBOLS 10
typedef struct {
char lhs;
char rhs[MAX_SYMBOLS];
} Produc on;
Produc on produc ons[MAX_PRODUCTIONS];
int num_produc ons = 0;
char non_terminals[MAX_NON_TERMINALS];
int num_non_terminals = 0;
char follow[MAX_NON_TERMINALS][MAX_SYMBOLS];
int is_non_terminal(char c) {
return isupper(c);
int add_to_follow(char nt, char symbol) {
int i;
for (i = 0; follow[nt - 'A'][i] != '\0'; i++) {
if (follow[nt - 'A'][i] == symbol) {
return 0; // Symbol already exists, no change
}
follow[nt - 'A'][i] = symbol;
follow[nt - 'A'][i + 1] = '\0';
return 1; // Symbol added, change occurred
void compute_follow() {
int i, j, k;
char nt, symbol;
int changed;
// Add $ to FOLLOW(S)
add_to_follow(produc ons[0].lhs, '$');
do {
changed = 0;
for (i = 0; i < num_produc ons; i++) {
nt = produc ons[i].lhs;
for (j = 0; produc ons[i].rhs[j] != '\0'; j++) {
if (is_non_terminal(produc ons[i].rhs[j])) {
symbol = produc ons[i].rhs[j];
if (produc ons[i].rhs[j + 1] == '\0') {
for (k = 0; follow[nt - 'A'][k] != '\0'; k++) {
if (add_to_follow(symbol, follow[nt - 'A'][k])) {
changed = 1;
} else if (is_non_terminal(produc ons[i].rhs[j + 1])) {
// Add FIRST(next symbol) to FOLLOW(current symbol)
for (k = 0; k < num_produc ons; k++) {
if (produc ons[k].lhs == produc ons[i].rhs[j + 1]) {
if (add_to_follow(symbol, produc ons[k].rhs[0])) {
changed = 1;
// If next symbol is nullable, also add FOLLOW(next symbol)
if (strchr(produc ons[i].rhs + j + 1, 'e') != NULL) {
for (k = 0; follow[produc ons[i].rhs[j + 1] - 'A'][k] != '\0'; k++) {
if (add_to_follow(symbol, follow[produc ons[i].rhs[j + 1] - 'A'][k])) {
changed = 1;
} else {
if (add_to_follow(symbol, produc ons[i].rhs[j + 1])) {
changed = 1;
} while (changed);
void print_follow() {
int i, j;
for (i = 0; i < num_non_terminals; i++) {
prin ("FOLLOW(%c) = { ", non_terminals[i]);
for (j = 0; follow[non_terminals[i] - 'A'][j] != '\0'; j++) {
prin ("%c ", follow[non_terminals[i] - 'A'][j]);
prin ("}\n");
}
int main() {
char lhs, rhs[MAX_SYMBOLS];
int i;
prin ("Enter produc ons (one per line, 'end' to finish):\n");
while (1) {
if (scanf(" %c -> %s", &lhs, rhs) != 2) {
prin ("Invalid input format. Please use 'X -> abc' format.\n");
while (getchar() != '\n'); // Clear input buffer
con nue;
if (strcmp(rhs, "end") == 0) break;
if (!is_non_terminal(lhs)) {
prin ("Le -hand side must be a non-terminal (uppercase le er)\n");
con nue;
produc ons[num_produc ons].lhs = lhs;
strcpy(produc ons[num_produc ons].rhs, rhs);
num_produc ons++;
for (i = 0; i < num_non_terminals; i++) {
if (non_terminals[i] == lhs) break;
if (i == num_non_terminals) {
non_terminals[num_non_terminals++] = lhs;
}
}
compute_follow();
print_follow();
return 0;
// Enter produc ons (one per line, 'end' to finish):
// E -> E+T
// E -> T
// T -> T*F
// T -> F
// F -> (E)
// F -> id
// S->end
// FOLLOW(E) = { $ + ) }
// FOLLOW(T) = { $ + * ) }
// FOLLOW(F) = { $ + * ) }