_new Compiler Practls
_new Compiler Practls
class Grammar:
def main(self):
temp = [''] * 20
left = [''] * 20
tempn = [''] * 20
right = ''
count = 0
str_list = []
while True:
line = input()
if line == 'q':
break
str_list.append(line)
print(rule)
print("Terminals are:")
try:
if not temp[0]:
temp[count] = rule[j]
else:
count += 1
temp[count] = rule[j]
except IndexError:
pass
print("\nNon-terminals are:")
count = 0
try:
if not tempn[0]:
tempn[count] = rule[j]
else:
count += 1
tempn[count] = rule[j]
except IndexError:
pass
cr = 0
if 'A' <= rule[0] <= 'Z' and 'A' <= rule[-1] <= 'Z':
if (len(rule) - 2) // 2 >= 1:
left[cr] = rule[j]
cr += 1
right = left[k]
left[k] = left[(len(rule) - 2) - 1 - k]
left[(len(rule) - 2) - 1 - k] = right
print(f"{left[0]}'-{rule[0]}'", end='')
print(left[k], end='')
print()
else:
print(f"{rule[-1]}'-{rule[0]}'")
else:
print(f"Z'-{rule[0]}'", end='')
print(rule[j], end='')
print()
if __name__ == "__main__":
grammar = Grammar()
grammar.main()
Practical 2
# Input NFA
nfa = {input(f"State {i + 1}: "): {input(f"Symbol {j + 1}: "): input(f"End state(s) for state {i + 1} through symbol {j + 1}:
").split()
for j in range(int(input("No of Transitions: ")))} for i in range(int(input("No of States: ")))}
while new_states:
curr = new_states.pop(0)
dfa[curr] = {}
for path in paths:
state = "".join(sorted(set(sum((nfa[s][path] for s in curr if path in nfa[s]), []))))
if state:
dfa[curr][path] = state
if state not in dfa: new_states.append(state)
a)Warshall Algorithm
nv, INF = 4, 999
def floyd_warshall(G):
for k in range (nv):
for i in range (nv):
for j in range (nv):
G[i][j] = min(G[i][j], G[i][k] + G[k][j])
for row in G:
print( " " .join("INF" if x == INF else str(x) for x in row ))
G=[
[0,3,INF,5],
[2,0,INF,4],
[INF,1,0,4],
[INF,INF,2,0]
]
floyd_warshall(G)
b) Transitive closure
def transitive_closure(graph):
V = len(graph)
closure=[[0]* V for _ in range(V)]
for i in range(V):
for j in range(V):
closure[i][j] = graph[i][j]
for k in range(V):
for i in range(V):
for j in range(V):
closure[i][j] = closure[i][j] or (closure[i][k] and closure[k][j])
return closure
graph= [
[1, 1, 0, 1],
[0, 1, 1, 0],
[0, 0, 1, 1],
[0, 0, 0, 1]
]
result = transitive_closure(graph)
print("transitive closure:")
for row in result:
print(row)
Practical 4
Aim: Generating Simple Precedence Matrix
import numpy as np
def topological_sort(precedence_matrix):
# Number of vertices
n = len(precedence_matrix)
linear_order = []
while queue:
node = queue.popleft()
linear_order.append(node)
in_degree[neighbor] -= 1
if in_degree[neighbor] == 0:
queue.append(neighbor)
return linear_order
# Example usage
precedence_matrix = np.array([
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1],
[0, 0, 0, 0]
])
Practical 5
Aim: Parsing using Simple Precedence Matrix
# Simple Precedence Parser in Python
print(f"Stack\tInput\tAction")
print(f"{''.join(stack)}\t{input_string[i:]}\t")
print(f"{''.join(stack)}\t{input_string[i:]}\t{action}")
# Example Usage
input_string = "i+i*i"
parse(input_string)
Practical 6
import numpy as np
return f, g
Practical 7
def create_precedence_matrix(operators):
precedence_rules = {
('+','+'): '.>', ('+','*'): '<.', ('+','('): '<.', ('+',')'): '.>',
('*','+'): '.>', ('*','*'): '.>', ('*','('): '<.', ('*',')'): '.<',
('(','+'): '<.', ('(','*'): '<.', ('(','('): '<.', (')','+'): '>.',
(')','*'): '>.', (')',')'): '.>'
}
return [[precedence_rules.get((op1, op2), '.') for op2 in operators] for op1 in operators]
Practical 8
Aim: Program for computation of FIRST AND FOLLOW of non-terminals.
return first[symbol]
# Function to compute the FOLLOW set for a given symbol
def compute_follow(symbol):
if follow[symbol]:
return follow[symbol]
if symbol == 'S':
follow[symbol].add('$') # Assuming $ is the end of input marker
return follow[symbol]
print("\nFOLLOW sets:")
for key, value in follow.items():
print(f"{key}: {value}")
Practical 9
Aim: Conversion of Infix to Postfix notation, Postfix to Infix notations
def infix_to_postfix(expression):
stack, output = [], []
for char in expression:
if is_operand(char): output.append(char)
elif char == '(': stack.append(char)
elif char == ')':
while stack[-1] != '(': output.append(stack.pop())
stack.pop()
else:
while stack and precedence(char) <= precedence(stack[-1]): output.append(stack.pop())
stack.append(char)
return ''.join(output + stack[::-1])
expression = "A+B*(C-D)"
print("Infix Expression:", expression)
print("Postfix Expression:", infix_to_postfix(expression))
b) Postfix to Infix notations
def precedence(op): return {'+': 1, '-': 1, '*': 2, '/': 2, '^': 3}.get(op, 0)
def is_operand(char): return char.isalnum()
def infix_to_postfix(expression):
stack, output = [], []
for char in expression:
if is_operand(char): output.append(char)
elif char == '(': stack.append(char)
elif char == ')':
while stack[-1] != '(': output.append(stack.pop())
stack.pop()
else:
while stack and precedence(char) <= precedence(stack[-1]): output.append(stack.pop())
stack.append(char)
return ''.join(output + stack[::-1])
expression = "A+B*(C-D)"
print("Infix Expression:", expression)
print("Postfix Expression:", infix_to_postfix(expression))
Practical 10
Aim: Generation of three address code and DAG for the given arithmetic expression
class ThreeAddressCode:
def __init__(self):
self.temp_count = 0
self.code = []
def new_temp(self):
self.temp_count += 1
return f't{self.temp_count}'
return output
return self.code
class DAGNode:
def __init__(self, value):
self.value = value
self.children = []
self.label = None
def __repr__(self):
return f"{self.value} (label: {self.label})"
class DAG:
def __init__(self):
self.nodes = []
while stack:
output.append(stack.pop())
return output
return stack[0]
# Generate TAC
tac_generator = ThreeAddressCode()
tac = tac_generator.generate_tac(expression)
print("Three Address Code:")
for line in tac:
print(line)
# Generate DAG
dag = DAG()
root = dag.create_dag(expression)
print("\nDirected Acyclic Graph:")
dag.display(root)