Technische Universität München
Fakultät für Informatik
Prof. Dr. Helmut Seidl
Riitta Höllerer
Praktikum des Übersetzerbaus SS 2004:
Generierung von Benutzungsoberflächen
Aufgabenblatt 4
19. Mai 2004
Compilerbau-Werkzeuge: JFlex, CUP und classgen
Bisher haben wir eine Benutzungsoberfläche per Hand implementiert und
eine mit EMUGEN generiert. Auf den nächsten Arbeitsblättern befassen
wir uns mit den Techniken aus dem Übersetzerbau, die zur Erstellung
von EMUGEN-artigen Werkzeugen verwendet werden. Wir werden einige kleine
Compiler erstellen.
Als erstes erzeugen wir einen Compiler für einen Teil der
EMUGEN-Eingabesprache und erzeugen beispielhaft Java-Code. Wie Sie schon gesehen
haben, ist der wirkliche Code, den EMUGEN für eine eine Spezifikation erzeugt,
sehr umfangreich.
Bei der Erstellung des Compilers
kommen die Werkzeuge: Scannergenerator
JFlex, Parsergenerator
Cup
und das Werkzeug
classgen
zum Einsatz. Diese Werkzeuge sind in dem vorgegebenen
Werkzeugpaket für das Praktikum
CompilerConstructionKit
enthalten. Die einzelnen Werkzeuge sind in den Merkblättern 1-3 genauer
beschrieben.
6. Aufgabe (Scanner für EMUGEN)
In dieser Aufgabe wollen wir einen Scanner für einen kleinen Teil der EMUGEN-Eingabe
definieren. Vom Datenmodell nehmen wir nur die Tupel- und Listenproduktionen,
also Varianten- und Referenzproduktionen lassen wir weg. Als Basistypen verwenden wir
String und Integer und vom Java-Code-Teil behandeln wir nur
die Methoden- und Aktionsdefinitionen.
Schauen Sie zunächst unser Adressbuch-Beispiel (ohne Referenzen) an.
Welche Schlüsselwörter und Sonderzeichen kommen vor und was sind die Identifikatoren in diesem Beispiel?
-
Erstellen Sie dann eine Scanner-Spezifikation für unseren reduzierten Datenmodell-Teil der EMUGEN-Eingabe
und generieren Sie den Scanner mit JFlex. Erstellen Sie den Scanner im
standalone-Modus und testen Sie den Scanner mit einigen Bespielen.
Als Ausgabe soll der Scanner die erkannten Symbole ausdrucken.
- Erweitern Sie ihre Scannerspezifikation, so dass auch Java-Codeteile
für Methoden- und Aktionsdefinitionen erkannt werden können. Dabei kann der Text zwischen den Zeichen {: und :} so wie Kommentare behandelt werden, mit dem Unterschied, dass Kommentare gelesen und ignoriert werden und der Java-Code an den Parser weitergegeben wird, d.h. in dieser Aufgabe nur ausgedruckt wird (s. 4.3.2 Semantics, in JFlex Manual, Operator ~).
Als Ausgabe soll der Scanner die erkannten Symbole ausdrucken.
Geben Sie als Lösung der Aufgabe Ihre Scanner-Spezifikation, Ihren lauffähigen Scanner und einige Beispiele
als Aufgabe6.jar-Datei sowie Ihre Scanner-Spezifikation, die Beispiele und Ausgaben als eine Aufgabe6.html-Datei ab.
Hinweise zum JFlex sind im Merkblatt 1 zusammengestellt.
Durch die Installierung des Werkzeugpakets für das Praktikum sind die Pfade für
JFlex schon richtig gesetzt, so dass Sie aus der Eingabe
emugen.jflex
den Scanner durch
jflex emugen.jflex
javac Lexer.java
java Lexer adressbuch.emu
generieren und mit dem Beispiel adressbuch.emu testen können.
7. Aufgabe (Scanner und Parser für EMUGEN)
In dieser Aufgabe realisieren wir den Scanner und Parser für den
obigen Teil der EMUGEN-Eingabe.
Zwei Arbeitsschritte sind notwendig:
- In der Aufgabe 6 haben wir für unsere EMUGEN-Eingabesprache
einen Scanner erzeugt, der allein arbeitet und die erkannten Symbole ausdruckt.
Nun benötigen wir einen Scanner, der mit einem Parser zusammenarbeitet, d.h.
die erkannten Symbole in geeigneter Form dem Parser übergibt.
Parser, die mit CUP generiert werden, erwarten diese Information
als Objekte vom Typ Symbol. (Hier zu finden:
Symbol.java)
Ändern Sie Ihre Scannerspezifikation, so dass der Scanner Objekte vom
Typ Symbol liefert. (Lassen Sie die Druckausgaben drin.)
- Erstellen Sie eine Parser-Spezifikation für unsere EMUGEN-Eingabesprache.
Ergänzen sie die CUP-Eingabe um einen Testrahmen (als Main-Methode der
generierten Parserklasse), das eine in der Kommandozeile übergebene Datei
öffnet und ihren Inhalt parst und eine geeignete Meldung abgibt. Z. B. so:
import java_cup.runtime.Symbol;
parser code {:
public static void main(String argv[]) {
try {
Lexer l = new Lexer(new java.io.FileReader(argv[0]));
Parser p = new Parser(l);
Object result = p.parse().value;
System.out.println("Parserlauf fertig, Eingabe korrekt!");
}
catch (Exception e) {
e.printStackTrace();
}
}
:};
Hinweise zu CUP sind im Merkblatt 2 zusammengefaßt.
Geben Sie als Lösung der Aufgabe Ihre Scanner-und Parser-Spezifikation
(emugen.jflex, emugen.cup), Ihren lauffähigen Compiler und einige Beispiele
als Aufgabe7.jar-Datei sowie Ihre Scanner- und Parser-Spezifikation, die Beispiele und Ausgaben als eine Aufgabe7.html-Datei ab.
Der in der Besprechung behandelte Compiler ist hier:
demo.zip
Hinweise:
-
Sind die Quell-Dateien des Ihres Compilers emugen.jflex und
emugen.cup und die Eingabe
adressbuch.emu
im aktuellen Verzeichnis
und das CompilerConstructionKit installiert
und somit CCK_HOME besetzt, kann der Compiler
mit folgenden Kommandos erstellt und getestet
werden:
jflex emugen.jflex
cup -interface -expect 3 -parser Parser emugen.cup
javac -classpath .:$CCK_HOME/lib/java-cup-10k-b2-runtime-TUM.jar *.java
java -classpath .:$CCK_HOME/lib/java-cup-10k-b2-runtime-TUM.jar Parser adressbuch.emu
- Für die Erstellung und Testen des Compilers sowie das Archiv erstellen
können Sie auch das vorgegebene
ant-file:
build.xml
verwenden.
Abgabetermin: Dienstag, 25. Mai 15:00