1. Develop a lexical analyzer to recognize a few patterns in PASCAL and C. (Ex. identifiers, constants, comments, operators etc.) #include #include #include #include #include #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
2. Develop a recursive decent parser
#include #include #include #include #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 {
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 #include int nIndex=0; struct InterCode { char operand1; char operand2; char opera; }; %} %union { char sym; } %token LETTER NUMBER %type 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
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
Output: [root@localhost]# lex intcode.l [root@localhost]# yacc -d intcode.y [root@localhost]# ./a.out Enter The Expression: a=b+c*d/e;
B:= C:= D:= E:=
THREE ADDRESS CODE d/ e c* B b+ B 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
B:= C:= D:= E:=
THREE ADDRESS CODE c* d B/ e b+ B 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 #include #include #incldue 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 #include #include #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 *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(“\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 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 *******************************************************************/ 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 #include 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 #include 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” %} %% “=” “+” “-“ “/” “*”
{printf(“\n {printf(“\n {printf(“\n {printf(“\n {printf(“\n
[a-z A-Z]*[0-9]*
\n %%
Operator Operator Operator Operator Operator
is is is is is
for the expression */
EQUAL”);} PLUS”);} MINUS”);} DIVISION”);} MULTIPLICATION”);}
{ printf(“\n Identifier is %s”,yytext); return ID;
} return yytext[0]; return 0;
int yywrap() { return 1; }
Program Name : arith_id.y %{ #include /* This YYAC program is for recognizing the Expression */ %} %% statement: A’=’E | E { printf(“\n Valid arithmetic expression”); $$ = $1; }; E: E’+’ID | E’-’ID | E’*’ID | E’/’ID | ID ;
%% extern FILE *yyin;
main() { do { yyparse(); }while(!feof(yyin)); } yyerror(char*s) { }
Output: [root@localhost]# lex arith_id.1 [root@localhost]# yacc –d arith_id.y [root@localhost]# gcc lex.yy.c y.tab.c [root@localhost]# ./a.out x=a+b; Identifier is x Operator is EQUAL Identifier is a Operator is PLUS Identifier is b
b) Program to recognise a valid variable which starts with a letter followed by any number of letters or digits. Program name: variable_test.l %{ /* This LEX program returns the tokens for the Expression */ #include "y.tab.h" %} %% "int " {return INT;} "float" {return FLOAT;} "double" {return DOUBLE;} [a-zA-Z]*[0-9]*{ printf("\nIdentifier is %s",yytext); return ID; } return yytext[0]; \n return 0; int yywrap() { return 1; }
Program name: variable_test.y %{ #include /* This YACC program is for recognising the Expression*/ %} %token ID INT FLOAT DOUBLE %% D;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]
\$
\n| %%
;
/*Ignore white spaces*/
/*End of input*/ {return 0;} /*Catch the remaining and return a single character token to the parser*/ return yytext[0];
Program Name : calci.y %{ double memvar; %} /*To define possible symbol types*/ %token NUMBER %token 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 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 #include #include #include #include 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
/*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 main() { float pi=3.14,r,a; a = pi*r*r; printf(“a = %f”,a); return 0; }
Output File: output.txt #include 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 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;kc)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
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 #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;kc)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='A') { for(tt=0;tt
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
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 ]