Compiler Design EXP-5
Compiler Design EXP-5
5
Aim: - WAP to compute FIRST and FOLLOW of non-terminals.
Theory: -
FIRST and FOLLOW sets – a necessary preliminary to constructing the LL(1)
parsing table
A predictive parser can only be built for an LL(1) grammar. A grammar is not LL(1) if it is:
1. Left recursive, or
However, grammars that are not left recursive and are left factored may still not be LL(1). To
see if a grammar is LL(1), try to build the parse table for the predictive parser by the method
we are about to describe. If any element in the table contains more than one grammar rule
To build the table, we must must compute FIRST and FOLLOW sets for the grammar.
FIRST Sets
Ultimately, we want to define FIRST sets for the right-hand sides of each of the grammar’s
productions. The idea is that for a sequence α of symbols, FIRST(α) is the set of terminals
that begin the strings derivable from α, and also, if α can derive ǫ, then ǫ is in FIRST(α).
More formally:
To define FIRST(α) for arbitrary α, we start by defining FIRST(X), for a single symbol
• X is a terminal: FIRST(X) = X
• X is ǫ: FIRST(X) = ǫ
• X is a nonterminal. In this case, we must look at all grammar productions with X on the
HET ANAND DAVE 40 ROLL NO-05
left, i.e., productions of the form:
X → Y1Y2Y3 . . . Yk
where each Yk is a single terminal or nonterminal (or there is just one Y, and it is ǫ).
–...
– If ǫ is in FIRST(Yi) for 1 _ i _ k (all production right- hand sides) then put ǫ into
FIRST(X).
For example, compute the FIRST sets of each of the non-terminals in the following
grammar:
Once we have computed FIRST(X) for each terminal and nonterminal X, we can compute
FIRST(α) for every production’s right-hand-side α. In general, alpha will be of the form:
X1X2 . . .Xn
The rules for computing FIRST(α) are essentially the same as the rules for computing the
first set of a nonterminal.
•...
For the example grammar above, compute the FIRST sets for each production’s right-hand
side.
Why do we care about the FIRST(α) sets? During parsing, suppose the top-of-stack symbol is
nonterminal A, that there are two productions A → α and A → β, and that the current token is
a. Follow Sets
FOLLOW set is a concept used in syntax analysis, specifically in the context of LR parsing
algorithms. It is a set of terminals that can appear immediately after a given non-terminal in a
grammar.
The FOLLOW set of a non-terminal A is defined as the set of terminals that can appear
immediately after A in any derivation of the grammar. If A can appear at the right-hand side of
a production rule, then the FOLLOW set of the left-hand side non-terminal of that production
Example:
S ->Aa | Ac
A ->b
SS
/\/\
AaAc
||
bb
Here, FOLLOW (A) = {a, c}
Example :
Production Rules:
E -> TE’
E’ -> +T E’|Є
T -> F T’
T’ -> *F T’ | Є
F -> (E) | id
FIRST set
FIRST(E) = FIRST(T) = { ( , id }
FIRST(E’) = { +, Є }
FIRST(T) = FIRST(F) = { ( , id }
FIRST(T’) = { *, Є }
FIRST(F) = { ( , id }
FOLLOW Set
FOLLOW(E) = { $ , ) } // Note ')' is there because of 5th rule
FOLLOW(T’) = FOLLOW(T) = { + , $ , ) }
Program: -
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int count, n = 0;
char calc_first[10][100];
char calc_follow[10][100];
int m = 0;
char production[10][10];
int k;
char ck;
int e;
int km = 0;
int i, choice;
char c, ch;
count = 8;
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;
calc_first[k][kay] = '!';
}
}
c = production[k][0];
point2 = 0;
xxx = 0;
if (c == done[kay])
xxx = 1;
if (xxx == 1)
continue;
findfirst(c, 0, 0);
ptr += 1;
done[ptr] = c;
printf("\n First(%c) = { ", c);
calc_first[point1][point2++] = c;
chk = 1;
break;
if (chk == 0) {
printf("%c, ", first[i]);
calc_first[point1][point2++] = first[i];
printf("}\n");
jm = n;
point1++;
printf("\n");
printf("-----------------------------------------------"
"\n\n");
char donee[count];
ptr = -1;
calc_follow[k][kay] = '!';
}
int land = 0;
ck = production[e][0];
point2 = 0;
xxx = 0;
if (ck == donee[kay])
xxx = 1;
if (xxx == 1)
continue;
land += 1;
follow(ck);
ptr += 1;
donee[ptr] = ck;
calc_follow[point1][point2++] = ck;
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;
if (production[0][0] == c) {
f[m++] = '$';
}
for (i = 0; i < 10; i++) {
if (production[i][j + 1] != '\0') {
followfirst(production[i][j + 1], i,
(j + 2));
if (production[i][j + 1] == '\0'
&& c != production[i][0]) {
follow(production[i][0]);
int j;
if (!(isupper(c))) {
first[n++] = c;
}
if (production[j][2] == '#') {
if (production[q1][q2] == '\0')
first[n++] = '#';
findfirst(production[q1][q2], q1,
(q2 + 1));
else
first[n++] = '#';
else if (!isupper(production[j][2])) {
first[n++] = production[j][2];
else {
findfirst(production[j][2], j, 3);
int k;
if (!(isupper(c)))
f[m++] = c;
else {
int i = 0, j = 1;
if (calc_first[i][0] == c)
break;
if (calc_first[i][j] != '#') {
f[m++] = calc_first[i][j];
else {
if (production[c1][c2] == '\0') {
follow(production[c1][0]);
else {
followfirst(production[c1][c2], c1,
c2 + 1);
j++;
}
Output:
CONCLUSION: - Hence we have studied about and implemented a program for computing FIRST and
FOLLOW of non-terminals.