CD Lab Manual Final

You might also like

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 51

Lab Manual

Compiler Design Lab


(KCS-552)

B.Tech ( Session 2021-22)


Odd Semester

Department of Computer Science and Engineering


KRISHNA ENGINEERING COLLEGE
95, Loni Road, Mohan Nagar, Ghaziabad (Uttar Pradesh), Pin-201007
Course Outcomes of Compiler Design LAB
(KCS-552)

1. Ability to create lexical rules and grammars for a programming language

2. Ability to use Flex or similar tools to create a lexical analyzer and Yacc/Bison
tools to create a parser.

3. Ability to implement a lexer without using Flex or any other lexer generation
tools.

4. Ability to implement a parser such as a bottom-up SLR parser without using


Yacc/Bison or any other compiler-generation tools.

5. Ability to implement semantic rules into a parser that performs attribution while
parsing.

6. Ability to design a compiler for a concise programming language.


KRISHNA ENGINEERING COLLEGE
Department of Computer Science & Engineering
List of Practical’s
Compiler Design Lab (KCS-552)

S. Name of Practical Date Grade Signature


No.
1 WAP to check whether the entered string is accepted or not
for a given grammar.
2 Develop a lexical analyzer to recognize a few patterns in C. (Ex.
identifiers, constants, comments, operators etc.)
3 Implementation of LEXICAL ANALYZER for ARITHMETIC
EXPRESSION
4 Implementation of LEXICAL ANALYZER for IF
STATEMENT
5 WAP to compute LEADING and TRAILING sets of a
grammar (given).
6 WAP to calculate FIRST and FOLLOW
7 Write a program to remove left recursion from the given
grammar.
8 Write a program to eliminate left factor from the given grammar.

9 Write a program to Implement SHIFT REDUCE PARSING


ALGORITHM
10 Write a program to Implement RECURSIVE DESCENT
PARSER
11 Write a program to Implement OPERATOR PRECEDENCE
PARSER
Program 1

Aim:

To write a C program to check whether the entered string is accepted or not for a given
grammar.

Algorithm:

Start the Program.

Enter the regular expression R over alphabet E.

Decompose the regular expression R into its primitive components

For each component construct finite automata.

To construct components for the basic regular expression way that corresponding to that way
compound regular expression.

Stop the Program.

Program:
#include<stdio.h>
#include<conio.h>
void main()
{
  int state[10];
  int str[10],input[10];
  char ch;
  int x[20];
  int s,n,k=0,j,a,i,l,t,q=0,fs,b,nxt;
  clrscr();
printf("enter the no. states\n");
scanf("%d",&s);
printf("enter the no.of i/ps\n");
scanf("%d",&n);
for(i=0;i<s;i++)
{
printf("enter the state\n");
scanf("%d",&state[i]);
printf("is it final state?... .y..1/n..0\n");
scanf("%d",&a);
if(a==1)
 fs=state[i];
}
printf("enter the i/ps\n");
for(i=0;i<n;i++)
scanf("%d",&input[i]);
printf("transition state\n");
for(i=0;i<s;i++)
{
for(j=0;j<n;j++)
 {
printf("(q%d,%d)=q",state[i],input[j]);
scanf("%d",&b);
 x[k]=b; k++;
 }
 }
printf("enter the length of string\n");
scanf("%d",&l);
printf("enter the i/p string\n");
 for(i=0;i<l;i++)
scanf("%d",&str[i]);
  for(i=0;i<l;i++)
 {
    t=0;
    do
      {
      if(str[i]==input[t])
      {
            nxt=x[n*q+t];
for(j=0;j<s;j++)
{
  if(nxt==state[j])
  q=j;
}
t++;
     }
    else
      t++;
   }
     while(t!=n);
 }
  if(nxt==fs)
printf("\n string is accepted\n");
else
printf("\n not accepted\n");
getch();
}
Sample Input & Output:

Enter the no. of states


2
Enter the no. of i\ps
2
Enter the state
0
Is it final state ….y..1/n..0
1
Is it final state ….y..1/n..0
0
Enter the i\ps
0
1
Transition state
(q0,0)=q1
(q0,1)=q0
(q1,0)=q0
(q1,1)=q1
Enter the length of string
3
Enter the input string
0
0
1

String is accepted

Result:
The above C program was successfully executed and verified
Program 2

Aim:

To write a C program to implement lexical analyzer to recognize a few patterns in C.

Algorithm:

Input:
Output: A sequence of tokens.
Tokens have to be identified and its respective attributes have to be printed.

Keywords:
Examples- for, while, if etc.

Identifier
Examples- Variable name, function name etc.

Operators:
Examples- '+', '++', '-' etc.

Separators:
Examples- ', ' ';' etc

Program:

#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// Returns 'true' if the character is a DELIMITER.


bool isDelimiter(char ch)
{
if (ch == ' ' || ch == '+' || ch == '-' || ch == '*' ||
ch == '/' || ch == ',' || ch == ';' || ch == '>' ||
ch == '<' || ch == '=' || ch == '(' || ch == ')' ||
ch == '[' || ch == ']' || ch == '{' || ch == '}')
return (true);
return (false);
}

// Returns 'true' if the character is an OPERATOR.


bool isOperator(char ch)
{
if (ch == '+' || ch == '-' || ch == '*' ||
ch == '/' || ch == '>' || ch == '<' ||
ch == '=')
return (true);
return (false);
}

// Returns 'true' if the string is a VALID IDENTIFIER.


bool validIdentifier(char* str)
{
if (str[0] == '0' || str[0] == '1' || str[0] == '2' ||
str[0] == '3' || str[0] == '4' || str[0] == '5' ||
str[0] == '6' || str[0] == '7' || str[0] == '8' ||
str[0] == '9' || isDelimiter(str[0]) == true)
return (false);
return (true);
}

// Returns 'true' if the string is a KEYWORD.


bool isKeyword(char* str)
{
if (!strcmp(str, "if") || !strcmp(str, "else") ||
!strcmp(str, "while") || !strcmp(str, "do") ||
!strcmp(str, "break") ||
!strcmp(str, "continue") || !strcmp(str, "int")
|| !strcmp(str, "double") || !strcmp(str, "float")
|| !strcmp(str, "return") || !strcmp(str, "char")
|| !strcmp(str, "case") || !strcmp(str, "char")
|| !strcmp(str, "sizeof") || !strcmp(str, "long")
|| !strcmp(str, "short") || !strcmp(str, "typedef")
|| !strcmp(str, "switch") || !strcmp(str, "unsigned")
|| !strcmp(str, "void") || !strcmp(str, "static")
|| !strcmp(str, "struct") || !strcmp(str, "goto"))
return (true);
return (false);
}

// Returns 'true' if the string is an INTEGER.


bool isInteger(char* str)
{
int i, len = strlen(str);

if (len == 0)
return (false);
for (i = 0; i < len; i++) {
if (str[i] != '0' && str[i] != '1' && str[i] != '2'
&& str[i] != '3' && str[i] != '4' && str[i] != '5'
&& str[i] != '6' && str[i] != '7' && str[i] != '8'
&& str[i] != '9' || (str[i] == '-' && i > 0))
return (false);
}
return (true);
}
// Returns 'true' if the string is a REAL NUMBER.
bool isRealNumber(char* str)
{
int i, len = strlen(str);
bool hasDecimal = false;

if (len == 0)
return (false);
for (i = 0; i < len; i++) {
if (str[i] != '0' && str[i] != '1' && str[i] != '2'
&& str[i] != '3' && str[i] != '4' && str[i] != '5'
&& str[i] != '6' && str[i] != '7' && str[i] != '8'
&& str[i] != '9' && str[i] != '.' ||
(str[i] == '-' && i > 0))
return (false);
if (str[i] == '.')
hasDecimal = true;
}
return (hasDecimal);
}

// Extracts the SUBSTRING.


char* subString(char* str, int left, int right)
{
int i;
char* subStr = (char*)malloc(
sizeof(char) * (right - left + 2));

for (i = left; i <= right; i++)


subStr[i - left] = str[i];
subStr[right - left + 1] = '\0';
return (subStr);
}

// Parsing the input STRING.


void parse(char* str)
{
int left = 0, right = 0;
int len = strlen(str);

while (right <= len && left <= right) {


if (isDelimiter(str[right]) == false)
right++;

if (isDelimiter(str[right]) == true && left == right) {


if (isOperator(str[right]) == true)
printf("'%c' IS AN OPERATOR\n", str[right]);

right++;
left = right;
} else if (isDelimiter(str[right]) == true && left != right
|| (right == len && left != right)) {
char* subStr = subString(str, left, right - 1);

if (isKeyword(subStr) == true)
printf("'%s' IS A KEYWORD\n", subStr);

else if (isInteger(subStr) == true)


printf("'%s' IS AN INTEGER\n", subStr);

else if (isRealNumber(subStr) == true)


printf("'%s' IS A REAL NUMBER\n", subStr);

else if (validIdentifier(subStr) == true


&& isDelimiter(str[right - 1]) == false)
printf("'%s' IS A VALID IDENTIFIER\n", subStr);

else if (validIdentifier(subStr) == false


&& isDelimiter(str[right - 1]) == false)
printf("'%s' IS NOT A VALID IDENTIFIER\n", subStr);
left = right;
}
}
return;
}
// DRIVER FUNCTION
int main()
{
// maximum legth of string is 100 here
char str[100]
printf(“Enter the string:”);
gets(str);
parse(str); // calling the parse function
return (0);
}
Sample Input & Output:
Enter the String: int a = b + c1;

'int' IS A KEYWORD
'a' IS A VALID IDENTIFIER
'=' IS AN OPERATOR
'b' IS A VALID IDENTIFIER
'+' IS AN OPERATOR
'c1' IS A VALID IDENTIFIER
Program 3

Aim:

To write a C program to implement lexical analyzer for Arithmetic Expression.

Algorithm:

Input: Programming language arithmetic expression Output: A sequence of tokens.

Tokens have to be identified and its respective attributes have to be printed.

Lexeme Token
******* ******
Variable name <1,#adddress
>
Numeric constant <2,#address>
; <3,3>
= <4,4>
+ <43,43>
+= <430,430>
- <45,45>
-= <450,450>
* <42,42>
*= <420,420>
/ <47,47>
/= <470,470>
% <37,37>
%= <370,370>
^ <94,94>
^= <940,940>

Program:

#include<stdio.h>
#include<ctype.h>
#include<conio.h>

#include<string.h> char vars[100][100]; int vcnt;

char input[1000],c; char token[50],tlen;


int state=0,pos=0,i=0,id;
char *getAddress(char str[])
{
for(i=0;i<vcnt;i++)

if(strcmp(str,vars[i])==0) return vars[i]; strcpy(vars[vcnt],str); return vars[vcnt++];


}

intisrelop(char c)
{

if(c=='+'||c=='-'||c=='*'||c=='/'||c=='%'||c=='^') return 1;

else return 0;
}

int main(void)
{
clrscr();

printf("Enter the Input String:"); gets(input);

do
{
c=input[pos];
putchar(c);
switch(state)
{

case 0: if(isspace(c)) printf("\b"); if(isalpha(c))


{

token[0]=c;
tlen=1;
state=1;
}
if(isdigit(c))
state=2;

if(isrelop(c))
state=3;
if(c==';')
printf("\t<3,3>\n");
if(c=='=')
printf("\t<4,4>\n");
break;
case 1: if(!isalnum(c))
{
token[tlen]='\o';
printf("\b\t<1,%p>\n",getAddress(token));

state=0; pos--;
}

else token[tlen++]=c; break;

case 2: if(!isdigit(c))

{
printf("\b\t<2,%p>\n",&input[pos]);

state=0; pos--;
}

break; case 3:
id=input[pos-1]; if(c=='=')

printf("\t<%d,%d>\n",id*10,id*10); else
{

printf("\b\t<%d,%d>\n",id,id); pos--;
}
state=0;
break;
}
pos++;
}
while(c!=0);

getch(); return 0;
}
Sample Input & Output:

Enter the Input String: a=a*2+b/c;

A <1,08CE>
= <4,4>
A <1,08CE>
* <42,42>
2 <2,04E9>
+ <43,43>
B <1,0932>
/ <47,47>
C <1,0996>
; <3,3>

Result:

The above C program was successfully executed and verified.


Program 4

Aim:

To write a C program to implement lexical analyzer for 'if' statement.

Algorithm:

Input: Programming language 'if' statement Output: A sequence of tokens.


Tokens have to be identified and its respective attributes have to be printed.

Lexeme Token
******** *******
If <1,1>

variable-name <2,#address>
numeric-constant <3,#address>
; <4,4>
( <5,0>
) <5,1>
{ <6,0>
} <6,1>
> <62,62>
>= <620,620>
< <60,60>
<= <600,600>
! <33,33>
!= <330,330>
= <61,61>
== <610,610>

Program:

#include<stdio.h>
#include<ctype.h>
#include<conio.h>
#include<string.h> char vars[100][100]; int vcnt;
char input[1000],c; char token[50],tlen;
int state=0,pos=0,i=0,id;

char*getAddress(char str[])
{

for(i=0;i<vcnt;i++)
if(strcmp(str,vars[i])==0) return vars[i]; strcpy(vars[vcnt],str); return vars[vcnt++];
}
Int isrelop(char c)
{

if(c=='>'||c=='<'||c=='|'||c=='=') return 1;

else return 0;
}
int main(void)
{
clrscr();

printf("Enter the Input String:");


gets(input);
do
{
c = input[pos];
put char(c);
switch(state)
{

case 0: if(c=='i') state=1; break; case 1: if(c=='f')

{
printf("\t<1,1>\n"); state =2;
}

break; case 2:
if(isspace(c))

printf("\b");
if(isalpha(c))
{
token[0]=c;

tlen=1;

state=3;
}

if(isdigit(c))
state=4;
if(isrelop(c))
state=5;
if(c==';')printf("\t<4,4>\n");
if(c=='(')printf("\t<5,0>\n");

if(c==')')printf("\t<5,1>\n"); if(c=='{') printf("\t<6,1>\n"); if(c=='}') printf("\t<6,2>\n");

break; case 3:
if(!isalnum(c))

{
token[tlen]='\o';
printf("\b\t<2,%p>\n",getAddress(token));

state=2; pos--;
}

else token[tlen++]=c; break;

case 4: if(!isdigit(c))
{
printf("\b\t<3,%p>\n",&input[pos]);

state=2; pos--;
}

break; case 5:

id=input[pos-1]; if(c=='=')

printf("\t<%d,%d>\n",id*10,id*10); else
{

printf("\b\t<%d,%d>\n",id,id); pos--;
}

state=2;

break;
}
pos++;
}
while(c!=0);

getch(); return 0;
}
Sample Input & Output:

Enter the input string: if(a>=b) max=a;

if <1,1>
( <5,0>
a <2,0960>
>= <620,620>
b <2,09c4>
) <5,1>
max <2,0A28>
= <61,61>
a <2,0A8c>
; <4,4>

Result:

The above C program was successfully executed and verified.


Program 5

AIM:

WAP to compute LEADING and TRAILING sets of a grammar(given).

Grammar: E E+T | T
T T*F | F
F (E) | id

PROGRAM :

#include<iostream.h>
#include<conio.h>
void main()
{
clrscr();
char s,l[20],r[10],lead[10],trail[10];
int n,j,m;
for(int i=0;i<10;i++)
{
lead[i]=NULL;
trail[i]=NULL;
}
cout<<"\nenter total no. of productions";
cin>>n;
int k=0;
m=0;
for(i=0;i<n;i++)
{
cout<<"\nenter the LHS of production";
cin>>l[i];
cout<<"\nenter the RHS of production";
cin>>r;
for(int j=0;j<2;j++)
{
if((r[j]=='(') || r[j]==')' || r[j]=='*' || r[j]=='+' || r[j]=='-' || r[j]=='/' )
{
lead[k]=r[j];
k=k+1;
}
if((r[j]=='i') && (r[j+1]=='d'))
{
lead[k]=r[j];
lead[k+1]=r[j+1];
k=k+1;
}
}
for(j=1;j<=2;j++)
{
if((r[j]=='(') || r[j]==')' || r[j]=='*' || r[j]=='+' || r[j]=='-' || r[j]=='/' )
{
trail[m]=r[j];
m=m+1;
}
if((r[j-1]=='i') && (r[j]=='d'))
{
trail[m]=r[j-1];
trail[m+1]=r[j];
m=m+1;
}
}

}
cout<<"\nthe Leading(A) is :\n";
cout<<"{ ";
for(i=0;i<k;i++)
{
if((lead[i]=='i') && (lead[i+1]=='d'))
cout<<lead[i]<<lead[i+1]<<" ";
else
cout<<lead[i]<<" ";
}
cout<<"}";
cout<<"\nthe Trailing(A) is :\n";
cout<<"{ ";
for(i=0;i<m;i++)
{
if((trail[i]=='i') && (trail[i+1]=='d'))
cout<<trail[i]<<trail[i+1]<<" ";
else
cout<<trail[i]<<" ";
}
cout<<"}";

getch();
}

Output:

enter total no. of productions: 6

enter the LHS of production: E


enter the RHS of production: E+T

enter the LHS of production: T


enter the RHS of production: T*F

enter the LHS of production: T


enter the RHS of production: F

enter the LHS of production: E


enter the RHS of production: T

enter the LHS of production: F


enter the RHS of production: (E)

enter the LHS of production :F


enter the RHS of production: id

the Leading(A) is :
{ + * ( id }
the Trailing(A) is :
{ + * ) id }
Program 6

Aim:

To write a C program to find the FIRST of the Non Terminals in the Grammar.

Algorithm:
Apply following rules:
1. If X is terminal, FIRST(X) = {X}.
2. If X → ε is a production, then add ε to FIRST(X).
3. If X is a non-terminal, and X → Y1 Y2 … Yk is a production, and ε is in all of
FIRST(Y1), …, FIRST(Yk), then add ε to FIRST(X).
4. If X is a non-terminal, and X → Y1 Y2 … Yk is a production, then add a to FIRST(X) if
for some i, a is in FIRST(Yi), and ε is in all of FIRST(Y1), …, FIRST(Yi-1).

Assumptions:

Each Non terminal character is represented by one Uppercase letter.


Each Terminal character is represented by one lowercase letter.
LHS and RHS of each production will be separated by a "=" symbol.
There will be no Blank space within a production string. 
Assumed that Left recursion is avoided in all input productions. 

Program:

#include<stdio.h>
#include<ctype.h>
void FIRST(char[],char );
void addToResultSet(char[],char);
int numOfProductions;
char productionSet[10][10];
main()
{
int i;
char choice;
char c;
char result[20];
printf("How many number of productions ? :");
scanf(" %d",&numOfProductions);
for(i=0;i<numOfProductions;i++)//read production string eg: E=E+T
{
printf("Enter productions Number %d : ",i+1);
scanf(" %s",productionSet[i]);
}
do
{
printf("\n Find the FIRST of :");
scanf(" %c",&c);
FIRST(result,c); //Compute FIRST; Get Answer in 'result' array
printf("\n FIRST(%c)= { ",c);
for(i=0;result[i]!='\0';i++)
printf(" %c ",result[i]); //Display result
printf("}\n");
printf("press 'y' to continue : ");
scanf(" %c",&choice);
}
while(choice=='y'||choice =='Y');
}
/*
*Function FIRST:
*Compute the elements in FIRST(c) and write them
*in Result Array.
*/
void FIRST(char* Result,char c)
{
int i,j,k;
char subResult[20];
int foundEpsilon;
subResult[0]='\0';
Result[0]='\0';
//If X is terminal, FIRST(X) = {X}.
if(!(isupper(c)))
{
addToResultSet(Result,c);
return ;
}
//If X is non terminal
//Read each production
for(i=0;i<numOfProductions;i++)
{
//Find production with X as LHS
if(productionSet[i][0]==c)
{
//If X → ε is a production, then add ε to FIRST(X).
 if(productionSet[i][2]=='$') addToResultSet(Result,'$');
//If X is a non-terminal, and X → Y1 Y2 … Yk
//is a production, then add a to FIRST(X)
//if for some i, a is in FIRST(Yi),
//and ε is in all of FIRST(Y1), …, FIRST(Yi-1).
else
{
j=2;
while(productionSet[i][j]!='\0')
{
foundEpsilon=0;
FIRST(subResult,productionSet[i][j]);
for(k=0;subResult[k]!='\0';k++)
addToResultSet(Result,subResult[k]);
for(k=0;subResult[k]!='\0';k++)
if(subResult[k]=='$')
{
foundEpsilon=1;
break;
}
//No ε found, no need to check next element
if(!foundEpsilon)
break;
j++;
}
}
}
}
return ;
}
/* addToResultSet adds the computed
*element to result set.
*This code avoids multiple inclusion of elements
*/
void addToResultSet(char Result[],char val)
{
int k;
or(k=0 ;Result[k]!='\0';k++)
if(Result[k]==val)
return;
Result[k]=val;
Result[k+1]='\0';
}
Sample Input & Output:
How many no. of productions? 3
Enter production no.1 : S=CC
Enter production no.2 : C=cC
Enter production no.3 : C=d

Find the first of: S

First(S) = {c,d}

Press ‘y’ to continue: y


Find the first of: C

First(C) = {c,d}
Result:

The above C program was successfully executed and verified.


Find the Follow of Non Terminal in the Grammar

Aim:
To write a C program to find the FOLLOW of the Non Terminals in the Grammar.

Algorithm:
Apply the following rules:

1. If $ is the input end-marker, and S is the start symbol, $ ∈


FOLLOW(S).
2. If there is a production, A → αBβ, then (FIRST(β) – ε) ⊆ FOLLOW(B).
3. If there is a production, A → αB, or a production A → αBβ, where ε ∈ FIRST(β), then
FOLLOW(A) ⊆ FOLLOW(B).

Program:

#include<stdio.h>
#include<string.h>
int n,m=0,p,i=0,j=0;
char a[10][10],f[10];
void follow(char c);
void first(char c);
int main()
{
int i,z;
char c,ch;
printf("Enter the no.of productions:");
scanf("%d",&n);
printf("Enter the productions(epsilon=$):\n");
for(i=0;i<n;i++)
scanf("%s%c",a[i],&ch);

do
{
m=0;
printf("Enter the element whose FOLLOW is to be found:");

scanf("%c",&c);
follow(c);
printf("FOLLOW(%c) = { ",c);
for(i=0;i<m;i++)
printf("%c ",f[i]);
printf(" }\n");
printf("Do you want to continue(0/1)?");
scanf("%d%c",&z,&ch);
}
while(z==1);
}
void follow(char c)
{

if(a[0][0]==c)f[m++]='$';
for(i=0;i<n;i++)
{
for(j=2;j<strlen(a[i]);j++)
{
if(a[i][j]==c)
{
if(a[i][j+1]!='\0')first(a[i][j+1]);

if(a[i][j+1]=='\0'&&c!=a[i][0])
follow(a[i][0]);

}
}
}
}
void first(char c)
{
int k;
if(!(isupper(c)))f[m++]=c;
for(k=0;k<n;k++)
{
if(a[k][0]==c)
{
if(a[k][2]=='$') follow(a[i][0]);
else if(islower(a[k][2]))f[m++]=a[k][2];
else first(a[k][2]);
}
}

}
SAMPLE INPUT AND OUTPUT:
Enter the no. of Productio:4
Enter the productions(epsilon=$)
S -> AaAb
S-> BbBa
A->$
B->$
Enter the element whose FOLLOW is to be found:S
FOLLOW(S) = {$}
Do you want to continue(0/1)?1
Enter the element whose FOLLOW is to be found:A
FOLLOW(S) = {a,b}
Do you want to continue(0/1)?1
Enter the element whose FOLLOW is to be found:B
FOLLOW(S) = {b,a}
Result:

The above C program was successfully executed and verified.


Program 7

Aim:

To write a C program to remove left factoring in the Grammar.

Algorithm:
∀A NT,
find the longest prefix that occurs in two or more right-hand sides of A
if α ≠ 𝛜 then replace all of the A productions,
A →αβ1 |αβ2 |αβ3 |... |αβn |𝛾 ,

with
A → α Z |𝛾
Z → β 1|β 2| ... |β n

where Z is a new element of NT


Repeat until no common prefixes remain

Program:

#include<stdio.h>
#include<conio.h>
void main()
{
char l,r1[5],r2[5];
int i,j=0;
clrscr();
printf("\nEnter Left Non-Terminal :\t");
scanf("%c->%s / %s",&l,r1,r2);
if(l==r1[0])
{
printf("\nLeft Recusion ");
for(i=1;r1[i-1]!='\0';i++) r1[j++]=r1[i];
printf("Solution :");
printf("\n\t\t%c->%s%c'\n\t\t%c' >%s %c'/%c", l,r2,l,l,r1 ,l,238);
}
if(l==r2[0]) {
printf("\nLeft Recusion ");
for(i=1;r2[i-1]!='\0';i++) r2[j++]=r2[i];
printf("Solution :");
printf("\n\t\t%c->%s %c'\n\t\t%c'->%s%c'/%c",l,r1,l,l,r2,l,238);
}
getch();
}

Sample Input & Output:


Result:
The above C program was successfully executed and verified.
Program 8

Aim:

To write a C program to remove left factoring in the Grammar.

Algorithm:
∀A NT,
find the longest prefix that occurs in two or more right-hand sides of A
if α ≠ 𝛜 then replace all of the A productions,
A →αβ1 |αβ2 |αβ3 |... |αβn |𝛾 ,

with
A → α Z |𝛾
Z → β 1|β 2| ... |β n

where Z is a new element of NT


Repeat until no common prefixes remain

Program:

#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("\n A->%s",modifiedGram);
printf("\n X->%s\n",newGram);
getch();
}
Sample Input & Output:
Enter Production: A-> abB|aC

Output:
A-> aX
X-> bB|C
Result:

The above C program was successfully executed and verified.


Program 9
Aim:

To write a C program to implement the shift-reduce parsing algorithm.

Algorithm:
Grammar:

E->E+E
E->E*E
E->(E)
E->id
Method:

Stack Input Symbol Action


$ id1*id2$ shift
$id1 *id2 $ shift *
$* id2$ shift id2
$id2 $ shift
$ $ accept

Shift: Shifts the next input symbol onto the stack.

Reduce: Right end of the string to be reduced must be at the top of the stack. Accept: Announce
successful completion of parsing.

Error: Discovers a syntax error and call an error recovery routine.


Program:
#include<stdio.h>
#include<string.h>
int k=0,z=0,i=0,j=0,c=0;
char a[16],ac[20],stk[15],act[10];
void check();
int main()
{

puts("GRAMMAR is E->E+E \n E->E*E \n E->(E) \n E->id");


puts("enter input string ");
gets(a);
c=strlen(a);
strcpy(act,"SHIFT->");
puts("stack \t input \t action");
for(k=0,i=0; j<c; k++,i++,j++)
{
if(a[j]=='i' && a[j+1]=='d')
{
stk[i]=a[j];
stk[i+1]=a[j+1];
stk[i+2]='\0';
a[j]=' ';
a[j+1]=' ';
printf("\n$%s\t%s$\t%sid",stk,a,act);
check();
}
else
{
stk[i]=a[j];
stk[i+1]='\0';
a[j]=' ';
printf("\n$%s\t%s$\t%ssymbols",stk,a,act);
check();
}
}
getch();
}
void check()
{
strcpy(ac,"REDUCE TO E");
for(z=0; z<c; z++)
if(stk[z]=='i' && stk[z+1]=='d')
{
stk[z]='E';
stk[z+1]='\0';
printf("\n$%s\t%s$\t%s",stk,a,ac);
j++;
}
for(z=0; z<c; z++)
if(stk[z]=='E' && stk[z+1]=='+' && stk[z+2]=='E')
{
stk[z]='E';
stk[z+1]='\0';
stk[z+2]='\0';
printf("\n$%s\t%s$\t%s",stk,a,ac);
i=i-2;
}
for(z=0; z<c; z++)
if(stk[z]=='E' && stk[z+1]=='*' && stk[z+2]=='E')
{
stk[z]='E';
stk[z+1]='\0';
stk[z+1]='\0';
printf("\n$%s\t%s$\t%s",stk,a,ac);
i=i-2;
}
for(z=0; z<c; z++)
if(stk[z]=='(' && stk[z+1]=='E' && stk[z+2]==')')
{
stk[z]='E';
stk[z+1]='\0';
stk[z+1]='\0';
printf("\n$%s\t%s$\t%s",stk,a,ac);
i=i-2;
}
}
Sample Input & Output:

Result:

The above C program was successfully executed and verified.


Program 10

Aim:

To write a C program to implement the Recursive Descent Parser

Program:

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<string.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);
for(n=0;n<l&&op[n]!='E';n++);
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);
for(n=0;n<l&&op[n]!='T';n++);
i=n+1;
do
{
op[i+2]=op[i];
i++;
}while(i<l);
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++;
}while(i<l);
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);
for(n=0;n<l&&op[n]!='F';n++);
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
{
printf("\n\t syntax error");
getch();
exit(1);
}
}
}

void advance()
{
ip_ptr++;
}

void main()
{
int i;
clrscr();
printf("\nGrammar without left recursion");
printf("\n\t\t E->TE' \n\t\t E'->+TE|e' \n\t\t T->FT' ");
printf("\n\t\t T'->*FT|e' \n\t\t F->(E)|i");
printf("\n Enter the input expression:");
gets(ip_sym);
printf("Expressions");
printf("\t Sequence of production rules\n");
e();
for(i=0;i<strlen(ip_sym);i++)
{
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();
}

Sample Input & Output:


Result:

The above C program was successfully executed and verified.


Program 11

Aim:

To write a C program to implement Operator Precedence Parser.

Algorithm:

Input: String of terminals from the operator grammar

Output: Sequence of shift reduce step1

Method:

1- Let the input string to be initially the stack contains, when the reduce action takes place we
have to reach create parent child relationship.

2- See IP to pointer to the first symbol of input string and repeat forever if only $ is on the input
accept and break else begin.

3- Let 'd’ be the top most terminal on the stack and 'b' be current input IF(a<b) or a=b then Begin
push 'b' onto the stack.

4- Advance Input to the stack to the next Input symbol end;

else if(a>b)

5- Repeat pop the stack until the top most terminal is related by < to the terminal most recently
popped else error value routine

end;

Program:

#include<stdio.h>
char str[50],opstr[75];
int f[2][9]={2,3,4,4,4,0,6,6,0,1,1,3,3,5,5,0,5,0};
int col,col1,col2;
char c;
swt()
{
switch(c)
{
case'+':col=0;break;
case'-':col=1;break;
case'*':col=2;break;
case'/':col=3;break;
case'^':col=4;break;
case'(':col=5;break;
case')':col=6;break;
case'd':col=7;break;
case'$':col=8;break;
default:printf("\nTERMINAL MISSMATCH\n");
exit(1);
33
break;
}
// return 0;
}
main()
{
int i=0,j=0,col1,cn,k=0;
int t1=0,foundg=0;
char temp[20];
clrscr();
printf("\nEnter arithmetic expression:");
scanf("%s",&str);
while(str[i]!='\0')
i++;
str[i]='$';
str[++i]='\0';
printf("%s\n",str);
come:
i=0;
opstr[0]='$';
j=1;
c='$';
swt();
col1=col;
c=str[i];
swt();
col2=col;
if(f[1][col1]>f[2][col2])
{
opstr[j]='>';
j++;
}
else if(f[1][col1]<f[2][col2])
{
opstr[j]='<';
j++;
}
34
else
{
opstr[j]='=';j++;
}
while(str[i]!='$')
{
c=str[i];
swt();
col1=col;
c=str[++i];
swt();
col2=col;
opstr[j]=str[--i];
j++;
if(f[0][col1]>f[1][col2])
{
opstr[j]='>';
j++;
}
else if(f[0][col1]<f[1][col2])
{
opstr[j]='<';
j++;
}
else
{
opstr[j]='=';j++;
}
i++;
}
opstr[j]='$';
opstr[++j]='\0';
printf("\nPrecedence Input:%s\n",opstr);
i=0;
j=0;
while(opstr[i]!='\0')
35
{
foundg=0;
while(foundg!=1)
{
if(opstr[i]=='\0')goto redone;
if(opstr[i]=='>')foundg=1;
t1=i;
i++;
}
if(foundg==1)
for(i=t1;i>0;i--)
if(opstr[i]=='<')break;
if(i==0){printf("\nERROR\n");exit(1);}
cn=i;
j=0;
i=t1+1;
while(opstr[i]!='\0')
{
temp[j]=opstr[i];
j++;i++;
}
temp[j]='\0';
opstr[cn]='E';
opstr[++cn]='\0';
strcat(opstr,temp);
printf("\n%s",opstr);
i=1;
}
redone:k=0;
while(opstr[k]!='\0')
{
k++;
if(opstr[k]=='<')
{
Printf("\nError");
exit(1);
}
36
}
if((opstr[0]=='$')&&(opstr[2]=='$'))goto sue;
i=1
while(opstr[i]!='\0')
{
c=opstr[i];
if(c=='+'||c=='*'||c=='/'||c=='$')
{
temp[j]=c;j++;}
i++;
}
temp[j]='\0';
strcpy(str,temp);
goto come;
sue:
printf("\n success");
return 0;
}
Sample Input & Output:

Enter the arithmetic expression


(d*d)+d$

(d*d)+d$
Precedence input:$<(<d>*<d>)>+<d>$
$<(E*<d>)>+<d>$
$<(E*E)>+<E>$
$E+<E>$
$E+E$
Precedence input:$<+>$
$E$
success

Result:

The above C program was successfully executed and verified.

You might also like