§5 Semantische Analyse Symboltabelle Attribute

Werbung
§5 Semantische Analyse
Symboltabelle
Compiler
Benutzerdialog
Scanner
Parser
Symboltabelle
Codegenerator
Attribute
Variablen erhalten Attribute wie
• Name
mit dem sie angesprochen wird
• Typ
der die Sorte bestimmt
• Platz
Bedarf an Speicher für den Typ
• Scope
Deklarationsumgebung
• Range
Bedingungen an die Werte in der Variablen
• Adresse
wo sie im Speicher abgelegt wird (Offset)
Compilerbau §5
2
Kontrollaufgaben
Der Compiler hat viele Kontrollaufgaben zu erfüllen
• Welchen Typ hat ein Bezeichner
(Const, Var, Type, Function, Procedure)?
• Deklaration eintragen
• Platzbedarf
• Adresse (Offset von einer Basisadresse)
• Ist ein Bezeichner schon deklariert?
• Auflösung von Überladung
• Typprüfungen
• Fehlerbehandlung
3
Compilerbau §5
Zwischenablage
• VAR x,y,z : A_Typ;
Problem: Verarbeitung erst nach Lesen des Typs !
• Lösung: Temporäre Speicherung in einer Zwischenablage
UNIT NameBuffer;
INTERFACE
USES Global;
PROCEDURE Ablegen(Name:Identifier);
FUNCTION Entnehmen : Identifier;
• Je nach Anwendung muß die Zwischenablage wie hier als
Stack oder bei anderen Problemen als Queue realisiert
werden.
Compilerbau §5
4
Symboltabelle Zugriffe
• Zugriffe der Symboltabelle fürVariablen elem. Typs
FUNCTION new_name(Entry : SymTabRec) : BOOLEAN;
• Trägt einen neuen Namen mit Typ und Adresse in die
Symboltabelle ein und liefert TRUE zurück. FALSE bei
ERROR_duplicate_identifier.
FUNCTION get_name(Name : Identifier
VAR Entry : SymTabRec) : BOOLEAN;
• Sucht einen Namen in der Tabelle und legt die zugehörigen
Angaben in Entry ab. Gibt FALSE aus, wenn der Name
nicht gefunden wird.
5
Compilerbau §5
Suchbaum
• Form:
binärer Baum
realisiert als
– Zeiger auf einen Knoten
– Jeder Knoten enthält neben der eigentlichen Information Zeiger auf zwei
Teilbäume links und rechts.
• Bedingungen:
– KnotenInfo "größer" als alle KnotenInfo's im linken Teilbaum
– KnotenInfo "kleiner" als alle KnotenInfo's im rechten Teilbaum
• Zugriffe:
– Suche nach einer Info : Vergleiche in einem Knoten und gehe nach
Ergebnis rechts oder links
– Einfügen: Nach erfolgloser Suche steht man an einer Stelle, wo die Info
korrekt eigefügt werden kann.
Compilerbau §5
6
Suchbaum Beispiel
8
Zeiger auf Nichts
6
20
4
25
10
1
5
Hier endet
die Suche
21
17
soll eingefügt werden
7
Compilerbau §5
Suchbaum Aufzählen
Auflisten der Baum-Inhalte
links - Wurzel - rechts :
1 4 5 6 8
10 20 21 25
natürliche Ordnung
8
6
4
1
20
25
10
5
Auflisten der Baum-Inhalte
Wurzel - links - rechts :
8 6 4 1 5
20 10 25 21
z.B. Prüf. der Bedingung
21
Auflisten der Baum-Inhalte
links - rechts - Wurzel :
1 5 4 6 10
21 25 20 8
z.B. beim Löschen
Compilerbau §5
8
Feldtypen
• Unsere Grammatik läßt zusätzlich ARRAY-Typen zu
— Type ::=
— Types ::=
id
(* benannter Typ *)
| ARRAY [IntConst] OF Type (* unbenannter Array type *)
[TYPE id = Type ; {id = Type ;}]
• Die Symboltabelle hat nun außer den Symbolarten VAR
und CONST noch die Symbolart TYPE
— SymKind
= (VarSym, ConstSym, TypeSym)
• Jede Symbolart erhält ihren eigenen Description Record
Compilerbau §5
9
SIMPL-Deklaration
• CONST Dim = 10
• TYPE
• VAR
Index
Element
Vector
Matrix
v
v1
M
i
j
x
:
:
:
:
:
:
=
=
=
=
Integer;
Integer;
ARRAY[Dim] OF Element;
ARRAY[Dim] OF ARRAY[Dim]OF Element;
Vektor;
ARRAY[Dim] OF Element;
Matrix;
Index;
Integer;
Element
Compilerbau §5
10
Der zugehörige Suchbaum
INTEGER
BOOLEAN
Vektor
CHAR
x
Matrix
j
Dim
Index
v
M
v1
Element
i
Compilerbau §5
11
Platzbedarf von Typen
• Berechnung der Adresse (Anfangsadresse) von Variablen:
– Ein Zeiger FreeDataSpace : PData zeigt auf den nächsten freien
Platz im Datensegment, er wird mit 0 initialisiert.
– Jede neue Variable bekommt diesen Zeiger als Adresse zugeordnet,
danach wird dem Zeiger der Platzbedarf des Variablen-Typs aufaddiert.
• Berechnung des Platzbedarfs eines Typs
– Für die Elementaren Typen wird jeweils der Platzbedarf festgehalten
(im Beispiel 1 für alle drei elementaren Typen)
– Der Platzbedarf für einen User-Typ ist derselbe, wie der für den Typ in der
zugehörigen Definition
– Der Platzbedarf für einen Array-Typ errechnet sich aus dem Platzbedarf für
den Element-Typ multipliziert mit dem Limit.
– Der Platzbedarf muß im Typ-Descriptor in einem weiteren Feld Size
festgehalten werden, Die Berechnung erfolgt rückwärts über die
Typdefinition (Zwischenablage der Deskriptorenzeiger notwendig!)
Compilerbau §5
12
Typprüfung
• Beispiel:
–
{
{
{
{
1
2
3
4
}
}
}
}
{
{
{
5 }
6 }
7 }
{ 8 }
{ 9 }
{ 10 }
{ 11 }
x
i
x
x
:=
:=
:=
:=
v[ 5 ];
x;
v[ i ];
v[ i ] + 15;
x := j;
x := i;
x := i + 1;
v
v
v1
v[i]
:=
:=
:=
:=
v1;
M[ 1 ];
M[ 1 ];
v1[i];
Linke Seite
Rechte Seite Ok?
Element
Index
Element
Element
Element
Element
Element
Element
+Integer
Integer
Index
Index
+Integer
V2.2 (ARRAY)
T7.2 (ARRAY)
T7.2 (ARRAY)
Element
Element
Element
Element
Vektor
Vektor
V2.2 (ARRAY)
Element
j
n
j
?
?
n
?
n
n
n
j
– j : Typen stimmen überein
– n : Typen sind verschieden
– ? : Integer ist "generisch" für Element ( bzw. Index)
13
Compilerbau §5
Typgleichheit
• identisch : sind Typen, die genau denselben Descriptor
besitzen (equal).
• generisch sind Typen, wenn einer durch eine Folge von
gleich :
User-Umbenennungen aus dem anderen entsteht (Generischer Abkömling : eqivalent).
• vergleichbar : sind Typen, die generische Abkömmlinge
desselben Typs sind (compatible).
• ähnlich :
sind Typen, die bis auf Umbenennungen
dieselbe Definition besitzen(similar).
• gleichmächtig : sind Typen, die denselben Speicherplatz
benötigen(equipotent).
Compilerbau §5
14
Typgleichheit
• equal, eqivalent und compatible sind die einzigen
Typgleichheitsbegriffe, die für Compileroptionen zur
Verfügung stehen sollten.
TYPE Equality = ( NotEqual, Compatible, Equivalent, Equal );
FUNCTION CompareTypes( a, b : TypeDesrcRec ): Equality;
VAR Erfolgswert : Equality;
BEGIN
IF a = b THEN BEGIN CompareTypes := Equal; exit END;
IF ( a^.TypeKind <> UserTyp ) OR ( b^.TypeKind <> UserTyp )
THEN Erfolgswert := Equivalent
ELSE Erfolgswert := Compatible;
{ reduziere Anwendertyp auf nächste Grundform }
WHILE a^.TypeKind = UserTyp DO a := a^.TypeDescr;
WHILE b^.TypeKind = UserTyp DO b := b^.TypeDescr;
IF a = b THEN CompareTypes := Erfolgswert
ELSE CompareTypes := NotEqual
END; { FUNCTION CompareTypes }
15
Compilerbau §5
Type-Casting
Veränderung des Typs ohne Veränderung der Daten : in Form eines
Funktionsaufrufs mit den Typnamen des neu zuzuweisenden Typs:
•
VAR
x : A_typ;
y : B_typ;
{vom gleichem Platzbedarf}
:
BEGIN
:
....
A_typ(y);
{ist derselbe Speicherbereich wie y,
kann aber nach den Regeln von A_typ
behandelt, z.B. x zugewiesen, werden.}
:
END;
Die Verantwortung für die Datenintegrität liegt nun ganz beim Benutzer!
Compilerbau §5
16
Prozeduren und Funktionen
• Program
::=
PROGRAM Id ";" Vars Routines Block "."
• Routines
::=
{ Funcdecl | Procdecl }
• Funcdecl
::=
FUNCTION Id "(" Parlist ")" ":" Type ";"
Vars Routines Block ";" |
EXTERN FUNCTION Id "(" Parlist ")" ":" Type ";"
• Procdecl
::=
PROCEDURE Id "(" Parlist ")" ";" Vars
Routines Block ";" |
EXTERN PROCEDURE Id "(" Parlist ")" ";"
• Parlist
::=
{ [ VAR ] Decl }
• Call
::=
Id "(" Callpara ")"
• Callpara
::=
empty | Expr { "," Expr }
• Return
::=
RETURN [ Expr ]
• Stmt
::=
While | If | Assign | Call | Return
Compilerbau §5
17
Herunterladen