Exercise No: IT18611 – AUTOMATA AND COMPILER DESIGN LABORATORY Date: Register No: 180801097 Page No: DESIGN LEXICAL ANALYZER IN C AIM: To design a Lexical Analyzer in C. ALGORITHM: 1. Declare the header files 2. Declare an array of strings containing all the reserve keywords in C. 3. Declare an array of characters containing all the operators in C. 4. Declare a function check_keyword() which returns 1 if the argument is a keyword, else returns 0. 5. Declare a function check_operator() which returns 1 if the argument is an operator, else returns 0. 6. Declare a function check_preprocessor() which uses a regular expression to check if the argument is a preprocessor and returns 1 if the argument is a preprocessor, else returns 0. 7. Declare a function check_identifier() which uses a regular expression to check and print the argument name as a valid/invalid identifier. 8. Declare variables and file pointers to read the contents of the sample file. 9. Open the file in ‘r’ mode. 10. Read the contents of the file and tokenise using strtok(). 11. Check if the content is header or identifier or operator or symbol or keyword by calling the corresponding function. 12. Loop till the end of file is reached. Exercise No: IT18611 – AUTOMATA AND COMPILER DESIGN LABORATORY Date: Register No: 180801097 Page No: SOURCE CODE: #include <stdio.h> #include <string.h> #include <regex.h> regex_t regex; int reti; char keywords[33][12] = {"return", "continue", "extern", "static", "long", "signed", "switch", "char", "else", "unsigned", "if", "struct", "union", "goto", "while", "float", "enum", "sizeof", "double", "volatile", "const", "case", "for", "break", "void", "register", "int", "do", "default", "short", "typedef", "auto", "main"}; char operators[6][2] = {"+", "-", "*", "/", "%", "="}; int check_keyword(char *p) { for (int i = 0; i< 33; ++i) { if (strstr(p, keywords[i])) return 1; } return 0; } int check_operator(char *p) { for (int i = 0; i< 6; ++i) { if (strstr(p, operators[i])) return 1; } return 0; } int check_preprocessor(char *p) { reti = regcomp(®ex, "[#.*]", REG_EXTENDED); reti = regexec(®ex, p, 0, NULL, 0); if (!reti) return 1; else if (reti == REG_NOMATCH) Exercise No: IT18611 – AUTOMATA AND COMPILER DESIGN LABORATORY Date: Register No: 180801097 Page No: return 0; } int check_identifier(char *p) { reti = regcomp(®ex, "^[a-zA-Z_]+[a-zA-Z0-9_]*", REG_EXTENDED); reti = regexec(®ex, p, 0, NULL, 0); if (!reti) printf("%s \t\t\t Valid identifier\n", p); else if (reti == REG_NOMATCH) printf("%s \t\t\t Invalid identifier\n", p); } int main() { FILE *fp = fopen("sample.c", "r"); char str[100]; while (!feof(fp)) { fgets(str, sizeof(str), fp); char *p = strtok(str, " }{\n"); while (p != NULL) { int j = 0, f = 0; if (check_keyword(p)) printf("%s \t\t\t Keyword\n", p); else if (check_operator(p)) printf("%s \t\t\t Operator\n", p); else if (check_preprocessor(p)) printf("%s \t Preprocessor\n", p); else check_identifier(p); p = strtok(NULL, ",;()\n "); } } } Exercise No: IT18611 – AUTOMATA AND COMPILER DESIGN LABORATORY Date: Register No: 180801097 Page No: SAMPLE INPUT: sample.c #include<stdio.h> void main() { int a, b; float _f; char 2c; _f = a + b; } SAMPLE OUTPUT: #include<stdio.h> Preprocessor void Keyword main Keyword int Keyword a Valid identifier b Valid identifier float Keyword _f Valid identifier char Keyword 2c Invalid identifier _f Valid identifier = Operator a Valid identifier + Operator b Valid identifier RESULT: The C program to design a lexical analyzer was successfully implemented. Exercise No: IT18611 – AUTOMATA AND COMPILER DESIGN LABORATORY Date: Register No: 180801097 Page No: ACCEPTANCE OF A STRING USING A REGULAR EXPRESSION AIM: To write a C program to check for the acceptance of a string using a Regular Expression. ALGORITHM: 1. Declare header files. 2. Declare a function match() which takes the pattern and string asarguments, usesregular expression to check if the string matches with thepattern. 3. If the string matches the pattern, return 1, else return 0. 4. In main function, get the pattern and string as input from the user and call the match() function until the user terminates the program. 5. If the function returns 1, print that the pattern matches. Else, print that the pattern does not match. Exercise No: IT18611 – AUTOMATA AND COMPILER DESIGN LABORATORY Date: Register No: 180801097 Page No: SOURCE CODE: #include <stdio.h> #include <regex.h> int match(char *string, char *pattern) { regex_t re; if (regcomp(&re, pattern, REG_EXTENDED | REG_NOSUB) != 0) return 0; int status = regexec(&re, string, 0, NULL, 0); regfree(&re); if (status != 0) return 0; return 1; } int main(void) { char re[100]; printf("Enter Regular expression : "); scanf("%s", re); char s1[100]; while (1) { printf("Enter string : "); scanf("%s", s1); printf("%s", match(s1, re) ? "Valid string\n" : "Invalid string\n"); } } SAMPLE INPUT AND OUTPUT: Enter Regular expression : ^a*babba*b$ Enter string : ababbab Valid string Enter string : aaaababbaaab Valid string Enter string : abbabab Invalid string RESULT : A C program to check the acceptance of a string using a regular expression was successfully implemented. Exercise No: IT18611 – AUTOMATA AND COMPILER DESIGN LABORATORY Date: Register No: 180801097 Page No: CONSTRUCTION OF NFA FOR A GIVEN REGULAR EXPRESSION AIM: To write a C program to construct a NFA for a given regular expression. ALGORITHM: 1. Declare a struct called Node with node_no, a_count, b_count and node pointers next_a, next_b and next. 2. Declare a static variable nodecount. 3. Get the regular expression from the user. 4. Check each character in the regular expression until the last is reached. 5. If the character is ‘(‘, parse the regex till ‘)’ is encountered. If the character is ‘a’, assign p- >nexta=p and increment a_count. Do the same for ‘b’ 6. If the character is *, loop the state to itself. 7. If the character is ‘a’ or ‘b’, define a new state by creating a temp node and assign the respective pointers. 8. Incremen t the ‘nodecount’ value everytime a new node is created. 9. Print the transition table. For each state, print the next states for ‘a’ and ‘b’ inputs. 10. Stop. Exercise No: IT18611 – AUTOMATA AND COMPILER DESIGN LABORATORY Date: Register No: 180801097 Page No: SOURCE CODE: #include <stdio.h> #include <string.h> #include <stdlib.h> int nodecount = 0; struct Node { struct Node *Next; int node_no; char nextA[3]; char nextB[3]; }; struct Node *Head, *p, *Temp; struct Node *create() { int c; Temp = (struct Node *)malloc(sizeof(struct Node)); Temp->node_no = nodecount; nodecount++; Temp->Next = NULL; return Temp; } void update(struct Node *p, char Ch) { char c; if (Ch == 'a') { c = p->node_no + '0'; //int to char conversion strncat(p->nextA, &c, 1); } else if (Ch == 'b') { c = p->node_no + '0'; strncat(p->nextB, &c, 1); } } int main(void) { char prev; Exercise No: IT18611 – AUTOMATA AND COMPILER DESIGN LABORATORY Date: Register No: 180801097 Page No: char regex[100], Ch[5]; int s, j, i; char c; printf("Enter the regular expression"); scanf("%s", regex); Head = create(); p = Head; for (i = 0; i<strlen(regex); i++) { if (regex[i] == '(') { s = 0; Ch[0] = Ch[1] = Ch[2] = '\0'; char prev; while (regex[i] != ')') { if (regex[i] == 'a' || regex[i] == 'b') { Ch[s] = regex[i]; s++; } i++; } if (regex[i + 1] == '*') { s = 0; while (Ch[s] != '\0') { update(p, Ch[s]); s++; } i++; } if (regex[i + 1] == '+') { Temp = create(); c = Temp->node_no + '0'; strcat(p->nextA, &c); strcat(p->nextB, &c); p->Next = Temp; s = 0; p = Temp; while (Ch[s] != '\0') Exercise No: IT18611 – AUTOMATA AND COMPILER DESIGN LABORATORY Date: Register No: 180801097 Page No: { update(p, Ch[s]); s++; } } } else if (regex[i] == '+') { prev = regex[i - 1]; update(p, prev); } else if (regex[i + 1] == '*') { prev = regex[i]; update(p, prev); i++; } else { // a or b Temp = create(); p->Next = Temp; c = Temp->node_no + '0'; if (regex[i] == 'a') strncat(p->nextA, &c, 1); else if (regex[i] == 'b') strncat(p->nextB, &c, 1); p = Temp; } } printf("\nTransition table"); printf("\n+-----------------------------------------------+"); printf("\n|\tState\t|\ta\t|\tb\t|"); printf("\n|-----------------------------------------------|"); p = Head; for (j = 0; j <nodecount; j++) { printf("\n|\t%d", p->node_no); if (p->nextA[0] == 0) printf("\t|\tnull"); else { printf("\t|\t"); Exercise No: IT18611 – AUTOMATA AND COMPILER DESIGN LABORATORY Date: Register No: 180801097 Page No: for (i = 0; i< p->nextA[i] != '\0'; i++) { printf("%c,", p->nextA[i]); } } if (p->nextB[0] == 0) printf("\t|\tnull\t|"); else { printf("\t|\t"); for (i = 0; p->nextB[i] != '\0'; i++) printf("%c,", p->nextB[i]); printf("\t|"); } p = p->Next; } printf("\n+-----------------------------------------------+"); return 0; } SAMPLE INPUT: Enter the regular expression (a/b)*abb SAMPLE OUTPUT: RESULT : The C program to construct NFA for a given regular expression was successfully implemented. Exercise No: IT18611 – AUTOMATA AND COMPILER DESIGN LABORATORY Date: Register No: 180801097 Page No: CONSTRUCTION OF DFA FOR A GIVEN REGULAR EXPRESSION AIM: To write a C program to construct a DFA for a given regular expression. ALGORITHM: 1. Declare a struct called Node with node_no and node pointers nexta, nextb and nextnode. 2. Declare a static variable nodecount. 3. Get the regular expression from the user. 4. Check each character in the regular expression until the last is reached. 5. If the character is ‘(‘, parse the regex till ‘)’ is encountered. If the character is ‘a’, assign p- >nexta=p and increment a_count. Do the same for ‘b’ 6. If the character is *, loop the state to itself and assign flag=1, temp1 to p. 7. If the character is ‘a’ or ‘b’, define a new state by creating a temp node and assign the respective pointers. If the flag is 1, point the p->nexta to temp1(if input is defined only for b). 8. Increment the ‘nodecount’ value everytime a new node is creat ed. 9. Print the transition table. For each state, print the next states for ‘a’ and ‘b’ inputs. If the next state is NULL, print inf which refers to the dead state. 10. Stop. SOURCE CODE: #include <stdio.h> #include <stdlib.h> #include <string.h> #define INF -999 struct Node { struct Node *Prev; int State; struct Node *a; struct Node *b; struct Node *Next; }; struct Node *Head = NULL, *Temp = NULL, *p, *q; int main(void) { char regex[100]; int i, Count = 0; printf("Enter the regular expression : "); Exercise No: IT18611 – AUTOMATA AND COMPILER DESIGN LABORATORY Date: Register No: 180801097 Page No: scanf("%s", regex); Head = (struct Node *)malloc(sizeof(struct Node)); p = Head; p->State = 0; p->Prev = NULL; for (i = 0; i<strlen(regex); i++) { if (regex[i] == '(') { while (regex[i] != ')') i++; if (regex[i + 1] == '*') { if (regex[i + 2] == 'a') p->b = p; if (regex[i + 2] == 'b') p->a = p; } i++; } else { Temp = (struct Node *)malloc(sizeof(struct Node)); Temp->Prev = p; p->Next = Temp; Temp->State = ++Count; Temp->Next = NULL; if (regex[i] == 'a') p->a = Temp; else p->b = Temp; p = p->Next; } } p->a = p->b = Head; p = Head; while (p != NULL) { if (p->a == NULL) p->a = p->Prev->a; if (p->b == NULL) Exercise No: IT18611 – AUTOMATA AND COMPILER DESIGN LABORATORY Date: Register No: 180801097 Page No: p->b = p->Prev->b; p = p->Next; } printf("+-------+-------+-------+\n"); printf("|State\t|a\t| b\t|\n"); printf("|-------|-------|-------|\n"); p = Head; while (p) { printf("|%d\t|", p->State); if (p->a != NULL) printf("%d\t|", p->a->State); else printf("inf\t|"); if (p->b != NULL) printf("%d\t|\n", p->b->State); else printf("inf\t|\n"); p = p->Next; } printf("+-------+-------+-------+\n"); return 0; } SAMPLE INPUT: Enter the regular expression (a/b)*abb SAMPLE OUTPUT: RESULT : The C program to construct DFA for a given regular expression was successfully implemented. Exercise No: IT18611 – AUTOMATA AND COMPILER DESIGN LABORATORY Date: Register No: 180801097 Page No: CONVERSION OF NFA TO DFA AIM: To write a c program to convert NFA to DFA for a given regular expression. ALGORITHM: Suppose there is an NFA N < Q, ∑, q0, δ, F > which recognizes a language L. Then the DFA D < Q’, ∑, q0, δ’, F’ > can be constructed for language L as: Step 1: Initially Q’ = ɸ. Step 2: Add q0 to Q’. Step 3: For each s tate in Q’, find the possible set of states for each input symbol using transition function of NFA. If this set of states is not in Q’, add it to Q’. Step 4: Final state of DFA will be all states with contain F (final states of NFA) CODE: #include<stdio.h> #include<string.h> #include<stdlib.h> int nodecount=0; struct node{ struct node *next_node; int node_no; char nexta[3]; char nextb[3]; }*head, *p, *temp; struct node* create(){ int c; temp=(struct node*)malloc(sizeof(struct node)); temp->node_no=nodecount; nodecount++; temp->next_node=NULL; return temp; Exercise No: IT18611 – AUTOMATA AND COMPILER DESIGN LABORATORY Date: Register No: 180801097 Page No: } void update (struct node*p, char ch){ char c; if(ch=='a'){ c=p->node_no+'0';//int to char conversion strncat(p->nexta,&c,1); } else if(ch=='b'){ c=p->node_no+'0'; strncat(p->nextb,&c,1); } } main(){ char prev; char regex[100],ch[5]; printf("Enter the regular expression"); scanf("%s",regex); int s,j,i; char c; head=create(); p=head; for(i=0;i<strlen(regex);i++){ if(regex[i]=='('){ s=0; ch[0]=ch[1]=ch[2]='\0'; char prev; while(regex[i]!=')'){ if(regex[i]=='a'||regex[i]=='b'){ ch[s]=regex[i]; s++; } i++; } if(regex[i+1]=='*'){ s=0; while(ch[s]!='\0'){ Exercise No: IT18611 – AUTOMATA AND COMPILER DESIGN LABORATORY Date: Register No: 180801097 Page No: update(p,ch[s]); s++; } i++; } if(regex[i+1]=='+'){ temp=create(); c=temp->node_no+'0'; strcat(p->nexta,&c); strcat(p->nextb,&c); p->next_node=temp; s=0; p=temp; while(ch[s]!='\0'){ update(p,ch[s]); s++; } } } else if(regex[i]=='+'){ prev=regex[i-1]; update(p,prev); } else if(regex[i+1]=='*'){ prev=regex[i]; update(p,prev); i++; } else{ // a or b temp=create(); p->next_node=temp; c=temp->node_no+'0'; if(regex[i]=='a') strncat(p->nexta,&c,1); else if(regex[i]=='b') strncat(p->nextb,&c,1); p=temp; Exercise No: IT18611 – AUTOMATA AND COMPILER DESIGN LABORATORY Date: Register No: 180801097 Page No: } } //transition table p=head; printf("\nTransition table"); printf("\n+-----------------------------------------------+"); printf("\n|\tState\t|\ta\t|\tb\t|"); printf("\n|-----------------------------------------------|"); for(j=0;j<nodecount;j++) { printf("\n|\t%d",p->node_no); if(p->nexta[0]==0) printf("\t|\tnull"); else{ printf("\t|\t"); for(i=0;i<p->nexta[i]!='\0';i++){ printf("%c,",p->nexta[i]); } } if(p->nextb[0]==0) printf("\t|\tnull\t|"); else{ printf("\t|\t"); for(i=0;p->nextb[i]!='\0';i++){ printf("%c,",p->nextb[i]); } printf("\t|"); } p=p->next_node; } printf("\n+-----------------------------------------------+"); } Exercise No: IT18611 – AUTOMATA AND COMPILER DESIGN LABORATORY Date: Register No: 180801097 Page No: OUTPUT: RESULT: A C program was written to convert NFA to DFA for a given regular expression. Exercise No: IT18611 – AUTOMATA AND COMPILER DESIGN LABORATORY Date: Register No: 180801097 Page No: SHIFT REDUCE PARSER AIM: To parse the given input string for a grammar using shift reduce parser. ALGORITHM: 1. Start 2. Define the grammar 3. Get input string. 4. Shift each symbol of the input string one by one into the stack. 5. While doing so, if the stack can be reduced using any of the production rule defined by the grammar. 6. If yes reduce by applying production rule else keep shifting 7. Repeat step 5-6 until only start symbol is present in the stack. 8. Stop. CODE: #include<stdio.h> #include<string.h> int k=0,z=0,i=0,j=0,c=0; char a[16],ac[20],stk[15],act[10]; void check(); int main() { puts("GRAMMAR is E->E+E \n E->E*E \n E->(E) \n E->id");