Compiler Lab File
Compiler Lab File
Some of the most time consuming and tedious parts of writing a compiler involve the lexical scanning
and syntax analysis. Luckily there is freely available software to assist in these functions. While they
will not do everything for you, they will enable faster implementation of the basic functions. Lex and
Yacc are the most commonly used packages with Lex managing the token recognition and Yacc
handling the syntax. They work well together, but conceivably can be used individually as well. Both
operate in a similar manner in which instructions for token recognition or grammar are written in a
special file format. The text files are then read by lex and/or yacc to produce c code. This resulting
source code is compiled to make the final application. In practice the lexical instruction file has a “.l”
suffix and the grammar file has a “.y” suffix. This process is shown in Figure 1.
The file format for a lex file consists of (4) basic sections
• The first is an area for c code that will be place verbatim at the beginning of the generated source
code. Typically, is will be used for things like #include, #defines, and variable declarations.
• The next section is for definitions of token types to be recognized. These are not mandatory, but in
general makes the next section easier to read and shorter.
• The third section set the pattern for each token that is to be recognized, and can also include c
code to be called when that token is identified
• The last section is for more c code (generally subroutines) that will be appended to the end of the
generated c code. This would typically include a main function if lex is to be used by itself.
• The format is applied as follows (the use and placement of the % symbols are necessary):
%{
//header c code
%}
//definitions
%%
//rules
%%
//subroutines
The format for a yacc file is similar, but includes a few extras.
• The first area (preceded by a %token) is a list of terminal symbols. You do not need to list single
character ASCII symbols, but anything else including multiple ASCII symbols need to be in this list
(i.e. “==”).
• The next is an area for c code that will be place verbatim at the beginning of the generated source
code. Typically is will be used for things like #include, #defines, and variable declarations.
• The next section is for definitions - none of the following examples utilize this area
• The fourth section set the pattern for each token that is to be recognized, and can also include c
code to be called when that token is identified
• The last section is for more c code (generally subroutines) that will be appended to the end of the
generated c code. This would typically include a main function if lex is to be used by itself.
• The format is applied as follows (the use and placement of the % symbols are necessary):
%{
//header c code
%}
//definitions
%%
//rules
%%
//subroutines
Experiment 2
Aim: Write a program to check whether a string belongs to the grammar or not.
Program
#include<stdio.h>
#include<conio.h>
#include<string.h>
void main() { char
string[50]; int
flag,count=o;
clrscr();
printf("The grammar is: S->aS, S->Sb, S-
>ab\n"); printf("Enter the string to be
checked:\n"); gets(string); if(string[0]=='a')
{ flag=0;
for (count=1;string[count-
1]!='\0';count++) {
if(string[count]=='b') { flag=1;
continue;
} else if((flag==1)&&(string[count]=='a')) { printf("The string does
not belong to the specified grammar"); break;
} else if(string[count]=='a')
continue; else
if(flag==1)&&(string[count]='\0')) {
printf("String accepted…..!!!!");
break;
} else { printf("String not
accepted");
}
}
}
getc
h();
}
Output
The grammer is:
S->aS
S->Sb
S->ab
String accepted....!!!!
Experiment 3
Aim : Write a program to generate a parse tree
Program
from pythonds.basic.stack import Stack from
def buildParseTree(fpexp):
fplist =
fpexp.split()
pStack = Stack()
eTree =
BinaryTree('')
pStack.push(eTree)
currentTree =
eTree
for i in
fplist: if
i == '(':
currentTree.insertLeft('')
pStack.push(currentTree)
currentTree = currentTree.getLeftChild()
currentTree.setRootVal(int(i))
parent = pStack.pop()
currentTree = parent
currentTree.insertRight('')
pStack.push(currentTree)
currentTree = currentTree.getRightChild()
elif i == ')':
currentTree = pStack.pop()
else:
raise ValueError
return eTree
Output
Experiment 4
Aim : Write a program to find leading terminals
Program
#include<iostream.h>
#include<stdio.h>
#include<conio.h>
#include<string.h>
int n,d,f,xn,xt,top=-1;
char X,Y; int a[20][20];
char
terminal[20],nonterm[20];
struct production
{
char l;
char r[10];
};
struct stack
{
char nt;
char t;
};
clrscr();
for(i=0;i<=n-1;i++)
{
for(int j=0;j<d;j++)
{
if(prod[i].r[0]==terminal[j])
install(prod[i].l,prod[i].r[0]);
else if(prod[i].r[1]==terminal[j])
install(prod[i].l,prod[i].r[1]);
}
}
while(top>-1)
{
pop();
for(int c=0;c<=n-
1;c++)
{
if(prod[c].r[0]==X)
install(prod[c].l,Y);
}
}
//Output cout<<"\n\n--------------------------------------------
--------------------"; cout<<"\n leading elements are:- " ;
cout<<"\n\n-----------------------------------------------------------------";
cout<<endl<<" ";
for(int w=0;w<d;w++)
cout<<" "<<terminal[w];
cout<<endl;
for(p=0;p<f;p++)
{
cout<<nonterm[p]<<" ";
for(int q=0;q<d;q++)
{
cout<<a[p][q]<<" ";
}
cout<<endl;
}
getch();
}
void install(char
x,char y) { int g;
xn=pon(x);
xt=pot(y);
g=checkstatus(xn,
xt); if(g==0)
return; else
if(g==1)
{
top++;
st[top].nt=x;
st[top].t=y;
a[xn][xt]=1;
}
}
void pop()
{
X=st[top].nt;
Y=st[top].t;
top--;
}
int pon(char u)
{ for(int
x=0;x<f;x++)
{
if(u==nonterm[x])
return x;
}
}
int pot(char v)
{ for(int
x=0;x<d;x++)
{
if(v==terminal[x])
return x;
} } int checkstatus(int
xn,int xt) {
if(a[xn][xt]==1)
return 0; else
return 1;
Output
:
Experiment 5
Aim : Write a program to find trailing terminals
Program
#include<iostream.h>
#include<stdio.h>
#include<conio.h>
#include<string.h>
struct production
{ char l;
char r[10];
int rear;
};
struct stack
{
char nt;
char t;
};
struct stack st[20]; struct
production prod[20];
void main()
{
clrscr();
cout<<"Enter the number of terminals: "; cin>>d;
cout<<"Enter the terminal symbols for your production: ";
for(int k=0;k<d;k++)
{
cin>>terminal[k];
}
for(int p=0;p<f;p++)
{
for(int q=0;q<d;q++)
{
a[p][q]=0;
}
}
for(i=0;i<=n-1;i++)
{
for(int j=0;j<d;j++)
{
if(prod[i].r[prod[i].rear-1]==terminal[j])
install(prod[i].l,prod[i].r[prod[i].rear-1]);
else if(prod[i].r[prod[i].rear-2]==terminal[j])
install(prod[i].l,prod[i].r[prod[i].rear-2]);
}
}
while(top>-1)
{ pop();
for(int c=0;c<=n-1;c++)
{
if(prod[c].r[prod[c].rear-1]==X)
install(prod[c].l,Y);
}
}
cout<<"\n\n****************************************************";
cout<<"\n TRAILING ELEMENTS OF GIVEN PRODUCTION ";
cout<<"\n****************************************************** ";
cout<<endl<<" ";
for(int w=0;w<d;w++)
cout<<" "<<terminal[w];
cout<<endl;
for(p=0;p<f;p++)
{
cout<<nonterm[p]<<" ";
for(int q=0;q<d;q++)
{
cout<<a[p][q]<<" ";
}
cout<<endl;
}
cout<<endl<<endl;
for(i=0;i<f;i++)
{
cout<<"Leading("<<nonterm[i]<<")="<<" "<<"{";
for(int j=0;j<d;j++)
{ if(a[i][j]==1)
cout<<terminal[j]<<",";
}
cout<<"}"<<endl;
}
getch();
}
void pop()
{
X=st[top].nt;
Y=st[top].t; top-
-;
}
int pon(char u)
{ for(int
x=0;x<f;x++)
{
if(u==nonterm[x])
return x;
}
}
int pot(char v)
{ for(int
x=0;x<d;x++)
{
if(v==terminal[x])
return x;
}
}
int checkstatus(int xn,int
xt) { if(a[xn][xt]==1)
return 0; else return 1;
}
Output
Experiment 6
Aim : Write a program to compute FIRST of non-terminals
Program
#include<stdio.h>
#include<conio.h> char
array[10][20],temp[10]; int
void main()
for(i=0;i<n;i++) scanf("%s",array[i]);
for(i=0;i<n;i++)
c=-1,p[0]=-1,p[1]=-1; fun(i,p);
printf("First(%c) : [ ",array[i][0]);
for(j=0;j<=c;j++)
printf("%c,",temp[j]); printf("\b
].\n"); getch();
}
}
{ int k;
if(!key)
{
for(k=0;k<n;k++)
if(array[i][j]==array[k][0])
break; p[0]=i;p[1]=j+1;
fun(k,p); return 0;
else
for(k=0;k<=c;k++)
if(array[i][j]==temp[k])
break;
if(k>c)return 1;
else return 0;
p[])
1]=='/')
key=0;
fun2(i,j,p,key);
else
{
key = 1; if(fun2(i,j,p,key)) temp[++c] = array[i][j];
key=0;
fun2(p[0],p[1],p,key);
array[p[0]][p[1]]!=NULL)
if(fun2(p[0],p[1],p,key))
temp[++c]=array[p[0]][p[1]];
}
}
}
}
}
Output
Experiment 7
Aim : Write a program to compute FOLLOW of non-terminals
Program
#include<stdio.h>
#include<conio.h>
#define max 10
#define MAX 15
void ffun(int,int);
void fun(int,int[]);
char array[max][MAX],temp[max][MAX];
p[],int key)
{ int k; if(!key){
for(k=0;k<n;k++)
if(array[i][j]==array[k][0])
break; p[0]=i;p[1]=j+1;
fun(k,p); return 0;
else{ for(k=0;k<=c;k++){
if(array[i][j]==temp[t][k])
break;
if(k>c)return 1;
else return 0;
}
}
void fun(int i,int p[])
{ int j,k,key;
for(j=2;array[i][j]!=NULL;j++)
if(array[i][j-1]=='/'){
if(array[i][j]>='A'&&array[i][j]<='Z'){
key=0; fun2(i,j,p,key);
temp[t][++c]=array[i][j]; if(array[i][j]=='@'&&p[0]!=-1){
if(array[p[0]][p[1]]>='A'&&array[p[0]][p[1]]<='Z'){
key=0;
fun2(p[0],p[1],p,key);
else
if(array[p[0]][p[1]]!='/'&&array[p[0]][p[1]]!=NULL){
if(fun2(p[0],p[1],p,key))
temp[t][++c]=array[p[0]][p[1]];
void follow(int i)
{ int j,k; for(j=0;j<=ff0;j++)
if(array[i][0]==ff[j]) return;
if(j>ff0)ff[++ff0]=array[i][0];
if(i==0)fol[l][++f]='$';
for(j=0;j<n;j++)
for(k=2;array[j][k]!=NULL;k++)
if(array[j][k]==array[i][0])
ffun(j,k);
{ int ii,null=0,tt,cc;
if(array[j][k+1]=='/'||array[j][k+1]==NULL)
null=1;
for(ii=k+1;array[j][ii]!='/'&&array[j][ii]!=NULL;ii++){
if(array[j][ii]<='Z'&&array[j][ii]>='A')
for(tt=0;tt<n;tt++)
if(temp[tt][0]==array[j][ii])break;
for(cc=1;temp[tt][cc]!=NULL;cc++)
if(temp[tt][cc]=='@')null=1;
else fol[l][++f]=temp[tt][cc];
else fol[l][++f]=array[j][ii];
if(null)follow(j);
}
int main()
scanf("%s",array[i]);
for(i=0,t=0;i<n;i++,t++){ c=0,p[0]=-
1,p[1]=-1; temp[t][0]=array[i][0];
fun(i,p);
temp[t][++c]=NULL;
printf("First(%c) : [ ",temp[t][0]);
for(j=1;j<c;j++)
printf("%c,",temp[t][j]); printf("\b
].\n");
/* Follow Finding */
for(i=0,l=0;i<n;i++,l++)
f=-1;ff0=-1;
fol[l][++f]=array[i][0];
follow(i);
fol[l][++f]=NULL;
for(i=0;i<n;i++)
{
printf("\nFollow[%c] : [
",fol[i][0]);
for(j=1;fol[i][j]!=NULL;j++)
printf("%c,",fol[i][j]); printf("\b
]");
getch();
return 0; }
Output
Experiment 8
Aim : Write a program to check whether a grammar is left recursive and remove left recursion
Program
#include<iostream.h>
#include<stdio.h>
#include<conio.h>
#include<string.h>
struct production
{
char l;
char r[10];
int rear;
};
struct production prod[20],pr_new[20];
void main()
{
clrscr();
for(int m=0;m<f;m++)
{
x=nonterm[m];
for(int j=0;j<n;j++)
{
if((prod[j].l==x)&&(prod[j].r[0]==prod[j].l))
flag=1;
}
for(int i=0;i<n;i++)
{
if((prod[i].l==x)&&(prod[i].r[0]!=x)&&(flag==1))
{
pr_new[b].l=x;
for(int c=0;c<prod[i].rear;c++)
pr_new[b].r[c]=prod[i].r[c];
pr_new[b++].r[c]=alpha[p];
}
else if((prod[i].l==x)&&(prod[i].r[0]==x)&&(flag==1))
{
pr_new[b].l=alpha[p];
for(int a=0;a<=prod[i].rear-2;a++)
pr_new[b].r[a]=prod[i].r[a+1];
pr_new[b++].r[a]=alpha[p];
pr_new[b].l=alpha[p];
pr_new[b++].r[0]=epsilon;
}
else if((prod[i].l==x)&&(prod[i].r[0]!=x)&&(flag==0))
{
pr_new[b].l=prod[i].l;
strcpy(pr_new[b].r,prod[i].r);
b++;
}
}
flag=0;
p++; }
cout<<"\n\n*******************************************";
cout<<"\n AFTER REMOVING LEFT RECURSION ";
cout<<"\n*******************************************"<<endl;
for(int s=0;s<=b-1;s++)
{
cout<<"Production "<<s+1<<" is: ";
cout<<pr_new[s].l;
cout<<"->";
cout<<pr_new[s].r;
cout<<endl;
}
getche();
}
Output
Experiment 9
Aim : Write a program to remove left factoring
Program
#include<iostream.h>
#include<stdio.h>
#include<conio.h>
#include<string.h>
//Structure Declaration
struct production
{ char lf;
char rt[10];
int prod_rear;
int fl;
};
struct production prodn[20],prodn_new[20]; //Creation of object
//Variables Declaration
int b=-1,d,f,q,n,m=0,c=0;
char terminal[20],nonterm[20],alpha[10],extra[10];
char epsilon='^'; //Beginning of Main Program
void main()
{
clrscr();
//Input of Productions
for(int cnt1=0;cnt1<n;cnt1++)
{
for(int cnt2=cnt1+1;cnt2<n;cnt2++)
{
if(prodn[cnt1].lf==prodn[cnt2].lf)
{
cnt=0;
int p=-1;
while((prodn[cnt1].rt[cnt]!='\0')&&(prodn[cnt2].rt[cnt]!='\0'))
{
if(prodn[cnt1].rt[cnt]==prodn[cnt2].rt[cnt])
{
extra[++p]=prodn[cnt1].rt[cnt];
prodn[cnt1].fl=1;
prodn[cnt2].fl=1;
}
else {
if(p==-1)
break; else
{
int h=0,u=0;
prodn_new[++b].lf=prodn[cnt1].lf;
strcpy(prodn_new[b].rt,extra);
prodn_new[b].rt[p+1]=alpha[c];
prodn_new[++b].lf=alpha[c]; for(int
g=cnt;g<prodn[cnt2].prod_rear;g++)
prodn_new[b].rt[h++]=prodn[cnt2].rt[g];
prodn_new[++b].lf=alpha[c];
for(g=cnt;g<=prodn[cnt1].prod_rear;g++)
prodn_new[b].rt[u++]=prodn[cnt1].rt[g];
m=1; break;
}
}
cnt++;
}
if((prodn[cnt1].rt[cnt]==0)&&(m==0))
{
int h=0;
prodn_new[++b].lf=prodn[cnt1].lf;
strcpy(prodn_new[b].rt,extra);
prodn_new[b].rt[p+1]=alpha[c];
prodn_new[++b].lf=alpha[c];
prodn_new[b].rt[0]=epsilon;
prodn_new[++b].lf=alpha[c]; for(int
g=cnt;g<prodn[cnt2].prod_rear;g++)
prodn_new[b].rt[h++]=prodn[cnt2].rt[g];
}
if((prodn[cnt2].rt[cnt]==0)&&(m==0))
{
int h=0;
prodn_new[++b].lf=prodn[cnt1].lf;
strcpy(prodn_new[b].rt,extra);
prodn_new[b].rt[p+1]=alpha[c];
prodn_new[++b].lf=alpha[c];
prodn_new[b].rt[0]=epsilon;
prodn_new[++b].lf=alpha[c]; for(int
g=cnt;g<prodn[cnt1].prod_rear;g++)
prodn_new[b].rt[h++]=prodn[cnt1].rt[g];
}
c++;
m=0;
}
}
}
//Display of Output
cout<<"\n\n********************************";
cout<<"\n AFTER LEFT FACTORING ";
cout<<"\n********************************";
cout<<endl;
for(int cnt3=0;cnt3<=b;cnt3++)
{
cout<<"Production "<<cnt3+1<<" is: ";
cout<<prodn_new[cnt3].lf; cout<<"-
>"; cout<<prodn_new[cnt3].rt;
cout<<endl<<endl;
}
for(int cnt4=0;cnt4<n;cnt4++)
{
if(prodn[cnt4].fl==0)
{
cout<<"Production "<<cnt3++<<" is: ";
cout<<prodn[cnt4].lf; cout<<"->";
cout<<prodn[cnt4].rt;
cout<<endl<<endl;
}
}
getche(); } //end of
main program
Output
Experiment 10
Aim : Write a program to check whether a grammar is Operator precedent
Program
#include<stdio.h>
#include<string.h>
char *input;
int i=0;
char lasthandle[6],stack[50],handles[][5]={")E(","E*E","E+E","i","E^E"};
//(E) becomes )E( when pushed to stack
/*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()
{
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
}
}
}
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);
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;"); }
Output
Experiment 11
Aim : To show all the operations of a stack.
Program
#include<iostream.h>
#include<conio.h>
void main()
{ int
stack[5],ch; int
n=0; char
choice;
clrscr();
do
{
cout<<"\n\n";
cout<<"\nenter the choice::";
cout<<"\n1. push";
cout<<"\n2. pop";
cout<<"\n3. view"; cin>>ch;
if(ch==1)
{ if(n==5) cout<<"\nstack
overflow!!"; else
{
int ele;
cout<<"\nenter the element to be pushed::";
cin>>ele; stack[n]=ele;
n++;
}
}
else
if(ch==2)
{ if(n==-1) cout<<"\nstack
underflow";
else
{
n--;
cout<<"\nElement pop";
}
}
else
if(ch==3)
{ for(int i=0;
i<n;i++)
cout<<stack[i];
}
else cout<<"\ninvalid choice";
cout<<"\nDo you wish to continue\n";
cin>>choice;
}
while(choice=='y'|| choice=='Y');
}
Output
Experiment 12
Aim : To show various operations i.e., read, write and modify in a text file
Program
#include<stdio.h>
#include<fstream.h>
#include<stdlib.h>
#include<conio.h>
class stud
{ int rno,obj;
char name[25];
public:
void getdata()
{cout<<"enter rno and name::";
cin>>rno>>name;}
void showdata()
{
cout<<"\nrno is:"<<rno;
cout<<"\nname is:"<<name;
}
};
void main()
{
int obj; char name[25]; stud stu[5]; clrscr();
fstream fl1;
fl1.open("dfile",ios::out|ios::in|ios::binary|ios::ate);
cout<<"\n <----Writing in the file---->"<<endl;
for(int i=0;i<=4;i++)
{
stu[i].getdata();
fl1.write((char*)&stu[i],sizeof(stu[i]));
}
fl1.seekg(0);
cout<<"\n <----Reading from the file---->"<<endl;
for(i=0;i<=4;i++)
{
fl1.read((char*)&stu[i],sizeof(stu[i]));
stu[i].showdata();
}
cout<<"\n<--Modification in the file-->"<<endl;
cout<<"\nEnter the obj to update";
cin>>obj; int loc=(obj-
1)*sizeof(stu);
if(fl1.eof())
fl1.clear();
fl1.seekp(loc);
stud smo;
cout<<"\nenter new value of obj";
smo.getdata();
fl1.write((char*)&smo,sizeof(smo));
fl1.seekg(0);
cout<<"\n<----Contents of file after modification---->"<<endl;
for(i=0;i<=4;i++)
{
fl1.read((char*)&stu[i],sizeof(stu[i]));
stu[i].showdata();
}
getch();
}