Compiler Design Final Record
Compiler Design Final Record
EX. NO. 1
AIM: To write a program to implement a lexical analyzer in C++.
ALGORITHM:
1. Start.
2. Get the input program from the file prog.txt.
3. Read the program line by line and check if each word in a line is a keyword, identifier,
constant or an operator.
4. If the word read is an identifier, assign a number to the identifier and make an entry into
the symbol table stored in sybol.txt.
5. For each lexeme read, generate a token as follows:
a. If the lexeme is an identifier, then the token generated is of the form <id, number>
b. If the lexeme is an operator, then the token generated is <op, operator>.
c. If the lexeme is a constant, then the token generated is <const, value>.
d. If the lexeme is a keyword, then the token is the keyword itself.
6. The stream of tokens generated are displayed in the console output.
7. Stop.
PROGRAM:
#include <bits/stdc++.h>
using namespace std;
vector<string> split(string s)
{
vector<string> v;
int i;
for(i = 0; i < s.length() && s[i] != ';'; i++)
{
string word = "";
if(s[i] == ' ')
continue;
while(true)
{
if(isalnum(s[i])||s[i] == '_')
word += s[i];
else if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='=')
{
string op = "";
op += s[i];
if(s[i-1] != ' ')
v.push_back(word);
v.push_back(op);
break;
}
else if(s[i] == '(')
{
string p = "";
if(s[i-1] != ' ')
v.push_back(word);
p += s[i];
while(s[i++] != ')')
p += s[i];
p += s[i];
v.push_back(p);
break;
}
i++;
if(s[i] == ',' || s[i] == ' ' || s[i] == ';')
{
v.push_back(word);
break;
}
}
}
return v;
}
bool is_keyword(string s)
{
set<string, greater<string> > keywords;
keywords.insert("void"); keywords.insert("int");
keywords.insert("return"); keywords.insert("using");
keywords.insert("namespace");
if(keywords.find(s) != keywords.end()) return true;
else return false;
}
bool is_operator(string s)
{
set<string, greater<string> > oper;
oper.insert("+"); oper.insert("-");
oper.insert("*"); oper.insert("/");
oper.insert("="); oper.insert("%%");
oper.insert("()"); oper.insert(";");
if(oper.find(s) != oper.end()) return true;
else return false;
}
bool is_valid_id(string s)
{
int i;
if(!(isalpha(s[0])||s[0] == '_')) return false;
for(i = 0; i < s.length(); i++)
if(!(isalnum(s[i])||s[i] == '_'))
return false;
return true;
}
bool is_num_const(string s)
{
int i;
for(i = 0; i != s.length(); i++)
if(!isdigit(s[i]))
return false;
return true;
}
int main()
{
ifstream fin("prog.txt");
string line;
vector<string> program;
vector<string>::iterator ptr;
set<string,greater<string> > keywords, oper;
set<string,greater<string> >::iterator itr;
vector<string> cons;
int id_no = 1;
map <string,int> id;
map <string,int>::iterator idtr;
if(fin.is_open())
{
while(getline(fin, line))
program.push_back(line);
fin.close();
}
for(ptr=program.begin(); ptr!=program.end(); ptr++)
{
line = *ptr;
if(line[0]=='#'||line.compare("{")==0||line.compare("}") == 0)
continue;
vector<string> words = split(line);
for(vector<string>::iterator it=words.begin();it!=words.end();
it++)
{
string word = *it;
if(word.compare("}")==0||word.compare("{")==0)
break;
if(is_keyword(word))
{
keywords.insert(word);
cout<<"<"<<word<<">";
}
else if(is_valid_id(word))
{
idtr = id.find(word);
if(idtr == id.end())
{
id.insert(make_pair(word,id_no));
cout<<"<id,"<<id_no<<">";
id_no++;
}
else
cout<<"<id,"<<idtr->second<<">";
}
else if(is_operator(word))
{
oper.insert(word);
if(word.compare(";") != 0)
cout<<"<op,"<<word<<">";
}
else if(is_num_const(word))
{
cons.push_back(word);
cout<<"<const,"<<word<<">";
}
}
cout<<"\n";
}
ofstream fout("symbol.txt");
fout<<"\nKeywords:\n";
for(itr = keywords.begin(); itr != keywords.end(); itr++)
fout<<*itr<<"\n";
fout<<"\nOperators:\n";
for(itr = oper.begin(); itr != oper.end(); itr++)
fout<<*itr<<"\n";
fout<<"\nIdentifiers:\n";
for(idtr = id.begin(); idtr != id.end(); idtr++)
fout<< idtr->first <<"\t <id,"<< idtr->second <<">\n";
fout.close();
return 0;
}
OUTPUT:
Contents of prog.txt:
#include <iostream>
using namespace std;
int main()
{
int a, b = 15, c;
a = 10;
c = a + b;
return;
}
Contents of symbol.txt:
Keywords: using, return, namespace, int
Operators: = +
Identifiers:
a <id,3>
b <id,4>
c <id,5>
main <id,2>
std <id,1>
Console output:
<using> <namespace> <id,1>
<int> <id,2>
<int> <id,3> <id,4> <op,=> <const,15> <id,5>
<id,3> <op,=> <const,10>
<id,5> <op,=> <id,3> <op,+> <id,4>
<return>
RESULT: The implementation of lexical analyser in C++ was compiled, executed and
verified successfully.
CONVERSION FROM REGULAR EXPRESSION TO ε-NFA
EX. NO. 2
AIM: To write a program for converting Regular Expression to ε-NFA using C++ Language.
ALGORITHM:
1. Start
2. Get the input from the user
3. Initialize separate variables and functions for Postfix , Display and NFA
4. Create separate methods for different operators like +,*, .
5. By using Switch case Initialize different cases for the input
6. For ' . ' operator Initialize a separate method by using various stack functions do the
same for the other operators like ' * ' and ' + '.
7. Regular expression is in the form like a.b (or) a+b
8. Display the output
9. Stop
PROGRAM:
#include<bits/stdc++.h>
using namespace std;
char reg[20];
void postfix();
void e_nfa();
void disp(int,char,int);
int main()
{
cout<<”Enter RE: ”;
cin>>reg;
postfix();
cout<<”Postfix : “<<reg<<endl;
e_nfa();
return 0;
}
void postfix()
{
char string[10],stack[10];
int string_n=0,stack_n=0;
int n=0;
strcat(reg,"X");
while(reg[n]!='\0')
{
switch(reg[n])
{
case 'a': string [string_n]='a';
string_n++;
string[string_n]='\0';
break;
case 'b': string[string_n]='b';
string_n++;
string[string_n]='\0';
break;
case '*' : string[string_n]='*';
string_n++;
string[string_n]='\0';
break;
case '(' : stack[stack_n]='(';
stack_n++;
break;
case ')' : stack_n--;
while(stack[stack_n]!='(')
{
string[string_n]=stack[stack_n];
stack[stack_n]='\0';
string_n++;
string[string_n]='\0';
stack_n--;
}
stack[stack_n]='\0';
break;
case 'X' : while(stack_n!=0)
{
stack_n--;
string[string_n]=stack[stack_n];
stack[stack_n]='\0';
string_n++;
string[string_n]='\0';
}
break;
case '+':
if(stack[stack_n-1]!='+' && stack[stack_n-1]!='.')
{
stack[stack_n]='+';
stack_n++;
stack[stack_n]='\0';
break;
}
else
{
string[string_n]=stack[stack_n-1];
string_n++;
stack[stack_n-1]='+';
break;
}
case '.' :
if(stack[stack_n-1]!='+'&&stack[stack_n-1]!='.')
{
stack[stack_n]='.';
stack_n++;
stack[stack_n]='\0';
break;
}
else
{
string[string_n]=stack[stack_n-1];
string_n++;
stack[stack_n-1]='.';
break;
}
default:break;
}
n++;
}
strcpy(reg,string);
}
void e_nfa()
{
int strt[3],last[3],s,l;
int n=0,x=0,i=-1;
cout<<”\nTransitions:\n”;
while(reg[n]!='\0')
{
switch(reg[n])
{
case 'a':i++;
strt[i]=x++;
last[i]=x++;
disp(strt[i],'a',last[i]);
break;
case 'b':i++;
strt[i]=x++;
last[i]=x++;
disp(strt[i],'b',last[i]);
break;
case '+' : s=x++;
l=x++;
disp(s,'e',strt[i]);
disp(s,'e',strt[i-1]);
disp(last[i],'e',l);
disp(last[i-1],'e',l);
i--;
strt[i]=s;
last[i]=l;
break;
case '.' : disp(last[i-1],'e',strt[i]);
last[i-1]=last[i];
i--;
break;
case '*' : s=x++;
l=x++;
disp(s,'e',strt[i]);
disp(s,'e',l);
disp(last[i],'e',strt[i]);
disp(last[i],'e',l);
strt[i]=s;
last[i]=l;
break;
default:break;
}
n++;
}
cout<<i<<" "<<strt[i]<<" "<<last[i];
}
RESULT: The given NFA was converted to a DFA using C++ successfully.
FIRST AND FOLLOW
EX. NO. 4
AIM: To write a program to perform first and follow using C language.
ALGORITHM:
For computing the first:
1. If X is a terminal then FIRST(X) = {X}
Example: F -> I | id
We can write it as FIRST(F) -> { ( , id )
2. If X is a non-terminal like E -> T then to get FIRSTI substitute T with other productions
until you get a terminal as the first symbol
3. If X -> ε then add ε to FIRST(X).
For computing the follow:
1. Always check the right side of the productions for a non-terminal, whose FOLLOW set is
being found. (never see the left side).
2. (a) If that non-terminal (S,A,B…) is followed by any terminal (a,b…,*,+,(,)…) , then add
that terminal into FOLLOW set.
(b) If that non-terminal is followed by any other non-terminal then add FIRST of other
nonterminal into FOLLOW set.
PROGRAM:
#include<bits/stdc++.h>
#define max 20
using namespace std;
char prod[max][10], ter[10], nt[10], first[10][10],follow[10][10];
int eps[10], count=0;
int findpos(char ch)
{
int n;
for(n=0;nt[n]!=’\0’;n++)
if(nt[n]==ch) break;
if(nt[n]==’\0’) return 1;
return n;
}
int IsCap(char c)
{
return (c >= ‘A’ && c <= ‘Z’)? 1 : 0;
}
void add(char *arr,char c)
{
15nti ,flag=0;
for(i = 0; arr[i]!=’\0’; i++)
if(arr[i] == c)
{
flag=1; break;
}
if(flag!=1)
arr[strlen(arr)] = c;
}
void addarr(char *s1,char *s2)
{
16nti ,j,flag=99;
for(i=0;s2[i]!=’\0’;i++)
{
flag=0;
for(j=0;;j++)
{
if(s2[i]==s1[j])
{
flag=1; break;
}
if(j==strlen(s1) && flag!=1)
{
s1[strlen(s1)] = s2[i]; break;
}
}
}
}
void addprod(char *s)
{
16nti ;
prod[count][0] = s[0];
for(i=3;s[i]!=’\0’;i++)
{
if(!IsCap(s[i]))
add(ter,s[i]);
prod[count][i-2] = s[i];
}
prod[count][i-2] = ‘\0’;
add(nt,s[0]);
count++;
}
void findfirst()
{
16nti ,j,n,k,e,n1;
for(i=0;i<count;i++)
{
for(j=0;j<count;j++)
{
n = findpos(prod[j][0]);
if(prod[j][1] == (char)238) eps[n] = 1;
else
{
for(k=1,e=1;prod[j][k]!=’\0’ && e==1;k++)
{
if(!IsCap(prod[j][k]))
{
e=0;
add(first[n],prod[j][k]);
}
else
{
n1 = findpos(prod[j][k]);
addarr(first[n],first[n1]);
if(eps[n1] == 0) e=0;
}
}
if(e==1) eps[n]=1;
}
}
}
}
void findfollow()
{
17nti ,j,k,n,e,n1;
n = findpos(prod[0][0]);
add(follow[n],’#’);
for(i=0;i<count;i++)
{
for(j=0;j<count;j++)
{
for(k = strlen(prod[j])-1; k>0; k--)
{
if(IsCap(prod[j][k]))
{
n=findpos(prod[j][k]);
if(prod[j][k+1] == ‘\0’) // A -> aB
{
n1 = findpos(prod[j][0]);
addarr(follow[n],follow[n1]);
}
if(IsCap(prod[j][k+1])) // A -> aBb
{
n1 = findpos(prod[j][k+1]);
addarr(follow[n],first[n1]);
if(eps[n1]==1)
{
n1=findpos(prod[j][0]);
addarr(follow[n],follow[n1]);
}
}
else if(prod[j][k+1] != ‘\0’)
add(follow[n],prod[j][k+1]);
}
}
}
}
}
int main()
{
char s[max],i;
cout<<”\nEnter the productions (type ‘end’ at the last of the
production)\n”;
cin>>s;
while(strcmp(“end”,s))
{
addprod(s);
cin>>s;
}
findfirst();
findfollow();
for(i=0; i<strlen(nt); i++)
{
cout<<”\nFIRST[“<<nt[i]<<”]: “<<first[i];
if(eps[i]==1)
cout<<(char)238<<”\t”;
else
cout<<”\t”;
cout<<”FOLLOW[“<<nt[i]<<”]: “<<follow[i];
}
return 0;
}
OUTPUT:
FIRST[E]: ( i FOLLOW[E]: $ )
FIRST[D]: + ε FOLLOW[D]: $ )
FIRST[T]: ( i FOLLOW[T]: + $ )
FIRST[G]: * ε FOLLOW[G]: + $ )
FIRST[F]: ( i FOLLOW[F]: * + $ )
RESULT: The FIRST and FOLLOW sets of the non-terminals of a grammar were found
successfully using C++.
ELIMINATION OF LEFT RECURSION
EX. NO. 5
AIM: To implement a C++ program to eliminate left recursion from a context free grammar.
ALGORITHM:
1. Start the program.
2. Initialize the arrays for taking input from the user.
3. Prompt the user to input the no. of non-terminals having left recursion and no. of
productions for these non-terminals.
4. Prompt the user to input the right production for non-terminals.
5. Eliminate left recursion using the following rules:-
A->Aα1| Aα2 | . . . . . |Aαm
A->β1| β2| . . . . .| βn
Then replace it by
A’-> βi A’ i=1,2,3,…..m
A’-> αj A’ j=1,2,3,…..n
A’-> Ɛ
6. After eliminating the left recursion by applying these rules, display the productions
without left recursion.
7. Stop.
PROGRAM:
#include<bits/stdc++.h>
using namespace std;
int main()
{
char input[100],*l,*r,*temp,tempprod[20],productions[25][50];
19nti =0,j=0,flag=0;
cout<<”Enter the productions: “;
cin>>input;
l = strtok(input,”->”);
r = strtok(NULL,”->”);
temp = strtok(r,”|”);
while(temp)
{
if(temp[0] == l[0])
{
flag = 1;
19nti 19(productions[i++],”%s’->%s%s’\0”,l,temp+1,l);
}
else
19nti 19(productions[i++],”%s->%s%s’\0”,l,temp,l);
temp = strtok(NULL,”|”);
}
19nti 19(productions[i++],”%s’->\u238\0”,l);
if(flag == 0)
cout<<”The given productions don’t have Left Recursion”;
else
for(j=0;j<i;j++)
cout<<”\n”<<productions[j];
return 0;
}
OUTPUT:
Enter the productions: A->A+b|A*c|(d)|a
A->(d)A’|aA’
A’->+bA’|*cA’|ε
RESULT: Left Recursion was eliminated from the given grammar successfully using C++.
LEFT FACTORING
EX. NO. 6
AIM: To Write a C Program to eliminate Left Factoring in the given grammar.
ALGORITHM:
1. Start
2. Get productions from the user
3. Check for common left factors in the production
4. Group all like productions
5. Simplify original production
6. Create the new production
7. Display all productions
8. Stop
PROGRAM:
#include<bits/stdc++.h>
using namespace std;
int main()
{
char a[10],a1[10],a2[10],a3[10],a4[10],a5[10];
21nti ,j=0,k,l;
cout<<”Enter any productions A->”);
cin>>a;
for(i=0;a[i]!=’|’;i++,j++)
a1[j]=a[i];
a1[j]=’\0’;
for(j=++i,i=0;a[j]!=’\0’;j++,i++)
a2[i]=a[j];
a2[i]=’\0’;
k=0;l=0;
for(i=0;i<strlen(a1)||i<strlen(a2);i++)
{
if(a1[i]==a2[i])
a3[k++]=a1[i];
else
{
a4[l]=a1[i];
a5[l]=a2[i];
l++;
}
}
a3[k]=’X’; a3[++k]=’\0’;
a4[l]=’|’; a5[l]=’\0’;
a4[++l]=’\0’;
strcat(a4,a5);
cout<<”\n A->”<<a3;
cout<<”\n X->”<<a4;
return 0;
}
OUTPUT:
Enter any productions A->bcd|bcf
A->bcX
X->d|f
RESULT: Left factoring was performed on the given grammar successfully using C++.
PREDICTIVE PARSER
EX. NO. 7
AIM: To construct a predictive parser in C++.
ALGORITHM:
1. Start the program.
2. Initialize the required variables.
3. Get the number of coordinates and productions from the user.
4. Perform the following
for (each production A → α in G) {
for (each terminal a in FIRST(α))
add A → α to M[A, a];
if (ε is in FIRST(α))
for (each symbol b in FOLLOW(A))
add A → α to M[A, b];
5. Print the resulting stack.
6. Print if the grammar is accepted or not.
7. Exit the program.
PROGRAM:
#include<bits/stdc++.h>
using namespace std;
int main()
{
char fin[10][20], st[10][20], ft[20][20], fol[20][20];
int a, i, t, b, n, j, s = 0, p;
cout<<"Enter the number of productions: ";
cin>>n;
cout<<"Enter the productions of the grammar:\n");
for(i = 0; i < n; i++)
cin>>st[i];
cout<<"\nEnter the FIRST and FOLLOW of each non-terminal:");
for(i = 0; i < n; i++)
{
cout<<"\nFIRST["<<st[i][0]<<"] : ";
cin>>ft[i];
cout<<"FOLLOW["<<st[i][0]<<"] : ";
cin>>fol[i];
}
cout<<"\nThe contents of the predictive parser table are:\n"
for(i = 0; i < n; i++)
{
j = 3;
while(st[i][j] != '\0')
{
if(st[i][j-1] == '|'|| j == 3)
{
for(p = 0; p <= 2; p++)
fin[s][p] = st[i][p];
t = j;
for(p=3; st[i][j]!='|' && st[i][j]!='\0'; p++, j++)
fin[s][p] = st[i][j];
fin[s][p] = '\0';
if(st[i][t] == 'e')
{
a = b = 0;
while(st[a++][0] != st[i][0]);
while(fol[a][b] != '\0')
{
cout<<"M["<<st[i][0]<<","<<fol[a][b]
<<"] = "<<fin[s]<<"\n";
b++;
}
}
else if(!(st[i][t] > 64 && st[i][t] < 91))
cout<<"M["<<st[i][0]<<","<<st[i][t]
<<"] = "<<fin[s]<<"\n";
else
{
a = b = 0;
while(st[a++][0] != st[i][3]);
while(ft[a][b] != '\0')
{
cout<<"M["<<st[i][0]<<","<<ft[a][b]
<<"] = "<<fin[s]<<"\n";
b++;
}
}
s++;
}
if(st[i][j] == '|')
j++;
}
}
return 0;
}
OUTPUT:
Enter the number of productions: 5
Enter the productions of the grammar:
E->TD
D->+TD|e
T->FG
G->*FG|e
F->(E)|i
FIRST[E]=(i
FOLLOW[E]=$)
FIRST[D]=+e
FOLLOW[D]=$)
FIRST[T]=(i
FOLLOW[T]=+$)
FIRST[G]=*e
FOLLOW[G]=+$)
FIRST[F]=(i
FOLLOW[F]=*+$)
M[E,(] = E->TD
M[E,i] = E->TD
M[D,+] = D->+TD
M[D,$] = D->e
M[D,)] = D->e
M[T,(] = T->FG
M[T,i] = T->FG
M[G,*] = G->*FG
M[G,+] = G->e
M[G,$] = G->e
M[G,)] = G->e
M[F,(] = F->(E)
M[F,i] = F->i
RESULT: The C++ program to implement the predictive parser was compiled, executed and
verified successfully.
LEADING AND TRAILING
EX. NO. 8
AIM: To implement a C++ program to find the LEADING and TRAILING sets of variables
of a given CFG.
ALGORITHM:
1. For Leading, check for the first non-terminal.
2. If found, print it.
3. Look for next production for the same non-terminal.
4. If not found, recursively call the procedure for the single non-terminal present before the
comma or End Of Production String.
5. Include it's results in the result of this non-terminal.
6. For trailing, we compute same as leading but we start from the end of the production to
the beginning.
7. Stop
PROGRAM:
#include<bits/stdc++.h>
using namespace std;
int nt,t,top=0;
char s[50],NT[10],T[10],st[50],l[10][10],tr[50][50];
int searchnt(char a)
{
int count=-1,i;
for(i=0;i<nt;i++)
{
if(NT[i]==a)
return i;
}
return count;
}
int searchter(char a)
{
int count=-1,i;
for(i=0;i<t;i++)
{
if(T[i]==a)
return i;
}
return count;
}
void push(char a)
{
s[top]=a;
top++;
}
char pop()
{
top--;
return s[top];
}
void installl(int a,int b)
{
if(l[a][b]=='f')
{
l[a][b]='t';
push(T[b]);
push(NT[a]);
}
}
void installt(int a,int b)
{
if(tr[a][b]=='f')
{
tr[a][b]='t';
push(T[b]);
push(NT[a]);
}
}
int main()
{
int i,s,k,j,n;
char pr[30][30],b,c;
cout<<"Enter the number of productions:";
cin>>n;
cout<<"Enter the productions:\n";
for(i=0;i<n;i++)
cin>>pr[i];
nt=0;
t=0;
for(i=0;i<n;i++)
if((searchnt(pr[i][0]))==-1)
NT[nt++]=pr[i][0];
for(i=0;i<n;i++)
for(j=3;j<strlen(pr[i]);j++)
if(searchnt(pr[i][j])==-1)
if(searchter(pr[i][j])==-1)
T[t++]=pr[i][j];
for(i=0;i<nt;i++)
for(j=0;j<t;j++)
l[i][j]='f';
for(i=0;i<nt;i++)
for(j=0;j<t;j++)
tr[i][j]='f';
for(i=0;i<nt;i++)
for(j=0;j<n;j++)
if(NT[(searchnt(pr[j][0]))]==NT[i])
{
if(searchter(pr[j][3])!=-1)
installl(searchnt(pr[j][0]),searchter(pr[j][3]));
else
for(k=3;k<strlen(pr[j]);k++)
if(searchnt(pr[j][k])==-1)
{
installl(searchnt(pr[j][0]),searchter(pr[j][k]));
break;
}
}
while(top!=0)
{
b=pop();
c=pop();
for(s=0;s<n;s++)
if(pr[s][3]==b)
installl(searchnt(pr[s][0]),searchter(c));
}
cout<<”\nLEAD sets of non-terminals:\n”;
for(i=0;i<nt;i++)
{
cout<<"LEAD["<<NT[i]<<"]"<<": {";
for(j=0;j<t;j++)
if(l[i][j]=='t')
cout<<T[j]<<",";
cout<<"\b}\n";
}
top=0;
for(i=0;i<nt;i++)
for(j=0;j<n;j++)
if(NT[searchnt(pr[j][0])]==NT[i])
{
if(searchter(pr[j][strlen(pr[j])-1])!=-1)
installt(searchnt(pr[j][0]),searchter(pr[j][strlen(pr[j])-1]));
else
for(k=(strlen(pr[j])-1);k>=3;k--)
if(searchnt(pr[j][k])==-1)
{
installt(searchnt(pr[j][0]),searchter(pr[j][k]));
break;
}
}
while(top!=0)
{
b=pop();
c=pop();
for(s=0;s<n;s++)
{
if(pr[s][3]==b)
installt(searchnt(pr[s][0]),searchter(c));
}
}
cout<<”\nTRAIL sets of non-terminals:\n”;
for(i=0;i<nt;i++)
{
cout<<"TRAIL["<<NT[i]<<"]"<<": {";
for(j=0;j<t;j++)
if(tr[i][j]=='t')
cout<<T[j]<<",";
cout<<"\b}\n";
}
return 0;
}
OUTPUT:
Enter the number of productions: 3
Enter the productions:
E->E+T|T
T->T*F|F
F->(E)|i
RESULT: The C++ implementation to find the LEAD and TRAIL sets of variables of a CFG
was compiled, executed and verified successfully.
SHIFT REDUCE PARSER
EX. NO. 9
AIM: To implement Shift Reduce Parser in C++.
ALGORITHM:
1. Start the program.
2. Initialize the required variables.
3. Enter the input symbol.
4. Perform the following:
for top-of-stack symbol, s, and next input symbol, a
Shift x: (x is a STATE number)
Push a, then x on the top of the stack
Advance ip to point to the next input symbol.
At this point the top of the stack should be a state number, say s’.
Push A, then goto of T[s’,A] (a state number) on the top of the stack.
Output the production A→ß.
5. Print if string is accepted or not.
6. Stop the program.
PROGRAM:
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<string.h>
char ip_sym[15],stack[15];
int ip_ptr=0,st_ptr=0,len,i;
char temp[2],temp2[2];
char act[15];
void check();
int main()
{
printf("\n\t\t SHIFT REDUCE PARSER\n");
printf("\n GRAMMAR\n");
printf("\n E->E+E\n E->E/E");
printf("\n E->E*E\n E->a/b");
printf("\n Enter the input symbol:\t");
gets(ip_sym);
printf("\n\t Stack implementation table");
printf("\n Stack\t\t Input symbol\t\t Action");
printf("\n______\t\t ____________\t\t ______\n");
printf("\n $\t\t%s$\t\t\t--",ip_sym);
strcpy(act,"shift ");
temp[0]=ip_sym[ip_ptr];
temp[1]='\0';
strcat(act,temp);
len=strlen(ip_sym);
for(i=0;i<=len-1;i++)
{
stack[st_ptr]=ip_sym[ip_ptr];
stack[st_ptr+1]='\0';
ip_sym[ip_ptr]=' ';
ip_ptr++;
printf("\n $%s\t\t%s$\t\t\t%s",stack,ip_sym,act);
strcpy(act,"shift ");
temp[0]=ip_sym[ip_ptr];
temp[1]='\0';
strcat(act,temp);
check();
st_ptr++;
}
st_ptr++;
check();
}
void check()
{
int flag=0;
temp2[0]=stack[st_ptr];
temp2[1]='\0';
if((!strcmpi(temp2,"a"))||(!strcmpi(temp2,"b")))
{
stack[st_ptr]='E';
if(!strcmpi(temp2,"a"))
printf("\n $%s\t\t%s$\t\t\tE->a",stack, ip_sym);
else
printf("\n $%s\t\t%s$\t\t\tE->b",stack,ip_sym);
flag=1;
}
if((!strcmpi(temp2,"+"))||(strcmpi(temp2,"*"))||(!strcmpi(temp2,"/")
))
{
flag=1;
}
if((!strcmpi(stack,"E+E"))||(!strcmpi(stack,"E\E"))||(!strcmpi(stack
,"E*E")))
{
strcpy(stack,"E");
st_ptr=0;
if(!strcmpi(stack,"E+E"))
printf("\n $%s\t\t%s$\t\t\tE->E+E",stack,ip_sym);
else
if(!strcmpi(stack,"E\E"))
printf("\n $%s\t\t %s$\t\t\tE->E\E",stack,ip_sym);
else
printf("\n $%s\t\t%s$\t\t\tE->E*E",stack,ip_sym);
flag=1;
}
if(!strcmpi(stack,"E")&&ip_ptr==len)
{
printf("\n $%s\t\t%s$\t\t\tACCEPT",stack,ip_sym);
getch();
exit(0);
}
if(flag==0)
{
printf("\n%s\t\t\t%s\t\t reject",stack,ip_sym);
exit(0);
}
return;
}
OUTPUT:
SHIFT REDUCE PARSER
GRAMMAR
E->E+E
E->E/E
E->E*E
E->a|b
$ a+a/b$ --
$a +a/b$ shift a
$E +a/b$ E->a
$E+ a/b$ shift +
$E+a /b$ shift a
$E+E /b$ E->a
$E /b$ E->E*E
$E/ b$ shift /
$E/b $ shift b
$E/E $ E->E/E
$E $ ACCEPT
RESULT: The C++ implementation of Shift Reduce Parser was compiled, executed and
verified successfully.
LR(0) PARSER
EX. NO. 10
AIM: To implement LR(0) Parser in C++.
ALGORITHM:
1. Start.
2. Create structure for production with LHS and RHS.
3. Open file and read input from file.
4. Build state 0 from extra grammar Law S' -> S $ that is all start symbol of grammar and one
Dot ( . ) before S symbol.
5. If Dot symbol is before a non-terminal, add grammar laws that this non-terminal is in Left
Hand Side of that Law and set Dot in before of first part of Right Hand Side.
6. If state exists (a state with this Laws and same Dot position), use that instead.
7. Now find set of terminals and non-terminals in which Dot exist in before.
8. If step 7 Set is non-empty go to 9, else go to 10.
9. For each terminal/non-terminal in set step 7 create new state by using all grammar law that
Dot position is before of that terminal/non-terminal in reference state by increasing Dot point
to next part in Right Hand Side of that laws.
10. Go to step 5.
11. End of state building.
12. Display the output.
13. End.
PROGRAM:
#include<stdio.h>
#include<string.h>
int i,j,k,m,n=0,o,p,ns=0,tn=0,rr=0,ch=0;
char read[15][10], gl[15], gr[15][10], temp, templ[15], tempr[15][10];
char *ptr, temp2[5], dfa[15][15];
struct states
{
char lhs[15],rhs[15][10];
int n;
}I[15];
int compstruct(struct states s1,struct states s2)
{
int t;
if(s1.n!=s2.n)
return 0;
if( strcmp(s1.lhs,s2.lhs)!=0 )
return 0;
for(t=0;t<s1.n;t++)
if( strcmp(s1.rhs[t],s2.rhs[t])!=0 )
return 0;
return 1;
}
void moreprod()
{
int r,s,t,l1=0,rr1=0;
char *ptr1,read1[15][10];
for(r=0;r<I[ns].n;r++)
{
ptr1=strchr(I[ns].rhs[l1],'.');
t=ptr1-I[ns].rhs[l1];
if( t+1==strlen(I[ns].rhs[l1]) )
{
l1++;
continue;
}
temp=I[ns].rhs[l1][t+1];
l1++;
for(s=0;s<rr1;s++)
if( temp==read1[s][0] )
break;
if(s==rr1)
{
read1[rr1][0]=temp;
rr1++;
}
else
continue;
for(s=0;s<n;s++)
{
if(gl[s]==temp)
{
I[ns].rhs[I[ns].n][0]='.';
I[ns].rhs[I[ns].n][1]=NULL;
strcat(I[ns].rhs[I[ns].n],gr[s]);
I[ns].lhs[I[ns].n]=gl[s];
I[ns].lhs[I[ns].n+1]=NULL;
I[ns].n++;
}}}}
void canonical(int l)
{
int t1;
char read1[15][10],rr1=0,*ptr1;
for(i=0;i<I[l].n;i++)
{
temp2[0]='.';
ptr1=strchr(I[l].rhs[i],'.');
t1=ptr1-I[l].rhs[i];
if( t1+1==strlen(I[l].rhs[i]) )
continue;
temp2[1]=I[l].rhs[i][t1+1];
temp2[2]=NULL;
for(j=0;j<rr1;j++)
if( strcmp(temp2,read1[j])==0 )
break;
if(j==rr1)
{
strcpy(read1[rr1],temp2);
read1[rr1][2]=NULL;
rr1++;
}
else
continue;
for(j=0;j<I[0].n;j++)
{
ptr=strstr(I[l].rhs[j],temp2);
if( ptr )
{
templ[tn]=I[l].lhs[j];
templ[tn+1]=NULL;
strcpy(tempr[tn],I[l].rhs[j]);
tn++;
}}
for(j=0;j<tn;j++)
{
ptr=strchr(tempr[j],'.');
p=ptr-tempr[j];
tempr[j][p]=tempr[j][p+1];
tempr[j][p+1]='.';
I[ns].lhs[I[ns].n]=templ[j];
I[ns].lhs[I[ns].n+1]=NULL;
strcpy(I[ns].rhs[I[ns].n],tempr[j]);
I[ns].n++;
}
moreprod();
for(j=0;j<ns;j++)
{
//if ( memcmp(&I[ns],&I[j],sizeof(struct
states))==1 )
if( compstruct(I[ns],I[j])==1 )
{
I[ns].lhs[0]=NULL;
for(k=0;k<I[ns].n;k++)
I[ns].rhs[k][0]=NULL;
I[ns].n=0;
dfa[l][j]=temp2[1];
break;
}}
if(j<ns)
{
tn=0;
for(j=0;j<15;j++)
{
templ[j]=NULL;
tempr[j][0]=NULL;
}
continue;
}
dfa[l][j]=temp2[1];
printf("\n\nI%d :",ns);
for(j=0;j<I[ns].n;j++)
printf("\n\t%c -> %s",I[ns].lhs[j],I[ns].rhs[j]);
getch();
ns++;
tn=0;
for(j=0;j<15;j++)
{
templ[j]=NULL;
tempr[j][0]=NULL;
}}}
void main()
{
FILE *f;
int l;
clrscr();
for(i=0;i<15;i++)
{
I[i].n=0;
I[i].lhs[0]=NULL;
I[i].rhs[0][0]=NULL;
dfa[i][0]=NULL;
}
f=fopen("tab6.txt","r");
while(!feof(f))
{
fscanf(f,"%c",&gl[n]);
fscanf(f,"%s\n",gr[n]);
n++;
}
printf("THE GRAMMAR IS AS FOLLOWS\n");
for(i=0;i<n;i++)
printf("%c -> %s\n",gl[i],gr[i]);
I[0].lhs[0]='Z';
strcpy(I[0].rhs[0],".S");
I[0].n++;
l=0;
for(i=0;i<n;i++)
{
temp=I[0].rhs[l][1];
l++;
for(j=0;j<rr;j++)
if( temp==read[j][0] )
break;
if(j==rr)
{
read[rr][0]=temp;
rr++;
}
else
continue;
for(j=0;j<n;j++)
{
if(gl[j]==temp)
{
I[0].rhs[I[0].n][0]='.';
strcat(I[0].rhs[I[0].n],gr[j]);
I[0].lhs[I[0].n]=gl[j];
I[0].n++;
}
}
}
ns++;
printf("\nI%d :\n",ns-1);
for(i=0;i<I[0].n;i++)
printf("\t%c -> %s\n",I[0].lhs[i],I[0].rhs[i]);
for(l=0;l<ns;l++)
canonical(l);
printf("\n\n\n\t\tPRESS ANY KEY TO EXIT");
}
OUTPUT:
GRAMMAR
E->E+E
E->E/E
E->E*E
E->a|b
$ a+a/b$ --
$a +a/b$ shift a
$E +a/b$ E->a
$E+ a/b$ shift +
$E+a /b$ shift a
$E+E /b$ E->a
$E /b$ E->E*E
$E/ b$ shift /
$E/b $ shift b
$E/E $ E->E/E
$E $ ACCEPT
RESULT: The C++ implementation of LR(0) Parser was compiled, executed and verified
successfully.