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?

  1. 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.

  2. 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:
  1. 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.)

  2. 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:

Abgabetermin: Dienstag, 25. Mai 15:00