class Node: def _pos_str(self): start_pos_str = "?" if self.pos is not None: start_pos_str = f"{self.pos[0]}:{self.pos[1]}" end_pos_str = "?" if self.end_pos is not None: end_pos_str = f"{self.end_pos[0]}:{self.end_pos[1]}" return f" # {start_pos_str}-{end_pos_str}" def _make_str(self, indent=None, positions=False): if indent is not None: s = " " * indent else: s = "" s += self.__class__.__name__ s += "(" if self.value: s += repr(self.value) if self.children: s += ", " if positions and self.children: s += self._pos_str() for i, child in enumerate(self.children): if indent is not None: s += "\n" s += child._make_str( indent=None if indent is None else indent + 1, positions=positions ) if i < len(self.children) - 1: s += ", " s += ")" if positions and not self.children: s += self._pos_str() return s def pretty(self, positions=False): return self._make_str(indent=0, positions=positions) def accept(self, visitor): raise NotImplementedError() class Script(Node): def __init__(self, statements): self.statements = statements def accept(self, visitor): return visitor.visit_script(self) class ProcDef(Node): def __init__(self, name, args, body): self.name = name self.args = args self.body = body def accept(self, visitor): return visitor.visit_proc(self) class SetStmt(Node): def __init__(self, varname, value): self.varname = varname self.value = value def accept(self, visitor): return visitor.visit_set(self) class Namespace(Node): def __init__(self, name, body): self.name = name self.body = body def accept(self, visitor): return visitor.visit_namespace(self) class CommandSubst(Node): def __init__(self, name, args): self.name = name self.args = args def accept(self, visitor): return visitor.visit_command(self)