PI5003 Programmiersprachen: Konzepte und Realisation (PKR) | Hochschule: THM (Technische Hochschule Mittelhessen) | Jahr: 2026
Dieses Projekt ist eine TypeScript Version vom Nimic, welches eine free-form macro language beschreibt und Befehle in die Tiefe parst.
- Aufgabenstellung: das Rewriting System Nimic in TypeScript umzusetzen und Namespaces einführen.
- Herausforderungen: Implementierung anhand des BlogPosts und Haskell-Codes
- Eine Webseite/Web-App, mit dem Nutzer*innen Macro Befehle sowie Namespaces erstellen können und daraus Regeln speichern, um Befehle schrittweise zu reduzieren.
Die Anwendung folgt einer klaren Trennung von Parsing, Logik und UI:
- Parsing (
parser/): Konvertiert den Code in strukturierte abstrakte Syntaxbäume (ASTs) bzw. symbolische Terme. - Logik (
engine/):macro-logics.ts: Verwaltet Muster und deren Ersetzungsregeln.reduction.ts: Implementiert die Reduktionsschritte (Step-Funktion) basierend auf Pattern-Matching. Unterstützt Definitionen von Namespaces, um Namenskonflikte zu vermeiden.
- Typen (
types/): Stark typisierte Datenstrukturen für eine saubere Datenhaltung zwischen den Parser und Engine. - UI (
components/undhooks/): Binden die Engine an die React-Oberfläche an, um den schrittweisen Evaluierungsprozess visuell darzustellen.
Integration-Tests im Ordner tests, um das Zusammenspiel zwischen den Funktionen zu testen
macros.test.tsprüft, wie Macros durch verschiedene Funktionen geparst werdennamespaces.test.tsprüft, wie Namespaces mit Macros evaluiert werdenmocks.tsenthält die benötigten Mockdaten für beide Testdateien Tests ausführen:
cd app
npm run test
- Mehrere Befehle gleichzeitig zu speichern -> Lösung durch Hilfsmethoden
- Code wie BlogPost zu formatieren -> blieb offen
- Vertiefung im Bereich Compiler-Design sowie Traversierung von Syntaxbäumen
- Framework Shadcn UI kennengelernt, welches Zeit bei Komponentenerstellung deutlich reduziert
- Framework Parsimmon für einfaches Parsing
cd app
npm install
cd app
npm run build
cd app
npm run preview
Anmerkung: Step 2 muss vor Step 3 laufen, immer wenn Quellcode verändert wird.
-
Nacdem das Projekt erfolgreich gestartet wurde, kann das URL aus dem Terminal im Browser geöffnet werden.
-
Beispiele: Im Input-Feld folgende Befehle eingeben und dann mit dem
Submit-Button speichern und demStep-Button die Befehle reduzieren, bis zum Ende:
; Drop the top element (discard #x, keep #y and #x)
(macro (drop #x #y #z) -> #y #z)
; Swap the top three elements (#x, #y and #z)
(macro (swap #x #y #z) -> #z #y #x)
; Rotate elements (#x, #y, #z -> #y, #z, #x)
(macro (rot #x #y #z) -> #y #z #x)
Befehle auch mit den Submit- und Step-Buttons evaluieren:
drop 1 2 3
Hierbei ist das Ergebnis (2 3)
swap 1 2 3
Hierbei ist das Ergebnis (3 2 1)
rot 1 2 3
Hierbei ist das Ergebnis (2 3 1)
Mit Namespaces können benutzerdefinierten Makros in isolierten Bereichen organisieren, anstatt die globale Umgebung zu überladen.
- Beispiele:
namespace MathA
(macro (op #x) -> (add #x 1))
- Ein weiteres Namespace einfügen:
namespace MathB
(macro (op #x) -> (mul #x 2))
Macros einfügen, um das Matching zu evaluieren:
; match #val of ( #pat -> #res ; #rest )
----------
if (judge #val #pat) then #res else (match #val of #rest)
; match #val of ( #pat -> #res )
----------
if (judge #val #pat) then #res else (failed match)
Macro-Defintion einfügen, um Namespaces zu evaluieren:
(macro
(ns-run #ns . #op (#x)) ->
(match #ns of (
MathA -> (match #op of (
op -> (add #x 1) ;
#other -> (failed match)
)) ;
MathB -> (match #op of (
op -> (mul #x 2) ;
#other -> (failed match)
)) ;
#other -> (failed match)
)))
Namespaces evaluieren:
ns-run MathA . op (5)
ns-run MathB . op (2)
Bei den ns-run MathA . op (5) hört das Programm bei (add 5 1) und bei ns-run MathB . op (2) endet das Program bei (mull 2 1).
Alternativ können namespaces frei ohne Macro Regeln verwendet werden, jedoch müssen dann die Variablen innerhalb der Namespaces eindeutig sein:
namespace MathA
(macro (opA #x) -> (add #x 1))
namespace MathB
(macro (opB #x) -> (mul #x 2))
Evalution mit den Befehlen:
opA (5)
opB (2)
cd app
npm run docs
npm run docs:serve
Macro Befehle erstellen
Namespaces einführen und evaluieren:

Namespaces mit Macros evaluieren:

1-2, da die meisten Anforderungen erfüllt sind.



