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())