Semantik =
Beispiele:
Hilfsmittel: Attributgrammatiken
operational, axiomatisch, denotational
A : Knotenmenge→Attributwerte
eine Menge (Relation) von erlaubten Attribut-Tupeln
(A(X0), A(X1),…, A(Xn))
für Knoten X0
ein Ableitungsbaum mit Annotationen ist
Plan:
Ursprung:
Donald Knuth: Semantics of Context-Free Languages,
(Math. Systems Theory 2, 1968)
technische Schwierigkeit: Attributwerte
effizient bestimmen. (beachte: (zirkuläre) Abhängigkeiten)
(Band 3: Sortieren und Suchen)
(Leslie Lamport: LATEX)
http://www-cs-faculty.stanford.edu/~uno/
hängt nur von Attributwerten in Kindknoten ab
hängt nur von Attributwerten in Elternknoten
und (linken) Geschwisterknoten ab
Wenn Abhängigkeiten bekannt sind,
kann man Attributwerte durch Werkzeuge bestimmen lassen.
abstrakter Syntaxbaum kann als
synthetisiertes Attribut konstruiert werden.
...bei geschachtelten Funktionsaufrufen
Beispiel
(Curry-Howard-Isomorphie)
SableCC is a parser generator for building compilers, interpreters ...,
strictly-typed abstract syntax trees and tree walkers
Benutzung:
(dafür muß
Multiplikation,
Subtraktion,
Klammern,
Potenzen
Kommentar: in Java fehlen: algebraische Datentypen,
Pattern Matching, Funktionen höherer Ordnung.
Deswegen muß SableCC das simulieren -- das sieht
nicht schön aus. Die „richtige`` Lösung
sehen Sie später im Compilerbau.
Abstrakter Syntaxbaum, Interpreter:
http://www.imn.htwk-leipzig.de/~waldmann/edu/ws11/cb/folien/main/node12.html,
Kombinator-Parser:
http://www.imn.htwk-leipzig.de/~waldmann/edu/ws11/cb/folien/main/node70.html
beschreibt Wirkung von Anweisungen
durch Änderung des Programmzustandes
ordnet jedem (Teil-)Programm einen Wert zu,
Bsp: eine Funktion (höherer Ordnung).
Beweis von Programmeigenschaften durch
Term-Umformungen
enthält Schlußregeln,
um Aussagen über Programme zu beweisen
arithmetischer Ausdruck
⇒
3*x + 1
Beispiele: Java-Bytecode (javac, javap),
Bemerkung: soweit scheint alles trivial--interessant
wird es bei Teilausdrücken mit Nebenwirkungen,
Bsp.
Schleife
wird übersetzt in Sprungbefehle
Aufgabe: übersetze
Beispiele
Vorteile denotationaler Semantik:
Programmiersprache ist Beschreibungssprache
beschreibt eine Zahl
beschreibt eine Funktion (von Variablenbelegung nach Wahrheitswert)
beschreibt eine formale Sprache
beschreibt eine Funktion (?)
Unterprogramme definiert durch Gleichungssysteme.
Sind diese immer lösbar? (überhaupt? eindeutig?)
Geben Sie geschlossenen arithmetischen Ausdruck für:
Notation für Aussagen über Programmzustände:
Beispiel:
Gültigkeit solcher Aussagen kann man
Bertrand Meyer, http://www.eiffel.com/
Kalkül: für jede Anweisung ein Axiom,
das die schwächste Vorbedingung
(weakest precondition) beschreibt.
Beispiele
Beispiel:
Schreiben Sie eine Java-Methode, deren Kompilation
genau diesen Bytecode erzeugt:
a)
b)
Ergänze das Programm:
S→mSS
S→e
Terminale:
A(e) = 1, A(m) = 0
korrekt bezüglich einer Attributgrammatik,
wenn
unwesentlich sind z. B. die Knoten,
die zu Hilfsvariablen der Grammatik gehören.
E -> E + P ; E.abs = new Plus(E.abs, P.abs)
E -> P ; E.abs = P.abs
String x = "foo"; String y = "bar";
Boolean.toString (x.length() < y.length()));
linke-seite { -> attribut-typ }
= { zweig-name } rechte-seite { -> attribut-wert }
git clone git://dfa.imn.htwk-leipzig.de/ws13-code/pps.git
cd pps/rechner ; make ; make test ; make clean
sablecc
gefunden werden, also /usr/local/waldmann/bin
im PATH
sein)
rechner.grammar
enthält Attributgrammatik, diese beschreibt die Konstruktion
des abstrakten Syntaxbaumes (AST) aus dem Ableitungsbaum (konkreten Syntaxbaum)
Eval.java
enthält Besucherobjekt, dieses beschreibt die Attributierung
der AST-Knoten durch Zahlen
Interpreter.java
Makefile
rechner/*
Der erzeugte Code ist synthetisiertes Attribut!
push c;
code(x); code(y); o;
x <- pop; y <- pop; push (x o y);
CIL (gmcs, monodis)
x++ - --x
;
while (B) A
if (B) ...
(vervollständige!)
for(A; B; C) D
in while!
Vorteil deklarativer Programierung:
f (x) = if x > 52
then x - 11
else f (f (x + 12))
t (x, y, z) =
if x <= y then z + 1
else t ( t (x-1, y, z)
, t (y-1, z, x)
, t (z-1, x, y) )
{ V } A { N }
{ x >= 5 } y := x + 3 { y >= 7 }
class Stack [G] feature
count : INTEGER
item : G is require not empty do ... end
empty : BOOLEAN is do .. end
full : BOOLEAN is do .. end
put (x: G) is
require not full do ...
ensure not empty
item = x
count = old count + 1
Beispiel sinngemäß aus: B. Meyer:
Object Oriented Software Construction,
Prentice Hall 1997
{ N[x/E] } x := E { N }
{ V und B } C { N }
und { V und not B } D { N }
=> { V } if (B) then C else D { N }
wenn { I and B } A { I },
dann { I } while (B) do A { I and not B }
Eingabe int p, q;
// p = P und q = Q
int c = 0;
// inv: p * q + c = P * Q
while (q > 0) {
???
}
// c = P * Q
Moral: erst Schleifeninvariante (Spezifikation),
dann Implementierung.
public static int h(int, int);
Code:
0: iconst_3
1: iload_0
2: iadd
3: iload_1
4: iconst_4
5: isub
6: imul
7: ireturn
public static int g(int, int);
Code:
0: iload_0
1: istore_2
2: iload_1
3: ifle 17
6: iload_2
7: iload_0
8: imul
9: istore_2
10: iload_1
11: iconst_1
12: isub
13: istore_1
14: goto 2
17: iload_2
18: ireturn
Eingabe: natürliche Zahlen a, b;
// a = A und b = B
int p = 1; int c = ???;
// Invariante: c^b * p = A^B
while (b > 0) {
???
b = abrunden (b/2);
}
Ausgabe: p; // p = A^B