Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
33% found this document useful (3 votes)
6K views

Compiler - Design Lab Manual

The document discusses developing programs to generate intermediate code forms from source code, including programs to generate three address code, quadruple intermediate code, and Polish notation from expressions entered by the user. It includes code snippets for lexical analysis and parsing to extract operands, operators, and generate the intermediate code forms from the parsed input expressions.
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
33% found this document useful (3 votes)
6K views

Compiler - Design Lab Manual

The document discusses developing programs to generate intermediate code forms from source code, including programs to generate three address code, quadruple intermediate code, and Polish notation from expressions entered by the user. It includes code snippets for lexical analysis and parsing to extract operands, operators, and generate the intermediate code forms from the parsed input expressions.
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 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 #define #define #define #define #define #define #define SIZE 128 NONE -1 EOS '\0' NUM 257 KEYWORD 258 ID 259 DONE 260 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 { } } } 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); } tokenval=NONE; return t;

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
/* %{ #includey.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 %% /* Program name: intcode.y */ {return 0;} {return yytext[0];} Program name: intcode.l */

%{ #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 d/ e c* B b+ B a= B

B:= C:= D:= E:=

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 c* d B/ e b+ B a= B

B:= C:= D:= E:=

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(\n1.Insert a node as a head node); printf(\n1.Insert a node as a last node); printf(\n1.Insert a node as at the intermediate position in the list ); printf(\n1.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 *searched *Output:looks for the element in *If found returns pointer to the *Parameter Passing Methods: call *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; }

and the elemnt to be the list previous node otherwise NULL by value

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

and the elemnt to be the list previous node otherwise NULL by value

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(\nThe 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 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 Heap using Dynamic memory

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]* %%

#.* int | float | char | double | while | for | do | if | break | continue | void | switch | switch | case | long | struct | const | typedef | return | else | goto

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

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

\".*\" [0-9]+ \)(\;)? \( = \+| \-

{if(!COMMENT)printf("\n\t% is a STRING",yytext);} {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 if is (argc < is 2 is ) BEGINS a KEYWORD is an INDENTIFIER a RELATIONAL OPERATOR 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 #include y.tab.h %} %% = + - / * for the expression */

{printf(\n {printf(\n {printf(\n {printf(\n {printf(\n

Operator Operator Operator Operator Operator

is is is is is

EQUAL);} PLUS);} MINUS);} DIVISION);} MULTIPLICATION);}

[a-z A-Z]*[0-9]*

{ printf(\n Identifier is %s,yytext); return ID;

\n %%

} return yytext[0]; 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]# [root@localhost]# [root@localhost]# [root@localhost]# lex anb.1 yacc -d anb.y gcc lex.yy.c y.tab.c ./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*/ return yytext[0];

\n| %%

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