Bitte schicken Sie Korrekturen, Verbesserungsvorschläge und weitere Fragen, die in den Kommentaren zu den Beispielen nicht behandelt werden an mich: nino@complang.tuwien.ac.at. Genauer erklärte Musterlösungen kommen Ihren Kollegen zugute und wir freuen uns immer über gute Ergebnisse.
Bestimmen Sie die First- und Follow-Mengen aller Nonterminale.
Nonterminal | First-Menge | Follow-Menge |
---|---|---|
DEF | {class,interface} | {$} |
CLASS | {class} | {$} |
INTERFACE | {interface} | {$} |
EXTENDS | {extends,![]() | {implements,"{"} |
IMPLEMENTS | {implements,![]() | {"{"} |
FIELDS | {field} | {"}"} |
Erzeugen Sie für das obige Programmstück Quadrupel-Code nach der Kontrollflußmethode. Ein INTEGER ist 4 Byte groß. Die Untergrenze aller Indexbereiche ist 0. Optimieren Sie den Code NICHT.
if i < 5 goto L1 goto IFFALSE L1: if j < 8 goto WBEGIN goto IFFALSE WBEGIN: t1 := i * 8 t2 := t1 + j t3 := t2 * 4 t4 := t3 + adr(a) t5 := @t4 if t5 < 12 goto WTRUE goto WFALSE WTRUE: t6 := i * 8 (* 1 *) t7 := t6 + j t8 := t7 * 4 t9 := t8 + adr(a) @t9 := k t10 := k * 4 t11 := t10 + adr(b) t12 := @t11 k := t12 t13 := k * 4 (* 2 *) t14 := t13 + adr(b) @t14 = 1 goto WBEGIN WFALSE: goto IFEND IFELSE: k := 0 IFEND: (* ENDE *)
k := b[k] b[k] := 1sondern diesem:
k1 := k k := b[k] b[k1] := 1Sie sehen also, daß "Optimierungen" dieser Art nicht nur nicht der vorgeschriebenen Vorgangsweise im Skriptum entsprechen, sondern auch die Semantik des erzeugten Codes ändern können.
Für a[i,j] wird die Formel im Skriptum zu (i*8+j)*4 + adr(a), da i1 = i, i2 = j, n2 = 8 und w = 4 ist.
a) (10%)
Geben Sie eine Reguläre Definition für Ausdrücke an, die folgendermaßen definiert sind: eine Ziffer n von 0 bis 5, gefolgt von höchstens n Großbuchstaben, falls n gerade (oder 0) ist und höchstens n Kleinbuchstaben, falls n ungerade ist (ohne Umlaute), das ganze beliebig oft wiederholt. Beispiel: 3ab4AAA002BB15. (0 ist hier die Ziffer Null, nicht Buchstabe O)
b) (15%)
Geben Sie eine Reguläre Definition für Bit-Ketten an, deren Länge ein Vielfaches von 8 ist (8, 16, 24 ...), mit gerader Parität in jedem 8-Bit-Block (gerade Anzahl von 1ern, oder nur 0en), an. Beispiel: 00010010 01110010 00001111.
K = [a-z]? G = [A-Z]? EXPR = ( 0 | 1 K | 2 G G | 3 K K K | 4 G G G G | 5 K K K K K ) +
U2 = 01 | 10 G2 = 00 | 11 U4 = U2 G2 | G2 U2 G4 = U2 U2 | G2 G2 B = U4 U4 | G4 G4 EXPR = ( B )+Oder auch
G4 = 0000 | 0011 | 0101 | 0110 | 1001 | 1010 | 1100 | 1111 U4 = 0001 | 0010 | 0100 | 0111 | 1000 | 1011 | 1101 | 1110 B = U4 U4 | G4 G4 EXPR = ( B )+Oder gar
B = 00000000 | 00000011 | 00000101 | ... EXPR = ( B )+... wobei alle Möglichkeiten aufgezählt werden (nicht empfehlenswert) oder eindeutig beschrieben werden (mit Erklärung, was da stehen sollte). Auch diese Lösung ist korrekt.
Folgende Grammatik beschreibt verschachtelte Flächen mit Position und Farbe (Grauton):
Die 4 Zahlen nach flaeche sind die Eckpunkte x1,y1,x2,y2 für die gilt: x2>=x1 und y2>=y1. Die Zahl nach grau gibt den Helligkeitswert an (Weiß = 1, Schwarz = 0). Die Flächen überschneiden sich nicht. Erweitern Sie die Grammatik zu einer attributierten Grammatik, die im Attribut grau von S den durchschnittlichen Helligkeitswert der gesamten Fläche berechnet (Summe aller Teilflächen multipliziert mit ihren Helligkeitswerten, dividiert durch die Gesamtfläche). Mit inum.val und rnum.val erhalten Sie die Zahlenwerte. Achten Sie darauf, daß Sie keine Bereiche doppelt zählen. Beispiel:
F -> schwarz { F.g := 0 } F -> weiss { F.g := 1 } F -> grau rnum { F.g := rnum.val }Hier werden die Helligkeitswerte initialisiert und nach oben im Attribut g weitergegeben.
FARBE -> F { FARBE.v := FARBE.s * F.g }Hier sind wir in einem Reckteck ohne Teilflächen. Wir benötigen also den Helligkeitswert (wird in F.g synthetisiert) und die Fläche des Rechtecks, die wir von FARBE bekommen werden und können nun einen Wert berechnen, der der Helligkeit dieser rechteckigen Fläche multipliziert mit ihrer Fläche entspricht. Alternativ dazu könnte man die Multiplikation auch in der nächsten Regel durchführen.
FLAECHE -> flaeche inum1 inum2 inum3 inum4 FARBE { FLAECHE.s := (inum2.val - inum1.val) * (inum4.val - inum3.val) FARBE.s := FLAECHE.s FLAECHE.v := FARBE.v }In dieser Regel wird die Fläche des angegebenen Rechtecks berechnet und zur nach unten weitergegeben, damit dort die Berechnung des Attributs v durchgeführt werden kann. Bisher funktioniert das nur für Rechtecke ohne enthaltene Teilflächen, wir müssen also noch die nachfolgende Regel für diesen Fall implementieren.
FARBE -> "(" F FLAECHEN ")" { FARBE.v := (FARBE.s - FLAECHEN.s) * F.g + FLAECHEN.v }Wir gehen hier davon aus, daß wir die Gesamtfläche der enthaltenen Teilflächen in FLAECHEN.s synthetisiert haben, sowie deren Helligkeitswerte gewichtet mit den Flächen (deren Größe) in FLAECHEN.v bekommen. Somit können wir den gewichteten Gesamt-Helligkeitswert für die umgebende Fläche und die enthaltenen Flächen berechnen. Dazu ziehen wir die Gesamtfläche der Teilflächen von der umgebenden Fläche ab, um keine Bereiche doppelt zu zählen.
FLAECHEN -> FLAECHE { FLAECHEN.s := FLAECHE.s; FLAECHEN.v := FLAECHE.v } FLAECHEN -> FLAECHEN2 FLAECHE { FLAECHEN.s := FLAECHEN2.s + FLAECHE.s FLAECHEN.v := FLAECHEN2.v + FLAECHE.v }Hier werden die Größen einer Liste von Teilflächen sowie deren gewichtete Helligkeitswerte aufsummiert.
Es fehlt nur mehr die endgültige Berechnung der durchschnittlichen Helligkeit der gesamten Fläche. Wir benötigen dazu die Gesamtfläche (das ist jene der auf der obersten Ebene definierten, also des umgebenden Rechtecks) sowie den gewichteten Helligkeitswert für diese Fläche.
S -> FLAECHE { S.grau := FLAECHE.v / FLAECHE.s }
Bei dieser Prüfung war die attributierte Grammatik anscheinend viel leichter als bisher, da fast alle Teilnehmer relativ gut damit zurecht kamen. Fehler gab es u.a. bei der Berechnung der Fläche und manchmal wurden Attribute nicht bei allen Produktionen fuer ein Nonterminal berechnet.