0% found this document useful (0 votes)
12 views69 pages

CD53 Final

Uploaded by

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

CD53 Final

Uploaded by

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

FORM NO.

- F/ TL / 021
Rev.00 Date 20.03.2020

RECORD NOTEBOOK

EBCS22L06-COMPILER DESIGN LAB

2024–2025 (ODD SEMESTER)


DEPARTMENT
OF
COMPUTER SCIENCE AND ENGINEERING

NAME : J.AMIRTHA HARSHINI

REGISTER NO : 221061101014
COURSE : B.TECH (CSE)

YEAR/SEM/SEC : III / V/ A
FORM NO.- F/ TL / 021
Rev.00 Date 20.03.2020

BONAFIDE CERTIFICATE

Register No : 221061101014
Name of Lab : COMPILER DESIGN LAB
Department : COMPUTER SCIENCE AND ENGINEERING

Certified that, this Record note book is a bonafide record of work done by J.AMIRTHA
HARSHINI of III Year B. Tech / CSE, Sec - ‘A’ in the COMPILER DESIGNLAB during
the year 2024-2025.

Signature of Lab-in-Charge Signature of Head of Dept

Submitted for the Practical Examination held on

Internal Examiner External Examiner


INDEX

SINO NAME OF THE EXPERIMENT DATE MARKS SIGN

1. Implementation of symbol table.


25/7/24

1/8/24
Develop a lexical analyzer to recognize a few patterns in Python
2.

Design a lexical analyzer for the given language. The 3/8/24


3. lexical analyzer should ignore redundant spaces,tabs and
new lines, comments etc.

4. Program to recognize a valid variable which starts with a letter 8/8/24


followed by any number of letter ordigits.

5. Program to implement NFAs that recognize identifiers, constants, 22/8/24


and operators of the mini language.

Program to implement DFAs that recognize identifiers, constants, 29/8/24


6. and operators of the mini language.

7. Program to eliminate Left Factoring. 5/9/24

8. Program to Construct top-down parsing table. 12/9/24

Program for Shift-reduce parsing algorithm. 19/9/24


9.

10. Program to Operator-Precedence parsing algorithm. 26/9/24

11. Program to Construct LR-Parsing table. 26/9/24

12. Program to Generate a code for a given intermediate code. 3/10/24

13. Generate Machine code. 3/10/24


Exp.No:1 Date:25-07-24

Implementation of symbol table


Aim:

To implement a symbol table for Python like programming language.


Algorithm:
Here’s a simplified algorithm to create a symbol table:
1. Initialize an empty dictionary to store symbols.

2. For each line in the input C program:

 Tokenize the line into symbols.


 For each symbol:
 If the symbol is not in the table, add it with
initial attributes.
 If the symbol is already in the table, update its
attributes if necessary.
3. Output the symbol table.

J.AMIRTHA HARSHINI 1 221061101014


Program:
import re
class
SymbolTable:
def init (self):
self.table = {}

def add_symbol(self, name, symbol_type, size,


line_no): if name not in self.table:
self.table[name] = {
'type': symbol_type,
'size': size,
'lines': [line_no]
}
elif line_no not in self.table[name]['lines']: self.table[name]
['lines'].append(line_no)

def str (self):


output = ""
for name, info in self.table.items():
output += f"Name: {name}, Type: {info['type']}, Size: {info['size']} bytes, Lines:
{info['lines']}\n"
return output

def tokenize(line):
tokens = re.findall(r'\b\w+\b', line)
return tokens

def main():
J.AMIRTHA HARSHINI 2 221061101014
symbol_table =
SymbolTable() file_path =
'Desktop\sample.c'

# Define data types and their sizes


data_types = {
"int": 4, # Corrected size for
int "float": 4,
"char": 1,
"double": 8,
"void": 0 # Assuming void variables are not stored
}

# Define pattern for variable declarations


declaration_pattern = re.compile(r'^(int|float|char|double|void)\s+([^;]+);')

# Read file
with open(file_path, 'r') as file:
lines = file.readlines()

# Track declared symbols to avoid counting them again in the same line
declared_symbols = set()

for line_no, line in enumerate(lines,


start=1): line = line.strip()

# Check for variable declarations


match = declaration_pattern.match(line)

J.AMIRTHA HARSHINI 3 221061101014


if match:
symbol_type = match.group(1)
size = data_types[symbol_type]
variables = match.group(2).split(',')
for var in variables:
var_name = var.strip().split('=')[0].strip()
symbol_table.add_symbol(var_name, symbol_type, size, line_no)
declared_symbols.add(var_name)

# Check for usage of symbols, including declarations


for line_no, line in enumerate(lines, start=1):
tokens = tokenize(line)
for token in tokens:
if token in symbol_table.table:
symbol_table.add_symbol(token, symbol_table.table[token]['type'],
symbol_table.table[token]['size'], line_no)

# Print symbol
table
print(symbol_table)

if name == " main ":


main()

J.AMIRTHA HARSHINI 4 221061101014


Sample input file named Sample.C
#include <stdio.h>
int main() {
int a, b, c;
float d;
char e;
a = 5;
b = 10;
c = a + b;
d = 3.14;
e = 'x';
printf("Sum: %d\n", c);
printf("Pi: %f\n", d);
printf("Character: %c\n", e);
return 0;
}

J.AMIRTHA HARSHINI 5 221061101014


Output:

Result:
Thus the program was executed and tested successfully.

J.AMIRTHA HARSHINI 6 221061101014


Exp.No:2 Date:01-08-24

Develop a lexical analyzer to recognize a few patterns in Python


(ex. Identifiers, constants, comments,operators etc.)

Aim:
To implement a lexical analyzer to recognize different token types

Algorithm:

 Start: Begins the process.


 Initialize tokens: Initializes an empty list to store tokens.
 Initialize idx: Initializes index to track current position in input text.
 Loop while idx < len(input_text): Continues processing until end of input text.
 For each pattern in patterns: Checks each defined pattern sequentially.
 Attempt to match pattern: Tries to match current pattern starting from
idxin input_text.
 If match found: If a match is found, tokenizes it and updates idx.
 If no match found: Handles whitespace or raises an error for
unexpected characters.
 Output tokens: Once all tokens are identified, outputs them.
 End: Ends the process.

J.AMIRTHA HARSHINI 7 221061101014


Program:
import re
class SymbolTable:
def init (self):
self.table = {}
def add_symbol(self, name, symbol_type, size, line_no):
if name not in self.table:
self.table[name] = {
'type': symbol_type,
'size': size,
'lines': [line_no]
}
elif line_no not in self.table[name]['lines']: self.table[name]
['lines'].append(line_no)
def str (self):
output = ""
for name, info in self.table.items():
output += f"Name: {name}, Type: {info['type']}, Size: {info['size']} bytes, Lines: {info['lines']}\n"
return output
def tokenize(line):
tokens = re.findall(r'\b\w+\b',
line) return tokens
def main():
symbol_table = SymbolTable()
file_path = 'Desktop\sample.c'
# Define data types and their sizes
data_types = {
"int": 4, # Corrected size for
int "float": 4,
"char": 1,

J.AMIRTHA HARSHINI 8 221061101014


"double": 8,
"void": 0 # Assuming void variables are not stored
}
# Define pattern for variable declarations
declaration_pattern = re.compile(r'^(int|float|char|double|void)\s+([^;]+);')
# Read file
with open(file_path, 'r') as file:
lines = file.readlines()
# Track declared symbols to avoid counting them again in the same line
declared_symbols = set()
for line_no, line in enumerate(lines, start=1):
line = line.strip()
# Check for variable declarations
match = declaration_pattern.match(line)
if match:
symbol_type = match.group(1)
size = data_types[symbol_type]
variables = match.group(2).split(',')
for var in variables:
var_name = var.strip().split('=')[0].strip()
symbol_table.add_symbol(var_name, symbol_type, size, line_no)
declared_symbols.add(var_name)
# Check for usage of symbols, including declarations
for line_no, line in enumerate(lines, start=1):
tokens =
tokenize(line) for
token in tokens:
if token in symbol_table.table:
symbol_table.add_symbol(token, symbol_table.table[token]['type'],
symbol_table.table[token]['size'], line_no)

J.AMIRTHA HARSHINI 9 221061101014


# Print symbol
table
print(symbol_table)
if name == " main ":
main()

J.AMIRTHA HARSHINI 10 221061101014


Output:

Result:
Thus the program was executed and tested successfully.

J.AMIRTHA HARSHINI 11 221061101014


Exp.No:3 Date:03-08-24

Design a lexical analyzer for the given language. The lexical analyzer should
ignore redundant spaces,tabs and new lines, comments etc.

Aim:
To write a Python program to implement a lexical analyzer that ignore redundant spaces, tabs
and new lines, comments, etc.
Algorithm:
 Start: Begins the process.
 Initialize tokens: Initializes an empty list to store tokens.
 Initialize idx: Initializes index to track current position in input text.
 Loop while idx < len(input_text): Continues processing until end of
input text.
 Skip whitespace using isspace(): Skips over spaces, tabs, and newlines.
 Check for comment "//": If //is found, skips to the next newline character.
 Check for comment "/*": If /*is found, skips to the closing */sequence.
 For each pattern in patterns: Checks each defined pattern sequentially.
 Attempt to match pattern: Tries to match current pattern starting from
idxin input_text.

 If match found: If a match is found, tokenizes it and updates idx.


 If no match found: Handles errors for unexpected characters.
 Output tokens: Once all tokens are identified, outputs them.
 End: Ends the process.

J.AMIRTHA HARSHINI 12 221061101014


Program:
import re
class SymbolTable:
def init (self):
self.table = {}
def add_symbol(self, name, symbol_type, size, line_no):
if name not in self.table:
self.table[name] = {
'type': symbol_type,
'size': size,
'lines': [line_no]
}
elif line_no not in self.table[name]['lines']: self.table[name]
['lines'].append(line_no)
def str (self):
output = ""
for name, info in self.table.items():
output += f"Name: {name}, Type: {info['type']}, Size: {info['size']} bytes, Lines: {info['lines']}\n"
return output
def tokenize(line):
tokens = re.findall(r'\b\w+\b',
line) return tokens
def main():
symbol_table = SymbolTable()
file_path = 'Desktop\sample.c'
# Define data types and their sizes
data_types = {
"int": 4, # Corrected size for
int "float": 4,
"char": 1,

J.AMIRTHA HARSHINI 13 221061101014


"double": 8,
"void": 0 # Assuming void variables are not stored
}
# Define pattern for variable declarations
declaration_pattern = re.compile(r'^(int|float|char|double|void)\s+([^;]+);')
# Read file
with open(file_path, 'r') as file:
lines = file.readlines()
# Track declared symbols to avoid counting them again in the same line
declared_symbols = set()
for line_no, line in enumerate(lines, start=1):
line = line.strip()
# Check for variable declarations
match = declaration_pattern.match(line)
if match:
symbol_type = match.group(1)
size = data_types[symbol_type]
variables = match.group(2).split(',')
for var in variables:
var_name = var.strip().split('=')[0].strip()
symbol_table.add_symbol(var_name, symbol_type, size, line_no)
declared_symbols.add(var_name)
# Check for usage of symbols, including declarations
for line_no, line in enumerate(lines, start=1):
tokens =
tokenize(line) for
token in tokens:
if token in symbol_table.table:
symbol_table.add_symbol(token, symbol_table.table[token]['type'],
symbol_table.table[token]['size'], line_no)

J.AMIRTHA HARSHINI 14 221061101014


# Print symbol
table
print(symbol_table)
if name == " main ":
main()

J.AMIRTHA HARSHINI 15 221061101014


Output:

Result:
Thus the program was executed and tested successfully.

J.AMIRTHA HARSHINI 16 221061101014


Exp.No:4 Date:08-08-24

Program to recognize a valid variable which starts with a letter followed by any
number of letter or digits.

Aim:
To write a Python program to check whether it follows a given regular expression as letter
followed by zero or more letter and digit.

Algorithm:
 Start
 Prompt the user to input a variable name.
 Define a function is_valid_variable(variable_name):

 Create a regular expression pattern: ^[a-zA-Z][a-zA-Z0-9]*$


 Use re.match(pattern, variable_name)to check if the
variable name matches the pattern.
 If it matches, return True; otherwise, return False.

 Call the function is_valid_variable(variable_name)with the user input.


 If the function returns True, print that the variable name is valid.
 If the function returns False, print that the variable name is not valid.
 End

J.AMIRTHA HARSHINI 17 221061101014


Program:

import re
def is_valid_variable(variable_name):
# Regular expression for a valid variable name
pattern = r'^[a-zA-Z][a-zA-Z0-9]*$'
# Match the pattern with the variable_name
return bool(re.match(pattern, variable_name))
# Get user input for the variable name
variable_name = input("Enter the variable name: ")
# Check if the variable name is valid
if is_valid_variable(variable_name):
print(f"{variable_name} is a valid variable name.")
else:
print(f"{variable_name} is not a valid variable name. Please enter a name starting with a letter and
followed by letters or digits.")

J.AMIRTHA HARSHINI 18 221061101014


Output:

Result:
Thus the program was executed and tested successfully.

J.AMIRTHA HARSHINI 19 221061101014


Exp.No:5 Date:22-08-24

Program to recognize a valid variabProgram to implement NFAs


that recognize identifiers, constants, and operators of the mini language.

Aim:

To Write a Python program that implements NFA for the assumed mini language.

Algorithm:
1. Start: Begin the program.
2. Initialize NFAs: Initialize the NFAs for identifiers,
constants, and operators with their respective states,
accept states, and transition functions.
3. Input String: Provide the input string for testing.
4. Identify NFA Type: Determine which NFA to use
based on the type of input string (identifier, constant,
or operator).
5. Start State: Set the current state to the start state of the chosen NFA.
6. Iterate Characters: For each character in the input string, do the following:
 Check Transitions: Check the transition
function for the current character and update the
current state.
 Update States: Update the current states based on the
transition function.
 End of String: If the end of the string is reached, proceed to the
next step.
7. Check Acceptance: Check if the current state is an accept state.
8. Output Result: Output whether the input string is accepted or rejected.
9. Repeat: Repeat steps 3-8 for each test case.
10. End: End the program.

J.AMIRTHA HARSHINI 20 221061101014


Program:
import re
class NFA:
def init (self, start_state, accept_states, transition_function):
"""
Initialize the NFA with the given start state, accept states, and transition function.
Args:
start_state (str): The initial state of the NFA.
accept_states (set): A set of states that are considered accepting.
transition_function (dict): A dictionary mapping (state, input) pairs to sets of
next
states.
"""
self.start_state = start_state
self.accept_states = accept_states
self.transition_function = transition_function

def recognize(self, string):


"""
Check if the given string is accepted by the NFA.

Args:
string (str): The input string to check.

Returns:
bool: True if the string is accepted, False otherwise.
"""
current_states = {self.start_state}
for char in string:
next_states = set()
for state in current_states:
if (state, char) in self.transition_function:
J.AMIRTHA HARSHINI 21 221061101014
next_states.update(self.transition_function[(state, char)])
if (state, 'ANY') in self.transition_function and re.match(r'[a-zA-Z]', char):
next_states.update(self.transition_function[(state, 'ANY')])
if (state, 'DIGIT') in self.transition_function and re.match(r'\d', char):
next_states.update(self.transition_function[(state, 'DIGIT')])
current_states = next_states
return bool(current_states & self.accept_states)

# Helper function to classify input characters


def classify_char(char):
if re.match(r'[a-zA-Z]', char):
return 'ANY'
elif re.match(r'\d', char):
return 'DIGIT'
return char

# Identifier NFA
identifier_start_state = 'q0'
identifier_accept_states = {'q1'}
identifier_transition_function = {
('q0', 'ANY'): {'q1'},
('q1', 'ANY'): {'q1'},
('q1', 'DIGIT'): {'q1'}
}
identifier_nfa = NFA(identifier_start_state, identifier_accept_states,
identifier_transition_function)

# Constants NFA
constant_start_state = 'q0'
constant_accept_states = {'q2', 'q4'}
constant_transition_function = {

J.AMIRTHA HARSHINI 22 221061101014


('q0', '+'): {'q1'},
('q0', '-'): {'q1'},
('q0', 'DIGIT'): {'q2'},
('q1', 'DIGIT'): {'q2'},
('q2', 'DIGIT'): {'q2'},
('q2', '.'): {'q3'},
('q3', 'DIGIT'): {'q4'},
('q4', 'DIGIT'): {'q4'}
}
constant_nfa = NFA(constant_start_state, constant_accept_states,
constant_transition_function)

# Operators NFA
operator_start_state = 'q0'
operator_accept_states = {'q1'}
operator_transition_function = {
('q0', '+'): {'q1'},
('q0', '-'): {'q1'},
('q0', '*'): {'q1'},
('q0', '/'): {'q1'}
}
operator_nfa = NFA(operator_start_state, operator_accept_states,
operator_transition_function)

def test_nfa(nfa, test_cases):


"""
Test the given NFA with the provided test cases.

Args:
nfa (NFA): The NFA to test.
test_cases (list): A list of strings to test.

J.AMIRTHA HARSHINI 23 221061101014


"""
for test in test_cases:
result = nfa.recognize(test)
print(f"Input: {test}, Result: {'Accepted' if result else 'Rejected'}")

# Test cases
identifier_test_cases = ['var1', '1var', 'variable', 'var_123', 'varName']
constant_test_cases = ['123', '-456', '3.14', '+0.001', '12.', '.56']
operator_test_cases = ['+', '-', '*', '/']

print("Testing Identifiers:")
test_nfa(identifier_nfa, identifier_test_cases)
print("\nTesting Constants:")
test_nfa(constant_nfa, constant_test_cases)
print("\nTesting Operators:")
test_nfa(operator_nfa, operator_test_cases)

J.AMIRTHA HARSHINI 24 221061101014


Output:

Result:
Thus the program was executed and tested successfully.

J.AMIRTHA HARSHINI 25 221061101014


Exp.No:6 Date:29-08-24

Program to implement DFAs that recognize identifiers, constants,


and operators of the mini language.

Aim:

To implement a DFA that recognize identifiers.

Algorithm:
1. Initialize the current state to q0.
2. Read each character from the input string:
oIf the current state is q0:
 If the character matches [a-zA-Z_], transition to q1.
 If it doesn't match, reject the string.
o If the current state is q1:
 If the character matches [a-zA-Z0-9_], stay in q1.
 If it doesn't match, reject the string.
3. After processing all characters, if the final state is q1, accept the string as
a valid identifier. Otherwise, reject it

J.AMIRTHA HARSHINI 26 221061101014


Program:
# Define the function to check if a given string is a valid identifier
def is_identifier(input_string):
# Define the initial state
state = 'q0'

# Transition through each character in the input string


for char in input_string:
if state == 'q0':
if char.isalpha() or char == '_':
state = 'q1' # Move to state 'q1' if the first character is a letter or underscore
else:
return False # Invalid identifier if the first character is not a letter or underscore
elif state == 'q1':
if char.isalnum() or char == '_':
state = 'q1' # Stay in state 'q1' if subsequent characters are alphanumeric or
underscore
else:
return False # Invalid identifier if characters are not alphanumeric or underscore

# Final state check


return state == 'q1' # Valid identifier if it ends in state 'q1'

# Sample inputs to test the DFA


inputs = ["abc", "_xyz", "a1_b2", "9abc", "a!bc"]

# Run the DFA on each input and print the result


for identifier in inputs:
result = is_identifier(identifier)
print(f"Input: '{identifier}' is {'a valid' if result else 'an invalid'} identifier.")

J.AMIRTHA HARSHINI 27 221061101014


Output:

Result:
Thus the program was executed and tested successfully.

J.AMIRTHA HARSHINI 28 221061101014


Exp.No:7 Date:

Program to eliminate Left Factoring.


Aim:

To write a Python program that finds the left factored CFG.

Algorithm:
1. Initialize an empty dictionary new_productions to store the new production rules.

2. Iterate through the input productions dictionary:

 For each nonterminal symbol lhs (left-hand side):

 Find the common prefix among


the right-hand sides rhs_list using
the find_common_prefix function.

 If a common prefix is found:

 Create a new nonterminal symbol new_lhs by appending a prime


(') to the original lhs.

 Create a new list of right-hand sides new_rhs_list by removing the


common prefix from each right-hand side in rhs_list.

 Add the production rule f"{common_prefix}{new_lhs}" to the


new_productions[lhs] list.

 Add the production rules in new_rhs_list to the


new_productions[new_lhs] list.

 If no common prefix is found, add the original rhs_list to the


new_productions[lhs] list.

3. Return the new_productions dictionary.

J.AMIRTHA HARSHINI 29 221061101014


Program:
def eliminate_left_factoring(productions):
new_productions = {}
for lhs, rhs_list in productions.items():
if not rhs_list: # Check for empty list
new_productions[lhs] = rhs_list
continue
common_prefix = find_common_prefix(rhs_list)
if common_prefix:
new_lhs = f"{lhs}'"
new_rhs_list = [cp[len(common_prefix):] for cp in rhs_list if
cp.startswith(common_prefix) and cp != common_prefix]
new_productions[lhs] = [f"{common_prefix}{new_lhs}"]
new_productions[new_lhs] = new_rhs_list
else:
new_productions[lhs] = rhs_list
return new_productions

def find_common_prefix(rhs_list):
if not rhs_list or any(not rhs for rhs in rhs_list): # Check for empty list or empty strings
return ""
prefix = rhs_list[0]
for rhs in rhs_list[1:]:
i=0
while i < len(prefix) and i < len(rhs) and prefix[i] == rhs[i]:
i += 1
prefix = prefix[:i]
if not prefix:
return ""
return prefix

J.AMIRTHA HARSHINI 30 221061101014


# Example usage
productions = {
"S": ["aAb", "aC", "aAd"],
"A": ["x", "y"]
}
new_productions = eliminate_left_factoring(productions)
print(new_productions)

J.AMIRTHA HARSHINI 31 221061101014


Output:

Result:
Thus the program was executed and tested successfully.

J.AMIRTHA HARSHINI 32 221061101014


Exp.No:8 Date:12-09-24

Program to Construct top-down parsing table.


Aim:

To implement SLR top-down parsing table.

Algorithm:
 Start: The program begins with initializing and defining the grammar.
 Define the Grammar: Define the CFG using a dictionary structure.
 Initialize First and Follow Sets: Initialize data
structures for storing First and Follow sets.
 Compute First Sets: Iterate over the grammar rules
and calculate the First sets for each non-terminal.
 Compute Follow Sets: Calculate Follow sets by
considering the grammar rules and First sets.
 Construct Parsing Table: Use the First and Follow sets to fill in the
parsing table.
 Display Parsing Table: Output the constructed parsing table.
 Display First and Follow Sets: Output the First and Follow sets for
each non-terminal.
 End: The program terminates.

J.AMIRTHA HARSHINI 33 221061101014


Program:

from collections import defaultdict


def compute_first(symbol, grammar, first, visited):
"""
Compute the First set for a symbol.
Args:
symbol (str): The symbol for which to compute the First set.
grammar (dict): The grammar.
first (dict): The First sets for non-terminals.
visited (set): The non-terminals currently being visited.
Returns:
set: The First set for the symbol.
"""
if symbol in first:
return first[symbol]

if symbol.islower(): # Terminal
first[symbol] = {symbol}
return first[symbol]

if symbol in visited: # Handle left recursion


return set()

visited.add(symbol)

first[symbol] = set()

for production in grammar.get(symbol, []):


for char in production:
first_char = compute_first(char, grammar, first, visited)
first[symbol].update(first_char - {'ε'})

J.AMIRTHA HARSHINI 34 221061101014


if 'ε' not in first_char:
break
else:
first[symbol].add('ε')
visited.remove(symbol)
return first[symbol]
def compute_follow(symbol, grammar, first, follow, start_symbol, visited):
"""
Compute the Follow set for a symbol.

Args:
symbol (str): The symbol for which to compute the Follow set.
grammar (dict): The grammar.
first (dict): The First sets for non-terminals.
follow (dict): The Follow sets for non-terminals.
start_symbol (str): The start symbol of the grammar.
visited (set): The non-terminals currently being visited.

Returns:
set: The Follow set for the symbol.
"""
if symbol == start_symbol:
follow[symbol].add('$')

if symbol in visited: # Handle left recursion


return follow[symbol]

visited.add(symbol)

for lhs, productions in grammar.items():


for production in productions:
for i, char in enumerate(production):

J.AMIRTHA HARSHINI 35 221061101014


if char == symbol:
if i + 1 < len(production):
next_first = compute_first(production[i + 1], grammar, first, visited)
follow[symbol].update(next_first - {'ε'})
if 'ε' in next_first and lhs != symbol:
follow[symbol].update(compute_follow(lhs, grammar, first,
follow, start_symbol, visited))
elif lhs != symbol:
follow[symbol].update(compute_follow(lhs, grammar, first, follow,
start_symbol, visited))

visited.remove(symbol)
return follow[symbol]
def construct_parsing_table(grammar, first, follow):
"""
Construct the parsing table.

Args:
grammar (dict): The grammar.
first (dict): The First sets for non-terminals.
follow (dict): The Follow sets for non-terminals.

Returns:
dict: The parsing table.
"""
table = defaultdict(dict)
for lhs, productions in grammar.items():
for production in productions:
first_set = set()
if production[0] == 'ε':
first_set = follow[lhs]
else:
first_set = compute_first(production[0], grammar, first, set())

J.AMIRTHA HARSHINI 36 221061101014


for terminal in first_set - {'ε'}: table[lhs]
[terminal] = production
if 'ε' in first_set:
for terminal in follow[lhs]: table[lhs]
[terminal] = production
return table
# Define the grammar
grammar = {
'E': ['TE\''],
'E\'': ['+TE\'', 'ε'],
'T': ['FT\''],
'T\'': ['*FT\'', 'ε'],
'F': ['(E)', 'id']
}
# Initialize First and Follow sets
first = {}
follow = defaultdict(set)
# Compute First sets
for non_terminal in grammar:
compute_first(non_terminal, grammar, first, set())
# Compute Follow sets
start_symbol = 'E'
for non_terminal in grammar:
compute_follow(non_terminal, grammar, first, follow, start_symbol, set())
# Construct the parsing table
parsing_table = construct_parsing_table(grammar, first, follow)
# Display the parsing table
print("Parsing Table:")
for non_terminal, transitions in parsing_table.items():
for terminal, production in transitions.items():
print(f"M[{non_terminal}, {terminal}] = {non_terminal} → {production}")

J.AMIRTHA HARSHINI 37 221061101014


# Display First and Follow sets
print("\nFirst Sets:")
for non_terminal, first_set in first.items():
print(f"First({non_terminal}) = {first_set}")
print("\nFollow Sets:")
for non_terminal, follow_set in follow.items():
print(f"Follow({non_terminal}) = {follow_set}")

J.AMIRTHA HARSHINI 38 221061101014


Output:

Result:
Thus the program was executed and tested successfully.

J.AMIRTHA HARSHINI 39 221061101014


Exp.No:9 Date:19-09-24

Program for Shift-reduce parsing algorithm.


Aim:

To write Program for Shift-reduce parsing algorithm.

Algorithm:

1. Input:
 Production rules in the form left->right.
 Input string to be parsed.
2. Initialization:
 Start with an empty stack.
 Set the input index to the start of the string.
3. Shift Operation:
 Print the current stack and the remaining input string.
 Mark the operation as "Shift".
4. Reduce Operation:
 Check if any production rule's right-hand side matches a substring
in the stack:
 If a match is found:
 Replace the matched substring in
the stack with the left-hand side of
the rule.
 Print the current stack and the remaining input string.
 Mark the operation as "Reduce".
5. Loop:
 Repeat the Shift and Reduce operations until:
 The stack matches the start symbol, and
the input string is fully processed (Accept).
 No further reductions are possible, and
the input string is fully processed
(Reject).
6. Output:
 Print "Accepted" if the input string is
successfully parsed according to the
grammar.
 Print "Not Accepted" if the parsing fails.

J.AMIRTHA HARSHINI 40 221061101014


Program:

class ProductionRule:

def init (self, left, right):

self.left = left

self.right = right

def shift_reduce_parser(rules, input_string):

"""

Shift-Reduce Parser implementation.

Args:

rules (list): List of ProductionRule objects representing the grammar.

input_string (str): Input string to parse.

Returns:

None

"""

stack = ''

i=0

rule_count = len(rules)

while True:

# If there are more characters in the input string, add the next character to the stack

if i < len(input_string):

ch = input_string[i]

i += 1

J.AMIRTHA HARSHINI 41 221061101014


stack += ch print(f"{stack}\t{input_string[i:]}\

tShift {ch}")

# Iterate through the production rules to find a possible reduction

reduced = False

for j in range(rule_count):

# Check if the right-hand side of the production rule matches a substring in the stack

if rules[j].right in stack:

# Replace the matched substring with the left-hand side of the production rule

stack = stack.replace(rules[j].right, rules[j].left, 1) print(f"{stack}\

t{input_string[i:]}\tReduce {rules[j].left}->{rules[j].right}") reduced = True

break # Stop searching for more reductions

# If no reduction was possible, check if the input has been fully shifted

if not reduced:

# Check if the stack contains only the start symbol and if the entire input string has
been processed

if stack == rules[0].left and i == len(input_string): print("\

nAccepted")

break

# If the input string has been fully processed and no further reduction is possible

elif i == len(input_string):

print("\nNot Accepted")

break

def main():

J.AMIRTHA HARSHINI 42 221061101014


rules = []

# User input for the number of production rules

rule_count = int(input("\nEnter the number of production rules: "))

# User input for each production rule in the form 'left->right'

print("\nEnter the production rules (in the form 'left->right'): ")

for _ in range(rule_count):

temp = input().strip()

left, right = temp.split("->")

rules.append(ProductionRule(left, right))

# User input for the input string

input_string = input("\nEnter the input string: ").strip()

# Call the parser function

shift_reduce_parser(rules, input_string)

if name == " main ":

main()

J.AMIRTHA HARSHINI 43 221061101014


Output:

Result:
Thus the program was executed and tested successfully.

J.AMIRTHA HARSHINI 44 221061101014


Exp.No:10 Date:26-09-24

Program to Operator-Precedence parsing algorithm.

Aim:
To implement Operator-Precedence parsing algorithm.
Algorithm:

1. Input Number of Production Rules:


 Prompt the user to enter the number of production rules.
2. Grammar Check:
 For each production:
 Split the input on ->to separate the
left- hand side and right- hand side.
 Validate the production based on specific
criteria (e.g., non- empty, valid
symbols).
 If all productions are valid,
confirm that the grammar is
accepted.
3. String Check:
 Prompt the user to enter the operators and
terminals used in the grammar, ending with
$.
 Initialize a precedence relational table nbased
on the operators and terminals.
 Populate the table using precedence rules:
 Compare terminals and operators
to fill in the relational table.
 Prompt the user for a string to check, appending $to the end.
 Implement a parsing algorithm to validate
the string against the precedence table:
 Use a stack to manage input and states.
 Loop until the stack and
input match the expected end
state.
 If the string matches the grammar,
return true; otherwise, return
false.
4. Output Results:
Print whether the grammar and string are accepted or not.

J.AMIRTHA HARSHINI 45 221061101014


Program:

import numpy as np
def stringcheck():
operators = list(input("Enter the operators used in the given grammar including the terminals:\
n "))
operators.append('$')
print(operators)
terminals = list("abcdefghijklmnopqrstuvwxyz")
operator_symbols = list('(/*%+-)')
n = np.empty([len(operators) + 1, len(operators) + 1], dtype=str, order="C")
for j in range(1, len(operators) + 1):
n[0][j] = operators[j - 1]
n[j][0] = operators[j - 1]
for i in range(1, len(operators) + 1):
for j in range(1, len(operators) + 1):
if n[i][0] in terminals and n[0][j] in terminals:
n[i][j] = ""
elif n[i][0] in terminals:
n[i][j] = ">"
elif n[i][0] in operator_symbols and n[0][j] in operator_symbols:
if operator_symbols.index(n[i][0]) <= operator_symbols.index(n[0][j]):
n[i][j] = ">"
else:
n[i][j] = "<"
elif n[i][0] in operator_symbols and n[0][j] in terminals:
n[i][j] = "<"
elif n[i][0] == "$" and n[0][j] != "$":
n[i][j] = "<"
elif n[0][j] == "$" and n[i][0] != "$":
n[i][j] = ">"

J.AMIRTHA HARSHINI 46 221061101014


else:
break
print("The Operator Precedence Relational Table\
n=============================================")
print(n)
input_string = list(input("Enter the string to be checked (non-terminals should be in
lowercase): "))
input_string.append("$")
s = [None] *
len(input_string) q = 0
s.insert(q, "$")
x = [row[0] for row in
n] y = list(n[0])
h=0
while s[0] != s[1]:
if input_string[len(input_string) - 2] in operator_symbols:
break
elif (s[q] in x) and (input_string[h] in y):
if n[x.index(s[q])][y.index(input_string[h])] ==
"<": q += 1
s.insert(q,
input_string[h]) h += 1
elif n[x.index(s[q])][y.index(input_string[h])] ==
">": s.pop(q)
q -= 1
elif (n[x.index(s[q])][y.index(input_string[h])] == '') and (s[q] == "$" and input_string[h]
== "$"):
s[1] = s[0]
else:
break
if s[0] != s[1]:

J.AMIRTHA HARSHINI 47 221061101014


return False
return True
def grammarcheck(i):
print(f"Enter the {i + 1}th grammar (production) to be checked:\n For null production, please
enter any special symbol or whitespace...")
b = list(input().split("->"))
terminals = list("abcdefghijklmnopqrstuvwxyz")
if b[0] == " " or b[0] == "" or b[0] in terminals or len(b) == 1:
return False
b.pop(0)
b = list(b[0])
non_terminals = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
operators = list("(abcdefghijklmnopqrstuvwxyz^/*+-|)")
special_symbols = ['!', '@', '#', '$', '?', '~', '`', ',', ';', ':', '"', '=', '_', '&', "'", "", " "]
g = True
for i in range(0, len(b),
2): if b[i] == " ":
g = False
elif b[i] in special_symbols:
g = False
break
elif b[len(b) - 1] in operators and ((b[0] == "(" and b[len(b) - 1] == ")") or (b.count("(") ==
b.count(")"))):
g = True
elif b[i] in
terminals: g =
True
elif b[len(b) - 1] in operators:
g = False
elif (i == len(b) - 1) and (b[i] in
non_terminals): g = True

J.AMIRTHA HARSHINI 48 221061101014


elif (i == len(b) - 1) and (b[i] not in non_terminals) and (b[i] in operators) and b[i - 1] in
operators:
g = True
elif (b[i] in non_terminals) and (b[i + 1] in
operators): g = True
elif (b[i] in non_terminals) and (b[i + 1] in
non_terminals): g = False
break
else:
g=
False
break
return g
c = int(input("Enter the number of production rules:\
n")) t = True
for i in range(c):
if
grammarcheck(i)
: t = True
else:
t=
False
break
if t:
print("Grammar is accepted")
if stringcheck():
print("String is accepted")
else:
print("String is not accepted")
else:
print("Grammar is not accepted")

J.AMIRTHA HARSHINI 49 221061101014


Output:

Result:
Thus the program was executed and tested successfully.

J.AMIRTHA HARSHINI 50 221061101014


Exp.No:11 Date:26-09-24

Program to Construct LR-Parsing table.


Aim:
To implement SLR(1) parsing table construction for the grammar S->AA, A->aA, A->b.

Algorithm:
1. Initialization:
o The grammar is initialized with a set of productions.
o The start symbol is extended (to S' -> S) to facilitate parsing.
o The algorithm identifies terminals and non-terminals in the grammar.
2. FIRST Sets Calculation:
o FIRST sets for each non-terminal are
computed, representing the set of terminals that
begin the derivation of a non-terminal.
3. FOLLOW Sets Calculation:
o FOLLOW sets for each non-terminal are
computed, representing the set of terminals that
can appear immediately to the right of the non-
terminal in any derivation.
4. LR(0) Items Construction:
o The LR(0) items (states) are constructed using
closure and goto operations. These represent
possible parsing scenarios at different points in
the parsing process.
5. Parsing Table Construction:
o The parsing table is built, containing actions
(Shift, Reduce, Accept) and goto transitions for
each state based on the grammar rules and LR(0)
items.

J.AMIRTHA HARSHINI 51 221061101014


Program:

class Grammar:
def init (self, productions):
self.original_start_symbol = list(productions.keys())[0]
self.start_symbol = self.original_start_symbol + "'"
self.productions = {self.start_symbol: [self.original_start_symbol]}
self.productions.update(productions)
self.non_terminals = set()
self.terminals = set()
self.first_sets = {}
self.follow_sets = {}
self.lr0_items = []
self.parsing_table = {}

self.initialize_grammar()
self.compute_first_sets()
self.compute_follow_sets()
self.construct_lr0_items()
self.construct_parsing_table()

def initialize_grammar(self):
for lhs, rhs_list in self.productions.items():
self.non_terminals.add(lhs)
for rhs in rhs_list:
for symbol in
rhs:
if symbol.islower() or not symbol.isalpha():
self.terminals.add(symbol)
else:
self.non_terminals.add(symbol)

def compute_first_sets(self):
for non_terminal in self.non_terminals:
self.first_sets[non_terminal] = set()
self.first(non_terminal)

def first(self, symbol):


if symbol in self.terminals:
return {symbol}
if symbol in self.first_sets and self.first_sets[symbol]:
return self.first_sets[symbol]

for production in self.productions[symbol]:


for sym in production:
temp_first = self.first(sym)
self.first_sets[symbol].update(temp_first)
if 'ε' not in temp_first:
break
else:

J.AMIRTHA HARSHINI 52 221061101014


self.first_sets[symbol].discard('ε')

return self.first_sets[symbol]

def compute_follow_sets(self):
for non_terminal in
self.non_terminals:
self.follow_sets[non_terminal] = set()
self.follow_sets[self.start_symbol].add('$')

for _ in range(len(self.non_terminals)):
for non_terminal in self.non_terminals:
self.follow(non_terminal)

def follow(self, A):


for lhs, rhs_list in self.productions.items():
for rhs in rhs_list:
for i, symbol in enumerate(rhs):
if symbol == A:
if i + 1 < len(rhs):
next_symbol = rhs[i +
1]
self.follow_sets[A].update(self.first(next_symbol))
if 'ε' in self.first_sets[next_symbol]:
self.follow_sets[A].discard('ε')
self.follow_sets[A].update(self.follow_sets[lhs])
else:
self.follow_sets[A].update(self.follow_sets[lhs])

def closure(self, item_set):


closure_set = set(item_set)
while True:
new_items = set()
for lhs, rhs, dot_pos in closure_set:
if dot_pos < len(rhs):
symbol = rhs[dot_pos]
if symbol in self.non_terminals:
for production in self.productions[symbol]:
new_items.add((symbol, production, 0))
if new_items.issubset(closure_set):
break
closure_set.update(new_items)
return closure_set

def goto(self, item_set, symbol):


goto_set = set()
for lhs, rhs, dot_pos in item_set:
if dot_pos < len(rhs) and rhs[dot_pos] ==
symbol: goto_set.add((lhs, rhs, dot_pos + 1))
return self.closure(goto_set)

J.AMIRTHA HARSHINI 53 221061101014


def construct_lr0_items(self):
initial_item = [(self.start_symbol, self.productions[self.start_symbol][0], 0)]
initial_closure = self.closure(initial_item)
self.lr0_items = [initial_closure]

while True:
new_item_sets = []
for item_set in self.lr0_items:
for symbol in self.terminals.union(self.non_terminals):
goto_set = self.goto(item_set, symbol)
if goto_set and goto_set not in self.lr0_items and goto_set not in
new_item_sets: new_item_sets.append(goto_set)
if not new_item_sets:
break
self.lr0_items.extend(new_item_sets)

def construct_parsing_table(self):
for i, item_set in enumerate(self.lr0_items):
self.parsing_table[i] = {'action': {}, 'goto': {}}

for i, item_set in enumerate(self.lr0_items):


for lhs, rhs, dot_pos in item_set:
if dot_pos < len(rhs):
symbol = rhs[dot_pos]
if symbol in self.terminals:
goto_set = self.goto(item_set, symbol)
if goto_set in self.lr0_items:
goto_state = self.lr0_items.index(goto_set) self.parsing_table[i]
['action'][symbol] = f'Shift {goto_state}'
else:
if lhs == self.start_symbol and rhs == [self.original_start_symbol]: self.parsing_table[i]
['action']['$'] = 'Accept'
else:
for terminal in self.follow_sets[lhs]:
self.parsing_table[i]['action'][terminal] = f'Reduce {lhs} -> {"".join(rhs)}'

for symbol in self.non_terminals:


goto_set = self.goto(item_set, symbol)
if goto_set in self.lr0_items:
goto_state = self.lr0_items.index(goto_set)
self.parsing_table[i]['goto'][symbol] = goto_state

def print_follow_sets(self): print("\


nFollow Sets:")
for non_terminal, follow_set in self.follow_sets.items():
print(f"{non_terminal}: {follow_set}")

def print_parsing_table(self):
print("SLR(1) Parsing Table:")

J.AMIRTHA HARSHINI 54 221061101014


for state, transitions in self.parsing_table.items():
print(f"State {state}:")
print(f" Action: {transitions['action']}")
print(f" Goto: {transitions['goto']}")
print()

def main():
productions =
{
'S': ['AA'],
'A': ['aA', 'b']
}
grammar = Grammar(productions)
grammar.print_follow_sets()
grammar.print_parsing_table()

if name == " main ":


main()

J.AMIRTHA HARSHINI 55 221061101014


Output:

Result:
Thus the program was executed and tested successfully.

J.AMIRTHA HARSHINI 56 221061101014


Exp.No:12 Date:03-10-24

Program to Generate a code for a given intermediate code


Aim:
To implement a code generator for a given intermediate code.

Algorithm:
Algorithm for Converting a Mathematical Expression to x64 Assembly Code
Phase 1: Generate Three-Address Code (TAC)
Input: A mathematical expression as a string (e.g., "a + b + c").
Output: A list of TAC instructions.
Steps:
1. Initialize a temporary variable counter (temp_count) to 1.
2. Split the expression into tokens (operands and operators).
3. Loop through tokens to create TAC:
o For every two operands and one operator (e.g., a + b):
 Create a new temporary variable (t1, t2, etc.).
 Form a TAC instruction in the format tX = operand1 operator operand2.
 Increment the temporary variable counter.
4. Store each TAC instruction in a list.
5. Return the list of TAC instructions.
Phase 2: Convert TAC to x64 Assembly
Code Input: A list of TAC instructions.

Output: A list of x64 assembly code instructions.


Steps:
1. Initialize an empty list to store assembly code instructions.
2. Loop through each TAC instruction:
o Parse the instruction to extract the operands and the operator.
o Generate an MOV instruction to move the first operand into the RAX register.
o Based on the operator:
 If the operator is +, generate an ADD instruction with the second operand.

J.AMIRTHA HARSHINI 57 221061101014


 If the operator is -, generate a SUB instruction with the second operand.
 Extend for other operators as needed.
o Generate an MOV instruction to move the result from RAX to the
temporary variable.
3. Store each assembly instruction in a list.
4. Return the list of x64 assembly code instructions.
Flow Sequence for x64 Assembly Code Generation
1. Start: Begin the process.
2. Input Expression: Input the mathematical expression to be converted into TAC and
x64 assembly code.
3. Initialize Temp Counter: Set the temporary variable counter (temp_count) to 1.
4. Split Expression: Split the input expression into individual tokens (operands and operators).
5. For Loop (TAC Generation): Loop through tokens to generate TAC:
o If there are more tokens to process, continue to the next step.
o If not, end the TAC generation process.
6. Generate TAC Instruction: Create a TAC instruction in the form tX = operand1
operator operand2.
7. Store TAC Instruction: Store the generated TAC instruction in a list.
8. Increment Temp Counter: Increase the temporary variable counter by 1.
9. For Loop (Assembly Generation): Loop through TAC instructions to generate
assembly code:
o If there are more TAC instructions to process, continue to the next step.
o If not, proceed to output the final assembly code.
10. Parse TAC Instruction: Extract operands and the operator from the TAC instruction.
11. Generate MOV Instruction: Create a MOV instruction to move the first operand into
the RAX register.
12. Generate Arithmetic Instruction: Create an arithmetic instruction (ADD, SUB, etc.)
based on the operator.
13. Generate MOV Instruction (Result): Create a MOV instruction to move the result
from RAX to the temporary variable.
14. Store Assembly Instruction: Store the generated assembly instruction in a list.
15. Output Assembly Code: Output the final x64 assembly code.
16. End: Terminate the process.

J.AMIRTHA HARSHINI 58 221061101014


Program:

def generate_three_address_code(expr):
temp_count = 1
instructions = []
tokens = expr.split()
# Simple parsing to handle multiple operations
while len(tokens) > 1:
# Assuming binary operations only
op1 = tokens[0]
operator = tokens[1]
op2 = tokens[2]
result = f't{temp_count}'
instructions.append(f"{result} = {op1} {operator} {op2}")
# Replace the first three tokens with the result
tokens = [result] + tokens[3:] # Use the result as the new operand
temp_count += 1
return instructions
def generate_x86_code(instructions):
assembly_code = []
for instr in instructions:
result, expr = instr.split(' = ')
op1, operator, op2 = expr.split()
assembly_code.append(f"MOV EAX, {op1}")
if operator == '+':
assembly_code.append(f"ADD EAX, {op2}")
elif operator == '-':
assembly_code.append(f"SUB EAX, {op2}")
elif operator == '*':
assembly_code.append(f"MUL {op2}") # Note: EAX is used as the implicit operand

J.AMIRTHA HARSHINI 59 221061101014


elif operator == '/':
assembly_code.append(f"XOR EDX, EDX") # Clear EDX for division
assembly_code.append(f"DIV {op2}") # EAX = EAX / op2; quotient in EAX,
remainder in EDX
# Add more operators as needed
assembly_code.append(f"MOV {result}, EAX")
return assembly_code
# Example usage
expression = "a + b + c"
tac_instructions = generate_three_address_code(expression)
x86_code = generate_x86_code(tac_instructions)
print("Three-Address Code:")
for instr in tac_instructions:
print(instr)
print("\nGenerated x86 Assembly
Code:") for line in x86_code:
print(line)

J.AMIRTHA HARSHINI 60 221061101014


Output:

Result:
Thus the program was executed and tested successfully.

J.AMIRTHA HARSHINI 61 221061101014


Exp.No:13 Date:03-10-24

Generate Machine code


Aim:

To implement a machine code generator.


Algorithm:
Algorithm for Python Program to Generate Binary Code for x64 Assembly
Phase 1: Initialize Program
1. Define Functions:
o Define a function assemble_instruction(instruction) to translate each assembly
instruction into binary code.
o Define a function assemble_code(assembly_code) to process a list of assembly
instructions.
Phase 2: Translate Assembly Instructions to Binary
Input: A string containing an assembly instruction (e.g., "MOV RAX,
0x0000000000000001").
Output: A byte sequence representing the binary machine code.
Steps:
1. Parse the Instruction:
o Split the instruction string by spaces (e.g., "MOV
RAX, 0x0000000000000001" becomes ["MOV",
"RAX,", "0x0000000000000001"]).
2. Identify the Operation:
o Check the first part of the instruction to determine the operation (e.g.,
MOV, ADD).
3. Generate Binary Opcode:
o If the operation is MOV and the destination is RAX, append the corresponding
binary opcode (0x48B8) to the binary code.
o If the operation is ADD and the destination is RAX, append the
corresponding binary opcode (0x4805) to the binary code.
4. Process the Operand:
o Convert the operand (e.g., "0x0000000000000001") to an integer.
o Convert the integer to its binary representation using little-endian format.
o Append the binary representation of the operand to the binary code.
5. Return the Binary Code:
o Return the complete binary code for the instruction.

J.AMIRTHA HARSHINI 62 221061101014


Phase 3: Assemble Multiple Instructions
Input: A list of assembly instructions.
Output: A complete binary code sequence for all instructions.
Steps:
1. Initialize Binary Code:
o Start with an empty binary sequence.
2. Process Each Instruction:
o Loop through each instruction in the list.
o Call assemble_instruction to convert each instruction into binary code.
o Append the binary code for each instruction to the overall binary sequence.
3. Return the Complete Binary Code:
o Return the complete binary sequence for the entire assembly code.
Phase 4: Output the Binary Code
 Convert the final binary code sequence to a human-readable format (e.g.,
hexadecimal) for display or further use.

J.AMIRTHA HARSHINI 63 221061101014


Proogram:

def assemble_instruction(instruction):
binary_code = b""
parts = instruction.split()
if parts[0] == "MOV":
if parts[1] == "RAX,":
# MOV RAX,
imm64
binary_code += b'\x48\xb8' # Opcode for MOV RAX, imm64
operand = int(parts[2], 16) if parts[2].startswith("0x") else int(parts[2])
binary_code += operand.to_bytes(8, 'little') # Little-endian representation
elif parts[1].startswith("[") and parts[1].endswith("]"):
# MOV [imm64], RAX
binary_code += b'\x48\xa3' # Opcode for MOV [imm64], RAX
operand = int(parts[1][1:-1], 16) if parts[1][1:-1].startswith("0x") else int(parts[1][1:-
1])
binary_code += operand.to_bytes(8, 'little') # Address in memory
elif parts[0] == "ADD":
if parts[1] == "RAX,":
# ADD RAX, imm32
binary_code += b'\x48\x05' # Opcode for ADD RAX, imm32
operand = int(parts[2], 16) if parts[2].startswith("0x") else int(parts[2])
binary_code += operand.to_bytes(4, 'little') # Little-endian representation
return binary_code
def assemble_code(assembly_code):
binary_code = b""
for instruction in assembly_code:
binary_code += assemble_instruction(instruction)
return binary_code

J.AMIRTHA HARSHINI 64 221061101014


# Example usage
assembly_code = [
"MOV RAX, 0x0000000000000001", # RAX = 1
"ADD RAX, 0x00000001", # RAX += 1
"MOV [0x0000000000401000], RAX" # Memory[0x401000] = RAX
]
binary_code = assemble_code(assembly_code)
# Output the binary code in a readable format
print("Binary Code (hex):", binary_code.hex())

J.AMIRTHA HARSHINI 65 221061101014


Output:

Result:
Thus the program was executed and tested successfully.

J.AMIRTHA HARSHINI 66 221061101014

You might also like