0% found this document useful (0 votes)
46 views

Code:: Compiler Design (3170701) 190090107055

The document describes the use of LEX tool for implementing a lexical analyzer. It discusses: - The functions of LEX tool which takes a program written in LEX language as input and generates C code for a lexical analyzer. - The importance of LEX in identifying text tokens from source code in a structured way. - The typical structure of a LEX program including declarations, translation rules, and auxiliary functions sections. - How lexical analyzers work by matching regular expressions to identify tokens and resolve conflicts. - Lookahead operators that allow lexical analyzers to read ahead to distinguish patterns for tokens.

Uploaded by

bsaahire
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
46 views

Code:: Compiler Design (3170701) 190090107055

The document describes the use of LEX tool for implementing a lexical analyzer. It discusses: - The functions of LEX tool which takes a program written in LEX language as input and generates C code for a lexical analyzer. - The importance of LEX in identifying text tokens from source code in a structured way. - The typical structure of a LEX program including declarations, translation rules, and auxiliary functions sections. - How lexical analyzers work by matching regular expressions to identify tokens and resolve conflicts. - Lookahead operators that allow lexical analyzers to read ahead to distinguish patterns for tokens.

Uploaded by

bsaahire
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 76

Compiler Design (3170701) 190090107055

Practical 1
Design a lexical analyzer for a given language and the lexical
analyzer should ignore redundant spaces, tabs and newlines. It
should also ignore comments. Although the syntax specification
states that identifiers can be arbitrarily long, you may restrict the
length to some reasonable value. Simulate the same in C language.

• Code:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <ctype.h>

int isKeyword(char buffer[])

char keywords[32][10] = {"auto", "break", "case", "char", "const", "continue", "default", "do",
"double", "else", "enum", "extern", "float", "for", "goto", "if", "int", "long", "register", "return",
"short", "signed", "sizeof", "static", "struct", "switch", "typedef", "union", "unsigned", "void",
"volatile", "while"};

int i, flag = 0;

for (i = 0; i < 32; ++i)

if (strcmp(keywords[i], buffer) == 0)

flag = 1;
1|Page
Compiler Design (3170701) 190090107055

break;

return flag;

int main()

char ch, buffer[15], operators[] = "+-*/%=";

FILE *fp;

int i, j = 0;

fp = fopen("c:\\practical.txt", "r");

if (fp == NULL)

printf("error while opening the file\n");

exit(0);

while ((ch = fgetc(fp)) != EOF)

for (i = 0; i < 6; ++i)

if (ch == operators[i])

printf("%c is operator\n", ch);

if (isalnum(ch))

2|Page
Compiler Design (3170701) 190090107055

buffer[j++] = ch;

else if ((ch == ' ' || ch == '\n') && (j != 0))

buffer[j] = '\0';

j = 0;

if (isKeyword(buffer) == 1)

printf("%s is keyword\n", buffer);

else

printf("%s is indentifier\n", buffer);

fclose(fp);

return 0;

3|Page
Compiler Design (3170701) 190090107055

• Text File:

• Output:

4|Page
Compiler Design (3170701) 190090107055

Practical 2
Implement generic DFA to recognize any regular any regular
expression and perform string validation.

• Code:

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

int ninputs;
//function
declarationint
check(char,
int); int
dfa[10][10];
char c[10],
string[10];int
main()
{
int nstates,
nfinals;int
f[10];
int i, j, s = 0, final = 0;
printf("enter the number of states that your dfa consist
of \n");scanf("%d", &nstates);
printf("enter the number of input symbol that dfa
have \n");scanf("%d", &ninputs);
printf("\n enter input
symbols\t");for (i = 0; i <
ninputs; i++)
5|Page
Compiler Design (3170701) 190090107055

{
printf("\n\n %d input\t",
i + 1);printf("%c", c[i] =
getch());
}
printf("\n\n enter number of final
states\t");scanf("%d", &nfinals);
or (i = 0; i < nfinals; i++)
{
printf("\n\n Final state %d : q",
i + 1);scanf("%d", &f[i]);
}
printf(" ");
printf("\n\ndefine transition rule as (initial state, input symbol ) = final
state\n");for (i = 0; i < ninputs; i++)
{
for (j = 0; j < nstates; j++)
{
printf("\n(q%d , %c ) = q", j, c[i]);
scanf("%d", &dfa[i][j]);
}
}
do
{
i = 0;
printf("\n\n Enter Input
String.. ");scanf("%s",
string);
while (string[i] != '\0')
if ((s = check(string[i++],
s)) < 0)break;
for (i = 0; i <
nfinals; i++)if (f[i]
== s)
6|Page
Compiler Design (3170701) 190090107055

final = 1;
if (final == 1)
printf("\n valid string");
else
printf("invalid
string");getch();
printf("\n Do you want to continue.? \n(y/n) ");
}
while (getch() == 'y');

getch();

}
int check(char b, int d)
{
int j;
for (j = 0; j <
ninputs; j++)if (b ==
c[j])
return
(dfa[d][j]);
return -1;
}

7|Page
Compiler Design (3170701) 190090107055

• Output:

8|Page
Compiler Design (3170701) 190090107055

Practical 3
Implement generic DFA to recognize any regular any regular
expression and perform string validation.

• What is LEX tool?

o Lex is a program that generates lexical analyzer. It is used with YACC parser generator.
o The lexical analyzer is a program that transforms an input stream into a sequence of tokens.
o It reads the input stream and produces the source code as output through implementing the
lexical analyzer in the C program.

• The functions of LEX are follows:

o Firstly, lexical analyzer creates a program lex. l in the Lex language. Then Lex compiler
runs the lex. l program and produces a C program lex.yy.c.
o Finally, C compiler runs the lex.yy.c program and produces an object program a.out.
o a.out is lexical analyzer that transforms an input stream into a sequence of tokens.

• Importance of LEX tool:

o Lex is a lexical analysis tool that can be used to identify specific text strings in a structured
way from source text. Yacc is a grammar parser; it reads text and can be used to turn a
sequence of words into a structured format for processing.

• Use of LEX tool:

9|Page
Compiler Design (3170701) 190090107055

o lex.l is an a input file written in a language which describes the generation of lexical
analyzer. The lex compiler transforms lex.l to a C program known as lex.yy.c.
o lex.yy.c is compiled by the C compiler to a file called a.out.
o The output of C compiler is the working lexical analyzer which takes stream of input
characters and produces a stream of tokens.
o yylval is a global variable which is shared by lexical analyzer and parser to return the name
and an attribute value of token.
o The attribute value can be numeric code, pointer to symbol table or nothing.
o Another tool for lexical analyzer generation is Flex.

• Structure of LEX program:

Lex program will be in following form

declarations
%%
Translation rules
%%
auxiliary functions
10 | P a g e
Compiler Design (3170701) 190090107055

• Declarations: This section includes declaration of variables, constants and regular


definitions.
• Translation rules: It contains regular expressions and code segments.
Form: Pattern {Action}
Pattern is a regular expression or regular definition.
Action refers to segments of code.
• Auxiliary functions: This section holds additional functions which are used in actions.
These functions are compiled separately and loaded with lexical analyzer.
Lexical analyzer produced by lex starts its process by reading one character at a time until
a valid match for a pattern is found.
Once a match is found, the associated action takes place to produce token.
The token is then given to parser for further processing.

• Conflict resolution in lex tool:

Conflict arises when several prefixes of input matches one or more patterns. This can be
resolved by the following:
o Always prefer a longer prefix than a shorter prefix.
o If two or more patterns are matched for the longest prefix, then the first pattern listed
in lex program is preferred.

• Lookahead Operators:

o Lookahead operator is the additional operator that is read by lex in order to distinguish
additional pattern for a token.
o Lexical analyzer is used to read one character ahead of valid lexeme and then retracts to
produce token.
o At times, it is needed to have certain characters at the end of input to match with a pattern.

11 | P a g e
Compiler Design (3170701) 190090107055

Regular Meaning
Expression
* Matches with zero or more occurrences of preceding expressions.
For example, 1* occurrence of 1 for any number of times.
. Matches any single character other than new line character.
[] A character class which matches any character within the bracket.
For example, [a-z] matches with any alphabet in lower case.
() Group of regular expressions together put into a new regular
expression.
““ The string written in quotes matches literally. For example,
“Hanumaan” matches with the string Hanumaan.
$ Matches with the end of line as last character.
+ Matches with one or more occurrences of preceding expression.
For example, [0 – 9] + any number but not empty string.
? Matches zero or one occurrence of preceding regular expression.
For example, [+ -] ? [0 – 9] + a number with unary operator.
^ Matches the beginning of a line as first character.
[^] Used as for negation. For example, [^verb] means except verb
match with anything else.
\ Used as escape metacharacter.
For example, \n is a new line character.
\# prints the # literally
| To represent the or i.e. another alternative.
For example, a | b means match with either a or b.

• LEX Actions:

There are various LEX actions that can be used for ease of programming using LEX tool.

1. BEGIN – It indicates the start state. The lexical analyzer starts at state 0.

2. ECHO – It emits the input as it is.

12 | P a g e
Compiler Design (3170701) 190090107055

3. yytext – When laxer matches or recognize the token from input token then the lexeme is
stored in a null terminated string called yytext.
As soon as new token is found the contents of yytext are replaced bt new token.

4. yylex() – This is an important function. As soon as call to yytext() is encountered scanner


starts scanning the source program.

5. yywrap() – The function yywrap() is called when scanner encounters end of file. If yywrap()
returns 0 then scanner continues scanning. When yywrap() returns 1 that means end of file is
encountered.

6. yyin – It is the standard input file that stores input source program.

7. yyleng – When a laxer recognize token then the lexeme is stored in a null terminated string
called yytext. And yyleng stores the length or number of characters in input string. The value
in yyleng is same as strlen() functions.

8. How to write main() in LEX?

The main() can be written as


void main
{
yylex();
}
Or it can be written with command line parameters such as argc and srgv. If command line
parameters are passed to the main then while executing the program we give input source file
name.
For example – if the source program which is to be scanned is x.c then
#./a.out x.c
Will scan the input source x.c.

9. Where to write C code –

13 | P a g e
Compiler Design (3170701) 190090107055

o We can write a valid ‘C’ code between


%{%}
o We can write any C function in a subroutine section.
o We can write valid C code in the action part for corresponding regular expression.

We have to construct recognizer that looks for the lexemes stored in the input buffer.
It works using these two rules -
1. If more than one pattern matches then recognizer has to choose the longest lexeme matched.
2. If there are two or more pattern that match the longest lexeme, the first listed matching
pattern is chosen.

• Using Command Line Parameters

o The command line parameters that are appearing on the shell prompt.
o The command line interface is the interface which allows the user to interact with the
computer by typing the commands.
o In C we can pass these parameters to the main function to the form of character array.

For example:
$ cp abc.txt pqr.txt
Here
argv[0] = cp
argv[1] = abc.txt
argv[2] = pqr.txt

As there are three such parameters that are present at the command line interface argc value
will be 3.

• Design of lexical analyzer:

o Lexical analyzer can either be generated by NFA or by DFA.


o DFA is preferable in the implementation of lex.

14 | P a g e
Compiler Design (3170701) 190090107055

• Structure of generated analyzer:

o Architecture of lexical analyzer generated by lex is given in fig.

• Lexical analyzer program includes:

o Program to simulate automata.


o Components created from lex program by lex itself which are listed as follows:
➢ A transition table for automaton.
➢ Functions that are passed directly through lex to the output.
➢ Actions from input program (fragments of code) which are invoked by automation
simulator when needed.

LEX Program Tool:

1. Lex Program to accept string starting with vowel

• CODE:

%{
int flag = 0;
%}

%%

15 | P a g e
Compiler Design (3170701) 190090107055

[aeiouAEIOU].[a-zA-Z0-9.]+ flag=1;[a-zA-Z0-9]+

%%

main()
{
yylex();
if (flag == 1) printf("Accepted");
else
printf("Not Accepted");
}

2. Lex program to count number of words.

• CODE:

%{
#include<stdio.h>#include<string.h> inti = 0;
%}

/* Rules Section*/
%%
([a-zA-Z0-9])* {i++;} /* Rule for counting
number of words*/

"\n" {printf("%d\n", i); i = 0;}


%%

int yywrap(void){}int main()


{
//Thefunctionthatstartstheanalysisyylex();

return 0;
}

3. Lex program to count noof lines,words ,digits,small letters, capital


letters and special characters.

• CODE:

%{
#include<stdio.h>
int lines=0, words=0,s_letters=0,c_letters=0, num=0, spl_char=0,total=0;
%}
16 | P a g e
Compiler Design (3170701) 190090107055

%%
\n { lines++; words++;}[\t ' ']words++;
[A-Z]
c_letters++; [a-z]s_letters++; [0-9]num++;
. spl_char++;
%%
int main()
{
yyin= fopen("test.txt","r");yylex();
total=s_letters+c_letters+num+spl_char;

printf(" This File contains ..."); printf("\n\t%d lines", lines); printf("\n\t%d words",words);
printf("\n\t%d small letters", s_letters); printf("\n\t%d capital letters",c_letters);printf("\n\t%d
digits", num);
printf("\n\t%d special characters",spl_char);printf("\n\tIn total %d characters..\n",total);
}
int yywrap(void){}

4. Lex program to convert lowercase to uppercase.

• CODE:

lower [a-z]CAPS [A-Z]


space [ \t\n]

%%
{lower} {printf("%c",yytext[0]- 32);}
{CAPS} {printf("%c",yytext[0]+ 32);}
{space} ECHO;
. ECHO;
%%

main()
{
yylex();

}
int yywrap(void){}

17 | P a g e
Compiler Design (3170701) 190090107055

Practical 4
Implement the following programs using Lex.
A. Create a program to take input from a text file and count no
of characters, no. of lines & no. of words.
B. Count the number of vowels and consonants in a given input
string.
C. Print only numbers from the given file.
D. Convert Roman to Decimal
E. Print all HTML tags from the given file.
F. Add line numbers to the given file and display them on the
standard output.
G. Count the number of comment lines in a given C program.
H. Eliminate comments from a given C program and create a
separate file without comments.
I. Generate Histogram of Words
J. Caesar Cypher
K. Check weather given statement is compound or simple

A. Create a program to take input from a text file and count no


of characters, no. of lines & no. of words.

• Code:

%
{
#include<studio.h> int n_chars=0;
int n_lines=0; int n_words = 0;
%}

%%

\n {n_chars++;n_lines++;}
[^ \n\t]+ {n_words++, n_chars=n_chars+yyleng;}

18 | P a g e
Compiler Design (3170701) 190090107055

. {n_chars++;}

%%

int yywrap(){}
int main(int argc[],char *argv[])
{
yyin=fopen("c:\\practical.txt", "r");
yylex();
printf("no of characters: %d",n_chars); printf("\n");
printf("no of lines: %d",n_lines); printf("\n");
printf("no of words: %d",n_words); printf("\n");
return 0;
}

• Text File:

19 | P a g e
Compiler Design (3170701) 190090107055

• Output:

B. Count the number of vowels and consonants in a given input


string.

• Code:

%
{
int vow_count=0; int const_count =0;
%}

%%
[aeiouAEIOU] {vow_count++;} [a-zA-Z] {const_count++;}
%%
int yywrap(){} int main()
{
printf("Enter the string of vowels and consonants:"); yylex();
printf("Number of vowels are: %d\n", vow_count); printf("Number of consonants are: %d\n",
const_count); return 0;
}

20 | P a g e
Compiler Design (3170701) 190090107055

• Output:

C. Print only numbers from the given file.

• Code:

%
{
#include<stdio.h> int num_count=0;
%}

num [0-9]+

%%
{num} {num_count++; printf("%s",yytext);
}
%%
int yywrap(void){} int main()
{
yyin = fopen("c:\\practical.txt", "r");
yylex();
printf("\nTotal of numbers: %d",num_count);
}

21 | P a g e
Compiler Design (3170701) 190090107055

• Text File:

• Output:

22 | P a g e
Compiler Design (3170701) 190090107055

E. Print all HTML tags from the given file.

• Code:

%{
%}

%%
"<"[^>]*> {printf("%s\n", yytext); } /* if anything enclosed in
these < > occur print text*/
. ; // else do nothing
%%

int yywrap(){}

int main(int argc, char*argv[])


{
// Open tags.txt in read mode
extern FILE *yyin = fopen("tags.txt","r");

// The function that starts the analysis


yylex();

return 0;
}

• Output:

23 | P a g e
Compiler Design (3170701) 190090107055

F. Add line numbers to the given file and display them on the
standard output.

• Code:

%
{
int line_number = 1;

line .*\n

%%
{line} { printf("%10d %s", line_number++, yytext); }

%%

int yywrap(){}

int main(int argc, char*argv[])


{
extern FILE *yyin;

yyin = fopen("c:\\practical.txt", "r");


yylex();
24 | P a g e
Compiler Design (3170701) 190090107055

• Text File:

• Output:

25 | P a g e
Compiler Design (3170701) 190090107055

G. Count the number of comment lines in a given C program.

• Code:

%{#include<stdio.h>
int count = 0;
%}

%x C
%%
"/*"][.]*"*/" {count++;}
"/*" {BEGIN C;}
<C>"*/" {BEGIN 0; count++;}
<C>\n {;}
<C>. {;}
\/\/.* {count++;}
%%

void main()
{
char file[] = "data.c";
yyin = fopen("c:\\practical.txt", "r");
yylex();
printf("Number of comment lines in c file %s is %d\n", file, count);
}

int yywrap()
{
return 1;
}

26 | P a g e
Compiler Design (3170701) 190090107055

• Text File:

• Output:

27 | P a g e
Compiler Design (3170701) 190090107055

H. Eliminate comments from a given C program and create a


separate file without comments.

• Code:

%
{
#include<stdio.h>
%}

%%

\/\/(.*) {};

\/\*(.*\n)*.*\*\/ {};
%%

int yywrap()
{
return 1;
}

int main()
{
yyin=fopen("c:\\practical.txt", "r");
yyout=fopen("C:\\out.c","w");

yylex();
return 0;
}

28 | P a g e
Compiler Design (3170701) 190090107055

• Output:

I. Generate Histogram of Words

• Code:

%
{
#include<stdio.h>
#include<string.h>

char word [] = "geeks";


int count = 0;

29 | P a g e
Compiler Design (3170701) 190090107055

%}

%%
[a-zA-Z]+ { if(strcmp(yytext, word)==0)
count++; }
. ;
%%

int yywrap()
{
return 1;
}

int main()
{
extern FILE *yyin, *yyout;

yyin=fopen("input.txt", "r");
yylex();

printf("%d", count);
}

• Output:

30 | P a g e
Compiler Design (3170701) 190090107055

J. Caesar Cypher

• Code:

%%
[a-z] {char ch = yytext[0];
ch += 3;
if (ch> 'z') ch -= ('z'+1- 'a');
printf ("%c" ,ch );
}
[A-Z] { char ch = yytext[0] ;
ch += 3;
if (ch> 'Z') ch -= ('Z'+1- 'A');
printf("%c",ch);
}
%%

• Output:

31 | P a g e
Compiler Design (3170701) 190090107055

K. Check weather given statement is compound or simple

• Code:

%{
#include<stdio.h>
int flag=0;
%}

%%
and |
or |
but |
because |
if |
then |
nevertheless { flag=1; }
. ;
\n { return 0; }
%%

int main()
{
printf("Enter the sentence:\n");
yylex();
if(flag==0)
printf("Simple sentence\n");
else
printf("compound sentence\n");
}

int yywrap( )
{
32 | P a g e
Compiler Design (3170701) 190090107055

return 1;
}

• Output:

33 | P a g e
Compiler Design (3170701) 190090107055

Practical 5
Write a C program to find FIRST and FOLLOW of specific
grammar.
Input: The string consists of grammar symbols.
Output: The First and Follow set for a given string. Explanation:
The student has to assume a typical grammar. The program when
run will ask for the string to be entered. The program will find
the First and Follow set of the
given string.

• Code:

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

char a[8][8];
int n=5 ; struct firTab
{
int n;
char firT[5];
};
struct folTab
{
int n;
char folT[5];
};
struct folTab follow[5]; struct firTab first[5]; int col;
void findFirst(char,char); void findFollow(char,char);
void folTabOperation(char,char); void firTabOperation(char,char); void main()
{
int i,j,c=0,cnt=0; char ip;
char b[8];
printf("\n\t\t======FIRST AND FOLLOW SET====== \n\nEnter Production Amount : ");
scanf("%d",&n);
printf("\n\tenter %d productions in format E->T+G\n",n); printf("\t \n");
for(i=0; i<n; i++)
{
scanf("%s",&a[i]);
}
for(i=0; i<n; i++)
{ c=0;
for(j=0; j<i+1; j++)
{
if(a[i][0] == b[j])
34 | P a g e
Compiler Design (3170701) 190090107055

c=1;
break;
}
}
if(c !=1)
{
b[cnt] = a[i][0]; cnt++;
}

}
printf("\n");

for(i=0; i<cnt; i++)


{
col=1; first[i].firT[0] = b[i]; first[i].n=0; findFirst(b[i],i);
}
for(i=0; i<cnt; i++)
{
col=1; follow[i].folT[0] = b[i]; follow[i].n=0; findFollow(b[i],i);
}

printf("\n"); for(i=0; i<cnt; i++)


{
for(j=0; j<=first[i].n; j++)
{
if(j==0)
{
printf("First(%c) : {",first[i].firT[j]);
}
else
{
printf(" %c",first[i].firT[j]);
}
}
printf(" } ");
printf("\n");
}
printf("\n"); for(i=0; i<cnt; i++)
{

for(j=0; j<=follow[i].n; j++)


{
if(j==0)
{
printf("Follow(%c) : {",follow[i].folT[j]);
}
else
{
35 | P a g e
Compiler Design (3170701) 190090107055

printf(" %c",follow[i].folT[j]);
}
}
printf(" } ");

printf("\n");
}

}
void findFirst(char ip,char pos)
{
int i;
for(i=0; i<n; i++)
{
if(ip == a[i][0])
{
if(isupper(a[i][3]))
{
findFirst(a[i][3],pos);
}
else
{

first[pos].firT[col]=a[i][3]; first[pos].n++;
col++;
}
}
}
}
void findFollow(char ip,char row)
{
int i,j;
if(row==0 && col==1)
{
follow[row].folT[col]= '$'; col++;
follow[row].n++;
}
for(i=0; i<n; i++)

{
for(j=3; j<7; j++)
{
if(a[i][j] == ip)
{
if(a[i][j+1] == '\0')
{
if(a[i][j] != a[i][0])
{
folTabOperation(a[i][0],row);
}
36 | P a g e
Compiler Design (3170701) 190090107055

}
else if(isupper(a[i][j+1]))
{
if(a[i][j+1] != a[i][0])
{
firTabOperation(a[i][j+1],row);

}
}
else
{
follow[row].folT[col] = a[i][j+1]; col++;
follow[row].n++;
}
}
}
}
}
void folTabOperation(char ip,char row)
{
int i,j;
for(i=0; i<5; i++)
{
if(ip == follow[i].folT[0])
{
for(j=1; j<=follow[i].n; j++)
{
follow[row].folT[col] = follow[i].folT[j]; col++;
follow[row].n++;
}
}
}
}

void firTabOperation(char ip,char row)


{
int i,j;
for(i=0; i<5; i++)
{
if(ip == first[i].firT[0])
{
for(j=1; j<=first[i].n; j++)
{
if(first[i].firT[j] != '0')
{
follow[row].folT[col] = first[i].firT[j]; follow[row].n++;
col++;
}
else
{
37 | P a g e
Compiler Design (3170701) 190090107055

folTabOperation(ip,row);
}
}
}
}
}

• Output:

38 | P a g e
Compiler Design (3170701) 190090107055

Practical 6
Write a C program for constructing LL (1) parsing using FIRST
and FOLLOW generated in the above program.

• Code:

#include<stdio.h>
#include<string.h>
#define TSIZE 128
// table[i][j] stores
// the index of production that must be applied on
// ith varible if the input is
// jth nonterminal
int table[100][TSIZE];
// stores all list of terminals
// the ASCII value if use to index terminals
// terminal[i] = 1 means the character with
// ASCII value is a terminal
char terminal[TSIZE];
// stores all list of terminals
// only Upper case letters from 'A' to 'Z'
// can be nonterminals
// nonterminal[i] means ith alphabet is present as
// nonterminal is the grammar
char nonterminal[26];
// structure to hold each production
// str[] stores the production
// len is the length of production
struct product {
char str[100];
int len;
}pro[20];
// no of productions in form A->ß
int no_pro;
char first[26][TSIZE];
char follow[26][TSIZE];
// stores first of each production in form A->ß
char first_rhs[100][TSIZE];
// check if the symbol is nonterminal

39 | P a g e
Compiler Design (3170701) 190090107055

int isNT(char c) {
return c >= 'A' && c <= 'Z';
}
// reading data from the file
void readFromFile() {
FILE* fptr;
fptr = fopen("text.txt", "r");
char buffer[255];
int i;
int j;
while (fgets(buffer, sizeof(buffer), fptr)) {
printf("%s", buffer);
j = 0;
nonterminal[buffer[0] - 'A'] = 1;
for (i = 0; i < strlen(buffer) - 1; ++i) {
if (buffer[i] == '|') {
++no_pro;
pro[no_pro - 1].str[j] = '\0';
pro[no_pro - 1].len = j;
pro[no_pro].str[0] = pro[no_pro - 1].str[0];
pro[no_pro].str[1] = pro[no_pro - 1].str[1];
pro[no_pro].str[2] = pro[no_pro - 1].str[2];
j = 3;
}
else {
pro[no_pro].str[j] = buffer[i];
++j;
if (!isNT(buffer[i]) && buffer[i] != '-' && buffer[i] != '>') {
terminal[buffer[i]] = 1;
}
}
}
pro[no_pro].len = j;
++no_pro;
}
}
void add_FIRST_A_to_FOLLOW_B(char A, char B) {
int i;
for (i = 0; i < TSIZE; ++i) {
if (i != '^')
follow[B - 'A'][i] = follow[B - 'A'][i] || first[A - 'A'][i];
}

40 | P a g e
Compiler Design (3170701) 190090107055

}
void add_FOLLOW_A_to_FOLLOW_B(char A, char B) {
int i;
for (i = 0; i < TSIZE; ++i) {
if (i != '^')
follow[B - 'A'][i] = follow[B - 'A'][i] || follow[A - 'A'][i];
}
}
void FOLLOW() {
int t = 0;
int i, j, k, x;
while (t++ < no_pro) {
for (k = 0; k < 26; ++k) {
if (!nonterminal[k]) continue;
char nt = k + 'A';
for (i = 0; i < no_pro; ++i) {
for (j = 3; j < pro[i].len; ++j) {
if (nt == pro[i].str[j]) {
for (x = j + 1; x < pro[i].len; ++x) {
char sc = pro[i].str[x];
if (isNT(sc)) {
add_FIRST_A_to_FOLLOW_B(sc, nt);
if (first[sc - 'A']['^'])
continue;
}
else {
follow[nt - 'A'][sc] = 1;
}
break;
}
if (x == pro[i].len)
add_FOLLOW_A_to_FOLLOW_B(pro[i].str[0], nt);
}
}
}
}
}
}
void add_FIRST_A_to_FIRST_B(char A, char B) {
int i;
for (i = 0; i < TSIZE; ++i) {
if (i != '^') {

41 | P a g e
Compiler Design (3170701) 190090107055

first[B - 'A'][i] = first[A - 'A'][i] || first[B - 'A'][i];


}
}
}
void FIRST() {
int i, j;
int t = 0;
while (t < no_pro) {
for (i = 0; i < no_pro; ++i) {
for (j = 3; j < pro[i].len; ++j) {
char sc = pro[i].str[j];
if (isNT(sc)) {
add_FIRST_A_to_FIRST_B(sc, pro[i].str[0]);
if (first[sc - 'A']['^'])
continue;
}
else {
first[pro[i].str[0] - 'A'][sc] = 1;
}
break;
}
if (j == pro[i].len)
first[pro[i].str[0] - 'A']['^'] = 1;
}
++t;
}
}
void add_FIRST_A_to_FIRST_RHS__B(char A, int B) {
int i;
for (i = 0; i < TSIZE; ++i) {
if (i != '^')
first_rhs[B][i] = first[A - 'A'][i] || first_rhs[B][i];
}
}
// Calculates FIRST(ß) for each A->ß
void FIRST_RHS() {
int i, j;
int t = 0;
while (t < no_pro) {
for (i = 0; i < no_pro; ++i) {
for (j = 3; j < pro[i].len; ++j) {
char sc = pro[i].str[j];

42 | P a g e
Compiler Design (3170701) 190090107055

if (isNT(sc)) {
add_FIRST_A_to_FIRST_RHS__B(sc, i);
if (first[sc - 'A']['^'])
continue;
}
else {
first_rhs[i][sc] = 1;
}
break;
}
if (j == pro[i].len)
first_rhs[i]['^'] = 1;
}
++t;
}
}
int main() {
readFromFile();
follow[pro[0].str[0] - 'A']['$'] = 1;
FIRST();
FOLLOW();
FIRST_RHS();
int i, j, k;

// display first of each variable


printf("\n");
for (i = 0; i < no_pro; ++i) {
if (i == 0 || (pro[i - 1].str[0] != pro[i].str[0])) {
char c = pro[i].str[0];
printf("FIRST OF %c: ", c);
for (j = 0; j < TSIZE; ++j) {
if (first[c - 'A'][j]) {
printf("%c ", j);
}
}
printf("\n");
}
}

// display follow of each variable


printf("\n");
for (i = 0; i < no_pro; ++i) {

43 | P a g e
Compiler Design (3170701) 190090107055

if (i == 0 || (pro[i - 1].str[0] != pro[i].str[0])) {


char c = pro[i].str[0];
printf("FOLLOW OF %c: ", c);
for (j = 0; j < TSIZE; ++j) {
if (follow[c - 'A'][j]) {
printf("%c ", j);
}
}
printf("\n");
}
}
// display first of each variable ß
// in form A->ß
printf("\n");
for (i = 0; i < no_pro; ++i) {
printf("FIRST OF %s: ", pro[i].str);
for (j = 0; j < TSIZE; ++j) {
if (first_rhs[i][j]) {
printf("%c ", j);
}
}
printf("\n");
}

// the parse table contains '$'


// set terminal['$'] = 1
// to include '$' in the parse table
terminal['$'] = 1;

// the parse table do not read '^'


// as input
// so we set terminal['^'] = 0
// to remove '^' from terminals
terminal['^'] = 0;

// printing parse table


printf("\n");
printf("\n\t**************** LL(1) PARSING TABLE *******************\n");
printf("\t--------------------------------------------------------\n");
printf("%-10s", "");
for (i = 0; i < TSIZE; ++i) {
if (terminal[i]) printf("%-10c", i);

44 | P a g e
Compiler Design (3170701) 190090107055

}
printf("\n");
int p = 0;
for (i = 0; i < no_pro; ++i) {
if (i != 0 && (pro[i].str[0] != pro[i - 1].str[0]))
p = p + 1;
for (j = 0; j < TSIZE; ++j) {
if (first_rhs[i][j] && j != '^') {
table[p][j] = i + 1;
}
else if (first_rhs[i]['^']) {
for (k = 0; k < TSIZE; ++k) {
if (follow[pro[i].str[0] - 'A'][k]) {
table[p][k] = i + 1;
}
}
}
}
}
k = 0;
for (i = 0; i < no_pro; ++i) {
if (i == 0 || (pro[i - 1].str[0] != pro[i].str[0])) {
printf("%-10c", pro[i].str[0]);
for (j = 0; j < TSIZE; ++j) {
if (table[k][j]) {
printf("%-10s", pro[table[k][j] - 1].str);
}
else if (terminal[j]) {
printf("%-10s", "");
}
}
++k;
printf("\n");
}
}
}

45 | P a g e
Compiler Design (3170701) 190090107055

• Text File:

• Output:

46 | P a g e
Compiler Design (3170701) 190090107055

Practical 7
Implementation of Recursive Descent Parser without
backtracking
Input: The string to be parsed.
Output: Whether string parsed successfully or not.

• Code:

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

charinput[10];
int i,
error;
void E();
void T();
void Eprime();
void Tprime();
void F();

main()
{
printf("\nRecursivedescentparsingfor thefollowinggrammar\n");
printf("\nE -> E+T |T\nT -> T*F |F\nF -> (E) |id\n");
i = 0;
error = 0;
printf("\nEnteranarithmeticexpression : ");//Eg:a+a*a gets(input);
E();
if (strlen(input) == i && error == 0)
printf("\nParsing Successful..!!!\n");
else
printf("\nError..!!!\n");

47 | P a g e
Compiler Design (3170701) 190090107055

void E()
{
T();
Eprime();
}
void Eprime()
{
if (input[i] == '+')
{
i++;
T();
Eprime();
}
}
void T()
{
F();
Tprime();
}
void Tprime()
{
if (input[i] == '*')
{
i++; F();
Tprime();
}
}
void F()
{
if (isalnum(input[i])) i++;
else if (input[i] == '(')

48 | P a g e
Compiler Design (3170701) 190090107055

{
i++; E();
if(input[i] ==')') i++;

else
error = 1;
}

else
error = 1;
}

Output:

49 | P a g e
Compiler Design (3170701) 190090107055

Practical 8
Write a C program to implement operator precedence parsing.

• Code:

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

char *input;
int i=0;
char lasthandle[6],stack[50],handles[][5]={")E(","E*E","E+E","i","E^E"};
//(E) becomes )E( when pushed to stack

int top=0,l;
char prec[9][9]={

/*input*/

/*stack + - * / ^ i ( ) $ */

/* + */ '>', '>','<','<','<','<','<','>','>',

/* - */ '>', '>','<','<','<','<','<','>','>',

/* * */ '>', '>','>','>','<','<','<','>','>',

/* / */ '>', '>','>','>','<','<','<','>','>',

/* ^ */ '>', '>','>','>','<','<','<','>','>',

/* i */ '>', '>','>','>','>','e','e','>','>',

50 | P a g e
Compiler Design (3170701) 190090107055

/* ( */ '<', '<','<','<','<','<','<','>','e',

/* ) */ '>', '>','>','>','>','e','e','>','>',

/* $ */ '<', '<','<','<','<','<','<','<','>',

};

int getindex(char c)
{
switch(c)
{
case '+':return 0;
case '-':return 1;
case '*':return 2;
case '/':return 3;
case '^':return 4;
case 'i':return 5;
case '(':return 6;
case ')':return 7;
case '$':return 8;
}
}

int shift()
{
stack[++top]=*(input+i++);
stack[top+1]='\0';
}

int reduce()

51 | P a g e
Compiler Design (3170701) 190090107055

{
int i,len,found,t;
for(i=0;i<5;i++)//selecting handles
{
len=strlen(handles[i]);
if(stack[top]==handles[i][0]&&top+1>=len)
{
found=1;
for(t=0;t<len;t++)
{
if(stack[top-t]!=handles[i][t])
{
found=0;
break;
}
}
if(found==1)
{
stack[top-t+1]='E';
top=top-t+1;
strcpy(lasthandle,handles[i]);
stack[top+1]='\0';
return 1;//successful reduction
}
}
}
return 0;
}

void dispstack()
{

52 | P a g e
Compiler Design (3170701) 190090107055

int j;
for(j=0;j<=top;j++)
printf("%c",stack[j]);
}

void dispinput()
{
int j;
for(j=i;j<l;j++)
printf("%c",*(input+j));
}

void main()
{
int j;

input=(char*)malloc(50*sizeof(char));
printf("\nEnter the string\n");
scanf("%s",input);
input=strcat(input,"$");
l=strlen(input);
strcpy(stack,"$");
printf("\nSTACK\tINPUT\tACTION");
while(i<=l)
{
shift();
printf("\n");
dispstack();
printf("\t");

53 | P a g e
Compiler Design (3170701) 190090107055

dispinput();
printf("\tShift");
if(prec[getindex(stack[top])][getindex(input[i])]=='>')
{
while(reduce())
{
printf("\n");
dispstack();
printf("\t");
dispinput();
printf("\tReduced: E->%s",lasthandle);
}
}
}

if(strcmp(stack,"$E$")==0)
printf("\nAccepted;");
else
printf("\nNot Accepted;");
}

54 | P a g e
Compiler Design (3170701) 190090107055

• Output:

55 | P a g e
Compiler Design (3170701) 190090107055

Practical 9
Implement a C program to implement LALR parsing.

• Code:

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
void push(char *, int *, char);
char stacktop(char *);
void isproduct(char, char);
int ister(char);
int isnter(char);
int isstate(char);
void error();
void isreduce(char, char); char pop(char *, int *);
void printt(char *, int *, char[], int); void rep(char[], int);
struct action
{
char row[6][5];
};
const struct action A[12] = {
{"sf", "emp", "emp", "se", "emp", "emp"},
{"emp", "sg", "emp", "emp", "emp", "acc"},
{"emp", "rc", "sh", "emp", "rc", "rc"},
{"emp", "re", "re", "emp", "re", "re"},
{"sf", "emp", "emp", "se", "emp", "emp"},
{"emp", "rg", "rg", "emp", "rg", "rg"},
{"sf", "emp", "emp", "se", "emp", "emp"},
{"sf", "emp", "emp", "se", "emp", "emp"},
{"emp", "sg", "emp", "emp", "sl", "emp"},

56 | P a g e
Compiler Design (3170701) 190090107055

{"emp", "rb", "sh", "emp", "rb", "rb"},


{"emp", "rb", "rd", "emp", "rd", "rd"},
{"emp", "rf", "rf", "emp", "rf", "rf"}}; struct gotol
{
char r[3][4];
};
const struct gotol G[12] = {
{"b", "c", "d"},
{"emp", "emp", "emp"},
{"emp", "emp", "emp"},
{"emp", "emp", "emp"},
{"i", "c", "d"},
{"emp", "emp", "emp"},

{"emp", "j", "d"},


{"emp", "emp", "k"},
{"emp", "emp", "emp"},
{"emp", "emp", "emp"},
};
char ter[6] = {'i', '+', '*', ')', '(', '$'};
char nter[3] = {'E', 'T', 'F'}; char
states[12] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'm', 'j', 'k', 'l'};
char stack[100]; int top = -1; char temp[10]; struct grammar
{
char left; char right[5];
};
const struct grammar rl[6] = {
{'E', "e+T"},
{'E', "T"},
{'T', "T*F"},
{'T', "F"},
{'F', "(E)"},
{'F', "i"},

57 | P a g e
Compiler Design (3170701) 190090107055

};
void main()
{
char inp[80], x, p, dl[80], y, bl = 'a'; int i = 0, j, k, l, n, m, c, len;
printf(" Enter the input :"); scanf("%s", inp);
len = strlen(inp); inp[len] = '$';
inp[len + 1] = '\0'; push(stack, &top, bl); printf("\n stack \t\t\t input"); printt(stack, &top, inp,
i);
do
{
x = inp[i];
p = stacktop(stack); isproduct(x, p);
if (strcmp(temp, "emp") == 0) error();
if (strcmp(temp, "acc") == 0) break;
else
{

if (temp[0] == 's')
{
push(stack, &top, inp[i]); push(stack, &top, temp[1]); i++;
}
else
{
if (temp[0] == 'r')
{
j = isstate(temp[1]); strcpy(temp, rl[j - 2].right); dl[0] = rl[j - 2].left;
dl[1] = '\0';
n = strlen(temp);
for (k = 0; k < 2 * n; k++) pop(stack, &top);
for (m = 0; dl[m] != '\0'; m++)
push(stack, &top, dl[m]); l = top;
y = stack[l - 1]; isreduce(y, dl[0]);
for (m = 0; temp[m] != '\0'; m++) push(stack, &top, temp[m]);

58 | P a g e
Compiler Design (3170701) 190090107055

}
}
}
printt(stack, &top, inp, i);
} while (inp[i] != '\0');
if (strcmp(temp, "acc") == 0) printf(" \n accept the input "); else
printf(" \n do not accept the input "); getch();
}
void push(char *s, int *sp, char item)
{
if (*sp == 100) printf(" stack is full "); else
{
*sp = *sp + 1; s[*sp] = item;
}
}
char stacktop(char *s)
{
char i;

i = s[top]; return i;
}
void isproduct(char x, char p)
{
int k, l;
k = ister(x);
l = isstate(p);
strcpy(temp, A[l - 1].row[k - 1]);
}
int ister(char x)
{
int i;
for (i = 0; i < 6; i++) if (x == ter[i]) return i + 1;
return 0;

59 | P a g e
Compiler Design (3170701) 190090107055

}
int isnter(char x)
{
int i;
for (i = 0; i < 3; i++) if (x == nter[i]) return i + 1;
return 0;
}
int isstate(char p)
{
int i;
for (i = 0; i < 12; i++) if (p == states[i]) return i + 1;
return 0;
}
void error()
{
printf(" error in the input "); exit(0);
}
void isreduce(char x, char p)
{
int k, l;
k = isstate(x); l = isnter(p);
strcpy(temp, G[k - 1].r[l - 1]);
}
char pop(char *s, int *sp)
{

char item;
if (*sp == -1)
printf(" stack is empty "); else
{
item = s[*sp];
*sp = *sp - 1;
}

60 | P a g e
Compiler Design (3170701) 190090107055

return item;
}
void printt(char *t, int *p, char inp[], int i)
{
int r; printf("\n");
for (r = 0; r <= *p; r++) rep(t, r); printf("\t\t\t");
for (r = i; inp[r] != '\0'; r++)
printf("%c", inp[r]);
}
void rep(char t[], int r)
{
char c; c = t[r];
switch (c)
{
case 'a': printf("0"); break; case 'b': printf("1"); break; case 'c': printf("2"); break; case 'd':
printf("3"); break; case 'e': printf("4"); break; case 'f': printf("5"); break; case 'g': printf("6");
break; case 'h':

printf("7"); break; case 'm': printf("8"); break; case 'j': printf("9"); break; case 'k':
printf("10"); break;
case 'l': printf("11"); break; default:
printf("%c", t[r]); break;
}
}

61 | P a g e
Compiler Design (3170701) 190090107055

• Output:

62 | P a g e
Compiler Design (3170701) 190090107055

Practical 10
To Study about Yet Another Compiler-Compiler (YACC).

● YACC stands for Yet Another Compiler Compiler.

● YACC provides a tool to produce a parser for a given grammar.

● YACC is a program designed to compile a LALR (1) grammar.

● It is used to produce the source code of the syntactic analyzer of the languageproduced
by LALR (1) grammar.

● The input of YACC is the rule or grammar and the output is a Cprogram.

Input File :

/* definitions */
....
%%
/* rules */
....
%%
/* auxiliary routines */
....

Definition Part:

The definition part includes information about the tokens used in the syntax
definition. Yacc also recognizes single characters as tokens. The definition part can
include C code external to the definition of the parser and variable declarations,
within %{ and %} in the first column.

63 | P a g e
Compiler Design (3170701) 190090107055

Rule Part:

The rules part contains grammar definition in a modified BNF form. Actions is C code in { }
and can be embedded inside (Translation schemes).

Auxiliary Routines Part:

The auxiliary routines part is only C code. It includes function definitions for every function
needed in rules part. It can also contain the main() function definition if the parser is going
to be run as a program. The main() function must call the function yyparse().

YACC input file generally finishes with: .y

Output Files :

The output of YACC is a file named y.tab.c


If it contains the main() definition, it must be compiled to be executable. Otherwise,
the code can be an external function definition for the function int yyparse() .
If called with the –d option in the command line, Yacc produces as output a header file
y.tab.h with all its specific definitions.
If called with the –v option, Yacc produces as output a file y.output containing a textual
description of the LALR(1) parsing table used by the parser. This is useful fortracking down
how the parser solves conflicts

For Compiling YACC Program :

1. Write lex program in a file file.l and yacc in a file file.y


2. Open Terminal and Navigate to the Directory where you have saved thefiles.
3. type lex file.l
4. type yacc file.y
5. type cc lex.yy.c y.tab.h -ll
6. type ./a.out

64 | P a g e
Compiler Design (3170701) 190090107055

Example:

Yacc File (.y):

%{
#include<ctype.h>
#include<stdio.h> #define
YYSTYPE double
}%
%%
Lines : Lines S ‘\n’ { printf(“OK \n”);}
| S ‘\n’
| error ‘\n’ {yyerror(“Error: reenter last line:”);
yyerrok; };
S : ‘(’ S ‘)’
| ‘[‘ S ‘]’
|

%%

#include “lex.yy.c”

Void yyerror(char * s){


Fprintf (stderr, “%s\n”, s);
}

int main(void){
Return yyparse();
}

Lex File (.l):

%{
%}

65 | P a g e
Compiler Design (3170701) 190090107055

%%
[ \t] {}
\n]. { return yytext[0];}
%%

66 | P a g e
Compiler Design (3170701) 190090107055

Practical 11
Create Yacc and Lex specification files to recognizes arithmetic
expressions involving +, -, * and / .

• Code

test.l file:

test.l file:

%option noyywrap %{
#include "stdio.h" #include "test.tab.h" extern int yylval;
%}
%%
[0-9]+ {yylval=atoi(yytext);return number;} \+ { return plus;}
\- { return minus;}
\* { return multiply;}
\/ {return divide;}
. {return yytext[0];} [\t]+;
\n return 0;
%%

test.y file:

%{
#include "stdio.h" int result=0;
void yyerror(const char *str)
{
fprintf(stderr,"error: %s\n",str); } int yywrap(void)
{
return 1;
67 | P a g e
Compiler Design (3170701) 190090107055

}
%}
%token number plus minus divide multiply %left plus minus
%left multiply divide
%right '^'
%nonassoc UMINUS %% ae: exp {result=$1;} ; exp: number { $$ = $1;}
| exp minus exp {$$ = $1 - $3;} | exp plus exp { $$ = $1 + $3;} | exp divide exp { if($3==0)
yyerror("divide by zero"); else $$ = $1 / $3;}
| minus exp %prec UMINUS {$$ = -$2; } | exp multiply exp { $$ = $1 * $3 ;} |exp'^'exp{}
;
%%

#include "math.h" int main(void)


{
yyparse(); printf("=%d",result);
}

• Output

68 | P a g e
Compiler Design (3170701) 190090107055

Practical 12
Generate 3-tuple intermediate code for given infix expression

• Code:

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

void pm();
void plus();
void div();
int i,ch,j,l,addr=100;
char ex[10], exp[10] ,exp1[10],exp2[10],id1[5],op[5],id2[5];
void main()
{
clrscr();
while(1)
{
printf("\n1.assignment\n2.arithmetic\n3.relational\n4.Exit\nEnter the choice:");
scanf("%d",&ch);
switch(ch)
{
case 1:
printf("\nEnter the expression with assignment operator:");
scanf("%s",exp);
l=strlen(exp);
exp2[0]='\0';
i=0;
while(exp[i]!='=')
{
i++;
}

69 | P a g e
Compiler Design (3170701) 190090107055

strncat(exp2,exp,i);
strrev(exp);
exp1[0]='\0';
strncat(exp1,exp,l-(i+1));
strrev(exp1);
printf("Three address code:\ntemp=%s\n%s=temp\n",exp1,exp2);
break;

case 2:
printf("\nEnter the expression with arithmetic operator:");
scanf("%s",ex);
strcpy(exp,ex);
l=strlen(exp);
exp1[0]='\0';

for(i=0;i<l;i++)
{
if(exp[i]=='+'||exp[i]=='-')
{
if(exp[i+2]=='/'||exp[i+2]=='*')
{
pm();
break;
}
else
{
plus();
break;
}
}
else if(exp[i]=='/'||exp[i]=='*')
{
div();

70 | P a g e
Compiler Design (3170701) 190090107055

break;
}
}
break;

case 3:
printf("Enter the expression with relational operator");
scanf("%s%s%s",&id1,&op,&id2);
if(((strcmp(op,"<")==0)||(strcmp(op,">")==0)||(strcmp(op,"<=")==0)||(strcmp(op,">=")==0)||(s
trcmp(op,"==")==0)||(strcmp(op,"!=")==0))==0)
printf("Expression is error");
else
{
printf("\n%d\tif %s%s%s goto %d",addr,id1,op,id2,addr+3);
addr++;
printf("\n%d\t T:=0",addr);
addr++;
printf("\n%d\t goto %d",addr,addr+2);
addr++;
printf("\n%d\t T:=1",addr);
}
break;
case 4:
exit(0);
}
}
}
void pm()
{
strrev(exp);
j=l-i-1;
strncat(exp1,exp,j);
strrev(exp1);

71 | P a g e
Compiler Design (3170701) 190090107055

printf("Three address code:\ntemp=%s\ntemp1=%c%ctemp\n",exp1,exp[j+1],exp[j]);


}
void div()
{
strncat(exp1,exp,i+2);
printf("Three address code:\ntemp=%s\ntemp1=temp%c%c\n",exp1,exp[i+2],exp[i+3]);
}
void plus()
{
strncat(exp1,exp,i+2);
printf("Three address code:\ntemp=%s\ntemp1=temp%c%c\n",exp1,exp[i+2],exp[i+3]);
}

• Output:

72 | P a g e
Compiler Design (3170701) 190090107055

Practical 13
Extract Predecessor and Successor from given Control Flow
Graph.

• Code:

#include <iostream>
using namespace std;

// BST Node
struct Node
{
int key;
struct Node *left, *right;
};

// This function finds predecessor and successor of key in BST.


// It sets pre and suc as predecessor and successor respectively
void findPreSuc(Node* root, Node*& pre, Node*& suc, int key)
{
// Base case
if (root == NULL) return ;

// If key is present at root


if (root->key == key)
{
// the maximum value in left subtree is predecessor
if (root->left != NULL)
{
Node* tmp = root->left;
while (tmp->right)
tmp = tmp->right;

73 | P a g e
Compiler Design (3170701) 190090107055

pre = tmp ;
}

// the minimum value in right subtree is successor


if (root->right != NULL)
{
Node* tmp = root->right ;
while (tmp->left)
tmp = tmp->left ;
suc = tmp ;
}
return ;
}

// If key is smaller than root's key, go to left subtree


if (root->key > key)
{
suc = root ;
findPreSuc(root->left, pre, suc, key) ;
}
else // go to right subtree
{
pre = root ;
findPreSuc(root->right, pre, suc, key) ;
}
}

// A utility function to create a new BST node


Node *newNode(int item)
{
Node *temp = new Node;
temp->key = item;
temp->left = temp->right = NULL;

74 | P a g e
Compiler Design (3170701) 190090107055

return temp;
}

/* A utility function to insert a new node with given key in BST */


Node* insert(Node* node, int key)
{
if (node == NULL) return newNode(key);
if (key < node->key)
node->left = insert(node->left, key);
else
node->right = insert(node->right, key);
return node;
}

// Driver program to test above function


int main()
{
int key = 65; //Key to be searched in BST

/* Let us create following BST


50
/ \
30 70
/\/\
20 40 60 80 */
Node *root = NULL;
root = insert(root, 50);
insert(root, 30);
insert(root, 20);
insert(root, 40);
insert(root, 70);
insert(root, 60);
insert(root, 80);

75 | P a g e
Compiler Design (3170701) 190090107055

Node* pre = NULL, *suc = NULL;

findPreSuc(root, pre, suc, key);


if (pre != NULL)
cout << "Predecessor is " << pre->key << endl;
else
cout << "No Predecessor";

if (suc != NULL)
cout << "Successor is " << suc->key;
else
cout << "No Successor";
return 0;
}

• Output

76 | P a g e

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy