0% found this document useful (0 votes)
3 views9 pages

Compiler Design Lab Assignment

Compiler_Design_Lab_Assignment
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views9 pages

Compiler Design Lab Assignment

Compiler_Design_Lab_Assignment
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

COMPILER DESIGN LABORATORY ASSIGNMENT

INTRODUCTION TO FIRST, FOLLOW, LEFT RECURSION, LEFT


FACTORING
➤ 1. FIRST Set

FIRST(X) is the set of terminals that begin the strings derivable from X.

➤ 2. FOLLOW Set

FOLLOW(A) is the set of terminals that can appear immediately to the right of A in some sentential form.

➤ 3. Left Recursion

A grammar has left recursion if a non-terminal refers to itself as the leftmost symbol in one of its productions:

4. Left Factoring

Used when two or more productions for a non-terminal begin with the same symbols:

EXAMPLE
➤ 1. FIRST Se

E → T E'

E' → + T E' | ε

T → F T'

T' → * F T' | ε

F → ( E ) | id

FIRST(E) = { (, id }

FIRST(E') = { +, ε }

FIRST(T) = { (, id }

FIRST(T') = { *, ε }

FIRST(F) = { (, id }

➤ 2. FOLLOW Set: Consider previous example

FOLLOW(E) = { $ }

FOLLOW(E') = { $ }

FOLLOW(T) = { +, $ }

FOLLOW(T') = { +, $ }

FOLLOW(F) = { *, +, $ }
➤ 3. Left Recursion:

A → Aα | β
Can be converted into:

A → βA'
A' → αA' | ε

4. Left Factoring:

A → αβ1 | αβ2
Can be converted into:
A → αA'
A' → β1 | β2

CODE IMPLEMENTATION IN C:

➤ 1. FIRST Set:

#include <stdio.h>
#include <ctype.h>
#include <string.h>

char prod[10][10];

char first[10];
int n, m = 0;

void findFirst(char c);

int main() {
int i;
char c, ch;

printf("Enter number of productions: ");

scanf("%d", &n);
printf("Enter productions (e.g., E=E+T):\n");
for (i = 0; i < n; i++)

scanf("%s", prod[i]);

printf("Enter symbol to find FIRST: ");


scanf(" %c", &c);

findFirst(c);

printf("FIRST(%c) = { ", c);


for (i = 0; i < m; i++)
printf("%c ", first[i]);

printf("}\n");

return 0;
}

void findFirst(char c) {
int i;
if (!isupper(c)) {
first[m++] = c;
return;

for (i = 0; i < n; i++) {


if (prod[i][0] == c) {
if (!isupper(prod[i][2]))
first[m++] = prod[i][2];

else
findFirst(prod[i][2]);
}
}
}
➤ 2. FOLLOW Set:

#include <stdio.h>
#include <string.h>

#include <ctype.h>

char prods[10][10];
int n;
char follow[10];
int m = 0;

void findFirst(char c, char* result);


void findFollow(char c);

int main() {

int i;
char c;

printf("Enter number of productions: ");


scanf("%d", &n);

printf("Enter productions (e.g., S=AB):\n");


for (i = 0; i < n; i++)
scanf("%s", prods[i]);

printf("Enter symbol to find FOLLOW: ");

scanf(" %c", &c);

findFollow(c);

printf("FOLLOW(%c) = { ", c);

for (i = 0; i < m; i++)


printf("%c ", follow[i]);
printf("}\n");
return 0;

void findFirst(char c, char* result) {


int i, k = 0;
if (!isupper(c)) {

result[k++] = c;
result[k] = '\0';
return;
}

for (i = 0; i < n; i++) {


if (prods[i][0] == c) {
if (!isupper(prods[i][2]))
result[k++] = prods[i][2];
else

findFirst(prods[i][2], result);
}
}
result[k] = '\0';
}

void findFollow(char c) {
int i, j;
char result[10];
if (c == prods[0][0])
follow[m++] = '$';

for (i = 0; i < n; i++) {


for (j = 2; j < strlen(prods[i]); j++) {
if (prods[i][j] == c) {
if (prods[i][j + 1] != '\0') {

findFirst(prods[i][j + 1], result);


for (int k = 0; result[k] != '\0'; k++)
follow[m++] = result[k];

}
if (prods[i][j + 1] == '\0' && c != prods[i][0])
findFollow(prods[i][0]);
}
}

}
}

➤ 3. Left Recursion:

#include <stdio.h>
#include <string.h>

void removeLeftRecursion(char *);

int main() {
char production[100];
printf("Enter production (e.g., A=Aa|b): ");
scanf("%s", production);
removeLeftRecursion(production);

return 0;
}

void removeLeftRecursion(char *prod) {


char nonTerminal = prod[0];

char alpha[10][10], beta[10][10];


int i = 0, j = 0, k = 0, m = 0, n = 0;

i = 2; // Skip A=
while (prod[i] != '\0') {

if (prod[i] == '|') {
if (prod[2] == nonTerminal) // Left recursive
alpha[m++][k] = '\0';
else
beta[n++][j] = '\0';

k = j = 0;
i++;
} else if (prod[2] == nonTerminal && k == 0) {
i++;
} else {

if (prod[2] == nonTerminal) {
alpha[m][k++] = prod[i++];
} else {
beta[n][j++] = prod[i++];
}

}
}
if (prod[2] == nonTerminal)
alpha[m++][k] = '\0';
else

beta[n++][j] = '\0';

if (m == 0) {
printf("No Left Recursion\n");
return;

printf("After removing Left Recursion:\n");


printf("%c -> ", nonTerminal);
for (i = 0; i < n; i++)
printf("%s%c' | ", beta[i], nonTerminal);

printf("\b\b \n");

printf("%c' -> ", nonTerminal);


for (i = 0; i < m; i++)
printf("%s%c' | ", alpha[i], nonTerminal);

printf("ε\n");
}
4. Left Factoring:

#include <stdio.h>
#include <string.h>

void leftFactor(char *prod);

int main() {
char prod[100];
printf("Enter production (e.g., A=abc|abd): ");
scanf("%s", prod);
leftFactor(prod);

return 0;
}

void leftFactor(char *prod) {


char nt = prod[0];

char part1[20], part2[20];


int i = 2, j = 0;

while (prod[i] != '|')


part1[j++] = prod[i++];
part1[j] = '\0';

i++; j = 0;
while (prod[i] != '\0')
part2[j++] = prod[i++];
part2[j] = '\0';

// Find common prefix


char prefix[20];
int len = strlen(part1) < strlen(part2) ? strlen(part1) : strlen(part2);
for (i = 0; i < len; i++) {
if (part1[i] == part2[i])

prefix[i] = part1[i];
else
break;
}
prefix[i] = '\0';

if (strlen(prefix) == 0) {
printf("No common prefix, no left factoring needed.\n");
return;
}

printf("After Left Factoring:\n");


printf("%c -> %s%c'\n", nt, prefix, nt);
printf("%c' -> %s | %s\n", nt, &part1[i], &part2[i]);
}

OBJECTIVE:-
• Write a C program to construct the LL(1) parsing table using computed FIRST and
FOLLOW sets.
• Write a C program to simulate an LL(1) parser using a hardcoded parsing table
and stack simulation
• Write a C program that checks whether a given grammar is LL(1) or not.

You might also like