You are on page 1of 45

1. Develop a lexical analyzer to recognize a few patterns in PASCAL and C.

(Ex. identifiers, constants, comments, operators etc.)

#include<stdio.h>
#include<conio.h>
#include<ctype.h>
#include<string.h>
#include<stdlib.h>
#define SIZE 128
#define NONE -1
#define EOS ‘\0’
#define NUM 256
#define KEYWORD 257
#define PAREN 258
#define ID 259
#define ASSIGN 260
#define REL_OP 261
#define DONE 262
#define MAX 999
char lexemes[MAX];
char buffer[SIZE];
int lastchar = -1;
int lastentry = 0;
int tokenval=NONE;
int lineno=1;
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)
{
fprint(stderr,”line %d: %s”,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(chars[],int tok)
{
int len;
len=strlen(s);
if(lastentry+1>=MAX)
Error_Message(“Symbol Table is Full”);
if(lastchar+len+1>=MAX)
Error_Message(“Lexemes Array is Full”);
lastentry++;
symtable[lastentry].token=tok;
symtable[lastentry].lexptr=&lexemes[lastcher+1];
lastchar = lastchar + len + 1;
strcpy(smtable[lastentry].lexptr,s);
return lastentry;
}

void Initialize()
{
struct entry *ptr;
for(ptr=keywords;ptr->token;ptr++)
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++;
else if(t == ’(‘ || t == ‘)’)
return PAREN;
else if(t==‘<’ ||t==‘>’ ||t==‘<=’ ||t==‘>=’ ||t == ‘!=’)
return REL_OP;
else if(t == ’=’)
return ASSIGN;
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++;
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 main()
{
int lookahead;
char ans;
clrscr();
printf(“\n]t]t Program for Lexical Analysis \n”);
Initialize();
printf(“\n Enter the expression and put ; at the end”);
printf(“\n Press Ctrl + Z to terminate... \n”);
lookahead=lexer();
while(lookahead!=DONE)
{
if(lookahead==NUM)
printf(“\n Number: %d”,tokenval);
if(lookahead==’+’|| lookahead==’-’|| lookahead==’*’||

lookahead==’/’)
printf(“\n Operator”);
if(lookahead==PAREN)
printf(“\n Parentesis”);
if(lookahead==ID)
printf(“\n Identifier: %s“,
symtable[tokenval].lexptr);
if(lookahead==KEYWORD)
printf(“\n Keyword);
if(lookahead==ASSIGN)
printf(“\n Assignment Operator”);
if(lookahead==REL_OP)
printf(“\n Relataional Operator”);
lookahead=lexer();
}
}

OUTPUT:

Program for Lexical Analysis


Enter the expression and put ; at the end
Press Ctrl + Z to terminate ...
2+3
Number: 2
Operator
Number: 3
if(a<b) a=a+b;

Keyword
Parenthesis
Identifier: a
Relational Operator
Identifier: b
Parenthesis
Identifier: a
Assigment Operator
Identifier: a
Operator
Identifier: b
^Z
2. Develop a recursive decent parser

#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.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 errormsg(char *m)


{
fprintf(stderr,"line %d:%s\n",lineno,m);
exit(1);
}

int lookup(char s[])


{
int k;
for(k=lastentry;k>0;k=k-1)
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)
errormsg("symtable is full");
if(lastentry+len+1>=MAX)
errormsg("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 initialise()
{
struct entry *ptr;
for(ptr=keywords;ptr->token;ptr++)
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)
errormsg("compile error");
}
buffer[i]=EOS;
if(t!=EOF)
ungetc(t,stdin);
val=lookup(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
errormsg("syntax error");
}

void display(int t,int tval)


{
if(t=='+'||t=='-'||t=='*'||t=='/')
printf("\n arithmetic 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:
errormsg("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);
F();
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;
clrscr();
printf("\n \t \t Program for recursive decent parsing");
initialise();
printf("enter the expression & place;at the end \n Press CTRL
+ Z to terminate");
parser();
return 0;
}

OUTPUT:
Program for recursive decent parsing

Enter the expression & place ; at the end


Press CTRL + Z to terminate
2+3*4;

number 2
number 3
number 4
arithmetic operator *
arithmetic operator +

2+3*4+5;
number 2
number 3
number 4
arithmetic operator *
arithmetic operator +
number 5
arithmetic operator +

a-b;
identifier a
identifier b
arithmetic operator –

+1
Line7: syntaxerror
3. Write a program for generating for various intermediate code forms:
● Three address code
● Quadruple

/* Program name: intcode.l


*/
%{
#include”y.tab.h”
extern char yyval;
%}

NUMBER [0-9]+
LETTER [a-zA-Z]+
%%
{NUMBER} {yylval.sym=(char)yytext[0];return NUMBER;}
{LETTER} {yylval.sym=(char)yytext[0];return LETTER;}

\n {return 0;}
{return yytext[0];}
%%

/* Program name: intcode.y


*/

%{
#include<stdio.h>
#include<string.h>
int nIndex=0;
struct InterCode
{
char operand1;
char operand2;
char opera;
};
%}

%union
{
char sym;
}

%token <sym> LETTER NUMBER


%type <sym> expr
%left ‘-’ ‘+’
%right ‘*’ ’/’
%%
statement: LETTER ‘=’ expr ‘;’
{AddToTable((char)$1.(char)$3,’=’);}
| expr ‘;’ ;

expr :expr ‘+’ expr {$$ = AddToTable((char)$1.(char)$3,’+’);}


|expr ‘-’ expr {$$ = AddToTable((char)$1.(char)$3,’-’);}
|expr ‘*’ expr {$$ = AddToTable((char)$1.(char)$3,’*’);}
|expr ‘/’ expr {$$ = AddToTable((char)$1.(char)$3,’/’);}
|’(‘expr’)’ {$$=(char)$2;)
| NUMBER {$$=(char)$1;}
| LETTER {$$=(char)$1;}
;
%%
yyerror(char *s)
{
printf(“%s”,s);
exit(0);
}
struct InterCode Code[20];

char AddToTable(char operand1,char operand2,char opera)


{
char temp = ’A’;
Code[nIndex].operand1=operand1;
Code[nIndex].operand2=operand2;
Code[nIndex].opera=opera;
nIndex++;
temp++;
return temp;
}

ThreeAddressCode()
{
int nCnt=0;
char temp =’A’;
printf(“\n\n\t THREE ADDRESS CODE\n\n”);
temp++;
while(nCnt<nIndex)
{
printf(“%c : =\t”,temp);
if(isAlpha(Code[nCnt]].operand1))
printf(“%c\t”,Code[nCnt].operand1);
else
printf(“%c\t”,temp);
printf(“%c\t”,Code[nCnt].opera);

if(isAlpha(Code[nCnt]].operand2))
printf(“%c\t”,Code[nCnt].operand2);
else
printf(“%c\t”,temp);
printf(“\n”);
nCnt++;
temp++;
}
}

void Quadruples()
{
int nCnt=0;
char temp =’A’;
temp++;
printf(“\n\n\t QUADRUPLES\n”);
printf(“\n ID OPERATOR OPERAND1 OPERAND2 RESULT\n”);

while(nCnt<nIndex)
{
printf(“\n(%d)\t%c\t”,nCnt,Code[nCnt].opera);
if(isAlpha(Code[nCnt]].operand1))
printf(“%c\t”,Code[nCnt].operand1);
else
printf(“%c\t”,temp);

if(isAlpha(Code[nCnt]].operand2))
printf(“%c\t”,Code[nCnt].operand2);
else
printf(“%c\t”,temp);
printf(“%c\t”,temp);
nCnt++;
temp++;
}
}

main()
{
printf(“\nEnter The Expression”);
yyparse();
ThreeAddressCode();
Quadruples();
}

yywrap()
{
return 1;
}
Output:
[root@localhost]# lex intcode.l
[root@localhost]# yacc -d intcode.y
[root@localhost]# ./a.out

Enter The Expression: a=b+c*d/e;

THREE ADDRESS CODE


B:= d/ e
C:= c* B
D:= b+ B
E:= a= B

QUADRUPLES
ID OPERATOR OPERAND1 OPERAND2 RESULT
(0) / d e B
(1) * c B C
(2) + b B D
(3) = a B E

[root@localhost]# ./a.out

Enter The Expression: a=(b)+(c*d)/e

THREE ADDRESS CODE


B:= c* d
C:= B/ e
D:= b+ B
E:= a= B

QUADRUPLES
ID OPERATOR OPERAND1 OPERAND2 RESULT
(0) * c d B
(1) / B e C
(2) + b B D
(3) = a B E
4. Write a program to generate the intermediate code in the form of Polish
Notation

#include<stdio.h>
#include<conio.h>
#include<string.h>
#incldue<stdlib.h>

struct stack
{char s[30];
int top;
}st;

void main()
{
char input[30];
void input_to_code(char infix[30]);
clrscr();
printf("\n Enter an input in the form of expression ");
scanf("%s",input);
input_to_code(input);
getch();
}

void input_to_code(char input[30])


{
st.top=-1;
st.s[st.top]='$';
char polish[30];
int i,j;
char ch;
int instack(char ch);
int incoming(char ch);
void push(char item);
char pop();
j=0;
strrev(input);
for(i=0;input[i]!='\0';i++)
{
ch =input[i];
while(instack(st.s[st.top])>incoming(sh))
{
polish[j]=pop();
j++;
}
if(instack(st.s[st.top])!=incoming(ch))
push(ch);
else
pop();
}
while((ch=pop()!='$')
{
polish[j]=ch;
j++;
}
polish[j]='\0;;
strrev(polish);
printf("\n The Polish Notation is %s",polish);
}

int instack(char ch)


{
int priority;
switch(ch)
{
case ')':priority=0;
break;
case '+':
case '-':priority=1;
break;
case '*';
case '/':priority=3;
break
case '^':priority=6;
break;
case '$':priority=-1;
break;
default:priority=8;//when it is operand
break;
}
return priority;
}

int incoming(char ch)


{
int priority;
switch(ch)
{
case '+':
case '-':priority=2;
break;
case '*';
case '/':priority=4;
break
case '^':priority=5;
break;
case '(':priority=0;
break;
case ')':priority=9;
break;
default:priority=7;//when it is operand
}
return priority;
}
void push(char item)
{
st.top++;
st.s[st.top]=item;
}

char pop()
{
char e;
e=st.s[st.top];
st.top--;
return e;
}

Output:
Enter an input in the form of expression (a+b)*(c-d)

The polish notation is *+ab-cd


5. Write a program to Simulate Heap storage allocation strategy

/************************************************************
Program to perform various operations such as creation,
insertion, deletion, display of heap
*************************************************************/
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#define TRUE 1
#include FALSE 0

typedef struct Heap


{
int data;
struct Heap *next;
}node;

node *create();

void main()
{
/*local declarations*/
int choice,val;
char ans;
node *head;
void display(node *);
node *search(node *,int);
node *insert(node *);
void dele(node **);
head=NULL;
do
{
clrscr();
printf(“\n Program to perform various operations on heap
using dynamic memory management”);
printf (“\n1.Create”):
printf (“\n2.Display”):
printf (“\n3.Insert an element in a list”);
printf (“\n4.Delete an element from list”);
printf (“\n5.Quit”);
printf (“\n Enter Your Choice(1-5)”);
scanf(“%d,&choice”);
switch(choice)
{
case 1:head=create();
break;
case 2:display(head);
break;
case 3:head=insert(head);
break;
case 4:dele(&head);
break;
case 5:exit(0);
default:clrscr();
printf(“Invalid Choice,Try again”);
getch();
}
}while(choice!=5);
}

/*The create function creates a list of allocated node


*Input:None
*Output:Retyurns a pointer to head of list
*Parameter Passing Methopd:Node
**/

node *create()
{
node *temp,*new,* head;
int val,flag;
char ans=’y’;
node *get_node();
temp=NULL;
flag=TRUE;
/*flag to indicate whether a new node is created for the first time
or not*/
do
{
printf(“\n Enter the Element”);
scanf(“%d”,&val);
/*allocate new node*/
new =get_node();

if(new==NULL)
printf(“\n Memory is not allocated”);
new-> data=val;
if (flag==TRUE)/* Executed only for the first time*/
{
head=new;
temp=head; /*head is the first node in the heap*/
flag=FALSE;
}
else
{
/*temp keeps track of the most recently created node*/

temp->next=new;
temp=new;
}
printf(\nDo you want to enter more elements?(y/n)”);
ans=getch();
}while(ans= = ‘y’);

printf(“\nThe list is created”);


getch();
clrscr();
return head;
}
node *get_node()
{
node *temp;
temp=(node*)malloc(sizeof(node));
//using the mem. Allocation function
temp->next=NULL;
return temp;
}

/*
*The display function
*Input:Address of the first node of the list
*Output:Displays the list of allocated nodes
*Parameter Passing Method : call by value
*Called by main
**/

void display(node*head)
{
node *temp;
temp=head;
if(temp= =NULL)
{
printf(“\n The list is empty\n”);
getch();
clrscr();
return;
}
while(temp!= NULL)
{
printf(“%d->”,temp-> data);
temp=temp->next;
}
print(“NULL”);
getch();
clrscr();
}

/*
*The search function
*Input: Address of the starting node and the element which is
*to be searched
*Output:Searches for the element in list
*If found returns pointer to that node Otherwise NULL
*Parameter passing Method:call by value
*Called by:main
*Calls:None
**/

node *search(node *head,int key)


{
node*temp;
int found;
temp=head;
if (temp= =Null)
{
printf(“The linked list is empty\n”);
getch();
clrscr();
return NULL;
}

found=FALSE;
While(temp!= NULL && found= =FALSE)
{
if(temp->data != key)
temp = temp->next;
else
found = True;
}

if(found == TRUE)
{
printf(“\n The Elements is present in the list”\n);
getch();
return temp;
}
else
printf(“\n The Element is not present in the list\n”);
getch();
return NULL;
}

/*
*The insert function
*Input: Address of starting node of the list
*Output:inserts element into the list
*Parameter Passing Methods: call by value
*Called by : main
*Calls : search()
**/

node *insert(node *head)


{
int choice;
node *insert_head(node*);
void insert_after(node*);
void insert_last(node*);
printf(“\n”1.Insert a node as a head node”);
printf(“\n”1.Insert a node as a last node”);
printf(“\n”1.Insert a node as at the intermediate position in
the list ”);
printf(“\n”1.Enter your choice for insertion of node ”);
scanf(“%d”,&choice);
switch(choice)
{
case 1:head = insert_head(head);
break;
case2:insert_last(head);
break;
case2:insert_after (head);
break;
}
return head;
}

/*Insertion of node at first position*/

node *insert_head(node*head)
{
node *New,*temp;
New = get_node();
printf (“\n Enter the element which you want to insert ”);
scanf(“%d”,&New->data);
if(head == NULL)
head = New;
else
{
temp=head;
New->next = temp;
head= New;
}
return head;
}

/*Insertion of node at last position*/

void insert_last(node *head)


{
node *New,*temp;
New = get_node();
printf (“\n Enter the element which you want to insert ”);
scanf(“%d”,&New->data);
if(head == NULL)
{
head = New;
}
else
{
temp=head;
while(temp->next!=NULL)
temp=temp->next;
temp->next=New;
New->next=NULL;
}
}

/*Insertion of node at intermediate position*/

void insert_after(node *head)


{
int key;
node *New,*temp;
New = get_node();
printf(“Enter the element after which you want to insert ”);
scanf(“%d”,&key);
temp=head;
do
{
if(temp->data==key)
{
printf (“Enter element which you want to insert ”);
scanf(“%d”,&New->data);
New->next=temp->next;
temp->next=New;
return;
}
else
temp=temp->next;
}while(temp!=NULL);
}

/*
*The get prev function
*Input: Address of starting node and the elemnt to be
*searched
*Output:looks for the element in the list
*If found returns pointer to the previous node otherwise NULL
*Parameter Passing Methods: call by value
*Called by : dele()
*Calls : none
**/

node *get_prev(node *head,int val)


{
node*temp.*prev;
int flag;
temp = head;
if(temp == NULL)
return NULL;
flag = FALSE;
prev = NULL;
while(temp!=NULL && !flag)
{
if(temp->data!=val)
{
prev = temp;
temp = temp->next;
}
else
flag = TRUE;
}

if(flag) /*if Flag is true*/


return prev;
else
return NULL;
}
/*
*The get prev function
*Input: Address of starting node and the elemnt to be
*searched
*Output:looks for the element in the list
*If found returns pointer to the previous node otherwise NULL
*Parameter Passing Methods: call by value
*Called by : dele()
*Calls : none
**/

void dele(node **head)


{
int key;
node *New,*temp;
temp=*head;
if (temp== NULL)
{
printf (“\n The list is empty\n ”);
getch();
clrscr();
return;
}

clrscr();
printf("\nENTER the Element you want to delete:");
scanf("%d".&key);
temp= search(*head,key);
if(temp !=NULL)
{
prev = get_prev(*head,key);
if(prev != NULL)
{
prev ->next = temp-> next;
free(temp);
}
else
{
*head = temp->next;
free(temp); // using the mem. Dellocation function
}
printf(“\n”The Element is deleted\n”);
getch();
clrscr();
}
}
Output:
Program to perform various operations on heap using Dynamic memory
management.

1. Create
2. Display
3. Insert an element in a list
4. Delete an element from list
5. Quit
Enter your choice(1-5) 1

Enter the element: 10

Do you want to enter more elements? (y/n) y

Enter the element:20

Do you want to enter more elements?(y/n)y

Enter the element:30

Do you want to enter more elements?(y/n)n

The List is created

Program to perform various operations on Heap using Dynamic memory


management.

1. Create
2. Display
3. Insert an element in a list
4. Delete an element from list
5. Quit
Enter your choice(1-5) 4

Enter the element you want to delete: 20

The element is present in the list

The element is deleted

Program to perform various operations on Heap using Dynamic memory


management.

1. Create
2. Display
3. Insert an element in a list
4. Delete an element from list
5. Quit
Enter your choice(1-5) 2
10-> 30-> NULL
6. Generate Lexical analyzer using LEX.
%{
/*******************************************************************
Program to obtain tokens from a c program using LEX
<lexp.l>
*******************************************************************/
int COMMENT = 0;
int cnt = 0;

%}

identifier[a-zA-Z][a-zA-Z0-9]*
%%

#.* {printf("\n%is a PREPROCESSOR DIRECTIVE", yytext);}

int |
float |
char |
double |
while |
for |
do |
if |
break |
continue |
void |
switch |
switch |
case |
long |
struct |
const |
typedef |
return |
else |
goto {printf("\n\t%s is a KEYWORD",yytext);}

"*/" {COMMENT = 1;}

"*/" {COMMENT = 0;}


cnt++;
}
{identifier}\(if(COMMENT){printf("\n\nFUNCTIONAL\n\t%s",yytext);}
\{ {if(!COMMENT) printf("\n BLOCK BEGINS");}

\} {if(!COMMENT)printf("\nBLOCK ENDS");}
{identifier}(\[0-9]*\])? {if(!COMMENT)printf("\n\t%s is an
IDENTIFIER",yytext);}

\".*\" {if(!COMMENT)printf("\n\t% is a STRING",yytext);}

[0-9]+ {if(!COMMENT)printf("\n\t%is a NUMBER",yytext);}

\)(\;)? {if(!COMMENT)printf("\n\t");ECHO;print("\n";)}

\( ECHO;
= {if(!COMMENT)printf("\n\t%s is an ASSIGNMENT OPERATOR",yytext)}

\+|
\- {if(!COMMENT)printf("\n\t%s is an OPERATOR",yytext);}

\<=|
\>=|
\<|
==|
\> {if(!COMMENT)printf(\n\t%s is a RELATIONAL OPERATOR",yytext);}

|\n

%%
int main(int argc.char**argv)
{
if(argc>1)
{
FILE *file';
file fopen(argv[1]."r");
if(file)
{
printf(“\n Could not open %s”,argv[1];
exit(0);
}
yyin = file;
}
yylex();
printf(“ \n Total number of comments are %d”,cnt);
return 0;
}

int yywrap()
{
return 1;
}
Input File:

#include<stdio.h>
#include<stdlib.h>

double area_of_circle(double r);

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


{
if(argc < 2)
{
printf(“ Usage: %s radius \n”,argv[0]);
exit(1);
}
else
{
/* This is a double line comment */
double radius = atof(argv[1]);
double area = area_of_circle(radius);
printf(“ Area of circle with radius %f = %f \n”,radius,area);
}
return 0;
}
Output:

[root@localhost]# lex lexp.l


[root@localhost]# gcc lex.yy.c
[root@localhost]# ./a.out area.c

#include<stdio.h>
#include<stdlib.h>
double is a KEYWORD
area is an INDENTIFIER
of is an INDENTIFIER
circle is an INDENTIFIER
(double is a KEYWORD
r is an INDENTIFIER
);

int is a KEYWORD
main is an INDENTIFIER
(int is a KEYWORD
argc is an INDENTIFIER
char is a KEYWORD
argv[] is an INDENTIFIER
)

BLOCK BEGINS
if is a KEYWORD
(argc is an INDENTIFIER
< is a RELATIONAL OPERATOR
2 is a NUMBER
)

BLOCK BEGINS
printf is an INDENTIFIER
(“ Usage: %s radius \n”,is a STRING
argv[0] is an INDENTIFIER
);

exit is an INDENTIFIER
(1 is a NUMBER
);

BLOCK ENDS
else is a KEYWORD

BLOCK BEGINS
double is a KEYWORD
radius is an INDENTIFIER
= is an ASSIGNMENT OPERATOR
atof is an INDENTIFIER
(argv[1]is an INDENTIFIER
);

double is a KEYWORD
area is an INDENTIFIER
= is an ASSIGNMENT OPERATOR
area is an INDENTIFIER
of is an INDENTIFIER
circle is an INDENTIFIER
(radius is an INDENTIFIER
);

printf is an INDENTIFIER
(“Area of circle with radius %f = %f \n”, is a STRING
radius is an INDENTIFIER
area is an INDENTIFIER
);

BLOCK ENDS
return is a KEYWORD
0 is a NUMBER

BLOCK ENDS
Total number of comments are 3{root@localhost]#
7. 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<stdio.h>
/* 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 <stdio.h>
/* This YACC program is for recognising the Expression*/
%}
%token ID INT FLOAT DOUBLE
%%
D;T L
;
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]#
c) Program to recognise the gramar(anb where n>=10)

Program name: anb.l

%{
/*Lex Program for anb(n>=10)*/
%}
%%
a {return A;}
b {return B;}
. {return yytext[10];}
\n return('\n');
%%
int yywrap()
{
return 1;
}

Program name:anb.y

%{
/*YACC program for recognising anb(n>=10)*/
%}
%token A B
%%
stmt:A A A A A A A A A A anb'\n'{printf("\n Valid string");
return 0;
}
;
anb:A anb
|A B
;
%%
main()
{
printf("\nEnter some valid string\n");
yyparse();
}

int yyerror(char*s)
{
printf("\nInvalid string\n");
}

Output:
[root@localhost]# lex anb.1
[root@localhost]# yacc -d anb.y
[root@localhost]# gcc lex.yy.c y.tab.c
[root@localhost]# ./a.out
Enter some valid string
aaaaaaaaab

Invalid string
[root@localhost]# ./a.out

Enter some valid string


aaaaaaaaaaab

Valid string [root@localhost]#

d) Implementation of Calculator using LEX and YACC

Program name:calci.l

%{
#include "y.tab.h" /*defines the tokens*/
#include ,math.h.
%}
%%
/*To recognise a valid number*/
([0-9] + |([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?) {yylval.dval =
atof(yytext);
return NUMBER;}
/*For log no | Log no (log base 10)*/
log | LOG {return LOG;}

/*For ln no (Natural Log)*/


ln {return nLOG;}

/*For sin angle*/


sin | SIN {return SINE;}

/*For cos angle*/


cos | COS {return COS;}

/*For tan angle*/


tan | TAN {return TAN;}
/*For memory*/
mem {return MEM;}

[\t] ; /*Ignore white spaces*/

/*End of input*/
\$ {return 0;}

/*Catch the remaining and return a single character token to


the parser*/
\n| return yytext[0];
%%
Program Name : calci.y
%{
double memvar;
%}

/*To define possible symbol types*/


%token <dval> NUMBER
%token <dval> MEM
%token LOG SINE nLOG COS TAN

/*Defining the precedences and associativity*/


%left ‘-’ ‘+’ /*Lowest precedence*/
%left ‘*’ ‘/’
%right ‘^’
%left LOG SINE nLOG COS TAN /*Highest precence*/

/*No associativity*/
%nonassoc UMINUS /*Unary Minus*/

/*Sets the type for non-terminal*/


%type <dual> expression
%%
/*Start state*/
start: statement ‘\n’
| start statement ‘\n’
;

/*For storing the answer(memory)*/


statement: MEM’=’ expression {memvar=$3;}
| expression {printf(“Answer = %g\n”,$1);}
; /*For printing the Answer*/

/*For binary arithmetic operations*/


expression: expression ‘+’ expression {$$ = $1 + $3;}
| expression ‘-’ expression {$$ = $1 - $3;}
| expression ‘*’ expression {$$ = $1 * $3;}
| expression ‘/’ expression
{ /*Tohandle divide by zero case*/
If($3 == 0)
yyerror(“divide by zero”);
else
$$ = $1 / $3;
}
| expression ‘^’ expression {$$ = pow($1,$3);}
;

/*For unary operators*/


expression: ‘-’expression %prec UMINUS {$$ = -$2;}
/*%prec UMINUS signifies that unary minus should have the
highest precedence*/
| ‘(’ expression ‘)’ {$$ = $2}
| LOG expression {$$ = log($2)/log(10);}
| nLOG expression {$$ = log($2);}
*/Trigonometric functions*/
| SINE expression {$$ = sin($2 * 3.141592654 / 180);}
| COS expression {$$ = cos($2 * 3.141592654 / 180);}
| TAN expression {$$ = tan($2 * 3.141592654 / 180);}
| NUMBER {$$ = $1;}
| MEM {$$ = $1;}
; /*Retrieving the memory contents*/
%%
main()
{
printf(“Enter the expression:”);
yyparse();
}
int yyerror(char *error)
{
fprintf(stderr,”%s\n”,error);
}

Output:

The output of the program can be obtained by following commands


[root@localhost]]# lex calci.l
[root@localhost]]# yacc –d calci.y
[root@localhost]]# cc y.tab.c lexyy.c –ll –ly –lm
[root@localhost]]# ./a.out

Enter the expression: 2+@


Answer = 4

2 * 2 + 5 / 4
Answer = 5.25

mem = cos 45
sin 45/mem
Answer = 1

ln 10
Answer = 2.30259
8. Given any intermediate code form implement code optimization
techniques.

/*******************************************************************
Program for Code Optimization Technique of Constant Folding
*******************************************************************/
#include<stdio.h>
#include<string.h>
#include<conio.h>
#include<stdlib.h>
#include<ctype.h>

struct ConstFold
(

char new_Str[10];
char str[10];
}Opt_Data[20];

void ReadInput(char Buffer[],FILE *Out_file);


int Gen_token(char str[],char Tokens[][10]);

int New_Index=0;

int main()
{
file *In_file,*Out_file;
char Buffer[100],ch;
int i=0;
In_file = fopen(“d:\\code.txt”,”r”);
Out_file = fopen(“d:\\output.txt”,”w”);
clrscr();
while(1)
{

Ch = fgetc(In_file);
i=0;
while(1)
{
If(ch == ‘\n’)
break;
Buffer[i++]=ch;
ch = fgetc(_file);
if(ch == EOF)
break;
}//End while
if(ch ==EOF)
break;
Buffer[i]=’\0’;
ReadInput(Bufer, Out_file);//writing to the output file
}//End while
return 0;
}//End main
void ReadInput(char Buffer[],FILE *Out_file)
{
char temp[100],Token[10][10];
int n,I,j,flag=0;
strcpy(temp,Buffer);
n= Gen_token(temp,Token);
for(i=0;i<n;i++)
{
if(!strcmp(Token[i],”=”))
{
if(isdigit(Token[i+1][0])||Token[i+1][0] == ’.’)
{
/*If yes then saving that number and its variable
In the Opt_Data array*/
flag=1;
strcpy(Opt_Data[New_Index].New_Str,Token[i-1]);
strcpy(Opt_Data[New_Index++].str,Token[i+1]);
}//End if
}//End if
}//End for
if(!flag)
{
for(i=0;i<New_index;i++)
{
for(j=0;j<n;j++)
{
if(!strcmp(Opt_Data[i].new_Str,Token[j]))
strcpy(Token[j],Opt_Data[i].str);
}//End for
}//End for
}//End if
fflush(Out_file);
strcpy(temp,””);
for(i=0;i<n;i++) /*Loop to obtain complete tokens*/
{
strcat(tem,Token[i]);
if(Token[i+1][0]!=’,’||Token[i+1][0] != ‘,’)
strcat(temp,” “);
}//End for
strcat(temp,”\n\0”);
fwrite(&temp,strlen(temp),1,Out_file);
}

/*The Gen_Token function breaks the input line into tokens*/

int Gen_Token(char str[], char Token[][10])


{
int i=0;j=0,k=0;
while(str[k]!=’\0’)
{
j=0;
while(str[k] ==’ ‘|| str[k] ==’\t’)
k++;
while(str[k])!=’ ’&& str[k]!=’\0’
&& str[k]!= ‘=’ && str[k] != ‘/’
&& str[k]!= ‘+’ && str[k] != ‘-’
&& str[k]!= ‘*’ && str[k] != ‘,’ && str[k]!= ‘;’)
Token[i][j++] = str[k++];
Token[i++][j] = ‘\0’;
if(str[k] == ‘=’|| str[k] == ‘/’|| str[k] == ‘+’|| str[k]
== ‘-’|| str[k] == ‘*’|| str[k] == ‘*’|| str[k] == ‘,’||
str[k] == ‘;’)
{
Token[i][0] = str[k++];
Token[i++][1] = ‘\0’;
}//End if
if (str[k] == ‘\0’)
break;
}//End while
return i;
}

Input File: code.txt


#include<stdio.h>

main()
{
float pi=3.14,r,a;
a = pi*r*r;
printf(“a = %f”,a);
return 0;
}

Output File: output.txt


#include<stdio.h>
main()
{
float pi = 3.14, r, a;
a = 3.14 * r * r;
printf(“a = %f”,a);
return 0;
}
9. Write a program to find FIRST of NON TERMINALS of the given
grammar.

#include"stdio.h"
#include<conio.h>
char array[10][20],temp[10];
int c,n;void fun(int,int[]);
int fun2(int i,int j,int 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[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]!='\0';j++)
{
if(array[i][j-1]=='/')
{
if(array[i][j]>='A'&&array[i][j]<='Z')
{
key=0;
fun2(i,j,p,key);
}
else
{
key=1;
if(fun2(i,j,p,key))
temp[++c]=array[i][j];
if(array[i][j]=='@'&&p[0]!=-1)
{ //taking ,@, as null symbol.
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]]!='\0')
{
if(fun2(p[0],p[1],p,key))
temp[++c]=array[p[0]][p[1]];
}
}
}
}
}
}

void main()
{
int p[2],i,j;
clrscr();
printf("Enter the no. of productions :");
scanf("%d",&n);
printf("Enter the productions :\n");
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();
}
}

Output:

Enter the no. of productions :6


Enter the productions :
S/aBDh
B/cC
C/bC/@
D/E/F
E/g/@
F/f/@
First(S) : [ a ].
First(B) : [ c ].
First(C) : [ b,@ ].
First(D) : [ g,@,f ].
First(E) : [ g,@ ].
First(F) : [ f,@ ].
10. Write a program to find out FOLLOW of NONTERMINALS of given
productions.

#include"stdio.h"
#include<conio.h>
#define max 10
#define MAX 15
char array[max][MAX],temp[max][MAX];
int c,n,t;void fun(int,int[]);

int fun2(int i,int j,int 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]!='\0';j++)
{
if(array[i][j-1]=='/')
{
if(array[i][j]>='A'&&array[i][j]<='Z')
{
key=0;
fun2(i,j,p,key);
}
else
{
key=1;
if(fun2(i,j,p,key))
temp[t][++c]=array[i][j];
if(array[i][j]=='@'&&p[0]!=-1)
{ //taking ,@, as null symbol.
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]]!='\0')
{
if(fun2(p[0],p[1],p,key))
temp[t][++c]=array[p[0]][p[1]];
}
}
}
}
}
}

char fol[max][MAX],ff[max];int f,l,ff0;


void ffun(int,int);

void follow(int i)
{
int j,k;
for(j=0;j<=ff0;j++)
if(array[i][0]==ff[j])
return 0;
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]!='\0';k++)
if(array[j][k]==array[i][0])
ffun(j,k);
}

void ffun(int j,int k)


{
int ii,null=0,tt,cc;
if(array[j][k+1]=='/'||array[j][k+1]=='\0')
null=1;
for(ii=k+1;array[j][ii]!='/'&&array[j][ii]!='\0';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]!='\0';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);
}
void main()
{
int p[2],i,j;
clrscr();
printf("Enter the no. of productions :");
scanf("%d",&n);
printf("Enter the productions :\n");
for(i=0;i<n;i++)
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]='\0';
printf("First(%c) : [ ",temp[t][0]);
for(j=1;j<c;j++)
printf("%c,",temp[t][j]);
printf("\b ].\n");
getch();
}

/* 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]='\0';
}
for(i=0;i<n;i++)
{
printf("\nFollow[%c] : [ ",fol[i][0]);
for(j=1;fol[i][j]!='\0';j++)
printf("%c,",fol[i][j]);
printf("\b ]");
getch();
}
}

Output:
Enter the no. of productions :6
Enter the productions :
S/aBDh
B/cC
C/bC/@
D/E/F
E/g/@
F/f/@
First(S) : [ a ].
First(B) : [ c ].
First(C) : [ b,@ ].
First(D) : [ g,@,f ].
First(E) : [ g,@ ].
First(F) : [ f,@ ].
Follow[S] : [ $ ]
Follow[B] : [ g,f,h,$ ]
Follow[C] : [ g,f,h,$ ]
Follow[D] : [ h ]
Follow[E] : [ h ]
Follow[F] : [ h ]

You might also like