Files
Construction-of-Compilers/Project-02/main.py
Jan-Niclas Loosen 7ac8889a1d Finish refactoring
2025-11-20 19:19:52 +01:00

107 lines
3.0 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 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.")