Files
2025-02-06 20:33:26 +02:00

112 lines
3.7 KiB
Python

import string
class TreeNode:
def __init__(self, value, father=None):
self.value = value # Grammar symbol (terminal/nonterminal)
self.father = father # Parent node
self.sibling = None # Sibling node
self.children = [] # List of children for easy access
def add_child(self, child):
"""Adds a child to the current node."""
if self.children:
# Set sibling for the last child
self.children[-1].sibling = child
self.children.append(child)
def __str__(self):
"""String representation of the node."""
return self.value
class ParserOutput:
def __init__(self, terminal, nonterminal):
self.root = None # Root of the parse tree
self.terminal = terminal
self.nonterminal = nonterminal
def build_tree(self, production_sequence):
"""
Builds the parse tree from a sequence of productions.
:param production_sequence: List of (nonterminal, production) tuples
"""
if not production_sequence:
return None
stack = [] # Stack for constructing the tree
for nonterminal, production in production_sequence:
if not self.root:
# Create the root node
self.root = TreeNode(nonterminal)
stack.append(self.root)
current = stack.pop()
symbols = production.split()
for symbol in symbols:
child = TreeNode(symbol, current)
current.add_child(child)
if symbol in self.nonterminal: # Nonterminal
stack.append(child)
else:
# Create nodes based on production
current = stack.pop()
symbols = production.split()
for symbol in symbols:
child = TreeNode(symbol, current)
current.add_child(child)
if symbol in self.nonterminal: # Nonterminal
stack.append(child)
def transform_representation(self, node=None, level=0):
if node is None:
node = self.root
result = "-" * level + str(node) + "\n"
for child in node.children:
result += self.transform_representation(child, level + 1)
return result
def print_to_screen(self):
print(self.print_table())
def print_table(self):
"""
Prints a table representation of the parse tree.
"""
rows = []
index_map = {}
def traverse(node, index=1, parent_index=None):
current_index = len(rows)
index_map[node] = current_index
# Determine right sibling
sibling_index = None
if node.sibling:
sibling_index = len(rows) + 1 # Right sibling will be the next node added
rows.append((current_index, node.value, parent_index, sibling_index))
for child in node.children:
traverse(child, len(rows), current_index)
traverse(self.root)
# Print the table
s = ""
s += "+-------+-------+--------+---------------+" + "\n"
s += "| Index | Value | Parent | Right Sibling |" + "\n"
s += "+-------+-------+--------+---------------+" + "\n"
for index, value, parent, sibling in rows:
s += f"| {index:<3} | {value:<3} | {parent + 1 if parent is not None else '0':<4} | {sibling if sibling is not None else '0':<11} |" + "\n"
s += "+-------+-------+--------+---------------+" + "\n"
return s
def save_to_file(self, filename):
with open(filename, 'w') as file:
file.write(self.print_table())