Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

Übersetzertechnik (in Arbeit!!!)

Ähnliche Präsentationen


Präsentation zum Thema: "Übersetzertechnik (in Arbeit!!!)"—  Präsentation transkript:

1 Übersetzertechnik (in Arbeit!!!)
© Günter Riedewald Die Folien sind eine Ergänzung der Vorlesung und nur für den internen Gebrauch konzipiert.

2 Motivation Programmiersprachen als wichtiges Mittel der Softwaretechnik  Weiterentwicklung der Softwaretechnik erfordert neue Sprachen einschließlich deren Implementation Programmiersprachen: - universell (Universalsprachen, general purpose languages): allgemein einsetzbar und unabhängig von einem konkreten Einsatzgebiet; Compilerentwicklung durch Spezialisten

3 - spezialisiert (Fachprogrammiersprachen, Spezialsprachen, special purpose languages, domain specific languages): in Syntax und Semantik zugeschnitten auf ein bestimmtes Fachgebiet; wegen stetig wachsendem Bedarf Entwicklung von Compilern/Interpretern auch durch Nichtspezialisten Probleme des Übersetzerbaus treten auch in anderen Gebieten der Informatik auf (z.B. XML) Abstrakte Betrachtung einer Übersetzung: - Analyse der Struktur der Eingabedaten - Strukturabhängige Erzeugung der Ausgabedaten

4 Gute Kenntnisse über Programmiersprachen und deren Compiler als Voraussetzung für Qualitätssoftware
Didaktische Gründe: - Exemplarisches Vorgehen für die Entwicklung größerer Softwaresysteme: klarer logischer Aufbau, Modularisierung, Nutzung von Werkzeugen, Wartbarkeit, Wiederverwendbarkeit - Fachübergreifende Rolle bzgl. Voraussetzungen und eingesetzten Techniken: Automatentheorie, Theorie der formalen Sprachen, Theorie der Programmiersprachen, Prinzipien der Softwaretechnik, Rechnerarchitektur/ Rechnersysteme ...

5 - Enger Zusammenhang zwischen Theorie und Praxis: gute theoretische Basis als Voraussetzung der Automatisierung der Compilerentwicklung  Vorbildcharakter für andere Informatikbereiche

6 Literatur A.V. Aho, J.D. Ullman: The Theory of Parsing, Translation and Compiling, Prentice Hall, 1972 A.V. Aho, J.D. Ullman: Principles of Compiler Design Addison-Wesley, 1977 A.V. Aho, R. Sethi, J.D. Ullman (2007 zusätzlich: M. S. Lam): Compilers Principles, Techniques and Tools, (Drachenbuch), Addison Wesley, 1986, 2007

7 A.V. Aho, R. Sethi, J.D. Ullman: Compilerbau, (Drachenbuch), Addison-Wesley, 1988, 1990
H. Alblas, A. Nymeyer: Practice and Principles of Compiler Building with C, Prentice Hall, 1996 A. W. Appel: modern compiler implementation in Java (in C) – basic techniques, Cambridge University Press, 1997 J. Elder: Compiler Construction – A Recursive Descent Model, Prentice Hall, 1994 D. Gries: Compiler Construction for Digital Computers, Wiley, 1971 In Russ.: Konstruirovanije kompiljatorov dlja cifrovych vyčislitelnych mašin, Mir, 1975

8 J. Holmes: Object-Oriented Compiler Construction, Prentice-Hall, 1995
U. Kastens: Übersetzerbau, Oldenbourg Verlag, 1990 H. Loeper, W. Otter, H.-J. Jäkel: Compiler und Interpreter für höhere Programmiersprachen, Akademie-Verlag, 1987 K. C. Louden: Compiler Construction – Principles and Practice, PWS Publ. Com., 1997 S. S. Muchnik: Advanced Compiler Design and Implementation, Morgan Kaufmann Publishers, 1997

9 S. Naumann, H. Langer: Parsing, Teubner Stuttgart, 1994
P. Rechenberg, M. Mössenbeck: Ein Compiler-Generator für Mikrocomputer, Hanser Verlag, 1985 W.M. Waite, G. Goos: Compiler Construction, Springer, 1984 D.A. Watt: Programming Language Processors, Prentice Hall International Series in Computer Science, 1993 D.A. Watt, D. F. Brown: Programming Language Processors in Java – Compilers and Interpreters, Prentice-Hall, 2000

10 R. Wilhelm, D. Maurer: Übersetzerbau – Theorie, Konstruktion, Generierung, Springer-Lehrbuch, 1992
N. Wirth: Compilerbau, Teubner Studienbücher Informatik, Teubner Stuttgart, 1986 P. D. Terry: Compilers & Compiler Generators – An Introduction with C++, Intern. Thomson Computer Press, 1997 H. Zima: Compilerbau I, II , BI Mannheim, Reihe Informatik 36,37, 1982, 1983

11 Translatoren - Arten Assemblierer (Assembler): übersetzt aus einer Sprache niederen Niveaus (Sprache mit symbolischer Adressierung, Assemblersprache) in Maschinensprache meist im Verhältnis 1:1 Makroassembler: übersetzt aus einer Sprache niederen Niveaus in Maschinensprache meist im Verhältnis 1:n mit n  1 Compiler: übersetzt aus Sprache von hohem Niveau in Maschinensprache (letztendlich)

12 Präprozessor: übersetzt aus Obermenge zu einer Sprache in Ausgangssprache
Translator auf hohem Niveau: übersetzt aus Sprache hohen Niveaus in andere Sprache hohen Niveaus Decompiler (Disassembler): Regeneriert Quellcode aus Zielcode Self-resident translator: Erzeugung von Zielcode für die Wirtsmaschine (host) Cross-translator: Erzeugung von Zielcode für andere Maschine Interpreter: anweisungsweise Übersetzung und sofortige Ausführung von Quellcode

13 Interpretativer Compiler: Übersetzung aus einer Sprache hohen Niveaus in eine Zwischensprache mit anschließender Interpretation Emulator: Interpretation des Codes einer anderen Maschine

14 1 Übersetzerbau - Einführung
1.1 Symbolische Darstellungen Übersetzer Übersetzung Programm P Übersetzer Programm P von P in Quell- in I in Zielsprache Z sprache Q Abarbeitung Eingabe- P Ausgabe- von P daten in Z daten

15 Interpretation Programm P Inter- Ausgabedaten von P in Quell- preter sprache Q Eingabedaten T-Diagramme (tombstones) Übersetzer P P Q Q  Z Z I

16 Abarbeitung eines Programms E P A Z Interpreter Q

17 Modifikationen der T-Diagramme
Programm P in L geschrieben P L Maschine M M Bezeichneter Compiler <Name>

18 1.2 Einführungsbeispiel Übersetzung von Pascal in P-Code
P-Code: - Sprache der P-Maschine (abstrakter Rechner) - Zwischensprache in Compilern P P P Pascal Pascal  P-Code P-Code P-Code  M M M M

19 1.2.1 Implementierungsprinzipien für ausgewählte imperative Sprachkonzepte
Imperative Konzepte Variablenkonzept: - Variable als Modell für einen Speicherplatz - Möglichkeit des Lesens und der Wertänderung (Schreiben)  Compilersicht: Speicherplatzzuordnung + Zugriff zum Wert als Ganzes oder in Teilen + Lebensdauer + Gültigkeitsbereich (Zugriffsrechte) Strukturierungskonzept für Datenstrukturen  Compilersicht: Abspeicherungskonzept + Zugriff

20 Sprachkonzepte zur Ablaufsteuerung 
Compilersicht: Umsetzung in Sprünge unterschiedlicher Art Prozedurkonzept: - Nichtrekursive Prozedur  Compilersicht: Ersetzen des Aufrufs durch Anweisungen der Prozedur oder Sprünge mit Rückkehr zur Anweisungsfolge - Rekursive Prozedur  Compilersicht: mehrere gleichzeitige Aufrufe erfordern mehrere Inkarnationen des Speicherbereichs der Prozedur (Verwendung von Kellertechnik) - Parameterübergabe  Compilersicht: zusätzliche Anweisungen

21 Programmspeicher CODE
P-Maschine Datenspeicher STORE 0 SP maxstr Programmspeicher CODE PC codemax Befehlsausführung: Steuerung durch Steuerschleife do PC := PC + 1; Ausführung des Befehls in CODE[PC-1] od - Initialisierung PC := 0

22 1.2.2 Ausgewählte Sprachkonstrukte und ihre Übersetzung
Voraussetzungen: Die Kontextbedingungen sind erfüllt (durch semantische Analyse geprüft). Alle Konstrukte sind syntaktisch eindeutig zerlegbar (Durchführung durch syntaktische Analyse). Ausdrücke Übersetzungsfunktion: - code: Ausdruck x Umgebung  P-Code (Umgebung: u: Variablen  Adressen)

23 Unterschiedliche Ausdruckbehandlung auf linker und rechter Seite einer Zuweisung 
codeR : Übersetzung in Befehle zur Berechnung eines Werts codeL : Übersetzung in Befehle zur Berechnung einer Adresse Wertzuweisung code〚x := e〛u = codeL〚x〛u ; codeR〚e〛u ; sto T T Typ; u Umgebung; x Variable; e Ausdruck

24 Adresse von x (u(x) = ); w Wert von e STORE nach w 
Wirkung von sto: STORE vor   w Abarbeitung  SP-2 SP Adresse von x (u(x) = ); w Wert von e STORE nach w   SP

25 codeR〚e1 + e2〛u = codeR〚e1〛u; codeR〚e2〛u; add T
T Typ; e1, e2 Ausdrücke Wirkung von add: STORE vor  w1 w2 Abarbeitung SP STORE nach  w Abarbeitung w = w1 + w2

26 codeR〚c〛u = ldc T c, c Konstante vom Typ T STORE vor  Abarbeitung
SP STORE nach  c

27 codeL〚x〛u = ldc a u(x) , x Variable STORE vor  Abarbeitung
SP STORE nach  u(x)

28 codeR〚x〛u = codeL〚x〛u; ind T = ldc a u(x); ind T , x Variable
STORE vor w  Abarbeitung u(x) =   SP STORE nach w   Abarbeitung von ldc a u(x)  SP STORE nach w  w von ind T  SP

29 Beispiel: Übersetzung von x := (x + (3 + y)) , x, y vom Typ i code〚 x := (x + (3 + y))〛u = codeL〚 x〛u; codeR〚(x + (3 + y))〛u; sto i = ldc a u(x); codeR〚 x〛u; codeR〚(3 + y)〛u; add i; sto i = ldc a u(x); ldc a u(x); ind i; codeR〚3〛u; codeR〚y〛u; add i; add i; sto i = ldc a u(x); ldc a u(x); ind i; ldc i 3; ldc a u(y); ind i; add i; add i; sto i

30 Abarbeitungsschritte:
u(x) = , u(y) = , w1 Wert von x, w2 Wert von y, w3 = 3 + w2, w4 = w1 + w3   STORE-Zustände w1 w2 k w1 w2 k  w1 w2 k   w1 w2 k  w1 w1 w2 k  w1 3 w1 w2 k  w  w1 w2 k  w w2 w1 w2 k  w1 w3 w1 w2 k  w4 w4 w2 k

31 Bedingte Anweisungen code〚if e then st1 else st2 fi〛u = codeR〚e〛u; fjp l1; code〚st1〛u; ujp l2; l1: code〚st2〛u; l2:... Wirkung von fjp l1: k false  k PC := l1 k true  k Wirkung von ujp l2: PC := l2 Anweisungsfolgen code〚st1; st2〛u = code〚st1〛u; code〚st2〛u

32 code〚while e do st od〛u =
Wiederholungen code〚while e do st od〛u = l1: codeR〚e〛u; fjp l2; code〚st〛u; ujp l1; l2:... Beispiel: code〚while a > b do a := a - b od〛u = l1: codeR〚a > b〛u; fjp l2; code〚 a := a - b 〛u; ujp l1; l2:...= l1: ldc a u(a); ind i; ldc a u(b); ind i; grt i; fjp l2; ldc a u(a); ldc a u(a); ind i; ldc a u(b); ind i; sub i; sto i; ujp l1; l2:...

33 1.3 Logische Compilerstruktur Physische Compilerstruktur
Treiber Syntaktische Semantische Semantische Analyse Analyse Synthese Lexikalische Analyse

34 Physische Compilerstruktur (Fortsetzung)
Treiber Syntaktische Analyse Lexikalische Semantische Semantische Analyse Analyse Synthese

35 Logische Compilerstruktur (1)
Quellprogramm Analyse Lexikalischer Datentabellen Analysator Codierte Terminalfolge Syntaktischer Datenmodule Syntaxbaum Semantischer Dekorierter Semantische Synthese Zielprogramm

36 Logische Compilerstruktur (2)
Quellprogramm Lexikalische Analyse Symbol- Syntaktische Fehlerbehandlung tabellen- Analyse verwaltung Semantische Zwischencode- Code- Code- Erzeugung Optimierung Erzeugung Zielprogramm

37 2 Lexikalischer Analysator
Aufgabe: Transformation des Quellprogramms aus einer Zeichenfolge in eine codierte Folge von Terminalen (Tokenfolge, Grundsymbolfolge) mit Sammlung spezieller Informationen in Tabellen Teilaufgaben: Auffinden und Erkennen eines Lexems (≙ Terminal) Codierung der Lexeme Auslassung überflüssiger Zeichenfolgen Erstellung von Datentabellen

38 2.1 Auffinden und Erkennen von Lexemen
Fakt: Lexeme sind überwiegend durch reguläre Grammatikregeln beschreibbar.  Es existieren endliche Automaten, die genau diese Lexeme akzeptieren. Beispiel: <ganze Zahl> ::= 0|1|...|9|0 <ganze Zahl>|...|9 <ganze Zahl> <Identifikator> ::= A|...|Z|A <Id1>|...|Z <Id1> <Id1> ::= A|...|Z|0|...|9| A <Id1>|...|9 <Id1> <Beschränker> ::= +|-|(|)|/|/ <schräg>|* <Stern>|: <gleich>|;|, <schräg> ::= / <Stern> ::= * <gleich> ::= =

39 Endliche Automaten zu den Regeln: 0,. ,9 S gZ 0,. ,9 A,. ,Z S Id A,
Endliche Automaten zu den Regeln: 0,...,9 S gZ 0,...,9 A,...,Z S Id A,...,9 + - ( ) ; , * * S S St / / : = S gl

40 Endlicher Automat für Akzeptanz aller Lexeme:
A,...,Z A,...,Z,0,...,9 0,...,9 + - ( ) ; , * * / : =

41 2.2 Kodierung der Lexeme 1 Identifikator 9 ** 2 ganze Zahl 10 (
Kodierung Lexem Kodierung Lexem 1 Identifikator 9 ** 2 ganze Zahl 10 ( 3 BEGIN ) 4 END // 5 REAL := 6 / ; 8 -

42 Semantische Aktionen ADD Aufsammeln von Zeichen eines Lexems in einer Puffervariablen A GC Lesen des nächsten Quellprogrammzeichens, Zwischenablage in der Variablen Char sowie Bestimmung der Art des Zeichens LOOKUP Bestimmung der Kodierung des in A abgelegten Lexems gemäß Tabelle der internen Kodierung (Kodierung 1 bei Nichtvorhandensein) OUT(C,A) Ausgabe eines Lexems (in A) zusammen mit seiner Kodierung (in C) GPC Überlesen aller bedeutungslosen Zeichen und Fortsetzung wie GC sowie Löschen von A

43 Endlicher Automat mit semantischen Aktionen:
A,...,Z LOOKUP(A,C);OUT(C,A) ADD;GC A,...,Z,0,...,9 ADD;GC 0,...,9 OUT(2,A) ADD;GC 0,...,9 GPC ADD;GC + - ( ) ; , ADD;GC LOOKUP(A,C);OUT(C,A) * * ADD;GC ADD;GC OUT(9,A) / ADD;GC / OUT(6,A) ADD;GC OUT(12,A) : = ADD;GC ADD;GC OUT(13,A)

44 2.5 Automatische Erzeugung von lexikalischen Analysatoren
Lexembeschreibung Lexikalischer (reguläre Ausdrücke, Analysator - semantische Rahmensystem Aktionen) Generator Steuerung

45 Lex-Spezifikation <Deklarationsteil> %% <regulärer Ausdruck> {<semantische Aktion in C>} ... <Nutzerunterprogramme>

46 Beispiel: # include ´´y.tab.h´´ extern int yyz, yyli;
extern symbol *lookup(), *install(); %% ´´\n´´ {yyli ++;} [ ] ; [0-9][0-9]* {symbol *s; if ((s=lookup(yytext))==0) s=install(yytext); ...; return (ZAHL);} if {return (IF);} ... true {keys *k; k=lookkey(yytext); yylval.yyk=k; return (TRUE);} [a-z][a-z 0-9]* {symbol *s; if ((s=lookup(yytext))==0) s=install(yytext); yylval.yysym=s; return (IDENTIFIKATOR);}

47 3 Syntaktische Analyse Beispiel: Aus  Id ( Aus ) Aus  Id [ Aus ]
Id  f Id  z

48 Syntaxbaum von f(a[z]) Aus Top-down Analyse 11 Id Aus Id Aus Id Bottom-up Analyse 16 f ( a [ z ] )

49 3.1 Kellerspeicher in der Syntaxanalyse Top-down Analyse - Grundalgorithmus
Voraussetzung: Verwendung eines Analysekellers Schritte des Algorithmus´: Startsymbol in den Keller Wiederholung folgender Schritte bis zum Erreichen eines leeren Kellers: - Nichtterminal an Kellerspitze: Expansion (Ersetzen des Nichtterminals durch rechte Seite einer geeigneten Syntaxregel) - Terminal an Kellerspitze: Vergleich mit aktuellem Element des analysierten Wortes; bei Gleichheit Streichen aus dem Keller, nächstes Element des Wortes wird aktuelles Element; bei Ungleichheit Backtracking

50 Beispiel:Top-down Analyse von f(a[z]) Aktuelles Element Keller (Spitze links) Operation f(a[z]) Aus Aus  Id ( Aus ) f(a[z]) Id ( Aus ) Id  f f(a[z]) f ( Aus ) 2x Vergleich a[z]) Aus ) Aus  Id [ Aus ] a[z]) Id [ Aus ] ) Id  a a[z]) a [ Aus ] ) 2x Vergleich z]) Aus ] ) Aus  Id  z z]) z] ) 3x Vergleich 

51 Bottom-up Analyse - Grundalgorithmus
Schritte des Algorithmus´: Start mit leerem Keller Wiederholung folgender Schritte, bis das Startsymbol allein im Keller ist: - Reduktion: nur möglich, wenn an der Kellerspitze die rechte Seite einer Regel ist ( Ersetzen durch linke Seite) - Einlesen (Verschiebung): Einlesen des nächsten Elements des Wortes in den Keller

52 Beispiel: Bottom-up Analyse von f(a[z])
Restwort Keller (Spitze rechts) Operation f(a[z])  Lesen f (a[z]) f Reduktion f zu Id (a[z]) Id Lesen (a [z]) Id (a Reduktion a zu Id [z]) Id ( Id Lesen [z ]) Id ( Id [z Reduktionen z zu Id, Id zu Aus ]) Id ( Id [ Aus Lesen ] ) Id ( Id [ Aus ] Reduktion Id [ Aus ] zu Aus ) Id ( Aus Lesen )  Id ( Aus ) Reduktion Id ( Aus ) zu Aus  Aus

53 3. 2 Deterministische Syntaxanalyse 3. 2
3.2 Deterministische Syntaxanalyse Top-down Verfahren - Methode des rekursiven Abstiegs Grundmethode: Idee: Syntaktische Regel A  ...wird als Prozedur zur Erkennung von Zeichenketten aus L(A) betrachtet, wobei die rechte Seite der Regel die Struktur vorgibt: Terminal: erwartetes Terminal Nichtterminal: Aufruf der entsprechenden Prozedur Alternativen: Code-Alternativen in der Prozedur

54 Beispiel: Prozedur zur Regel T  ( Aus )| [ Aus ] procedure T; begin case token of (: match( ( ); Aus; match( ) ); [: match( [ ); Aus; match( ] ); else error; end case; end T; Vor.: token enthält aktuelles Terminal der zu analysierenden Zeichenkette

55 Definition der Prozedur match: procedure match(expectok); begin if token = expectok then gettoken else error fi; end match; gettoken liest das nächste Zeichen aus der Zeichenkette und ordnet es token zu.

56 Konstruktion der Zerlegungsprozeduren
N  X : procedure N; <parse X> <parse X> bedeutet Anweisungen zur Erkennung von X, wobei - X =  einer Leeranweisung - X = t (Terminal, token) match(t) - X = M (Nichtterminal) M (Aufruf der Prozedur) - X = A B <parse A>; <parse B>

57 - X = A| B case token of e1: <parse A>; e2: <parse B>; else error; end case; e1  DS(N, A), e2  DS(N, B) - X = A* while token  DS(N, A) do <parse A> od entspricht.

58 Definition der Entscheidungsmenge (director set) Vor. : A  1|
Definition der Entscheidungsmenge (director set) Vor.: A  1| ...| n DS(A, i) = {a  T| a  FIRST1(i) ∨ (i *  ⋀ a  FOLLOW1(A))} Beispiel: 1 A  I T 11/12/13 T  ( A )| [ A ]|  14/15/16 I  a| f| z DS(T, 1) = { ( } DS(I, 1) = {a} DS(T, 2) = { [ } DS(I, 2) = {f} DS(T, 3) = { ], ), } DS(I, 3) = {z}

59 Top-down Analyse von f(a[z])
Keller () Zeichenkette Keller Zeichenkette A f(a[z]) [ A ] ) I T A ] ) z]) f T I T ] ) T (a[z]) z T ] ) ( A ) T ] ) ]) A ) a[z]) ] ) I T ) ) ) a T )   T ) [z])

60 LL(k)-Grammatik G = (N, T, P, S)
G ist eine kontextfreie Grammatik Für beliebige Paare von Linksableitungen S + A   * x S + A   * y mit FIRSTk(x) = FIRSTk(y) gilt  =  .

61 Starke LL(k)-Grammatik G = (N, T, P, S)
Für jedes Paar von Regeln aus P A  x und A  y (A  x | y) gilt FIRSTk(x FOLLOWk(A))  FIRSTk(y FOLLOWk(A)) = 

62 Tabellengesteuerte LL(1)-Analyse
Analysealgorithmus: Eingabe: Analysetabelle M, Zeichenkette w  T* Ausgabe: Fehlermeldung oder Regelnummernfolge Startkonfiguration: (w, S#, ) Schritte: 1. (ax, A, r) ⊢ (ax, , r i) für M(A, a) = (, i) 2. (ax, a, r) ⊢ (x, , r), a  T 3. (, #, r) erfolgreicher Abschluss 4. Fehler sonst

63 Analysetabelle für obige Grammatik und Analyse von f(a[z]) a f z ( [ ) ]  A IT,1 IT,1 IT,1 T (A),11 [A],12 ,13 ,13 , 13 I a,14 f,15 z,16 (f(a[z]), A#, ) ⊢ (f(a[z]), IT#, (1)) ⊢ (f(a[z]), fT#, (1 15)) ⊢ ((a[z]), T#, (1 15)) ⊢ ((a[z]), (A)#, ( )) ⊢ (a[z]), A)#, ( )) ⊢ (a[z]), IT)#, ( )) ⊢ (a[z]), aT)#, ( )) ⊢ ([z]), T)#, ( )) ⊢

64 ([z]), T)#, ( )) ⊢ ([z]),[A])#, ( )) ⊢ (z]), A])#, ( )) ⊢ (z]), IT])#, ( )) ⊢ (z]), zT])#, ( )) ⊢ (]), T])#, ( )) ⊢ (]), ])#, ( )) ⊢ (), )#, ( )) ⊢ (, #, ( ))

65 Deterministische Syntaxanalyse 3. 2
Deterministische Syntaxanalyse Bottom-up Verfahren - Einfache Präzedenz Einfache Präzedenz Relationen: R <∙ S: Es existiert eine Regel U  ...R V ... und V + S R ≐ S: Es existiert eine Regel U  ...R S... . R ∙> S: Es existiert eine Regel U  ...V W... Und V + ...R sowie W * S

66 Präzedenzmatrix für Beispielgrammatik
Aus Id ( ) [ ] a f z Aus ≐ ≐ Id ≐ ∙> ≐ ∙> ( ≐ <∙ <∙ <∙ <∙ ) ∙> ∙> [ ≐ <∙ <∙ <∙ <∙ ] ∙> ∙> a ∙> ∙> ∙> ∙> f ∙> ∙> ∙> ∙> z ∙> ∙> ∙> ∙>

67 Analyseprozess unter Nutzung der Präzedenzmatrix Wiederholung folgender Schritte: 1. Einspeicherung der Zeichen der Zeichenkette in den Keller, bis an der Kellerspitze ein Zeichen E steht , das in der Relation ∙> mit dem nächsten einzulesenden Zeichen steht 2. Abstieg im Keller bis zum Erreichen des ersten Zeichens A mit y <∙ A, dabei befindet sich y im Keller direkt unter A 3. Reduktion der Zeichenkette A...E im Keller gemäß syntaktischen Regeln

68 Analyse von f(a[z]) Keller Restwort <∙ f ∙> ( a [ z ] )
<∙ Id ≐ ( <∙ a ∙> [ z ] ) <∙ Id ≐ ( <∙ Id ≐ [ <∙ z ∙> ] ) <∙ Id ≐ ( <∙ Id ≐ [ <∙Id ∙> ] ) <∙ Id ≐ ( <∙ Id ≐ [≐ Aus ≐ ] ∙> ) <∙ Id ≐ ( ≐ Aus ≐ ) ∙> Aus

69 LR(k)- Analyse Charakterisierung:
Entspricht Grundverfahren modifiziert durch Vorausschau auf k Elemente Darstellung durch eine Zustandsmenge zusammen mit Übergangsfunktion in Form einer Analysetabelle, bestehend aus Aktionstabelle (Einlesen und Reduktion) und Sprungtabelle (Fortsetzung nach Reduktion)

70 Beispiel: Konstruktion der Analysetabelle für
A  I ( A )| I [ A ]| I I  a| f| z Zustände und Übergänge des charakteristischen endlichen Automaten Zustand Q0: Zustand Q1: Zustand Q2: T  . A ⊣ T  A .⊣ A  I .( A ) A  .I ( A ) A  I .[ A ] A  .I [ A ] A  I. A  .I Zustand Q3: Zustand Q4: I  .a I  a. I  f. I  .f I  .z Zustand Q5: I  z.

71 Zustand Q6: Zustand Q7: Zustand Q8: A  I ( .A ) A  I [ .A ] A  I ( A .) A  .I ( A ) A  .I ( A ) A  .I [ A ] A  .I [ A ] Zustand Q9: A  .I A  .I A  I [ A .] I  .a I  .a I  .f I  .f Zustand Q10: I  .z I  .z A  I ( A ). Zustand Q11: A  I [ A ].

72 Q0 A I Q1 a f z Q2 Q3 Q4 Q5 [ ( I Q7 a f z A I a f z Q9 Q6 Q2 Q3 Q4 Q5 A ] Q8 ) Q11 Q10 Charakteristischer endlicher Automat

73 Analysetabelle ( [ a f z ] ) ⊣ A I Q0 Q3 Q4 Q5 Q1 Q2 Q1 T  A⊣
Q2 Q6 Q A  I ... Q I  a ... Q I  f ... Q I  z ... Q6 Q3 Q4 Q Q8 Q2 Q7 Q3 Q4 Q Q9 Q2 Q Q10 Q Q11 Q A  I ( A ) ... Q A  I [ A ] ...

74 Syntaxanalyse unter Verwendung einer Analysetabelle (AT):
Verwendung zweier Keller: Elementekeller (EK) wie im Grundalgorithmus und Zustandskeller (ZK) Start der Analyse: Q0 im Zustandskeller Ende der Analyse: Altes Startsymbol im Elementekeller; Endezeichen als aktuelles Zeichen Schritte: 1. Einlesen: Aktuelles Zeichen der Eingabe in EK und neuer Zustand gemäß AT (bestimmt aus altem Zustand und Zeichen) in ZK 2. Reduktion:- Reduktion an EK-Spitze gemäß Regel aus AT (bestimmt durch alten Zustand und aktuelles Zeichen) - Entfernen von Zuständen aus ZK (Anzahl gleich Anzahl der Elemente auf r. S. der Regel) - Neuer Zustand gemäß AT (bestimmt durch Zustand an ZK-Spitze und Nichtterminal auf l. S. der Regel) in ZK

75 Beispiel: Analyse von f ( a [ z ] ) ⊣
Elementekeller Restwort Zustandskeller Aktion f(a[z])⊣ Q Einlesen f (a[z])⊣ Q0Q4 Reduktion I (a[z])⊣ Q0Q2 Einlesen I ( a[z])⊣ Q0Q2Q6 Einlesen I ( a [z])⊣ Q0Q2Q6Q3 Reduktion I ( I [z])⊣ Q0Q2Q6Q2 Einlesen I ( I [ z])⊣ Q0Q2Q6Q2Q7 Einlesen I ( I [ z ])⊣ Q0Q2Q6Q2Q7Q5 Reduktion I ( I [ I ])⊣ Q0Q2Q6Q2Q7Q2 Reduktion I ( I [ A ])⊣ Q0Q2Q6Q2Q7Q9 Einlesen I ( I [ A ] )⊣ Q0Q2Q6Q2Q7Q9Q11 Reduktion I ( A )⊣ Q0Q2Q6Q8 Einlesen I ( A ) ⊣ Q0Q2Q6Q8Q10 Reduktion A ⊣ Q0Q1

76 Konflikte im charakteristischen endlichen Automaten
Reduktion-Reduktion: zwei unterschiedliche Reduktionen im gleichen Zustand Beispiel: T  S ⊣ S  a A b A  A b A  c T  . S ⊣ a S  a .A b A S  a A .b b S  a A b. S  .a A b A  .A b A  A .b A  A b. A  .c S c T  S. ⊣ A  c.

77 Reduktion-Einlesen: Aus einem Zustand mit einer Reduktion führt eine mit einem Terminal bewertete Kante. Beispiel: siehe Zustand Q2 im charakteristischen endlichen Automaten des Standardbeispiels  Grammatikklassifizierung LR(0)-Grammatik: Der charakteristische endliche Automat ist konfliktfrei. SLR(1)-Grammatik: Konflikte lassen sich auf der Basis von einem Element Vorausschau unter Nutzung der FOLLOW-Mengen auflösen.

78 Zustand Q2 im Standardbeispiel
Beispiele: Zustand Q2 im Standardbeispiel A  I .( A ) Einlesen (benötigt werden ( oder [ ) oder A  I .[ A ] Reduktion von I zu A? A  I. FOLLOW1(A) = { ), ], ⊣ }, (, [ ∉ FOLLOW1(A)  - Ist das aktuelle Zeichen ( oder [, dann erfolgt Einlesen. - Ist das aktuelle Zeichen aus FOLLOW1(A), dann erfolgt Reduktion. - Sonst liegt ein syntaktischer Fehler vor. Obiger Reduktion-Reduktion-Konflikt läßt sich auflösen: FOLLOW1(S) = { ⊣ } FOLLOW1(A) = { b }

79 LALR(1)-Grammatik: analog zur SLR(1)-Grammatik, aber mit „Verfeinerung“ der FOLLOW-Mengen
Beispiel: d S T  S .⊣ c A A c FOLLOW1(A) = { a, b} FOLLOW1 1 (A) = { b } A  c A  c. FOLLOW1 2 (A) = { a } a b a b S  d c a. S  d A b. S  A a S  c b.

80 LR(k)-Grammatik (-frei)
Für beliebige Paare von Ableitungsfolgen S * w1 z w2  w1 v w2 , z  v  P, w2  T* S * w1´ z´ w2´  w1´ v´ w2´ , z´  v´  P, w2´  T* mit w1 v = w1´ v´ und FIRSTk(w2) = FIRSTk(w2´) Folgt z = z´ und v = v´.

81 Zustände des charakteristischen endlichen Automaten für LR(k)-Grammatiken
Ergänzung einer „Situation“ A  x. X z durch einen Kontext K, wobei folgende Eigenschaften erfüllt sein müssen: Anfangszustand enthält Situation S  .w ⊣ Zustand q enthalte Situation A  u .X, K und zu X existieren die Regeln X  w1 ; ...; X  wn , dann enthält q ebenfalls X  .w1 , K´; ...; X  wn , K´ mit K´= FIRSTk( K)

82 Enthält der Zustand q die Situation A  u
Enthält der Zustand q die Situation A  u. x , K , dann erfolgt ein Übergang in einen Zustand mit der Situation A  u. x , K Konflikte im charakteristischen endlichen Automaten: Reduktion-Reduktion: Ein Zustand enthält die Situationen A  u. , K1 und A  v. , K2 mit A ≠ B oder u ≠ v, aber t  K1  K2 Reduktion-Einlesen: Ein Zustand enthält die Situation A  u. , K und besitzt einen Übergang mit dem Terminal t und t  K .

83 Beispiel: LR(1)-Zustände für Standardbeispiele (Auswahl) Q0: T 
Beispiel: LR(1)-Zustände für Standardbeispiele (Auswahl) Q0: T  .A ⊣ Q0  Q2: A  I.(A) , ⊣ A  .I(A) , ⊣ A  I.[A] , ⊣ A  .I[A] , ⊣ A  I. , ⊣ A  .I , ⊣ I  .a , {(, [, ⊣} I  .f , {(, [, ⊣} I  .z , {(, [, ⊣}

84 3.4 Syntaktische Fehler Aufgaben der Fehlerbehandlung:
Lokalisierung des Fehlers Klassifizierung des Fehlers Fehlernachricht: - Fehlerposition - Grad oder Art des Fehlers - Genauere Angaben zum Fehler Stabilisierung und Fortsetzung der Analyse

85 Fehlerposition: w  T* und es existiert w´  T* , wobei w w´  L(G) (w lässt sich durch w´ zum Wort aus L(G) ergänzen) Für w x, x  T, existiert keine Ergänzung v  T* , so dass w x v  L(G).  x ist eine Fehlerposition Beispiel: In x * (3 – z / y ; ist das „;“ eine Fehlerposition, da x * (3 – z / y richtig ergänzt werden kann, aber x * (3 – z / y ; nicht.

86 Bemerkungen: Bei LL(1)- und LR(1)-Verfahren der syntaktischen Analyse wird ein Fehler immer an einer Fehlerposition erkannt. Der Fehler muss nicht durch das Zeichen an der Fehlerposition verursacht worden sein.

87 3.5 Automatische Erzeugung von Syntaxanalysatoren
Kontextfreie Grammatik Analysator Rahmen programm Generator Tabellen

88 yacc-Spezifikation <Deklarationen> %% <Syntaxregeln und Semantik> <Programmteil>

89 4 Semantische Analyse 4.1 Symboltabellen Einfache Struktur
Hashtabelle mit Verkettungstechnik Beispiel: 1 DE A1B 0 3 CAESAR 4 FAUL F 0 6 D1 0 C5 0 frei

90 Symboltabellen mit abgetrennter Schlüsselliste
Hashtabelle mit Verkettungstechnik und abgetrennter Schlüsselliste Beispiel: 1 3 4 frei 2 D E 3 A 1 B 6 C A E S A R 4 F A U L 1 F 2 D C 5

91 Beispiel: Programm mit Blockstruktur
BEGIN REAL a, b, c, d; ... BEGIN REAL c, f; L1:... END; BEGIN REAL g, d; L2: BEGIN REAL a; L3:... END

92 Symboltabelle mit Blockstruktur 1
Beispiel: Symboltabelle für obiges Programm L1 Blocknummer f c Übergeordneter Block a L3 Anzahl Eintragungen L2 d Adresse g c b a

93 Symboltabelle mit Blockstruktur 2
Form der Listenelemente: Deklarationen Block Zeiger auf Verkettung Verkettung nummer Information im Block Identifikatoren Blockstruktur Block Anfang Übergeordneter nummer Blockkette Block

94 Beispiel: Symboltabelle zum obigen Programm
c / / d / 5 f / g / / 8 L / L / L /

95 Blockstrukturtabelle 1 1 4 / 2 2 9 1 3 3 11 1 4 4 1 3

96 4.2 Realisierung der semantischen Analyse
Beispiel: Attributierte Grammatik für Deklarationsfolgen Kontextfreie Basisgrammatik <decl list> ::= VAR <id decl> ; <dec list> <dec list>0 ::= <id decl> ; <dec list>1 <dec list> ::=  <id decl> ::= <type> <id> <type> ::= BOOL <type> ::= INT Kontextbedingung: Kein Identifikator darf mehrfach deklariert werden.

97 Zuordnung der Attribute Attribut Art Bedeutung Zuordnung Sv  Symboltabelle <dec list> vorläufig Sn  Symboltabelle neu <dec list>, <decl list> IT  (Identifikator, Typ) <id decl> T  Typ <type> I  Identifikator <id> error  true, false <decl list>, <dec list>

98 Semantische Regeln 1 <decl list>.Sn := <dec list>.Sn
<decl list>.error := <dec list>.error <dec list>.Sv := INIT(<id decl>.IT) 2 <dec list>0.Sn := <dec list>1.Sn <dec list>0.error := <dec list>1.error  IN(<dec list>0.Sv, <id decl>.IT) <dec list>1.Sv := ENTRY(<dec list>0.Sv, <id decl>.IT), wenn ¬ IN(<dec list>0.Sv, <id decl>.IT) 3 <dec list>.Sn := <dec list>.Sv <dec list>.error := false 4 <id decl>.IT := IDDECL(<id>.I, <type>.T) 5 <type>.T := ´bool´ <type>.T := ínt´

99 Dekorierter Syntaxbaum von VAR INT x; BOOL y;
<decl list> {(´x´,´int´),(´y´,´bool´)}, false VAR <id decl> ; <dec list> (´x´,´int´) {(´x´,´int´)}, {(´x´,´int´),(´y´,´bool´)}, false <type> <id> <id decl> ; ´int´ ´x´ (´y´,´bool´) <dec list> {(´x´,´int´),(´y´,´bool)}, INT x <type> <id> {(´x´,´int´),(´y´,´bool´)}, ´bool´ ´y´ false BOOL y 

100 Schachtelung von Programmeinheiten
Beispiel: Programm PROGRAM H; PROC B; PROC D; ; call C; END B; END D; call B; PROC A; END A; PROC C; ; call A;...; call D;... ...; call D; END H; END C;

101 Statische Schachtelung mit Schachtelungstiefe
D/1 A/1 C/2 B/2 Dynamische Schachtelung H A D B C D

102 Datenbereich (Prozedurschachtel, Kellerrahmen) einer Prozedur (eines Blocks) zur Laufzeit
Allgemeiner Aufbau Funktions Statischer Dynamischer alter EP Rücksprung wert Vorgänger Vorgänger Wert adresse MP Parameter Lokale Felder Zwischen (statisch) Variablen (semidyn.) ergebnisse SP EP

103 Variablenadressierung: (Schachtelungstiefe, Relativadresse)
Beispiel: PROGRAM H; Adressierung: VAR x1, y; In H: x (0, 5) PROC p; y (0, 6) VAR i, x1, k; In p: i (1, 5) ...x x (1, 6) ...k k (1, 7) ...y... END p; call p; ...x1... END H;

104 Aktionen bei Eintritt in eine Prozedur q (p ruft q auf)
Setzen des statischen Vorgängers von q Setzen des dynamischen Vorgängers von q (Anfangsadresse des Datenbereichs von p – alter MP-Wert) Retten des alten EP-Wertes Berechnung der aktuellen Parameter Setzen des MP-Registers auf Anfangsadresse des Datenbereiches von q (SP + 1)

105 Abspeicherung der Rückkehradresse
Ausführung des Sprungs auf ersten Befehl des übersetzten q-Programms Setzen des SP-Registers Berechnung des EP-Wertes und Setzen des EP-Registers sowie Überprüfung auf mögliche Kollision zwischen Keller und Halde

106 Aktionen bei Verlassen der Prozedur q (Rückkehr nach p)
Freigabe des Datenbereichs bis auf eventuellen Funktionswert Setzen der MP-, EP- und SP-Register für die Prozedur p Rückkehr nach p

107 Beispiel: rekursiver Funktionsaufruf
PROGRAM Fak; VAR r : integer; FUNCTION F(n: integer): integer; IF n = 1 THEN F := 1 ELSE F := n * F(n – 1); END F; r := F(3); END Fak; Adressierung r (0, 5) n (1, 5) F (1, 0)

108 Übersetzung von Fak <Befehle für Aufbau des DB>; lda i 0 6; <Übersetzung des Aufrufs F(3)>; M1: sto i; <Befehle für Abbau des DB> Übersetzung von F(n) <Befehle für Aufbau des DB>; lod i 0 5; ldc i 1; equ i; fjp l1; lda i 0 0; ldc i 1; sto i; ujp l2; l1: lda i 0 0;lod i 0 5; <Übersetzung des Aufrufs F(n – 1)>; M2: mul i; sto i; l2: <Befehle für Abbau des DB und Rückkehr>

109 Abspeicherung von Datenstrukturen Mehrdimensionale Felder
A: ARRAY [u1.. o1, ..., un.. on] OF <type> Speicherabbildungsfunktion Adresse(A[i1, ..., in]) = Adresse(A[u1, ..., un]) + (i1 – u1) * d2 * ...* dn + (i2 – u2) * d3 * ...* dn + ... + (in – un) = k + v (di = oi – ui + 1)

110 Semidynamische Felder
Beispiel: semidynamische Felder in ALGOL 68 begin ... n := ...; ...; m := ...; ... begin [n] int A; [m] int B; A[i] := B[j+3] * k; end

111 Schablone (Felddeskriptor) eines semidynamischen Feldes
A: ARRAY [u1.. o1, ..., un.. on] OF <type> u1 o1 d1 ... un on dn n k´ adr adr = Adresse(A[u1, ..., un]) k´= u1 * d2 * dn + u2 * d3 * dn un

112 Datenbereich für inneren Block
Schablone für A Schablone für B Voraussetzung: Zur Laufzeit gilt n = 4 und m = 5 .

113 Erzeugte Befehlsfolgen (im Beispiel):
Aufbau des DB einschließlich der teilweise gefüllten Schablonen Berechnung von n und der fehlenden Elemente der Schablone für A Neuberechnung der ersten freien Adresse des freien dynamischen Speicherteils Berechnung von m und der fehlenden Elemente der Schablone für B Adressberechnung für A[i] aus der Schablone für A Adressberechnung für B[j+3] aus der Schablone für B

114 Datenmüllbeseitigung (garbage collection)
Arbeitsschritte: Zeigerverfolgung und Markierung besetzter Speicherbereiche  Speicherkarte Herstellung eines Adressbuchs (alte Adressen, neue Adressen) Zeigertransformation (auf neue Adressen) Komprimierung des Speichers (Auslassung von Müllbereichen)

115 Parameterübergaben Referenzaufruf (call by reference):
PROC del(VAR t: Elem;...); Befehlsfolgen: BEGIN ...t := ...END; - Berechnung  Abspeicherung von  auf del(T,...); Platz von t T t LD LD  DB aufrufende Prozedur DB von del

116 Werteaufruf (call by value):
PROC del1 (k: Key;...); Befehlsfolgen: BEGIN...z := k;...END; - Berechnung von w aus a del1(a,...); Abspeicherung von k w auf Platz von k LD w w Wert von a DB von del1

117 Werte-Resultatsaufruf (call by value-result):
Kombination von call by reference und call by value mit Änderung des aktuellen Parameters erst bei Rückkehr (zusätzlicher Umspeicherungsbefehl) T t LD w LD  w Aufruf LD w´ LD  w´ Rückkehr DB aufrufende Prozedur DB aufgerufene Prozedur

118 Namensaufruf (call by name):
Beispiele: ALGOL 60 procedure p(x); integer x; begin ... i := 2; x := 9; ... end; array a[1 : 9]; Realisierung: integer i; begin ... i := 2; a[i] := 9; i := 1; p(a[i]); end

119 procedure R(X, I); begin I := 2; X := 5; I := 3; X := 1 end; ... R(B[J * 2], J); Realisierung: begin J := 2; B[J * 2] := 5; J := 3; B[J * 2] := 1 end

120 Konkreter Syntaxbaum – abstrakter Syntaxbaum Beispiel: Ausdruck 5 * a
Konkreter Syntaxbaum Abstrakte Syntaxbäume <int expr> * <term> num(5) id(a) <term> <int op> <elem> <elem> * <var> * num(5) id(a) <num> a 5

121 Quadrupel (Dreiadresscode)
Allgemeine Form: [<Operator>, <Operand1>, <Operand2>, <Resultat>] mit Operand, Resultat: - Bezeichner (deklarierte oder temporäre Variable) - Zahl (Konstante, Sprungziel) - leer (ohne Bedeutung)

122 Unbedingter Sprung: [ujp, <Marke>]
Ausdrücke: [<Operator>, <Variable/Konstante>, <Variable/Konstante>, <temporäre Variable>] Beispiel: [add-int, t1, t2, h] Zuweisung: [sto-T, <Konstante/Variable>, , <Variable>] , T Typ Beispiel: [sto-int, x, , y] Unbedingter Sprung: [ujp, <Marke>] Bedingter Sprung: [fjp, <Variable>, <Marke>] Ausführung des Sprungs zur Anweisung mit der Marke, wenn der Wert der Variablen false ist

123 If-Anweisung IF e THEN st1 ELSE st2 FI:
Quad(e) Quadrupel zur Berechnung von e; Wert von e wird h1 zugewiesen [fjp, h1, l1] Quad(st1) Quadrupelfolge für st1 [ujp, l2] l1: Quad(st2) Quadrupelfolge für st2 l2: ... Andere Darstellung von Marken: [label, <Marke>]

124 Beispiel: IF a < b THEN a := a + 1 ELSE b := b + 1 FI [les-int, a, b, h1] [fjp, h1, l1] [add-int, a, 1, h1] [sto-int, h1, a] [ujp, l2] l1: [add-int, b, 1, h1] [sto-int, h1, b] l2: ...

125 Tripel (Binärbaum) Allgemeine Form:
(<Operator>, <Operand1>, <Operand2>) Repräsentation des Ergebnisses durch das Tripel selbst Graphische Darstellung: Operator Operand Operand2

126 Beispiel: IF a < b THEN a := a + 1 ELSE b := b + 1 FI (1) (les-int, a, b) (2) (fjp, (1), l1) (3) (add-int, a, 1) (4) (sto-int, a, (3)) (5) (ujp, l2) l1: (6) (add-int, b, 1) (7) (sto-int, b, (6)) l2: (8) ...

127 Erzeugung von Zwischensprachrepräsentationen
Methoden: Aufruf semantischer Routinen in Verbindung mit syntaktischer Analyse Verwendung attributierter Grammatiken Verwendung attributierter Translationsgrammatiken Baumtransformation

128 Speicherbedarf: Die Befehle ldc i, ldc a, ind i, add i,
Beispiel: Voraussetzungen: Bezeichnungen: P Feld für P-Code mit Zeiger p auf nächste Eintragstelle, S Analysekeller mit Spitze i Speicherbedarf: Die Befehle ldc i, ldc a, ind i, add i, mul i, neg i benötigen (kodiert) nur je 1 Speicherplatz. Bezeichner und Konstanten brauchen 2 Speicherplätze (Kenncode, Adresse in entsprechender Tabelle). Regeln: <Z> ::= <E> <E> ::= <T>

129 <E> ::= <E> + <T>
P[p] := ´ add i´; p := p + 1; P[p] := ´;´; p := p + 1; <E> ::= - <T> P[p] := ´ neg i´; p := p + 1; P[p] := ´;´; p := p + 1; <T> ::= <F> <T> ::= <T> * <F> P[p] := ´ mul i´; p := p + 1; P[p] := ´;´; p := p + 1;

130 <F> ::= <Bez>
P[p] := ´ ldc a´; p := p + 1; P[p] := S[i]; p := p + 2; P[p] := ´;´; p := p + 1; P[p] := ´ ind i´; p := p + 1; P[p] := ´;´; p := p + 1; <F> ::= <Kon> P[p] := ´ ldc i´; p := p + 1; P[p] := S[i]; p := p + 2; P[p] := ´;´; p := p + 1; 9 <F> ::= (<E>)

131 Beispiel: Syntaxanalyse und Erzeugung von P-Code Ausdruck: a * (b + 5)
Tokenfolge (symbolisch): Beza * ( Bezb + Kon5) Analysekeller S Regel P[p] Beza 7 ldc a a; ind i; <F> 5 <T> * (Bezb 7 ldc a b; ind i; <T> * (<F> 5, 2 <T> * (<E> + Kon5 8 ldc i 5; <T> * (<E> + <F> 5 <T> * (<E> + <T> 3 add i; <T> * (<E>) 9 <T> * <F> 6 mul i <T> 2, 1 <Z>

132 Beispiel: vorheriges Beispiel unter Verwendung einer
attributierten Grammatik Attribute: P synthetisiert P-Code I synthetisiert Bezeichner K synthetisiert Konstante Syntaktische Regeln: s.o. Semantische Regeln: P(<Z>) := P(<E>) P(<E>) := P(<T>) P(<E>0) := CONCAT(P(<E>1), P(<T>), ´add i;´)

133 P(<E>) := CONCAT(P(<T>), ´neg i;´)
5 P(<T>) := P(<F>) 6 P(<T>0) := CONCAT(P(<T>1), P(<F>), ´mul i;´) 7 P(<F>) := CONCAT(´ldc a ´, I(<Bez>), ´; ind i;´) 8 P(<F>) := CONCAT(´ldc i ´, K(<Kon>), ´;´) 9 P(<F>) := P(<E>)

134 Beispiel: Z ABCDE E T ABCDE T * F BCD F A ( E BCD ) Bez a E + T
A ldc a a; ind i; B ldc a b; ind i; T F C C ldc i 5; D add i; F B Kon 5 E mul i; Bez b

135 Beispiel: Attributierte Translationsgrammatik für arithmetische
Beispiel: Attributierte Translationsgrammatik für arithmetische Ausdrücke <Z>x  <E>p x := p <E>x  <T>p x := p <E>x  <E>q + <T>r ADDy,z,p <x,p> := NEWT; y := q; z := r <E>x  - <T>q NEGy,p <x,p> := NEWT; y := q <T>x  <F>p x := p <T>x  <T>q * <F>r MULTy,z,p <x,p> := NEWT; y := q; z := r

136 <F>x  <Bez>p x := p
<F>x  <Kon>p x := p <F>x  (<E>p) x := p Attributwerte: Speicheradressen <a, b> :=NEWT: a und b wird die Adresse eines freien Speicherplatzes im Speicher T zugewiesen Translation (ohne Attribute): Bez * (Bez + Kon)  ADD MULT

137 Codeerzeugung im engeren Sinne
Arten von Zielcode: Maschinenprogramm mit absoluten Adressen (Load-and-go-Compiler) Maschinenprogramm mit relativen Adressen (relocatable Code)  Bearbeitung vor Abarbeitung: - Zusammenstellung unabhängig voneinander übersetzter Programmkomponenten mit externen Referenzen aufeinander zu einem Lademodul (load module) - Auflösung der externen Referenzen durch Binder (linker) - Überführung in absolut adressiertes, ausführbares Programm durch Ladeprogramm (loader)

138 Programm in Assemblersprache  Notwendigkeit eines Assemblerlaufes
Programm in Programmiersprache einer abstrakten Maschine  zweistufige Übersetzung: Quellsprache  Sprache der abstrakten Maschine  Zielsprache Beispiel: Übersetzung von Pascal in P-Code (Code der P-Maschine) und Übersetzung des P-Codes in Zielsprache

139 Übersetzung Zwischensprache – Zielsprache Grundlegende Techniken
Voraussetzungen: Befehle der Zielmaschine LOAD R O <O>  R STORE R O <R>  O STORE O1 O2 <O1>  O2 ADD-I R O <R> + <O>  R SUB-I R O <R> - <O>  R <a> Inhalt von Speicherplatz a  a Abspeicherung auf Speicherplatz a

140 R Registeradresse (im Falle 1 Registers ACC) O kann sein: Registeradresse <Registeradresse> Hauptspeicheradresse <Hauptspeicheradresse> = Konstante (Direktoperand) STACK Adresse der Spitze des Kellerspeichers

141 Beispiel: Tabellengesteuerte Codeerzeugung
Voraussetzungen: Übersetzung aus Tripeldarstellung in Befehle obiger Zielmaschine gen(a) erzeugt Befehl a code(t) vertritt Befehlsfolge, die durch Übersetzung des Teilbaums t entstand LB linker Teilbaum RB rechter Teilbaum Eine Variable in den erzeugten Befehlen vertritt den ihr im Hauptspeicher zugeordneten Speicherplatz.

142 Tabelle für SUB-I (bzw. DIV-I)
Variable/Konstante Unterbaum Var. gen( LOAD ACC LB ) code( RB ) / gen( SUB-I ACC RB ) gen( STORE ACC STACK ) Kon. gen( LOAD ACC LB ) gen( SUB-I ACC STACK ) Un code( LB ) code( RB ) ter gen( SUB-I ACC RB ) gen( STORE ACC STACK ) ba code( LB ) um gen( SUB-I ACC STACK )

143 Tabelle für ADD-I (bzw. MUL-I)
Variable/Konstante Unterbaum Var. gen( LOAD ACC LB ) code( RB ) / gen( ADD-I ACC RB ) gen( ADD-I ACC LB ) Kon. Un code( LB ) code( LB ) ter gen( ADD-I ACC RB ) gen( STORE ACC STACK ) ba code( RB ) um gen( ADD-I ACC STACK )

144 Tabelle für Zuweisung Variable/Konstante Unterbaum
Var. gen( STORE RB LB ) code( RB ) gen( STORE ACC LB ) Un code( LB ) code( RB ) ter gen( STORE RB <ACC> ) gen( STORE ACC STACK ) ba code( LB ) um gen( STORE STACK <ACC>)

145 Beispiel: Zuweisung h := a * ((c + 5 * a) – (c * d)) Tripel (mul-int, 5, a) (add-int, c, (1)) (mul-int, c, d) (sub-int, (2), (3)) (mul-int, a, (4)) (sto-int, (5), h)

146 Tripel als Binärbaum := (6) h * (5) a - (4) + (2) * (3) c * (1) c d 5 a

147 Erzeugte Befehlsfolgen
LOAD ACC =5 code((1)) code((4)) code((5)) MUL-I ACC a MUL-I ACC a code((1)) code((2)) code((5)) code((6)) ADD-I ACC c STORE ACC h LOAD ACC c code((3)) MUL-I ACC d code((3)) code((4)) STORE ACC STACK code((2)) SUB-I ACC STACK

148 Generatoren für Codegeneratoren Verwendung von Baumgrammatiken
Vorgehensweise: Beschreibung der Codeerzeugung: - Regeln der Baumgrammatik beschreiben die Zwischensprache: <Baumknoten> ::= <Baummuster> - Zuordnung von Schablonenfolgen für Erzeugung der Zielsprachbefehle zu Regeln

149 Erzeugung des Codegenerators aus vorheriger Beschreibung
Codeerzeugung durch Codegenerator: - Überdeckung des Baums zum Zwischensprachprogramm durch Baummuster (in Form von Termen); Auflösung von Mehrdeutigkeiten durch Kostenfunktion - Erzeugung von Zielcode aus Schablonenfolgen gemäß Überdeckung

150 Beispiel: Baumgrammatikregeln mit Schablonen
1 r.2 ::= word( d.1 ) { LOAD R.2 D.1 } 2 r.1 ::= iadd( r.1, r.2 ) { ADD-I R.1 R.2 } 3  ::= store( word( d.1 ), r.2 ) { STORE R.2 D.1 } r.i Registeradresse; d.i Hauptspeicheradresse einer deklarierten Variable word, iadd, store Operatoren der Zwischensprache (Präfixform)

151 Quellsprache Zwischensprache A := A + B store(word(d. a), iadd(word(d
Quellsprache Zwischensprache A := A + B store(word(d.a), iadd(word(d.a), word(d.b))) Überdeckungsbaum store word iadd d.a word word d.a d.b

152 Objektorientierte Compilerstruktur (nach D. A. Watt, D. F
Objektorientierte Compilerstruktur (nach D. A. Watt, D. F. Brown: Programming Language Processors in Java) Compilertreiber Treiber Parser Checker Encoder Scanner

153 Compilertreiber public class Compiler {
public static void compileProgram(...) { //Generierung des Parsers Parser parser = new Parser(...); //Generierung des semantischen Analysators Checker checker = new Checker(...); //Generierung des Zielcodegenerators Encoder generator = new Encoder(...);

154 //Aufruf des Parsers mit Erzeugung des abstrakten Syntaxbaums //AST Program theAST = parser.parse(); //Aufruf des semantischen Analysators mit Dekoration von AST checker.check(theAST); //Aufruf des Codegenerators mit Erzeugung des Zielprogramms generator.encode(theAST); } public static void main(String[] args) {...compileProgram(...); ...}

155 Pakete: AbstractSyntaxTrees: - Klassen zur Definition der AST-Datenstrukturen Je Klasse: Konstruktor zum AST-Aufbau und visitor-Methode zur Verknüpfung mit semantischer Analyse (contextual analyzer) und Codeerzeugung (code generator) - Manipulation der AST-Felder SyntacticAnalyzer: - Parserklassen zur syntaktischen Analyse (Methode des rekursiven Abstiegs) und zur AST-Konstruktion - Hilfsklassen

156 ContextualAnalyzer: Checker-Klasse zur Durchführung der semantischen Analyse CodeGenerator: Encoder-Klasse führt ausgehend vom AST Speicherzuteilung durch und erzeugt Zielcode

157 Parser public class Parser{
//Aktuelles Symbol im analysierten Programm private Token currentToken; //Vergleich aktuelles Symbol – erwartetes Symbol private void accept(byte expectedKind){ if (currentToken.kind == expectedKind) currentToken = scanner.scan(); else Fehlermeldung;}

158 //Nächstes Symbol wird zum aktuellen Symbol
private void acceptIt(){ currentToken = scanner.scan();} //Hilfsmethoden //Parsingmethoden private Program parseProgram(){ //Instanzvariable für AST //Syntaxanalyse für Programme //AST-Erzeugung für Programme return //AST für Programm } ...

159 public Program parse(){ currentToken = scanner
public Program parse(){ currentToken = scanner.scan(); Program progAST = parseProgram(); if (currentToken.kind != Token.EOT) Fehlermeldung return progAST} ... }

160 AST-Konstruktor der Klasse AssignCommand
Abstrakte Klasse für AST: public abstract class AST{...} AST-Knoten als Unterklassen der AST-Klasse Abstrakte Klasse für Expression: public abstract class Expression extends AST{...} Konkrete Klassen mit Konstruktor für AST Beispiel: AST-Konstruktor der Klasse AssignCommand public AssignCommand(Vname V, Expression E){ this.V = V; this.E = E;}

161 Lexikalische Analyse public class Scanner{ ...
private boolean isDigit(char c){...} //true, falls c eine Ziffer ist public Token scan(){ return new Token(currentKind, currentSpelling.toString());} } public class Token{...} //Lexembeschreibungen in Aufbau und Codierung

162 Semantische Analyse Anwendung des visitor pattern: 1
Semantische Analyse Anwendung des visitor pattern: 1. Einrichtung einer Schnittstelle Visitor 2. Für jeden konkreten AST einer Unterklasse A Verwendung einer Visitor-Methode visitA 3. Anreicherung der abstrakten AST-Klasse mit der visit-Methode zum Besuch von AST-Knoten 4. Implementation von visit in jeder Unterklasse 5. Implementation der eigentlichen semantischen Analyseprozeduren im Checker (semantischer Analysator)

163 Schnittstelle Visitor
public interface Visitor{ //visitA-Methoden public Object visitProgram(Program prog, Object arg); ... public Object visitAssignCommand(AssignCommand com, Object arg);}

164 Implementierung von Visitor in Checker
public final class Checker implements Visitor{ //Symboltabelle private IdentificationTable idTable; //Visitor-Methoden public Object visitAssignCommand(Assigncommand com, Object arg){ Type vType = (Type) com.V.visit(this, null); Type eType = (Type) com.E.visit(this, null); if(! eType.equals(vType)) Fehlermeldung return null; }

165 ... //Start der semantischen Analyse public void check(Program prog){ //Initialisierung der Symboltabelle idTable = new IdentificationTable(); prog.visit(this, null); }

166 Erweiterung der AST-Klasse
public abstract class AST{ ... public abstract Object visit(Visitor v, Object arg); } Implementierung von visit in den AST-Unterklassen public class A extends ...{ public Object visit(Visitor v, Object arg){ return v.visitA(this, arg);}

167 Codeerzeugung Nutzung des visitor patterns mit Implementierung der Visitor-Methoden in der Klasse Encoder: public final class Encoder implements Visitor{ ... //Visitor-Methoden public Object visitAssignCommand(AssignCommand com, Object arg){ com.E.visit(this, arg); encodeAssign(com.V); return null;} public void encode(Program prog){ prog.visit(this, null);} }


Herunterladen ppt "Übersetzertechnik (in Arbeit!!!)"

Ähnliche Präsentationen


Google-Anzeigen