compiler Design lab
compiler Design lab
LEX:-
Lex is a program that generates lexical analyzer. It is used with YACC parser generator.
The lexical analyzer is a program that transforms an input stream into a sequence of tokens.
It reads the input stream and produces the source code as output through implementing the lexical analyzer
in the C program.
The function of Lex is as follows:
Firstly lexical analyzer creates a program lex.1 in the Lex language. Then Lex compiler runs the lex.1
program and produces a C program lex.yy.c.
Finally C compiler runs the lex.yy.c program and produces an object program a.out.
a.out is lexical analyzer that transforms an input stream into a sequence of tokens.
Lex file
format
A Lex
program is separated into three sections by %% delimiters. The formal of Lex source is as follows:
{ definitions }
%%
{ rules }
%%
{ user subroutines }
Definitions include declarations of constant, variable and regular definitions.
Rules define the statement of form p1 {action1} p2 {action2}....pn {action}.
Where pi describes the regular expression and action1 describes the actions what action the lexical analyzer
should take when pattern pi matches a lexeme.
User subroutines are auxiliary procedures needed by the actions. The subroutine can be loaded with the
lexical analyzer and compiled separately.
YACC
#include <iostream>
#include <string>
using namespace std;
bool belongsToGrammar(string str, int index) {
if (index == str.length()) {
return true;
}
if (str[index] == '0' && str[str.length() - 1 - index] == '0') {
return belongsToGrammar(str, index + 1);
}
return false;
}
int main() {
string input;
cout << "Enter a binary string: ";
cin >> input;
if (belongsToGrammar(input, 0)) {
cout << "The string belongs to the grammar." << endl;
} else {
cout << "The string does not belong to the grammar." << endl;
}
return 0;
}
Output:-
Program 3
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
vector<string> keywords = {"if", "else", "while", "for", "int", "float", "return", "void"};
string input;
cout << "Enter a string: ";
getline(cin, input);
bool containsKeyword = false;
for (const string& keyword : keywords) {
if (input.find(keyword) != string::npos) {
containsKeyword = true;
break;
}
}
if (containsKeyword) {
cout << "The string contains at least one keyword." << endl;
} else {
cout << "The string does not contain any keywords." << endl;
}
return 0;
}
Output:-
Program 4
#include<iostream>
#include<string>
using namespace std;
int main()
{ string ip,op1,op2,temp;
int sizes[10] = {};
char c;
int n,j,l;
cout<<"Enter the Parent Non-Terminal : ";
cin>>c;
ip.push_back(c);
op1 += ip + "\'->";
ip += "->";
op2+=ip;
cout<<"Enter the number of productions : ";
cin>>n;
for(int i=0;i<n;i++)
{ cout<<"Enter Production "<<i+1<<" : ";
cin>>temp;
sizes[i] = temp.size();
ip+=temp;
if(i!=n-1)
ip += "|";
}
cout<<"Production Rule : "<<ip<<endl;
for(int i=0,k=3;i<n;i++)
{
if(ip[0] == ip[k])
{
cout<<"Production "<<i+1<<" has left recursion."<<endl;
if(ip[k] != '#')
{
for(l=k+1;l<k+sizes[i];l++)
op1.push_back(ip[l]);
k=l+1;
op1.push_back(ip[0]);
op1 += "\'|";
}
}
else
{
cout<<"Production "<<i+1<<" does not have left recursion."<<endl;
if(ip[k] != '#')
{
for(j=k;j<k+sizes[i];j++)
op2.push_back(ip[j]);
k=j+1;
op2.push_back(ip[0]);
op2 += "\'|";
}
else
{
op2.push_back(ip[0]);
op2 += "\'";
}}}
op1 += "#";
cout<<op2<<endl;
cout<<op1<<endl;
return 0;}
Output:-
Program 5
int main() {
string gram, part1, part2, modifiedGram, newGram, tempGram;
int pos = 0;
modifiedGram += 'X';
return 0;
}
Output:-
Program 6
Output:-
Program 7
int main() {
int n;
cout << "Enter the number of productions: ";
cin >> n;
vector<string> productions(n);
vector<string> leading(n);
for (int i = 0; i < n; i++) {
leading[i] = productions[i].substr(0, 1);
for (int j = 1; j < productions[i].size(); j++) {
if (productions[i][j] == '|') {
j++;
if (j < productions[i].size()) {
if (isupper(productions[i][j])) {
leading[i] += productions[i][j];
}
}
}
}
}
return 0;
}
Output:-
Program 8
void check();
int main() {
cout << "\n\t\tSHIFT REDUCE PARSER\n";
cout << "\nGRAMMAR\n";
cout << "E -> E+E\nE -> E/E\nE -> E*E\nE -> a/b\n";
stack = "$";
act = "shift";
len = ip_sym.length();
cout << "\n$" << stack << "\t" << ip_sym << "$\t" << act;
act = "shift";
act += ip_sym[ip_ptr];
check();
st_ptr++;
}
st_ptr++;
check();
return 0;
}
void check() {
string temp2 = stack.substr(st_ptr, 1);
if (temp2 == "a" || temp2 == "b") {
stack[st_ptr] = 'E';
cout << "\n$" << stack << "\t" << ip_sym << "$\tE->" << temp2;
} else if (temp2 == "+" || temp2 == "*" || temp2 == "/") {
// Do nothing for these symbols
} else if (stack.substr(st_ptr) == "E+E" || stack.substr(st_ptr) == "E/E" || stack.substr(st_ptr) == "E*E") {
stack = "E";
st_ptr = 0;
cout << "\n$" << stack << "\t" << ip_sym << "$\tE->" << stack.substr(0, 3);
} else if (stack == "E" && ip_ptr == len) {
cout << "\n$" << stack << "\t" << ip_sym << "$\tACCEPT";
exit(0);
} else {
cout << stack << "\t" << ip_sym << "\treject";
exit(0);
}
}
Output:-
Program 10
bool isOperator(char c) {
return c == '+' || c == '-' || c == '*' || c == '/';
}
return operators.empty();
}
int main() {
std::string expression = "a + b * c - d";
if (isOperatorPrecedent(expression)) {
std::cout << "The grammar is operator precedent." << std::endl;
} else {
std::cout << "The grammar is not operator precedent." << std::endl;
}
return 0;
}
Output:-