Files
Construction-of-Compilers/Project-02-03/main.py
2025-12-07 23:12:35 +01:00

101 lines
2.9 KiB
Python

import triplayacc as yacc
import triplalex as lex
import syntax
from pathlib import Path
from graphviz import Source
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import lib.console as cnsl
import os
import matplotlib
matplotlib.use("TkAgg")
# Renders a diagram of the AST
def render_diagram(dot_string: str):
# Set DPI for PNG
os.environ["GV_FILE_DPI"] = "300"
src = Source(dot_string, format="png", engine="dot")
png_path = src.render(cleanup=True)
img = mpimg.imread(png_path)
fig = plt.figure(figsize=(12, 12))
fig.canvas.manager.window.wm_title("TRIPLA AST Viewer")
plt.imshow(img)
plt.axis("off")
plt.show()
# Pretty prints the AST
def pretty_print(node, indent=0):
prefix = " " * indent
print(f"{prefix}{type(node).__name__}:")
for key, value in node.__dict__.items():
if isinstance(value, syntax.EXPRESSION):
pretty_print(value, indent + 4)
elif isinstance(value, list):
print(f"{prefix} {key}: [")
for element in value:
if isinstance(element, syntax.EXPRESSION):
pretty_print(element, indent + 4)
else:
print(" " * (indent + 4) + str(element))
print(f"{prefix} ]")
else:
print(f"{prefix} {key}: {value}")
# Exports the AST as a DOT file
def export_dot_file(dot_string: str, filename: str):
try:
Path(filename).write_text(dot_string, encoding="utf-8")
print(f"Saved DOT file as: {filename}")
except Exception as e:
print(f"Could not save DOT file: {e}")
if __name__ == "__main__":
print("\nTRIPLA Parser Tool")
while True:
choice = cnsl.prompt_choice("\nSelect action:", ["Parse .tripla", "Exit"])
if choice == 1:
print("\nBye Bye.")
break
programs = cnsl.search_programs()
if not programs:
print("\nNo .tripla files found.")
continue
idx = cnsl.prompt_choice("\nSelect program to parse:", [p.name for p in programs])
path = programs[idx]
source = path.read_text()
ast = yacc.parser.parse(source)
# Pretty print
if cnsl.prompt_confirmation("\nPretty-print AST?"):
print("")
pretty_print(ast)
# Export DOT
dot_str = ast.to_dot()
if cnsl.prompt_confirmation("Export AST as .dot file?"):
default = f"{path.stem}.dot"
cnsl = input(f"Filename [{default}]: ").strip()
if not cnsl:
cnsl = default
export_dot_file(dot_str, cnsl)
# Display AST diagram
if cnsl.prompt_confirmation("Display AST diagram?"):
render_diagram(dot_str)
print("Rendered AST diagram.")