class EXPRESSION: pp_count = 0 def __init__(self): self.pp = EXPRESSION.pp_count EXPRESSION.pp_count += 1 @staticmethod def copy(): return EXPRESSION() def children(self): """Return a list of (name, childNode).""" out = [] for key, value in self.__dict__.items(): if key == "pp": continue if isinstance(value, EXPRESSION): out.append((key, value)) elif isinstance(value, list): for i, elem in enumerate(value): if isinstance(elem, EXPRESSION): out.append((f"{key}{i}", elem)) return out def to_dot(self, visited=None, root=True): if visited is None: visited = set() # Prevent infinite recursion if id(self) in visited: return "" visited.add(id(self)) parts = [] # Add a header at the root node if root: parts.append("digraph AST {\n") # Append to label label = type(self).__name__ if hasattr(self, "operator"): label += f"({self.operator})" if hasattr(self, "name"): label += f"({self.name})" if hasattr(self, "value"): label += f"({self.value})" parts.append(f' node{self.pp} [label="{label}"];\n') # Draw edges for edge_name, child in self.children(): parts.append(f' node{self.pp} -> node{child.pp} [label="{edge_name}"];\n') parts.append(child.to_dot(visited, root=False)) # Add footer at the root node if root: parts.append("}\n") return "".join(parts) class LET(EXPRESSION): def __init__(self, decls, body): super().__init__() self.decl = decls self.body = body def __str__(self): return "let " + ", ".join(str(d) for d in self.decl) + " in " + str(self.body) class DECL(EXPRESSION): def __init__(self, f_name, params, body): super().__init__() self.f_name = f_name self.params = params self.body = body def __str__(self): return f"{self.f_name}({self.params}) {{ {self.body} }}" class CALL(EXPRESSION): def __init__(self, f_name, args): super().__init__() self.f_name = f_name self.arg = args def __str__(self): return self.f_name + "(" + ",".join(str(a) for a in self.arg) + ")" class ID(EXPRESSION): def __init__(self, name): super().__init__() self.name = name def __str__(self): return self.name class CONST(EXPRESSION): def __init__(self, value): super().__init__() self.value = value def __str__(self): return str(self.value) class AOP(EXPRESSION): def __init__(self, operator, arg1, arg2): super().__init__() self.operator = operator self.arg1 = arg1 self.arg2 = arg2 def __str__(self): return "(" + str(self.arg1) + " " + str(self.operator) + " " + str(self.arg2) + ")" class EQOP(EXPRESSION): def __init__(self, operator, arg1, arg2): super().__init__() self.operator = operator self.arg1 = arg1 self.arg2 = arg2 def __str__(self): return "(" + str(self.arg1) + " " + str(self.operator) + " " + str(self.arg2) + ")" class COMP(EXPRESSION): def __init__(self, operator, arg1, arg2): super().__init__() self.operator = operator self.arg1 = arg1 self.arg2 = arg2 def __str__(self): return "(" + str(self.arg1) + " " + str(self.operator) + " " + str(self.arg2) + ")" class LOP(EXPRESSION): def __init__(self, operator, arg1, arg2): super().__init__() self.operator = operator self.arg1 = arg1 self.arg2 = arg2 def __str__(self): return "(" + str(self.arg1) + " " + str(self.operator) + " " + str(self.arg2) + ")" class ASSIGN(EXPRESSION): def __init__(self, var, expr): super().__init__() self.var = var self.expr = expr def __str__(self): return self.var.name + " = " + str(self.expr) class SEQ(EXPRESSION): def __init__(self, exp1, exp2): super().__init__() self.exp1 = exp1 self.exp2 = exp2 def __str__(self): return str(self.exp1) + "; " + str(self.exp2) class IF(EXPRESSION): def __init__(self, cond, exp1, exp2): super().__init__() self.cond = cond self.exp1 = exp1 self.exp2 = exp2 def __str__(self): return "if (" + str(self.cond) + ") then { " + str(self.exp1) + " } else { " + str(self.exp2) + " }" class WHILE(EXPRESSION): def __init__(self, cond, body): super().__init__() self.cond = cond self.body = body def __str__(self): return "while (" + str(self.cond) + ") do { " + str(self.body) + " }"