CD FILE (1) - Merged
CD FILE (1) - Merged
MISSION
The Institute shall endeavor to incorporate the following basic missions in the
teaching methodology:
1. LEX Program:
%{
#include <stdio.h>
%}
%%
"hello" { printf("Hello, World!\n"); }
"bye" { printf("Goodbye!\n"); }
. { /* Ignore all other characters */ }
%%
int main() {
yylex();
return 0;
}
2. YACC Program:
%{
#include <stdio.h>
%}
%%
statement: "print" STRING { printf("Printing: %s\n", $2); }
| "assign" ID "=" INT { printf("%s = %d\n", $2, $4); }
;
%%
3. Sample Input:
OUTPUT:
Experiment No – 2
Aim: Write a program to check whether a string belong to the grammar or not.
a) S -> aS
S -> Sb
S -> ab
String of the form: aab
b) S -> aSa
S -> bSb
S -> a
S -> b
The Grammar generated is: All Odd Length Palindromes
c) S -> aSbb
S -> abb
The Grammar generated is: anb2n, where n>1
d). S -> aSb
S -> ab
The Grammar generated is: anbn, where n>0
Source Code:
#include <iostream>
#include <string>
// Check if the counts of 'a's and 'b's follow the grammar rules
if (countA >= 2 * countB) {
return true;
}
return false;
}
// Check if the string is not empty and the first and last characters are the same
if (len == 0 || input[0] != input[len - 1]) {
return false;
}
bool isGrammarA(string s) {
int countA = 0;
int countB = 0;
for (char c : s) {
if (c == 'a') {
countA++;
} else if (c == 'b') {
countB++;
} else {
return false; // Invalid string
}
}
bool isGrammarB(string s) {
int countA = 0;
int countB = 0;
for (char c : s) {
if (c == 'a') {
countA++;
} else if (c == 'b') {
countB++;
} else {
return false; // Invalid string
}
}
int main() {
int choice;
cout << "Choose the Grammar to check:\n";
cout << "Grammar 1 (Form of 'aab') \n";
cout << "Grammar 2 (Odd Length Palindromes)\n";
cout << "Grammar 3 (anbn)\n";
cout << "Grammar 4 (a^nb^2n)\n";
cout << "Enter your choice (1/2/3/4): ";
cin >> choice;
string input;
cout << "Enter a string: ";
cin >> input;
switch (choice) {
case 1:
result = Grammar_1(input);
break;
case 2:
result = Grammar_2(input);
break;
case 3:
result = isGrammarA(input);
break;
case 4:
result = isGrammarB(input);
break;
default:
cout << "Invalid choice! Please select 1, 2, 3, or 4." << endl;
return 1;
}
if (result) {
cout << "Accepted! The string belongs to the selected Grammar." << endl;
} else {
cout << "Rejected! The string does not belong to the selected Grammar." << endl;
}
return 0;
}
Output:
Experiment No – 3
Aim: Write a program to check whether a string include keyword or not.
Source Code:
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
return count;
}
int main() {
string inputString;
string wordsToMatch = "alignas alignof and and_eq asm auto bitand bitor bool break case
catch char class compl const constexpr const_cast continue decltype default"; // Words to match
in the paragraph
return 0;
}
Output:
Experiment No – 4
Aim:
Write a program to remove left recursion from a Grammar.
Source Code:
#include <iostream>
#include <vector>
#include <sstream>
int main() {
char nonTerminal;
vector<string> productions;
stringstream ss(productionsInput);
string production;
while (getline(ss, production, '|')) {
productions.push_back(production);
}
return 0;
}
Output:
Experiment No – 5
Source Code:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
int main() {
vector<string> productionRules;
if (rule.empty()) {
break;
}
productionRules.push_back(rule);
}
return 0;
}
Output:
Experiment No – 6
Source Code:
#include <iostream>
#include <vector>
using namespace std;
class Stack
{
private:
vector<int> stack; // Using a vector to implement the stack
public:
void push(int element)
{
stack.push_back(element);
cout << "Pushed: " << element << endl;
}
void pop()
{
if (!stack.empty())
{
int poppedElement = stack.back();
stack.pop_back();
cout << "Popped: " << poppedElement << endl;
}
else
{
cout << "Stack underflow: Cannot pop from an empty stack." << endl;
}
}
void peek()
{
if (!stack.empty())
{
cout << "Top element: " << stack.back() << endl;
}
else
{
cout << "Stack is empty. Cannot peek." << endl;
}
}
bool isEmpty()
{
return stack.empty();
}
};
int main()
{
Stack myStack;
myStack.push(10);
myStack.push(20);
myStack.push(30);
myStack.peek();
myStack.pop();
myStack.pop();
myStack.pop();
return 0;
}
Experiment No – 7
Aim: Write a program to find out the leading of the non‐terminals in a grammar.
Source Code:
#include <iostream>
#include <unordered_map>
#include <set>
#include <sstream>
using namespace std;
istringstream grammarStream(grammar);
string production;
char nonTerminal;
ruleStream >> nonTerminal;
string body;
ruleStream >> body;
return leadingSets;
}
int main()
{
// Example grammar
string grammar =
"S -> AbCd\n"
"A -> a | $\n"
"B -> b | $\n"
"C -> c | $\n"
"D -> d | $\n";
Output:
Experiment No – 8
// Pop symbols from the stack based on the length of the rhs
for (size_t i = 0; i < rhs.size(); ++i)
{
parseStack.pop();
}
// Check if the top of the stack and the next input form a valid pair in the parsing table
if (parsingTable[stackTop].find(nextInput) != parsingTable[stackTop].end())
{
// Valid pair, perform the specified action
string action = parsingTable[stackTop][nextInput];
if (action.substr(0, 5) == "shift")
{
shift(parseStack, input);
}
else if (action.substr(0, 5) == "reduce")
{
reduce(parseStack, action.substr(6));
}
}
else
{
cout << "Error: Invalid pair (" << stackTop << ", " << nextInput << ")" << endl;
break;
}
int main()
{
// Input string for parsing
vector<string> input = {"id", "+", "id", "*", "id", "$"};
// Perform parsing
parse(parseStack, input);
return 0;
}
Output:
Experiment No – 9
Aim:
Write a program to find out the FIRST of the Non‐terminals in a grammar.
Theory:
The concept of "First" in the context of formal language theory and context-free grammars
refers to the set of terminal symbols that can begin a string derived from a given symbol
(terminal or non-terminal). The First set is a crucial component in various parsing algorithms
and is used for constructing predictive parsing tables. Here's the theory on the "First" of non-
terminals in a grammar:
1. Definition of First:
o The First(X) set for a symbol X is defined as the set of terminal symbols that
can appear as the first symbol in some string derivable from X in a single
derivation step.
2. Calculation of First Sets:
o The First sets are calculated based on the production rules of a grammar. The
process involves considering all possible derivations from a non-terminal and
identifying the terminal symbols that can appear as the first symbol.
3. Rules for Calculating First Sets:
o For terminals, First(T) is {T}.
o For non-terminals, First(N) includes the First sets of the alternatives in its
production rules. If an alternative can produce an empty string, the First set of
the next symbol in the production is also included.
4. Application in LL Parsing:
o First sets are fundamental in LL parsing algorithms, particularly in the
construction of parsing tables. In LL parsers, the First set is used to predict
which production to apply based on the next input symbol.
5. Handling ε-Productions:
o If a non-terminal can derive an empty string (ε), the First set of that non-
terminal includes ε as well. This is because ε can be the first symbol in the
derived string.
Source Code:
#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <vector>
unordered_set<char> firstSet;
return firstSet;
}
int main()
{
// Define the grammar with production rules
vector<Production> productions = {
{"S", "aAB"},
{"A", "b"},
{"A", ""},
{"B", "cC"},
{"C", "d"},
{"C", ""}};
return 0;
}
Output:
Experiment No – 10
Aim:
Write a program to check whether a grammar is operator precedent.
Theory:
Operator precedence is a concept in formal language theory and compiler design that defines
the priority of different operators in expressions. It determines the order in which operators
are evaluated when they appear together in an expression. This concept is crucial for parsing
expressions and generating the correct execution order in programming languages. Here is
the theory on operator precedence:
return true;
}
int main()
{
// Define the grammar with production rules
vector<Production> productions = {
{"E", "E+T"},
{"E", "T"},
{"T", "T*F"},
{"T", "F"},
{"F", "(E)"},
{"F", "id"}};
return 0;
}
Output: