Ein vollstaendiger Compiler, der Pascal-Quellcode ueber mehrere Stufen in ausfuehrbaren JVM-Bytecode uebersetzt.
Der Compiler durchlaeuft die klassischen Phasen eines Compilerbaus:
- Lexing & Parsing — Eine ANTLR-4-Grammatik (
Pascal.g4) zerlegt den Pascal-Quellcode in einen Parse Tree - Semantische Analyse — Ein
TypeCheckVisitorprueft Typen, Scopes und Korrektheit des Programms - Codeerzeugung — Ein
CodeGenVisitortraversiert den AST und erzeugt Jasmin-Assembler (ein textuelles Format fuer JVM-Bytecode) - Assemblierung — Der Jasmin-Assembler uebersetzt den erzeugten Code in
.class-Dateien, die direkt auf der JVM ausfuehrbar sind
Compiler
┌─────────────┐ ┌──────────────────────────────────────────────┐ ┌────────────┐
│ │ │ │ │ │
│ Pascal │───>│ ANTLR 4 Semantische Code- Jasmin │───>│ JVM │
│ Quellcode │ │ Parser -> Analyse -> erzeugung -> Asm │ │ Bytecode │
│ (.pas) │ │ │ │ (.class) │
│ │ │ │ │ │
└─────────────┘ └──────────────────────────────────────────────┘ └────────────┘
Darueber hinaus implementiert der Compiler zwei Analyseverfahren aus dem Bereich der Compiler-Optimierung:
- Liveness-Analyse — Datenflussanalyse auf einem Kontrollflussgraphen (CFG), die ermittelt, wie viele Register ein Programm minimal benoetigt
- Konstantenpropagation — Statische Analyse, die erkennt, welche Variablen zur Compile-Zeit konstante Werte tragen
| Kategorie | Elemente |
|---|---|
| Datentypen | integer, double, string, boolean |
| Arithmetik | +, -, *, /, mod |
| Vergleich | =, <>, <, >, <=, >= |
| Logik | and, or, not |
| Kontrollfluss | if/then/else, while/do, begin/end |
| Funktionen & Prozeduren | Parameter, Rekursion, lokale & globale Variablen |
| Ausgabe | writeln(ausdruck) |
program Fibonacci;
function Fib(n: integer): integer;
begin
if n > 0 then
if n <= 2 then
Fib := 1
else
Fib := Fib(n-1) + Fib(n-2)
else
Fib := 0
end;
begin
writeln(Fib(10))
end../gradlew run --args="-compile Fibonacci.pas"
java -cp output/classes Fibonacci
# Ausgabe: 55| Komponente | Technologie |
|---|---|
| Sprache | Java |
| Build-System | Gradle (Kotlin DSL) |
| Parser-Generator | ANTLR 4.13.2 |
| Assembler | Jasmin (mitgeliefert) |
| Test-Framework | JUnit 5 |
| Zielplattform | JVM-Bytecode |
- Java JDK 8 oder hoeher
- Kein weiteres Setup noetig — Gradle Wrapper und Jasmin-Assembler sind im Repository enthalten
# Linux / macOS
./gradlew build
# Windows
gradlew.bat build# Kompilieren (erzeugt .j und .class Dateien im output/ Verzeichnis)
./gradlew run --args="-compile MeinProgramm.pas"
# Erzeugten Bytecode ausfuehren
java -cp output/classes MeinProgramm# Liveness-Analyse: Minimale Registeranzahl bestimmen
./gradlew run --args="-liveness MeinProgramm.pas"
# Konstantenpropagation: Konstantenzustand pro Zeile ausgeben
./gradlew run --args="-constants MeinProgramm.pas"
# Debug-Modus: Ausfuehrliche Ausgabe waehrend der Kompilierung
./gradlew run --args="-debug -compile MeinProgramm.pas"# Alle Tests
./gradlew test
# Einzelne Testklasse
./gradlew test --tests "com.wiegand.luca.ArithmeticTest"src/
├── main/
│ ├── antlr/
│ │ └── Pascal.g4 # ANTLR-Grammatik
│ └── java/com/wiegand/luca/
│ ├── StupsCompiler.java # Haupteinstiegspunkt (CLI)
│ ├── TypeCheckVisitor.java # Semantische Analyse & Typueberpruefung
│ ├── CodeGenVisitor.java # Codeerzeugung (AST -> Jasmin)
│ ├── SymbolTable.java # Symboltabelle mit Scope-Verwaltung
│ ├── JasminEmitter.java # Jasmin-Instruktions-Ausgabe
│ ├── LocalVarTable.java # JVM-Variablen-Slot-Verwaltung
│ ├── ConstantPropagationAnalyzer.java
│ └── cfg/ # Kontrollflussgraph-Analyse
│ ├── Instruction.java # IR-Instruktionen
│ ├── BasicBlock.java # CFG-Grundbloecke
│ ├── ControlFlowGraph.java
│ └── LivenessAnalyzer.java # Liveness-Analyse & Registerallokation
└── test/
└── java/com/wiegand/luca/ # JUnit-5-Tests
libs/
└── jasmin.jar # Jasmin-Assembler (mitgeliefert)
output/
├── jasmin/ # Erzeugte .j Dateien
└── classes/ # Erzeugte .class Dateien