Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

CD Labmanual

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 54

Design a Lexical analyzer for the given language.

The lexical
analyzer should ignore redundant spaces, tabs and newlines. It
should also ignore comments. Although the syntax specification
states that identifiers can be arbitrarily long, you may restrict the
length to some reasonable value.

Description:

The first phase of the compiler is lexical analysis or scanning.Lexical analyzer


divides the source code in to tokens.We can design lexical analyzer using c
language.

For example, in lexical analysis the characters in the assignment statement

position:=initial + rate * 60

would be grouped into the following tokens.

The identifier position

The assignment operator :=

The identifier initial

The multiplication sign

The number 60

Program:

/* a C progam to implement lexical analyzer */

#include<stdio.h>
#include<ctype.h>
#include<string.h>
main()
{
intcount,i,j,p;
char c,s,ch,st[50];
FILE *fp;
count=0;
fp=fopen("g.c","r");
if(fp==NULL)
{
printf("cannot open source file\n");
return 0; }
while(1)
{
ch=fgetc(fp);
if(ch==EOF)
break;

while(1)

if(count==1)

count=0;

if(isalpha(ch))

s=ch;

ch='x';

else if(isdigit(ch))

{
ch='y';

else if(ch=='('|| ch==')'|| ch=='{'|| ch=='}'|| ch==';'|| ch==':'|| ch=='|'|| ch=='"'||ch==',')

ch='z';

else if(ch=='/')

c=fgetc(fp);

if(c=='/')

while(c!='\n')

c=fgetc(fp);

break;

else if(c=='*')

while(1)

if(fgetc(fp)=='*')

if(fgetc(fp)=='/')
{

p=1;

break;

if(p==1)

p=0;

break;

else

ch='z';

else if(ch=='+'||ch=='*'||ch=='/'||ch=='%'||ch=='^')

ch='w';

switch(ch)
{

case '<':{c=fgetc(fp);

if(c=='=')

printf("\n less than or equal\t");

else

printf("\n less than\t");

count=1;

break;

case '>':

c=fgetc(fp);

if(c=='=')

printf("\n greater than or equal\t");

else

printf("\n greater than\t");

count=1;

break;
}

case '=':

c=fgetc(fp);

if(c=='=')

printf("\n equal to\t");

else

printf("\n assignment operator\t");

count=1;

break; }

case '!':

if(fgetc(fp)=='=')

printf("\n not equal\t");

break;

case 'x':

{
i=0;

st[i++]=s;

c=fgetc(fp);

while(isalpha(c)||isdigit(c)||c=='-')

st[i++]=c;

c=fgetc(fp);

st[i]='\0';

count=1;

if(strcmp(st,"int")==0||strcmp(st,"float")==0||strcmp(st,"char")==0||
strcmp(st,"static")==0||strcmp(st,"do")==0||strcmp(st,"case")==0||
strcmp(st,"while")==0||strcmp(st,"if")==0||strcmp(st,"else")==0||
strcmp(st,"auto")==0||strcmp(st,"for")==0)

printf("\n keyword\t\t");

else

printf("\n identifier\t");

break;

}
case 'y':

c=fgetc(fp);

while(isdigit(c))

c=fgetc(fp);

if(c=='.')

c=fgetc(fp);

while(isdigit(c))

c=fgetc(fp);

printf("\n real constant\t");

else

printf("\n integer constant\t");

count=1;

break;

case 'z':
{

printf("\n special symbol\t");

break;

case 'w':

printf("\n arthmetic operator\t");

break;

case ' ':break;

case '\n':

printf("\n");

break;

ch=c;

if(count==0)

break;

} } }

fclose(fp);
return 0;

OUTPUT:
g.c program is:
main()
{
inta,b;
a=10;
}
Output is:
identifier
special symbol
special symbol

special symbol

keyword
identifier

Implement the lexical analyzer using JLex, flex or lex or other lexical
analyzer generating tools.
Description:

The first phase of the compiler is lexical analysis or scanning.Lexical analyzer


divides the source code intptokens.We can design lexical analyzer using LEX
tool.

Lex is an unix utility which generates the lexical analyzer in lex tool designing the
regular expressions for corresponding tokens is a logical task. The file name can
be specified as lex.l and is given to lex compiler to produce lex.yy.c. the lex.yy.c
is given to C compiler to produce executable program.

Program:
delim [ \t\n]
ws {delim}+
digit [0-9]
num {digit}+
num1 {digit}+.{digit}+
letter [a-zA-Z]
id {letter}({letter}|{digit})*

%%

{ws} { }
{num1} {printf("\n %s \t\treal\n",yytext);}

{num} {printf("\n %s \t\tinteger\n",yytext);}


int|float|long|double|short|main|for|while|do|case|break|continue|if|else {printf("\n
%s \t\tkeyword\n",yytext);}
{id} {printf("\n %s \t\tidentifier\n",yytext);}
\+|-|\*|\/|\% {printf("\n %s \t\tarthemetic operator\n",yytext);}
\+\+ {printf("\n %s \t\tincrement operator\n",yytext);}
-- {printf("\n %s \t\tdecrement operator\n",yytext);}
,|\{|\}|\[|\]|\;|\:|\(|\) {printf("\n %s \t\tspecial symbol",yytext);}
#.* {printf("\n %s \t\t preprocessor directive",yytext);}
==|!=|<=|>= {printf("\n %s \t\t relational operator",yytext);}
= {printf("\n %s \t\t assignment operaor",yytext);}
\&\&|\|\||\! {printf("\n %s \t\t logical operator",yytext);}
\/\*.*\*\/|\/\/.* {printf("\n %s is a comment",yytext);}
%%
OUTPUT:
Execution:
$lexlexcial.l
$cc lex.yy.c -lfl
$./a.out<ex.c
ex.c program:
// ex.c
/* program as i/p for lex.l */
#include<stdio.h>
main()
{
int a=2;
float b=5.6;
printf("hello");
}
Output:
// ex.c is a comment
/* program as i/p for lex.l */ is a comment
#include<stdio.h> preprocessor directive
main keyword
( special symbol
) special symbol
{ special symbol
int keyword
a identifier
= assignment operaor
2 integer
; special symbol
float keyword
b identifier
= assignment operaor
5.6 real
; special symbol
printf identifier
( special symbol"
hello identifier
"
) special symbol
; special symbol
} special symbol

Construct a recursive descent parser for the following


grammar

E->TE1

E1->+TE1 | Epsilon

T->FT1

T1->*FT1 | Epsilon

F->(E) | i

Description:

Recursive Descent parser is the one of the Predictive parser. In Recursive Descent
parsing, we create a separate function for each nonterminal in the given
grammar.Parser program activated by function of start symbol.
/*
implementation of recursive descent (predictive parser) for the grammer
E->TE1
E1->+TE1 | Epsilon
T->FT1
T1->*FT1 | Epsilon
F->(E) | i
*/
#include<stdio.h>
#include<string.h>
charip[100];
char *ptr;
void E(void);
void E1(void);
void T(void);
void T1(void);
void F(void);
main()
{
system("clear");
printf("\nenter the string to be parsed with $ at end\n");
scanf("%s",ip);
ptr=ip;
E();
if(*ptr=='$')
{
printf("\nSting : %s is Accepted",ip);
}
else
{
printf("\nString : %s is Rejected",ip);
}
}
void E(void)
{
T();
E1();
}
void E1(void)
{
if(*ptr=='+')
{
ptr++;
T();
E1();
}
else
{
/*do nothing as E1 -> epsilon*/
}

}
void T(void)
{
F();
T1();
}
void T1(void)
{
if(*ptr=='*')
{
ptr++;
F();
T1();
}
else
{
/*do nothing as T1 -> epsilon*/
}
}
void F(void)
{
if(*ptr=='(')
{
ptr++;
E();
if(*ptr==')')
ptr++;
else
{
printf("\nERROR");
ptr++;
}
}
else if(*ptr=='i')
ptr++;
}
OUTPUT :
enter the string to be parsed with $ at end
i+i*i$
Sting :i+i*i$ is Accepted
enter the string to be parsed with $ at end
i+i*(i+i)$
String :i+i*(i+i) is Rejected

Simulate First and Follow of a Grammar


Description:

char T[]="+*()de";

char NT[]="EATBF";

char FT[5][6];

char FLWT[5][6];

char P[8][10]={ "E->TA",

"A->+TA",

"A->e",

"T->FB",

"B->*FB",

"B->e",

"F->(E)",

"F->d" };

intgetIndex(char A[],char c)
{

int i=0;

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

if(A[i]==c)

return i;

return -1;

voidaddEpsilon(char c)

FT[getIndex(NT,c)][5]='e';

inthasEpsilon(char c)

if(FT[getIndex(NT,c)][5]=='e')

return(1);

return(0);

intisNonTerminal(char c)

int i;

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

if(NT[i]==c)

return 1;

return 0;

intisTerminal(char c)

int i=0;

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

if(T[i]==c)

return 1;

return 0;

voidComputeFollow()

intlen,i,j,k,added=0;

char sym1,sym2,elm1,elm2,sym;

FLWT[getIndex(NT,'E')][5]='$';

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

len=strlen(P[i]);

for(j=3;j<len;j++)

sym1=P[i][j];

sym2=P[i][j+1];

if(isNonTerminal(sym1) &&isTerminal(sym2))

FLWT[getIndex(NT,sym1)][getIndex(T,sym2)]=sym2;

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

len=strlen(P[i]);

for(j=3;j<len;j++)

sym1=P[i][j];

sym2=P[i][j+1];

if(isNonTerminal(sym1) &&isNonTerminal(sym2))

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

elm1=FLWT[getIndex(NT,sym1)][k];

elm2=FT[getIndex(NT,sym2)][k];
if(elm1!=elm2)

if(elm2!='\0' && elm2!='e')

FLWT[getIndex(NT,sym1)][k]=elm2;

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

sym1=P[i][strlen(P[i])-1];

if(isNonTerminal(sym1))

sym2=P[i][0];

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

elm1=FLWT[getIndex(NT,sym1)][k];

elm2=FLWT[getIndex(NT,sym2)][k];

if(elm1!=elm2)

if(elm2!='\0' && elm2!='e')

{
added=1;

FLWT[getIndex(NT,sym1)][k]=elm2;

sym=P[i][strlen(P[i])-1];

if(isNonTerminal(sym) &&hasEpsilon(sym))

sym1=P[i][strlen(P[i])-2];

if(isNonTerminal(sym1))

sym2=P[i][0];

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

elm1=FLWT[getIndex(NT,sym1)][k];

elm2=FLWT[getIndex(NT,sym2)][k];

if(elm1!=elm2)

if(elm2!='\0' && elm2!='e')

added=1;

FLWT[getIndex(NT,sym1)][k]=elm2;

}
}

if(i==7)

if(added)

i=-1;

added=0;

voidComputeFirst()

int added=0,i,j,k;

char X,elm1,elm2;

clrscr();

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

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

{
FT[i][j]='\0';

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

X = P[i][3];

if(X=='e')

addEpsilon(P[i][0]);

else if(isTerminal(X))

FT[getIndex(NT,P[i][0])][getIndex(T,X)]=X;

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

X = P[i][3];

if(isNonTerminal(X))

for(j=3;j<6;j++) {

X=P[i][j];

for(k=0;k<5;k++)
{

elm1=FT[getIndex(NT,P[i][0])][k];

elm2=FT[getIndex(NT,X)][k];

if(elm1!=elm2)

if(elm2!='\0')

added=1;

FT[getIndex(NT,P[i][0])][k]=elm2;

if(!hasEpsilon(X))

break;

if(j==strlen(P[i]))

added=1;

FT[getIndex(NT,P[i][0])][5]='e';

if(i==7)

if(added)
{

i=-1;

added=0;

void main()

inti,j;

ComputeFirst();

printf("THE GIVEN GRAMMAR IS::\n");

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

printf("%s\n",P[i]);

printf("\nThe FIRST for all grammar symbols::\n");

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

printf("FIRST(%c)={",NT[i]);

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

if(FT[i][j]!='\0')

printf("%c,",FT[i][j]);

}
printf("\b}\n");

ComputeFollow();

printf("\nThe FOLLOW for all grammar symbols::\n");

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

printf("FOLLOW(%c)={",NT[i]);

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

if(FLWT[i][j]!='\0')

printf("%c,",FLWT[i][j]);

printf("\b}\n");

getch();

Output:

THE GIVEN GRAMMAR IS::

E->TA

A->+TA

A->e

T->FB

B->*FB

B->e

F->(E)
F->d

The FIRST for all grammar symbols::

FIRST(E)={(,d}

FIRST(A)={+,e}

FIRST(T)={(,d}

FIRST(B)={*,e}

FIRST(F)={(,d}

The FOLLOW for all grammar symbols::

FOLLOW(E)={),$}

FOLLOW(A)={),$}

FOLLOW(T)={+,),$}

FOLLOW(B)={+,),$}

FOLLOW(F)={+,*,),$}

Write a program to implement LALR Bottom up parser


Description:

YACC is one automatic tool for generating the parser program. YACC stands for
Yet Another Compiler Compiler with is basically the utility available from unix.
YACC can report conflicts in the form of error messages.

Program:

/* File name: parser.l */

%{
#include<stdio.h>
#include"y.tab.h"
%}
%%
[0-9]+ { yylval.dval=atoi(yytext);
return DIGIT;
}
\n|. returnyytext[0];
%%

/* File name :parser.y */

%{
#include<stdio.h>
%}

/* to define possible symbol types */

%union
{
doubledval;
}

/* tokens used, which are returned by lexical analyzer */

%token <dval> DIGIT

/* sets the type for non terminals */

%type <dval>expr
%type <dval> term
%type <dval> factor

%%

line: expr '\n' { printf("%g\n",$1);};


expr: expr '+' term {$$ = $1 + $3;}|term;
term: term '*' factor {$$ = $1 * $3;}|factor;
factor: '(' expr ')' {$$ = $2;}|DIGIT;

%%

int main()
{
printf("enter expression : ");
yyparse();
return 0;
}
yyerror(char *s)
{
printf("%s",s);
}

Execution:

$lexparser.l
$yacc -d parser.y
$cc lex.yy.cy.tab.c -ll -lm
$./a.out
enter expression :2+3*5
17

Develop an operator precedence parser for a given language

Description:operator precedence parser is one of the bottom up parser.

Method:
1.Let the input string to be initially the stack contains, when the reduce action takes place we
have to reach create parent child relationship.

2. See IP to pointer to the first symbol of input string and repeat forever if only $ is on the
input accept and break else begin.

3. Let 'd’ be the top most terminal on the stack and 'b' be current input IF(a<b) or a=b then
Begin push 'b' onto the stack.

4. Advance Input to the stack to the next Input symbol


end;
else if(a>b)
5. Repeat pop the stack until the top most terminal is related by < to the terminal most
recently popped else error value routine
end;

#include<stdio.h>

#include<conio.h>

#include<string.h>

#include<ctype.h>

char q[9][9]={

{'>','>','<','<','<','<','>','<','>' },

{'>','>','<','<','<','<','>','<','>' },

{'>','>','>','>','<','<','>','<','>' },

{'>','>','>','>','<','<','>','<','>' },

{'>','>','<','<','<','<','>','<','>' },

{'<','<','<','<','<','<','=','<','E' },

{'>','>','>','>','>','E','>','E','>' },

{'>','>','>','>','>','E','>','E','>' },

{'<','<','<','<','<','<','E','<','A' }

};

char s[30],st[30],qs[30];

int top=-1,r=-1,p=0;

void push(char a)

top++;

st[top]=a;

char pop()

char a;
a=st[top];

top--;

return a;

int find(char a)

switch(a)

case '+':return 0;

case '-':return 1;

case '*':return 2;

case '/':return 3;

case '^':return 4;

case '(':return 5;

case ')':return 6;

case 'a':return 7;

case '$':return 8;

default :return -1;

void display(char a)

printf("\n Shift %c",a);

void display1(char a)

{
if(isalpha(a))

printf("\n Reduce E->%c",a);

else if((a=='+')||(a=='-')||(a=='*')||(a=='/')||(a=='^'))

printf("\n Reduce E->E%cE",a);

else if(a==')')

printf("\n Reduce E->(E)");

intrel(char a,charb,char d)

if(isalpha(a)!=0)

a='a';

if(isalpha(b)!=0)

b='a';

if(q[find(a)][find(b)]==d)

return 1;

else

return 0;

void main()

char s[100];

int i=-1;

clrscr();

printf("\n\t Operator Preceding Parser\n");

printf("\n Enter the Arithmetic Expression End with $..");

gets(s);
push('$');

while(i)

if((s[p]=='$')&&(st[top]=='$'))

printf("\n\nAccepted");

break;

else if(rel(st[top],s[p],'<')||rel(st[top],s[p],'='))

display(s[p]);

push(s[p]);

p++;

else if(rel(st[top],s[p],'>'))

do

r++;

qs[r]=pop();

display1(qs[r]);

while(!rel(st[top],qs[r],'<'));

getch();
}

Output:

Operator Preceding Parser

Enter the Arithmetic Expression End with $..a+b*a$

Shift a

Reduce E->a

Shift +

Shift b

Reduce E->b

Shift *

Shift a

Reduce E->a

Reduce E->E*E

Reduce E->E+E

Accepted

Implementation of shift reduce parsing algorithm.


Description: shift-reduce parser uses a parse stack which (conceptually) contains
grammar symbols. During the operation of the parser, symbols from the input are shifted
onto the stack. If a prefix of the symbols on top of the stack matches the RHS of a
grammar rule which is the correct rule to use within the current context, then the parser
reduces the RHS of the rule to its LHS, replacing the RHS symbols on top of the stack
with the nonterminal occurring on the LHS of the rule. This shift-reduce process
continues until the parser terminates, reporting either success or failure. It terminates with
success when the input is legal and is accepted by the parser. It terminates with failure if
an error is detected in the input.

Program:

#include<conio.h>

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

charip_sym[15],stack[15];

intip_ptr=0,st_ptr=0,len,i;

char temp[2],temp2[2];

char act[15];

void check();

void main()

clrscr();

printf("\n\n\t Shift Reduce Parser\n");

printf("\n\t***** ****** ******");

printf("\n Grammar\n\n");

printf("E->E+E\nE->E/E\n");

printf("E->E*E\nE->a/b");

printf("\n Enter the Input Symbol:\t");

gets(ip_sym);

printf("\n\n\t Stack Implementation Table");


printf("\n Stack\t\t Input Symbol\t\t Action");

printf("\n $\t\t %s$\t\t\t --",ip_sym);

strcpy(act,"shift");

temp[0]=ip_sym[ip_ptr];

temp[1]='\0';

strcat(act,temp);

len=strlen(ip_sym);

for(i=0;i<=len-1;i++)

stack[st_ptr]=ip_sym[ip_ptr];

stack[st_ptr+1]='\0';

ip_sym[ip_ptr]=' ';

ip_ptr++;

printf("\n$%s\t\t%s$\t\t\t%s",stack,ip_sym,act);

strcpy(act,"shift");

temp[0]=ip_sym[ip_ptr];

temp[1]='\0';

strcat(act,temp);

check();

st_ptr++;

st_ptr++;

check();

getch();

void check()
{

int flag=0;

temp2[0]=stack[st_ptr];

temp[1]='\0';

if((!strcmpi(temp2,"a"))||(!strcmpi(temp2,"b")))

stack[st_ptr]='E';

if(!strcmpi(temp2,"a"))

printf("\n$%s\t\t%s$\t\t\tE->a",stack,ip_sym);

else

printf("\n$%s\t\t%s$\t\t\tE->a",stack,ip_sym);

flag=1;

if((!strcmpi(temp2,"+"))||(strcmpi(temp2,"*"))||(!strcmpi(temp2,"/")))

flag=1;

if((!strcmpi(stack,"E+E"))||(!strcmpi(stack,"E/E"))||(!strcmpi(stack,"E*E")))

strcpy(stack,"E");

st_ptr=0;

if(!strcmpi(stack,"E+E"))

printf("\n$%s\t\t%s$\t\t\tE->E+E",stack,ip_sym);

else

if(!strcmpi(stack,"E/E"))

printf("\n$%s\t\t\t%s$\t\tE->E/E",stack,ip_sym);
else

printf("\n$%s\t\t%s$\t\t\tE->E*E",stack,ip_sym);

flag=1;

if(!strcmpi(stack,"E")&&ip_ptr==len)

printf("\n$%s\t\t%s$\t\t\tAccept",ip_sym);

getch();

exit(0);

if(flag==0)

printf("\n %s \t\t\t %s \t\t Reject",stack,ip_sym);

return;

Output:

Shift Reduce Parser

***** ****** ******

Grammar

E->E+E

E->E/E
E->E*E

E->a/b

Enter the Input Symbol: a+b

Stack Implementation Table

Stack Input Symbol Action

$ a+b$ --

$a +b$ shifta

$E +b$ E->a

$E+ b$ shift+

$E+b $ shiftb

$E+E $ E->a

$E $ E->E*E

$  ☻=$ Accept

#include<stdio.h>

#define TOGETHER (8)

main(void)

int i = 0;

int entries = 33; /* total number to process */

int repeat; /* number of times for while.. */

int left = 0; /* remainder (process later) */


/* If the number of elements is not be divisible by BLOCKSIZE, */

/* get repeat times required to do most processing in the while loop */

repeat = (entries / TOGETHER); /* number of times to repeat */

left = (entries % TOGETHER); /* calculate remainder */

/* Unroll the loop in 'bunches' of 8 */

while (repeat--)

printf("process(%d)\n", i );

printf("process(%d)\n", i + 1);

printf("process(%d)\n", i + 2);

printf("process(%d)\n", i + 3);

printf("process(%d)\n", i + 4);

printf("process(%d)\n", i + 5);

printf("process(%d)\n", i + 6);

printf("process(%d)\n", i + 7);

/* update the index by amount processed in one go */

i += TOGETHER;

/* Use a switch statement to process remaining by jumping to the case label */

/* at the label that will then drop through to complete the set */

switch (left)
{

case 7 : printf("process(%d)\n", i + 6); /* process and rely on drop through */

case 6 : printf("process(%d)\n", i + 5);

case 5 : printf("process(%d)\n", i + 4);

case 4 : printf("process(%d)\n", i + 3);

case 3 : printf("process(%d)\n", i + 2);

case 2 : printf("process(%d)\n", i + 1); /* two left */

case 1 : printf("process(%d)\n", i); /* just one left to process */

case 0 : ; /* none left */

}return 0;

Output:

process(0)

process(1)

process(2)

process(3)

process(4)

process(5)

process(6)

process(7)

process(8)

process(9)

process(10)

process(11)

process(12)

process(13)
process(14)

process(15)

process(16)

process(17)

process(18)

process(19)

process(20)

process(21)

process(22)

process(23)

process(24)

process(25)

process(26)

process(27)

process(28)

process(29)

process(30)

process(31)

process(32)

Design predictive parser for the given language


#include<stdio.h>

#include<conio.h>
#include<string.h>

void main()

char fin[10][20],st[10][20],ft[20][20],fol[20][20];

int a=0,e,i,t,b,c,n,k,l=0,j,s,m,p;

clrscr();

printf("enter the no. of coordinates\n");

scanf("%d",&n);

printf("enter the productions in a grammar\n");

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

scanf("%s",st[i]);

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

fol[i][0]='\0';

for(s=0;s<n;s++)

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

j=3;

l=0;

a=0;

l1:if(!((st[i][j]>64)&&(st[i][j]<91)))

for(m=0;m<l;m++)

if(ft[i][m]==st[i][j])

goto s1;
}

ft[i][l]=st[i][j];

l=l+1;

s1:j=j+1;

else

if(s>0)

while(st[i][j]!=st[a][0])

a++;

b=0;

while(ft[a][b]!='\0')

for(m=0;m<l;m++)

if(ft[i][m]==ft[a][b])

goto s2;

ft[i][l]=ft[a][b];

l=l+1;

s2:b=b+1;

}
}

while(st[i][j]!='\0')

if(st[i][j]=='|')

j=j+1;

goto l1;

j=j+1;

ft[i][l]='\0';

printf("first pos\n");

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

printf("FIRS[%c]=%s\n",st[i][0],ft[i]);

fol[0][0]='$';

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

k=0;

j=3;

if(i==0)

l=1;

else

l=0;

k1:while((st[i][0]!=st[k][j])&&(k<n))
{

if(st[k][j]=='\0')

k++;

j=2;

j++;

j=j+1;

if(st[i][0]==st[k][j-1])

if((st[k][j]!='|')&&(st[k][j]!='\0'))

a=0;

if(!((st[k][j]>64)&&(st[k][j]<91)))

for(m=0;m<l;m++)

if(fol[i][m]==st[k][j])

goto q3;

fol[i][l]=st[k][j];

l++;

q3:

else
{

while(st[k][j]!=st[a][0])

a++;

p=0;

while(ft[a][p]!='\0')

if(ft[a][p]!='@')

for(m=0;m<l;m++)

if(fol[i][m]==ft[a][p])

goto q2;

fol[i][l]=ft[a][p];

l=l+1;

else

e=1;

q2:p++;

if(e==1)

e=0;

goto a1;
}

else

a1:c=0;

a=0;

while(st[k][0]!=st[a][0])

a++;

while((fol[a][c]!='\0')&&(st[a][0]!=st[i][0]))

for(m=0;m<l;m++)

if(fol[i][m]==fol[a][c])

goto q1;

fol[i][l]=fol[a][c];

l++;

q1:c++;

goto k1;

fol[i][l]='\0';
}

printf("follow pos\n");

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

printf("FOLLOW[%c]=%s\n",st[i][0],fol[i]);

printf("\n");

s=0;

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

j=3;

while(st[i][j]!='\0')

if((st[i][j-1]=='|')||(j==3))

for(p=0;p<=2;p++)

fin[s][p]=st[i][p];

t=j;

for(p=3;((st[i][j]!='|')&&(st[i][j]!='\0'));p++)

fin[s][p]=st[i][j];

j++;

fin[s][p]='\0';

if(st[i][k]=='@')

{
b=0;

a=0;

while(st[a][0]!=st[i][0])

a++;

while(fol[a][b]!='\0')

printf("M[%c,%c]=%s\n",st[i][0],fol[a][b],fin[s]);

b++;

else if(!((st[i][t]>64)&&(st[i][t]<91)))

printf("M[%c,%c]=%s\n",st[i][0],st[i][t],fin[s]);

else

b=0;

a=0;

while(st[a][0]!=st[i][3])

a++;

while(ft[a][b]!='\0')

printf("M[%c,%c]=%s\n",st[i][0],ft[a][b],fin[s]);

b++;
}

s++;

if(st[i][j]=='|')

j++;

getch();

Output:

enter the no. of coordinates

enter the productions in a grammar

S->CC

C->eC|d

firstpos

FIRS[S]=ed

FIRS[C]=ed

followpos

FOLLOW[S]=$

FOLLOW[C]=ed$

M[S,e]=S->CC

M[S,d]=S->CC

M[C,e]=C->eC
M[C,d]=C->d

You might also like