Professional Documents
Culture Documents
LABORATORY MANUAL
B.TECH (R20)
(III YEAR – I SEM)
(2022‐2023)
List of Experiments:
WEEK-1 . Simulate the following CPU scheduling algorithms:
a. Round Robin (b) SJF (c) FCFS (d) Priority
WEEK-2 Simulate the following:
a) Multiprogramming with a fixed number of tasks (MFT)
b) Multiprogramming with a variable number of tasks (MVT)
WEEK-3. Simulate the following page replacement algorithms:
a) FIFO b) LRU c) LFU
WEEK-4. Write a C program that illustrates two processes communicating using shared memory
WEEK-5. Write a C program to simulate producer and consumer problem usingsemaphores
WEEK-6. Simulate Bankers Algorithm for Dead Lock Avoidance
WEEK- 7. Simulate Bankers Algorithm for Dead Lock Prevention.
WEEK- 8. Write a C program to identify different types of Tokens in a given Program.
WEEK- 9. Write a Lex Program to implement a Lexical Analyzer using Lex tool.
WEEK- 10. Write a C program to Simulate Lexical Analyzer to validating a given input String.
WEEK- 11. Write a C program to implement the Brute force technique of Top down Parsing.
WEEK- 12. Write a C program to implement a Recursive Descent Parser.
WEEK-13. Write C program to compute the First and Follow Sets for the given Grammar.
WEEK-14. Write a C program for eliminating the left recursion and left factoring of a given grammar
WEEK-15. Write a C program to check the validity of input string using Predictive Parser.
WEEK-16. Write a C program for implementation of LR parsing algorithm to accept a given input
string.
WEEK-17. Write a C program for implementation of a Shift Reduce Parser using Stack Data
Structure to accept a given input string of a given grammar
WEEK- 18. Simulate the calculator using LEX and YACC too
REFERENCE BOOKS:
1. An Introduction to Operating Systems, P.C.P Bhatt, 2nd edition, PHI.
2. Modern Operating Systems, Andrew S Tanenbaum, 3rd Edition, PHI
OUTCOMES:
By the end of the course, student will be able to Implement various scheduling, page
replacement algorithms and algorithms related to deadlocks
Design programs for shared memory management and semaphores
Determine predictive parsing table for a CFG
Apply Lex and Yacc tools
Examine LR parser and generating SLR Parsing table
DEPARTMENT OF CSE-Artificial Intelligence
TABLE OF CONTENTS
Description:
As it is known that Lexical Analysis is the first phase of compiler also known as scanner. It converts the
inputprogramintoasequenceofTokens.
A C program consists of various tokens and a token is either a keyword, an identifier, a constant, a
stringliteral,orasymbol.
For Example:
1) Keywords:
Examples- for, while, if etc.
2) Identifier
Examples- Variable name, function name etc.
3) Operators:
Examples- '+', '++', '-' etc.
4) Separators:
Examples- ', ' ';' etc
Below is a C program to print all the keywords, literals, valid identifiers, invalid identifiers, integer
number, real number in a given C program:
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
return (true);
return (false);
ch == '=')
return (true);
return (false);
return (false);
return (true);
{
if (!strcmp(str, "if") || !strcmp(str, "else") ||
!strcmp(str, "break") ||
return (true);
return (false);
if (len == 0)
return (false);
return (false);
return (true);
}
if (len == 0)
return (false);
return (false);
if (str[i] == '.')
hasDecimal = true;
return (hasDecimal);
int i;
return (subStr);
if (isDelimiter(str[right]) == false)
right++;
if (isOperator(str[right]) == true)
right++;
left = right;
if (isKeyword(subStr) == true)
left = right;
return;
// DRIVER FUNCTION
int main()
return (0);
}
OUTPUT
'int' IS A KEYWORD
'a' IS A VALID IDENTIFIER
'=' IS AN OPERATOR
'b' IS A VALID IDENTIFIER
'+' IS AN OPERATOR
'1c' IS NOT A VALID IDENTIFIER
-2
WEEK-9
AIM:’ Write a Lex Program to implement a Lexical Analyzer using Lex tool
Description: Lexical analyzer: scans the input stream and converts sequences of characters
into tokens. Lex is a tool for writing lexical analyzers. Syntactic Analysis: reads tokens and
assembles them into language constructs using the grammar rules of the language. Yacc is a tool
for constructing parsers.
AIM: Write a C program to Simulate Lexical Analyzer to validating a given input String.
DESCRIPTION:
Description:
Top-Down Parser:
Recursive descent parser is also known as the Brute force parser or the backtracking parser. It
basically generates the parse tree by using brute force and backtracking. Non-recursive
descent parser is also known as LL(1) parser or predictive parser or without backtracking parser
or dynamic parser.
A brute force approach is an approach that finds all the possible solutions to find a satisfactory
solution to a given problem. The brute force algorithm tries out all the possibilities till a
o Optimizing: In this case, the best solution is found. To find the best solution, it may
either find all the possible solutions to find the best solution or if the value of the best
solution is known, it stops finding when the best solution is found. For example: Finding
the best path for the travelling salesman problem. Here best path means that travelling all
o Satisficing: It stops finding the solution as soon as the satisfactory solution is found. Or
example, finding the travelling salesman path which is within 10% of optimal.
o Often Brute force algorithms require exponential time. Various heuristics and
o Heuristic: A rule of thumb that helps you to decide which possibilities we should look at
first.
#include<iostream.h>
#include<conio.h>
#include<string.h>
class parse
{
int nt,t,m[20][20],i,s,n,p1,q,k,j;
char p[30][30],n1[20],t1[20],ch,b,c,f[30][30],fl[30][30];
public:
int scant(char);
int scannt(char);
void process();
void input();
};
int parse::scannt(char a)
{
int c=-1,i;
for(i=0;i<nt;i++)
{
if(n1[i]==a)
{
return i;
}
}
return c;
}
int parse::scant(char b)
{
int c1=-1,j;
for(j=0;j<t;j++)
{
if(t1[j]==b)
{
return j;
}
}
return c1;
}
void parse::input()
{
cout<<"Enter the number of productions:";
cin>>n;
cout<<"Enter the productions one by one"<<endl;
for(i=0;i<n;i++)
cin>>p[i];
nt=0;
t=0;
}
void parse::process()
{
for(i=0;i<n;i++)
{
if(scannt(p[i][0])==-1)
n1[nt++]=p[i][0];
}
for(i=0;i<n;i++)
{
for(j=3;j<strlen(p[i]);j++)
{
if(p[i][j]!='e')
{
if(scannt(p[i][j])==-1)
{
if((scant(p[i][j]))==-1)
t1[t++]=p[i][j];
}
}
}
}
t1[t++]='$';
for(i=0;i<nt;i++)
{
for(j=0;j<t;j++)
m[i][j]=-1;
}
for(i=0;i<nt;i++)
{
cout<<"Enter first["<<n1[i]<<"]:";
cin>>f[i];
}
for(i=0;i<nt;i++)
{
cout<<"Enter follow["<<n1[i]<<"]:";
cin>>fl[i];
}
for(i=0;i<n;i++)
{
p1=scannt(p[i][0]);
if((q=scant(p[i][3]))!=-1)
m[p1][q]=i;
if((q=scannt(p[i][3]))!=-1)
{
for(j=0;j<strlen(f[q]);j++)
m[p1][scant(f[q][j])]=i;
}
if(p[i][3]=='e')
{
for(j=0;j<strlen(fl[p1]);j++)
m[p1][scant(fl[p1][j])]=i;
}
}
for(i=0;i<t;i++)
cout<<"\t"<<t1[i];
cout<<endl;
for(j=0;j<nt;j++)
{
cout<<n1[j];
for(i=0;i<t;i++)
{
cout<<"\t"<<" ";
if(m[j][i]!=-1)
cout<<p[m[j][i]];
}
cout<<endl;
}
}
void main()
{
clrscr();
parse p;
p.input();
p.process();
getch();
}
Top Down Parsing in Complier Design output
Enter the number of productions:8
Enter the productions one by one
E->TA
A->+TA
A->e
T->FB
B->e
B->*FB
F->(E)
F->i
Enter first[E]: (i
Enter first[A]: +e
Enter first[T]: (i
Enter first[B]: *e
Enter first[F]: (i
Enter follow[E]: $)
Enter follow[A]: $)
Enter follow[T]: +)$
Enter follow[B]: +)$
Enter follow[F]: +*)$
+()i*$
E E->TA E->TA
A A->+TA A->e A->e
T T->FB T->FB
B B->e B->e B->*FB B->e
F F->(E) F->i
Top down Parsing in Compiler Design Output
Enter the no of productions:
8
Enter the production one by one:
E->TX
X->+TX
X->e
T->FY
Y->*FY
Y->e
F->(E)
F->i
Enter FIRST[E](i
Enter FIRST[X]+e
Enter FIRST[T](i
Enter FIRST[Y]*e
Enter FIRST[F](i
Enter FOLLOW[E])$
Enter FOLLOW[X])$
Enter FOLLOW[T]+)$
Enter FOLLOW[Y]+)$
Enter FOLLOW[F]*+)$
+*()i$
E E->TX E->TX
X X->+TX X->e X->e
T T->FY T->FY
Y Y->e Y->*FY Y->e Y->e
F F->(E) F->i
5 AIM: Write a C program to implement a Recursive Descent Parser
WEEK-12
Description:
Source code:
#include"stdio.h"
#include"conio.h"
#include"string.h"
#include"stdlib.h"
#include"ctype.h"
char ip_sym[15],ip_ptr=0,op[50],tmp[50];
void e_prime();
void e();
void t_prime();
void t();
void f();
void advance();
int n=0;
void e()
strcpy(op,"TE'");
printf("E=%-25s",op);
printf("E->TE'\n");
t();
e_prime();
}
void e_prime()
int i,n=0,l;
for(i=0;i<=strlen(op);i++)
if(op[i]!='e')
tmp[n++]=op[i];
strcpy(op,tmp);
l=strlen(op);
if(ip_sym[ip_ptr]=='+')
i=n+2;
do
op[i+2]=op[i];
i++;
}while(i<=l);
op[n++]='+';
op[n++]='T';
op[n++]='E';
op[n++]=39;
printf("E=%-25s",op);
printf("E'->+TE'\n");
advance();
t();
e_prime();
else
op[n]='e';
for(i=n+1;i<=strlen(op);i++)
op[i]=op[i+1];
printf("E=%-25s",op);
printf("E'->e");
void t()
int i,n=0,l;
for(i=0;i<=strlen(op);i++)
if(op[i]!='e')
tmp[n++]=op[i];
strcpy(op,tmp);
l=strlen(op);
do
op[i+2]=op[i];
i++;
op[n++]='F';
op[n++]='T';
op[n++]=39;
printf("E=%-25s",op);
printf("T->FT'\n");
f();
t_prime();
void t_prime()
int i,n=0,l;
for(i=0;i<=strlen(op);i++)
if(op[i]!='e')
tmp[n++]=op[i];
strcpy(op,tmp);
l=strlen(op);
for(n=0;n < l && op[n]!='T';n++);
if(ip_sym[ip_ptr]=='*')
i=n+2;
do
op[i+2]=op[i];
i++;
op[n++]='*';
op[n++]='F';
op[n++]='T';
op[n++]=39;
printf("E=%-25s",op);
printf("T'->*FT'\n");
advance();
f();
t_prime();
else
op[n]='e';
for(i=n+1;i<=strlen(op);i++)
op[i]=op[i+1];
printf("E=%-25s",op);
printf("T'->e\n");
void f()
int i,n=0,l;
for(i=0;i<=strlen(op);i++)
if(op[i]!='e')
tmp[n++]=op[i];
strcpy(op,tmp);
l=strlen(op);
if((ip_sym[ip_ptr]=='i')||(ip_sym[ip_ptr]=='I'))
op[n]='i';
printf("E=%-25s",op);
printf("F->i\n");
advance();
else
{
if(ip_sym[ip_ptr]=='(')
advance();
e();
if(ip_sym[ip_ptr]==')')
advance();
i=n+2;
do
op[i+2]=op[i];
i++;
}while(i<=l);
op[n++]='(';
op[n++]='E';
op[n++]=')';
printf("E=%-25s",op);
printf("F->(E)\n");
else
exit(1);
void advance()
ip_ptr++;
void main()
int i;
clrscr();
gets(ip_sym);
printf("Expressions");
e();
if(ip_sym[i]!='+'&&ip_sym[i]!='*'&&ip_sym[i]!='('&&
ip_sym[i]!=')'&&ip_sym[i]!='i'&&ip_sym[i]!='I')
printf("\nSyntax error");
break;
for(i=0;i<=strlen(op);i++)
if(op[i]!='e')
tmp[n++]=op[i];
strcpy(op,tmp);
printf("\nE=%-25s",op);
getch();
Output:
WEEK-13
6
AIM: Write C program to compute the First and Follow Sets for the given Grammar
Description:
Assuming the reader is familiar with the basics discussed above, let’s start discussing how to
implement the C program to calculate the first and follow of given grammar.
Example :
Input :
E -> TR
R -> +T R| #
T -> F Y
Y -> *F Y | #
F -> (E) | i
Output :
First(E)= { (, i, }
First(R)= { +, #, }
First(T)= { (, i, }
First(Y)= { *, #, }
First(F)= { (, i, }
-----------------------------------------------
Follow(E) = { $, ), }
Follow(R) = { $, ), }
Follow(T) = { +, $, ), }
Follow(Y) = { +, $, ), }
Follow(F) = { *, +, $, ), }
The functions follow and followfirst are both involved in the calculation of the Follow Set of
a given Non-Terminal. The follow set of the start symbol will always contain “$”. Now the
calculation of Follow falls under three broad cases :
If a Non-Terminal on the R.H.S. of any production is followed immediately by a
Terminal then it can immediately be included in the Follow set of that Non-Terminal.
If a Non-Terminal on the R.H.S. of any production is followed immediately by a Non-
Terminal, then the First Set of that new Non-Terminal gets included on the follow set of
our original Non-Terminal. In case encountered an epsilon i.e. ” # ” then, move on to the
next symbol in the production.
Note: “#” is never included in the Follow set of any Non-Terminal.
If reached the end of a production while calculating follow, then the Follow set of that
non-terminal will include the Follow set of the Non-Terminal on the L.H.S. of that
production. This can easily be implemented by recursion.
Assumptions :
1. Epsilon is represented by ‘#’.
2. Productions are of the form A=B, where ‘A’ is a single Non-Terminal and ‘B’ can be
any combination of Terminals and Non- Terminals.
3. L.H.S. of the first production rule is the start symbol.
4. Grammar is not left recursive.
5. Each production of a non-terminal is entered on a different line.
6. Only Upper Case letters are Non-Terminals and everything else is a terminal.
7. Do not use ‘!’ or ‘$’ as they are reserved for special purposes.
Explanation :
Store the grammar on a 2D character array production. findfirst function is for calculating
the first of any non terminal. Calculation of first falls under two broad cases :
If the first symbol in the R.H.S of the production is a Terminal then it can directly be
included in the first set.
If the first symbol in the R.H.S of the production is a Non-Terminal then call the
findfirst function again on that Non-Terminal. To handle these cases like Recursion is the
best possible solution. Here again, if the First of the new Non-Terminal contains an
epsilon then we have to move to the next symbol of the original production which can
again be a Terminal or a Non-Terminal.
Note : For the second case it is very easy to fall prey to an INFINITE LOOP even if the code
looks perfect. So it is important to keep track of all the function calls at all times and never
call the same function again.
Recommended: Please try your approach on {IDE} first, before moving on to the solution.
#include<stdio.h>
#include<ctype.h>
#include<string.h>
char calc_first[10][100];
char calc_follow[10][100];
int m = 0;
char production[10][10];
int k;
char ck;
int e;
int jm = 0;
int km = 0;
int i, choice;
char c, ch;
count = 8;
// The Input grammar
strcpy(production[0], "E=TR");
strcpy(production[1], "R=+TR");
strcpy(production[2], "R=#");
strcpy(production[3], "T=FY");
strcpy(production[4], "Y=*FY");
strcpy(production[5], "Y=#");
strcpy(production[6], "F=(E)");
strcpy(production[7], "F=i");
int kay;
char done[count];
calc_first[k][kay] = '!';
{
c = production[k][0];
point2 = 0;
xxx = 0;
if(c == done[kay])
xxx = 1;
if (xxx == 1)
continue;
// Function call
findfirst(c, 0, 0);
ptr += 1;
done[ptr] = c;
calc_first[point1][point2++] = c;
if (first[i] == calc_first[point1][lark])
chk = 1;
break;
if(chk == 0)
calc_first[point1][point2++] = first[i];
printf("}\n");
jm = n;
point1++;
printf("\n");
printf("-----------------------------------------------\n\n");
char donee[count];
ptr = -1;
calc_follow[k][kay] = '!';
point1 = 0;
int land = 0;
ck = production[e][0];
point2 = 0;
xxx = 0;
// Checking if Follow of ck
if(ck == donee[kay])
xxx = 1;
if (xxx == 1)
continue;
land += 1;
// Function call
follow(ck);
ptr += 1;
donee[ptr] = ck;
calc_follow[point1][point2++] = ck;
if (f[i] == calc_follow[point1][lark])
chk = 1;
break;
if(chk == 0)
calc_follow[point1][point2++] = f[i];
printf(" }\n\n");
km = m;
point1++;
void follow(char c)
int i, j;
if(production[0][0] == c) {
f[m++] = '$';
if(production[i][j] == c)
if(production[i][j+1] != '\0')
followfirst(production[i][j+1], i, (j+2));
}
follow(production[i][0]);
int j;
// encounter a Terminal
if(!(isupper(c))) {
first[n++] = c;
if(production[j][0] == c)
{
if(production[j][2] == '#')
if(production[q1][q2] == '\0')
first[n++] = '#';
else
first[n++] = '#';
else if(!isupper(production[j][2]))
first[n++] = production[j][2];
else
// at the beginning
findfirst(production[j][2], j, 3);
}
int k;
// a Terminal
if(!(isupper(c)))
f[m++] = c;
else
int i = 0, j = 1;
if(calc_first[i][0] == c)
break;
if(calc_first[i][j] != '#')
f[m++] = calc_first[i][j];
else
if(production[c1][c2] == '\0')
// end of a production
follow(production[c1][0]);
else
j++;
}
Output :
First(E)= { (, i, }
First(R)= { +, #, }
First(T)= { (, i, }
First(Y)= { *, #, }
First(F)= { (, i, }
-----------------------------------------------
Follow(E) = { $, ), }
Follow(R) = { $, ), }
Follow(T) = { +, $, ), }
Follow(Y) = { +, $, ), }
Follow(F) = { *, +, $, ), }
7 Write a C program for eliminating the left recursion and left factoring of a given grammar.
WEEK-14
Description:
7:
Left factoring is removing the common left factor that appears in two productions of the same
non-terminal. It is done to avoid back-tracing by the parser. Suppose the parser has a look-ahead,
consider this example:
A -> qB | qC
where A, B and C are non-terminals and q is a sentence.
In this case, the parser will be confused as to which of the two productions to choose and it might
have to back-trace. After left factoring, the grammar is converted to:
A -> qD
D -> B | C
In this case, a parser with a look-ahead will always choose the right production.
Left recursion is a case when the left-most non-terminal in a production of a non-terminal is the
non-terminal itself (direct left recursion) or through some other non-terminal definitions, rewrites
to the non-terminal again (indirect left recursion).
(2) A -> Bq
B -> Ar (indirect)
Left recursion has to be removed if the parser performs top-down parsing.
#include<stdio.h>
#include<string.h>
void main() {
char input[100],l[50],r[50],temp[10],tempprod[20],productions[25][50];
int i=0,j=0,flag=0,consumed=0;
printf("Enter the productions: ");
scanf("%1s->%s",l,r);
printf("%s",r);
while(sscanf(r+consumed,"%[^|]s",temp) == 1 && consumed <=
strlen(r)) {
if(temp[0] == l[0]) {
flag = 1;
sprintf(productions[i++],"%s->%s%s'\0",l,temp+1,l);
}
else
sprintf(productions[i++],"%s'->%s%s'\0",l,temp,l);
consumed += strlen(temp)+1;
}
if(flag == 1) {
sprintf(productions[i++],"%s->ε\0",l);
printf("The productions after eliminating Left Recursion are:\n");
for(j=0;j<i;j++)
printf("%s\n",productions[j]);
}
else
printf("The Given Grammar has no Left Recursion");
}
OUTPUT
#include<stdio.h>
#include<string.h>
int main()
{
char gram[20],part1[20],part2[20],modifiedGram[20],newGram[20],tempGram[20];
int i,j=0,k=0,l=0,pos;
printf("Enter Production : A->");
gets(gram);
for(i=0;gram[i]!='|';i++,j++)
part1[j]=gram[i];
part1[j]='\0';
for(j=++i,i=0;gram[j]!='\0';j++,i++)
part2[i]=gram[j];
part2[i]='\0';
for(i=0;i<strlen(part1)||i<strlen(part2);i++){
if(part1[i]==part2[i]){
modifiedGram[k]=part1[i];
k++;
pos=i+1;
}
}
for(i=pos,j=0;part1[i]!='\0';i++,j++){
newGram[j]=part1[i];
}
newGram[j++]='|';
for(i=pos;part2[i]!='\0';i++,j++){
newGram[j]=part2[i];
}
modifiedGram[k]='X';
modifiedGram[++k]='\0';
newGram[j]='\0';
printf("\nGrammar Without Left Factoring : : \n");
printf(" A->%s",modifiedGram);
printf("\n X->%s\n",newGram);
}
+
WEEK-15
-8 AIM: Write a C program to check the validity of input string using Predictive Parser
Description:
#include<stdio.h>
#include<conio.h>
#include<string.h>
char prol[7][10]={"S","A","A","B","B","C","C"};
char pror[7][10]={"A","Bb","Cd","aB","@","Cc","@"};
char table[5][6][10];
int numr(char c)
switch(c){
return(2);
void main()
int i,j,k;
clrscr();
for(i=0;i<5;i++)
for(j=0;j<6;j++)
strcpy(table[i][j]," ");
printf("%s\n",prod[i]);
fflush(stdin);
for(i=0;i<7;i++){
k=strlen(first[i]);
for(j=0;j<10;j++)
if(first[i][j]!='@')
strcpy(table[numr(prol[i][0])+1][numr(first[i][j])+1],prod[i]);
for(i=0;i<7;i++){
if(strlen(pror[i])==1)
if(pror[i][0]=='@')
{
k=strlen(follow[i]);
for(j=0;j<k;j++)
strcpy(table[numr(prol[i][0])+1][numr(follow[i][j])+1],prod[i]);
strcpy(table[0][0]," ");
strcpy(table[0][1],"a");
strcpy(table[0][2],"b");
strcpy(table[0][3],"c");
strcpy(table[0][4],"d");
strcpy(table[0][5],"$");
strcpy(table[1][0],"S");
strcpy(table[2][0],"A");
strcpy(table[3][0],"B");
strcpy(table[4][0],"C");
printf("\n--------------------------------------------------------\n");
for(i=0;i<5;i++)
for(j=0;j<6;j++){
printf("%-10s",table[i][j]);
if(j==5)
printf("\n--------------------------------------------------------\n");
}
getch();
Output:
The following is the predictive parsing table for the following grammar:
S->A
A->Bb
A->Cd
B->aB
B->@
C->Cc
C->@
Predictive parsing table is
--------------------------------------------------------
abcd$
--------------------------------------------------------
S S->A S->A S->A S->A
--------------------------------------------------------
A A->Bb A->Bb A->Cd A->Cd
--------------------------------------------------------
B B->aB B->@ B->@ B->@
--------------------------------------------------------
C C->@ C->@ C->@
--------------------------------------------------------
9
WEEK-16
AMI: Write a C program for implementation of LR parsing algorithm to accept a given input string.
Description:
ALGORITHM:
1. Get the input expression and store it in the input buffer.
2. Read the data from the input buffer one at the time and convert in to corresponding Non
Terminal using production rules available.
3. Perform push & pop operation for LR parsing table construction.
4. Display the result with conversion of corresponding input symbols to production and
production reduction to start symbol. No operation performed on the operator.
PROGRAM:
#include
#include
char stack[30];
int top=-1;
void push(char c)
top++;
stack[top]=c;
char pop()
char c;
if(top!=-1)
c=stack[top];
top--;
return c;
return'x';
void printstat()
int i;
printf("\n\t\t\t $");
for(i=0;i<=top;i++)
printf("%c",stack[i]);
void main()
int i,j,k,l;
char s1[20],s2[20],ch1,ch2,ch3;
clrscr();
printf("\n\n\t\t LR PARSING");
scanf("%s",s1);
l=strlen(s1);
j=0;
printf("\n\t\t $");
s1[i]=' ';
s1[i+1]='E';
printstat(); printf("id");
push('E');
printstat();
push(s1[i]);
printstat();
printstat();
l=strlen(s2);
while(l)
ch1=pop();
if(ch1=='x')
printf("\n\t\t\t $");
break;
if(ch1=='+'||ch1=='/'||ch1=='*'||ch1=='-')
ch3=pop();
if(ch3!='E')
printf("errror");
exit();
else
push('E');
printstat();
ch2=ch1;
getch();
} </l;i++)<>
OUTPUT:
LR PARSING
id+id*id-id
$id
$E
$E+
$E+id
$E+E
$E+E*
$E+E*id
$E+E*E
$E+E*E-
$E+E*E-id
$E+E*E-E
$E+E*E-E
$E+E*E
$E
$
10
WEEK-17
AIM: Write a C program for implementation of a Shift Reduce Parser using Stack Data Structure
to accept a given input string of a given grammar
Shift Reduce parser attempts for the construction of parse in a similar manner as done in
bottom-up parsing i.e. the parse tree is constructed from leaves(bottom) to the root(up). A more
general form of the shift-reduce parser is the LR parser.
This parser requires some data structures i.e.
An input buffer for storing the input string.
A stack for storing and accessing the production rules.
Basic Operations –
Shift: This involves moving symbols from the input buffer onto the stack.
Reduce: If the handle appears on top of the stack then, its reduction by using appropriate
production rule is done i.e. RHS of a production rule is popped out of a stack and LHS
of a production rule is pushed onto the stack.
Accept: If only the start symbol is present in the stack and the input buffer is empty then,
the parsing action is called accept. When accepted action is obtained, it is means
successful parsing is done.
Error: This is the situation in which the parser can neither perform shift action nor
reduce action and not even accept action.
Example 1 – Consider the grammar
S– >S+S
S– >S*S
S– > id
Perform Shift Reduce parsing for input string “id + id + id”.
$ (a,(a,a))$ Shift
$( a,(a,a))$ Shift
$ ( L, ( L ))$ Shift
$ ( L, ( L ) )$ Reduce S → (L)
$ ( L, S )$ Reduce L → L, S
$(L )$ Shift
$S $ Accept
// Including Libraries
#include <bits/stdc++.h>
// Global Variables
int z = 0, i = 0, j = 0, c = 0;
// Modify array size to increase
// which is to be Reduce.
void check()
if(stk[z] == '4')
{
printf("%s4", ac);
stk[z] = 'E';
stk[z + 1] = '\0';
//printing action
stk[z + 2] == '2')
printf("%s2E2", ac);
stk[z] = 'E';
stk[z + 1] = '\0';
stk[z + 2] = '\0';
i = i - 2;
stk[z + 2] == '3')
printf("%s3E3", ac);
stk[z]='E';
stk[z + 1]='\0';
stk[z + 1]='\0';
i = i - 2;
}
// Driver Function
int main()
// a is input string
strcpy(a,"32423");
c=strlen(a);
strcpy(act,"SHIFT");
// This will print Labels (column name)
printf("\n$\t%s$\t", a);
// Printing action
printf("%s", act);
stk[i] = a[j];
stk[i + 1] = '\0';
a[j]=' ';
// Printing action
check();
check();
printf("Accept\n");
else //else reject
printf("Reject\n");
Output –
GRAMMAR is -
E->2E2
E->3E3
E->4
Description:
Input :
5*4
Output :
20.0
Below is the implementation:
SOURCE CODE:
- a simple calculator.*/
%{
int op = 0,i;
float a, b;
%}
dig [0-9]+|([0-9]*)"."([0-9]+)
add "+"
sub "-"
mul "*"
div "/"
pow "^"
ln \n
%%
{dig} {digi();}
{add} {op=1;}
{sub} {op=2;}
{mul} {op=3;}
{div} {op=4;}
{pow} {op=5;}
%%
digi()
if(op==0)
else
b=atof(yytext);
switch(op)
case 1:a=a+b;
break;
case 2:a=a-b;
break;
case 3:a=a*b;
break;
case 4:a=a/b;
break;
case 5:for(i=a;b>1;b--)
a=a*i;
break;
op=0;
}
yylex();
yywrap()
return 1;
OUTPUT: