0% found this document useful (0 votes)
14 views35 pages

CD File

The document contains code implementations for various concepts in compiler design, including a lexical analyzer in C that ignores whitespace, an implementation using the Lex tool, YACC specifications for syntax categories, and algorithms for converting NFA to DFA and minimizing DFA. It also includes functions for calculating epsilon closures and operator precedence parsing. Each section provides code snippets and explanations for the respective tasks.

Uploaded by

db880074
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views35 pages

CD File

The document contains code implementations for various concepts in compiler design, including a lexical analyzer in C that ignores whitespace, an implementation using the Lex tool, YACC specifications for syntax categories, and algorithms for converting NFA to DFA and minimizing DFA. It also includes functions for calculating epsilon closures and operator precedence parsing. Each section provides code snippets and explanations for the respective tasks.

Uploaded by

db880074
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 35

Q1.

Design and implement a lexical analyser for given language using C and
the lexical analyser should ignore redundant spaces, tabs, and new lines .
Ans:-

#include <stdio.h>

#include <ctype.h>

#include <string.h>

char keywords[6][10] = {"if", "else", "while", "return", "int", "float"};

int isKeyword(char *str) {

for (int i = 0; i < 6; i++) {

if (strcmp(str, keywords[i]) == 0)

return 1;

return 0;

void lexer(const char *filename) {

FILE *fp = fopen(filename, "r");

if (!fp) {

prin ("Cannot open file.\n");

return;

char ch, buffer[100];

int i = 0;

while ((ch = fgetc(fp)) != EOF) {

if (isalnum(ch)) {

buffer[i++] = ch;

} else {

if (i > 0) {

buffer[i] = '\0';

if (isKeyword(buffer))

prin ("Keyword: %s\n", buffer);

else if (isdigit(buffer[0]))
prin ("Number: %s\n", buffer);

else

prin ("Iden fier: %s\n", buffer);

i = 0;

if (ch == ' ' || ch == '\n' || ch == '\t') con nue;

if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '=')

prin ("Operator: %c\n", ch);

else if (ch == '(' || ch == ')' || ch == '{' || ch == '}' || ch == ';')

prin ("Separator: %c\n", ch);

fclose(fp);

INPUT

OUTPUT
Q2. Implementation of lexical analyzer using Lex Tool.
Ans:-
%{

#include <stdio.h>

%}

%op on noyywrap

%%

int { prin ("Keyword: int\n"); }

float { prin ("Keyword: float\n"); }

if { prin ("Keyword: if\n"); }

else { prin ("Keyword: else\n"); }

while { prin ("Keyword: while\n"); }

for { prin ("Keyword: for\n"); }

[0-9]+ { prin ("Number: %s\n", yytext); }

[a-zA-Z_][a-zA-Z0-9_]* { prin ("Iden fier: %s\n", yytext); }

[+\-*/] { prin ("Operator: %s\n", yytext); }

= { prin ("Assignment Operator: %s\n", yytext); }

[ \t\n]+ { /* skip whitespace */ }

. { prin ("Unknown character: %s\n", yytext); }

%%

int main() {

prin ("Enter input (press Ctrl+D to finish):\n");

yylex();

return 0;

}
INPUT

OUTPUT
Q3. Generate YACC specification for a few syntactic categories.

Ans:-
%{

#include <stdio.h>

#include <stdlib.h>

#include <ctype.h>

%}

%union {

int num; // For numbers

char* id; // For iden fiers

%token <num> NUMBER

%token <id> IDENTIFIER

%token PLUS MINUS MUL DIV ASSIGN

%token LPAREN RPAREN

%token INT

%type <num> expression statement program

%%

program:

program statement { prin ("Statement processed\n"); }

| statement { prin ("Single statement\n"); }

statement:

IDENTIFIER ASSIGN expression { prin ("Assignment to %s\n", $1); }

| expression { prin ("Expression statement\n"); }

;
expression:

NUMBER { $$ = $1; }

| IDENTIFIER { $$ = 0; prin ("Iden fier: %s\n", $1); }

| expression PLUS expression { $$ = $1 + $3; prin ("Addi on result\n"); }

| expression MINUS expression { $$ = $1 - $3; prin ("Subtrac on result\n"); }

| expression MUL expression { $$ = $1 * $3; prin ("Mul plica on result\n"); }

| expression DIV expression { if ($3 == 0) {

yyerror("Division by zero");

} else {

$$ = $1 / $3;

prin ("Division result\n");

| LPAREN expression RPAREN { $$ = $2; }

%%

int main() {

prin ("Enter input (press Ctrl+D to finish):\n");

yyparse();

return 0;

int yyerror(char *s) {

fprin (stderr, "Error: %s\n", s);

return 0;

}
INPUT

OUTPUT
Q4. WAP to find ℇ-closure of all states of any given NFA with ℇ transition.
Ans:-
#include <stdio.h>

#define MAX 10

int nfa[MAX][MAX];

int n; // number of states

void epsilonClosure(int state, int closure[]) {

closure[state] = 1; // include the state itself

for (int i = 0; i < n; i++) {

if (nfa[state][i] == 1 && closure[i] == 0) {

epsilonClosure(i, closure); // recursively explore epsilon transi ons

int main() {

int i, j;

// Input number of states

prin ("Enter the number of states: ");

scanf("%d", &n);

// Input epsilon transi on matrix

prin ("Enter the epsilon transi ons (0 for no transi on, 1 for transi on):\n");

for (i = 0; i < n; i++) {

for (j = 0; j < n; j++) {

prin ("From state %d to state %d: ", i, j);

scanf("%d", &nfa[i][j]);

// Compute and print epsilon-closure for each state

for (i = 0; i < n; i++) {

int closure[MAX] = {0}; // Ini alize closure array for each state
prin ("Epsilon-closure of state %d: { ", i);

epsilonClosure(i, closure);

for (j = 0; j < n; j++) {

if (closure[j]) {

prin ("%d ", j);

prin ("}\n");

return 0;

}
INPUT

OUTPUT
Q5. WAP to convert NFA with ℇ transition to NFA without ℇ transition.
Ans:-
#include <stdio.h>

#define MAX 10

int e[MAX][MAX], nfa[MAX][2][MAX], n;

void closure(int state, int c[]) {

c[state] = 1;

for (int i = 0; i < n; i++)

if (e[state][i] && !c[i])

closure(i, c);

void epsilon_closure(int state, int result[]) {

int stack[MAX], top = -1;

int visited[MAX] = {0};

stack[++top] = state;

visited[state] = 1;

while (top >= 0) {

int s = stack[top--];

result[s] = 1;

for (int i = 0; i < n; i++) {

if (e[s][i] && !visited[i]) {

stack[++top] = i;

visited[i] = 1;

int main() {

prin ("Enter number of states: ");

scanf("%d", &n);
prin ("Enter epsilon transi ons matrix (0/1):\n");

for (int i = 0; i < n; i++)

for (int j = 0; j < n; j++)

scanf("%d", &e[i][j]);

prin ("Enter transi ons for 'a' and 'b' (0/1):\n");

for (int sym = 0; sym < 2; sym++)

for (int i = 0; i < n; i++)

for (int j = 0; j < n; j++)

scanf("%d", &nfa[i][sym][j]);

prin ("\nNFA without epsilon transi ons:\n");

for (int i = 0; i < n; i++) {

int ec[MAX] = {0};

closure(i, ec); // get epsilon-closure of state i

for (int sym = 0; sym < 2; sym++) {

int reachable[MAX] = {0};

for (int j = 0; j < n; j++) {

if (ec[j]) {

for (int k = 0; k < n; k++) {

if (nfa[j][sym][k]) {

// compute epsilon-closure of target state

int temp[MAX] = {0};

closure(k, temp);

for (int x = 0; x < n; x++)

if (temp[x]) reachable[x] = 1;

}
prin ("From %d on '%c' -> { ", i, 'a' + sym);

for (int x = 0; x < n; x++)

if (reachable[x]) prin ("%d ", x);

prin ("}\n");

return 0;

INPUT

OUTPUT
Q.6 WAP to convert NFA to DFA
Ans:-
#include <stdio.h>

int nfa[10][2][10], dfa[20][2], n, dfa_states = 0;

void convert() {

for (int i = 0; i < (1 << n); i++) {

for (int j = 0; j < 2; j++) {

int state = 0;

for (int k = 0; k < n; k++) {

if (i & (1 << k)) {

for (int l = 0; nfa[k][j][l] != -1; l++) {

state |= (1 << nfa[k][j][l]);

dfa[i][j] = state;

int main() {

prin ("Enter number of NFA states: ");

scanf("%d", &n);

prin ("Enter transi ons (state 0/1, -1 to end):\n");

for (int i = 0; i < n; i++) {

for (int j = 0; j < 2; j++) {

int k = 0;

do {

scanf("%d", &nfa[i][j][k]);

} while (nfa[i][j][k++] != -1);

}
}

convert();

prin ("\nDFA Transi ons:\n");

for (int i = 0; i < (1 << n); i++) {

prin ("State %d --0--> %d, --1--> %d\n", i, dfa[i][0], dfa[i][1]);

return 0;

INPUT

OUTPUT
Q7. WAP to minimize any given DFA.
Ans:-
#include <stdio.h>

#include <stdbool.h>

#define MAX 10

int dfa[MAX][2], n, m, minDFA[MAX][2];

bool equivalence[MAX][MAX], visited[MAX];

// Func on to check if two states are equivalent

bool areEquivalent(int state1, int state2) {

return dfa[state1][0] == dfa[state2][0] && dfa[state1][1] == dfa[state2][1];

// Func on to minimize the DFA

void minimize() {

// Ini alize equivalence matrix

for (int i = 0; i < n; i++) {

for (int j = 0; j < n; j++) {

equivalence[i][j] = (dfa[i][0] == dfa[j][0] && dfa[i][1] == dfa[j][1]);

// Mark states as reachable and group equivalent states

int group[MAX] = {-1}; // -1 indicates ungrouped state

m = 0; // Ini alize number of minimized states

// Group equivalent states and assign them new state ids

for (int i = 0; i < n; i++) {

if (group[i] == -1) {

group[i] = m++;

minDFA[group[i]][0] = dfa[i][0];

minDFA[group[i]][1] = dfa[i][1];

}
for (int j = i + 1; j < n; j++) {

if (areEquivalent(i, j)) {

group[j] = group[i];

// Build minimized DFA based on equivalence groups

for (int i = 0; i < n; i++) {

if (group[i] != -1) {

minDFA[group[i]][0] = group[dfa[i][0]]; // Transi on for input 0

minDFA[group[i]][1] = group[dfa[i][1]]; // Transi on for input 1

// Func on to display the minimized DFA

void displayMinimizedDFA() {

prin ("\nMinimized DFA Transi ons:\n");

for (int i = 0; i < m; i++) {

prin ("State %d --0--> %d, --1--> %d\n", i, minDFA[i][0], minDFA[i][1]);

int main() {

prin ("Enter number of states: ");

scanf("%d", &n);

prin ("Enter DFA transi ons (state 0/1):\n");

for (int i = 0; i < n; i++) {

for (int j = 0; j < 2; j++) {

scanf("%d", &dfa[i][j]);

}
minimize();

displayMinimizedDFA();

return 0;

INPUT

OUTPUT
Q8. Develop an operator precedence parser for a given language.
Ans:-
#include <stdio.h>

#include <string.h>

int precedence(char op) {

if (op == '+' || op == '-') return 1;

if (op == '*' || op == '/') return 2;

return 0;

void parse(char* expr) {

char stack[100];

int top = -1;

for (int i = 0; expr[i] != '\0'; i++) {

if (expr[i] >= '0' && expr[i] <= '9') {

prin ("%c ", expr[i]);

} else {

while (top != -1 && precedence(stack[top]) >= precedence(expr[i])) {

prin ("%c ", stack[top--]);

stack[++top] = expr[i];

while (top != -1) {

prin ("%c ", stack[top--]);

int main() {

char expr[100];
prin ("Enter expression: ");

scanf("%s", expr);

parse(expr);

return 0;

INPUT

OUTPUT
Q9. WAP to find simulate First and Follow of any given
grammar.
Ans:-

#include <stdio.h>

#include <string.h>

#define MAX 10

char grammar[MAX][MAX];

char first[MAX][MAX], follow[MAX][MAX];

int n;

// Function to add a character to a set if not already present

void addToSet(char set[], char c) {

if (strchr(set, c) == NULL) {

int len = strlen(set);

set[len] = c;

set[len + 1] = '\0';

// Find First set for a given non-terminal

void findFirst(char c) {

for (int i = 0; i < n; i++) {

if (grammar[i][0] == c) {

if (grammar[i][2] >= 'a' && grammar[i][2] <= 'z') {

addToSet(first[c - 'A'], grammar[i][2]);


} else {

findFirst(grammar[i][2]);

for (int j = 0; first[grammar[i][2] - 'A'][j] != '\0'; j++) {

addToSet(first[c - 'A'], first[grammar[i][2] - 'A'][j]);

// Find Follow set for a given non-terminal

void findFollow(char c) {

if (c == grammar[0][0]) addToSet(follow[c - 'A'], '$');

for (int i = 0; i < n; i++) {

for (int j = 2; grammar[i][j] != '\0'; j++) {

if (grammar[i][j] == c) {

if (grammar[i][j + 1] != '\0' && grammar[i][j + 1] >= 'a' && grammar[i][j + 1] <= 'z') {

addToSet(follow[c - 'A'], grammar[i][j + 1]);

} else if (grammar[i][j + 1] != '\0') {

findFirst(grammar[i][j + 1]);

for (int k = 0; first[grammar[i][j + 1] - 'A'][k] != '\0'; k++) {

addToSet(follow[c - 'A'], first[grammar[i][j + 1] - 'A'][k]);

} else {

findFollow(grammar[i][0]);

for (int k = 0; follow[grammar[i][0] - 'A'][k] != '\0'; k++) {


addToSet(follow[c - 'A'], follow[grammar[i][0] - 'A'][k]);

int main() {

printf("Enter number of productions: ");

scanf("%d", &n);

printf("Enter productions (A->a format):\n");

for (int i = 0; i < n; i++) {

scanf("%s", grammar[i]);

// Initialize First and Follow sets

for (int i = 0; i < MAX; i++) {

first[i][0] = '\0';

follow[i][0] = '\0';

// Calculate First and Follow sets

for (int i = 0; i < n; i++) {

findFirst(grammar[i][0]);

findFollow(grammar[i][0]);
}

// Print First sets

printf("\nFirst sets:\n");

for (int i = 0; i < 26; i++) {

if (first[i][0] != '\0') {

printf("First(%c) = {", 'A' + i);

for (int j = 0; first[i][j] != '\0'; j++) {

printf(" %c", first[i][j]);

printf(" }\n");

// Print Follow sets

printf("\nFollow sets:\n");

for (int i = 0; i < 26; i++) {

if (follow[i][0] != '\0') {

printf("Follow(%c) = {", 'A' + i);

for (int j = 0; follow[i][j] != '\0'; j++) {

printf(" %c", follow[i][j]);

printf(" }\n");

}
return 0;

INPUT

OUTPUT
Q10. Construct a recursive descent parser for an expression

Ans:-
#include <stdio.h>

#include <ctype.h>

const char *p;

int expr(); // Forward declaration

int number() {

int val = 0;

while (isdigit(*p))

val = val * 10 + (*p++ - '0');

return val;

int factor() {

if (*p == '(') {

p++; // Skip '('

int val = expr();

p++; // Skip ')'

return val;

return number();

int term() {

int val = factor();

while (*p == '*' || *p == '/') {

char op = *p++;
int val2 = factor();

val = (op == '*') ? val * val2 : val / val2;

return val;

int expr() {

int val = term();

while (*p == '+' || *p == '-') {

char op = *p++;

int val2 = term();

val = (op == '+') ? val + val2 : val - val2;

return val;

int main() {

char input[100];

printf("Enter expression: ");

fgets(input, sizeof(input), stdin);

p = input;

printf("Result: %d\n", expr());

return 0;

INPUT OUTPUT
Q11. Construct a Shift Reduce parser for a given language.

Ans:-
#include <stdio.h>

#include <string.h>

char input[100], stack[100];

int top = -1, i = 0;

void shift() {

stack[++top] = input[i++];

stack[top + 1] = '\0';

printf("Shift: %s\n", stack);

void reduce() {

if (top >= 2 && stack[top - 2] == 'E' && stack[top - 1] == '+' && stack[top] == 'E') {

top -= 2;

stack[top] = 'E';

} else if (top >= 2 && stack[top - 2] == 'E' && stack[top - 1] == '*' && stack[top] == 'E') {

top -= 2;

stack[top] = 'E';

} else if (top >= 2 && stack[top - 2] == '(' && stack[top - 1] == 'E' && stack[top] == ')') {

top -= 2;

stack[top] = 'E';

} else if (stack[top] == 'i' && input[i] == 'd') {

top--;
stack[top] = 'E';

i++;

} else {

return;

stack[top + 1] = '\0';

printf("Reduce: %s\n", stack);

int main() {

printf("Enter input (e.g., id+id*id): ");

scanf("%s", input);

strcat(input, "$");

while (1) {

if (input[i] == 'd' && stack[top] == 'i') {

reduce();

} else if (input[i] != '$') {

shift();

} else {

reduce();

if (strcmp(stack, "E") == 0 && input[i] == '$') {

printf("Accepted\n");

break;

}
if (i >= strlen(input) && strcmp(stack, "E") != 0) {

printf("Rejected\n");

break;

return 0;

INPUT

OUTPUT
Q12. WAP to perform loop unrolling.
Ans:-
#include <stdio.h>

int main() {

int a[100], n, i;

prin ("Enter number of elements: ");

scanf("%d", &n);

prin ("Enter %d elements:\n", n);

for (i = 0; i < n; i++)

scanf("%d", &a[i]);

// Loop unrolling by factor of 4

for (i = 0; i <= n - 4; i += 4) {

a[i] *= 2;

a[i + 1] *= 2;

a[i + 2] *= 2;

a[i + 3] *= 2;

// Handle remaining elements

for (; i < n; i++)

a[i] *= 2;

prin ("A er loop unrolling:\n");

for (i = 0; i < n; i++)

prin ("%d ", a[i]);

return 0;

INPUT OUTPUT
Q13. WAP to perform constant propagation.
Ans:-
#include <stdio.h>

#include <string.h>

int main() {

char var1[10], var2[10], op[10];

int val;

prin ("Enter constant assignment (e.g., a = 5): ");

scanf("%s = %d", var1, &val);

prin ("Enter expression : ");

scanf("%s = %s %s %d", var2, op, op + 1, &val);

if (strcmp(op, var1) == 0)

prin ("%s = %d %s %d;\n", var2, val, op + 1, val);

else

prin ("No propaga on possible.\n");

return 0;

INPUT

OUTPUT
Q14. Implement intermediate code generation for simple
expressions.
Ans:-
#include <stdio.h>

int main() {

char a, b, c, d;

scanf("%c = %c + %c * %c", &a, &b, &c, &d);

prin ("t1 = %c * %c\n", c, d);

prin ("t2 = %c + t1\n", b);

prin ("%c = t2\n", a);

return 0;

INPUT

OUTPUT
Q15. Implement the back end of the compiler which takes the three-
address code and produces the 8086 assembly language instructions that
can be assembled and run using an 8086 assembler. the target assembly
instructions can be sample move, add, sub, jump etc.

Ans:-
#include <stdio.h>

int main() {

char op, t1, t2, t3;

prin ("Enter 3-address code (e.g., t1 = t2 + t3): ");

scanf("%c = %c %c %c", &t1, &t2, &op, &t3);

switch(op) {

case '+':

prin ("MOV AL, %c\n", t2); // Move t2 to AL

prin ("ADD AL, %c\n", t3); // AL = AL + t3

prin ("MOV %c, AL\n", t1); // Move result to t1

break;

case '-':

prin ("MOV AL, %c\n", t2); // Move t2 to AL

prin ("SUB AL, %c\n", t3); // AL = AL - t3

prin ("MOV %c, AL\n", t1); // Move result to t1

break;

case '*':

prin ("MOV AL, %c\n", t2); // Move t2 to AL

prin ("MUL %c\n", t3); // AL = AL * t3

prin ("MOV %c, AL\n", t1); // Move result to t1

break;

case '/':

prin ("MOV AL, %c\n", t2); // Move t2 to AL

prin ("DIV %c\n", t3); // AL = AL / t3

prin ("MOV %c, AL\n", t1); // Move result to t1


break;

default:

prin ("Unsupported opera on\n");

break;

return 0;

INPUT

OUTPUT

You might also like