Compilerbau. Bachelor-Programm. im SoSe Prof. Dr. Joachim Fischer Dr. Klaus Ahrens Dipl.-Inf. Ingmar Eveslage.

Ähnliche Dokumente
1 Attributierte Grammatiken. 2 Zyklische AG. 3 Codeerzeugung mit AGs. Zusatzfolien Semantische Analyse Wintersemester 2008/09 1 / 28

Compilerbau. Bachelor-Programm. im SoSe Prof. Dr. Joachim Fischer Dr. Klaus Ahrens Dipl.-Inf. Ingmar Eveslage.

Kapitel 5: Semantische Analyse

SYNTAXGESTEUERTE ÜBERSETZUNG

Praktikum Compilerbau Sitzung 4 Abstrakter Syntaxbaum

Zwischencode-Erzeugung. 2. Juni 2009

Kapitel 4. Attributierte Grammatiken. Attributierte Grammatiken Wintersemester 2009/10 1 / 64

Kapitel 4. Attributierte Grammatiken. Attributierte Grammatiken Sommersemester / 66

Compilerbau für die Common Language Run-Time

Inhalte der Vorlesung. 6. Syntaxgesteuerte Übersetzung. Attributierter Syntaxbaum. 6. Syntaxgesteuerte Übersetzung

Attributierte Grammatiken

7. Optimierung. Verschiedene Hilfsmittel zur Entscheidung der Optimierungsfrage:

Compilerbau. Bachelor-Programm. im SoSe Prof. Dr. Joachim Fischer Dr. Klaus Ahrens Dipl.-Inf. Ingmar Eveslage.

Compilerbau. Bachelor-Programm. im SoSe Prof. Dr. Joachim Fischer Dr. Klaus Ahrens Dipl.-Inf. Ingmar Eveslage.

Attributgrammatiken -Spezifikation der statischen Semantik von Programmiersprachen-

Definition Compiler. Bekannte Compiler

Inhalte der Vorlesung. 6. Syntaxgesteuerte Übersetzung. 6. Syntaxgesteuerte Übersetzung. Attributierter Syntaxbaum

Compilerbau. Bachelor-Programm. im SoSe Prof. Dr. Joachim Fischer Dr. Klaus Ahrens Dr. Andreas Kunert Dipl.-Inf.

Einführung in den Compilerbau

5. Syntaxanalyse und der Parser-Generator yacc. 5.5 Aufsteigende Analyse. Absteigende Analyse versus aufsteigende Analyse. 5.5 Aufsteigende Analyse

Definition von LR(k)-Grammatiken

ÜBERPRÜFUNG VON TYPEN

Compilerbau II Skript

Kapitel 5: Syntax-Analyse

Zwischencodeerzeugung Compiler II

Compilerbau. Bachelor-Programm. im SoSe Prof. Dr. Joachim Fischer Dr. Klaus Ahrens Dr. Andreas Kunert Dipl.-Inf.

Shift Reduce Parser (Bottom up Parser) Historie Grundbegriffe Tabellengesteuerter LR(1) Parser Konstruktion der Elementmengen Tabellenkonstruktion

Compilerbau. Bachelor-Programm. im SoSe Prof. Dr. Joachim Fischer Dr. Klaus Ahrens Dipl.-Inf. Ingmar Eveslage.

Übungs- und Praktikumsaufgaben zur Systemprogrammierung Dipl.-Ing. H. Büchter (Lehrbeauftragter) FH-Dortmund WS 2001/2002 / SS 2002

Stratego/XT und ASF+SDF Meta-Environment. Paul Weder Seminar Transformationen Datum:

Implementierung eines LR-Parser-Generators mit syntaktischen Prädikaten

Programmiersprachen und Übersetzer

15. Rekursion. Rekursive Funktionen, Korrektheit, Terminierung, Aufrufstapel, Bau eines Taschenrechners, BNF, Parsen

Topologische Sortierung

3.4 Struktur von Programmen

Methoden zur Interpretation LISPähnlicher. Programmiersprachen. Seminarvortrag / 53 FH AACHEN FACHBEREICH 9 TOBIAS STUMM MATR.-NR.

Kontextfreie Sprachen. Automaten und Formale Sprachen alias Theoretische Informatik. Sommersemester Kontextfreie Sprachen

9.4 Grundlagen des Compilerbaus

Syntax von Programmiersprachen

Grundlagen der Programmierung 3 A

...imbeispiel: Die Konkatenation der Blätter des Ableitungsbaums t bezeichnen wir auch mit yield(t). liefert die Konkatenation: name int + int.

7. Syntax: Grammatiken, EBNF

DieÜbersetzung funktionaler Programmiersprachen

LR-Parser, Shift-Reduce-Verfahren

Shift Reduce Parser (Bottom up Parser) Historie Grundbegriffe Tabellengesteuerter LR(1) Parser Konstruktion der Elementmengen Tabellenkonstruktion

Codegenerierung für Basisblöcke (1)

3 Syntax von Programmiersprachen

Definition von domänenspezifischen Sprachen mit Xtext: Einführung

Inhalte der Vorlesung. Wiederholung. Die Phasen der Übersetzung. 1. Einführung

Semantik von Programmiersprachen SS 2017

Fachseminar Compilerbau

Kapitel 12: Induktive

Struktur des MicroJava-Compilers

Theoretische Grundlagen der Informatik

Inhalt Kapitel 11: Formale Syntax und Semantik

Einführung - Parser. Was ist ein Parser?

4.4 Imperative Algorithmen Prozeduren

Theoretische Grundlagen der Informatik. Vorlesung am 8. Januar INSTITUT FÜR THEORETISCHE INFORMATIK

Offenbar hängt das Ergebnis nur von der Summe der beiden Argumente ab...

3 Syntax von Programmiersprachen

> Parallele Systeme Übung: 4. Übungsblatt Philipp Kegel Wintersemester 2012/2013. Parallele und Verteilte Systeme, Institut für Informatik

9 Compilerbau-Werkzeuge

Stackmaschine; Speicheradressierung

Compilerbau 12. Übungsblatt, Sommersemester 2015 Abgabetermin:

Compilerbau. Bachelor-Programm. im SoSe Prof. Dr. Joachim Fischer Dr. Klaus Ahrens Dr. Andreas Kunert Dipl.-Inf.

3.1 Reservierte Wörter

Das Kontrollfluss-Diagramm für Ò ¼ µ:

4. Lernen von Entscheidungsbäumen

5 BINÄRE ENTSCHEIDUNGS- DIAGRAMME (BDDS)

Werkzeuge zur Programmentwicklung

6 Kontextfreie Grammatiken

5. Die syntaktische Analyse

1 Der Baum. Informatik I: Einführung in die Programmierung 11. Bäume. Bäume in der Informatik. Bäume in der Informatik - Definition.

Grundlagen der Programmierung 3 A

Klassen und Objekte. Klassen sind Vorlagen für Objekte. Objekte haben. Attribute. Konstruktoren. Methoden. Merkblatt

Grundlagen der Programmierung 2 (Comp-A)

{P} S {Q} {P} S {Q} {P} S {Q} Inhalt. Hoare-Kalkül. Hoare-Kalkül. Hoare-Tripel. Hoare-Tripel. Hoare-Tripel

1 Grammar Engineering. 2 Abstrakte Syntax als abstrakte Algebra. 3 LL(1)-Parser. 4 LR Parser. 5 Fehlerbehandlung. 6 Earley Parser

Grundlagen der Programmierung 2 (Comp-A)

Kapitel 4: Datentyp Keller und Schlange

Äquivalente Grammatiken / attributierte Grammatik

Theoretische Grundlagen der Informatik

Automatisches Verstehen gesprochener Sprache

Von der Grammatik zum AST

Deterministische PDAs

Konstruieren der SLR Parsing Tabelle

Übersetzerbau Cluj-Napoca, Rumänien 2007

1 pulsierender Speicher

Phasen eines Compilers. Grundlagen der Programmierung 2. Programm für heute. LR-Parser, Shift-Reduce-Verfahren. Schiebe-Reduziere-Parser

Universität München, Hans-Peter Kriegel und Thomas Seidl Informatik II a[0] a[1] a[2] a[3] a[n 1]

Algorithmen & Programmierung. Ausdrücke & Operatoren (1)

Praktikum Softwareanalyse und -transformation

Ein Fragment von Pascal

Theoretische Informatik I

Lexikalische Programmanalyse der Scanner

1.1 Abstrakte Datentypen 1.2 Lineare Strukturen 1.3 Bäume 1.4 Prioritätsschlangen 1.5 Graphen

30. Parser-Generatoren

Institut für Programmierung und Reaktive Systeme. Java 2. Markus Reschke

Transkript:

Bachelor-Programm Compilerbau im SoSe 2014 Prof. Dr. Joachim Fischer Dr. Klaus Ahrens Dipl.-Inf. Ingmar Eveslage fischer@formatik.hu-berl.de J.Fischer 13.1

Position 6.1 Überblick: Grammatik-basierte Übersetzung Kapitel 1 Compilationsprozess 6.2 Teil I Attribut-Grammatiken Die Programmiersprache Kapitel C 2 Formalismen zur Sprachbeschreibung Teil II 6.3 Methodische Grundlagen Kapitel des 3 Compilerbaus S-attributierte Syntaxdefitionen exikalische Analyse: der Scanner Teil III 6.4 Entwicklung ees efachen Kapitel 4 Transcompilers Syntaktische Analyse: der Parser -attributierte Syntaxdefitionen Kapitel 5 6.5 Parser-Generatoren: Yacc, Bison Syntaxgesteuerte Übersetzungen im Überblick Kapitel 6 Kapitel 7 aufzeitsysteme Kapitel 8 Ausblick: Codegenerierung 6.6 Entwurf syntaxgesteuerter Übersetzungen 6.7 Symboltabelle 13.2

Synthetisierte und ererbte Attribute (Wdh.) nach Unterscheidung der Art der Attributberechnung Y 1.a= f( X.a ) Y 2.a= f( X.a ) Y 3.a= f( X.a ) Token (Termalsymbole) haben nur synthetisierte Attribute ihre Werte werden i.allg. vom Scanner geliefert Startsymbol ererbte Attribute Werte ererbter Attribute werden von oberen Knoten an untere zugewiesen (top-down) hat kee ererbten Attribute X Y 1 Y 2 Y 3 synthetisierte Attribute X Y 1 Y 2 Y 3 X Y 1 Y 2 Y 3 Werte synthetisierter Attribute werden von unten nach oben gereicht (bottom-up) X. a Y 1.a Y 2.a Y 3.a X.a= f(y 1.a,Y 2.a,Y 3.a) 13.3

Implementierung syntaxgesteuerter Defitionen (Wdh.) schwierig Implementierung ees Compilers, der eer beliebigen syntaxgesteuerten Defition folgt Klassifizierung syntaxgesteuerter Defitionen S-attributierte Defitionen (enthalten nur synthetisierte Attribute) können durch - und R-Parser on-the-fly ausgewertet werden synthetisierte Attribute X Y 1 Y 2 Y 3 X.a= f(y 1.a,Y 2.a,Y 3.a) - Parser kann Attribute der Metasymbole (RS) synchron zu den Metasymbolen auf dem Stack festhalten - bei eer Reduktion stehen dann diese Werte zur Verfügung, um die Attribute (S) zu bestimmen 13.4

Beispiel: Typdeklaration von Bezeichern syntaxgerichtete Defition Produktion D T T t T real 1, id id semantische Regel synthetisierte und ererbte Attribute Aufgabe der Regeln: Übernahme der Typformation ees Bezeichners aus eer Typdeklaration die Symboltabelle - Prüfen nicht, ob Bezeichner mehr als emal deklarariert worden ist - Reihenfolge der semantischen Aktionen ist zu bestimmen 13.5

Beispiel: Typdeklaration von Bezeichern Produktion D T T t T real 1, id id semantische Regel. := T.type T.type := teger T.type := real 1. :=. addtype (id.,.) addtype (id.,.) als geerbtes Attribut wird die Typformation top-down-artig im Baum verbreitet Hzufügen der Typformation zum vorhandenen Bezeichner id der Symboltabelle im Blattknoten Bewegung des Parsers T.type= real D.= real Egabe: real p, q, r real.= real, r.= real, p q Die -Knoten sorgen per addtype für die Aufnahme der Typfo des rechten Nachfolgers die Symboltabelle 13.6

Konstruktion des Abhängigkeitsgraphen Vorbereitung - jede Semantikregel wird folgende Funktions-Form gebracht: b:= f(c 1, c 2,..., c k ) synthetisiertes oder geerbtes Attribut von A Attribute der Grammatiksymbole der RS von Regel A a - der (Abhängigkeits-) Graph hat für jedes Attribut 1. een Knoten sowie 2. ee Kante von Knoten c i zum Knoten b, wenn b von c i abhängt 13.7

Konstruktion des Abhängigkeitsgraphen Beispielhafte Annahme: A X Y Produktion synthetisiertes Attribut semantische Regel A.a:= f (X.x, Y.y)... Idee: wird ee solche Regel beim Aufbau des Syntaxbaums benutzt, dann gibt es zwei gerichtete Verbdungen entsprechend der Datenflussrichtung X.x A.a Y.y 13.8

Algorithmus zur Konstruktion des Abhängigkeitsgraphen for each Knoten k syntaxbaum do for each Attribut a of GrammatikSymbol k do konstruiereknoten for a graph; for each Node k syntaxtree do for each semantischeregel b:= f(c 1, c 2,..., c n ) accociated with k do for i:= 1 to n do konstruierekante from Knoten k i of graph to Knoten b; danach: Durchführung eer topologischen Sortierung der Knoten Reihenfolge der Knoten bestimmt Reihenfolge der Attributberechnung 13.9

Beispiel: Konstruktion des Abhängigkeitsgraphen geg.: attributierter Syntaxbaum für Egabe: real p, q, r D 1.Schritt: Identifikation der Attribute im Baum T type real,, q r Produktion D T T t semantische Regel. := T.type T.type := teger p T real 1, id T.type := real 1. :=. addtype (id.,.) id addtype (id.,.) 13.10

Beispiel: Konstruktion des Abhängigkeitsgraphen D 2.Schritt: Eführung zusätzlicher Scheattribute s T type s real p s, s, q r Produktion D T T t T real 1, id semantische Regel. := T.type T.type := teger T.type := real 1. :=. addtype (id.,.) id addtype (id.,.) 13.11

Beispiel: Konstruktion des Abhängigkeitsgraphen D 3.Schritt: Konstruktion von Knoten je Attribut des Abhängigkeitsgraphen T type s real p s, s, q r Produktion D T T t T real 1, id semantische Regel. := T.type T.type := teger T.type := real 1. :=. addtype (id.,.) id addtype (id.,.) 13.12

Beispiel: Konstruktion des Abhängigkeitsgraphen 4. Schritt: Eführung von Kanten (Richtung entspr. Abhängigkeitsbeziehung) D T type s real p s, s, q r Produktion D T T t T real 1, id semantische Regel. := T.type T.type := teger T.type := real 1. :=. addtype (id.,.) id addtype (id.,.) 13.13

Beispiel: Konstruktion des Abhängigkeitsgraphen 4. Schritt: Fortsetzung D T type s real p s, s, q r Produktion D T T t T real 1, id semantische Regel. := T.type T.type := teger T.type := real 1. :=. addtype (id.,.) id addtype (id.,.) 13.14

Beispiel: Konstruktion des Abhängigkeitsgraphen 4. Schritt: Fortsetzung D T type s real p s, s, q r Produktion D T T t T real 1, id semantische Regel. := T.type T.type := teger T.type := real 1. :=. addtype (id.,.) id addtype (id.,.) 13.15

Beispiel: Konstruktion des Abhängigkeitsgraphen 4. Schritt: Fortsetzung D T type s real p s, s, q r Produktion D T T t T real 1, id semantische Regel. := T.type T.type := teger T.type := real 1. :=. addtype (id.,.) id addtype (id.,.) 13.16

Beispiel: Konstruktion des Abhängigkeitsgraphen 4. Schritt: Fortsetzung D T type s real p s, s, q r Produktion D T T t T real 1, id semantische Regel. := T.type T.type := teger T.type := real 1. :=. addtype (id.,.) id addtype (id.,.) 13.17

Beispiel: Konstruktion des Abhängigkeitsgraphen 4. Schritt: Fortsetzung D T type s real p s, s, q r Produktion D T T t T real 1, id semantische Regel. := T.type T.type := teger T.type := real 1. :=. addtype (id.,.) id addtype (id.,.) 13.18

Beispiel: Konstruktion des Abhängigkeitsgraphen fertig Abhängigkeitsbeziehung T type s real, r p s, s q Produktion D T T t T real 1, id semantische Regel. := T.type T.type := teger T.type := real 1. :=. addtype (id.,.) id addtype (id.,.) 13.19

Beispiel: Konstruktion des Abhängigkeitsgraphen 5.Schritt: Berechnungsreihenfolge der Attribute nach topologischer Sortierung ee topologische Sortierung ees gerichteten azyklischen Graphen ist irgendee Reihenfolge m 1, m 2,..., m k der Knoten m i des Graphen, so dass alle Kanten von Knoten ausgehen, die früher der Reihenfolge auftreten, und zu Knoten führen, die später vorkommen k i k j, mit k i vor k j, 13.20

Beispiel: Konstruktion des Abhängigkeitsgraphen T real 4 9 type p s 10 1, 7 s 8 5, q s 2 6 3 r alle Kanten im Graphen führen von eem Knoten mit kleerer Nummer zu eem Knoten höherer Nummer Abhängigkeitsgraph ist topologisch sortiert 13.21

Beispiel: Konstruktion des Abhängigkeitsgraphen Ergebnis: Ausführungsreihenfolge semantischer Aktionen (1) a 1 := "p" (2) a 2 := "q" (3) a 3 := "r" (4) a 4 := real (5) a 5 := a 4 (6) (a 6 :=) addtype(r., a 5 ) (7) a 7 := a 5 (8) (a 8 :=) addtype(r., a 5 ) Attributwerte vom Scanner Attribut a i ist mit Knoten i im Abgängigkeitsgraphen assoziiert (9) a 9 := a 7 (10) (a 10 :=) addtype(r., a 5 ) mit Ausführung der Aktionen: Typ real wird Symboltabelleneträgen für p, q, r übernommen 13.22

Zusammenfassung: Attribut-Abhängigkeitsgraph Graph-Syntax Knoten repräsentieren Attribute Kanten repräsentieren Fluss der Werte wichtige Erkenntnis: Klassifizierung der Attribute duziert Abhängigkeitsgraphen Eigenschaften Graph ist spezifisch für jeden Parse-Baum Größe steht fester Beziehung zur Größe des Parse-Baumes Abhängigkeitsgraph kann zusammen mit Parse-Baum erzeugt werden Forderung: der Graph muss azyklisch se; Testverfahren brauchen exponentielle Zeit (~ Größe der syntaxgesteuerten Defition) Ausführungsreihenfolge Topologische Sortierung auf dem Abhängigkeitsgraphen, um die Attribute zu ordnen dieser Ordnung werden die semantischen Regeln ausgewertet Ordnung hängt sowohl von der Grammatik aus auch von der Egabe ab 13.23

Problem mit beliebigem Mix geerbter und synthetisierter Attribute (Wdh.) kee Garantie für Edeutigkeit der Reihenfolge der Attributberechnung Beispiel: A B A A.s B B.i A.s:= B.i B.i:= A.s + 1 Regeln können i.allg. zirkulär se Ziel: Formulierung von Eschränkungen bzgl. der Abhängigkeiten von Attributberechnungen, die ee Zirkelfreiheit garantieren 13.24

Zwischenfazit Suche nach Möglichkeit zur efachen Implementation von solchen syntaxgesteuerten Defitionen, die neben synthetisierten auch gewisse ererbte Attribute zulassen S-Attributgrammatik zwar effizient berechenbar, unterliegt aber gewissen Eschränkungen (für die Praxis nicht mächtig genug) efache Implementation wäre: natürliche Navigation durch Baumstrukturen: Tiefe-Zuerst (angewendet auf die Baumwurzel) FRAGE: Welche Art von Attributabhängigkeit wird dabei vorausgesetzt? ANTWORT: führt zur Defition von -attributierten syntaxgesteuerten Defitionen 13.25

-Attributgrammatiken Bei Verletzung der ksorientierung kee -Attributgrammatik Defition: -Attributgrammatik X Y 1 Y 2 Y 3 X Y 1 Y 2 Y 3 Sei X Y 1 Y 2 Y n ee Produktionsregel, ab dann hängen die ererbten Attribute von Y i (h(y i )) mit 1 i n nur von (1) den ererbten Attributen des Nicht-Termals X ( h(x) ) und (2) synthetisierten Attributen von Y 1 Y i-1 (also nur von denen, Spezialfall eer -Attributgrammatik ist ee S-Attributgrammatik die lks von Y i stehen) 13.26

-Attribut-Grammatiken und -Parser impliziert folgende (kanonische) Berechnungsreihenfolge für Top-Down-Parser: h(x), h(y 1 ), syn(y 1 ),, h(y n ), syn(yn), syn(x) bei Betreten ees Knoten: Berechnung der ererbten Attribute bei Verlassen ees Knoten: Berechnung der synthetisierten A. syn X h X Y 1 Y 2 Y n syn h syn h syn h syn h Y 1 Y 2 Y i Y n und dies stimmt mit der Auswertungsreihenfolge ees -Parser (Top-Down-Parsg) übere!! steht für ks bedeutet: die Attributformation»fließt«von lks nach rechts (als e natürliches Przip) 13.27

Position Kapitel 1 6.2 Compilationsprozess Attributgrammatiken Teil I Die Programmiersprache Kapitel C 2 6.3 Formalismen zur Sprachbeschreibung S-attributierte Syntaxdefitionen Teil II Methodische Grundlagen des Compilerbaus 6.4 Kapitel 3 Attributierte Syntaxdefitionen mit synthetisierten exikalische Analyse: der Scanner und ererbten Attributen Teil III Entwicklung ees efachen Kapitel 4 Transcompilers 6.5 Syntaktische Analyse: der Parser -attributierte Syntaxdefitionen Kapitel 5 6.6 Parser-Generatoren: Yacc, Bison Verfahren syntaxgesteuerter Übersetzungen im Überblick Kapitel 6 6.1 Überblick: Grammatik-basierte Übersetzung 6.7 Entwurf syntaxgesteuerter Übersetzungen Kapitel 7 aufzeitsysteme Kapitel 8 Ausblick: Codegenerierung 6.8 Drei-Adress-Code-Generierung (eige Aspekte) 6.9 Symboltabelle 13.28

Erkenntnis-1: Bedeutung Attributgrammatiken Zentrales Problem bei der Übersetzung/statischen Analyse: Assoziation von Informationen zu Teilstrukturen des Ableitungsbaums Verwaltung der Informationen beim Aufbau des Baumes Attributgrammatiken als geeignetes Konzept Attribute als Info-Behälter für jedes Grammatiksymbol Beispiel: Typfos, Ausdruckswerte (als Zwischenresulte ees Interpreters) jeder Produktion der Grammatik kann ee Menge von Funktionen als semantische Regel zugeordnet werden Berechnung der Attribute erfolgt aus den Werten von Attributen anderer, der Produktion vorkommenden Symbole 13.29

Erkenntnis-2: Implementierung syntaxgesteuerter Defitionen ~ Art der Attributierung Klassifizierung syntaxgesteuerter Defitionen S-attributierte Defitionen (enthalten nur synthetisierte Attribute) -attributierte Defitionen (enthalten nur synthetisierte u. ererbte Attribute mit Nebenbedgung) können durch R-Parser on-the-fly ausgewertet werden??? als Mehrpass-Compiler (Abhängigkeitsgraph) können durch -Parser on-the-fly ausgewertet werden 13.30

Jetzt genauer Parsertyp Grammatiktyp Attributierungstyp Realisierungsmöglichkeiten /Probleme

Übersetzungsmethoden: on-the-fly Rekursiv-absteigender Parser -Grammatik mit eer -Attributierung (direkte Interpretation möglich) Methode: Funktionen des rekursiv absteigenden Parsers werden erweitert: Tabellengesteuerter Top-Down-Parser -Grammatik mit eer -Attributierung (direkte Interpretation möglich) Bottom-Up-Parser R-Grammatik mit eer S-Attributierung (direkte Interpretation möglich) ererbte Attribute werden zu Funktionsargumenten ihrer Nichttermalsymbole (die aufgerufene Funktion erbt Informationen ihres Aufrufers) synthetisierte Attribute werden von diesen Funktionen als Kollektion zurückgegeben. Bottom-Up-Parser -Grammatik mit eer -Attributierung (direkte Interpretation möglich) 13.32

Methode rekursiv absteigender Parser void A () { /*Choose an A-production, A X 1 X 2 X k ;*/ for ( i:= 1 to k) { if ( X i is a_nontermal ) call procedure X i (); else if (X i = current put symbol a) } } advance put to the next symbol; else /* error */ jetzt: Sematik-Aktionen: on-the-fly Vorbereitung Argumente von A: geerbte Attribute vom A-Caller Return-Wert von A: Kollektion der synthetisierten Attribute von A Funktion hält für jedes Attribut aller Nichttermalsymbole der A-Produktion ee lokale Variable Przip der Verarbeitung Betrachtung der Symbole/Aktionen X der rechten Seite der A-Produktion von lks nach rechts: Sei X e Termalsymbol mit dem synthetisierten Attribut x, dann wird der Wert X.x eer entsprechenden lokalen Variable gespeichert anschließend: Match von X und Aktualisierung der Egabe Sei X e Nichttermal B, erfolgt ee Zuweisung c:= B(b 1, b 2, b n ) mit b i als Variable der geerbten Attribute für B c als lokale A-Variable zur Aufnahme des synthetisierten Attributs von B Sei X ee Aktion, wird der Code kopiert und jede Referenz auf e Attribut wird durch die lokale Variable für dieses Attribut ersetzt 13.33

Beispiel Konstruktion ees rekursiv-absteigenden Parsers mit Auswerter der semantischen Regeln kann nun nach dem Kochrezept umgesetzt werden Produktion E E 1 + T E E 1 - T E T T (E) T number Semantische Regel E.val:= E 1.val + T.val E.val:= E 1.val - T.val E.val:= T.val T.val:= E.val T.val:= number.val Produktion E T {R.i:= T.val} R {E.val:= R.s} R + T {R 1.i:= R.i + T.val} R 1 {R.s:= R 1.s} R - T {R 1.i:= R.i - T.val} R 1 {R.s:= R 1.s} R e {R.s:= R.i} T (E {T.val:= E.val} ) T number {T.val:= number.val} attributierter Baum für 3+5 digit T Tval= 3 digit.lexval=3 lksrekursiv, S-attributiert Bei Entfernung der ksrekursion ändert sich die Attributierung: neues Symbol R mit zwei Attributen: i, s E rechtsrekursiv, -attributiert E.val= 8 + R R.i= 3 R.s= 8 T T.val=5 digit.lexval=5 R 1 R 1.i= 5 + 3 R 1.s= 8 e 13.34

Anwendung der Methode E T {R.i:= T.val} R {E.val:= R.s} Vorbereitung Argumente von A: geerbte Attribute vom A-Caller Return-Wert von A: Kollektion der synthetisierten Attribute von A Funktion hält für jedes Attribut aller Nichttermalsymbole der A-Produktion ee lokale Variable procedure E(): t { t Tval, Eval, Rs, Ri; } Tval:= T(); Ri:= Tval; Rs:= R(Ri); Eval:= Rs; return (Eval); 13.35

Anwendung der Methode E T {R.i:= T.val} R {E.val:= R.s} procedure E(): t { t Tval, Eval, Rs, Ri; } Tval:= T(); Ri:= Tval; Rs:= R(Ri); Eval:= Rs; return (Eval); T hat kee ererbten Attribute Vorbereitung Argumente von A: geerbte Attribute vom A-Caller Return-Wert von A: Kollektion der synthetisierten Attribute von A Funktion hält für jedes Attribut aller Nichttermalsymbole der A-Produktion ee lokale Variable Przip der Verarbeitung Betrachtung der Symbole/Aktionen X der rechten Seite der A-Produktion von lks nach rechts: Sei X e Termalsymbol mit dem synthetisierten Attribut x, dann wird der Wert X.x eer entsprechenden lokalen Variable gespeichert anschließend: Match von X und Aktualisierung der Egabe Sei X e Nichttermal B, erfolgt ee Zuweisung c:= B(b 1, b 2, b n ) mit b i als Variable der geerbten Attribute für B c als lokale A-Variable zur Aufnahme des synthetisierten Attributs von B Sei X ee Aktion, wird der Code kopiert und jede Referenz auf e Attribut wird durch die lokale Variable für dieses Attribut ersetzt 13.36

Anwendung der Methode E T {R.i:= T.val} R {E.val:= R.s} procedure E(): t { t Tval, Eval, Rs, Ri; } Tval:= T(); Ri:= Tval; Rs:= R(Ri); Eval:= Rs; return (Eval); Vorbereitung Argumente von A: geerbte Attribute vom A-Caller Return-Wert von A: Kollektion der synthetisierten Attribute von A Funktion hält für jedes Attribut aller Nichttermalsymbole der A-Produktion ee lokale Variable Przip der Verarbeitung Betrachtung der Symbole/Aktionen X der rechten Seite der A-Produktion von lks nach rechts: Sei X e Termalsymbol mit dem synthetisierten Attribut x, dann wird der Wert X.x eer entsprechenden lokalen Variable gespeichert anschließend: Match von X und Aktualisierung der Egabe Sei X e Nichttermal B, erfolgt ee Zuweisung c:= B(b 1, b 2, b n ) mit b i als Variable der geerbten Attribute für B c als lokale A-Variable zur Aufnahme des synthetisierten Attributs von B Sei X ee Aktion, wird der Code kopiert und jede Referenz auf e Attribut wird durch die lokale Variable für dieses Attribut ersetzt 13.37

Anwendung der Methode E T {R.i:= T.val} R {E.val:= R.s} procedure E(): t { t Tval, Eval, Rs, Ri; } Tval:= T(); Ri:= Tval; Rs:= R(Ri); Eval:= Rs; return (Eval); Vorbereitung Argumente von A: geerbte Attribute vom A-Caller Return-Wert von A: Kollektion der synthetisierten Attribute von A Funktion hält für jedes Attribut aller Nichttermalsymbole der A-Produktion ee lokale Variable Przip der Verarbeitung Betrachtung der Symbole/Aktionen X der rechten Seite der A-Produktion von lks nach rechts: Sei X e Termalsymbol mit dem synthetisierten Attribut x, dann wird der Wert X.x eer entsprechenden lokalen Variable gespeichert anschließend: Match von X und Aktualisierung der Egabe Sei X e Nichttermal B, erfolgt ee Zuweisung c:= B(b 1, b 2, b n ) mit b i als Variable der geerbten Attribute für B c als lokale A-Variable zur Aufnahme des synthetisierten Attributs von B Sei X ee Aktion, wird der Code kopiert und jede Referenz auf e Attribut wird durch die lokale Variable für dieses Attribut ersetzt 13.38

Anwendung der Methode E T {R.i:= T.val} R {E.val:= R.s} procedure E(): t { t Tval, Eval, Rs, Ri; } Tval:= T(); Ri:= Tval; Rs:= R(Ri); Eval:= Rs; return (Eval); Vorbereitung Argumente von A: geerbte Attribute vom A-Caller Return-Wert von A: Kollektion der synthetisierten Attribute von A Funktion hält für jedes Attribut aller Nichttermalsymbole der A-Produktion ee lokale Variable Przip der Verarbeitung Betrachtung der Symbole/Aktionen X der rechten Seite der A-Produktion von lks nach rechts: Sei X e Termalsymbol mit dem synthetisierten Attribut x, dann wird der Wert X.x eer entsprechenden lokalen Variable gespeichert anschließend: Match von X und Aktualisierung der Egabe Sei X e Nichttermal B, erfolgt ee Zuweisung c:= B(b 1, b 2, b n ) mit b i als Variable der geerbten Attribute für B c als lokale A-Variable zur Aufnahme des synthetisierten Attributs von B Sei X ee Aktion, wird der Code kopiert und jede Referenz auf e Attribut wird durch die lokale Variable für dieses Attribut ersetzt 13.39

procedure T(): t { t Tval, Eval, numberval; } if token == "(" then { nexttoken(); } Eval:= E(); Tval:= Eval(); if not (token == ")" ) then else { } error(); else if token == number then { } else error(); nexttoken(); return (Tval); numberval:= lexval; nexttoken(); Tval:= numberval; return (Tval); procedure E(): t { t Tval, Eval, Rs, Ri; } Tval:= T(); Ri:= Tval; Rs:= R(Ri); Eval:= Rs; return (Eval); Produktion E T {R.i:= T.val} R {E.val:= R.s} R + T {R 1.i:= R.i + T.val} R 1 {R.s:= R 1.s} R - T {R 1.i:= R.i - T.val} R 1 {R.s:= R 1.s} R e {R.s:= R.i} T (E {T.val:= E.val} ) T number {T.val:= number.val} procedure R (t Ri): t { t Rs, Tval, R1s, R1i; } if token == "+" then { } nexttoken(); Tval:= T(); R1i:= Ri + Tval; R1s:= R (R1i); Rs:= R1s; return (Rs); else if token == "-" then nexttoken(); Tval:= T(); R1i:= Ri - Tval; R1s:= R (R1i); Rs:= R1s; return (Rs); } else if token == ")" or token == "$" then { } else error(); Rs:= Ri; return (Rs); 13.40

Übersetzungsmethoden: on-the-fly Rekursiv-absteigender Parser -Grammatik mit eer -Attributierung (direkte Interpretation möglich, hausgemacht ) Tabellengesteuerter Top-Down-Parser -Grammatik mit eer -Attributierung (direkte Interpretation möglich) Methode: Hzunahme ees Werte-Kellers (wie bei S-Attributierung und R-Parser) Bottom-Up-Parser R-Grammatik mit eer S-Attributierung (direkte Interpretation möglich, hausgemacht ) aber schwieriger zu verwalten Wertekeller wächst und schrumpft nicht synchron zum Parser-Stack Bottom-Up-Parser -Grammatik mit eer -Attributierung (direkte Interpretation möglich) 13.41

Top-Down-Implementierung -attributierter Syntaxschemata (2) iegt der -attributierten syntaxbasierten Defition ee -Grammatik zugrunde, kann die Implementation (Ausführung der Aktionen) mit eem tabellengesteuerten -Parser erfolgen. Rekords für synthetisierte Attribute ees Nichttermalsymbols werden unterhalb des Nichttermalsymbols/Zustand auf dem Parser-Keller abgelegt, die ererbten Attribute ees Nichttermalsymbols werden synchron mit dem Nichttermalsymbol/Zustand (im Werte-Keller) abgelegt werden. Auch die Aktionen werden im Keller platziert, um die Attribute wie gefordert zu berechnen. wollen wir hier aber nicht weiter vertiefen 13.42

Übersetzungsmethoden: on-the-fly Rekursiv-absteigender Parser -Grammatik mit eer -Attributierung (direkte Interpretation möglich) Tabellengesteuerter Top-Down-Parser -Grammatik mit eer -Attributierung (direkte Interpretation möglich) Bottom-Up-Parser R-Grammatik mit eer S-Attributierung (direkte Interpretation möglich) Bottom-Up-Parser -Grammatik mit eer -Attributierung (direkte Interpretation möglich) Methode: E S-attributiertes Übersetzungsschema kann implementiert werden, wenn alle Aktionen am Ende von Produktionen stehen. Die Aktionen berechnen dabei die synthetisierten Attribute der RS aus den synthetisierten Attributen der S der Regeln. Ist die Ausgangsgrammatik vom Typ R, dann kann dieses Übersetzungsschema auf dem R- Parser-Kellerspeicher umgesetzt werden. 13.43

R-Parser mit S-attributierter Übersetzung %{ #clude <ctype.h> %} %token DIGIT Bison-Notation %% le: expr '\n' {prtf("%d\n", $1); } ; expr: expr '+' expr {$$ = $1 + $3; } term ; term: term '*' factor {$$ = $1 * $3; } factor ; factor: '(' expr ')' {$$ = $2; } DIGIT ; Produktion E n E E 1 + T -Grammatik R-Parser E T T T 1 * F T F F (E) F digit prt(val[tos]) syntaxgesteuerte Defition (S-Attributgrammatik) Semantische Regel val[ntos] := val[tos-2] + val[tos] val[ntos]:= val[tos-2] * val[tos] val[ntos] := val[tos-1] ermöglicht durch ee Erweiterung des Kellerspeichers, bei natürlicher Synchronität von Attribut-Werte-Stack und Parser-Stack zirkuläre syntaxorientierte Defitionen 13.44

Bottom-up-Analyse passt (tuitiv) zur S-Attributierung man arbeitet von unten nach oben Frage ässt sich -Attributberechnung und Bottom-up-Syntaxanalyse trotzdem kombieren? Jetzt R und Verallgemeerung der Methode R-Parser und S-Attributierung Attribute werden parallel zum Zustand e- bzw. ausgekellert Diese wird mächtig genug se, um -attributierte Defitionen, die auf eer (1)-Grammatik aufbauen, on-the-fly zu behandeln

Übersetzungsmethoden: on-the-fly Rekursiv-absteigender Parser: -Grammatik mit eer -Attributierung (direkte Interpretation möglich) Tabellengesteuerter Top-Down-Parser: -Grammatik mit eer -Attributierung (direkte Interpretation möglich) Bottom-Up-Parser R-Grammatik mit eer S-Attributierung (direkte Interpretation möglich) Methode Grammatik-Transformation: Eführung neuer Nichttermalsymbole als Marker Simulation ererbter Attribute durch synthetische Attribute der Marker Bottom-Up-Parser -Grammatik mit eer -Attributierung (direkte Interpretation möglich) 13.46

Konvertierungsprzip Übersetzungsschema A {B.i = f(a.i);} B C ACHTUNG auf den ersten Blick problematisch! Aktionen für M e haben keen Zugriff auf Attribute, die zu Grammatiksymbolen gehören, die nicht zu dieser Produktion gehören Eführung ees Markers M mit zwei Attributen i Kopie von A.i M s Stellvertreter für B.i Übersetzungsschema A M B C M e {M.i=A.i; M.s= f(a.i);} JEDOCH Implementation der Aktionen auf eem R-Parser- Kellerspeicher werden sehen, dass diese Attribute tatsächlich noch auf dem Keller liegen ATERNATIVER ANSATZ A müsste vorsorglich dafür sorgen, dass für andere Symbole (hier M), die die ererbten Attribute benötigen, diese globalen Speichern bereit gestellt werden Wie kommt man an diese Information? 13.47

Stack-Indizierung Yacc/Bison (bereits bekannt) jedes Grammatiksymbol hat im Rahmen eer Regelanwendung een semantischen Wert erreichbar über $i Notation Beispiel E E + E {$$ = $1 + $3;} E * E {$$ = $1 * $3; } num {$$ = $1;} ; neben Parser-Keller (Zustandskeller) gibt es een synchronen Wertekeller die Pseudovariable $i bezieht sich auf: tos ( RS -i) im Wertekeller $$ bezieht sich auf Wert des Nichttermalsymbols der S 13.48

Stack-Indizierung Yacc/Bison (neu) $i ist auch für i 0 defiert bezieht sich auf Wertekellerpositionen bevor die aktuelle Regel zur Anwendung gekommen ist ACHTUNG: natürlich muss der Kontext beim Zugriff bekannt se $0 F : E B + E { $$ =... } ; B : /* empty */ { temp_val= $0 ;} $0 refers to value of F the previous production 13.49

Zwischenfazit zwei Möglichkeiten Bison a) direkter Zugriff auf Kellerposition mit Index- u. Typunsicherheit b) Verwendung globaler Größen geg. -attributierte syntaxgesteuerte Defition (auf Basis eer -Grammatik) dann lässt sich bei Grammatik-Adaption die Defition auch für ee R-Analyse esetzen Methode (1) Starte mit Übersetzungsschema, das egebettete Aktionen vor dem Nichttermal platziert, um ererbte Attribute zu berechnen: A a {a} b (2) Führe jeweils verschiedene Nichttermalsymbole M zur Markierung der Position der zu verschiebenden egebetteten Aktionen e: A a M b Dabei ist jedes M nur mit eer Produktion auszustatten: M e, wobei die Aktionen a ans Ende der rechten Seite platziert werden: M e {a} (3) Modifiziere dabei die Aktion a zu a', so dass alle Attribute von A oder Attribute von Symbolen aus a, die von a benötigt werden, als ererbte Attribute von M kopiert werden Berechne die Attribute so wie a, aber mache diese zu synthetisierten Attributen von M 13.51

nachdem Syntaxbäume aufgebaut sd, kann man sowohl Analyse- als auch Synthese-Aufgaben realisiert werden Ziel des nächsten Unterkapitels: semantische Aktionen zur Baumbearbeitung mit dem Nebeneffekt: Ausgabe von 3-Adress-Code (als beliebte Zwischencode-Form für Back-End-Tools)

Zwischencode-Erzeugung Symboltabellenverwaltung Quellprogramm lexikalische Analyse Syntaxanalyse semantische Analyse ZwC- Generator Zwischencode Fehlerbehandlung Anforderungen an den Zwischencode - leicht zu erzeugen - leicht transformierbar den letztendlichen Zielcode durch das Backend Zwischencode kann verschiedene Formen haben. temp1:= ttoreal(60) temp2:= id3 * temp1 temp3:= id2 + temp2 id1 := temp3 13.53

Position Kapitel 1 6.2 Compilationsprozess Attributgrammatiken Teil I Die Programmiersprache Kapitel C 2 6.3 Formalismen zur Sprachbeschreibung S-attributierte Syntaxdefitionen Teil II Methodische Grundlagen des Compilerbaus 6.4 Kapitel 3 Attributierte Syntaxdefitionen mit synthetisierten exikalische Analyse: der Scanner und ererbten Attributen Teil III Entwicklung ees efachen Kapitel 4 Transcompilers 6.5 Syntaktische Analyse: der Parser -attributierte Syntaxdefitionen Kapitel 5 6.6 Parser-Generatoren: Yacc, Bison Verfahren syntaxgesteuerter Übersetzungen im Überblick Kapitel 6 6.1 Überblick: Grammatik-basierte Übersetzung 6.7 Entwurf syntaxgesteuerter Übersetzungen Kapitel 7 aufzeitsysteme Kapitel 8 Ausblick: Codegenerierung 6.8 Drei-Adress-Code-Generierung (eige Aspekte) 6.9 Symboltabelle 13.54

Drei-Adressbefehle (beliebte Zwischencodeform) x = y op z x = op y // op bärer Operator, x, y, z Adressen // op unärer Operator allg. Format x = y // Kopierbefehl goto if x goto if False x goto // unbedgter Sprung zur Marke im Programm // bedgte Sprünge Marke kann jedem Befehl als Präfix : hzugefügt werden if x relop y goto // bedgter Sprung mit Vergleich mit relop als Vergleichsoperator x = y[i] y[i] = x //Kopierbefehl mit Indizes x = &y x = *y *y= x // Kopierbefehl mit Adressrechnung 13.55

Beispiel-1: DreiAdress-Code (FOR-Anweisung) FOR-Schleife a=3; b=4; for(i=0;i<n;i++){ a=b+1; a=a*a; } c=a; 3-Adresscode a=3; b=4; i=0; 1: VAR1=i<n; if(var1) goto 2; goto 3; 4: i++; goto 1; 2: VAR2=b+1; a=var2; VAR3=a*a; a=var3; goto 4 3: c=a; 13.56

Beispiel-2: DreiAdress-Code (WHIE-Anweisung) WHIE-Schleife a=3; b=4; i=0; while(i<n){ a=b+1; a=a*a; i++; } c=a; 3-Adresscode a=3; b=4; i=0; 1: VAR1=i<n; if(var1) goto 2; goto 3; 2: VAR2=b+1; a=var2; VAR3=a*a; a=var3; i++; goto 1 3: c=a; 13.57

Vorbereitung zur Übersetzung DreiAdress-Code jedes Nichttermalsymbol der WHIE-Anweisungs-Regel erhält für Code-Generierung folg. Attribute: code: enthält den generierten 3ACode true: enthält Marke für Sprung mit assoziiertem Boolean-Ausdruck (falls true) false: (falls false) next: enthält Marke für Statement, das aus dem Nichttermalsymbol abgeleitet wird benutzte Funktion: newabel(): liefert bei jedem Aufruf neue Marke gen( ): generiert Code (als Strg), der als Parameter übergeben wird 13.58

Beispiel: WHIE-Statement-Übersetzung DreiAdress-Code S if C then S1 S if C then S1 else S2 S while C do S1 S assign-stmt P S { } S.next:= newabel ; P.code:= S.code gen (S.next : ) ; Bem.: konzentrieren uns lediglich auf den Programmfluss, (blenden hier Zwischencode für andere Teile aus) lokalevariable S while E do S1 { 1:= newabel ; 2:= newabel ; C.false := S.next ; S1.next := 1 ; C.true := 2 ; S.code := gen(1, : ) C.code gen(2, : ) S1.code ; } code true false next 13.59

Attributierung zur Code-Repräsentation Ann.: Unsere code-attribute der Meta-Symbole sd alle vom Typ strg (anschaulich, aber praktisch effizient) eigentliche Anforderung: Werte von code müssen sich nur efach verketten lassen (so wäre przipiell ee iste beliebigen Typen denkbar) next true false code Bem.: praktisch teressantere ösung wäre die sequentielle Ausgabe der Code- Stücke ee Datei (zeigen wir später) 13.60

Implementierung attributierter Übersetzungsschemata Problem: R-Grammatik + -attr.syntaxdef 1 : E-Code (next, 2) 2 : S1-Code (1) next: S while ( C ) S1 1= newabel(); 2= newabel(); S1.next= 1; C.false= S.next; C.true=2; S.code= gen(1, : ) C.code gen(2, : ) S1.code Behandlung der Marken 1, 2 diese sd Variablen, kee Attribute (so wie next) Übersetzungsschema ist zu transformieren S while ( { 1=newabel(); 2= newabel(); C.false= S.next; C.true=2; } C ) {S1.next= 1; } S1 {S.code= gen(1, : ) C.code gen(2, : ) S1.code } S while ( M C ) N S1 {S.code= gen(1, : ) C.code gen(2, : ) S1.code } M e {1=newabel(); 2= newabel(); C.false= S.next; C.true=2; } N e {S1.next= 1; } 13.61

Konvertierungsprzip (Ernerung) Übersetzungsschema A {B.i = f(a.i);} B C Eführung ees Markers M mit zwei Attributen i Kopie von A.i M s Stellvertreter für B.i Übersetzungsschema A M B C M e {M.i=A.i; M.s= f(a.i);} Wie kommt man an diese Information? 13.62

Schritte des R-Parsers (1) tos Egabe while ( C ) S1? Kellerbelegung unmittelbar vor der Erkennung von while S.next? tos while Sprungmarke als symbolisches Ende der aktuellen Anweisung S existiert bereits, wurde aber noch nicht im generierten Code verwendet!!! S.next Kellerbelegung sobald while aktuelles Egabe-Token wird man kennt zwar nicht den darunter liegenden Zustand bzw. das entspr. Nichttermalsymbol, aber es hat e synchron gespeichertes Datenrekord, das auf eer festen Position Form von S.next vorliegt 13.63

Schritte des R-Parsers (2) Egabe while ( C ) S1 R-Parser weiß, dass - es sich nach esen von ( um ee while-anweisung handelt - und wird dieser Situation ee Reduktion von e nach M durchführen - danach wird der Egabecode, der später C ergibt, analysiert? S.next while feste tos Positionen ( M C.true C.false 1 2 tos 2 S.next S while ( M C ) N S 1 { } M e { } N e { } M-Aktionen 1:= newabel(); 2:= newabel(); C.false:= stack[tos-3].next; C.true:= 2; 1 : C-Code (next, 2) 2 : S1-Code (1) next: ursprüngliche Aktionen zur Berechnung der ererbten Attribute von C werden jetzt zu Aktionen von M /*S.next*/ 13.64

Schritte des R-Parsers (3) tos tos? while ( M C ) N S.next C.true 2 C.code S1.next C.false 1 S.next S1.next= stack[tos-3].1; 2 N e { } Ann.: nächste Egabesymbole nach ( (Bool-Ausdruckskomponenten) können zu C reduziert werden; das synthetisierte Attribut C.code ist im Datenrecord von C enthalten (wird erzeugt) ) wird auf den Stack geschoben Parser weiß, dass er noch immer ee while-anweisung bearbeitet (-Grammatik) und wird e zu N reduzieren und die zugeordnete Aktion ausführen (hterlegt für kommende S1-Analyse 1 als Rücksprungmarke) 13.65

Schritte des R-Parsers (3) Egabe while ( C ) S1 tos? S.next 1 : C-Code (next, 2) 2 : S1-Code (1) next: while S ( M C.true C.false S1-Analyse + Code-Erzeugung (synthetisiert S1.code) Parser-Reduktion: S while ( M C ) N S1 { } Ausführung von { } 1 2 2 S.next C C.code ) N S1.next 1 tempcode:= gen(stack[tos-4].1, : ) stack[tos-3].code label stack[tos-4].2 stack[tos].code tos:= tos-6 stack[tos].code:= tempcode? S.next while tos S.code tempcode S while ( M C ) N S 1 { } M e { } N e { } S.next= abel für Sprungmarke als symbolischer Anfang der nächsten Anweisung S (== Ende der while-anweisung) S1 S1.code 13.66