compiler_design
compiler_design
Bachelor of Technology(B.Tech)
REGISTER NO : 10322210041
SEMESTER : 5th
YEAR : 3rd
SRM University Delhi-NCR, Sonepat, Haryana, Rajiv Gandhi Education City, Delhi-NCR, Sonepat-131029,
Haryana (India)
SRM UNIVERSITY DELHI-NCR, SONEPAT, HARYANA
BONAFIDE CERTIFICATE
This is to certify that is a bonafide work done by Mr. Saurav Kumar For
the 2 1 CS 3 1 1 7 Compiler Design L AB as a part of the B.Tech (Core), course
in SRM University Delhi-NCR, Sonepat, Haryana during the year of 2023-24.
The record was found to be completed and satisfactory.
i)One-Pass Assembler
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
char label[20];
int address;
} Symbol;
Symbol symbol_table[MAX_LABELS];
int symbol_count = 0;
Symbol Table:
START -> 0
void one_pass_assembler(char *assembly_code[], int line_count) {
int location_counter = 0;
printf("Machine Code:\n");
for (int i = 0; i < line_count; i++) {
char line[100];
strcpy(line, assembly_code[i]);
char *token = strtok(line, " ");
if (token[strlen(token) - 1] == ':') {
// Label definition
token[strlen(token) - 1] = '\0'; // Remove colon
add_to_symbol_table(token, location_counter);
token = strtok(NULL, " ");
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
char label[20];
int address;
} Symbol;
Symbol symbol_table[MAX_LABELS];
int symbol_count = 0;
Symbol Table:
START -> 0
// First Pass: Build Symbol Table
for (int i = 0; i < line_count; i++) {
char line[100];
strcpy(line, assembly_code[i]);
char *token = strtok(line, " ");
if (token[strlen(token) - 1] == ':') {
// Label definition
token[strlen(token) - 1] = '\0'; // Remove colon
add_to_symbol_table(token, location_counter);
}
location_counter++;
}
if (token[strlen(token) - 1] == ':') {
token = strtok(NULL, " "); // Skip label
}
printf("\nSymbol Table:\n");
for (int i = 0; i < symbol_count; i++) {
printf("%s -> %d\n", symbol_table[i].label, symbol_table[i].address);
}
}
int main() {
char *assembly_code[] = {
"START:",
"LOAD A",
"ADD B",
"STORE C",
"END:"
};
int line_count = sizeof(assembly_code) / sizeof(assembly_code[0]);
two_pass_assembler(assembly_code, line_count);
return 0;
}
2. Write a program to implement a symbol table.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
char name[MAX_NAME_LENGTH];
char type[20]; // e.g., "int", "float", "char"
int address;
} Symbol;
Symbol symbol_table[MAX_SYMBOLS];
int symbol_count = 0;
Symbol Table:
--------------------------------------------------
| Name | Type | Address |
--------------------------------------------------
|x | int | 100 |
--------------------------------------------------
int main() {
int choice;
char name[MAX_NAME_LENGTH], type[20];
int address;
do {
printf("\nSymbol Table Menu:\n");
printf("1. Add Symbol\n");
printf("2. Search Symbol\n");
printf("3. Display Symbol Table\n");
printf("4. Exit\n");
switch (choice) {
case 1:
printf("Enter symbol name: ");
scanf("%s", name);
printf("Enter symbol type: ");
scanf("%s", type);
printf("Enter symbol address: ");
scanf("%d", &address);
add_symbol(name, type, address);
break;
case 2:
printf("Enter symbol name to search: ");
scanf("%s", name);
int index = search_symbol(name);
if (index != -1) {
printf("Symbol found: Name = %s, Type = %s, Address = %d\n",
symbol_table[index].name,
symbol_table[index].type,
symbol_table[index].address);
} else
{
printf("Symbol '%s' not found in the table.\n", name);
}
break;
case 3:
display_symbol_table();
break;
case 4:
printf("Exiting...\n");
break;
default:
printf("Invalid choice. Please try again.\n");
}
} while (choice != 4);
return 0;
}
3. Develop a lexical analyzer to recognize a few patterns in C. (Ex.
identifiers, constants, comments, operators etc.)
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
// List of keywords
const char *keywords[] = {
"int", "float", "if", "else", "while", "return", "void", "char", "for", "do", "break"
};
const int num_keywords = sizeof(keywords) / sizeof(keywords[0]);
Lexical Analysis:
-------------------------------
| Token | Type |
-------------------------------
| int | Keyword |
| main | Identifier |
|( | Delimiter |
|) | Delimiter |
|{ | Delimiter |
| int | Keyword |
|x | Identifier |
|= | Operator |
| 10 | Constant |
|; | Delimiter |
| //... | Comment |
| float | Keyword |
|y | Identifier |
|= | Operator |
| 20 | Constant |
|. | Unknown |
|5 | Constant |
|; | Delimiter |
| if | Keyword |
|( | Delimiter |
|x | Identifier |
|< | Operator |
|y | Identifier |
|) | Delimiter |
|{ | Delimiter |
|x | Identifier |
|= | Operator |
|x | Identifier |
|+ | Operator |
|y | Identifier |
|; | Delimiter |
|} | Delimiter |
| /*...*/ | Comment |
|} | Delimiter |
-------------------------------
int is_constant(char *word) {
for (int i = 0; word[i] != '\0'; i++) {
if (!isdigit(word[i])) {
return 0;
}
}
return 1;
}
// Handle comments
if (code[i] == '/' && code[i + 1] == '/') {
printf("| %-12s | %-14s |\n", "//...", "Comment");
while (code[i] != '\0' && code[i] != '\n') {
i++;
}
continue;
}
if (is_keyword(buffer)) {
printf("| %-12s | %-14s |\n", buffer, "Keyword");
} else {
printf("| %-12s | %-14s |\n", buffer, "Identifier");
}
continue;
}
// Handle constants
if (isdigit(code[i])) {
int j = 0;
while (isdigit(code[i])) {
buffer[j++] = code[i++];
}
buffer[j] = '\0';
// Handle delimiters
if (is_delimiter(code[i])) {
printf("| %-12c | %-14s |\n", code[i], "Delimiter");
i++;
continue;
}
// Unknown token
printf("| %-12c | %-14s |\n", code[i], "Unknown");
i++;
}
printf("-------------------------------\n");
}
int main() {
const char *code = "int main() {\n"
" int x = 10; // This is a comment\n"
" float y = 20.5;\n"
" if (x < y) {\n"
" x = x + y;\n"
" }\n"
" /* Multi-line comment\n"
" Example */\n"
"}";
printf("Input Code:\n%s\n\n", code);
lexical_analyzer(code);
return 0;
}
4.Write a program to implement a lexical analyzer using Lex
Tool.
%{
#include <stdio.h>
%}
%%
%%
int main() {
yylex();
return 0;
}
int yywrap() {
return 1;
}
Keyword: int
Identifier: main
Delimiter: (
Delimiter: )
Delimiter: {
Keyword: int
Identifier: a
Operator: =
Constant: 10
Delimiter: ;
Single-line Comment: // This is a single-line comment
Keyword: float
Identifier: b
Operator: =
Constant: 20
Operator: .
Constant: 5
Delimiter: ;
Keyword: char
Identifier: c
Operator: =
Unknown Token: '
Identifier: z
Unknown Token: '
Delimiter: ;
Keyword: if
Delimiter: (
Identifier: a
Operator: <
Identifier: b
Delimiter: )
Delimiter: {
Identifier: a
Operator: =
Identifier: a
Operator: +
Identifier: b
Delimiter: ;
Delimiter: }
Multi-line Comment: /* Multi-line comment
Example */
Keyword: return
Constant: 0
Delimiter: ;
Delimiter: }
Input C file:
int main() {
int a = 10; // This is a single-line comment
float b = 20.5;
char c = 'z';
if (a < b) {
a = a + b;
}
/* Multi-line comment
Example */
return 0;
}
5.Write a program to design a lexical analyzer for a given
language, and the lexical analyzer should ignore redundant
spaces, tabs, and newlines.
%{
#include <stdio.h>
%}
%%
%%
int main() {
printf("Lexical Analysis:\n");
printf("-------------------------------\n");
yylex();
return 0;
}
int yywrap() {
return 1;
}
Lexical Analysis:
-------------------------------
Keyword: int
Identifier: main
Delimiter: (
Delimiter: )
Delimiter: {
Keyword: int
Identifier: a
Operator: =
Constant: 10
Delimiter: ;
Single-line Comment: // This is a comment
Keyword: float
Identifier: b
Operator: =
Constant: 20
Operator: .
Constant: 5
Delimiter: ;
Keyword: char
Identifier: c
Operator: =
Unknown Token: '
Identifier: z
Unknown Token: '
Delimiter: ;
Keyword: if
Delimiter: (
Identifier: a
Operator: <
Identifier: b
Delimiter: )
Delimiter: {
Identifier: a
Operator: =
Identifier: a
Operator: +
Identifier: b
Delimiter: ;
Delimiter: }
Keyword: return
Constant: 0
Delimiter: ;
Delimiter: }
Input File:
int main() {
int a = 10; // This is a comment
float b = 20.5;
char c = 'z';
if (a < b) {
a = a + b;
}
/* Multi-line comment
example */
return 0;
}
6. Write a program to implement the First and Follow of the
following Grammar:
E→ T E’
E’ → +T E’| Є
T → F T’
T’ → *FT’| Є
F → (E)|id
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAX 10
int main() {
// Initialize FIRST and FOLLOW arrays
for (int i = 0; i < MAX; i++) {
first[i][0] = '\0';
follow[i][0] = '\0';
}
// Display results
printf("Non-Terminal\tFIRST\tFOLLOW\n");
for (int i = 0; i < prodCount; i++) {
printf("%c\t\t%s\t%s\n", productions[i][0], first[productions[i][0] - 'A'],
follow[productions[i][0] - 'A']);
}
return 0;
}
7.Write a program to Develop an operator precedence parser
for a given language.
#include <stdio.h>
#include <string.h>
#define MAX 10
#define EMPTY ' '
char operators[] = {'+', '*', '(', ')', 'i', '$'}; // Operator set including terminals
char precedenceTable[MAX][MAX];
char stack[MAX];
int top = -1;
precedenceTable[getIndex('*')][getIndex('+')] = '>';
precedenceTable[getIndex('*')][getIndex('*')] = '>';
precedenceTable[getIndex('*')][getIndex('(')] = '<';
precedenceTable[getIndex('*')][getIndex(')')] = '>';
precedenceTable[getIndex('*')][getIndex('i')] = '<';
precedenceTable[getIndex('*')][getIndex('$')] = '>';
precedenceTable[getIndex('(')][getIndex('+')] = '<';
precedenceTable[getIndex('(')][getIndex('*')] = '<';
precedenceTable[getIndex('(')][getIndex('(')] = '<';
precedenceTable[getIndex('(')][getIndex(')')] = '=';
precedenceTable[getIndex('(')][getIndex('i')] = '<';
precedenceTable[getIndex(')')][getIndex('+')] = '>';
precedenceTable[getIndex(')')][getIndex('*')] = '>';
precedenceTable[getIndex(')')][getIndex(')')] = '>';
precedenceTable[getIndex(')')][getIndex('$')] = '>';
precedenceTable[getIndex('i')][getIndex('+')] = '>';
precedenceTable[getIndex('i')][getIndex('*')] = '>';
precedenceTable[getIndex('i')][getIndex(')')] = '>';
precedenceTable[getIndex('i')][getIndex('$')] = '>';
precedenceTable[getIndex('$')][getIndex('+')] = '<';
precedenceTable[getIndex('$')][getIndex('*')] = '<';
precedenceTable[getIndex('$')][getIndex('(')] = '<';
precedenceTable[getIndex('$')][getIndex('i')] = '<';
precedenceTable[getIndex('$')][getIndex('$')] = '=';
}
printf("\nStack\t\tInput\t\tAction\n");
while (*ptr != '\0') {
char topSymbol = peek();
int topIndex = getIndex(topSymbol);
int inputIndex = getIndex(*ptr);
if (precedence == '>') {
printf("Reduce\n");
pop();
} else {
printf("Error: Invalid precedence.\n");
return 0;
}
}
printf("Accept\n");
return 1;
}
int main() {
char input[MAX];
// Input string
printf("\nEnter input string ending with $: ");
scanf("%s", input);
return 0;
}
8.Write a program to construct a recursive descent parser for
an expression: E –> E + T | T
T –> T * F | F
F –> ( E ) | id
#include <stdio.h>
#include <string.h>
#include <ctype.h>
// Global variables
char input[100];
int position = 0;
// Function prototypes
int E();
int T();
int F();
Entering E
Entering T
Entering F
Entering T
Entering F
Entering E
Entering T
Entering F
return 0;
}
9.Write a program to construct an LL(1) parser for an
expression.
E -> T E'
E' -> + T E' | ε
T -> F T'
T' -> * F T' | ε
F -> ( E ) | id
#include <stdio.h>
#include <string.h>
#define MAX 10
// Parsing table
char parsingTable[MAX][MAX][MAX] = {
/* id + * ( ) $ */
/* E */ {"TE'", "", "", "TE'", "", ""},
/* E' */ {"", "+TE'", "", "", "ε", "ε"},
/* T */ {"FT'", "", "", "FT'", "", ""},
/* T' */ {"", "ε", "*FT'", "", "ε", "ε"},
/* F */ {"id", "", "", "(E)", "", ""}
};
char stack[MAX];
int top = -1;
int idx = 0;
char currentInput = input[idx];
while (top != -1) {
char topSymbol = pop();
// Main function
int main() {
char input[MAX];
if (parse(input)) {
printf("The input string is valid.\n");
} else {
printf("The input string is invalid.\n");
}
return 0;
}
10.Write a program to design a predictive parser for the
given language:
E->E+T|T
T->T*F|F
F->(E)|id
#include <stdio.h>
#include <string.h>
char stack[MAX];
int top = -1;
// Parsing table
char parsingTable[5][6][MAX] = {
// id + * ( ) $
{ "TE'", "", "", "TE'", "", "" }, // E
{ "", "+TE'", "", "", "ε", "ε" }, // E'
{ "FT'", "", "", "FT'", "", "" }, // T
{ "", "ε", "*FT'", "", "ε", "ε" }, // T'
{ "id", "", "", "(E)", "", "" } // F
};
int idx = 0;
char currentInput = input[idx];
// Match terminal
if (topSymbol == currentInput) {
printf("Match: %c\n", currentInput);
idx++;
currentInput = input[idx];
} else if (topSymbol >= 'A' && topSymbol <= 'Z') {
// Non-terminal
int row = getNonTerminalIndex(topSymbol);
int col = getTerminalIndex(currentInput);
if (parse(input)) {
printf("The input string is valid.\n");
} else {
printf("The input string is invalid.\n");
}
return 0;
}
11.Write a program to implement shift- reduce parsing
algorithm for the following grammar:
S→(L)|a
L→ L,S|S
and input string is (a,a).
#include <stdio.h>
#include <string.h>
// Grammar rules
char *rules[] = {
"S -> (L)",
"S -> a",
"L -> L,S",
"L -> S"
};
// Try to reduce
while (reduce(stack, &top)) {
// Keep reducing until no further reduction is possible
}
}
// Final check
if (top == 0 && stack[top] == 'S') {
printf("Input string is successfully parsed.\n");
} else {
printf("Error: Input string is invalid.\n");
}
}
// Main function
int main() {
char input[] = "(a,a)$";
shiftReduceParse(input);
return 0;
}
12.Write a program to design a LALR bottom-up parser for
the given language:
E→E+T | T
T→T*F | F
F→(E) | id for the input string id+id*id
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
char action[10];
int state;
} ParsingTableEntry;
// Grammar rules
char *rules[] = {
"E -> E+T",
"E -> T",
"T -> T*F",
"T -> F",
"F -> (E)",
"F -> id"
};
strcpy(actionTable[4][0].action, "s5");
strcpy(actionTable[4][3].action, "s4");
// Fill in gotoTable
gotoTable[0][0] = 1; // Goto E
gotoTable[0][1] = 2; // Goto T
gotoTable[0][2] = 3; // Goto F
gotoTable[4][0] = 8;
gotoTable[4][1] = 2;
gotoTable[4][2] = 3;
}
printf("Stack\t\tInput\t\tAction\n");
while (1) {
int state = stack[top];
char symbol = input[idx];
// Get action
ParsingTableEntry action = actionTable[state][col];
int main() {
initializeParsingTable();
parseInput(input);
return 0;
}
13.Write a program to perform loop unrolling.
#include <stdio.h>
int main() {
int size = 10;
int unrollFactor = 2; // Factor of unrolling
int arr1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int arr2[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
Original Array: 0 1 2 3 4 5 6 7 8 9
After Regular Loop: 1 2 3 4 5 6 7 8 9 10
After Unrolled Loop: 1 2 3 4 5 6 7 8 9 10
for (int i = 0; i < size; i++) {
printf("%d ", arr1[i]);
}
printf("\n");
// Regular loop
regularLoop(arr1, size);
printf("After Regular Loop: ");
for (int i = 0; i < size; i++) {
printf("%d ", arr1[i]);
}
printf("\n");
// Loop unrolling
unrolledLoop(arr2, size, unrollFactor);
printf("After Unrolled Loop: ");
for (int i = 0; i < size; i++) {
printf("%d ", arr2[i]);
}
printf("\n");
return 0;
}