0% found this document useful (0 votes)
7 views7 pages

A3 47 Practical5

Uploaded by

Mushan
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)
7 views7 pages

A3 47 Practical5

Uploaded by

Mushan
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/ 7

Shri Ramdeobaba College of Engineering and Management, Nagpur

Department of Computer Science and Engineering


Session: 2024-2025
Compiler Design Lab

PRACTICAL No. 5
Topic: Three Address Code Generation
Aim: Write a program to generate three address code for the given language construct
using SDTS.

(a) Batch 1: if-then-else,


(b) Batch 2: for loop
(c) Batch 3: while loop
(d) Batch 4: do while loop

Input

(e) simple_example = """


(f) while (i < 10) {
(g) sum = sum + i;
(h) i = i + 1
(i) }
(j) """
(k)
(l) and_example = """
(m) while (i < 10 && sum < 100) {
(n) sum = sum + i;
(o) i = i + 1
(p) }
(q) """
(r)
(s) or_example = """
(t) while (i < 10 || sum < 50) {
(u) sum = sum + i;
(v) i = i + 1
(w) }
(x) """

Code
class ThreeAddressCodeGenerator:
def __init__(self):
self.line_number = 1
self.temp_var_count = 1
self.code = []

def get_next_temp(self):
temp = f"T{self.temp_var_count}"
self.temp_var_count += 1
return temp

def emit(self, code):


self.code.append(f"{self.line_number}) {code}")
self.line_number += 1

def parse_expression(self, expr):


# Parse arithmetic expressions
expr = expr.strip()
if '+' in expr:
left, right = expr.split('+', 1)
temp = self.get_next_temp()
self.emit(f"{temp}={left.strip()}+{right.strip()}")
return temp
elif '-' in expr:
left, right = expr.split('-', 1)
temp = self.get_next_temp()
self.emit(f"{temp}={left.strip()}-{right.strip()}")
return temp
elif '*' in expr:
left, right = expr.split('*', 1)
temp = self.get_next_temp()
self.emit(f"{temp}={left.strip()}*{right.strip()}")
return temp
elif '/' in expr:
left, right = expr.split('/', 1)
temp = self.get_next_temp()
self.emit(f"{temp}={left.strip()}/{right.strip()}")
return temp
else:
return expr

def parse_assignment(self, stmt):


# Parse assignment statements
left, right = stmt.split('=', 1)
temp = self.parse_expression(right)
if temp != right.strip():
self.emit(f"{left.strip()}={temp}")
else:
self.emit(f"{left.strip()}={right.strip()}")

def parse_statement(self, stmt):


stmt = stmt.strip()
if '=' in stmt and not any(op in stmt for op in ['==', '>=', '<=', '!=']):
self.parse_assignment(stmt)
# Other statement types could be added here

def parse_condition(self, condition, true_label, false_label):


"""
Parse a condition and generate code to jump to true_label if the condition is true
or to false_label if the condition is false.
"""
condition = condition.strip()
# Handle AND operation (&&)
if '&&' in condition:
left, right = self.split_condition(condition, '&&')
# Create an intermediate label
intermediate_label = self.line_number + 2

# If the left condition is false, jump to false_label


self.parse_simple_condition(left, intermediate_label, false_label)

# If we reach here, the left condition was true, now evaluate the right condition
self.parse_condition(right, true_label, false_label)
return

# Handle OR operation (||)


elif '||' in condition:
left, right = self.split_condition(condition, '||')
# Create an intermediate label
intermediate_label = self.line_number + 2

# If the left condition is true, jump to true_label


self.parse_simple_condition(left, true_label, intermediate_label)

# If we reach here, the left condition was false, now evaluate the right condition
self.parse_condition(right, true_label, false_label)
return

# Handle simple conditions


else:
self.parse_simple_condition(condition, true_label, false_label)

def split_condition(self, condition, operator):


"""
Split a condition based on an operator, respecting parentheses.
"""
parentheses_count = 0
for i in range(len(condition)):
if condition[i] == '(':
parentheses_count += 1
elif condition[i] == ')':
parentheses_count -= 1
elif condition[i:i+len(operator)] == operator and parentheses_count == 0:
return condition[:i].strip(), condition[i+len(operator):].strip()
return condition, "" # Fallback, shouldn't reach here

def parse_simple_condition(self, condition, true_label, false_label):


"""
Parse a simple condition (without && or ||) and generate jumps.
"""
# Remove enclosing parentheses if any
condition = condition.strip()
while condition.startswith('(') and condition.endswith(')'):
# Check if these are matching parentheses
if self.are_matching_parentheses(condition):
condition = condition[1:-1].strip()
else:
break

if '<' in condition:
left, right = condition.split('<', 1)
self.emit(f"if {left.strip()} < {right.strip()} goto {true_label}")
self.emit(f"goto {false_label}")
elif '>' in condition:
left, right = condition.split('>', 1)
self.emit(f"if {left.strip()} > {right.strip()} goto {true_label}")
self.emit(f"goto {false_label}")
elif '<=' in condition:
left, right = condition.split('<=', 1)
self.emit(f"if {left.strip()} <= {right.strip()} goto {true_label}")
self.emit(f"goto {false_label}")
elif '>=' in condition:
left, right = condition.split('>=', 1)
self.emit(f"if {left.strip()} >= {right.strip()} goto {true_label}")
self.emit(f"goto {false_label}")
elif '==' in condition:
left, right = condition.split('==', 1)
self.emit(f"if {left.strip()} == {right.strip()} goto {true_label}")
self.emit(f"goto {false_label}")
elif '!=' in condition:
left, right = condition.split('!=', 1)
self.emit(f"if {left.strip()} != {right.strip()} goto {true_label}")
self.emit(f"goto {false_label}")
else:
# For conditions like "if x" (boolean variable)
self.emit(f"if {condition} goto {true_label}")
self.emit(f"goto {false_label}")

def are_matching_parentheses(self, expr):


"""
Check if the expression has matching opening and closing parentheses.
"""
if not expr.startswith('(') or not expr.endswith(')'):
return False

count = 0
for i in range(len(expr)):
if expr[i] == '(':
count += 1
elif expr[i] == ')':
count -= 1
if count == 0 and i < len(expr) - 1:
return False # Found closing parenthesis before the end
return count == 0

def calculate_actual_labels(self, body_statements):


"""
Calculate the actual line numbers for given points in the code.
This helps in generating correct goto targets.
"""
condition_lines = 2

body_start = self.line_number + condition_lines


body_end = body_start + 2 * len(body_statements)
after_loop = body_end + 1

return {
'condition_start': self.line_number,
'body_start': body_start,
'body_end': body_end,
'after_loop': after_loop
}

def parse_while_loop(self, condition, body_statements):


condition_label = self.line_number

labels = self.calculate_actual_labels(body_statements)

self.parse_condition(condition, labels['body_start'], labels['after_loop'])


for stmt in body_statements:
self.parse_statement(stmt)

self.emit(f"goto {condition_label}")

# Mark the end of the while loop


self.emit("END")

# Example usage
def generate_three_address_code(while_loop):
# Extract condition and body from the while loop
start_cond = while_loop.find('(') + 1
end_cond = while_loop.find(')')
condition = while_loop[start_cond:end_cond]

start_body = while_loop.find('{') + 1
end_body = while_loop.rfind('}')
body = while_loop[start_body:end_body].strip()

# Split body into statements


statements = [stmt.strip() for stmt in body.split(';') if stmt.strip()]

# Generate the three address code


generator = ThreeAddressCodeGenerator()
generator.parse_while_loop(condition, statements)

# Print the generated code


for line in generator.code:
print(line)

Output:
Example 1: Simple condition
Input:
while (i < 10) {
sum = sum + i;
i=i+1
}

Output:
1) if i < 10 goto 3
2) goto 8
3) T1=sum+i
4) sum=T1
5) T2=i+1
6) i=T2
7) goto 1
8) END

Example 2: AND condition


Input:

while (i < 10 && sum < 100) {


sum = sum + i;
i=i+1
}

Output:
1) if i < 10 goto 3
2) goto 8
3) if sum < 100 goto 3
4) goto 8
5) T1=sum+i
6) sum=T1
7) T2=i+1
8) i=T2
9) goto 1
10) END

Example 3: OR condition
Input:

while (i < 10 || sum < 50) {


sum = sum + i;
i=i+1
}

Output:
1) if i < 10 goto 3
2) goto 3
3) if sum < 50 goto 3
4) goto 8
5) T1=sum+i
6) sum=T1
7) T2=i+1
8) i=T2
9) goto 1
10) END

You might also like