CD Practical Jignasha
CD Practical Jignasha
PRACTICAL – 1
AIM: Implementation of Finite Automata and String Validation.
Code:
#include <iostream.h>
#include <string.ha>
using namespace std;
#define MAX 100
int main() {
char str[MAX];
char f = 'a';
cout << "Enter the string to be checked: ";
cin >> str;
VIEAT/B.E/SEM-VII/220943107040
1
Compiler Design (3170701)
PRACTICAL – 2
AIM: Introduction to Lex Tool.
LEX:
Lex plays a crucial role in compilers by classifying tokens based on their specific functions. To grasp the
concept of Lex in Compiler Design, we must first comprehend Lexical Analysis. This article will delve in
to Lex, but let’s start with an overview of Lexical Analysis.
Lexical Analysis:
Lexical Analysis is the initial phase of compiler design. It processes input, which is a sequence of charact
ers, and outputs tokens— a process known as tokenization. Tokens can be categories like identifiers, sepa
rators, keywords, operators, constants, and special characters. This process involves three main stages:
1. Tokenization: Converts the stream of characters into tokens.
2. Error Reporting: Identifies and reports lexical errors such as excessive length or unmatched strin
gs.
3. Comment Removal: Strips away comments, blank spaces, newlines, and indentation.
What is Lex in Compiler Design?
Lex is a software tool that creates Lexical Analyzers, which transform a sequence of characters into token
s. Essentially, Lex operates as a compiler. It accepts input and translates it into specific patterns. Lex is of
ten used alongside YACC (Yet Another Compiler Compiler). The tool was developed by Mike Lesk and
Eric Schmidt.
Function of Lex:
1. Initial Step:
The source code, written in Lex language and saved as ‘File.l’, is fed into the Lex Compiler, com
monly known as Lex, producing an output file named lex.yy.c.
2. Subsequent Step:
The lex.yy.c file is then passed to the C compiler, which outputs an ‘a.out’ file. Finally, the a.out f
ile processes a stream of characters and produces tokens as output.
lex.yy.c: It is a C program.
File.l: It is a Lex source program
a.out: It is a Lexical analyzer
VIEAT/B.E/SEM-VII/220943107040
2
Compiler Design (3170701)
Lex File Structure
A Lex program is composed of three sections, divided by %% delimiters:
1. Declarations:
Includes variable declarations.
2. Translation Rules:
Composed of patterns and their corresponding actions.
3. Auxiliary Procedures:
Contains auxiliary functions that are used in the actions.
These sections ensure a structured approach to defining the lexical analyzer.
For example:
declaration
number[0-9]
%%
translation
if {return (IF);}
%%
auxiliary function
int numberSum()
VIEAT/B.E/SEM-VII/220943107040
3
Compiler Design (3170701)
PRACTICAL – 3
AIM: Implement following Programs Using Lex
a. Generate Histogram of words
b. Ceasor Cypher
c. Extract single and multiline comments from C Program
a. Generate Histogram of Words.
%{
#include <stdio.h>
#include <string.h>
char word[] = "Jignasha";
int count = 0;
%}
%%
[a-zA-Z]+ {
if(strcmp(yytext,word)==0)
count++;
}
.;
%%
void main(){
yyin = fopen("input.txt", "r");
yylex();
printf("Number of occurrence of word \"Jignasha\" is %d.", count);
}
int yywrap() {
return 1;
}
Input.txt:
Hello ther Jignasha Soni Here,
Computer Enginnering student.
Output:
VIEAT/B.E/SEM-VII/220943107040
4
Compiler Design (3170701)
b. Ceasor Cypher:
%{
char ch;
%}
%%
[a-z] {
ch = yytext[0];
ch = ch + 3;
if(ch > 'z') ch = ch - ('z' + 1 - 'a');
printf("%c",ch);
}
[A-Z] {
ch = yytext[0];
ch = ch + 3;
if(ch > 'Z') ch = ch - ('Z' + 1 - 'A');
printf("%c",ch);
}
%%
void main(){
printf("Enter character :");
yylex();
}
int yywrap() {
return 1;
}
Output:
VIEAT/B.E/SEM-VII/220943107040
5
Compiler Design (3170701)
VIEAT/B.E/SEM-VII/220943107040
6
Compiler Design (3170701)
PRACTICAL – 4
AIM: Implement following Programs Using Lex
a. Convert Roman to Decimal
b. Check weather given statement is compound or simple
c. Extract html tags from .html file
VIEAT/B.E/SEM-VII/220943107040
7
Compiler Design (3170701)
VIEAT/B.E/SEM-VII/220943107040
8
Compiler Design (3170701)
c. Extract html tags from .html file.
#include
#include
#include
void extractHtmlTags(FILE *file) {
int c;
int insideTag = 0;
printf("HTML Tags in the file:\n");
while ((c = fgetc(file)) != EOF) {
if (c == '<') {
insideTag = 1;
putchar(c);
}
else if (c == '>') {
insideTag = 0;
putchar(c);
putchar('\n');
}
else if (insideTag) {
putchar(c);
}}}
int main() {
FILE *file;
char fileName[100];
printf("Enter the HTML file name: ");
scanf("%s", fileName);
file = fopen(fileName, "r");
if (file == NULL) {
printf("Error opening file.\n");
return 1; }
extractHtmlTags(file);
fclose(file);
return 0;
}
Output:
VIEAT/B.E/SEM-VII/220943107040
9
Compiler Design (3170701)
PRACTICAL – 5
AIM: Implementation of Recursive Descent Parser without backtracking
Input: The string to be parsed.
Output: Whether string parsed successfully or not.
Explanation: Students have to implement the recursive procedure for RDP for a
typical grammar. The production no. are displayed as they are used to derive the
string.
Code:
#include<stdio.h>
#include<ctype.h>
#include<string.h>
void Tprime();
void Eprime();
void E();
void check();
void T();
char expression[10];
int count,flag;
int main()
{
count =0;
flag = 0;
printf("\nEnter an Algebraic Expression:\t"); scanf("%s", expression);
E();
if((strlen(expression) == count) && (flag == 0))
{
printf("\nThe Expression %s is Valid\n", expression);
}
else
{ printf("\nThe Expression %s is Invalid\n", expression);
}}
void E(){
VIEAT/B.E/SEM-VII/220943107040
10
Compiler Design (3170701)
T();
Eprime(); }
void T(){
check();
Tprime(); }
void Tprime()
{
if(expression[count] =='*')
{
count++;
check();
Tprime();
}}
void check(){
if(isalnum(expression[count]))
{
count++;
}
else if(expression[count] == '(')
{
count++; E();
if(expression[count] == ')')
{
count++;
}
else
{ flag = 1;
}
}
else {
flag = 1;
}}
void Eprime(){
if(expression[count] =='+')
{
count++; T();
Eprime();
}}
VIEAT/B.E/SEM-VII/220943107040
11
Compiler Design (3170701)
Output:
VIEAT/B.E/SEM-VII/220943107040
12
Compiler Design (3170701)
PRACTICAL – 6
AIM: Finding “First” 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.
Code:
#include<stdio.h>
#include<ctype.h>
void FIRST(char );
int count,n=0;
char prodn[10][10], first[10];
main()
{
int i,choice; char c,ch;
printf("Howmanyproductions? :");
scanf("%d",&count);
printf("Enter %d productionsepsilon=$:\n\n",count);
for(i=0;i<count;i++)
scanf("%s%c",prodn[i],&ch);
do
{ n=0;
printf("Element :");
scanf("%c",c); FIRST(c);
printf("\n FIRST(%c)= { ",c);
for(i=0;i<n;i++)
printf("%c ",first[i]);
printf("}\n");
printf("press 1 to continue : ");
scanf("%d%c",&choice,&ch);
}
while(choice==1); }
void FIRST(char c) {
int j;
if(!(isupper(c)))
first[n++]=c;
for(j=0;j<count;j++)
VIEAT/B.E/SEM-VII/220943107040
13
Compiler Design (3170701)
{
if(prodn[j][0]==c)
{
if(prodn[j][2]=='$') first[n++]='$';
else if(islower(prodn[j][2]))first[n++]=prodn[j][2];
else FIRST(prodn[j][2]); }
}
}
Output:
VIEAT/B.E/SEM-VII/220943107040
14
Compiler Design (3170701)
PRACTICAL – 7
AIM: Generate 3-tuple intermediate code for given infix expression.
Intermediate code
Intermediate code is used to translate the source code into the machine code. Intermediate code lies
between the high-level language and the machine language.
o If the compiler directly translates source code into the machine code without generating
intermediate code then a full native compiler is required for each new machine.
o The intermediate code keeps the analysis portion same for all the compilers that's whyit
doesn't need a full compiler for every unique machine.
o Intermediate code generator receives input from its predecessor phase and semantic
analyzer phase. It takes input in the form of an annotated syntax tree.
o Using the intermediate code, the second phase of the compiler synthesis phase is
changed according to the target machine.
Intermediate representation
High level intermediate code can be represented as source code. To enhance performance of source
code, we can easily apply code modification. But to optimize the target machine, it is less preferred.
Low level intermediate code is close to the target machine, which makes it suitable for register and
memory allocation etc. it is used for machine-dependent optimizations.
Given Expression:
1. a := (-c * b) + (-c * d)
Three-address code is as follows: t1
VIEAT/B.E/SEM-VII/220943107040
15
Compiler Design (3170701)
:= -c
t2 := b*t1 t3
:= -c
t4 := d * t3 t5
:= t2 + t4 a := t5
VIEAT/B.E/SEM-VII/220943107040
16
Compiler Design (3170701)
PRACTICAL – 8
AIM: Extract Predecessor and Successor from given Control Flow Graph.
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 pushedto 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;
case '/':return 3;
case '^':return 4;
case 'i':return 5;
case '(':return 6;
case ')':return 7;
case '$':return 8;
}
}
int shift() {
VIEAT/B.E/SEM-VII/220943107040
17
Compiler Design (3170701)
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;//successfulreduction
}
}
}
return 0;
}
void dispstack() { 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);
VIEAT/B.E/SEM-VII/220943107040
18
Compiler Design (3170701)
input=strcat(input,"$");
l=strlen(input);
strcpy(stack,"$");
printf("\nSTACK\tINPUT\tACTION");
while(i<=l) { shift();
printf("\n"); dispstack();
printf("\t");
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;");
getch(); }
Output:
VIEAT/B.E/SEM-VII/220943107040
19
Compiler Design (3170701)
PRACTICAL – 9
AIM: Introduction to YACC and generate Calculator Program..
Code :
Input File:
If yylex() is not defined in the auxiliary routines sections, then it should be included:
#include "lex.yy.c"
YACC input file generally finishes with: .y
Output Files:
The output of YACC is a file named y.tab.c
If it contains themain() 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 (particularlyimportant 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
textualdescription of the LALR(1) parsing table used by the parser. This is useful for tracking
VIEAT/B.E/SEM-VII/220943107040
20
Compiler Design (3170701)
down how the parser solves conflicts.
For Compiling YACC Program:
Write lex program in a file file.l and yacc in a file file.y
Open Terminal and Navigate to the Directorywhere you have saved the files. type
lexfile.l type yacc file.y
type cc lex.yy.c y.tab.h -ll type
./a.out
Source Code:
LEX:
%{
#include<stdio.h> #include
"y.tab.h" extern int yylval;
%}
%%
[0-9]+ {
yylval=atoi(yytext); return NUMBER; }
[\t] ;
[\n] return0;
. return yytext[0];
%%
int yywrap() {
return 1;}
YAAC:
%{
#include<stdio.h> int
flag=0; %}
%token NUMBER
%left '+' '-'
%left '*' '/' '%'
%left '(' ')'
%%
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;}
VIEAT/B.E/SEM-VII/220943107040
21
Compiler Design (3170701)
|E'%'E {$$=$1%$3;}
|'('E')' {$$=$2;}
| NUMBER {$$=$1;}
;
%%
void main(){
77666666printf("\nEnter Any Arithmetic Expression which can have operations Addition, Subtraction,
Multiplication, Divison, Modulus and Round brackets:\n");
yyparse();
if(flag==0)
printf("\nEnteredarithmeticexpressionis Valid\n\n");
}
void yyerror(){
printf("\nEnteredarithmeticexpressionis Invalid\n\n");
flag=1;
}
Output:
VIEAT/B.E/SEM-VII/220943107040
22
Compiler Design (3170701)
PRACTICAL – 10
AIM: Finding “Follow” set Input: The string consists of grammar symbols.
Output: The 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 Follow set of the
given string.
Code:
#include<stdio.h>
#include<string.h> int
n,m=0,p,i=0,j=0;
char a[10][10],followResult[10];
void follow(charc);
void first(charc);
void addToResult(char); int
main()
{
int i;
int choice;
char c,ch;
printf("Enterthe no.ofproductions: ");
scanf("%d", &n);
printf(" Enter %d productions\nProduction with multiple terms should be give as separate
productions
\n", n);
for(i=0;i<n;i++)
scanf("%s%c",a[i],&ch); do {
m=0;
printf("Find FOLLOW of -->"); scanf("
%c",&c);
follow(c); printf("FOLLOW(%c)
={ ",c); for(i=0;i<m;i++)
printf("%c ",followResult[i]);
printf(" }\n");
printf("Do you want to continue(Press1 to continue....................)?");
scanf("%d
%c",&choice,&ch); }
while(choice==1); }
void follow(char c)
{ if(a[0][0]==c)addToResult('$');
VIEAT/B.E/SEM-VII/220943107040
23
Compiler Design (3170701)
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(charc)
{ int k;
if(!(isupper(c)))
//f[m++]=c; addToResult(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];
addToResult(a[k][2]);
else first(a[k][2]);
}}}
void addToResult(char c)
{
int i;
for( i=0;i<=m;i++) if(followResult[i]==c)
return; followResult[m++]=c;
}
Output:
VIEAT/B.E/SEM-VII/220943107040
24
Compiler Design (3170701)
PRACTICAL – 11
Aim: Implement a C program for constructing LL (1) parsing.
Code:
#include<stdio.h
#include<string.h>
#define TSIZE 128
int table[100][TSIZE];
char terminal[TSIZE];
char nonterminal[26];
struct product{
char str[100]; int
len;
}pro[20]; 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 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_pr
=
] o
1].str[0];
pro[no_pro].str[1 = pro[no_pr -
] o
VIEAT/B.E/SEM-VII/220943107040
25
Compiler Design (3170701)
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;
}
}
voidadd_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];
}
}
voidadd_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;
VIEAT/B.E/SEM-VII/220943107040
26
Compiler Design (3170701)
}
if (x == pro[i].len) add_FOLLOW_A_to_FOLLOW_B(pro[i].str[0], nt);
}}}}}}
voidadd_FIRST_A_to_FIRST_B(char A, char B){ int
i; for (i = 0; i < TSIZE; ++i) {
if (i != '^') {
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) {
VIEAT/B.E/SEM-VII/220943107040
27
Compiler Design (3170701)
for (j = 3; j < pro[i].len; ++j) { char sc
= pro[i].str[j];
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;
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"); } }
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("FOLLOW OF %c: ", c); for (j
= 0; j < TSIZE; ++j) {
if (follow[c - 'A'][j]) { printf("%c ", j);
}}
printf("\n");
}}
printf("\n");
for (i = 0; i < no_pro; ++i) { printf("FIRST OF
VIEAT/B.E/SEM-VII/220943107040
28
Compiler Design (3170701)
%s: ", pro[i].str); for (j = 0; j < TSIZE; ++j)
{ if (first_rhs[i][j]) {
printf("%c ", j); } } printf("\n");
}
terminal['$'] =1;
terminal['^'] = 0;
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); } 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");
}}}
VIEAT/B.E/SEM-VII/220943107040
29
Compiler Design (3170701)
Output:
VIEAT/B.E/SEM-VII/220943107040
30
Compiler Design (3170701)
PRACTICAL – 12
Aim: Implement a C program to implement LALR parsing.
Code:
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<string.h>
voidpush(char*,int*,char);
char stacktop(char*);
voidisproduct(char,char); int
ister(char);
int isnter(char);
int isstate(char);
void error();
voidisreduce(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"},
{"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"},
VIEAT/B.E/SEM-VII/220943107040
31
Compiler Design (3170701)
{"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()
{ 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]);
}
}
}
printt(stack,&top,inp,i);
}while(inp[i]!='\0');
if(strcmp(temp,"acc")==0) printf("
\n accept the input "); else
VIEAT/B.E/SEM-VII/220943107040
32
Compiler Design (3170701)
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;
Output:
VIEAT/B.E/SEM-VII/220943107040
34
Compiler Design (3170701)
VIEAT/B.E/SEM-VII/220943107040
35
Compiler Design (3170701)
PRACTICAL – 13
Aim: Implement a C program to implement operator precedence parsing.
Code:
#inclu
de<std
io.h>
#inclu
de<stri
ng.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 '-':return1;
VIEAT/B.E/SEM-VII/220943107040
36
Compiler Design (3170701)
case '*':return 2;
case '/':return3;
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()
{
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;
VIEAT/B.E/SEM-VII/220943107040
37
Compiler Design (3170701)
strcpy(lasthandle,handles[i]);
stack[top+1]='\0';
return 1;//successfulreduction
}}}
return 0;
}
void dispstack()
{
int j;
for(j=0;j<=t
op;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");
dispinput();
printf("\tShift");
if(prec[getindex(stack[top])][getindex(input[i])]=='>')
{
VIEAT/B.E/SEM-VII/220943107040
38
Compiler Design (3170701)
while(reduce())
{
printf("\n");
dispstack(); printf("\
t"); dispinput();
printf("\tReduced: E->%s",lasthandle);}
}}
if(strcmp(stack,"$
E$")==0)
printf("\
nAccepted;");
else
printf("\nNot Accepted;");
}
Output :
VIEAT/B.E/SEM-VII/220943107040
39