0% found this document useful (0 votes)
42 views85 pages

Compiler Design 3170701 LabManual 2022

Lab manual of complier design

Uploaded by

Priyank G
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)
42 views85 pages

Compiler Design 3170701 LabManual 2022

Lab manual of complier design

Uploaded by

Priyank G
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/ 85

Compiler Design

(3170701)

Lab Manual
Practical-1: Implementation of Finite Automata and String Validation.

Related Theory:

 Design a deterministic finite automata (DFA) for accepting the language


o L = { a^n b^m | n mod 2=0, m>= 1}
 Regular expression for above language L is,
o L = (aa)*.b+

 There are 3 steps involve which results in acceptance of string:


o Construct FA for (aa)^* means having even number of a’s.
o Construct FA for b^+ means having any number of b’s greater than one.
o Concatenate the two FA and make single DFA.
o Any other combination result is the rejection of the input string.

 DFA State Transition Diagram:

 Given DFA has following states. State 3 leads to the acceptance of the string, whereas
states 0, 1, 2 and 4 leads to the rejection of the string.

Compiler Design (3170701) 2


Input:Practical1.c
//program to implement DFS that accepts
// all string which follow the language
// L = { a^n b^m ; (n)mod 2=0, m>=1 }
#include <stdio.h>
#include <string.h>

// dfa tells the number associated


// string end in which state.
int dfa = 0;

// This function is for


// the starting state (Q0)of DFA
void start(char c)
{
if (c == 'a') {
dfa = 1;
}
else if (c == 'b') {
dfa = 3;
}

// -1 is used to check for any invalid symbol


else {
dfa = -1;
}
}

// This function is for the first state (Q1) of DFA


void state1(char c)
{
if (c == 'a') {
dfa = 2;
}
else if (c == 'b') {
dfa = 4;
}
else {
dfa = -1;
}
}

// This function is for the second state (Q2) of DFA


void state2(char c)
{
Compiler Design (3170701) 3
if (c == 'b') {
dfa = 3;
}
else if (c == 'a') {
dfa = 1;
}
else {
dfa = -1;
}
}

// This function is for the third state (Q3)of DFA


void state3(char c)
{
if (c == 'b') {
dfa = 3;
}
else if (c == 'a') {
dfa = 4;
}
else {
dfa = -1;
}
}

// This function is for the fourth state (Q4) of DFA


void state4(char c)
{
dfa = -1;
}

int isAccepted(char str[])


{
// store length of string
int i, len = strlen(str);

for (i = 0; i < len; i++) {


if (dfa == 0)
start(str[i]);

else if (dfa == 1)
state1(str[i]);

else if (dfa == 2)
state2(str[i]);

Compiler Design (3170701) 4


else if (dfa == 3)
state3(str[i]);

else if (dfa == 4)
state4(str[i]);
else
return 0;
}
if (dfa == 3)
return 1;
else
return 0;
}

// driver code
int main()
{
char str[] = "aaaaaabbbb";
if (isAccepted(str))
printf("ACCEPTED");
else
printf("NOT ACCEPTED");
return 0;
}

Output:

Compiler Design (3170701) 5


Practical-2: Introduction to Lex Tool.

Related Theory:
Lex is a computer program that generates lexical analyzers ("scanners" or "lexers"). Lex
is commonly used with the yacc parser generator. Lex, originally written by Mike Lesk and Eric
Schmidt and described in 1975, is the standard lexical analyzer generator on many Unix
systems, and an equivalent tool is specified as part of the POSIX standard.

Lex reads an input stream specifying the lexical analyzer and writes source code which
implements the lexical analyzer in the C programming language. In addition to C, some old
versions of Lex could also generate a lexer in Ratfor.

Although originally distributed as proprietary software, some versions of Lex are now
open-source. Open-source versions of Lex, based on the original proprietary code, are now
distributed with open-source operating systems such as OpenSolaris and Plan 9 from Bell Labs.
One popular open-source version of Lex, called flex, or the "fast lexical analyzer", is not derived
from proprietary coding.

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

Compiler Design (3170701) 6


Lex File Format

 A Lex program is separated into three sections by %% delimiters. The formal of Lex
source is as follows:

{ definitions }

%%

{ rules }

%%

{ user subroutines }

 Definitions include declarations of constant, variable and regular definitions.


 Rules define the statement of form p1 {action1} p2 {action2} .... pn {action}.
 Where pi describes the regular expression and action1 describes the actions what action
the lexical analyzer should take when pattern pi matches a lexeme.

Input: words.l
/*lex program to count number of words*/

%{
#include<stdio.h>
#include<string.h>
int i = 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()
{

Compiler Design (3170701) 7


// The function that starts the analysis
yylex();

return 0;
}

Output:

Compiler Design (3170701) 8


Practical-3: Implement following Programs Using Lex

A. Generate Histogram of words

Input: countword.l
%{
#include<stdio.h>
#include<string.h>

char word [] = "use";int


count = 0;

%}

/* Rule Section */
/* Rule 1 compares the matched token with the word to
count and increments the count variableon successful
match */
/* Rule 2 matches everything other than string (consists of
albhabets only ) and do nothing */

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

int yywrap()
{
return 1;
}

/* code section */int


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

/* open the input filein


read mode */
yyin=fopen("Input.txt", "r");yylex();

printf("%d", count);

}
Compiler Design (3170701) 9
Input File: Input.txt

Output:

Compiler Design (3170701) 10


B. Caesar Cipher

Input: cipher2.l

%%
[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:

Compiler Design (3170701) 11


C. Extract single and multiline comments from C Program

Input:
/*Definition Section*/
%{
#include<stdio.h>
%}

/*Rule Section*/

%%
/*Regular expression for single line comment*/
\/\/(.*) {};
/*Regular expression for multi line comment*/
\/\*(.*\n)*.*\*\/ {};
%%

/*call the yywrap function*/


int yywrap()
{
return 1;
}

/*Auxiliary function*/
/*Driver function*/

int main()
{
yyin=fopen("input6.c","r");
yyout=fopen("out.c","w");
/*call the yylex function.*/
yylex();
return 0;
}

Compiler Design (3170701) 12


Output:

input.c

output.c

Compiler Design (3170701) 13


Practical-4: Implement following Programs Using Lex

A. Convert Roman to Decimal

Input:roman.l
%{
#include<stdio.h>
#include<ctype.h>

FILE *ff,*fr; char


fname[20];int z;
%}

%%

1 {fprintf(fr,"I");}

2|3|4 { z=atoi(yytext);
while(z!=0)
{
{fprintf(fr,"I");}z--;
}
}

5 {fprintf(fr,"V ");}
6|7|8 { a=atoi(yytext);
{fprintf(fr,"V ");}
while(z!=5)
{
{fprintf(fr,"I");}z--;
}
}

9 {fprintf(fr,"IX");}
10 {fprintf(fr,"X");}
. {fprintf(fr,yytext);}

Compiler Design (3170701) 14


%%

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


{
strcpy(fname,argv[1]);
ff=fopen(fname,r+);
fr=fopen("output.txt","w+");
yyin=ff;
yylex();
return(0);
}

Output:

Input.txt Output.txt

B. Check weather given statement is compound or simple

%{
#include<stdio.h>int
is_simple=1;
%}

%%
[ \t\n]+[aA][nN][dD][ \t\n]+ {is_simple=0;}
[ \t\n]+[bB][uU][tT][ \t\n]+ {is_simple=0;}
[ \t\n]+[oO][rR][ \t\n]+ {is_simple=0;}

Compiler Design (3170701) 15


. {;}
%%

main()
{
printf("Enter the sentence: ");
yylex();

if(is_simple==1)
printf("\n the given sentence is simple sentence\n");else
printf("\n the given sentence is compound sentence\n");
}

int yywrap()
{
return 1;
}

Output:

:~$ lex simple.l


:~$ cc lex.yy.c -ll
:~$ ./a.out
Enter the sentence: compiler and lex programmingthe

given sentence is compound sentence

:~$ lex simple.l


:~$ cc lex.yy.c -ll
:~$ ./a.out
Enter the sentence: LEX

the given sentence is simple sentence

Compiler Design (3170701) 16


C. Extract html tags from .html file.

Input: extracttags.l

/* Declaration section*/
%{
%}
%%
"<"[^>]*> {printf("%s\n", yytext); } /* if anything enclosedin
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 analysisyylex();


return 0;
}

Output:

Compiler Design (3170701) 17


Practical-5: Implementation of Recursive Descent Parser without backtracking.

Input: Recursive-descent-parser.c

Example:
Grammar: E --> i E'
E' --> + i E' | e
____________________

int main()
{
// E is a start symbol.
E();

// if lookahead = $, it represents the end of the string


// Here l is lookahead.
if (l == '$')
printf("Parsing Successful");
}

// Definition of E, as per the given production


E()
{
if (l == 'i') {
match('i');
E'();
}
}

// Definition of E' as per the given production


E'()
{
if (l == '+') {
match('+');
match('i');
E'();
}//The second condition of E'
else if ( l == 'e' )
{
match('e');
}
return ();
}

Compiler Design (3170701) 18


// Match function
match(char t)
{
if (l == t) {
l = getchar();
}
else
printf("Error");
}

Output:

I+ie $

Pasring Sucessfully

Compiler Design (3170701) 19


Practical-6&10: Finding “First” and “Follow” set
Input: The string consists of grammar symbols.
Output: The First 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 set of
the given string.

Input: first_follow.c

// C program to calculate the First and


// Follow sets of a given grammar
#include<stdio.h>
#include<ctype.h>
#include<string.h>

// Functions to calculate Follow


void followfirst(char, int, int);
void follow(char c);

// Function to calculate First


void findfirst(char, int, int);

int count, n = 0;

// Stores the final result


// of the First Sets
char calc_first[10][100];

// Stores the final result


// of the Follow Sets
char calc_follow[10][100];
int m = 0;

// Stores the production rules


char production[10][10];
char f[10], first[10];
int k;
char ck;
int e;

int main(int argc, char **argv)


{
Compiler Design (3170701) 20
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];
int ptr = -1;

// Initializing the calc_first array


for(k = 0; k < count; k++) {
for(kay = 0; kay < 100; kay++) {
calc_first[k][kay] = '!';
}
}
int point1 = 0, point2, xxx;

for(k = 0; k < count; k++)


{
c = production[k][0];
point2 = 0;
xxx = 0;

// Checking if First of c has


// already been calculated
for(kay = 0; kay <= ptr; kay++)
if(c == done[kay])
xxx = 1;

if (xxx == 1)
continue;

// Function call
findfirst(c, 0, 0);
Compiler Design (3170701) 21
ptr += 1;

// Adding c to the calculated list


done[ptr] = c;
printf("\n First(%c) = { ", c);
calc_first[point1][point2++] = c;

// Printing the First Sets of the grammar


for(i = 0 + jm; i < n; i++) {
int lark = 0, chk = 0;

for(lark = 0; lark < point2; lark++) {

if (first[i] == calc_first[point1][lark])
{
chk = 1;
break;
}
}
if(chk == 0)
{
printf("%c, ", first[i]);
calc_first[point1][point2++] = first[i];
}
}
printf("}\n");
jm = n;
point1++;
}
printf("\n");
printf("-----------------------------------------------\n\n");
char donee[count];
ptr = -1;

// Initializing the calc_follow array


for(k = 0; k < count; k++) {
for(kay = 0; kay < 100; kay++) {
calc_follow[k][kay] = '!';
}
}
point1 = 0;
int land = 0;
for(e = 0; e < count; e++)
{
ck = production[e][0];
Compiler Design (3170701) 22
point2 = 0;
xxx = 0;

// Checking if Follow of ck
// has already been calculated
for(kay = 0; kay <= ptr; kay++)
if(ck == donee[kay])
xxx = 1;

if (xxx == 1)
continue;
land += 1;

// Function call
follow(ck);
ptr += 1;

// Adding ck to the calculated list


donee[ptr] = ck;
printf(" Follow(%c) = { ", ck);
calc_follow[point1][point2++] = ck;

// Printing the Follow Sets of the grammar


for(i = 0 + km; i < m; i++) {
int lark = 0, chk = 0;
for(lark = 0; lark < point2; lark++)
{
if (f[i] == calc_follow[point1][lark])
{
chk = 1;
break;
}
}
if(chk == 0)
{
printf("%c, ", f[i]);
calc_follow[point1][point2++] = f[i];
}
}
printf(" }\n\n");
km = m;
point1++;
}
}

Compiler Design (3170701) 23


void follow(char c)
{
int i, j;

// Adding "$" to the follow


// set of the start symbol
if(production[0][0] == c) {
f[m++] = '$';
}
for(i = 0; i < 10; i++)
{
for(j = 2;j < 10; j++)
{
if(production[i][j] == c)
{
if(production[i][j+1] != '\0')
{
// Calculate the first of the next
// Non-Terminal in the production
followfirst(production[i][j+1], i, (j+2));
}

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


{
// Calculate the follow of the Non-Terminal
// in the L.H.S. of the production
follow(production[i][0]);
}
}
}
}
}

void findfirst(char c, int q1, int q2)


{
int j;

// The case where we


// encounter a Terminal
if(!(isupper(c))) {
first[n++] = c;
}
for(j = 0; j < count; j++)
{
if(production[j][0] == c)
Compiler Design (3170701) 24
{
if(production[j][2] == '#')
{
if(production[q1][q2] == '\0')
first[n++] = '#';
else if(production[q1][q2] != '\0'
&& (q1 != 0 || q2 != 0))
{
// Recursion to calculate First of New
// Non-Terminal we encounter after epsilon
findfirst(production[q1][q2], q1, (q2+1));
}
else
first[n++] = '#';
}
else if(!isupper(production[j][2]))
{
first[n++] = production[j][2];
}
else
{
// Recursion to calculate First of
// New Non-Terminal we encounter
// at the beginning
findfirst(production[j][2], j, 3);
}
}
}
}

void followfirst(char c, int c1, int c2)


{
int k;

// The case where we encounter


// a Terminal
if(!(isupper(c)))
f[m++] = c;
else
{
int i = 0, j = 1;
for(i = 0; i < count; i++)
{
if(calc_first[i][0] == c)
break;
Compiler Design (3170701) 25
}

//Including the First set of the


// Non-Terminal in the Follow of
// the original query
while(calc_first[i][j] != '!')
{
if(calc_first[i][j] != '#')
{
f[m++] = calc_first[i][j];
}
else
{
if(production[c1][c2] == '\0')
{
// Case where we reach the
// end of a production
follow(production[c1][0]);
}
else
{
// Recursion to the next symbol
// in case we encounter a "#"
followfirst(production[c1][c2], c1, c2+1);
}
}
j++;
}
}
}

Compiler Design (3170701) 26


Output:

Compiler Design (3170701) 27


Practical-7: Generate 3-tuple intermediate code for given infix expression.

Input: ThreeAddressCode.c

#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++;
}
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';
Compiler Design (3170701) 28
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();
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)||(strcmp(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);
}
}
Compiler Design (3170701) 29
}
void pm()
{
strrev(exp);
j=l-i-1;
strncat(exp1,exp,j);
strrev(exp1);
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 :

1. assignment
2. arithmetic
3. relational
4. Exit
Enter the choice:1
Enter the expression with assignment operator:
a=b
Three address code:
temp=b
a=temp

1.assignment
2.arithmetic
3.relational
4.Exit
Enter the choice:2
Enter the expression with arithmetic operator:
a+b-c
Three address code:
temp=a+b
temp1=temp-c

1.assignment
Compiler Design (3170701) 30
2.arithmetic
3.relational
4.Exit
Enter the choice:2
Enter the expression with arithmetic operator:
a-b/c
Three address code:
temp=b/c
temp1=a-temp

1.assignment
2.arithmetic
3.relational
4.Exit
Enter the choice:2
Enter the expression with arithmetic operator:
a*b-c
Three address code:
temp=a*b
temp1=temp-c

1.assignment
2.arithmetic
3.relational
4.Exit
Enter the choice:2
Enter the expression with arithmetic operator:a/b*c
Three address code:
temp=a/b
temp1=temp*c
1.assignment
2.arithmetic
3.relational
4.Exit
Enter the choice:3
Enter the expression with relational operator
a
<=
b

100 if a<=b goto 103


101 T:=0
102 goto 104
103 T:=1

Compiler Design (3170701) 31


1.assignment
2.arithmetic
3.relational
4.Exit
Enter the choice:4

Compiler Design (3170701) 32


Practical-8: Extract Predecessor and Successor from given Control Flow Graph.

Input: InorderSuccessorPredecessor.java

// C++ program to find predecessor and successor in a BST


#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;
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 ;
}

Compiler Design (3170701) 33


// 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;
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);
Compiler Design (3170701) 34
insert(root, 30);
insert(root, 20);
insert(root, 40);
insert(root, 70);
insert(root, 60);
insert(root, 80);

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:

Predecessor is 60
Successor is 70

Compiler Design (3170701) 35


Practical-9: Introduction to YACC and generate Calculator Program.

Related Theory:

A parser generator is a program that takes as input a specification of a syntax, and


produces as output a procedure for recognizing that language. Historically, they
are also called compiler-compilers.

YACC (yet another compiler-compiler) is an LALR(1) (LookAhead, Left-to-right,


Rightmost derivation producer with 1 lookahead token) parser generator. YACC
was originally designed for being complemented by Lex.

Input File:

 YACC input file is divided into three parts.

Input File: Definition Part:

 The definition part includes information about the tokens used in the
syntax definition:

Compiler Design (3170701) 36


 Yacc automatically assigns numbers for tokens, but it can be overridden
by

 Yacc also recognizes single characters as tokens. Therefore, assigned token


numbers should not overlap ASCII codes.
 The definition part can include C code external to the definition of the
parser and variable declarations, within %{ and %} in the first column.
 It can also include the specification of the starting symbol in the grammar:

Input File: 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).

Input File: 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().

Input File:

 If yylex() is not defined in the auxiliary routines sections, then it should


be included:

#include "lex.yy.c"

Compiler Design (3170701) 37


 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 definition (particularly important are
token definitions to be included, for example, in a Lex input file).
 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 for tracking down how the parser solves conflicts.

Calculator Program:

Lexical Analyzer Source Code:


%{
/* Definition section */
#include<stdio.h>
#include "y.tab.h"
extern int yylval;
%}

/* Rule Section */
%%
[0-9]+ {
yylval=atoi(yytext);return
NUMBER;

}
[\t] ;

[\n] return 0;

. return yytext[0];

Compiler Design (3170701) 38


%%
int yywrap()
{
return 1;
}

Parser Source Code:


%{
/* Definition section */
#include<stdio.h>int
flag=0;
%}

%token NUMBER

%left '+' '-'

%left '*' '/' '%'

%left '(' ')'

/* Rule Section */
%%

ArithmeticExpression: E{

printf("\nResult=%d\n", $$);return 0;

};
E:E'+'E {$$=$1+$3;}

|E'-'E {$$=$1-$3;}

|E'*'E {$$=$1*$3;}

|E'/'E {$$=$1/$3;}

|E'%'E {$$=$1%$3;}

|'('E')' {$$=$2;}

| NUMBER {$$=$1;}

Compiler Design (3170701) 39


;

%%

Compiler Design (3170701) 40


//driver code
void main()
{
printf("\nEnter Any Arithmetic Expression which
can have operations Addition, Subtraction,
Multiplication, Division,
Modulus and Round brackets:\n");

yyparse(); if(flag==0)
printf("\nEntered arithmetic expression is Valid\n\n");
}

void yyerror()
{
printf("\nEntered arithmetic expression is Invalid\n\n");flag=1;
}

Output:

Compiler Design (3170701) 41


Practical-11: Implement a C program for constructing LL (1) parsing.

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

void followfirst(char , int


, int); void findfirst(char ,
int , int); void follow(char
c);

int count,n=0;
char
calc_first[10][100];
char
calc_follow[10][100];
int m=0;
char production[10][10],
first[10]; char f[10];
int k;
char
ck; int
e;

int main(int argc,char **argv)


{
int jm=0;
int km=0;
int
i,choice;
char c,ch;
printf("How many
productions ? :");
scanf("%d",&count);
printf("\nEnter %d productions in form A=B where A and B are grammar
symbols :\n\n",count); for(i=0;i<count;i++)
Compiler Design (3170701) 42
{
scanf("%s%c",production[i],&ch);
}
int kay;
char
done[count];
int ptr = -1;
for(k=0;k<count;k++){
for(kay=0;kay<100;kay++){
calc_first[k][kay] = '!';
}
}
int point1 =
0,point2,xxx;
for(k=0;k<count;k++
)
{

Compiler Design (3170701) 43


c=production[k]
[0]; point2 = 0;
xxx = 0;
for(kay = 0; kay <= ptr;
kay++) if(c ==
done[kay])
xxx = 1;
if (xxx == 1)
continu
e;
findfirst(c,0,0);
ptr+=1;
done[ptr] = c;
printf("\n First(%c)= { ",c);
calc_first[point1][point2+
+] = c; for(i=0+jm;i<n;i++){
int lark = 0,chk = 0;
for(lark=0;lark<point2;lark++){
if (first[i] ==
calc_first[point1][lark]
){ chk = 1;
break;
}
}
if(chk == 0){
printf("%c, ",first[i]);
calc_first[point1][point2++] =
first[i];
}
}
printf("}\n
"); jm=n;
point1++;
}
printf("\n");
printf("
\n\n"
); char donee[count];
ptr = -1;
for(k=0;k<count;k+
Compiler Design (3170701) 44
+){
for(kay=0;kay<100;kay++){
calc_follow[k][kay] = '!';
}
}
point1 =
0; int
land = 0;
for(e=0;e<count;e++)
{
ck=production[e]
[0]; point2 = 0;
xxx = 0;

Compiler Design (3170701) 45


for(kay = 0; kay <= ptr;
kay++) if(ck ==
donee[kay])
xxx = 1;
if (xxx == 1)
continu
e; land +=
1; follow(ck);
ptr+=1;
donee[ptr] =
ck;
printf(" Follow(%c) = { ",ck);
calc_follow[point1][point2++
] = ck; for(i=0+km;i<m;i++){
int lark = 0,chk = 0;
for(lark=0;lark<point2;lark++){
if (f[i] ==
calc_follow[point1][la
rk]){ chk = 1;
break;
}
}
if(chk == 0){
printf("%c, ",f[i]);
calc_follow[point1][point2++
] = f[i];
}
}
printf("
}\n\n");
km=m;
point1++;
}
char ter[10];
for(k=0;k<10;k
++){
ter[k] = '!';
}
int ap,vp,sid = 0;
for(k=0;k<count;k+
Compiler Design (3170701) 46
+){
for(kay=0;kay<count;kay++){
if(!isupper(production[k][kay]) && production[k][kay]!= '#' &&
production[k][kay] != '=' && production[k][kay] != '\0'){
vp = 0;
for(ap = 0;ap < sid; ap++){
if(production[k][kay] ==
ter[ap]){ vp = 1;
break;
}
}
if(vp == 0){
ter[sid] = production[k][kay];

Compiler Design (3170701) 47


sid ++;
}
}
}
}
ter[sid] =
'$'; sid++;
printf("\n\t\t\t\t\t\t\t The LL(1) Parsing Table for the above grammer :-");
printf("\n\t\t\t\t\t\t\t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
printf("\n\t\t\t====================================================================
======
===========================================\n");
printf("\t\t\t\t|\t");
for(ap = 0;ap < sid;
ap++){
printf("%c\t\t",ter[ap]);
}
printf("\n\t\t\t============================================================
==============
===========================================\n");
char
first_prod[count][sid];
for(ap=0;ap<count;ap
++){
int destiny =
0; k = 2;
int ct = 0;
char tem[100];
while(production[ap][k] !=
'\0'){
if(!isupper(production[ap][k])){
tem[ct++] =
production[ap][k];
tem[ct++] = '_';
tem[ct++] =
'\0'; k++;
break;
}
else{
int zap=0;
Compiler Design (3170701) 48
int tuna =
0;
for(zap=0;zap<count;zap++){
if(calc_first[zap][0] ==
production[ap][k]){
for(tuna=1;tuna<100;tuna
++){
if(calc_first[zap][tuna] != '!'){
tem[ct++] = calc_first[zap][tuna];
}
els
e break;
}
break;
}
}

Compiler Design (3170701) 49


tem[ct++] = '_';
}
k++
;
}
int zap = 0,tuna;
for(tuna = 0;tuna<ct;tuna++){
if(tem[tuna] == '#'){
zap = 1;
}
else if(tem[tuna] == '_'){
if(zap == 1){
zap = 0;
}
els
e break;
}
else
{
first_prod[ap][destiny++] = tem[tuna];
}
}
}
char
table[land][sid+1];
ptr = -1;
for(ap = 0; ap < land ; ap++){
for(kay = 0; kay < (sid + 1) ;
kay++){ table[ap][kay]
= '!';
}
}
for(ap = 0; ap < count ;
ap++){ ck =
production[ap][0];
xxx = 0;
for(kay = 0; kay <= ptr;
kay++) if(ck ==
table[kay][0])
xxx = 1;
Compiler Design (3170701) 50
if (xxx == 1)
continue;
else
{ ptr = ptr + 1;
table[ptr][0] =
ck;
}
}
for(ap = 0; ap < count ;
ap++){ int tuna =
0;
while(first_prod[ap][tuna]
!= '\0'){ int to,ni=0;
for(to=0;to<sid;to++)
{

Compiler Design (3170701) 51


if(first_prod[ap][tuna] ==
ter[to]){ ni = 1;
}
}
if(ni == 1){
char xz =
production[ap][0]; int
cz=0;
while(table[cz][0] != xz){
cz = cz + 1;
}
int vz=0;
while(ter[vz] !=
first_prod[ap][tuna]){ vz
= vz + 1;
}
table[cz][vz+1] = (char)(ap + 65);
}
tuna+
+;
}
}
for(k=0;k<sid;k++){
for(kay=0;kay<100;kay++){
if(calc_first[k][kay]
== '!'){ break;
}
else if(calc_first[k][kay]
== '#'){ int fz = 1;
while(calc_follow[k][fz] != '!'){
char xz =
production[k][0]; int
cz=0;
while(table[cz][0] !=
xz){
cz = cz + 1;
}
int vz=0;
while(ter[vz] !=
calc_follow[k][fz]){ vz

Compiler Design (3170701) 52


= vz + 1;
}
table[k][vz+1] =
'#'; fz++;
}
brea
k;
}
}
}
for(ap = 0; ap < land ; ap++){
printf("\t\t\t
%c\t|\t",table[ap][0]); for(kay = 1;
kay < (sid + 1) ; kay++){

Compiler Design (3170701) 53


if(table[ap][kay] == '!')
printf("\t\t");
else if(table[ap][kay] == '#')
printf("%c=#\t\t",table[ap][0]);
else
{ int mum =
(int)(table[ap][kay]); mum -=
65;
printf("%s\t\t",production[mu
} m]);
}
printf("\n");
printf("\t\t\t

")
printf("\n");
;
}
int
j;
printf("\n\nPlease enter the desired INPUT
STRING = "); char input[100];
scanf("%s%c",input,&ch);
printf("\n\t\t\t\t\t=================================================================
======
====\n");
printf("\t\t\t\t\t\tStack\t\t\tInput\t\t\tAction");
printf("\n\t\t\t\t\t=================================================================
======
====\n");
int i_ptr = 0,s_ptr
= 1; char
stack[100];
stack[0] = '$';
stack[1] =
table[0][0];
while(s_ptr != -1){
printf("\t\t\t\t\t\t
"); int vamp = 0;
for(vamp=0;vamp<=s_ptr;vamp++){
printf("%c",stack[vamp]);
}
Compiler Design (3170701) 54
printf("\t\t\t
"); vamp =
i_ptr;
while(input[vamp] != '\0'){
printf("%c",input[vamp]);
vamp++;
}
printf("\t\t\t");
char her =
input[i_ptr]; char
him = stack[s_ptr];
s_ptr--;
if(!isupper(him)){
if(her == him){

Compiler Design (3170701) 55


i_ptr++;
printf("POP ACTION\n");
}
else
{ printf("\nString Not Accepted by LL(1) Parser
!!\n"); exit(0);

}
}
else
{
for(i=0;i<sid;i++){
if(ter[i] == her)
break;
}
char produ[100];
for(j=0;j<land;j++){
if(him == table[j][0]){
if (table[j][i+1] == '#'){
printf("%c=#\n",table[j]
[0]); produ[0] = '#';
produ[1] = '\0';
}
else if(table[j][i+1] != '!'){
int mum =
(int)(table[j][i+1]); mum -=
65;
strcpy(produ,production[m
um]); printf("%s\n",produ);
}
else
{ printf("\nString Not Accepted by LL(1) Parser
!!\n"); exit(0);

}
}
}
int le =
strlen(produ); le =
le - 1;
if(le == 0){
continue;
Compiler Design (3170701) 56
}
for(j=le;j>=2;j--){
s_ptr++;
stack[s_ptr] = produ[j];
}
}
}
printf("\n\t\t\t===================================================================
=======
=============================================\n");

Compiler Design (3170701) 57


if (input[i_ptr] == '\0'){
printf("\t\t\t\t\t\t\t\tYOUR STRING HAS BEEN ACCEPTED !!\n");
}
else
printf("\n\t\t\t\t\t\t\t\tYOUR STRING HAS BEEN REJECTED !!\n");
printf("\t\t\t=====================================================================
=======
===========================================\n");
}

void follow(char c)
{
int i ,j;
if(production[0][0]==c
){
f[m++]='$';
}
for(i=0;i<10;i++)
{
for(j=2;j<10;j++)
{
if(production[i][j]==c)
{
if(production[i][j+1]!='\0'){
followfirst(production[i][j+1],i,(j+2));
}
if(production[i][j+1]=='\0'&&c!=productio
n[i][0]){ follow(production[i][0]);
}
}
}
}
}

void findfirst(char c ,int q1 , int q2)


{
int j;
if(!(isupper(c
))){
first[n++]=c;
}
Compiler Design (3170701) 58
for(j=0;j<count;j++)
{
if(production[j][0]==c)
{
if(production[j][2]=='#'){
if(production[q1][q2]
== '\0')
first[n++]='#';
else if(production[q1][q2] != '\0' && (q1 != 0 || q2 != 0))

Compiler Design (3170701) 59


{
findfirst(production[q1][q2], q1, (q2+1));
}
els
e first[n++]='#';

}
else if(!isupper(production[j][2])){
first[n++]=production[j][2];
}
else
{ findfirst(production[j][2], j, 3);

}
}
}
}

void followfirst(char c, int c1 , int c2)


{
int k;
if(!(isupper(
f[m++]=
c)))
c; int
else{
i=0,j=1;
for(i=0;i<count;i++)
{
if(calc_first[i][0] == c)
break;
}
while(calc_first[i][j] != '!')
{
if(calc_first[i][j] != '#'){
f[m++] = calc_first[i][j];
}
else
{ if(production[c1][c2] == '\0'){
follow(production[c1][0]);
j++;
}
} }
Compiler Design (3170701) 60
} }
else
{ followfirst(production[c1][c2],c1,c2+1);

Compiler Design (3170701) 61


Output:

Compiler Design (3170701) 62


Compiler Design (3170701) 63
Practical-12: Write a C program to implement LALR parsing.

Input: lalr.c

#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"},
Compiler Design (3170701) 64
{"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"},
{"emp","rb","sh","emp","rb","rb"},
{"emp","rb","rd","emp","rd","rd"},
{"emp","rf","rf","emp","rf","rf"}
};

struct gotol
{
char r[3][4];
};

Compiler Design (3170701) 65


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"},
};

void main()

{
Compiler Design (3170701) 66
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';

Compiler Design (3170701) 67


push(stack,&top,bl);
printf("\n stack \t\t\t
input");
printt(stack,&top,inp,i);

do
{
x=inp[i];
p=stacktop(sta
ck);
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

Compiler Design (3170701) 68


++)
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++)

Compiler Design (3170701) 69


push(stack,&top,temp[m]);
}
}
}

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]=ite
m;
}
}

char stacktop(char *s)


{
char i;
i=s[top
];

return i;
Compiler Design (3170701) 70
}

void isproduct(char x,char p)


{
int k,l;

k=ister(x)
;
l=isstate(
p);
strcpy(temp,A[l-1].row[k-1]);

Compiler Design (3170701) 71


}

int ister(char x)
{
int i;

for(i=0;i<6;i
++)
if(x==ter[i
])
return i+1;

return 0;
}

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;
}
Compiler Design (3170701) 72
void error()
{
printf(" error in the
input "); exit(0);
}

void isreduce(char x,char p)


{
int k,l;
k=isstate(
x);

Compiler Design (3170701) 73


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;
}

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]);
Compiler Design (3170701) 74
}

void rep(char t[],int r)


{

char
c;
c=t[r]
;

switch(c)

Compiler Design (3170701) 75


{

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;
Compiler Design (3170701) 76
case 'k':
printf("10");
break;

case 'l':
printf("11");
break;

default
:printf("%c",t[r]);
break;

Compiler Design (3170701) 77


Output:

Compiler Design (3170701) 78


Practical-13 Implement a C program to implement operator precedence parsing.

Input: OperatorPrecedence.c

#include<stdio.
h>
#include<string
.h>
#include<stdlib
.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','>','>',
/* ( */ '<', '<','<','<','<','<','<','>','e',
/* ) */ '>', '>','>','>','>','e','e','>','>',
/* $ */ '<', '<','<','<','<','<','<','<','>',
};
int getindex(char c)
{
switch(c)
{
case '+':return 0;
case '-':return 1;
case '*':return 2;
Compiler Design (3170701) 79
case '/':return 3;
case '^':return 4;
case 'i':return 5;
case '(':return 6;
case ')':return 7;
case '$':return 8;
}
}

Compiler Design (3170701) 80


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

int reduce()
{
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
}
}
}
Compiler Design (3170701) 81
return 0;
}

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

Compiler Design (3170701) 82


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");
dispinput();
printf("\tShif
t");
if(prec[getindex(stack[top])][getindex(input[i])]=='>')
{
while(reduce())
{
printf("\n
");
dispstack
();
printf("\t
");
dispinput
();
Compiler Design (3170701) 83
printf("\tReduced: E->%s",lasthandle);
}
}
}

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

Compiler Design (3170701) 84


Output:

Compiler Design (3170701) 85

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