0% found this document useful (0 votes)
14 views6 pages

Sslab 4

The document outlines an assignment to design an Operator Precedence parser for a user-defined context-free grammar (CFG). It includes functionalities to compute leading and trailing symbols, build a precedence table, and validate input strings using a stack. The provided C++ code implements these functionalities, allowing users to input grammar productions and test the validity of strings against the defined grammar.

Uploaded by

kapilyadav20005
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)
14 views6 pages

Sslab 4

The document outlines an assignment to design an Operator Precedence parser for a user-defined context-free grammar (CFG). It includes functionalities to compute leading and trailing symbols, build a precedence table, and validate input strings using a stack. The provided C++ code implements these functionalities, allowing users to input grammar productions and test the validity of strings against the defined grammar.

Uploaded by

kapilyadav20005
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
You are on page 1/ 6

Assignment - 4

Q)Design Operator Precedence parser for user input CFG with the following
operations:
1. Find out Trailing of NT
2. Find out Leading of NT
3. Build precedence table
4. Validate input string using stack

CODE-:
#include <bits/stdc++.h>

using namespace std;

map<char, vector<string>> grammar;


map<char, set<char>> leading, trailing;
set<char> terminals, non_terminals;
char start_symbol;

bool is_terminal(char ch) {


return !isupper(ch) && ch != 'ε';
}

void compute_leading(char nt) {


for (auto prod : grammar[nt]) {
if (is_terminal(prod[0]))
leading[nt].insert(prod[0]);
else {
if (prod[0] != nt) {
compute_leading(prod[0]);
leading[nt].insert(leading[prod[0]].begin(), leading[prod[0]].end()); }
}
}
}

void compute_trailing(char nt) {


for (auto prod : grammar[nt]) {
int len = prod.length();
if (is_terminal(prod[len - 1]))
trailing[nt].insert(prod[len - 1]);
else {
if (prod[len - 1] != nt) {
compute_trailing(prod[len - 1]);
trailing[nt].insert(trailing[prod[len - 1]].begin(), trailing[prod[len - 1]].end()); }
}
}
}

map<pair<char, char>, char> precedence_table;

void build_table() {
for (auto &g : grammar) {
for (auto &prod : g.second) {
for (size_t i = 0; i < prod.length() - 1; ++i) {
char a = prod[i];
char b = prod[i + 1];

if (is_terminal(a) && is_terminal(b)) {


precedence_table[{a, b}] = '=';
}

if (is_terminal(a) && isupper(b)) {


for (char l : leading[b]) {
precedence_table[{a, l}] = '<';
}
}

if (isupper(a) && is_terminal(b)) {


for (char t : trailing[a]) {
precedence_table[{t, b}] = '>';
}
}
if (i + 2 < prod.length() && is_terminal(prod[i]) && isupper(prod[i + 1]) &&
is_terminal(prod[i + 2])) {
precedence_table[{prod[i], prod[i + 2]}] = '=';
}
}
}
}
}

bool validate_input(const string &input) {


stack<char> st;
st.push('$');
string str = input + "$";
size_t i = 0;

while (!st.empty()) {
char top = st.top();
char current = str[i];

if (top == '$' && current == '$') return true;

char relation = 0;
auto temp_stack = st;
char top_terminal = '$';
while (!temp_stack.empty()) {
if (is_terminal(temp_stack.top()) || temp_stack.top() == '$') {
top_terminal = temp_stack.top();
break;
}
temp_stack.pop();
}

if (precedence_table.find({top_terminal, current}) != precedence_table.end()) {


relation = precedence_table[{top_terminal, current}];
} else {
return false;
}

if (relation == '<' || relation == '=') {


st.push(current);
i++;
} else if (relation == '>') {
while (!st.empty()) {
char s_top = st.top();
st.pop();

char next_terminal = '$';


auto temp_stack2 = st;
while (!temp_stack2.empty()) {
if (is_terminal(temp_stack2.top()) || temp_stack2.top() == '$') {
next_terminal = temp_stack2.top();
break;
}
temp_stack2.pop();
}

if (precedence_table[{next_terminal, s_top}] == '<' ||


precedence_table[{next_terminal, s_top}] == 0)
break;
}
} else {
return false;
}
}

return false;
}

int main() {
int n;
cout << "Enter number of productions: ";
cin >> n;
cin.ignore();

cout << "Enter productions (e.g., E->E+T):\n";


for (int i = 0; i < n; ++i) {
string line;
getline(cin, line);
char lhs = line[0];
start_symbol = start_symbol == 0 ? lhs : start_symbol;
non_terminals.insert(lhs);
string rhs = line.substr(3);
stringstream ss(rhs);
string prod;
while (getline(ss, prod, '|')) {
grammar[lhs].push_back(prod);
for (char ch : prod) {
if (is_terminal(ch) && ch != 'ε')
terminals.insert(ch);
else if (isupper(ch))
non_terminals.insert(ch);
}
}
}

for (char nt : non_terminals) {


compute_leading(nt);
compute_trailing(nt);
}

cout << "\nLEADING:\n";


for (auto &p : leading) {
cout << p.first << " : ";
for (char ch : p.second) cout << ch << " "; cout
<< endl;
}

cout << "\nTRAILING:\n";


for (auto &p : trailing) {
cout << p.first << " : ";
for (char ch : p.second) cout << ch << " "; cout
<< endl;
}

build_table();
cout << "\nOperator Precedence Table:\n";
for (char a : terminals) {
for (char b : terminals) {
auto it = precedence_table.find({a, b});
if (it != precedence_table.end())
cout << a << " " << it->second << " " << b << endl; }
}

string test_input;
cout << "\nEnter input string to validate (no spaces):
"; cin >> test_input;

bool result = validate_input(test_input);


cout << "Result: " << (result ? "Valid" : "Invalid") << endl;

return 0;
}

OUTPUT :

You might also like