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 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) # Show AST graph if prompt_yesno("Display AST diagram?"): dot_str = ast.to_dot() render_ast_from_string(dot_str) print("Rendered AST diagram.")