0% found this document useful (0 votes)
21 views68 pages

CD Lab Manual

The document provides a detailed guide on implementing a Lexical Analyzer in C and LEX, including a C program to identify different types of tokens in a given program. It outlines the structure of a LEX program, the algorithm for lexical analysis, and includes sample code for both a C program and a LEX program. Additionally, it covers the brute force technique for top-down parsing in compiler design.

Uploaded by

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

CD Lab Manual

The document provides a detailed guide on implementing a Lexical Analyzer in C and LEX, including a C program to identify different types of tokens in a given program. It outlines the structure of a LEX program, the algorithm for lexical analysis, and includes sample code for both a C program and a LEX program. Additionally, it covers the brute force technique for top-down parsing in compiler design.

Uploaded by

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

Department of Computer Science and Engineering

Compiler Design Lab

1. Write a C program to identify different types of Tokens in a given Program.

As it is known that Lexical Analysis is the first phase of compiler also known as
scanner. It converts the input program into a sequence of Tokens.
A C program consists of various tokens and a token is either a keyword, an identifier, a
constant, a string literal, or a symbol.
For Example:
1) Keywords: Examples- for, while, if etc.

2) Identifier Examples- Variable name, function name etc.

3) Operators Examples- '+', '++', '-' etc.

4) Separators Examples- ', ' ';' etc


Below is a C program to print all the keywords, literals, valid identifiers, invalid
identifiers, integer number, real number in a given C program:

#include <stdbool.h>

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

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


bool isDelimiter(char ch)

if (ch == ' ' || ch == '+' || ch == '-' || ch == '*' ||

ch == '/' || ch == ',' || ch == ';' || ch == '>' ||

ch == '<' || ch == '=' || ch == '(' || ch == ')' ||

ch == '[' || ch == ']' || ch == '{' || ch == '}')

return (true);

return (false);

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

bool isOperator(char ch)

if (ch == '+' || ch == '-' || ch == '*' ||

ch == '/' || ch == '>' || ch == '<' ||

ch == '=')

return (true);

return (false);

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

bool validIdentifier(char* str)

if (str[0] == '0' || str[0] == '1' || str[0] == '2' ||

str[0] == '3' || str[0] == '4' || str[0] == '5' ||

str[0] == '6' || str[0] == '7' || str[0] == '8' ||

str[0] == '9' || isDelimiter(str[0]) == true)

return (false);

return (true);

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

bool isKeyword(char* str)

if (!strcmp(str, "if") || !strcmp(str, "else") ||

!strcmp(str, "while") || !strcmp(str, "do") ||

!strcmp(str, "break") ||

!strcmp(str, "continue") || !strcmp(str, "int")


|| !strcmp(str, "double") || !strcmp(str, "float")

|| !strcmp(str, "return") || !strcmp(str, "char")

|| !strcmp(str, "case") || !strcmp(str, "char")

|| !strcmp(str, "sizeof") || !strcmp(str, "long")

|| !strcmp(str, "short") || !strcmp(str, "typedef")

|| !strcmp(str, "switch") || !strcmp(str, "unsigned")

|| !strcmp(str, "void") || !strcmp(str, "static")

|| !strcmp(str, "struct") || !strcmp(str, "goto"))

return (true);

return (false);

// Returns 'true' if the string is an

INTEGER. bool isInteger(char* str)

int i, len = strlen(str);

if (len == 0)

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

if (str[i] != '0' && str[i] != '1' && str[i] != '2'

&& str[i] != '3' && str[i] != '4' && str[i] != '5'

&& str[i] != '6' && str[i] != '7' && str[i] != '8'

&& str[i] != '9' || (str[i] == '-' && i > 0))

return (false);

return (true);

// Returns 'true' if the string is a REAL NUMBER.

bool isRealNumber(char* str)

int i, len = strlen(str);

bool hasDecimal = false;

if (len == 0)

return (false);

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


if (str[i] != '0' && str[i] != '1' && str[i] != '2'

&& str[i] != '3' && str[i] != '4' && str[i] != '5'

&& str[i] != '6' && str[i] != '7' && str[i] != '8'

&& str[i] != '9' && str[i] != '.' ||

(str[i] == '-' && i > 0))

return (false);

if (str[i] == '.')

hasDecimal = true;

return (hasDecimal);

// Extracts the SUBSTRING.

char* subString(char* str, int left, int right)

int i;

char* subStr = (char*)malloc(

sizeof(char) * (right - left + 2));

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


subStr[i - left] = str[i];

subStr[right - left + 1] = '\0';

return (subStr);

// Parsing the input

STRING. void parse(char*

str)

int left = 0, right =

0; int len =

strlen(str);

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

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

right++;

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

if (isOperator(str[right]) == true)

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

right++;

left = right;
} else if (isDelimiter(str[right]) == true && left != right

|| (right == len && left != right)) {

char* subStr = subString(str, left, right - 1);

if (isKeyword(subStr) == true)

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

else if (isInteger(subStr) == true)

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

else if (isRealNumber(subStr) == true)

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

else if (validIdentifier(subStr) == true

&& isDelimiter(str[right - 1]) == false)

printf("'%s' IS A VALID IDENTIFIER\n", subStr);

else if (validIdentifier(subStr) == false

&& isDelimiter(str[right - 1]) == false)

printf("'%s' IS NOT A VALID IDENTIFIER\n", subStr);

left = right;

}
}

return;

// DRIVER FUNCTION

int main()

// maximum length of string is 100 here

char str[100] = "int a = b + 1c; ";

parse(str); // calling the parse function

return (0);

Output:
'int' IS A KEYWORD
'a' IS A VALID IDENTIFIER
'=' IS AN OPERATOR
'b' IS A VALID IDENTIFIER
'+' IS AN OPERATOR
'1c' IS NOT A VALID IDENTIFIER
2. Write a LEX program to implement a Lexical Analyzer using a Lex Tool.

AIM: To write a program for implementing a Lexical analyser using LEX tool in Linux
platform.

ALGORITHM:
Step1: Lex program contains three sections: definitions, rules, and user subroutines.
Each section must be separated from the others by a line containing only the delimiter,
%%. The format is as follows: definitions %% rules %% user_subroutines

Step2: In definition section, the variables make up the left column, and their definitions
make up the right column. Any C statements should be enclosed in %{..}%. Identifier is
defined such that the first letter of an identifier is alphabet and remaining letters are
alphanumeric.

Step3: In rules section, the left column contains the pattern to be recognized in an input
file to yylex(). The right column contains the C program fragment executed when that
pattern is recognized. The various patterns are keywords, operators, new line character,
number, string, identifier, beginning and end of block, comment statements, preprocessor
directive statements etc.

Step4: Each pattern may have a corresponding action, that is, a fragment of C source
code to execute when the pattern is matched.

Step5: When yylex() matches a string in the input stream, it copies the matched text to
an external character array, yytext, before it executes any actions in the rules section.

Step6: In user subroutine section, main routine calls yylex(). yywrap() is used to get
more input.

Step7: The lex command uses the rules and actions contained in file to generate a
program, lex.yy.c, which can be compiled with the cc command. That program can
then receive input, break the input into the logical pieces defined by the rules in file,
and run program fragments contained in the actions in file.
PROGRAM CODE:
//Implementation of Lexical Analyzer using Lex tool
%{
int COMMENT=0;
%}
identifier [a-zA-Z][a-zA-Z0-9]*
%%
#.* {printf("\n%s is a preprocessor directive",yytext);}
int |
float |
char |
double |
while |
for |
struct |
typedef |
do |
if |
break |
continue |
void |
switch |
return |
else |
goto {
printf("\n\t%s is a keyword",yytext);}
"/*" {COMMENT=1;}{
printf("\n\t %s is a COMMENT",yytext);}
{identifier}\( {if(!COMMENT)
printf("\nFUNCTION \n\t%s",yytext);}
\{ {if(!COMMENT)
printf("\n BLOCK BEGINS");}
\} {if(!COMMENT)
printf("BLOCK ENDS ");}
{identifier}(\[[0-9]*\])? {if(!COMMENT)
printf("\n %s IDENTIFIER",yytext);}
\".*\" {if(!COMMENT)
printf("\n\t %s is a
STRING",yytext);} [0-9]+ {if(!
COMMENT)
printf("\n %s is a NUMBER ",yytext);}
\)(\:)? {if(!COMMENT)
printf("\n\t");ECHO;
printf("\n");}
\( ECHO;
= {if(!COMMENT)
printf("\n\t %s is an ASSIGNMENT OPERATOR",yytext);}
\<= |
\>= |
\< |
== |
\> {if(!COMMENT) printf("\n\t%s is a RELATIONAL OPERATOR",yytext);}
%%
int main(int argc, char **argv)
{
FILE *file;
file=fopen("var.c","r"); if(!
file)
{
printf("could not open the file");
exit(0);
}
yyin=file;
yylex();
printf("\n");
return(0);
}
int yywrap()
{
return(1);
}
INPUT:
//var.c
#include<stdio.h>
#include<conio.h>
void main()
{
int a,b,c;
a=1;
b=2;
c=a+b; printf("Sum:%d",c);
}
OUTPUT:

3. write a C program to simulate Lexical Analyzer to validating a given input String

LOGIC : Read the given input. If the given input matches with any operator
symbol. Then display in terms of words of the particular symbol. Else print not a
operator.
PROGRAM:
#include
#include
void
main()
{
char s[5];
clrscr();
printf("\n Enter any
operator:"); gets(s);
switch(s[0])
{
case'>': if(s[1]=='=')
printf("\n Greater than or
printf("\n Greater than");
break;
case'<': if(s[1]=='=')
printf("\n Less than or equal");
else
printf("\nLess than");
break;
case'=': if(s[1]=='=')
printf("\nEqual to");
else printf("\
nAssignment"); break;
case'!': if(s[1]=='=')
printf("\nNot Equal");
else
printf("\n Bit Not");
break;
case'&': if(s[1]=='&')
printf("\nLogical AND");
else
printf("\n Bitwise AND");
break;
case'|': if(s[1]=='|')
printf("\nLogical OR");
else
printf("\nBitwise OR");
break;
case'+': printf("\n Addition");
break;
case'-': printf("\nSubstraction");
break;
case'*': printf("\nMultiplication");
break;
case'/': printf("\nDivision");
break;
case'%': printf("Modulus");
break;
default: printf("\n Not a operator");
}
getch();
}
Input
Enter any operator: *
Output
Multiplicati

4. Write a C program to Implement the Brute Force Technbique of Top Down


Parsing.

First include the package and Necessary variable. I use the following function int
parse::scannt(char a), void parse::input(),int parse::scant(char b), void
parse::process(),void parse::input(), To perform the operation Processing.
Compiler Design Source code Programming
#include<iostream.h>
#include<conio.h>
#include<string.h>
class parse
{
int nt,t,m[20][20],i,s,n,p1,q,k,j;
char p[30][30],n1[20],t1[20],ch,b,c,f[30][30],fl[30][30];
public:
int scant(char);
int scannt(char);
void process();
void input();
};

int parse::scannt(char a)
{
int c=-1,i;
for(i=0;i<nt;i++)
{
if(n1[i]==a)
{
return i;
}
}
return c;
}

int parse::scant(char b)
{
int c1=-1,j;
for(j=0;j<t;j++)
{
if(t1[j]==b)
{
return j;
}
}
return c1;
}

void parse::input()

{
cout<<"Enter the number of productions:";
cin>>n;
cout<<"Enter the productions one by one"<<endl;
for(i=0;i<n;i++)
cin>>p[i];
nt=0;
t=0;
}

void parse::process()
{
for(i=0;i<n;i++)
{
if(scannt(p[i][0])==-1)
n1[nt++]=p[i][0];
}
for(i=0;i<n;i++)
{
for(j=3;j<strlen(p[i]);j++)
{
if(p[i][j]!='e')
{
if(scannt(p[i][j])==-1)
{
if((scant(p[i][j]))==-1)
t1[t++]=p[i][j];
}
}
}
} t1[t+
+]='$';
for(i=0;i<nt;i++)
{
for(j=0;j<t;j++)
m[i][j]=-1;
}
for(i=0;i<nt;i++)
{
cout<<"Enter first["<<n1[i]<<"]:";
cin>>f[i];
}

for(i=0;i<nt;i++)
{
cout<<"Enter follow["<<n1[i]<<"]:";
cin>>fl[i];
}
for(i=0;i<n;i++)
{
p1=scannt(p[i][0]);
if((q=scant(p[i][3]))!=-1)
m[p1][q]=i;
if((q=scannt(p[i][3]))!=-1)
{
for(j=0;j<strlen(f[q]);j++) m[p1][scant(f[q]
[j])]=i;
}
if(p[i][3]=='e')
{
for(j=0;j<strlen(fl[p1]);j++) m[p1][scant(fl[p1]
[j])]=i;
}
}
for(i=0;i<t;i++)
cout<<"\t"<<t1[i];
cout<<endl;
for(j=0;j<nt;j++)
{
cout<<n1[j];
for(i=0;i<t;i++)
{
cout<<"\t"<<"
"; if(m[j][i]!=-1)
cout<<p[m[j][i]];
}
cout<<endl;
}
}

void main()
{
clrscr();
parse p;
p.input();
p.process();
getch();
}
Top Down Parsing in Complier Design output
Enter the number of
productions:8 Enter the
productions one by one E->TA
A->+TA
A->e
T->FB
B->e
B->*FB
F->(E)
F->i

Enter first[E]: (i
Enter first[A]: +e
Enter first[T]: (i
Enter first[B]: *e
Enter first[F]: (i
Enter follow[E]: $)
Enter follow[A]: $)
Enter follow[T]: +)$
Enter follow[B]: +)$
Enter follow[F]: +*)
$
+()i*$
E E->TA E->TA
A A->+TA A->e A->e
T T->FB T->FB
B B->e B->e B->*FB B->e
F F->(E) F->i
5. Write a C program to implement a Recursive Descent Parser.

The grammar on which we are going to do recursive descent parsing is:

E -> E+T | T
T -> T*F | F
F -> (E) | id
RD parser will verify whether the syntax of the input stream is correct by checking each
character from left to right. A basic operation necessary is reading characters from the
input stream and matching then with terminals from the grammar that describes the
syntax of the input.

The given grammar can accept all arithmetic equations involving +, * and ().
eg:
a+(a*a) a+a*a , (a), a , a+a+a*a+a.....etc are accepted
a++a, a***a, +a, a*, ((a......etc are rejected.

Solution:
First we have to avoid left recursion

E -> TE'
E' -> +TE' |
ε T -> FT'
T' -> *FT' |
ε F -> (E) |
id

After eliminating Left recursion, we have to simply move from one character to next by
checking whether it follow the grammar. In this program, ε is indicated as $.

recursive.c

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

char input[10];
int i,error;
void E();
void T();
void Eprime();
void Tprime();
void F();
main()
{
i=0;
error=0;
printf("Enter an arithmetic expression : "); // Eg: a+a*a
gets(input);
E();
if(strlen(input)==i&&error==
0) printf("\
else printf("\nRejected..!!!\n");
}

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]=='(')
{
i++;
E();
if(input[i]==')')
i++;

else
Output:error=1;
a+(a*a) a+a*a , (a), a , a+a+a*a+a.... etc are accepted
}
++a, a***a, +a, a*, ((a . . . etc are rejected.
6. Writeelse
a C program to Caluclate FIRST and FOLLOW of the following Grammer.
error=1;
#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)

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

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

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

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)

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;

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

+;

}
7. Write a C program for eliminating the left recusrion and left Factoring of a
given grammer.

Left Recursion Program IN C:

#include<stdio.h
>
#include<string.h>
void main() {
char
input[100],l[50],r[50],temp[10],tempprod[20],productions[25
][50];
int i=0,j=0,flag=0,consumed=0;
printf("Enter the productions: ");
scanf("%1s->%s",l,r);
printf("%s",r);
while(sscanf(r+consumed,"%[^|]s",temp) == 1 &&
consumed <= strlen(r)) {
if(temp[0] == l[0]) {
flag = 1;
sprintf(productions[i++],"%s->%s%s'\0",l,temp+1,l);
}
else
sprintf(productions[i++],"%s'->%s%s'\0",l,temp,l);
consumed += strlen(temp)+1;
}
if(flag == 1) {
sprintf(productions[i++],"%s->ε\0",l);
printf("The productions after eliminating Left Recursion
are:\n");
for(j=0;j<i;j++)
printf("%s\n",productions[j]);
}
else
printf("The Given Grammar has no Left Recursion");
}

OUTPUT:

Enter the productions: E->E+E|T


The productions after eliminating Left Recursion
are: E->+EE'
E'->TE'
E->ε

Left Factoring IN C:
#include<iostream>

#include<string>

using namespace std;

int main()

{ string ip,op1,op2,temp;

int sizes[10] = {};

char c;

int n,j,l;

cout<<"Enter the Parent Non-Terminal : ";

cin>>c;

ip.push_back(c);

op1 += ip + "\'->";

op2 += ip + "\'\'->";;

ip += "->";

cout<<"Enter the number of productions : ";

cin>>n;

for(int i=0;i<n;i++)

cout<<"Enter Production "<<i+1<<" : ";

cin>>temp;

sizes[i] = temp.size();
ip+=temp;

if(i!=n-1)

ip += "|";

cout<<"Production Rule : "<<ip<<endl;

char x = ip[3];

for(int i=0,k=3;i<n;i++)

if(x == ip[k])

if(ip[k+1] == '|')

op1 += "#";

ip.insert(k+1,1,ip[0]);

ip.insert(k+2,1,'\'');

k+=4;

else

op1 += "|" + ip.substr(k+1,sizes[i]-1);

ip.erase(k-1,sizes[i]+1);

else

{
while(ip[k++]!='|');

char y = op1[6];

for(int i=0,k=6;i<n-1;i++)

if(y == op1[k])

if(op1[k+1] == '|')

op2 += "#";

op1.insert(k+1,1,op1[0]);

op1.insert(k+2,2,'\'');

k+=5;

else

temp.clear();

for(int s=k+1;s<op1.length();s++)

temp.push_back(op1[s]);

op2 += "|" + temp;

op1.erase(k-1,temp.length()+2);

} }}

op2.erase(op2.size()-1);

cout<<"After Left Factoring : "<<endl;


cout<<ip<<endl;

cout<<op1<<endl;

cout<<op2<<endl;

return 0;

OUTPUT:

Enter the Parent Non-Terminal : L

Enter the number of productions :

4 Enter Production 1 : i

Enter Production 2 : iL

Enter Production 3 : (L)

Enter Production 4 :

iL+L

Production Rule : L->i|iL|(L)|iL+L

After Left Factoring :

L->iL'|(L)

L'->#|LL''

L''->#|+L

8. Write a C program to check the validity of input string using Predictive Parser

#include<stdio.h> #include<ctype.h> #include<string.h> #include<stdlib.h> #define SIZE 128


#define NONE -1 #define EOS '\0' #define NUM 257
#define KEYWORD 258
#define ID 259
#define DONE 260
#define MAX 999 char lexemes[MAX];
char buffer[SIZE];
int lastchar=-1;
int lastentry=0;
int tokenval=DONE;
int lineno=1;
int lookahead;
struct entry
{
char *lexptr;
int token;
}
symtable[100];
struct entry
keywords[]=
{"if",KEYWORD,"else",KEYWORD,"for",KEYWORD,"int",KEYWORD,"float",KEYWORD,

"double",KEYWORD,"char",KEYWORD,"struct",KEYWORD,"return",KEYWORD,0,0
};
void Error_Message(char *m)
{
fprintf(stderr,"line %d, %s \n",lineno,m);
exit(1);
}
int look_up(char s[ ])
{
int k;
for(k=lastentry; k>0; k--)
if(strcmp(symtable[k].lexptr,s)==0)
return k;
return 0;
}
int insert(char s[ ],int tok)
{
int len;
len=strlen(s);
if(lastentry+1>=MAX)
Error_Message("Symbpl table is full");
if(lastchar+len+1>=MAX)
Error_Message("Lexemes array is full");
lastentry=lastentry+1;
symtable[lastentry].token=tok;
symtable[lastentry].lexptr=&lexemes[lastchar+1];
lastchar=lastchar+len+1;
strcpy(symtable[lastentry].lexptr,s);
return lastentry;
}
/*void Initialize()
{
struct entry *ptr;
for(ptr=keywords;ptr->token;ptr+1)
insert(ptr->lexptr,ptr->token);
}*/
int lexer()
{
int t;
int val,i=0;
while(1)
{
t=getchar();
if(t==' '||t=='\t');
else if(t=='\n')
lineno=lineno+1;
else if(isdigit(t))
{
ungetc(t,stdin);
scanf("%d",&tokenval);
return NUM;
}
else if(isalpha(t))
{
while(isalnum(t))
{
buffer[i]=t;
t=getchar();
i=i+1;
if(i>=SIZE)
Error_Message("Compiler error");
}
buffer[i]=EOS;
if(t!=EOF)
ungetc(t,stdin);
val=look_up(buffer);
if(val==0)
val=insert(buffer,ID);
tokenval=val;
return symtable[val].token;
}
else if(t==EOF)
return DONE;
else
{
tokenval=NONE;
return t;
}
}
}
void Match(int t)
{
if(lookahead==t)
lookahead=lexer();
else
Error_Message("Syntax error");
}
void display(int t,int tval)
{
if(t=='+'||t=='-'||t=='*'||t=='/') printf("\
nArithmetic Operator: %c",t);
else if(t==NUM)
printf("\n Number: %d",tval);
else if(t==ID)
printf("\n Identifier: %s",symtable[tval].lexptr);
else
printf("\n Token %d tokenval %d",t,tokenval);
}
void F()
{
//void E();
switch(lookahead)
{
case '(' :
Match('(');
E();
Match(')');
break;
case NUM :
display(NUM,tokenval);
Match(NUM);
break;
case ID :
display(ID,tokenval);
Match(ID);
break;
default :
Error_Message("Syntax error");
}
}
void T()
{
int t;
F();
while(1)
{
switch(lookahead)
{
case '*' :
t=lookahead;
Match(lookahead);
F();
display(t,NONE);
continue;
case '/' :
t=lookahead;
Match(lookahead);
display(t,NONE);
continue;
default :
return;
}
}
}
void E()
{
int t;
T();
while(1)
{
switch(lookahead)
{
case '+' :
t=lookahead;
Match(lookahead);
T();
display(t,NONE);
continue;
case '-' :
t=lookahead;
Match(lookahead);
T();
display(t,NONE);
continue;
default :
return;
}
}
}
void parser()
{
lookahead=lexer(); while(lookahead!=DONE)
{
E();
Match(';');
}
}
int main()
{
char ans[10];
printf("\n Program for recursive descent parsing "); printf("\n Enter the expression ");
printf("And place ; at the end\n"); printf("Press Ctrl-Z to terminate\n"); parser();
return 0;
}

SAMPLE OUTPUT:

Program for recursive descent parsing


Enter the expression And place ; at the
end Press Ctrl-Z to terminate
a*b+c;

Identifier: a
Identifier: b
Arithmetic Operator:
* Identifier: c
Arithmetic Operator:
+ 5*7;

Number: 5
Number: 7
Arithmetic Operator: *
*2;
line 5, Syntax error
9. Write a C program for Implementation of LR parsing algorithm to accept a
given input string.

#include<stdio.h>

#include<conio.h>

#include<stdlib.h>

#include<stdbool.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"},

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

};

void main()

char inp[80],x,p,dl[80],y,bl='a';

int i=0,j,k,l,n,m,c,len;

clrscr();

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

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

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

Output:
10. Write a C program for Implementing of a shift reduce parser using stack
Data Structure to accept a given input string of a given grammer.

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

#define MAX 100

// Stack implementation
struct stack {
int top;
char items[MAX];
};

void push(struct stack *s, char c)


{ if (s->top == MAX - 1) {
printf("Stack is full\n");
} else {
s->top++;
s->items[s->top] = c;
}
}
char pop(struct stack *s) {
char c;
if (s->top == -1) {
printf("Stack is empty\n");
return '\0';
} else {
c = s->items[s-
>top]; s->top--;
return c;
}
}

// Parsing function
void parse(char input[], char grammar[][10], int n)
{ struct stack s;
s.top = -1;
int i, j, k;
char c;
push(&s, '$'); // Pushing the end marker on the stack
push(&s, grammar[0][0]); // Pushing the start symbol on the stack

i = 0;
while (input[i] != '\0')
{ c = input[i];
if (c == s.items[s.top]) { // If top of stack is same as input symbol, pop from stack and
move to next input symbol
pop(&s);
i++;
} else if (s.items[s.top] >= 'A' && s.items[s.top] <= 'Z') { // If top of stack is a non-terminal
for (j = 0; j < n; j++) {
if (grammar[j][0] == s.items[s.top]) { // Find the production rule for the non-terminal
for (k = strlen(grammar[j])-1; k >= 3; k--) { // Push the production rule in reverse
order onto the stack
push(&s, grammar[j][k]);
}
}
}
if (s.items[s.top] >= 'A' && s.items[s.top] <= 'Z') { // If top of stack is still a non-
terminal, it cannot be reduced further
printf("Invalid input string\n");
return;
}
} else {
printf("Invalid input string\n");
return;
}
}

if (s.items[s.top] == '$') { // If end marker is on top of stack, input string is


valid printf("Valid input string\n");
} else {
printf("Invalid input string\n");
}
}

// Driver function
int main() {
char input[100];
printf("Enter the input string: ");
scanf("%s", input);

char grammar[][10] = { // Example grammar: S -> AB, A -> a, B -> b


"S->AB",
"A->a",
"B->b"
};
int n = sizeof(grammar)/sizeof(grammar[0]);

parse(input, grammar, n);

return 0;
}
11. Simulate the calculator using LEX and Yacc tool.

PROGRAM CODE:

//Implementation of calculator using LEX and YACC

LEX PART:

%
{

#include<stdio.h>

#include "y.tab.h"

extern int yylval;

%
}

%
%

[0 - 9] + {

yylval = atoi(yytext);

return NUMBER;

[\t];

[\n]
return 0;

.return yytext[0];

%
%

int yywrap()

{
return 1;

YACC PART:

%
{

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

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

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

|
NUMBER {
$$ = $1;
}

%
%

void main()

{
printf("\nEnter Any Arithmetic Expression which can have operations Addition,
Subtraction, Multiplication, Divison, 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 :
12. Generate YACC specification for a few syntactic categories.

a) Program to recognize a valid arithmetic expression that uses operator + , -, * and / .

Program name: arith_id.l

%
{
/* This LEX program returns the tokens for the expression */
#include “y.tab.h”

%
}

%
%“=”{
printf(“\n Operator is EQUAL”);
}“ + ”{
printf(“\n Operator is PLUS”);
}“ - “{
printf(“\n Operator is MINUS”);
}“
/” {printf(“\n Operator is DIVISION”);}“ * ”{
printf(“\n Operator is MULTIPLICATION”);
}

[a - z A - Z] * [0 - 9] * {
printf(“\n Identifier is % s”, yytext);
return ID;
}
return yytext[0];\
n
return 0; %
%

int yywrap() {
return 1;
}

Program Name: arith_id.y

%
{
#include

/* This YYAC program is for recognizing the Expression */ %


}%
%
statement: A’ = ’E |
E{
printf(“\n Valid arithmetic expression”);
$$ = $1;
};

E: E’ + ’ID |
E’ - ’ID |
E’ * ’ID |
E’ / ’ID |
ID; %
%
extern FILE * yyin;
main() {
do {
yyparse();
} while (!feof(yyin));
}

yyerror(char * s) {}

Output:

[root@localhost]# lex arith_id.1


[root@localhost]# yacc –d arith_id.y
[root@localhost]# gcc lex.yy.c
y.tab.c [root@localhost]# ./a.out
x=a+b;

Identifier is x
Operator is EQUAL
Identifier is a
Operator is PLUS
Identifier is b
b) Program to recognise a valid variable which starts with a
letter followed by any number of letters or digits.

Program name: variable_test.l

%
{
/* This LEX program returns the tokens for the Expression */
#include "y.tab.h"

%
}%
%
"int " {
return INT;
}
"float" {
return FLOAT;
}
"double" {
return DOUBLE;
}
[a - zA - Z] * [0 - 9] * {
printf("\nIdentifier is %s", yytext);
return ID;
}
return yytext[0];\
n
return 0;
int yywrap() {
return 1;
}

Program name: variable_test.y

%
{
#include

/* This YACC program is for recognising the Expression*/ %


}%
token ID INT FLOAT DOUBLE %
%
D;
TL
;
L: L, ID |
ID;
T: INT |
FLOAT |
DOUBLE; %
%
extern FILE * yyin;
main() {
do {
yyparse();
} while (!feof(yyin));
}
yyerror(char * s) {}

Output:

[root@localhost]# lex variable_test.I


[root@localhost]# yacc –d variable_test.y
[root@localhost]# gcc lex.yy.c y.tab.c
[root@localhost]# ./a.out
int a,b;

Identifier is a
Identifier is b[root@localhost]#

13. Write a C program for generating the three address code of a


given expression/statement.

Source 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++;
}
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();
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);
}
}
}
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
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

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

14. Write a C program for the implementation of a code Generation Algorithm of a


given expression/statement.

You might also like