Files
Construction-of-Compilers/Project-02/syntax.py
2025-11-20 15:10:38 +01:00

191 lines
5.7 KiB
Python

# (c) Stephan Diehl, University of Trier, Germany, 2025
class EXPRESSION:
pp_count = 0
def __init__(self):
self.pp = EXPRESSION.pp_count
EXPRESSION.pp_count += 1
@staticmethod
def copy():
return EXPRESSION()
def allNodes(self):
ret = [self]
for node in (self.__getattribute__(a) for a in self.__dict__.keys()):
if isinstance(node, EXPRESSION):
ret += node.allNodes()
if isinstance(node, list):
for n in node:
if isinstance(n, EXPRESSION):
ret += n.allNodes()
return ret
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, out):
# node label is class name or class name + value
label = type(self).__name__
if hasattr(self, "operator"): # AOP/EQOP/COMP/LOP
label += f"({self.operator})"
if hasattr(self, "name"): # ID
label += f"({self.name})"
if hasattr(self, "value"): # CONST
label += f"({self.value})"
out.write(f' node{self.pp} [label="{label}"];\n')
for (edge_name, child) in self.children():
out.write(f' node{self.pp} -> node{child.pp} [label="{edge_name}"];\n')
child.to_dot(out)
class LET(EXPRESSION):
def __init__(self, declarations, body):
super().__init__()
self.declarations = declarations
self.body = body
def __str__(self):
return "let " + ", ".join(str(d) for d in self.declarations) + " 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}(" + ",".join(str(p) for p in self.params) + ") { " + str(self.body) + " }"
class CALL(EXPRESSION):
def __init__(self, f_name, arguments):
super().__init__()
self.f_name = f_name
self.arguments = arguments
def __str__(self):
return self.f_name + "(" + ",".join(str(a) for a in self.arguments) + ")"
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, variable, expression):
super().__init__()
self.variable = variable
self.expression = expression
def __str__(self):
return self.variable.name + " = " + str(self.expression)
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, condition, exp1, exp2):
super().__init__()
self.condition = condition
self.exp1 = exp1
self.exp2 = exp2
def __str__(self):
return "if (" + str(self.condition) + ") then { " + str(self.exp1) + " } else { " + str(self.exp2) + " }"
class WHILE(EXPRESSION):
def __init__(self, condition, body):
super().__init__()
self.condition = condition
self.body = body
def __str__(self):
return "while (" + str(self.condition) + ") do { " + str(self.body) + " }"
def pretty_print(clas, indent=0):
print(' ' * indent + type(clas).__name__ + ':')
indent += 4
for k, v in clas.__dict__.items():
if isinstance(v, EXPRESSION):
pretty_print(v, indent)
else:
print(' ' * indent + f"{k}: {v}")
def export_dot(ast, filename="ast.dot"):
with open(filename, "w") as f:
f.write("digraph AST {\n")
f.write(" node [shape=box];\n")
ast.to_dot(f)
f.write("}\n")