22BCT0252
Vedh Bhattad
Code for Calculator:
st.l:
%{
#include <stdio.h>
#include <stdlib.h>
#include "st.tab.h"
extern int yylval;
%}
Num [0-9]+
AO [-+*/%]
PO [()]
%%
{AO} return *yytext;
{PO} return *yytext;
{Num} {yylval=atoi (yytext); return (Num);}
\n return *yytext;
%%
st.y:
%{
#include <stdio.h>
#include "st.tab.h"
int yylex();
void yyerror(char *s);
%}
%token Num
%%
S : E '\n' {printf("%d\n",$1);}
E : E '+' T {$$ = $1 + $3;}
| E '-' T {$$ = $1 - $3;}
| T {$$ = $1;}
T : T '*' F {$$ = $1 * $3;}
| T '/' F {$$ = $1 / $3;}
| T '%' F {$$ = $1 % $3;}
| F {$$ = $1;}
F : '(' E ')' {$$ = $2;}
| Num {$$ = $1;}
%%
int main(){
printf("Enter the expression: ");
yyparse();
return 0;
}
int yywrap(){
return 1;
}
void yyerror(char *s){
fprintf(stderr,"%s\n",s);
}
Output:
Increment Decrement Code:
st.l:
%{
#include <stdio.h>
#include <stdlib.h>
#include "st.tab.h"
extern int yylval;
%}
Num [0-9]+
AO [-+*/%]
PO [()]
%%
{AO} return *yytext;
{PO} return *yytext;
{Num} {yylval=atoi (yytext); return (Num);}
\n return *yytext;
%%
st.y:
%{
#include <stdio.h>
#include "st.tab.h"
int yylex();
void yyerror(char *s);
%}
%token Num
%%
S : E '\n' {printf("%d\n",$1);}
E : T '+' '+' {$$ = $1 + 1;}
| '+' '+' T {$$ = $3+1;}
| '-' '-' T {$$ = $3-1;}
| T '-' '-' {$$ = $1 -1;}
T : F {$$ = $1;}
F : '(' E ')' {$$ = $2;}
| Num {$$ = $1;}
%%
int main(){
printf("Enter the expression: ");
yyparse();
return 0;
}
int yywrap(){
return 1;
}
void yyerror(char *s){
fprintf(stderr,"%s\n",s);
}
Output:
Predictive Parser Code:
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <string>
using namespace std;
map<char, set<char>> firstSet, followSet;
map<char, vector<string>> productions;
map<pair<char, char>, string> parsingTable;
void computeFirst(char nonTerminal) {
if (!firstSet[nonTerminal].empty()) return; // Already computed
for (const string &prod : productions[nonTerminal]) {
for (char symbol : prod) {
if (!isupper(symbol)) { // Terminal
firstSet[nonTerminal].insert(symbol);
break;
} else { // Non-terminal
computeFirst(symbol);
set<char> tempFirst = firstSet[symbol];
bool epsilonFound = tempFirst.erase('#'); // Remove epsilon from first of symbol
firstSet[nonTerminal].insert(tempFirst.begin(), tempFirst.end());
if (!epsilonFound) break;
void computeFollow(char nonTerminal) {
if (!followSet[nonTerminal].empty()) return; // Already computed
for (auto &entry : productions) {
char lhs = entry.first;
for (string &prod : entry.second) {
for (int i = 0; i < prod.size(); i++) {
if (prod[i] == nonTerminal) {
// If A -> αBβ, add FIRST(β) to FOLLOW(B)
bool allNullable = true;
for (int j = i + 1; j < prod.size(); j++) {
if (isupper(prod[j])) {
computeFirst(prod[j]);
set<char> tempFirst = firstSet[prod[j]];
bool epsilonFound = tempFirst.erase('#');
followSet[nonTerminal].insert(tempFirst.begin(), tempFirst.end());
if (!epsilonFound) {
allNullable = false;
break;
} else {
followSet[nonTerminal].insert(prod[j]);
allNullable = false;
break;
if (allNullable || i + 1 == prod.size()) { // A -> αB
computeFollow(lhs);
followSet[nonTerminal].insert(followSet[lhs].begin(), followSet[lhs].end());
void generateParsingTable() {
for (auto &entry : productions) {
char nonTerminal = entry.first;
for (string &prod : entry.second) {
set<char> firstOfProd;
for (char symbol : prod) {
if (!isupper(symbol)) { // Terminal
firstOfProd.insert(symbol);
break;
} else {
firstOfProd = firstSet[symbol];
bool epsilonFound = firstOfProd.erase('#');
if (!epsilonFound) break;
for (char term : firstOfProd) {
parsingTable[{nonTerminal, term}] = prod;
if (firstOfProd.count('#')) {
for (char term : followSet[nonTerminal]) {
parsingTable[{nonTerminal, term}] = prod;
int main() {
int numProductions;
cout << "Enter number of productions: ";
cin >> numProductions;
for (int i = 0; i < numProductions; i++) {
char nonTerminal;
string production;
cout << "Enter production (e.g., A->BC or A->a): ";
cin >> nonTerminal >> production;
production = production.substr(2); // Skip the "->"
productions[nonTerminal].push_back(production);
char startSymbol;
cout << "Enter start symbol: ";
cin >> startSymbol;
// Compute First sets
for (auto &entry : productions) {
computeFirst(entry.first);
// Compute Follow sets
followSet[startSymbol].insert('$'); // Add '$' to the follow of the start symbol
for (auto &entry : productions) {
computeFollow(entry.first);
// Generate Parsing Table
generateParsingTable();
// Output First sets
cout << "\nFirst Sets:\n";
for (auto &entry : firstSet) {
cout << entry.first << ": { ";
for (char symbol : entry.second) {
cout << symbol << " ";
cout << "}\n";
// Output Follow sets
cout << "\nFollow Sets:\n";
for (auto &entry : followSet) {
cout << entry.first << ": { ";
for (char symbol : entry.second) {
cout << symbol << " ";
cout << "}\n";
// Output Parsing Table
cout << "\nParsing Table:\n";
for (auto &entry : parsingTable) {
cout << "M[" << entry.first.first << ", " << entry.first.second << "] = " << entry.second << "\n";
return 0;
Output:
Code for typecheck:
#include <iostream>
#include <string>
#include <unordered_map>
#include <sstream>
#include <vector>
#include <algorithm>
using namespace std;
string getType(const unordered_map<string, string> &varTypes, const string &var)
{
if (varTypes.find(var) != varTypes.end())
{
return varTypes.at(var);
}
else
{
return "NOT DECLARED";
}
}
void parseDeclaration(unordered_map<string, string> &varTypes, const string &line)
{
istringstream iss(line);
string type, var;
iss >> type;
while (iss >> var)
{
if (var.back() == ';')
var.pop_back();
if (var.back() == ',')
var.pop_back();
varTypes[var] = type;
}
}
void checkType(const unordered_map<string, string> &varTypes, const string &lhs, const
vector<string> &rhsVars)
{
string lhsType = getType(varTypes, lhs);
for (const string &rhsVar : rhsVars)
{
string rhsType = getType(varTypes, rhsVar);
if (lhsType == rhsType)
{
cout << "Type of " << lhs << " and " << rhsVar << " -> MATCHED" << endl;
}
else if (lhsType == "NOT DECLARED" || rhsType == "NOT DECLARED")
{
if (lhsType == "NOT DECLARED")
cout << "Type of " << lhs << " -> NOT DECLARED" << endl;
if (rhsType == "NOT DECLARED")
cout << "Type of " << rhsVar << " -> NOT DECLARED" << endl;
}
else
{
cout << "Type of " << lhs << " and " << rhsVar << " -> NOT MATCHED" << endl;
}
}
}
vector<string> extractVariables(const string &rhs)
{
vector<string> vars;
string token;
string cleanedToken;
for (char ch : rhs)
{
if (isspace(ch) || ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == ';')
{
if (!cleanedToken.empty())
{
vars.push_back(cleanedToken);
cleanedToken.clear();
}
}
else
{
cleanedToken += ch;
}
}
if (!cleanedToken.empty())
{
vars.push_back(cleanedToken);
}
return vars;
}
int main()
{
unordered_map<string, string> varTypes;
int n;
cout << "Enter number of lines of code: ";
cin >> n;
cin.ignore();
// Read the lines of code
for (int i = 0; i < n; i++)
{
string line;
getline(cin, line);
if (line.find("int") != string::npos || line.find("float") != string::npos || line.find("char") !=
string::npos)
{
parseDeclaration(varTypes, line);
}
else if (line.find('=') != string::npos)
{
size_t equalPos = line.find('=');
string lhs = line.substr(0, equalPos);
string rhs = line.substr(equalPos + 1);
lhs.erase(remove(lhs.begin(), lhs.end(), ' '), lhs.end());
vector<string> rhsVars = extractVariables(rhs);
checkType(varTypes, lhs, rhsVars);
}
}
return 0;
}
Ouput: