Files
Jan-Niclas Loosen ee0e5b0b4c Refactor export
2025-11-22 18:37:11 +01:00

123 lines
3.5 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 os
import matplotlib
matplotlib.use("TkAgg")
def render_ast_from_string(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()
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}")
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}")
def __prompt_choice(prompt: str, options: list) -> int:
print(prompt)
for i, opt in enumerate(options, 1):
print(f" {i}. {opt}")
while True:
try:
s = input(f"Enter choice (1-{len(options)}): ").strip()
idx = int(s) - 1
if 0 <= idx < len(options):
return idx
except Exception:
pass
print(f"Invalid. Enter a number between 1-{len(options)}.")
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")
def __search_programs():
base = Path(__file__).parent / "triplaprograms"
if not base.exists():
return []
return sorted([f for f in base.glob("*.tripla")])
if __name__ == "__main__":
print("\nTRIPLA Parser Tool")
while True:
choice = __prompt_choice("\nSelect action:", ["Parse .tripla", "Exit"])
if choice == 1:
print("\nBye Bye.")
break
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]
source = path.read_text()
ast = yacc.parser.parse(source)
# Pretty print
if __prompt_yesno("\nPretty-print AST?"):
print("")
pretty_print(ast)
# Export DOT
dot_str = ast.to_dot()
if __prompt_yesno("Export AST as .dot file?"):
default = f"{path.stem}.dot"
out = input(f"Filename [{default}]: ").strip()
if not out:
out = default
export_dot_file(dot_str, out)
# Display AST diagram
if __prompt_yesno("Display AST diagram?"):
render_ast_from_string(dot_str)
print("Rendered AST diagram.")