Program – 9
Aim: Program to make verb of any word using lexer table.
Source Code:
%{
#include <stdio.h>
#include <string.h>
void suggestVerb(char *word) {
if (strstr(word, "ing") || strstr(word, "ed") || strstr(word, "ize")) {
printf("\"%s\" is already a verb\n", word);
}
else if (strcmp(word, "beauty") == 0) {
printf("\"%s\" :- \"beautify\"\n", word);
}
else if (strcmp(word, "simple") == 0) {
printf("\"%s\" :- \"simplify\"\n", word);
}
else if (strcmp(word, "active") == 0) {
printf("\"%s\" :- \"activate\"\n", word);
}
else {
printf("\"%s\" :- \"%sing\"\n", word, word); // Default verb suggestion
}
}
%}
%%
[a-zA-Z]+ { suggestVerb(yytext); }
[ \t\n]+ ; // Ignore whitespace
. { printf("Unknown character: %s\n", yytext); }
%%
int main() {
printf("Enter words:\n");
yylex();
return 0;
}
int yywrap() {
return 1;
}
Output:
Program – 10
Aim: C Program to find the “leading terminals” of a grammar.
Source Code:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define MAX_RULES 10
#define MAX_SYMBOLS 10
typedef struct {
char nonTerminal;
char productions[MAX_RULES][MAX_SYMBOLS];
int count;
} Rule;
Rule grammar[MAX_RULES];
int ruleCount = 0;
void findLeadingTerminals(char nonTerminal, int visited[]) {
for (int i = 0; i < ruleCount; i++) {
if (grammar[i].nonTerminal == nonTerminal) {
for (int j = 0; j < grammar[i].count; j++) {
char firstSymbol = grammar[i].productions[j][0];
if (islower(firstSymbol) || firstSymbol == '+' || firstSymbol == '-' || firstSymbol == '*' ||
firstSymbol == '/') {
printf("%c ", firstSymbol); }
else if (isupper(firstSymbol) && !visited[firstSymbol - 'A']) {
visited[firstSymbol - 'A'] = 1;
findLeadingTerminals(firstSymbol, visited); }
}
}
}
}
int main() {
int i, j, n;
printf("Enter number of grammar rules: ");
scanf("%d", &ruleCount);
for (i = 0; i < ruleCount; i++) {
printf("Enter non-terminal: ");
scanf(" %c", &grammar[i].nonTerminal);
printf("Enter number of productions for %c: ", grammar[i].nonTerminal);
scanf("%d", &grammar[i].count);
for (j = 0; j < grammar[i].count; j++) {
printf("Enter production %d for %c: ", j + 1, grammar[i].nonTerminal);
scanf("%s", grammar[i].productions[j]); }
}
printf("\nLeading Terminals:\n");
for (i = 0; i < ruleCount; i++) {
int visited[26] = {0};
printf("Leading(%c): ", grammar[i].nonTerminal);
findLeadingTerminals(grammar[i].nonTerminal, visited);
printf("\n"); }
return 0;
}
Output:
Program – 11
Aim: C Program to find the “trailing terminals” of a grammar.
Source Code:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define MAX_RULES 10
#define MAX_SYMBOLS 10
typedef struct {
char nonTerminal;
char productions[MAX_RULES][MAX_SYMBOLS];
int count;
} Rule;
Rule grammar[MAX_RULES];
int ruleCount = 0;
void findTrailingTerminals(char nonTerminal, int visited[]) {
for (int i = 0; i < ruleCount; i++) {
if (grammar[i].nonTerminal == nonTerminal) {
for (int j = 0; j < grammar[i].count; j++) {
int len = strlen(grammar[i].productions[j]);
char lastSymbol = grammar[i].productions[j][len - 1];
if (islower(lastSymbol) || lastSymbol == '+' || lastSymbol == '-' || lastSymbol == '*' ||
lastSymbol == '/') {
printf("%c ", lastSymbol); }
else if (isupper(lastSymbol) && !visited[lastSymbol - 'A']) {
visited[lastSymbol - 'A'] = 1;
findTrailingTerminals(lastSymbol, visited); }
}
}
}
}
int main() {
int i, j;
printf("Enter number of grammar rules: ");
scanf("%d", &ruleCount);
for (i = 0; i < ruleCount; i++) {
printf("Enter non-terminal: ");
scanf(" %c", &grammar[i].nonTerminal);
printf("Enter number of productions for %c: ", grammar[i].nonTerminal);
scanf("%d", &grammar[i].count);
for (j = 0; j < grammar[i].count; j++) {
printf("Enter production %d for %c: ", j + 1, grammar[i].nonTerminal);
scanf("%s", grammar[i].productions[j]); }
}
printf("\nTrailing Terminals:\n");
for (i = 0; i < ruleCount; i++) {
int visited[26] = {0};
printf("Trailing(%c): ", grammar[i].nonTerminal);
findTrailingTerminals(grammar[i].nonTerminal, visited);
printf("\n"); }
return 0;
}
Output:
Program – 12
Aim: C program to find FIRST of non-terminals of a grammar.
Source Code:
#include <stdio.h>
#include <ctype.h>
void FIRST(char);
int count, n = 0;
char prodn[10][10], first[10];
int main() {
int i, choice;
char c, ch;
printf("How many productions? : ");
scanf("%d", &count);
printf("Enter %d productions (use '$' for epsilon):\n", count);
for (i = 0; i < count; i++) {
scanf("%s%c", prodn[i], &ch);
}
do{
n = 0;
printf("\nEnter element to find FIRST: ");
scanf("%c", &c);
FIRST(c);
printf("FIRST(%c) = { ", c);
for (i = 0; i < n; i++) {
printf("%c ", first[i]);
}
printf("}\n");
printf("Press 1 to continue: ");
scanf("%d%c", &choice, &ch);
} while (choice == 1);
return 0;
}
void FIRST(char c) {
int j;
if (!isupper(c)) {
first[n++] = c;
return;
}
for (j = 0; j < count; j++) {
if (prodn[j][0] == c) {
if (prodn[j][2] == '$'){
first[n++] = '$'; }
else if (islower(prodn[j][2])) {
first[n++] = prodn[j][2]; }
else {
FIRST(prodn[j][2]); }
}
}
}
Output:
Program – 13
Aim: C program to find FOLLOW of non-terminals of a grammar.
Source Code:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void follow(char c);
void first(char c);
int n, m = 0, i = 0, j = 0;
char a[10][10], f[10];
int main() {
int z;
char c, ch;
printf("Enter the no. of productions: ");
scanf("%d", &n);
printf("Enter the productions (use '$' for epsilon):\n");
for (i = 0; i < n; i++) {
scanf("%s%c", a[i], &ch);
}
do {
m = 0;
printf("\nEnter the element whose FOLLOW is to be found: ");
scanf("%c", &c);
follow(c);
printf("FOLLOW(%c) = { ", c);
for (i = 0; i < m; i++) {
printf("%c ", f[i]);
}
printf("}\n");
printf("Press 1 to continue: ");
scanf("%d%c", &z, &ch);
} while (z == 1);
return 0;
}
void follow(char c) {
if (a[0][0] == c) {
f[m++] = '$';
}
for (i = 0; i < n; i++) {
for (j = 2; j < strlen(a[i]); j++) {
if (a[i][j] == c) {
if (a[i][j + 1] != '\0') {
first(a[i][j + 1]);
}
if (a[i][j + 1] == '\0' && c != a[i][0]) {
follow(a[i][0]);
}
}
}
}
}
void first(char c) {
int k;
if (!isupper(c)) {
f[m++] = c;
return;
}
for (k = 0; k < n; k++) {
if (a[k][0] == c) {
if (a[k][2] == '$') {
follow(a[k][0]);
}
else if (islower(a[k][2])){
f[m++] = a[k][2];
}
else {
first(a[k][2]);
}
}
}
}
Output:
Program – 14
Aim: Program to generate a parse tree.
Source Code:
#include <iostream>
#include <string>
#include <stack>
using namespace std;
struct Node{
string value;
Node *left;
Node *right;
Node(string val) : value(val), left(nullptr), right(nullptr) {}
};
Node *buildParseTree(const string &postfix){
stack<Node *> stk;
for (char ch : postfix){
string val(1, ch);
if (isalnum(ch)){
stk.push(new Node(val));
} else {
Node *node = new Node(val);
node->right = stk.top();
stk.pop();
node->left = stk.top();
stk.pop();
stk.push(node);
}
}
return stk.top();
}
void printParseTree(Node *root, int level = 0){
if (root) {
printParseTree(root->right, level + 1);
cout << string(level * 4, ' ') << root->value << endl;
printParseTree(root->left, level + 1);
}
}
int main(){
string postfix;
cout << "Enter a postfix expression: ";
cin >> postfix;
Node *root = buildParseTree(postfix);
cout << "Parse Tree:\n";
printParseTree(root);
return 0;
}
Output:
Program – 15
Aim: Write a program to check whether a string belong to the grammar or not.
Source Code:
#include <iostream>
using namespace std;
string input;
bool isValid(int start, int end) {
if (start > end) return true;
if (input[start] == 'a' && input[end] == 'b') {
return isValid(start + 1, end - 1);
}
return false;
}
int main() {
cout << "Enter a string for grammar aSb|#: ";
cin >> input;
if (isValid(0, input.length() - 1)) {
cout << "The string belongs to the grammar.\n";
} else {
cout << "The string does NOT belong to the grammar.\n";
}
return 0;
}
Output:
Program – 16
Aim: Write a program to check whether a grammar is left recursion and remove left recursion.
Source Code:
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
bool hasLeftRecursion(string nonTerminal, vector<string> productions) {
for (string prod: productions) {
if (prod[0] == nonTerminal[0]) {
return true;
}
}
return false;
}
void removeLeftRecursion(string nonTerminal, vector<string> productions) {
vector<string> alpha, beta;
for (string prod: productions) {
if (prod[0] == nonTerminal[0]) {
alpha.push_back(prod.substr(1));
} else {
beta.push_back(prod);
}
}
if (alpha.empty()) {
cout << nonTerminal << " - ";
for (size_t i = 0; i < productions.size(); i++) {
cout << productions[i] << (i == productions.size() - 1 ? "" : " | ");
}
cout << endl;
return;
}
string newNonTerminal = nonTerminal + "'";
cout << nonTerminal << " - ";
for (size_t i = 0; i < beta.size(); i++) {
cout << beta[i] << newNonTerminal << (i == beta.size() - 1 ? "" : " | ");
}
cout << endl;
cout << newNonTerminal << " - ";
for (size_t i = 0; i < alpha.size(); i++) {
cout << alpha[i] << newNonTerminal << " | ";
}
cout << "#" << endl;
}
int main() {
int n;
cout << "Enter the number of non-terminals: ";
cin >> n;
cin.ignore();
for (int i = 0; i < n; i++) {
string nonTerminal, productionLine;
cout << "Enter non-terminal: ";
cin >> nonTerminal;
cin.ignore();
cout << "Enter productions (separated by '|'): ";
getline(cin, productionLine);
vector<string> productions;
stringstream ss(productionLine);
string prod;
while (getline(ss, prod, '|')) {
productions.push_back(prod);
}
if (hasLeftRecursion(nonTerminal, productions)) {
cout << "Left recursion detected! Removing it...\n";
removeLeftRecursion(nonTerminal, productions);
} else {
cout << "No left recursion found.\n";
}
cout << endl;
}
return 0;
}
Output: