Finish refactoring

This commit is contained in:
Jan-Niclas Loosen
2025-11-20 19:19:52 +01:00
parent 346c3c8ffd
commit 7ac8889a1d
3 changed files with 92 additions and 101 deletions

View File

@@ -6,52 +6,47 @@ from pathlib import Path
from graphviz import Source
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import os
import matplotlib
matplotlib.use("TkAgg")
# ------------------------------------------------------------
# Utility: rendering DOT → PNG → matplotlib
# ------------------------------------------------------------
def render_ast_from_string(dot_string: str):
# Set DPI for PNG
os.environ["GV_FILE_DPI"] = "300"
def render_ast(dotfile: str, outfile: str = "ast.png"):
with open(dotfile) as f:
dot_data = f.read()
src = Source(dot_string, format="png", engine="dot")
png_path = src.render(cleanup=True)
src = Source(dot_data)
src.render(outfile.replace(".png", ""), format="png", cleanup=True)
img = mpimg.imread(png_path)
fig = plt.figure(figsize=(12, 12))
fig.canvas.manager.window.wm_title("TRIPLA AST Viewer")
# Show via matplotlib only
img = mpimg.imread(outfile)
plt.imshow(img)
plt.axis("off")
plt.show()
# ------------------------------------------------------------
# Pretty print AST
# ------------------------------------------------------------
def pretty_print(node, indent=0):
prefix = " " * indent
print(f"{prefix}{type(node).__name__}")
print(f"{prefix}{type(node).__name__}:")
for key, value in node.__dict__.items():
if key == "pp":
continue
if isinstance(value, list):
print(f"{prefix} {key}: [")
for v in value:
if isinstance(v, syntax.EXPRESSION):
pretty_print(v, indent + 4)
else:
print(" " * (indent + 4) + str(v))
print(f"{prefix} ]")
elif isinstance(value, syntax.EXPRESSION):
print(f"{prefix} {key}:")
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}")
# Ask for a choice input
def prompt_choice(prompt: str, options: list) -> int:
print(prompt)
for i, opt in enumerate(options, 1):
@@ -65,21 +60,14 @@ def prompt_choice(prompt: str, options: list) -> int:
return idx
except Exception:
pass
print(f"Invalid. Enter a number between 1 and {len(options)}.")
print(f"Invalid. Enter a number between 1-{len(options)}.")
# Ask for a yes/no input
def prompt_yesno(question: str, default="y"):
s = input(f"{question} (y/n) [{default}]: ").strip().lower()
if not s:
s = default
return s.startswith("y")
# Ask for a value input
def prompt_value(prompt: str, default: str):
s = input(f"{prompt} [{default}]: ").strip()
return s if s else default
# Search for known .tripla files
def search_programs():
base = Path(__file__).parent / "triplaprograms"
if not base.exists():
@@ -90,38 +78,30 @@ if __name__ == "__main__":
print("\nTRIPLA Parser Tool")
while True:
choice = prompt_choice("\nSelect action:",["Parse TRIPLA program", "Exit"])
choice = prompt_choice("\nSelect action:", ["Parse .tripla", "Exit"])
if choice == 1:
print("\nBye.")
print("\nBye Bye.")
break
else:
programs = search_programs()
if not programs:
print("\nNo .tripla files found.")
continue
programs = search_programs()
if not programs:
print("\nNo .tripla files found.")
continue
idx = prompt_choice("\nSelect program to parse:", [p.name for p in programs])
path = programs[idx]
idx = prompt_choice("\nSelect program to parse:", [p.name for p in programs])
path = programs[idx]
source = path.read_text()
ast = yacc.parser.parse(source)
source = path.read_text()
ast = yacc.parser.parse(source)
# Pretty print
if prompt_yesno("\nPretty-print AST?"):
print("")
pretty_print(ast)
# Pretty print
if prompt_yesno("\nPretty-print AST?"):
print("")
pretty_print(ast)
# Export DOT
dot_name = prompt_value("\nSave DOT as", "ast.dot")
if not dot_name.endswith(".dot"):
dot_name += ".dot"
ast.to_dot(ast, dot_name)
# Show graph
if prompt_yesno("Display AST diagram?"):
render_ast(dot_name, "ast.png")
print("Rendered AST to ast.png")
print("\nDone.")
# Show AST graph
if prompt_yesno("Display AST diagram?"):
dot_str = ast.to_dot()
render_ast_from_string(dot_str)
print("Rendered AST diagram.")