COMPILER DESIGN LAB PROGRAMS
Program1: - Design and implement a lexical analyzer for given language using C
and the lexical analyzer should ignore redundant spaces, tabs and new lines.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define MAX_TOKEN_LENGTH 100
typedef enum {
TOKEN_IDENTIFIER,
TOKEN_NUMBER,
TOKEN_OPERATOR,
TOKEN_UNKNOWN
} TokenType;
typedef struct {
TokenType type;
char value[MAX_TOKEN_LENGTH];
} Token;
void printToken(Token token)
{ switch (token.type) {
case TOKEN_IDENTIFIER:
printf("Identifier: %s\n", token.value);
break;
case TOKEN_NUMBER:
printf("Number: %s\n", token.value);
break;
case TOKEN_OPERATOR:
printf("Operator: %s\n", token.value);
break;
default:
printf("Unknown: %s\n", token.value);
break;
}
}
void tokenize(const char *input)
{ int i = 0;
while (input[i] != '\0') {
// Skip redundant spaces, tabs, and new lines
if (isspace(input[i])) {
i++;
continue;
}
Token token;
int j = 0;
if (isalpha(input[i])) {
token.type = TOKEN_IDENTIFIER;
while (isalpha(input[i]) || isdigit(input[i])) { token.value[j+
+] = input[i++];
}
} else if (isdigit(input[i]))
{ token.type =
TOKEN_NUMBER; while
(isdigit(input[i])) {
token.value[j++] = input[i++];
}
} else if (input[i] == '+' || input[i] == '-' || input[i] == '*' || input[i] == '/')
{ token.type = TOKEN_OPERATOR;
token.value[j++] = input[i++];
} else {
token.type = TOKEN_UNKNOWN;
token.value[j++] = input[i++];
}
token.value[j] = '\0';
printToken(token);
}
}
int main() {
const char *input = "int a = 5 + 3;\n\tfloat b = a * 2.5;";
tokenize(input);
return 0;
}
2. Implementation of Lexical Analysis using LeX Tool in C.
%{
#include <stdio.h>
#include <string.h>
%}
%%
[ \t\n]+ {/* ignore whitespace */}
[0-9]+ { printf("INTEGER: %s\n", yytext); }
[a-zA-Z][a-zA-Z0-9]* { printf("IDENTIFIER: %s\n", yytext); }
"+" { printf("OPERATOR: +\n"); }
"-" { printf("OPERATOR: -\n"); }
"*" { printf("OPERATOR: *\n"); }
"/" { printf("OPERATOR: /\n"); }
"=" { printf("OPERATOR: =\n"); }
"(" { printf("LEFT_PAREN: (\n"); }
")" { printf("RIGHT_PAREN: )\n"); }
. { printf("INVALID: %s\n", yytext); }
%%
int main() {
yylex();
return 0;
}
Input:
int a = 10 + 5;
Output:
IDENTIFIER: int
IDENTIFIER: a
OPERATOR: =
INTEGER: 10
OPERATOR: +
INTEGER: 5
3. Generate YACC specification for a few syntactic categories.
a. Program to recognize a valid arithmetic expression that uses operator +, – , *
and /.
b. Program to recognize a valid variable which starts with a letter followed by
any number of letters or digits.
c. Implementation of Calculator using LEX and YACC
d. Convert the BNF rules into YACC form and write code to generate
abstract syntax tree
A)
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
#include <string.h>
int i;
bool isOperator(char ch) {
return (ch == '+' || ch == '-' || ch == '*' || ch == '/');
}
bool isValidExpression(const char *expr)
{ int len = strlen(expr);
bool lastWasOperator = true; // To ensure the expression doesn't start with an
operator
for ( i = 0; i < len; i++) {
if (isspace(expr[i])) {
continue; // Ignore whitespace
} else if (isdigit(expr[i]))
{ lastWasOperator = false;
} else if (isOperator(expr[i])) {
if (lastWasOperator) {
return false; // Two operators in a row or operator at the start
}
lastWasOperator = true;
} else {
return false; // Invalid character
}
}
return !lastWasOperator; // Ensure the expression doesn't end with an operator
}
int main() {
char expr[100];
printf("Enter an arithmetic expression: ");
fgets(expr, sizeof(expr), stdin);
if (isValidExpression(expr))
{ printf("The expression is valid.\
n");
} else {
printf("The expression is invalid.\n");
}
return 0;
}
Output:-
Enter an arithmetic expression: 1
The expression is valid
B)
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
#include <string.h>
int i;
// Function to check if a character is a letter
bool isLetter(char ch) {
return (isalpha(ch));
}
// Function to check if a character is a letter or digit
bool isLetterOrDigit(char ch) {
return (isalpha(ch) || isdigit(ch));
}
// Function to check if a string is a valid variable
bool isValidVariable(const char *str) {
int len = strlen(str);
// Check if the first character is a letter
if (!isLetter(str[0])) {
return false;
}
// Check the remaining characters
for (i = 1; i < len; i++) {
if (!isLetterOrDigit(str[i]))
{ return false;
}
}
return true;
}
int main() {
char variable[100];
printf("Enter a variable name: ");
scanf("%s", variable);
if (isValidVariable(variable))
{ printf("The variable name is valid.\
n");
} else {
printf("The variable name is invalid.\n");
}
return 0;
}
Output:-
Enter a variable name: venu
The variable name is valid
4) Write program to find ε – closure of all states of any given NFA with
ε transition
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX_STATES 100
int i,j;
typedef struct {
int transitions[MAX_STATES][MAX_STATES];
int num_states;
} NFA;
void initializeNFA(NFA *nfa, int num_states)
{ nfa->num_states = num_states;
for (i = 0; i < num_states; i++)
{ for ( j = 0; j < num_states; j+
+) {
nfa->transitions[i][j] = 0;
}
}
}
void addTransition(NFA *nfa, int from, int to)
{ nfa->transitions[from][to] = 1;
}
void epsilonClosure(NFA *nfa, int state, bool *visited)
{ visited[state] = true;
for ( i = 0; i < nfa->num_states; i++) {
if (nfa->transitions[state][i] && !visited[i]) {
epsilonClosure(nfa, i, visited);
}
}
}
void findEpsilonClosures(NFA *nfa)
{ for ( i = 0; i < nfa->num_states; i++)
{
bool visited[MAX_STATES] = {false};
epsilonClosure(nfa, i, visited);
printf("e-closure of state %d: { ", i);
for (j = 0; j < nfa->num_states; j++) {
if (visited[j]) {
printf("%d ", j);
}
}
printf("}\n");
}
}
int main() {
NFA nfa;
int num_states = 4;
initializeNFA(&nfa, num_states);
// Example transitions for e-closure
addTransition(&nfa, 0, 1);
addTransition(&nfa, 1, 2);
addTransition(&nfa, 2, 3);
addTransition(&nfa, 3, 0);
findEpsilonClosures(&nfa);
return 0;
}
Output:-
e-closure of state 7: { 0 1 2 3 }
5) Write program to convert NFA with ε transition to NFA without ε
transition. #include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX_STATES 100
#define MAX_SYMBOLS 10
int i,j,k,state,symbol,to;
typedef struct {
int transitions[MAX_STATES][MAX_SYMBOLS][MAX_STATES];
int epsilon_transitions[MAX_STATES][MAX_STATES];
int num_states;
int
num_symbols;
} NFA;
void initializeNFA(NFA *nfa, int num_states, int num_symbols)
{ nfa->num_states = num_states;
nfa->num_symbols = num_symbols;
for ( i = 0; i < num_states; i++) {
for ( j = 0; j < num_symbols; j++)
{ for ( k = 0; k < num_states; k++)
{
nfa->transitions[i][j][k] = 0;
}
}
for ( k = 0; k < num_states; k++)
{ nfa->epsilon_transitions[i][k] =
0;
}
}
}
void addTransition(NFA *nfa, int from, int symbol, int to)
{ nfa->transitions[from][symbol][to] = 1;
}
void addEpsilonTransition(NFA *nfa, int from, int to)
{ nfa->epsilon_transitions[from][to] = 1;
}
void epsilonClosure(NFA *nfa, int state, bool *visited)
{ visited[state] = true;
for ( i = 0; i < nfa->num_states; i++) {
if (nfa->epsilon_transitions[state][i] && !visited[i])
{ epsilonClosure(nfa, i, visited);
}
}
}
void findEpsilonClosure(NFA *nfa, int state, bool *closure) {
bool visited[MAX_STATES] = {false};
epsilonClosure(nfa, state, visited);
for (i = 0; i < nfa->num_states; i++) {
if (visited[i]) {
closure[i] = true;
}
}
}
void convertNFA(NFA *nfa, NFA *new_nfa)
{ initializeNFA(new_nfa, nfa->num_states, nfa-
>num_symbols); for (state = 0; state < nfa->num_states; state+
+) {
bool closure[MAX_STATES] = {false};
findEpsilonClosure(nfa, state, closure);
for (symbol = 0; symbol < nfa->num_symbols; symbol++)
{ bool new_closure[MAX_STATES] = {false};
for (i = 0; i < nfa->num_states; i++)
{ if (closure[i]) {
for ( j = 0; j < nfa->num_states; j++)
{ if (nfa->transitions[i][symbol][j])
{
findEpsilonClosure(nfa, j, new_closure);
}
}
}
}
for (i = 0; i < nfa->num_states; i++)
{ if (new_closure[i]) {
addTransition(new_nfa, state, symbol, i);
}
}
}
}
}
void printNFA(NFA *nfa) {
for (state = 0; state < nfa->num_states; state++) {
for ( symbol = 0; symbol < nfa->num_symbols; symbol++) {
printf("State %d, Symbol %d: ", state, symbol);
for ( to = 0; to < nfa->num_states; to++)
{ if (nfa->transitions[state][symbol][to])
{
printf("%d ", to);
}
}
printf("\n");
}
}
}
int main() {
NFA nfa, new_nfa;
int num_states = 4;
int num_symbols =
2;
initializeNFA(&nfa, num_states, num_symbols);
// Example transitions for NFA with e-transitions
addEpsilonTransition(&nfa, 0, 1);
addTransition(&nfa, 1, 0, 2);
addTransition(&nfa, 2, 1, 3);
addEpsilonTransition(&nfa, 3, 0);
convertNFA(&nfa, &new_nfa);
printf("NFA without e-transitions:\n");
printNFA(&new_nfa);
return 0;
}
Output:-
NFA without e-transitions:
State 0, Symbol 0: 2
State 0, Symbol 1:
State 1, Symbol 0: 2
State 1, Symbol 1:
State 2, Symbol 0:
State 2, Symbol 1: 0 1 3
State 3, Symbol 0: 2
State 3, Symbol 1:
6) Write program to convert NFA to
DFA #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STATES 100
#define MAX_SYMBOLS 10
int i,j,k,l;
typedef struct {
int nfa_states[MAX_STATES];
int nfa_state_count;
} DFAState;
int nfa[MAX_STATES][MAX_SYMBOLS][MAX_STATES];
int nfa_final_states[MAX_STATES];
int nfa_state_count, nfa_symbol_count;
DFAState dfa_states[MAX_STATES];
int dfa_state_count;
int dfa_final_states[MAX_STATES];
void add_dfa_state(DFAState state) {
dfa_states[dfa_state_count++] = state;
}
int is_dfa_state_equal(DFAState a, DFAState b) {
if (a.nfa_state_count != b.nfa_state_count) return 0;
for( i = 0; i < a.nfa_state_count; i++) {
if (a.nfa_states[i] != b.nfa_states[i]) return 0;
}
return 1;
}
int find_dfa_state(DFAState state) {
for ( i = 0; i < dfa_state_count; i++) {
if (is_dfa_state_equal(dfa_states[i], state)) return i;
}
return -1;
}
void convert_nfa_to_dfa()
{ DFAState initial_state;
initial_state.nfa_state_count = 1;
initial_state.nfa_states[0] = 0;
add_dfa_state(initial_state);
for ( i = 0; i < dfa_state_count; i++) {
for (j = 0; j < nfa_symbol_count; j++)
{ DFAState new_state;
new_state.nfa_state_count = 0;
for ( k = 0; k < dfa_states[i].nfa_state_count; k++)
{ int nfa_state = dfa_states[i].nfa_states[k];
for ( l = 0; l < nfa_state_count; l++)
{ if (nfa[nfa_state][j][l]) {
new_state.nfa_states[new_state.nfa_state_count++] = l;
}
}
}
if (new_state.nfa_state_count > 0) {
int state_index = find_dfa_state(new_state);
if (state_index == -1) {
add_dfa_state(new_state);
state_index = dfa_state_count - 1;
}
printf("DFA Transition: %d -- %c --> %d\n", i, 'a' + j, state_index);
}
}
}
}
int main() {
// Initialize NFA (example)
nfa_state_count = 3;
nfa_symbol_count = 2;
nfa[0][0][1] = 1;
nfa[0][1][0] = 1;
nfa[1][0][2] = 1;
nfa[1][1][1] = 1;
nfa[2][0][2] = 1;
nfa[2][1][2] = 1;
nfa_final_states[2] = 1;
convert_nfa_to_dfa();
return 0;
}
Output:-
DFA Transition: 1 -- a --> 1
DFA Transition: 1 -- b --> 1
7) Write program to minimize any given
DFA #include <stdio.h>
#include <stdbool.h>
#define MAX_STATES
100
#define MAX_SYMBOLS 10
int j,i,k;
typedef struct {
int transitions[MAX_STATES][MAX_SYMBOLS];
bool final_states[MAX_STATES];
int num_states;
int
num_symbols;
} DFA;
void initializeDFA(DFA *dfa, int num_states, int num_symbols)
{ dfa->num_states = num_states;
dfa->num_symbols = num_symbols;
for ( i = 0; i < num_states; i++) {
for ( j = 0; j < num_symbols; j++)
{ dfa->transitions[i][j] = -1;
}
dfa->final_states[i] = false;
}
}
void addTransition(DFA *dfa, int from, int symbol, int to)
{ dfa->transitions[from][symbol] = to;
}
void setFinalState(DFA *dfa, int state)
{ dfa->final_states[state] = true;
}
void minimizeDFA(DFA *dfa) {
bool distinguishable[MAX_STATES][MAX_STATES] = {false};
for ( i = 0; i < dfa->num_states; i++) {
for ( j = 0; j < dfa->num_states; j++) {
if (dfa->final_states[i] != dfa->final_states[j])
{ distinguishable[i][j] = true;
}
}
}
bool changed;
do {
changed = false;
for ( i = 0; i < dfa->num_states; i++)
{ for ( j = 0; j < dfa->num_states; j++)
{
if (!distinguishable[i][j]) {
for (k = 0; k < dfa->num_symbols; k++)
{ int to_i = dfa->transitions[i][k];
int to_j = dfa->transitions[j][k];
if (to_i != -1 && to_j != -1 && distinguishable[to_i][to_j])
{ distinguishable[i][j] = true;
changed = true;
break;
}
}
}
}
}
} while (changed);
int new_state[MAX_STATES];
for ( i = 0; i < dfa->num_states; i++)
{ new_state[i] = -1;
}
int new_num_states = 0;
for ( i = 0; i < dfa->num_states; i++)
{ if (new_state[i] == -1) {
new_state[i] = new_num_states++;
for ( j = i + 1; j < dfa->num_states; j++)
{ if (!distinguishable[i][j]) {
new_state[j] = new_state[i];
}
}
}
}
DFA new_dfa;
initializeDFA(&new_dfa, new_num_states, dfa->num_symbols);
for ( i = 0; i < dfa->num_states; i++) {
for (j = 0; j < dfa->num_symbols; j++)
{ int to = dfa->transitions[i][j];
if (to != -1) {
addTransition(&new_dfa, new_state[i], j, new_state[to]);
}
}
if (dfa->final_states[i]) {
setFinalState(&new_dfa, new_state[i]);
}
}
*dfa = new_dfa;
}
void printDFA(DFA *dfa) {
printf("DFA:\n");
for ( i = 0; i < dfa->num_states; i++)
{ printf("State %d: ", i);
if (dfa->final_states[i])
{ printf("(final) ");
}
for (j = 0; j < dfa->num_symbols; j++)
{ int to = dfa->transitions[i][j];
if (to != -1) {
printf("%c -> %d ", 'a' + j, to);
}
}
printf("\n");
}
}
int main() {
DFA dfa;
int num_states = 4;
int num_symbols =
2;
initializeDFA(&dfa, num_states, num_symbols);
// Example transitions for DFA
addTransition(&dfa, 0, 0, 1);
addTransition(&dfa, 0, 1, 2);
addTransition(&dfa, 1, 0, 0);
addTransition(&dfa, 1, 1, 3);
addTransition(&dfa, 2, 0, 3);
addTransition(&dfa, 2, 1, 0);
addTransition(&dfa, 3, 0, 2);
addTransition(&dfa, 3, 1, 1);
setFinalState(&dfa, 3);
printf("Original DFA:\n");
printDFA(&dfa);
minimizeDFA(&dfa);
printf("Minimized DFA:\n");
printDFA(&dfa);
return 0;
}
Output:-
Original DFA:
DFA:
State 0: a -> 1 b -> 2
State 1: a -> 0 b -> 3
State 2: a -> 3 b -> 0
State 3: (final) a -> 2 b -> 1
Minimized DFA:
DFA:
State 0: a -> 1 b -> 2
State 1: a -> 0 b -> 3
State 2: a -> 3 b -> 0
State 3: (final) a -> 2 b -> 1
8. Program: Develop an operator precedence parser for a given language
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX 100
int i;
typedef struct {
char items[MAX];
int top;
} Stack;
void initStack(Stack *s)
{ s->top = -1;
}
int isFull(Stack *s) {
return s->top == MAX - 1;
}
int isEmpty(Stack *s)
{ return s->top == -1;
}
void push(Stack *s, char value) {
if (!isFull(s)) {
s->items[++(s->top)] = value;
}
}
char pop(Stack *s)
{ if (!isEmpty(s))
{
return s->items[(s->top)--];
}
return '\0';
}
char peek(Stack *s)
{ if (!isEmpty(s)) {
return s->items[s->top];
}
return '\0';
}
int precedence (char op)
{ switch (op) {
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
default:
return 0;
}
}
void infixToPostfix(char *expression)
{ Stack stack;
initStack(&stack);
char output[MAX];
int k = 0;
for (i = 0; expression[i]; i++) {
if (isdigit(expression[i])) {
output[k++] = expression[i];
} else if (expression[i] == '(') {
push(&stack, expression[i]);
} else if (expression[i] == ')') {
while (!isEmpty(&stack) && peek(&stack) != '(')
{ output[k++] = pop(&stack);
}
pop(&stack); // Remove '(' from stack
} else {
while (!isEmpty(&stack) && precedence(expression[i]) <=
precedence(peek(&stack))) {
output[k++] = pop(&stack);
}
push(&stack, expression[i]);
}
}
while (!isEmpty(&stack))
{ output[k++] = pop(&stack);
}
output[k] = '\0';
printf("Postfix Expression: %s\n", output);
}
int main() {
char expression[MAX];
printf("Enter an infix expression: ");
scanf("%s", expression);
infixToPostfix(expression);
return 0;
}
input:
3+5*2/(7-2)
Output:
Postfix Expression: 352*72-/+
9. Program: Write program to find Simulate First and Follow of any
given grammar.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX 10
char production[MAX][MAX], first[MAX][MAX], follow[MAX][MAX];
int n;
void findFirst(char, int, int);
void findFollow(char);
void followFirst(char, int, int);
int main() {
int i, choice;
char c, ch;
printf("Enter the number of productions:
"); scanf("%d", &n);
printf("Enter the productions (e.g., E=TR):\n");
for (i = 0; i < n; i++) {
scanf("%s%c", production[i], &ch);
}
int k = 0;
for (i = 0; i < n; i++)
{ c = production[i]
[0]; findFirst(c, 0,
0);
}
printf("\nFirst sets:\n");
for (i = 0; i < n; i++) {
printf("First(%c) = { ", production[i]
[0]); for (int j = 0; j < strlen(first[i]); j+
+) {
printf("%c ", first[i][j]);
}
printf("}\n");
}
for (i = 0; i < n; i++)
{ c = production[i]
[0]; findFollow(c);
}
printf("\nFollow sets:\n");
for (i = 0; i < n; i++) {
printf("Follow(%c) = { ", production[i][0]);
for (int j = 0; j < strlen(follow[i]); j++) {
printf("%c ", follow[i][j]);
}
printf("}\n");
}
return 0;
}
void findFirst(char c, int q1, int q2) {
int j;
if (!(isupper(c)))
{ first[q1][q2++] = c;
}
for (j = 0; j < n; j++) {
if (production[j][0] == c) {
if (production[j][2] == '$')
{ followFirst(production[j][0], q1, (q2 -
1));
} else if (islower(production[j][2]))
{ first[q1][q2++] = production[j][2];
} else {
findFirst(production[j][2], q1, q2);
}
}
}
}
void followFirst(char c, int c1, int c2)
{ int k;
if (!(isupper(c)))
{ follow[c1][c2++] =
c;
} else {
for (k = 0; k < n; k++) {
if (production[k][0] == c) {
if (production[k][2] == '$')
{ followFirst(production[k][0], c1,
c2);
} else if (islower(production[k][2]))
{ follow[c1][c2++] = production[k]
[2];
} else {
followFirst(production[k][2], c1, c2);
}
}
}
}
}
void findFollow(char c)
{ int i, j;
if (production[0][0] == c) { follow[0]
[strlen(follow[0])] = '$';
}
for (i = 0; i < n; i++) {
for (j = 2; j < strlen(production[i]); j++)
{ if (production[i][j] == c) {
if (production[i][j + 1] != '\0')
{ followFirst(production[i][j + 1], i,
(strlen(follow[i])));
}
if (production[i][j + 1] == '\0' && c != production[i][0]) {
findFollow(production[i][0]);
}
}
}
}
}
Output:
Enter the number of productions: 4
Enter the productions (e.g.,
E=TR): E=TR
R=+TR
R=ε
T=F
F=(E)
F=id
First sets:
First(E) = { ( id
}
First(R) = { + ε }
First(T) = { ( id }
First(F) = { ( id }
Follow sets:
Follow(E) = { $ ) }
Follow(R) = { $ ) }
Follow(T) = { + $ ) }
Follow(F) = { * + $ ) }
10) Program: Construct a recursive descent parser for an expression.
#include <stdio.h>
#include <ctype.h>
char *input;
char lookahead;
void expr();
void term();
void factor();
void match(char expected);
void error() {
printf("Syntax Error\n");
exit(1);
}
void match(char expected) {
if (lookahead == expected)
{ lookahead = *input++;
} else {
error();
}
}
void expr() {
term();
while (lookahead == '+' || lookahead == '-')
{ char op = lookahead;
match(lookahead);
term();
printf("%c ", op);
}
}
void term() {
factor();
while (lookahead == '*' || lookahead == '/')
{ char op = lookahead;
match(lookahead);
factor();
printf("%c ", op);
}
}
void factor() {
if (isdigit(lookahead))
{ printf("%c ", lookahead);
match(lookahead);
} else if (lookahead == '(') {
match('(');
expr();
match(')');
} else {
error();
}
}
int main() {
char expression[100];
printf("Enter an expression: ");
scanf("%s", expression);
input = expression;
lookahead = *input++;
expr();
if (lookahead == '\0') { printf("\
nParsing successful\n");
} else {
error();
}
return 0;
}
Output:
Enter an expression: 3+(2*4)-5
324*+5-
Parsing successful
11) Program: Construct a recursive descent parser for an expression.
#include <stdio.h>
#include <ctype.h>
char *input;
char lookahead;
void expr();
void term();
void factor();
void match(char expected);
void error() {
printf("Syntax Error\n");
exit(1);
}
void match(char expected) {
if (lookahead == expected)
{ lookahead = *input++;
} else {
error();
}
}
void expr() {
term();
while (lookahead == '+' || lookahead == '-')
{ char op = lookahead;
match(lookahead);
term();
printf("%c ", op);
}
}
void term() {
factor();
while (lookahead == '*' || lookahead == '/')
{ char op = lookahead;
match(lookahead);
factor();
printf("%c ", op);
}
}
void factor() {
if (isdigit(lookahead))
{ printf("%c ", lookahead);
match(lookahead);
} else if (lookahead == '(') {
match('(');
expr();
match(')');
} else {
error();
}
}
int main() {
char expression[100];
printf("Enter an expression: ");
scanf("%s", expression);
input = expression;
lookahead = *input++;
expr();
if (lookahead == '\0') { printf("\
nParsing successful\n");
} else {
error();
}
return 0;
}
Output:
Enter an expression: 3+(2*4)-5
324*+5-
Parsing successful
12) Program: Write a program to perform loop
unrolling. #include <stdio.h>
#define N 8
int i;
void sum_unrolled(int *arr, int n)
{ int sum = 0;
int i;
// Unrolled loop
for (i = 0; i < n; i += 4) {
sum += arr[i] + arr[i + 1] + arr[i + 2] + arr[i + 3];
}
printf("Sum: %d\n", sum);
}
int main() {
int arr[N] = {1, 2, 3, 4, 5, 6, 7, 8};
printf("Array: ");
for (i = 0; i < N; i++)
{ printf("%d ", arr[i]);
}
printf("\n");
sum_unrolled(arr, N);
return 0;
}
Output:
Array: 1 2 3 4 5 6 7 8
Sum: 36
13) Program: Write a program to perform constant
propagation. #include <stdio.h>
void constant_propagation(int a, int b)
{ int x = a + b;
int y = x * 2;
int z = y - 10;
printf("x = %d\n", x);
printf("y = %d\n", y);
printf("z = %d\n", z);
}
int main() {
int a = 5;
int b = 3;
printf("Before constant propagation:\n");
printf("a = %d, b = %d\n", a, b);
constant_propagation(a, b);
// After constant propagation
int x = 8; // a + b
int y = 16; // x * 2
int z = 6; // y - 10
printf("\nAfter constant propagation:\n");
printf("x = %d\n", x);
printf("y = %d\n", y);
printf("z = %d\n", z);
return 0;
}
Output:
Before constant propagation:
a = 5, b = 3
x=8
y = 16
z=6
After constant propagation:
x=8
y = 16
z=6
14) Implement Intermediate code generation for simple expressions.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LEN 100
int i;
typedef struct
{ char op;
char arg1[MAX_LEN];
char arg2[MAX_LEN];
char result[MAX_LEN];
} TAC;
TAC code[MAX_LEN];
int codeIndex = 0;
int tempIndex = 0;
void generateTAC(char op, char *arg1, char *arg2, char *result)
{ code[codeIndex].op = op;
strcpy(code[codeIndex].arg1, arg1);
strcpy(code[codeIndex].arg2, arg2);
strcpy(code[codeIndex].result, result);
codeIndex++;
}
void printTAC() {
for (i = 0; i < codeIndex; i++) {
printf("%s = %s %c %s\n", code[i].result, code[i].arg1, code[i].op,
code[i].arg2);
}
}
void parseExpression(char *expr)
{ char temp[MAX_LEN];
char op;
int i = 0, j = 0;
while (expr[i] != '\0') {
if (expr[i] == '+' || expr[i] == '-' || expr[i] == '*' || expr[i] == '/')
{ op = expr[i];
temp[j] = '\0';
char arg1[MAX_LEN], arg2[MAX_LEN], result[MAX_LEN];
strcpy(arg1, temp);
j = 0;
i++;
while (expr[i] != '\0' && expr[i] != '+' && expr[i] != '-' && expr[i] != '*'
&& expr[i] != '/') {
temp[j++] = expr[i++];
}
temp[j] = '\0';
strcpy(arg2, temp);
sprintf(result, "t%d", tempIndex+
+); generateTAC(op, arg1, arg2,
result); strcpy(temp, result);
j = 0;
} else {
temp[j++] = expr[i++];
}
}
}
int main() {
char expr[MAX_LEN];
printf("Enter an arithmetic expression: ");
scanf("%s", expr);
parseExpression(expr);
printTAC();
return 0;
}
Output:-
Enter an arithmetic expression: +
t0 = +