Improve code maintainability

This commit is contained in:
Jan-Niclas Loosen
2025-12-07 23:12:35 +01:00
parent 6e9f0331ed
commit 88b8de363d
44 changed files with 45 additions and 58 deletions

View File

@@ -0,0 +1,26 @@
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_confirmation(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")])

View File

@@ -4,14 +4,17 @@ 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")
def render_ast_from_string(dot_string: str):
# Renders a diagram of the AST
def render_diagram(dot_string: str):
# Set DPI for PNG
os.environ["GV_FILE_DPI"] = "300"
@@ -27,6 +30,7 @@ def render_ast_from_string(dot_string: str):
plt.axis("off")
plt.show()
# Pretty prints the AST
def pretty_print(node, indent=0):
prefix = " " * indent
print(f"{prefix}{type(node).__name__}:")
@@ -47,6 +51,7 @@ def pretty_print(node, indent=0):
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")
@@ -54,69 +59,42 @@ def export_dot_file(dot_string: str, filename: str):
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"])
choice = cnsl.prompt_choice("\nSelect action:", ["Parse .tripla", "Exit"])
if choice == 1:
print("\nBye Bye.")
break
programs = __search_programs()
programs = cnsl.search_programs()
if not programs:
print("\nNo .tripla files found.")
continue
idx = __prompt_choice("\nSelect program to parse:", [p.name for p in programs])
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 __prompt_yesno("\nPretty-print AST?"):
if cnsl.prompt_confirmation("\nPretty-print AST?"):
print("")
pretty_print(ast)
# Export DOT
dot_str = ast.to_dot()
if __prompt_yesno("Export AST as .dot file?"):
if cnsl.prompt_confirmation("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)
cnsl = input(f"Filename [{default}]: ").strip()
if not cnsl:
cnsl = default
export_dot_file(dot_str, cnsl)
# Display AST diagram
if __prompt_yesno("Display AST diagram?"):
render_ast_from_string(dot_str)
if cnsl.prompt_confirmation("Display AST diagram?"):
render_diagram(dot_str)
print("Rendered AST diagram.")

View File

@@ -9,8 +9,8 @@ class EXPRESSION:
def copy():
return EXPRESSION()
# Returns a list of tuples (edge_name, child_expression)
def children(self):
"""Return a list of (name, childNode)."""
out = []
for key, value in self.__dict__.items():
if key == "pp":
@@ -23,6 +23,7 @@ class EXPRESSION:
out.append((f"{key}{i}", elem))
return out
# Export AST to dot format
def to_dot(self, visited=None, root=True):
if visited is None:
visited = set()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 252 KiB

View File

@@ -1,18 +0,0 @@
# This is a sample Python script for testing your TRIPLA parser.
# In PyCharm press Umschalt+F10 to execute it.
import triplayacc as yacc
import triplalex as lex
def test_parser(name):
source = "\n".join(open(name).readlines())
ast = yacc.parser.parse(source) # ,debug=True)
print("AST:")
print(ast)
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
test_parser('triplaprograms/complex.tripla')
# See PyCharm help at https://www.jetbrains.com/help/pycharm/