Technische Universität München
Fakultät für Informatik
Prof. Dr. Helmut Seidl
Riitta Höllerer


Praktikum des Übersetzerbaus WS 2004:

Generierung von Benutzungsoberflächen


Aufgabenblatt 7

9. Juni 2004

13. Aufgabe  (EmitcodeVisitor für den EMUGEN-Compiler)

In dieser Aufgabe realisieren wir einen kleinen Teil der Codeerzeugung für den EMUGEN-Compiler, für den wir die vereinfachte Identifikation in der Aufgabe 11 realisiert haben.

Schauen Sie zuerst, was Emugen für folgendes Beispiel generiert.

Adressbuch::= Person*: Privat Geschaeftlich

Geschaeftlich::= Person*

Person::= String:Nachname
          String:Vorname
          String:Telefon
Es werden Klassen für das Datenmodell (z.B. Adressbuch.java ), für die Darstellung des Modells ( z.B. AdressbuchPanel.java ), Klassen für die Aktionen (z.B. AdressbuchOeffnenAction.java ), ReferenceManager.java und die Klassen für die Visitorschnittstelle generiert.

Wir erzeugen nur Datenmodellklassen für Tupelproduktionen und das auch fragmentarisch. Etwa folgendes als Adressbuch.java :

public class Adressbuch extends emu_runtime.datamodel.TupelInteractionData{

private PersonList Privat;
private Geschaeftlich Geschaeftlich;

public Adressbuch () {
Privat = new PersonList();
Geschaeftlich = new Geschaeftlich();
}

public PersonList getPrivat() {
return Privat;
}

public Geschaeftlich getGeschaeftlich() {
return Geschaeftlich;
}
}
Es gibt eine Besonderheit bei dieser Codeerzeugung. Für die Komponenten auf der rechten Seite einer Tupelproduktion müssen Sie viele Codeteile erzeugen. Eine Deklaration, etwas in den Konstruktor, die get... (und set...)-Methoden usw. So haben Sie eigentlich mehrere Ausgabeströme. Wie realisiert man sowas?

Eine Lösung ist, den Code erst in einzelne StringBuffer zu schreiben und erst, wenn man mit der rechten Seite der Tupelproduktion fertig ist, auszugeben. Dafür definiert man im EmitcodeVisitor mehrere StringBuffer: z.B. für den Member-Teil, für den Konstruktorkopf und Konstruktorrumpf und für die Methoden.

Anbei ist die Klasse OutFile.java aus den EMUGEN Sourcen, die genau das zu Verfügung stellt. In Ihrem EmitcodeVisitor könnten Sie etwa folgendes schreiben:


package node;
import java.io.*;

public class EmitcodeVisitor extends VisitorAdaptor {

private OutFile file;

private void makeSections() {
  file.addSection("decl");
  file.addSection("members");
  file.addSection("condecl");
  file.addSection("conbody");
  file.addSection("methods");
  file.addSection("end");
  }

  ...

public void visit(Prod prod) {
  try {
  private String className=prod.getLhs();
  file = new OutFile( new File(className)+".java") );
  makeSections();
  String extending = "extends emu_runtime.datamodel.TupelInteractionData";
  printStandard(extending);
  production.childrenAccept(this);
  printEnd();
  System.out.println("Writing class "+className);
  file.emit();
  }
  catch (IOException e) {
  System.err.println("Error writing "+className+" :");
  e.printStackTrace();
  System.exit(1);
  }
}
Im printStandard würden Sie die Buffer initialisieren (den Anfang für die Klasse, Anfang für den Konstruktor usw.), im printEnd() abschließen (z.B. schliessende Klammern hinzufügen); dazwischen werden in den Kinderknoten die Buffer weiter ausgefüllt.

Erzänzen Sie Ihren Emugen-Compiler um den EmitcodeVisitor, in dem Sie obigen Code erzeugen.

Geben Sie als Lösung der Aufgabe

14. Aufgabe  (Oberfläche für EMUGEN)

In dieser Aufgabe erweitern wir die Aufgabe 5 von Aufgabenblatt 3 und realisieren nun eine Aktion, durch die für das eingegebene Beispiel *.emu -Text ausgegeben wird.

Gehen Sie von der vorgegebenen Eingabe aufg14.emu aufg14.emu aus und implementieren Sie die Aktion Generate.

Hinweis: Schauen Sie die generierten Klassen an und orientieren Sie sich daran, wie die toString()-Methoden realisiert sind. Dann definieren Sie in der Eingabe aufg14.emu für die einzelnen Knotentypen eine Methode, z.B. für EMUMetatype definiert als

EMUMetatype::= TupelProduction
             | ListProduction
folgende Methode:
methods of EMUMetatype {:
  public String getString() {
    switch(acttype) {
      case TUPELPRODUCTION:
        return TupelProduction.getString();
      case LISTPRODUCTION:
         return ListProduction .getString();
     }
     return null;
  }
:}
Geben Sie als Lösung der Aufgabe

Abgabetermin: Mittwoch, 16. Juni 2004, 9:00