Uploaded by Aritra Ghosh

ARITRA GHOSH CD ASSIGNMENT-2

advertisement
ARITRA GHOSH ( 21BCE2550 )
DIGITAL ASSIGNMENT-1
COMPILER DESIGN
SLOT: L1+L2
NAME:ARITRA GHOSH
REG NO:21BCE2550
Q1. Write a c program to find tokens in the following line if (a==b)c=a;
PROGRAM:
#include <stdio.h>
#include <string.h>
int main() {
char line[] = "if (a==b)c=a;";
char* token;
// Define delimiters for tokenization
const char delimiters[] = " =();";
// Tokenize the line
token = strtok(line, delimiters);
while (token != NULL) {
printf("Token: %s\n", token);
token = strtok(NULL, delimiters);
}
return 0;
}
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
OUTPUT:
ALGORITHM:
1. Define a structure to represent a token. Each token should have a type (e.g., identifier,
keyword, operator) and a value (the actual token string).
2. Define an array or list to store the tokens identified in the line.
3. Obtain the input line that needs to be parsed.
4. Implement a function findTokens(inputLine) that takes the input line as a parameter and
performs the following steps:
a. Initialize a variable currentToken to an empty string.
b. Iterate through each character in the input line:
•
If the current character is a whitespace character (space, tab, newline), check if
currentToken is not empty. If it's not empty, create a new token with the appropriate
type and value, and add it to the list of tokens. Reset currentToken to an empty
string.
•
If the current character is not a whitespace character, append it to currentToken.
c. After iterating through all the characters, check if currentToken is not empty. If it's not empty,
create a new token with the appropriate type and value, and add it to the list of tokens.
d. Return the list of tokens.
5. In the main() function or any other appropriate function, call the findTokens() function,
passing the input line as an argument.
6. Iterate through the list of tokens and display each token's type and value.
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
Q2. Write a c program to find whether given string is identifier or not.
PROGRAM:
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
bool isValidIdentifier(const char* str) {
// Check if the first character is a letter or an underscore
if (!isalpha(str[0]) && str[0] != '_')
return false;
// Check the remaining characters
for (int i = 1; i < strlen(str); i++) {
// Check if the character is alphanumeric or an underscore
if (!isalnum(str[i]) && str[i] != '_')
return false;
}
return true;
}
int main() {
char identifier[100];
printf("Enter a string: ");
scanf("%s", identifier);
if (isValidIdentifier(identifier))
printf("Valid identifier.\n");
else
printf("Not a valid identifier.\n");
return 0;
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
}
OUTPUT:
ALGORITHM:
1. Define the rules for a valid identifier in your programming language. In C, an identifier must
start with a letter (uppercase or lowercase) or an underscore character, followed by any
combination of letters, digits, or underscore characters.
2. Obtain the input string that needs to be checked.
3. Implement a function isIdentifier(input) that takes the input string as a parameter and
performs the following steps:
a. Check if the first character of the input string is a letter (uppercase or lowercase) or an underscore
character.
b. Iterate through each character in the input string, starting from the second character.
c. Check if each character is either a letter (uppercase or lowercase), a digit, or an underscore.
d. If any character does not meet the above criteria, return false to indicate that the input string is not a
valid identifier.
e. If all characters pass the validation, return true to indicate that the input string is a valid identifier.
4. In the main() function or any other appropriate function, prompt the user to enter an input
string.
5. Call the isIdentifier() function, passing the input string as an argument.
6. Based on the returned value, display an appropriate message indicating whether the input
string is a valid identifier or not.
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
Q3. Write a c program to scan and count the number of characters, words in a line
PROGRAM:
#include <stdio.h>
#define MAX_LINE_LENGTH 1000
int countCharacters(const char* line) {
int count = 0;
for (int i = 0; line[i] != '\0'; i++) {
if (line[i] != ' ' && line[i] != '\t' && line[i] != '\n')
count++;
}
return count;
}
int countWords(const char* line) {
int count = 0;
int wordStarted = 0;
for (int i = 0; line[i] != '\0'; i++) {
if (line[i] == ' ' || line[i] == '\t' || line[i] == '\n') {
wordStarted = 0;
} else if (!wordStarted) {
count++;
wordStarted = 1;
}
}
return count;
}
int main() {
char line[MAX_LINE_LENGTH];
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
printf("Enter a line of text: ");
fgets(line, sizeof(line), stdin);
int charCount = countCharacters(line);
int wordCount = countWords(line);
printf("Number of characters: %d\n", charCount);
printf("Number of words: %d\n", wordCount);
return 0;
}
OUTPUT:
ALGORITHM:
1. Define a maximum buffer size to store the input line.
2. Prompt the user to enter a line of text.
3. Read the input line using a function like fgets() and store it in a character array.
4. Initialize variables charCount and wordCount to 0.
5. Iterate through each character in the input line:
a. Increment charCount by 1 for each non-whitespace character encountered.
b. Check if the current character is a whitespace character (space, tab, or newline).
•
If it is, check if the previous character was not a whitespace character to avoid
counting consecutive whitespaces as separate words.
•
If the previous character was not a whitespace character, increment
wordCount by 1.
6. After iterating through all the characters, charCount will hold the total number of characters
in the line, and wordCount will hold the total number of words.
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
7. Display the values of charCount and wordCount to the user.
8. Optionally, you can repeat the process for multiple lines until the user chooses to exit.
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
Q4. Write a c program to find a whether a given string is a keyword or not.
PROGRAM:
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
bool isKeyword(const char* str) {
// List of C keywords
const char* keywords[] = {
"auto", "break", "case", "char", "const", "continue", "default",
"do", "double", "else", "enum", "extern", "float", "for", "goto",
"if", "int", "long", "register", "return", "short", "signed",
"sizeof", "static", "struct", "switch", "typedef", "union",
"unsigned", "void", "volatile", "while"
};
int numKeywords = sizeof(keywords) / sizeof(keywords[0]);
for (int i = 0; i < numKeywords; i++) {
if (strcmp(str, keywords[i]) == 0) {
return true;
}
}
return false;
}
int main() {
char input[100];
printf("Enter a string: ");
scanf("%s", input);
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
if (isKeyword(input)) {
printf("%s is a keyword.\n", input);
} else {
printf("%s is not a keyword.\n", input);
}
return 0;
}
OUTPUT:
ALGORITHM:
1. Define an array or list to store the keywords of the programming language. These keywords
are reserved and have a specific meaning in the language.
2. Obtain the input string that needs to be checked.
3. Implement a function isKeyword(input) that takes the input string as a parameter and
performs the following steps:
a. Iterate through the array or list of keywords.
b. Compare each keyword with the input string. You can use a string comparison function such as
strcmp() to check for equality.
c. If a match is found, return true to indicate that the input string is a keyword.
d. If no match is found after iterating through all the keywords, return false to indicate that the input
string is not a keyword.
4. In the main() function or any other appropriate function, prompt the user to enter an input
string.
5. Call the isKeyword() function, passing the input string as an argument.
6. Based on the returned value, display an appropriate message indicating whether the input
string is a keyword or not.
Note that the specific implementation details, choice of keywords, and syntax will depend on the
programming language for which you want to check the keywords. Also, consider handling edge
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
cases such as case sensitivity and considering the context in which the string appears (e.g., a string
could be a keyword in one context but not in another).
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
Q5. Write a c program to convert NFA to DFA
PROGRAM:
#include <stdio.h>
#define MAX_STATES 100
#define MAX_SYMBOLS 256
typedef struct {
// Define your state structure here
// Add necessary fields based on your requirements
} State;
typedef struct {
int states[MAX_STATES];
int symbols[MAX_SYMBOLS];
int transitions[MAX_STATES][MAX_SYMBOLS];
int initialState;
int finalStates[MAX_STATES];
} NFA;
typedef struct {
int states[MAX_STATES];
int symbols[MAX_SYMBOLS];
int transitions[MAX_STATES][MAX_SYMBOLS];
int initialState;
int finalStates[MAX_STATES];
} DFA;
// Function to convert NFA to DFA
DFA convertNFAToDFA(NFA nfa) {
// Implement your conversion logic here
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
DFA dfa;
// Conversion algorithm
// ...
return dfa;
}
int main() {
NFA nfa;
int numStates;
printf("Enter the number of states in the NFA: ");
scanf("%d", &numStates);
printf("Enter the states:\n");
for (int i = 0; i < numStates; i++) {
scanf("%d", &nfa.states[i]);
}
int numSymbols;
printf("Enter the number of symbols in the NFA: ");
scanf("%d", &numSymbols);
printf("Enter the symbols:\n");
for (int i = 0; i < numSymbols; i++) {
scanf("%d", &nfa.symbols[i]);
}
printf("Enter the transitions (use -1 to denote no transition):\n");
for (int i = 0; i < numStates; i++) {
for (int j = 0; j < numSymbols; j++) {
scanf("%d", &nfa.transitions[i][j]);
}
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
}
printf("Enter the initial state: ");
scanf("%d", &nfa.initialState);
int numFinalStates;
printf("Enter the number of final states: ");
scanf("%d", &numFinalStates);
printf("Enter the final states:\n");
for (int i = 0; i < numFinalStates; i++) {
scanf("%d", &nfa.finalStates[i]);
}
// Convert NFA to DFA
DFA dfa = convertNFAToDFA(nfa);
// Print the DFA states, symbols, transitions, initial state, and final states
printf("DFA States:\n");
// Print DFA states
printf("DFA Symbols:\n");
// Print DFA symbols
printf("DFA Transitions:\n");
// Print DFA transitions
printf("DFA Initial State: %d\n", dfa.initialState);
printf("DFA Final States:\n");
// Print DFA final states
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
return 0;
}
OUTPUT:
ALGORITHM:
1. Define a structure to represent a state in the DFA. Each state should have a unique identifier
and a set of NFA states it represents.
2. Define a structure to represent a transition in the DFA. Each transition should have a source
state, a symbol, and a destination state.
3. Define a structure to represent the DFA itself. It should include a set of states, a set of
transitions, and the initial state.
4. Create a function epsilonClosure() to compute the epsilon closure of a given set of NFA
states. The epsilon closure is the set of states reachable from the input states by following
epsilon transitions.
5. Create a function move() to compute the set of states reachable from a given set of NFA states
on a specific input symbol.
6. Create a function convertNFAtoDFA(nfa, dfa) to convert the NFA to a DFA. It takes the
NFA and an empty DFA as input. Inside this function:
a. Compute the epsilon closure of the initial state of the NFA and add it as the initial state of the DFA.
b. Create an empty set unmarkedStates and add the initial state of the DFA to it.
c. While unmarkedStates is not empty:
•
Remove a state T from unmarkedStates.
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
•
For each input symbol in the NFA's alphabet:
•
Compute the epsilon closure of the move from T on the input symbol.
•
If the resulting set of states is not empty:
•
If the set of states is not in the DFA's set of states, add it as a new
state.
•
Add a transition from T to the new state on the input symbol.
•
If the new state is not marked, add it to unmarkedStates.
d. Return the completed DFA.
7. Optionally, create a function displayDFA(dfa) to display the DFA's states, transitions, and
initial state for verification purposes.
8. In the main() function or any other appropriate function, create an NFA and an empty DFA.
9. Set up the NFA's states, transitions, and initial state.
10. Call the convertNFAtoDFA() function, passing the NFA and the empty DFA as arguments.
11. Optionally, call the displayDFA() function to display the converted DFA.
Note that the specific implementation details, data structures, and syntax will depend on your specific
NFA and DFA representation choices. Additionally, you may need to handle other aspects such as
accepting states in the NFA, merging duplicate states in the DFA, and more.
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
Q6. Write a c program to implement a symbol table
PROGRAM:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TABLE_SIZE 10
typedef struct Symbol {
char name[100];
int value;
struct Symbol* next;
} Symbol;
Symbol* symbolTable[TABLE_SIZE];
// Hash function to compute the index in the symbol table
int hash(char* name) {
int sum = 0;
for (int i = 0; i < strlen(name); i++) {
sum += name[i];
}
return sum % TABLE_SIZE;
}
// Function to insert a symbol into the symbol table
void insertSymbol(char* name, int value) {
int index = hash(name);
// Create a new symbol node
Symbol* newSymbol = (Symbol*)malloc(sizeof(Symbol));
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
strcpy(newSymbol->name, name);
newSymbol->value = value;
newSymbol->next = NULL;
// Insert the symbol at the beginning of the linked list
if (symbolTable[index] == NULL) {
symbolTable[index] = newSymbol;
} else {
newSymbol->next = symbolTable[index];
symbolTable[index] = newSymbol;
}
}
// Function to lookup a symbol in the symbol table
Symbol* lookupSymbol(char* name) {
int index = hash(name);
Symbol* symbol = symbolTable[index];
while (symbol != NULL) {
if (strcmp(symbol->name, name) == 0) {
return symbol;
}
symbol = symbol->next;
}
return NULL; // Symbol not found
}
// Function to display the symbol table
void displaySymbolTable() {
printf("Symbol Table:\n");
for (int i = 0; i < TABLE_SIZE; i++) {
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
if (symbolTable[i] != NULL) {
Symbol* symbol = symbolTable[i];
while (symbol != NULL) {
printf("Name: %s\tValue: %d\n", symbol->name, symbol->value);
symbol = symbol->next;
}
}
}
}
int main() {
// Initialize the symbol table
for (int i = 0; i < TABLE_SIZE; i++) {
symbolTable[i] = NULL;
}
int numSymbols;
printf("Enter the number of symbols to insert: ");
scanf("%d", &numSymbols);
for (int i = 0; i < numSymbols; i++) {
char name[100];
int value;
printf("Enter symbol name: ");
scanf("%s", name);
printf("Enter symbol value: ");
scanf("%d", &value);
insertSymbol(name, value);
}
// Display the symbol table
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
displaySymbolTable();
return 0;
}
OUTPUT:
ALGORITHM:
1. Define a structure to represent a symbol table entry. Each entry can contain information such
as the symbol name, data type, scope, memory address, etc., depending on your requirements.
2. Create a data structure to hold the symbol table. This could be an array, linked list, hash table,
or any other suitable data structure. The choice of data structure depends on the specific needs
of your symbol table implementation.
3. Define functions to perform operations on the symbol table:
a. insertSymbol(symbolEntry): This function inserts a symbol entry into the symbol table. It takes
the symbol entry as a parameter and adds it to the appropriate position in the symbol table data
structure.
b. lookupSymbol(symbolName): This function searches for a symbol in the symbol table based on
its name. It returns a pointer to the symbol entry if found, or NULL if the symbol is not present in the
symbol table.
c. updateSymbol(symbolEntry): This function updates the information of an existing symbol entry
in the symbol table. It takes the updated symbol entry as a parameter and modifies the corresponding
entry in the symbol table.
d. deleteSymbol(symbolName): This function removes a symbol entry from the symbol table based
on its name.
4. In the main() function or any other appropriate function, you can utilize the symbol table
operations as needed. For example:
a. Create a new symbol entry using the required information (name, data type, scope, etc.).
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
b. Call insertSymbol() to add the new symbol entry to the symbol table.
c. Use lookupSymbol() to search for a symbol in the symbol table and retrieve its information if it
exists.
d. Call updateSymbol() to modify the information of an existing symbol entry.
e. Use deleteSymbol() to remove a symbol entry from the symbol table.
5. Optionally, implement additional functions to traverse and display the symbol table, as per
your requirements. This can be useful for debugging or displaying the contents of the symbol
table for analysis purposes.
Remember to handle edge cases appropriately, such as duplicate symbol entries, error handling for
symbol not found, and ensuring memory management for dynamically allocated entries.
The specific implementation details and syntax will vary based on your requirements and the chosen
data structure for the symbol table.
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
Q7. Write a c program to implement recursive descends parsing for the grammar:
E->TE
E'->+TE/e
T->FT
T->*FT/e
F->(E)/id
PROGRAM:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
char input[100];
int position = 0;
int success = 1;
void E();
void E_prime();
void T();
void T_prime();
void F();
void match(char c);
void E() {
T();
E_prime();
}
void E_prime() {
if (input[position] == '+') {
match('+');
T();
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
E_prime();
}
}
void T() {
F();
T_prime();
}
void T_prime() {
if (input[position] == '*') {
match('*');
F();
T_prime();
}
}
void F() {
if (input[position] == '(') {
match('(');
E();
match(')');
} else if (isalpha(input[position])) {
match(input[position]);
} else {
success = 0;
}
}
void match(char c) {
if (input[position] == c) {
position++;
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
} else {
success = 0;
}
}
int main() {
printf("Enter an expression: ");
fgets(input, sizeof(input), stdin);
// Remove trailing newline character
if (input[strlen(input) - 1] == '\n') {
input[strlen(input) - 1] = '\0';
}
E();
if (success && input[position] == '\0') {
printf("Parsing successful.\n");
} else {
printf("Parsing unsuccessful.\n");
}
return 0;
}
OUTPUT:
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
ALGORITHM:
1. Define a set of functions, one for each non-terminal symbol in the grammar.
2. Define a global variable lookahead to store the current token being examined.
3. Implement a function getNextToken() to read the next token from the input.
4. Implement a function match(expectedToken) to compare the current lookahead token with an
expected token. If they match, call getNextToken() to move to the next token. Otherwise,
raise an error.
5. Implement a function for each non-terminal symbol in the grammar, following these steps: a.
Start with the highest-level non-terminal symbol (usually the start symbol). b. Write the
function to handle the production rule for that non-terminal symbol. c. Call the appropriate
functions for the non-terminal symbols on the right-hand side of the production rule. d.
Repeat step c for any additional production rules for the same non-terminal symbol.
6. Implement an error-handling function to handle cases where an invalid token or expression is
encountered.
7. In the main() function, prompt the user to enter an input string.
8. Call getNextToken() to initialize the lookahead variable.
9. Call the function for the start symbol to begin the parsing process.
10. Check if the lookahead token is the end of input. If it is, the input string is valid. Otherwise,
raise an error.
Note that this algorithm assumes a single-token lookahead and doesn't handle more complex parsing
scenarios such as operator precedence or associativity. It's a simplified approach to demonstrate the
basic idea of recursive descent parsing.
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
Q8. Write c program to find First() and Follow() for a given CFG
PROGRAM:
#include<stdio.h>
#include<ctype.h>
#include<string.h>
// Functions to calculate CFG_Follow
void T4Tutorials(char, int, int);
void CFG_Follow(char c);
// Function to calculate First
void Searching_First(char, int, int);
int count, n = 0;
// Stores the final result of the First Sets
char FirstCalculation[10][100];
// Stores the final result of the CFG_Follow Sets
char calc_CFG_Follow[10][100];
int m = 0;
// Stores the production rules
char production[10][10];
char f[10], first[10];
int k;
char ck;
int e;
int main(int argc, char **argv)
{
int jm = 0;
int km = 0;
int i, choice;
char c, ch;
count = 4;
// The Input grammar
strcpy(production[0], "E=XY");
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
strcpy(production[1], "X=ilove");
strcpy(production[3], "Y=t4tutorials");
int kay;
char done[count];
int ptr = -1;
// Initializing the FirstCalculation array
for(k = 0; k < count; k++) {
for(kay = 0; kay < 100; kay++) {
FirstCalculation[k][kay] = '!';
}
}
int point1 = 0, point2, xxx;
for(k = 0; k < count; k++)
{
c = production[k][0];
point2 = 0;
xxx = 0;
// Checking if First of c has already been calculated
for(kay = 0; kay <= ptr; kay++)
if(c == done[kay])
xxx = 1;
if (xxx == 1)
continue;
// Function call
Searching_First(c, 0, 0);
ptr += 1;
// Adding c to the calculated list
done[ptr] = c;
printf("\n First(%c) = { ", c);
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
FirstCalculation[point1][point2++] = c;
// Printing the First Sets of the grammar
for(i = 0 + jm; i < n; i++) {
int lark = 0, chk = 0;
for(lark = 0; lark < point2; lark++) {
if (first[i] == FirstCalculation[point1][lark])
{
chk = 1;
break;
}
}
if(chk == 0)
{
printf("%c, ", first[i]);
FirstCalculation[point1][point2++] = first[i];
}
}
printf("}\n");
jm = n;
point1++;
}
printf("\n");
printf("****************************************\n\n\n");
char donee[count];
ptr = -1;
// Initializing the calc_CFG_Follow array
for(k = 0; k < count; k++) {
for(kay = 0; kay < 100; kay++) {
calc_CFG_Follow[k][kay] = '!';
}
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
}
point1 = 0;
int land = 0;
for(e = 0; e < count; e++)
{
ck = production[e][0];
point2 = 0;
xxx = 0;
// Checking if CFG_Follow of ck
// has alredy been calculated
for(kay = 0; kay <= ptr; kay++)
if(ck == donee[kay])
xxx = 1;
if (xxx == 1)
continue;
land += 1;
// Function call
CFG_Follow(ck);
ptr += 1;
// Adding ck to the calculated list
donee[ptr] = ck;
printf(" CFG_Follow(%c) = { ", ck);
calc_CFG_Follow[point1][point2++] = ck;
// Printing the CFG_Follow Sets of the grammar
for(i = 0 + km; i < m; i++) {
int lark = 0, chk = 0;
for(lark = 0; lark < point2; lark++)
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
{
if (f[i] == calc_CFG_Follow[point1][lark])
{
chk = 1;
break;
}
}
if(chk == 0)
{
printf("%c, ", f[i]);
calc_CFG_Follow[point1][point2++] = f[i];
}
}
printf(" }\n\n");
km = m;
point1++;
}
}
void CFG_Follow(char c)
{
int i, j;
// Adding "$" to the CFG_Follow, set of the start symbol
if(production[0][0] == c) {
f[m++] = '$';
}
for(i = 0; i < 10; i++)
{
for(j = 2;j < 10; j++)
{
if(production[i][j] == c)
{
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
if(production[i][j+1] != '\0')
{
// Calculate the first of the next
// Variable (Non-Terminal ) in the production
T4Tutorials(production[i][j+1], i, (j+2));
}
if(production[i][j+1]=='\0' && c!=production[i][0])
{
// Calculate the CFG_Follow of the Variable (Non-Terminal )
// in the L.H.S. of the production
CFG_Follow(production[i][0]);
}
}
}
}
}
void Searching_First(char c, int q1, int q2)
{
int j;
// The case where we
// encounter a Terminal
if(!(isupper(c))) {
first[n++] = c;
}
for(j = 0; j < count; j++)
{
if(production[j][0] == c)
{
if(production[j][2] == '#')
{
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
if(production[q1][q2] == '\0')
first[n++] = '#';
else if(production[q1][q2] != '\0'
&& (q1 != 0 || q2 != 0))
{
// Recursion to calculate First of New
// Variable (Non-Terminal ) we encounter after epsilon
Searching_First(production[q1][q2], q1, (q2+1));
}
else
first[n++] = '#';
}
else if(!isupper(production[j][2]))
{
first[n++] = production[j][2];
}
else
{
// Recursion to calculate First of
// New Variable (Non-Terminal ) we encounter
// at the beginning
Searching_First(production[j][2], j, 3);
}
}
}
}
void T4Tutorials(char c, int c1, int c2)
{
int k;
// The case where we encounter
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
// a Terminal
if(!(isupper(c)))
f[m++] = c;
else
{
int i = 0, j = 1;
for(i = 0; i < count; i++)
{
if(FirstCalculation[i][0] == c)
break;
}
//Including the First set of the
// Variable (Non-Terminal ) in the CFG_Follow of
// the original query
while(FirstCalculation[i][j] != '!')
{
if(FirstCalculation[i][j] != '#')
{
f[m++] = FirstCalculation[i][j];
}
else
{
if(production[c1][c2] == '\0')
{
// Case where we reach the
// end of a production
CFG_Follow(production[c1][0]);
}
else
{
// Recursion to the next symbol in case we encounter a "#"
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
T4Tutorials(production[c1][c2], c1, c2+1);
}
}
j++;
}
}
}
OUTPUT:
ALGORITHM:
1. Read the number of non-terminals (N) from the user.
2. Read the non-terminals (N) from the user.
3. Read the number of terminals (T) from the user.
4. Read the terminals (T) from the user.
5. Read the number of production rules (P) from the user.
ARITRA GHOSH ( 21BCE2550 )
ARITRA GHOSH ( 21BCE2550 )
6. Read the production rules (P) from the user.
7. Initialize the FIRST and FOLLOW sets for each non-terminal as empty sets.
8. Repeat the following steps until there are no changes in any of the FIRST or FOLLOW sets:
•
For each production rule, check if the first symbol is a terminal. If so, add it to the
FIRST set of the corresponding non-terminal.
•
For each production rule, check if the first symbol is a non-terminal. If so, add the
FIRST set of that non-terminal to the FIRST set of the corresponding non-terminal.
•
For each production rule, check if there is a chain of non-terminals followed by
terminals or epsilon. If so, add the corresponding symbols to the FIRST set of the
non-terminal.
•
For each production rule, check if the non-terminal is at the end or followed by a
terminal. If so, add the terminal to the FOLLOW set of the non-terminal.
•
For each production rule, check if the non-terminal is followed by a non-terminal. If
so, add the FIRST set of the non-terminal to the FOLLOW set of the original nonterminal.
9. Print the FIRST and FOLLOW sets for each non-terminal.
Please note that this is the algorithmic description. To implement it in C, you will need to write the
code for each step using appropriate data structures and functions.
ARITRA GHOSH ( 21BCE2550 )
Download