15. Semantik, Übersetzen und Interpretieren, Verfikation

Slides:



Advertisements
Ähnliche Präsentationen
Blue J.
Advertisements

Vorlesung Compilertechnik Sommersemester 2008
Programmierung 1 - Repetitorium WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage:
Wiederholung Was ist Informatik?
7. Natürliche Binärbäume
Information - syntaktisch
8. Formale Sprachen und Grammatiken
10. Grundlagen imperativer Programmiersprachen
12. Iteration und Rekursion
3. Berechenbarkeit Wann ist eine Funktion (über den natürlichen Zahlen) berechenbar? Intuitiv: Wenn es einen Algorithmus gibt, der sie berechnet! Was heißt,
Imperative Programmierung
Terminierung und Deadlocks Enkhbat Daginaa Betreuerin Prof. Heike Wehrheim Totale Korrektheit.
Christos, Kornelia, Jan Christos, Kornelia, Jan Entwicklungsumgebung Versteht unseren Java Programm Code Versteht unseren Java Programm.
Christos, Kornelia, Jan Christos, Kornelia, Jan Entwicklungsumgebung Versteht unseren Java Programm Code Versteht unseren Java Programm.
Kapitel 4 Syntaktische Analyse: LR Parsing.
Parser generieren Yet Another Compiler – Compiler YACC.
FH-Hof Extensible Markup Language Richard Göbel. FH-Hof Extensible Markup Language XML XML ist universeller Ansatz für die Strukturierung von Zeichenketten.
Java: Objektorientierte Programmierung
Java: Dynamische Datentypen
Parser - Verfahren: Rekursiver Abstieg
Indirekte Adressierung
FH-Hof Indirekte Adressierung Richard Göbel. FH-Hof Einfache Speicherung von Daten Eine "einfache" Deklaration definiert direkt eine Speicherplatz für.
Formale Sprachen – Mächtigkeit von Maschinenmodellen
Java: Referenzen und Zeichenketten
REKURSION + ITERATION. Bemerkung: Die in den folgenden Folien angegebenen "Herleitungen" sind keine exakten Beweise, sondern Plausibilitätsbetrachtungen.
Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.
1 Vorlesung Informatik 2 Algorithmen und Datenstrukturen (02 – Funktionenklassen) Prof. Dr. Th. Ottmann.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (02 – Funktionenklassen) Tobias Lauer.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (02 – Funktionenklassen) Prof. Dr. Th. Ottmann.
Informatik II, SS 2008 Algorithmen und Datenstrukturen Vorlesung 2 Prof. Dr. Thomas Ottmann Algorithmen & Datenstrukturen, Institut für Informatik Fakultät.
Vorlesung Informatik 3 Einführung in die Theoretische Informatik (17 –Turingmaschinen) Prof. Dr. Th. Ottmann.
Fakten, Regeln und Anfragen
Imperative Programmierung
Grammatik als Deduktionssystem
Agenda Motivation Formale Sprachen Compiler Compilerentwicklung
PKJ 2005/1 Stefan Dissmann Zusammenfassung Vorwoche Programm besteht aus mehreren Bestandteilen: Schlüsselwörter Sonderzeichen Bezeichner Kommentare Texte.
handlungsorientierte Zugänge zur Algebra
DVG Ablaufsteuerung
DVG Klassen und Objekte
Von der Sprache zum Programm
Grundkonzepte Java - Klassendefinition
LS 2 / Informatik Datenstrukturen, Algorithmen und Programmierung 2 (DAP2)
BIT – Schaßan – WS 02/03 Basisinformationstechnologie HK-Medien Teil 1, 11.Sitzung WS 02/03.
Black Box Algorithmen Hartmut Klauck Universität Frankfurt SS
Einführung in die Informatik für Naturwissenschaftler und Ingenieure
Einführung in die Programmierung Wintersemester 2013/14 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Java Programmierung.
Automaten, formale Sprachen und Berechenbarkeit II SoSe 2004 Prof. W. Brauer Teil 1: Wiederholung (Vor allem Folien von Priv.-Doz. Dr. Kindler vom WS 2001/02.
Städtisches Gymnasium Beverungen Friedel Berlage
Dieser nicht Fehler finden Algorithmus enthält einfach einen gravierenden welcher zu ist.
MODULA-2.
Agenda für heute, 20. April, 2006 Wiederholte ProgrammausführungWiederholte Programmausführung Algorithmische Grundlagen Bedingungen zum Abbruch von Programmschleifen.
Agenda für heute, 14. April, 2005 Wiederholte ProgrammausführungWiederholte Programmausführung Algorithmische Grundlagen Bedingungen zum Abbruch von Programmschleifen.
Beispiele: KFG 2.Teil Beispiel 1: Sei G eine Grammatik mit den folgenden Regeln: S  Ac | Bd A  aAb | ab B  aBbb | abb Definieren Sie.
PHP: Operatoren und Kontrollstrukturen
Code-Optimierung Philipp Bergener Seminar „Übersetzung künstlicher Sprachen“
Frühjahrs-/Sommersemester 2013
Korrektheit von Programmen – Testen
Paul, Morten, Yannick Blue J. Entwicklungsumgebung  versteht Java Programmcode  Für die Entwicklung eigener Software  Durch die Programmierung.
Agenda Motivation und Einordnung Syntaxgerichtete Übersetzung
Mensch – Maschine - Kommunikation
Institut für Softwarewissenschaft – Universität WienP.Brezany 1 Beispiele (Frist: ) Beispiel 1: Sei  = {a, b} ein Alphabet und Q = {q 0, q 1 } eine.
7. Formale Sprachen und Grammatiken
Agenda für heute, 21. April, 2005 Interaktion mit Pascal-ProgrammenInteraktion mit Pascal-Programmen Dateneingabe Programmsteuerung Debugging Datentypen:
Inhalt Einordnung und Funktion der lexikalische Analyse Grundlagen
(Syntax, Strings/Zahlen, Variablen, Arrays)
Wann ist eine Funktion (über den natürlichen Zahlen) berechenbar?
Paul, Morten, Yannick Blue J. Entwicklungsumgebung  versteht Java Programmcode  Für die Entwicklung eigener Software  Durch die Programmierung.
Dr. Wolfram Amme, Semantik funktionaler Programme, Informatik II, FSU Jena, SS Semantik funktionaler Programme.
Funktionen (Zweck und Eigenschaften) Funktionen sind Unterprogramme, die einen bestimmten Zweck erfüllen Sie zerlegen Probleme in kleine, abgeschlossene.
 Präsentation transkript:

15. Semantik, Übersetzen und Interpretieren, Verfikation Korrektheit von Programmen zentrale Frage der Informatik Problem allgemein nicht algorithmisch lösbar, Kompromiß zwischen Risikominimierung und dafür nötigem Aufwand ist zu finden Test: Suche nach Fehlern anhand vorgegebener Solldaten Verifikation: Nachweis der Korrektheit mit mathematischen Mitteln Verifikation setzt präzise formale Beschreibung der Bedeutung (Semantik) von Programmen voraus formale Semantiken sind auch beim Übersetzerbau von entscheidender Bedeutung Ansätze zur Definition von Semantiken: Übersetzersemantik operationale Semantik denotationale Semantik axiomatische Semantik

Semantiktypen 1 Übersetzersemantik: die Bedeutung von Anweisungen einer Programmiersprache PN wird durch die Bedeutung von Anweisungen einer bereits bezüglich Syntax und Semantik bekannten alten Programmiersprache PA festgelegt. Das Grundprinzip ist also die formale Zurückführung einer jeden Anweisung von PN in eine äquivalente Anweisung oder Anweisungsfolge aus PA. Operationale Semantik: Man definiert bei der operationalen Semantik eine (mathematische) Maschine (auch Automat genannt) für eine Programmiersprache, die aus Eingabedaten durch schrittweise Abarbeitung des Programms die Ausgabedaten erzeugt. Das Adjektiv operational verdeutlicht, daß ein konkretes Verfahren angegeben wird, wie der Ausgabewert durch eine Folge von Rechenschritten (Operationen) effektiv aus der Eingabe erzeugt werden kann. Zur exakten Definition der Maschine eignen sich verschiedene Modelle.

Semantiktypen 2 Denotationale Semantik: Bei der denotationalen Semantik wird von einem konkreten Maschinenmodell (wie es bei der operationalen Semantik notwendig war) abstrahiert und nur die Wirkung von Anweisungen in Form veränderter Variablenbelegungen untersucht. Wenn Z die Menge aller möglichen Zustände ist, die bei der Ausführung eines Programms P durchlaufen werden können (formal: Z  W(v1)  W(v2)  W(vn), wobei v1, ..., vn die in P auftretenden Variablen und W(vi) der Wertebereich von vi, d.h. die Menge aller Werte, die vi annehmen kann, sind), dann ist die Wirkung einer Anweisung a eine Abbildung F [a] : Z  Z, die einem Zustand z einen Folgezustand z' zuordnet. F ordnet also einer Anweisung eine Zustandsänderung als Bedeutung in Form veränderter Variablenbelegung zu. F wird auch semantische Funktion genannt.

Beispiel: {-1000 < x ≤ 0} x := x - 1 {-1000 ≤ x < 0} Semantiktypen 3 Axiomatische Semantik: Bei der axiomatischen Semantik wird nur noch auf Eigenschaften von Zuständen und nicht mehr – wie bei der denotationalen – auf konkrete Zustände selbst Bezug genommen. Die Wirkung einer Anweisung a wird durch ein Tripel ({P}, a, {Q}) definiert, wobei P und Q Prädikate (Bedingungen) sind. Wenn P vor Ausführung von a gilt, dann muß Q nach Ausführung von a gelten, allerdings unter der wichtigen Voraussetzung, daß a terminiert. Beispiel: {-1000 < x ≤ 0} x := x - 1 {-1000 ≤ x < 0} Der axiomatische Semantikansatz ist geeignet, Eigenschaften von Programmen zu beweisen, z.B. deren Korrektheit bezüglich einer vorgegebenen, spezifizierten Funktion.

Operationale Semantik für MINI <Programm> => read <Varliste> ; <Anweisung> ; write <Varliste> . <Varliste> => <Bezeichner> | <Bezeichner> ; <Varliste> <Bezeichner> => a | b | c | ... | z <Anweisung> =>  | <Bezeichner> := 0 | <Bezeichner> := <Bezeichner> +1 | <Bezeichner> := <Bezeichner> -1 | <Anweisung> ; <Anweisung> | if <Bezeichner> = 0 then <Anweisung> else <Anweisung> end | while <Bezeichner> ≠ 0 do <Anweisung> end MINI-Syntax

Definition der Assemblersprache ASS <Anweisung> => lade 0 | lade <Bezeichner> | speichere <Bezeichner> | add1 | sub1 | <Anweisung> ; <Anweisung> |  | jump<Marke>| jumpnull <Marke> | <Marke>:<Anweisung> <Bezeichner> => wie bei MINI <Programm> => wie bei MINI <Variablenliste> => wie bei MINI <Marke> => <Bezeichner><Ziffernfolge> <Ziffernfolge> => <Zifer> | <Ziffer><Ziffernfolge> <Ziffer> => 0 |1| 2|3|4|5|6|7|8|9 ASS-Syntax

Übersetzung MINI in ASS  a:=0 a:=b+1 a:=b-1 <Anweisung1>;<Anweisung2> if a=0 then <Anweisung1> else <Anweisung2> end while a  0 do <Anweisung> end ASS  lade0; speichere a lade b; add1; speichere a lade b; sub1; speichere a <Anweisung1>;<Anweisung2> lade a; jumpnull l; <Anweisung2>; jump m; l: <Anweisung1>; m:  l: lade a; jumpnull m;<Anweisung>; jump l; m: 

Übersetzung MINI in ASS  a:=0 a:=b+1 a:=b-1 <Anweisung1>;<Anweisung2> if a=0 then <Anweisung1> else <Anweisung2> end while a  0 do <Anweisung> end ASS

Mathematische Maschinen Eine mathematische Maschine M ist ein Tupel M = (I, O, K, , , ) I: Eingabe, d.h. Programmanweisungen und Eingabedaten, O: eine Menge von Ausgabedaten, K: eine Menge von Konfigurationen, : I  K eine Eingabefunktion, : K O eine Ausgabefunktion, : K  K eine Übergangsfunktion. Die Menge der Konfigurationen K dieser Maschine definiert man als K = A  Z, wobei im konkreten Fall gilt: A ist die Menge aller Anweisungsfolgen von MINI, Z ist die Menge der Zustände, die ein Programm annehmen kann. Zustand: Wertebelegung der Bezeichner eines Programmes, z(b): Wert von b in Zustand z, z0: Anfangszustand, alle Bezeichner haben Wert 0, z <b w> : Zustand, der sich von z nur im Wert w von b unterscheidet (Zustand, den man aus z erhält, indem man den Wert der Variablen b auf w setzt).

Übergangsfunktion  else a; • berechnet Konfigurationsübergänge • Startkonfiguration (Programm, z) wird durch Iteration von  schrittweisein Zielkonfiguration (, z') überführt neuer Zustand (z ist alter Zustand) z z<b  0> z<b  z(b´) + 1> z<b  z(b´) - 1> verbleibende Anweisungsfolge a a; a2 falls z(b) = 0 a1; a2 sonst if b=0 then  else a; a falls b  0; a1 sonst alte Anweisungsfolge ; a b:= 0; a b := b´ + 1; a b1 := b´ - 1; a if b = 0 then a else a1 end; a2 while b  0 do a end; a1 

Ein-, Ausgabefunktionen Unser MINI-Programm P habe die Form read b1, ..., br; a; write c1,..., cs. Eingabefunktion: (P, x1,..., xr) = (a, , z0<b1  x1> ...<br  xr>) Ausgabefunktion: (, z) = (z(c1),...,z(cs)) Die Semantik von P ist die Funktion f: W  W, die auf folgende Weise entsteht: r s 1) Anwendung von  auf (P, x1,..., xr), 2) wiederholte Anwendung von  auf das Resultat von (1) bis eine Konfiguration z erreicht ist, 3) Anwendung von  auf , z. Mathematische Maschinen der beschriebenen Art heißen auch Interpreter

Übersetzen vs. Interpretieren Interpretation: Für jede Aktion (Deklaration, statement, ...) der höheren Programmiersprache gibt es ein Unterprogramm in Maschinensprache, das die Aktion ausführt. Ausführung des (höheren) Programms durch Aufruf von Unterprogrammen (in Maschinensprache) in der richtigen Reihenfolge. Interpreter führt folgenden Zyklus aus: 1. Hole nächsten Befehl. 2. Bestimme die Aktionen, die auszuführen sind. 3. Führe diese Aktionen aus. Interpretation kann als Simulation eines Rechners für die höhere Sprache aufgefaßt werden. Gegebenenfalls muß dieselbe Instruktion häufig dekodiert werden => größere Laufzeit Vorteile: interaktive Programmentwicklung, Fehlersuche, ... Oft werden sowohl Interpreter wie Compiler bereitgestellt - Interpreter für Entwicklung, Compiler für Generierung effizienten Codes nach der Validierung des Programms (Häufig auch Mischformen: Übersetzung in intermediate code, der dann interpretiert wird. Java: übersetzt in Java Bytecode, der auf client Maschinen interpretiert wird.)

Compilierung: Terminologie: Ein Übersetzer (translator ) ist ein Programm, das als Eingabe ein Programm in einer Quellsprache (source language) L1 bekommt und daraus ein äquivalentes Programm in der Zielsprache (target language ) L2 erzeugt. Wenn die Quellsprache eine höhere Programmiersprache und die Zielsprache Assembler oder Maschinensprache ist, so bezeichnet man den Übersetzer als Compiler. Wenn die Quellsprache eine Assemblersprache und die Zielsprache Maschinensprache ist, so nennt man Übersetzer Assembler Übersetzer, die von einer höheren Sprache in eine höhere übersetzen (z.B. in eine Teilmenge der Quellsprache) nennt man Präprozessor (preprocessor). Compiler, die auf Maschine M1 laufen und Maschinencode für eine andere Maschine M2 produzieren, heißen Cross-Compiler

Analyse Lexikalische Analyse: Gruppierung der Zeichen des Quellcodes in elementare Bestandteile (tokens, lexikalische Einheiten): Bezeichner, Zahlen, Schlüsselwörter, Operatoren, Kommentare... Syntaxanalyse (Parsing): Identifikation von Programmstrukturen, Syntaxbaum, Anweisungen, Deklarationen, Ausdrücke ... Semantische Analyse: Erzeugung von Zwischencode (interne Darstellung), Pflege d. Symboltabelle, Fehlererkennung, Makrobehandlung Synthese Optimierung: Zwischencode wird analysiert, Registernutzung, Berechnung von gemeinsamen Unterausdrücken optimiert, redundante Berechnungsschritte eliminiert Codeerzeugung: Generieren des Objektcodes aus dem optimierten Zwischencode

Binder fügt Ergebnisse getrennter Übersetzungen (etwa verschiedener Unterprogramme, Module) zu einer Einheit zusammen. Lader lädt gesamtes Programm als ausführbaren Maschinencode in den Hauptspeicher. Informationen über Namen im Quellprogramm werden in der Symboltabelle gespeichert, z.B.: Typ von Variablen, Größe von Arrays, Anzahl und Typ der Argumente einer Funktion, zugewiesener Speicherplatz. Sobald ein Name im Quellcode gefunden wird, wird überprüft, ob er bereits in der Symboltabelle enthalten ist. Ist das nicht der Fall, wird ein neuer Eintrag vorgenommen. Die Symboltabelle enthält Informationen, die immer wieder vom Compiler benötigt werden, etwa um zu prüfen, ob Deklarationen und die Verwendung von Namen konsistent sind, ob Operationen anwendbar sind, oder wieviel Speicher bei der Codegenerierung für ein Datenobjekt zu Verfügung gestellt werden muß.

1. Lexikalische Analyse: Beispiel (FORTRAN): IF(5.EQ.MAX)GOTO100 erzeugt token stream, z.B.: if( [const,341] eq [id, 729] ] goto [label, 554] Die Symboltabelle könnte folgende Informationen beinhalten: 341: constant, integer, value = 5 ... 554: label, value = 100 729: variable, integer, value = MAX Für die Implementierung spielen endliche Automaten eine wesentliche Rolle. Prinzip der längsten Teilkette: X12 1,2 oder 3 Token(s)? An jeder Stelle wird die längste mögliche Zeichenkette zu einem Token zusammengefaßt, also hier nur 1 Token.

2. Parsing Häufig verwendete Parsing-Technik: rekursiv absteigendes Parsing angelehnt an erweiterte Backus-Naur-Form (EBNF) für Grammatik: Regeln mit geschweiften Klammern (für beliebig oft wiederholte Bestandteile): <exp> ::= <term> {+ term} Regeln mit eckigen Klammern für optimale Teile <if-statement> ::= if <condition> then <statement> [else<statement>] Prozedur für jedes Nichtterminalsymbol wird aus EBNF erzeugt, Eingabe wird von links nach rechts gescannt, Fehlermeldung, falls String nicht als entsprechendes syntaktisches Objekt erkannt werden kann.

Beispielgrammatik: Erzeugte Prozeduren: <sentence> ::= <nounPhrase> <verbPhrase> <nounPhrase> ::= <article> <noun> <aticle> ::= a | the <noun> ::= girl | dog <verbPhrase> ::= <verb> <nounPhrase> <verb> ::= sees | pets Erzeugte Prozeduren: procedure sentence; begin nounPhrase; verbPhrase; end; procedure nounPhrase; article; noun;

procedure article; begin if Token =‘a‘ then GetToken else if Token = ‘the‘ then GetToken else Error; end; procedure noun; if Token =‘girl‘ then GetToken else if Token =‘dog‘ then GetToken procedure verbPhrase; verb; nounPhrase;

Spezifikation und Verifikation Spezifikation legt fest, was Programm leisten soll. Verifikation zeigt, daß Programm tut, was es tun soll. Axiomatische Methode verwendet hierfür Ausdrücke der Form A = {P} S {Q} Aussage P heißt Vorbedingung, Aussage Q Nachbedingung (Zusicherung). Bedeutung von A: falls vor Ausführung des Programmstückes S P gegolten hat, so gilt nach seiner Ausführung Q (S muß terminieren!!). Häufig interessiert man sich für das schwächste P, so daß {P} S {Q} wahr ist. Wir können A je nach Kontext für drei verschiedene Zwecke verwenden: Ist S eine einzelne Anweisung, so dient A der Definition dieser Anweisung. (axiomatische Semantik). Ist S ein Programm (oder Programm-Fragment), so kann A aus den Definitionen der einzelnen Befehle synthetisiert werden. A ist dann die Beschreibung des Programms. Ist S ein noch zu schaffendes Programm, so ist A die Spezifikation des Programms.

Zusammenfassung Die Beschreibung der Semantik kann u.a. folgenden Zwecken dienen: Axiomatische Definition einer Programmiersprache Programmbeschreibung (Was tut das Programm?) Programmspezifikation (Was soll das Programm tun?) Programmverifikation (Tut das Programm das, was es soll?). Die Definition ist die Vorschrift für denjenigen, der ein Sprachsystem (Interpreter, Compiler) implementiert. Eine Spezifikation ist eine Präzisierung der Anforderungen an ein Programm. Die Beschreibung des Programms entsteht dann durch Zusammensetzung der Axiome entsprechend dem Programmaufbau. Sie setzt also die formale Definition der Programmiersprache voraus. Die Verifikation setzt voraus, daß eine Spezifikation und eine Beschreibung aufgestellt wurden. Sie besteht im Nachweis, daß Beschreibung und Spezifikation übereinstimmen.