Compiler

Werbung
Programmierung 2
Übersetzer: Das Frontend
Sebastian Hack
[email protected]
Klaas Boesche
[email protected]
Sommersemester 2012
1
Vom Programm zur Maschine
Was passiert eigentlich mit unseren Java-Programmen?
Wie werden Sie ausgeführt?
Was macht ein Übersetzer?
Was macht das Laufzeitsystem?
Wie werden Konzepte wie
I
Variable
I
Methoden
I
Klassen
I
Vererbung
in das überführt, was ein Prozessor versteht?
Nächstes Projekt ist ein kleiner Compiler
2
Big Picture
Hierarchie
Programm
Bibliotheken
Laufzeitsystem
Betriebssystem
Prozessor / Hardware
3
Big Picture
In Java
Programm
Bibliotheken
Laufzeitsystem / VM
Betriebssystem
Prozessor / Hardware
3
Big Picture
In C/C++
Programm
Bibliotheken
Laufzeitsystem
Betriebssystem
Prozessor / Hardware
3
Laufzeitsystem
Abstrahiert von Betriebssystem und Prozessor
Speicherverwaltung
Threads
Laden/Nachladen von Bibliotheken
4
Übersetzer
(engl.: Compiler)
Ein Übersetzer
überprüft ein Programm auf Korrektheit bzgl. Syntax und statischer
Semantik
transformiert das Programm in eine Form, in der es vom Prozessor
ausgeführt werden kann
Verbindet das Programm mit dem Laufzeitsystem
5
Übersetzer
(engl.: Compiler)
Die Grenzen zwischen Compiler und Laufzeitsystem sind heutzutage
fließend:
In C/C++ befindet sich das Laufzeitsystem in einer Bibliothek, die
zum Programm gebunden wird (Linker)
Teilweise werden Teile der Laufzeitbibliothek vom Compiler in das
Programm eingefügt
In Java ist ein Teil des Übersetzers im Laufzeitsystem integriert
Java Programme werden nicht direkt in Maschinensprache übersetzt
sondern in Bytecode für eine virtuelle Maschine
Diese beherbergt einen weiteren Übersetzer, der die letzte Stufe der
Übersetzung vornimmt
6
Compiler
Architektur
Compiler bestehen aus drei Teilen
Frontend
1
2
3
Transformation
Backend
Frontend
I
Zerteilen des Quelltextes
I
Aufbau des abstrakte Syntaxbaums (AST)
I
Semantische Analyse (Namensanalyse, Typanalyse, etc.)
Transformation
I
Optimierung
I
Kopplung an das Laufzeitsystem
Backend
I
Abbildung von Hochsprachenkonstrukten auf Maschinenniveau
I
Erzeugung von Maschinencode
7
Compiler
Frontend
Das Frontend besteht wiederum aus mehreren Teilen:
Frontend
Lexer
1
2
3
Zerteiler
Analyse
Lexer
I
Zerteilt den Eingabetext in sog. Tokens
I
Entfernt Whitespace“ und Kommentare
”
Zerteiler (engl.: Parser)
I
Analysiert die Sprache auf syntaktische Korrektheit
I
Erstellt den abstrakten Syntaxbaum (AST)
Analyse (auf dem AST)
I
Kopplung der Verwendung von Bezeichnern an deren Vereinbarungen
I
Typüberprüfung
8
Compiler
Lexer
Programme sind Text Ô Strom von Zeichen
Zerteilt den Zeichenstrom in ein Strom von Tokens
Für die Syntaxanalyse ist nicht der genaue Text,
sondern die Art des Textes wichtig
Token besteht aus
I
Text im Programm, wenn wichtig
I
Koordinaten (Dateiname, Zeilen- und Spaltennummer)
Ô Für evtl. Fehlermeldungen
I
Art des Tokens (+, while, Bezeichner, Literal, etc.)
Bezeichnernamen sind später noch wichtig, daher merken
Lexer erkennt auch Zeichensequenzen,
die keine gültigen Tokens sind.
Ô Bei Java zum Beispiel:
123 abc , 0 xABXZ , 1 e *
9
Lexer
Beispiel
PUBLIC(1,1)
TYPE INT(1,8)
IDENT(1,12,"m")
LPAREN(1,13)
TYPE INT(1,14)
IDENT(1,18,"x")
public int m ( int x ) {
return x + 1;
}
LBRACE
wird zu folgendem Tokenstrom
RETURN(2,3)
RPAREN(1,19)
(1,21)
IDENT(2,10,"x")
PLUS(2,12)
INT LITERAL(2,14,1)
SEMI(2,15)
RBRACE(3,1)
10
Zerteiler
(engl.: Parser)
Lexer nicht ausreichend zur Feststellung der korrekten Syntax
I
123 + * 234
kann problemlos in Tokens zerlegt werden
I
Ist aber strukturell falsch
Struktur gegeben durch kontextfreie Grammatik (häufig BNF)
Zerteiler überprüft diese Struktur
Bestimmt somit gültige Sequenzen von Tokens
Grammatik bestimmt die Struktur des AST
Ô Erzeugung des AST beim Zerteilen
11
Zerteiler
(engl.: Parser)
Lexer nicht ausreichend zur Feststellung der korrekten Syntax
I
123 + * 234
kann problemlos in Tokens zerlegt werden
I
Ist aber strukturell falsch
Struktur gegeben durch kontextfreie Grammatik (häufig BNF)
Zerteiler überprüft diese Struktur
Bestimmt somit gültige Sequenzen von Tokens
Grammatik bestimmt die Struktur des AST
Ô Erzeugung des AST beim Zerteilen
Bemerkung
Es existieren Verfahren, wie man aus einer Grammatik automatisch ein
Programm erzeugen kann, dass Texte dieser Grammatik zerteilt
11
Zerteiler
Auszug aus der Grammatik für unser Beispiel
MethodDecl
Params
ParamDecl
Body
Stmts
Stmt
ReturnStmt
Expr
Literal
IdentUse
Type
Modifier
=
=
=
=
=
=
=
=
=
=
=
=
Modifier Type IDENT LPAREN Params RPAREN Body
Params COMMA ParamDecl | ParamDecl |
Type IDENT
LBRACE Stmts RBRACE
Stmt Stmts |
ReturnStmt | ...
RETURN Expr SEMI
Expr PLUS Expr | Literal | IdentUse | ...
INT_LITERAL | ...
IDENT
TYPE_INT | ...
PUBLIC | ... |
public int m ( int x ) {
return x + 1;
}
12
Zerteiler
Beispiel
MethodDecl3
public int m ( int x ) {
return x + 1;
}
Type2
Params
Body
1 : PUBLIC(1,1) , 2 : TYPE INT(1,8) ,
3 : IDENT(1,12,"m") , 4 : LPAREN(1,13) ,
5 : TYPE INT(1,14) , 6 : IDENT(1,18,"x") ,
ParamDecl
ReturnStmt9
Type5 Ident6
Expr11
7 : RPAREN(1,19) , 8 : LBRACE (1,21) ,
9 : RETURN(2,3) , 10 : IDENT(2,10,"x") ,
11 : PLUS(2,12) , 12 : INT LITERAL(2,14,1) ,
13 : SEMI(2,15) , 14 : RPAREN(3,1)
IdentUse10 Literal12
13
Zerteiler
Beispiel
MethodDecl = Modifier Type IDENT LPAREN Params RPAREN Body
Params
= ParamDecl COMMA Params
| ParamDecl
|
ParamDecl = Type IDENT
Body
= LBRACE Stmts RBRACE
Stmts
= Stmt Stmts |
Stmt
= ReturnStmt | ...
ReturnStmt = RETURN Expr SEMI
Expr
= Expr PLUS Expr
| Literal | IdentUse
| ...
Literal
= INT_LITERAL | ...
IdentUse
= IDENT
Type
= TYPE_INT | ...
Modifier
= PUBLIC | ... |
14
Zerteiler
Beispiel
MethodDecl = Modifier Type IDENT LPAREN Params RPAREN Body
Params
= ParamDecl COMMA Params
| ParamDecl
MethodDecl3
|
ParamDecl = Type IDENT
Body
= LBRACE Stmts RBRACE
Type2
Body
Params
Stmts
= Stmt Stmts |
Stmt
= ReturnStmt | ...
ReturnStmt = RETURN Expr SEMI
Expr
= Expr PLUS Expr
ReturnStmt9
ParamDecl
| Literal | IdentUse
| ...
Literal
= INT_LITERAL | ...
Type5 Ident6
Expr11
IdentUse
= IDENT
Type
= TYPE_INT | ...
Modifier
= PUBLIC | ... |
IdentUse10 Literal12
14
Abstrakter Syntaxbaum
(engl.: Abstract Syntax Tree, AST)
Grammatik der Sprache gibt Struktur des AST vor
Nichtterminale bilden die Knoten des AST
Tokens (Terminale) sind Attribute der Knoten
Baumdarstellung macht Weglassen vieler Tokens möglich
Trennzeichen, wie ;, {, (, etc.
Klammerung kann verworfen werden
15
Analyse
Zerteiler kann nur syntaktische Korrektheit des Programms feststellen
Verletzung der statischen Semantik können nicht geprüft werden,
z.B.:
I
Bezeichner zweimal vereinbart
I
implements mit Klasse statt Interface
I
Typisierung
int x = true ;
I
usw.
Zwei Kernaufgaben:
I
Namensanalyse
I
Typanalyse
16
Namensanalyse
Bezeichner werden verwendet, um Bezüge auf definierte Entitäten
herzustellen
I
Verwendung einer Variable in einem Ausdruck
I
Verwendung einer Klasse zum vereinbaren einer Referenz
Der Übersetzer muss diese Bezüge wieder herstellen
Im AST existiert der Bezug indirekt über Namen
Body
VarDecli
...
Assign
int x , i ;
...
x = 3 + i;
TypeINT TYPE
Expr+
Literal3 IdentUsei
17
Namensanalyse
Angenommen wir überprüfen Typen in x = 3 + i
Dazu benötigen wir den Typen von i
Dieser ist an der Vereinbarung vermerkt
Suchen im Baum?
Body
VarDecli
...
Assign
int x , i ;
...
x = 3 + i;
TypeINT TYPE
Expr+
Literal3 IdentUsei
18
Definitionstabelle
Wir erstellen eine Definitionstabelle
Bildet Bezeichner auf AST-Knoten seiner Vereinbarung ab
Existiert zusätzlich zum AST
...
i
x
Body
VarDeclx
...
...
VarDecli
TypeINT TYPE
...
Assign
Expr+
...
Literal3 IdentUsei
Beim Berechnen des Typs von x = 3 + i
Nachschlagen der Vereinbarung in der Definitionstabelle
19
Definitionstabelle
Was ist bei mehreren Vereinbarungen eines Bezeichners?
class A {
int m ( int x ) {
int a = x + 1;
return a ;
}
int n ( int y ) {
int a = y + 1;
return a ;
}
}
a zweimal vereinbart (in m und in n)
Offensichtlich haben Bezeichner Gültigkeitsbereiche
I
Verwendung von a in m bezieht sich auf die Vereinbarung in m
I
Vereinbarung nicht im ganzen Programm gültig
Hierarchische Definitionstabellen
20
Definitionstabelle
class A {
int m ( int x ) {
int a = x + 1;
return a ;
}
int n ( int y ) {
int a = y + 1;
return a ;
}
}
ren
pa
t
a
...
n
m
a
...
ClassDeclA
MethodDeclm
MethodDecln
VarDecla
VarDecla
21
Hierarchische Definitionstabelle
Einige Knotentypen erzeugen neue Umgebungen
I
Pakete, Klassen, Methoden, Blöcke ({ ... })
Jeder Knoten kann mit einer Referenz auf die Definitionstabelle
ausgestattet werden, in dem er sich befindet
Nachschlagen der Vereinbarung durch Nachschauen in der
Definitionstabelle
wenn nicht gefunden, dann konsultiere Tabelle des nächstäußeren
Bereichs
Beispiel:
class A {
int x ;
int n ( int p ) {
return x + p ;
}
}
x wird nicht im Block von n gefunden, aber in dem von A Ô mit x in
x + p ist also das Feld x von A gemeint
22
Namensanalyse
Namensräume
class A {
class name {
}
int name ;
int name () {
return 0;
}
}
name ist offensichtlich dreimal(!) vereinbart in A
Kein Problem!
In Java halten sich Klassen, Variable und Methoden in
unterschiedlichen Namensräumen auf
Es werden für Klassen, Variable und Methoden getrennte
Definitionstabellen angelegt
23
Namensanalyse
Zusammenfassung
Assoziierung von Auftreten eines Bezeichners mit Vereinbarungen
Vereinbarungen haben Gültigkeitsbereich
Vereinbarung desselben Bezeichners in unterschiedlichen Blöcken
möglich
Analyse implementiert durch hierarchische Definitionstabelle
Mehrere getrennte Namensräume möglich
Hinweis
Diese Prinzipien findet man in so gut wie fast allen modernen
Hochsprachen
24
Namensanalyse Java
Quiz
public class Main {
public static void main ( String [] args ) {
String s = new String ( " Hello World " );
System . out . println ( s );
}
}
class String {
private final java . lang . String s ;
public String ( java . lang . String s ) { this . s = s ; }
public java . lang . String toString () { return s ; }
}
Was gibt das Programm aus?
25
Namensanalyse Java
Quiz
public class Main {
public static void main ( String [] args ) {
String s = new String ( " Hello World " );
System . out . println ( s );
}
}
class String {
private final java . lang . String s ;
public String ( java . lang . String s ) { this . s = s ; }
public java . lang . String toString () { return s ; }
}
Was gibt das Programm aus?
Exception in thread "main" java.lang.NoSuchMethodError: main
25
Herunterladen