Master of Computer Application
1st Semester
Session 2024-2026
Compiler Design
(20MCA21C2)
Submitted To: Dr. Priyajot Singh Submitted by: Aashish
(Assistant Professor) Student ID: 146070
Certificate
This is to certify that Aashish S/O Anil Kumar has submitted a practical file for
fulfilment of MCA 1st semester lab course for Compiler Design.
Submitted To: Dr. Priyajot Singh Submitted by: Aashish
(Assistant Professor) Student ID: 146070
INDEX
[Link] EXPERIMENTS REMARKS
1. Write a LEX program to scan reserved word
and Identifiers of C language.
2. WAP in C to implement Predictive Parsing
algorithm.
3. Write a C program to generate three address
code
4. Implement SLR (1) Parsing algorithm.
5. Design LALR bottom-up parser for the given
language.
6. Construction of NFA from Regular
Expression.
EXPERIMENT 1
Write a LEX program to scan reserved word and Identifiers of C language.
#include <stdio.h>
#include <stdbool.h>
#include <ctype.h>
bool isOperator(char c) {
char operators[] = "+-*/%=<>&|!^";
for (int i = 0; operators[i] != '\0'; i++) {
if (c == operators[i]) {
return true;
}
}
return false;
}
bool isKeyword(char* word) {
char keywords[][32] = {
"auto", "break", "case", "char", "const", "continue", "default",
"do", "double", "else", "enum", "extern", "float", "for", "goto",
"if", "int", "long", "register", "return", "short", "signed",
"sizeof", "static", "struct", "switch", "typedef", "union",
"unsigned", "void", "volatile", "while"
};
for (int i = 0; i < sizeof(keywords) / sizeof(keywords[0]); i++) {
if (strcmp(word, keywords[i]) == 0) {
return true;
}
}
return false;
}
int main() {
char expression[1000];
printf("Enter an expression: ");
fgets(expression, sizeof(expression), stdin);
int operatorCount = 0;
int identifierCount = 0;
int keywordCount = 0;
int constantCount = 0;
char* token = expression;
while (*token) {
if (isOperator(*token)) {
operatorCount++;
token++;
} else if (isalpha(*token) || *token == '_') {
// Check if it's a keyword or identifier
char word[32];
int wordIndex = 0;
while (isalnum(*token) || *token == '_') {
word[wordIndex++] = *token;
token++;
}
word[wordIndex] = '\0';
if (isKeyword(word)) {
keywordCount++;
}
else {
identifierCount++;
}
}
else if (isdigit(*token) || (*token == '-' && isdigit(*(token + 1)))) {
// Check if it's a constant
while (isdigit(*token) || *token == '.' || *token == 'e' || *token == 'E' || (*token == '-' &&
(isdigit(*(token + 1)) || tolower(*(token + 1)) == 'e'))) {
token++;
}
constantCount++;
}
else {
token++;
}
}
printf("Operators: %d\n", operatorCount);
printf("Identifiers: %d\n",
identifierCount);
printf("Keywords: %d\n",
keywordCount);
printf("Constants: %d\n",
constantCount);
return 0;
}
Output:
EXPERIMENT 2
WAP in C to implement Predictive Parsing algorithm.
#include <stdio.h>
#include <string.h>
char prol[7][10] = { "S", "A", "A", "B", "B", "C",
"C" }; char pror[7][10] = { "A", "Bb", "Cd",
"aB", "@", "Cc", "@" };
char prod[7][10] = { "S->A", "A->Bb", "A->Cd", "B->aB", "B->@", "C->Cc", "C->@" };
char first[7][10] = { "abcd", "ab", "cd", "a@", "@",
"c@", "@" }; char follow[7][10] = { "$", "$", "$",
"a$", "b$", "c$", "d$" }; char table[5][6][10];
int numr(char c)
{
switch (c)
{
case 'S': return 0;
case 'A': return 1;
case 'B': return 2;
case 'C': return 3;
case 'a': return 0;
case 'b': return 1;
case 'c': return 2;
case 'd': return 3;
case '$': return 4;
}
return (2);
}
int main()
{ int i, j, k;
for (i = 0; i < 5; i++)
for (j = 0; j < 6; j++)
strcpy(table[i][j], " ");
printf("The following grammar is used for Parsing Table:\n");
for (i = 0; i < 7; i++)
printf("%s\n", prod[i]);
printf("\nPredictive parsing table:\n");
fflush(stdin);
for (i = 0; i < 7; i++)
{ k = strlen(first[i]); for (j = 0; j < 10; j++)
if (first[i][j] != '@')
strcpy(table[numr(prol[i][0]) + 1][numr(first[i][j]) + 1], prod[i]);
}
for (i = 0; i < 7; i++)
{
if (strlen(pror[i]) == 1)
{
if (pror[i][0] == '@')
{
k = strlen(follow[i]); for (j = 0; j < k; j++)
strcpy(table[numr(prol[i][0]) + 1][numr(follow[i][j]) + 1], prod[i]);
}
}
}
strcpy(table[0][0], " ");
strcpy(table[0][1], "a");
strcpy(table[0][2], "b");
strcpy(table[0][3], "c");
strcpy(table[0][4], "d");
strcpy(table[0][5], "$");
strcpy(table[1][0], "S");
strcpy(table[2][0], "A");
strcpy(table[3][0], "B");
strcpy(table[4][0], "C");
printf("\n \n");
for (i = 0; i < 5; i++)
for (j = 0; j < 6; j++)
{ printf("%-10s", table[i][j]);
if (j == 5)
printf("\n \n"); }
}
Output:
EXPERIMENT 3
Write a C program to generate three address code.
#include <stdio.h>
int temp_count = 0;
// Function to generate a new temporary variable
char* new_temp()
{
char temp_name[5];
sprintf(temp_name, "t%d", temp_count++);
return strdup(temp_name);
}
// Function to generate three-address code for addition
void generate_addition(char* result, char* operand1, char* operand2)
{
printf("%s = %s + %s\n", result, operand1, operand2);
}
// Function to generate three-address code for multiplication
void generate_multiplication(char* result, char* operand1, char* operand2)
{
printf("%s = %s * %s\n", result, operand1, operand2);
}
int main() {
char* temp1 = new_temp();
char* temp2 = new_temp();
char* temp3 = new_temp();
char* a = "a";
char* b = "b";
char* c = "c";
generate_addition(temp1, a, b);
generate_multiplication(temp2, temp1, c);
generate_addition(temp3, temp2, b);
return 0;
}
Output :
EXPERIMENT 4
Implement SLR(1) Parsing algorithm.
#include<stdio.h>
#include<string.h>
int axn[][6][2]={ {{100,5},{-1,-1},{-1,-1},{100,4},{-1,-1},{-1,-1}}, {{-1,-1},{100,6},{-1,-1},{-
1,-1},{-1,-1},{102,102}},
{{-1,-1},{101,2},{100,7},{-1,-1},{101,2},{101,2}}, {{-1,-1},{101,4},{101,4},{-1,-
1},{101,4},{101,4}},
{{100,5},{-1,-1},{-1,-1},{100,4},{-1,-1},{-1,-1}}, {{-1,-1},{101,6},{101,6},{-1,-
1},{101,6},{101,6}},
{{100,5},{-1,-1},{-1,-1},{100,4},{-1,-1},{-1,-1}}, {{100,5},{-1,-1},{-1,-1},{100,4},{-1,-1},{-
1,-1}},
{{-1,-1},{100,6},{-1,-1},{-1,-1},{100,1},{-1,-1}}, {{-1,-1},{101,1},{100,7},{-1,-
1},{101,1},{101,1}},
{{-1,-1},{101,3},{101,3},{-1,-1},{101,3},{101,3}}, {{-1,-1},{101,5},{101,5},{-1,-
1},{101,5},{101,5}}
};//Axn Table
int gotot[12][3]={1,2,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,8,2,3,-1,-1,-1,-1,9,3,-1,-1,10,-1,-1,-1,-1,-1,-1,-1,-
1,-1,-1,-1,-1}; //GoTo table
int a[10];
char b[10];
int top=-1,btop=-1,i;
void push(int k){
if(top<9)
a[++top]=k;
}
void pushb(char k){
if(btop<9)
b[++btop]=k;
}
char TOS(){
return a[top];
}
void pop(){
if(top>=0)
top--;
}
void popb(){
if(btop>=0)
b[btop--]='\0';
}
void display(){
for(i=0;i<=top;i++)
printf("%d%c",a[i],b[i]);
}
void display1(char p[],int m) {
int l;
printf("\t\t");
for(l=m;p[l]!='\0';l++)
printf("%c",p[l]);
printf("\n");
}
void error(){
printf("Syntax Error");}
void reduce(int p){
int len,k,ad;
char src,*dest;
switch(p){
case 1:dest="E+T";
src='E';
break;
case 2:dest="T";
src='E';
break;
case 3:dest="T*F";
src='T';
break;
case 4:dest="F";
src='T';
break;
case 5:dest="(E)";
src='F';
break;
case 6:dest="i";
src='F';
break;
default:dest="\0";
src='\0';
break; }
for(k=0;k<strlen(dest);k++){
pop();
popb();
}
pushb(src);
switch(src)
{
case 'E':ad=0;
break;
case 'T':ad=1;
break;
case 'F':ad=2;
break;
default: ad=-1;
break; }
push(gotot[TOS()][ad]);}
int main(){
int j,st,ic;
char ip[20]="\0",an;
printf("Enter any String\n");
scanf("%s",ip);
push(0);
display();
printf("\t%s\n",ip);
for(j=0;ip[j]!='\0';)
{
st=TOS();
an=ip[j];
if(an>='a'&&an<='z') ic=0;
else if(an=='+') ic=1;
else if(an=='*') ic=2;
else if(an=='(') ic=3;
else if(an==')') ic=4;
else if(an=='$') ic=5;
else {
error();
break;
}
if (axn[st][ic][0] == 100) {
pushb(an);
push(axn[st][ic][1]);
display();
j++;
display1(ip, j);
} else if (axn[st][ic][0] == 101) {
reduce(axn[st][ic][1]);
display();
display1(ip, j);
} else if (axn[st][ic][1] == 102) {
printf("Given String is accepted \n");
break;
}
else{
printf("Given String is rejected");
break; }}
return 0;
}
EXPERIMENT-5
Design LALR bottom-up parser for the given language.
<parser.l>
%{
#include<stdio.h>
#include "[Link].h"
%}
%%
[0-9]+ {[Link]=atof(yytext);
return DIGIT;
\n|. return yytext[0];
%%
<parser.y>
%{
#include<stdio.h>
%}
%union
{
double dval;
}
%token <dval> DIGIT
%type <dval> expr
%type <dval> term
%type <dval> factor
%%
line: expr '\n' {
printf("%g\n",$1);
}
;
expr: expr '+' term {$$=$1 + $3 ;}
| term
;
term: term '*' factor {$$=$1 * $3 ;}
| factor
;
factor: '(' expr ')' {$$=$2 ;}
| DIGIT
;
%%
int main()
{
yyparse();
}
yyerror(char *s)
{
printf("%s",s);
}
Output :
$lex parser.l
$yacc –d parser.y
$cc [Link].c [Link].c –ll –lm
$./[Link]
2+3
EXPERIMENT 6
Construction of NFA from Regular Expression.
#include <stdio.h>
#include <stdlib.h>
// Structure to represent a state in the NFA
typedef struct State {
int label; // State label
struct State *transitions[2]; // Array to store transitions (0 and 1)
} State;
// Structure to represent an NFA
typedef struct NFA {
State *start; // Initial state
State *accept; // Accepting state
} NFA;
// Function to create a new state
State *createState(int label) {
State *newState = (State *)malloc(sizeof(State));
newState->label = label;
newState->transitions[0] = newState->transitions[1] = NULL;
return newState;
}
// Function to create an NFA for a character
NFA *createCharNFA(char c) {
NFA *nfa = (NFA *)malloc(sizeof(NFA));
nfa->start = createState(0);
nfa->accept = createState(1);
nfa->start->transitions[c - 'a'] = nfa->accept;
printf("NFA for '%c':\n", c);
printf("(q%d) --%c--> (q%d)\n", nfa->start->label, c, nfa->accept->label);
return nfa;
}
// Function to create an NFA for concatenation (X.Y)
NFA *concatenateNFA(NFA *nfa1, NFA *nfa2) {
nfa1->accept->transitions[0] = nfa2->start;free(nfa2);
printf("Concatenation NFA:\n");
printf("(q%d) --ε--> (q%d) --ε--> (q%d)\n", nfa1->start->label, nfa1->accept->label, nfa1-
>accept->transitions[0]>label);
return nfa1;
}
// Function to create an NFA for union (X|Y)
NFA *unionNFA(NFA *nfa1, NFA *nfa2) {
NFA *nfa = (NFA *)malloc(sizeof(NFA));
nfa->start = createState(0);
nfa->accept = createState(1);
nfa->start->transitions[0] = nfa1->start;
nfa->start->transitions[1] = nfa2->start;
nfa1->accept->transitions[0] = nfa->accept;
nfa2->accept->transitions[0] = nfa->accept;
free(nfa1);
free(nfa2);
printf("\n\nUnion NFA:\n");
printf(" a\n(q%d)---a---> (q%d)\n", nfa->start->label, nfa1->start->label);
printf(" | b\n");
printf("|\n");
printf(" aa\n");
printf("||\n");
printf("(q%d) ---a---> (q%d)\n\n\n", nfa1->accept->transitions[0]->label, nfa->accept->label);
return nfa;
}
// Function to create an NFA for Kleene star (X*)
NFA *kleeneStarNFA(NFA *nfa) {
nfa->start->transitions[1] = nfa->accept;
nfa->accept->transitions[0] = nfa->start;
printf("\nKleene Star NFA:\n");
printf(" a\n");
printf("(q%d) ---a---> (q%d) ---a---> (q%d)\n", nfa->start->label, nfa->accept->transitions[0]-
>label, nfa->accept>label);
printf(" ^ |\n");
return nfa;
}
// Function to simulate the NFA for an input string
int simulateNFA(NFA *nfa, const char *input) {
State *currentState = nfa->start;
int i = 0;
while (input[i] != '\0') {
char currentSymbol = input[i];
if (currentSymbol == 'a') {
currentState = currentState->transitions[0];
} else if (currentSymbol == 'b') {
currentState = currentState->transitions[1];
} else {
fprintf(stderr, "Invalid input symbol: %c\n", currentSymbol);
return 0;
}
if (currentState == NULL) {
fprintf(stderr, "Invalid transition for symbol: %c\n", currentSymbol);
return 0;
}
i++;
}
if (currentState == nfa->accept) {
printf("Input string \"%s\" accepted!\n", input);
return 1;
} else {
printf("Input string \"%s\" rejected!\n", input);
return 0;
}
}
int main() {
// Construct NFA for 'ab|c*'
NFA *nfaA = createCharNFA('a');
NFA *nfaB = createCharNFA('b');
NFA *nfaC = kleeneStarNFA(createCharNFA('c'));
NFA *nfaUnion = unionNFA(nfaA, nfaB);
NFA *nfaConcatenate = concatenateNFA(nfaUnion, nfaC);
// Simulate the NFA for input strings
simulateNFA(nfaConcatenate, "ab");
simulateNFA(nfaConcatenate, "ac");
simulateNFA(nfaConcatenate, "abcc");
simulateNFA(nfaConcatenate, "cc");
// Clean up
free(nfaConcatenate);
return 0;
}
Output