1. kapitel einfÜhrung*und*...
TRANSCRIPT
Compilerbau
Prof. Dr. Wolfgang Schramm
EINFÜHRUNG UND ÜBERBLICK
1. Kapitel
1
Vorbemerkungen 1/4
o Einführung in die Grundlagen und Techniken des Compilerbaus. o Übersetzer transformieren Texte einer Quellsprache, deren Struktur durch eine
formale GrammaOk beschrieben ist, in eine Zielsprache. o Klassische Anwendung: Übersetzung höherer Programmiersprachen in
Maschinensprache. o Übersetzung von Programmiersprachen = grundlegendes Problem der
InformaOk. o Gut verstandene Theorie zu formalen Sprachen und Maschinen, die sie
akzepOeren. o Techniken der Syntaxanalyse und ihre Verbindungen mit Übersetzungs-‐akOonen
sind ausgefeilt. o Klare Zerlegung der Gesamtaufgabe des Übersetzungsprozesses in Teilaufgaben. o ImplemenOerung von Programmiersprachen = Allgemeinbildung eines
InformaOkers.
2
Vorbemerkungen 2/4
o Themengebiete des Compilerbau: ¤ Programmiersprachen ¤ Rechnerarchitektur ¤ Theorie (formaler) Sprachen ¤ Datenstrukturen und Algorithmen ¤ So^ware Engineering
3
Vorbemerkungen 3/4
o Einsatzbereiche von Compilerbautechniken ¤ Dokumentstrukturen ¤ GrafikspezifikaOonssprachen ¤ Kommandosprachen von Betriebssystemen ¤ Hardware-‐Beschreibungssprachen ¤ Anfragesprachen für Datenbanksysteme ¤ Protokolle in verteilten Systemen ¤ Formate für den Datenaustausch
4
Vorbemerkungen 4/4
o Vorlesungsinhalte ¤ Methoden des Übersetzerbaus (lexikalische Analyse, Syntaxanalyse,
syntaxgesteuerte Übersetzung, Code-‐OpOmierung). ¤ VielseiOgkeit der Anwendbarkeit der Techniken (Übersetzung einer
Dokumentbeschreibungssprache nach LATEX = Beispiel für eine vollständige ÜbersetzerimplemenOerung)
¤ Einsatz von Werkzeugen (Scanner-‐ und Parsergeneratoren; Lex/Flex und Yacc/-‐Bison).
¤ Detaillierte Behandlung der ImplemenOerung eines Compilers für eine klassische imperaOve Programmiersprache auf der Basis einer abstrakten Maschine.
5
Programmiersprachen -‐ GeneraOonen
o Maschinensprachen (1. GeneraOon – seit 1945) ¤ Befehle in Binärform ¤ Programme sind (fast) unlesbar, unübersichtlich und fehleranfällig
o Assemblersprachen (2. GeneraOon – seit 1950) ¤ Befehle maschinennah (mnemotechnisch) ¤ Programme sind schwer lesbar, wenig übersichtlich und fehleranfällig
o Höhere Programmiersprachen (3. GeneraOon – seit 1954) ¤ Loslösung von der Hardware à problemorienOert ¤ ImperaOve/prozedurale/objektorienOerte Sprachen Bsp.: Fortran, Cobol, C, Java
o 4GL (Sprachen der 4. GeneraOon -‐ seit 1970) ¤ Sprachenfür besondere Anwendungen; Bsp. SQL, PostScript, Maple
o DeklaraOve Programmiersprachen (5. GeneraOon -‐ seit 1980) ¤ Nicht der Lösungsalgorithmus sondern die Problemformulierung mit Hilfe logischer Ausdrücke
steht im Vordergrund ¤ Die Lösungsfindung ist weitgehend vom System vorgegeben. Bsp: Prolog
6
Höhere Programmiersprachen
• Fortran I – 2000 • Algol
• PL/I
• Cobol 68 - 02
• Basic
• Pascal
• C
• Modula-2
• ...
• Common Lisp
• Scheme
• Haskell
• Prolog
• ...
• Simula 67
• Smalltalk 80
• CLOS (Common Lisp Object System)
• Oberon-2
• C++
• ObjectPascal
• Delphi
• Ada
• Eiffel
• Java
• C#
• ...
7
Programmiersprachklassen
o ImperaOve Sprachen ¤ Eng an Struktur des von-‐Neumann-‐Rechners orienOert.
o FunkOonale Sprachen ¤ Keine Trennung zwischen Anweisungen und Ausdrücken. ¤ Namen nur für FunkOonen und Ausdrücke nicht aber für Speicherzellen.
o Logische Programmiersprachen ¤ Basieren auf der operaOonellen Sicht der Prädikatenlogik. ¤ Ausführungsmechanismus: ResoluOon.
o ObjektorienOerte Programmiersprachen ¤ Im Kern imperaOv, ihre Typsysteme unterstützen DatenabstrakOon. ¤ Ermöglichen evoluOonäre So^wareentwicklung.
o Sprachen für spezielle Anwendungsgebiete Beispiele: ¤ Hardware-‐Beschreibungssprachen. ¤ Kommandosprachen für Betriebssysteme. ¤ Text-‐ und GrafikspezifikaOonssprachen.
o Skriptsprachen ¤ InterpreOerte Sprachen mit Operatoren auf höherer Ebene, ¤ Kurze, sehr mächOge Befehle / Berechnungen = Skripts ¤ Beipiele: Awk, JavaScript. Perl, PHP, Python, Ruby, Tcl
8
Abstammung von Programmiersprachen Fortran I
Fortran IV Basic
Lisp Cobol Algol 60
PL/I Algol-W
Algol 68 BCPL C Pascal
Fortran 77
Fortran 90
Fortran 95
Ansi-C
Ada Common Lisp
1957
1960
1965
1970
1975
1980
1985
1990
1995
Modula-2 Smalltalk 80
C++
Java Oberon-2
CLOS
Ada 9x
ObjectPascal
Delphi
C#
Simula 67
9
Aufgabe eines Compilers
Compiler Quellprogramm in A
Zielprogramm in B
Meldungen
10
Grobmodell eines Compilers
Analyse
Synthese
Quellprogramm
Zwischenprogramm
Zielprogramm
11
Feinmodell eines Compilers
lexikalische Analyse
Syntaxanalyse
semantische Analyse
Zwischencodeerzeugung
Codeoptimierung
Codergenerierung
Quell-programm
Ziel-programm
Symbol-tabellenver-waltung
Fehlerbe-handlung
Synthese
Analyse
12
Symboltabelle
. . . enthält InformaOon über Bezeichner, die vom Programmierer eingeführt werden. Format:
Bezeichner Attribute
Beispiel: double r;
Attribute von r: • Typ: double • Relative Adresse innerhalb des umschließenden Unterprogramms / der
Klasse • Gültigkeitsbereich
13
Fehlerbehandlung
o Ziel der Fehlerbehandlung ¤ Entdeckung aller Fehler ¤ Beschreibung der Fehler ¤ Behebung der Fehler für eine Fortsetzung der Übersetzung
14
Lexikalische Analyse
Eingabe
Folge von einzelnen Zeichen – Buchstaben – Ziffern – Leerzeichen – Zeilenende – Operatorsymbole – Interpunktionszeichen
Aufgabe
Erkennen gewisser “Grundsymbole“ im Zeichenstrom
Ausgabe
Gruppe zusammengehöriger Zeichen – Bezeichner – Schlüsselworte – Operatoren: = <= != . . . – Zahlen – Trennzeichen /* */ – Zeichenketten “ . . . . . “
Zusätzliche Aktionen – Vorbereiten von Einträgen in die Symboltabelle – Entfernen von Kommentaren – Entfernen überflüssiger Leerzeichen (Blank Stripping) – Fehlerbehandlung
lexikalische Elemente,
Lexeme,
Token
15
SyntakOsche Analyse 1/2
Eingabe: Folgen lexikalischer Elemente.
Aufgabe: Erkennen hierarchischer Strukturen in Programmen.
Ausgabe: Hierarchische Darstellung („Baum“) von Folgen lexikalischer Elemente = Strukturbaum.
Beispiel: mitte = (links + rechts) / 2; assignment
identifier expression
expression number
identifier identifier
=
/
+
Strukturbaum
16
SyntakOsche Analyse 2/2
Komprimierung des Strukturbaums =
identifier /
+ number
identifier identifier
Syntaxbaum
Zusätzliche Aktionen – Ergänzungen in der Symboltabelle – Fehlerbehandlung
17
SemanOsche Analyse 1/2
Eingabe: Hierarchische Darstellung des Quellprogramms
Aufgabe: Überprüfung der Typverträglichkeiten
Überprüfung von Aspekten, die nicht von der syntakOschen Analyse erfassbar sind, z.B.:
n DeklaraOon / Verwendung von Bezeichnern.
n ÜbereinsOmmung zwischen formalen und aktuellen Parametern.
n ÜbereinsOmmung zwischen Dimension eines Feldes und Indizierung des Zugriffs.
n Auflösen überladener oder polymorpher OperaOonen.
Ausgabe: Geänderter Struktur-‐ (oder Syntax-‐) Baum
18
SemanOsche Analyse 2/2
Beispiel: mitte = (links + rechts) / 2;
Feststellen des Typs der Variablen links und rechts.
Überprüfen, ob für die beiden Typen idenOsch sind.
Sind beide beispielsweise vom Typ int, dann wird eine ganzzahlige AddiOon durchgeführt.
Sind die beiden von unterschiedlichem Typ, wird, falls in der Programmiersprache zugelassen, zuerst eine TypkonverOerung durchgeführt.
Dann wird analog weiter verfahren: Feststellen des Typs der AddiOon von links und rechts und von 2.
19
Zwischencode Erzeugung
Eingabe: Strukturbaum (Syntaxbaum)
Aufgabe: Erzeugen eines “höheren Maschinencodes“ aus dem Syntaxbaum
Ausgabe: Zwischencode
Beispiel: mitte = (links + rechts) / 2;
hilf_1 = links + rechts
hilf_2 = hilf_1 div 2
mitte = hilf_2 3-Adress-Code
20
CodeopOmierung
Eingabe: Zwischencode
Aufgabe: Auffinden von Ineffizienzen im Zwischencode
Ausgabe: (OpOmierter) Zwischencode
Beispiel:
hilf_1 = links + rechts
hilf_2 = hilf_1 div 2
mitte = hilf_2
hilf_1 = links + rechts
mitte = hilf_1 div 2
21
Codeerzeugung
Eingabe: OpOmierter Zwischencode
Aufgabe: Erzeugen von Assembler-‐ oder Maschinencode für die spezielle Zielmaschine
Ausgabe: Maschinencode
Beispiel: hilf_1 = links + rechts
mitte = hilf_1 div 2
LOAD links
ADD rechts
DIV 2
STORE mitte
1-Registermaschine “Akkumulator“
22
Die Systemumgebung des Compilers
Präprozessor
Compiler
Vorform des Quellprogramms
Quellprogramm
Assembler
Zielprogramm in Assemblersprache
Lader/Binder
Programm in verschiebbarem Maschinencode
Programm in absolutem Maschinencode
Andere Programmteile, Pro-‐gramme aus Bibliotheken in verschiebbarem Maschinencode
23
Aufgaben von Präprozessor, Assembler und Binder/Lader
o Präprozessor: Erzeugt aus der Vorform des Quellprogramms (enthält Spracherweiterungen wie z.B. Makros, Einbesung von Datenbank-‐anfragesprachen) die Eingabe für den Compiler.
o Assembler: Überführt ein Programm in Assemblersprache in ein „verschiebbares“ Programm in Maschinensprache. D.h. die im Maschinen-‐programm verwendeten Adressen sind relaOv zum Programmanfang.
o Binder und Lader: Bauen eine Menge von verschiebbaren Maschinenprogrammen aus unterschiedlichen Dateien zu einem einzigen ausführbaren Programm zusammen und laden es in den Hauptspeicher. Dabei werden externe Referenzen (links) aufgelöst (Binder) und es werden die relaOven Adressen entsprechend der LadeposiOon in absolute Adressen umgewandelt.
24
Ablauf eines komplexen Übersetzungsvorgangs
relokatierbare Einheit
ausführbarer Maschinencode im Hauptspeicher
Programm-einheit1
Assemblercode1
relokatierbarer Maschinencode1
Programm-einheitn
Assemblercoden
relokatierbarer Maschinencoden
Loader
Linker
Compiler
Assembler
25
Compiler und Interpreter
o Compiler: Übersetzt ein Quellprogramm in ein Zielprogramm, das zu einem beliebigen späteren Zeitpunkt ausgeführt wird.
o Interpreter: Analysiert das Quellprogramm genauso wie der Compiler. Statt der Überführung in ein Zielprogramm, wird das Quellprogramm direkt ausgeführt.
26
Ausführung von Compiler-‐Sprachen
Subsystems andProperties
2.Describe subsystemsby their properties
Set of Subsystems Set of Interconnections
1.Describe system
4.Determineactual mismatches
List of Mismatches
3.Determine potentialmismatches
List of PotentialMismatches
Subsystems andProperties
2.Describe subsystemsby their properties
Set of Subsystems Set of Interconnections
1.Describe system
4.Determineactual mismatches
List of Mismatches
3.Determine potentialmismatches
List of PotentialMismatches
Subsystems andProperties
2.Describe subsystemsby their properties
Set of Subsystems Set of Interconnections
1.Describe system
4.Determineactual mismatches
List of Mismatches
3.Determine potentialmismatches
List of PotentialMismatches
Programm (höhere Sprache)
Programm (Maschinen-
sprache) Compiler
27
Ausführung von Compiler-‐Sprachen
Subsystems andProperties
2.Describe subsystemsby their properties
Set of Subsystems Set of Interconnections
1.Describe system
4.Determineactual mismatches
List of Mismatches
3.Determine potentialmismatches
List of PotentialMismatches
Programm (Maschinen-
sprache)
28
Ausführung von Interpreter-‐Sprachen
Subsystems andProperties
2.Describe subsystemsby their properties
Set of Subsystems Set of Interconnections
1.Describe system
4.Determineactual mismatches
List of Mismatches
3.Determine potentialmismatches
List of PotentialMismatches
Programm (höhere Sprache)
Interpreter
29
InterpretaOon -‐ Arbeitsweise
= direktes Ausführen der zu den Anweisungen der höheren Programmiersprache gehörenden AkOonen.
Lesen der nächsten Anweisung
Bestimmen der auszuführenden Aktion
Ausführen dieser Aktion
1
2
3
30
Vor-‐ und Nachteile von Compilern und Interpretern
Compiler ¤ Compiler können das Programm bei der
Übersetzung auf Syntax-‐ und SemanOk-‐Fehler überprüfen, d.h. auf Schreibfehler und Widersprüche gegen die SprachdefiniOon.
¤ Anweisungen werden genau einmal (beim Übersetzen) geprü^ und beim Ablauf direkt vom Prozessor ausgeführt.
¤ Compiler zu erstellen ist schwierig.
¤ Treten zur Laufzeit Fehler auf (z.B. eine Division durch 0), sind diese meist schwer zu lokalisieren.
¤ Compiler erzeugen Code, der nur auf einem speziellen Prozessor läu^; Unterschiede z.B. in der Darstellung von Datentypen kann zu unterschiedlichen Ergebnissen des gleichen Programms führen.
¨ Interpreter ¤ SemanOk-‐Fehler werden eventuell erst bei der
Programmausführung bemerkt, ein Absturz kann die Folge sein.
¤ Anweisungen werden bei jedem Durchlauf erneut interpreOert, daher laufen interpreOerte Programme langsamer als übersetzte (Just-‐In-‐Time-‐Compiler helfen).
¤ Interpreter sind einfacher und schneller zu entwickeln. ¤ Interpreter können genauere Fehlermeldungen geben als
Compiler.
¤ Interpreter abstrahieren vom zugrundeliegenden Prozessor, Programme liefern auf jedem Rechner idenOsche Ergebnisse.
31
Hybridcompiler
Übersetzer
Virtuelle Maschine
Quellprogramm
Zwischenprogramm
Eingabe Ausgabe
Java-Sprach-
prozessoren
32
Zusammenspiel von Compiler und Interpreter
Quellsprache A
Zielsprache B
Quellsprache B
Maschinensprache X
Maschinensprache X
Compiler
Interpreter
Hardware
Abstrakte Maschine für B
Reale Maschine für X
33
Werkzeuge für den Compilerbau
Werkzeuge für die verschiedenen Teilaufgaben:
o Scannergenerator (Bsp.: Lex, Flex, JFlex)
o Parsergeneratoren (Bsp.: Yacc, Bison, JavaCC, SableCC)
o Generator für abstrakte Syntaxbäume
o Generator für Asributauswerter
o TransformaOon abstrakter Syntaxbäume
o Generator für Codegeneratoren
34
Vorlesungsgliederung
OrienOert an den Phasen des Compilers: • Lexikalische Analyse • SyntakOsche Analyse • SemanOsche Analyse – Syntax gesteuerte Übersetzung • (Zwischen)code Erzeugung und CodeopOmierung
35
Literaturempfehlungen – eine kleine Auswahl 1/2
o A. Aho, M. Lam, R. Sethi, J. Ullman: Compilers – Principles, Techniques and Tools 2nd EdiOon, Pearson InternaOonal 2007; Paperback (Englisch) 83,45 € Deutsche Übersetzung Pearson Verlag 2008 69,95 € Das Standardwerk des Compilerbaus. Hat (in seiner Erstausgabe) gewissermaßen alle weiteren Bücher zum Compilerbau beeinflusst. Sehr umfassend (Theorie + Praxis) und anschaulich, gut verständlich.
o R. GüOng, M. Erwig: Übersetzerbau – Techniken, Werkzeuge, Anwendungen, Springer
Verlag 1999, 32,95 € Verständlich geschriebenes, kompaktes Buch, ideal für den Einsatz der Compilerbautechniken in der Praxis. Buch mit dem geringsten Theorieanteil aber mit schönen Beispielen.
o N. Wirth: Grundlagen und Techniken des Compilerbaus 2. Auflage, Oldenbourg Verlag, München, 2008, 24,80 € Sehr kompaktes Buch. Die Theorie wird sehr knapp behandelt. Schwerpunkt liegt auf der prakOschen Umsetzung, d.h. der ImplemenOerung eines Compilers (mit konkreten Codefragmenten) für eine Teilmenge von Oberon.
36
Literaturempfehlungen – eine kleine Auswahl 2/2
o R. Wilhelm, D. Maurer: Übersetzerbau – Theorie, KonstrukOon, Generierung 2. Auflage, Springer Verlag 1997, 32,95 € Gutes Buch mit anderem (ungewöhnlichem) Auyau. Auyau orienOert an den 4 Typen von Programmiersprachen. Behandelt auch die Übersetzung funkOonaler, logischer und objektorienOerter Sprachen. DidakOsch anders mit Theorieanteil, der nicht ganz einfach zu verstehen ist.
o O. Mayer: Syntaxanalyse, BI 1978
Ein umfassendes Buch mit hohem Theorieanteil zum Thema Syntaxanalyse.
o J. Levine, T. Mason, D. Brown: „ lex & yacc“. O‘Reilly 1995. 29 €.
Gute, einfache Einführung in lex und yacc. Geht auch auf die unterschiedlichen „lexe“ und „yaccs“ ein.
o Herold: „ lex & yacc. Die Profitools zur lexikalischen und syntakOschen Textanalyse“. Addison-‐Wesley 2003. 24,95 €.
Gute, einfache Einführung in lex und yacc. Wie das Buch von Levine mit etwas zu vielen Redundanzen.