KOMPILÁTORY: Syntaxou riadený preklad Jana Dvořáková dvorakova@dcs.fmph.uniba.sk
Čo je syntaxou riadený preklad? Celý kompilátor je riadený procesom parsovania Syntaxou riadený preklad = prepojenie syntaktickej analýzy s nasledujúcimi fázami kompilácie syntaktická analýza syntaxou riadený preklad ďaľšie fázy K pravidlám gramatiky sú priradené akcie Generovanie kódu Ukladanie informácií do tabul ky symbolov Generovanie chybových hlásení Kontrola konzistencie typov..a d alšie Notácia 1 Syntaxou riadená definícia Abstraktná notácia 2 Prekladová schéma Podobná syntaxou riadenej definícií, ale viac implementačných detailov (poradie vykonania akcií)
Realizácia akcií 1 Počas parsovania Jeden prechod, používa sa v kompilátoroch Bez explicitnej konštrukcie stromu odvodenia Možné pre špeciálne typy syntaxou riadených definícií - Napr. L-atribútové definície zahŕňajú prakticky všetky syntaxou riadené definície, ktoré sa dajú realizovat bez explicitnej konštrukcie stromu odvodenia 2 Prechádzaním explicitne zostrojeného stromu odvodenia vstupný reťazec strom odvodenia graf závislostí poradie vyhodnocovania akcií
Syntaxou riadená definícia (SRD) Abstraktná špecifikácia syntaxou riadeného prekladu Vznikne rozšírením CF gramatiky vstupného jazyka o 1 Atribúty Priradené k symbolom gramatiky X.x = atribút x symbolu X Nesú d al šiu informáciu o danom symbole - Hodnota atribútu: ret azec, číslo, typ, miesto v pamäti,.. 2 Sémantické pravidlá Priradené k pravidlám gramatiky B.b := f (C 1.c 1,..., C k.c k ) Slúžia pre výpočet atribútov symbolov v rámci jedného pravidla gramatiky Môžu obsahovat funkcie s bočným efektom (napr. vypísanie hodnoty na výstup, zmena hodnoty globálnej premennej) SRD bez funkcií s bočným efektom = atribútová gramatika
Vrchol v strome odvodenia = záznam s pol ami symbol gramatiky atribút 1 atribút 2 Atribúty Symbol gramatiky je v prvom poli záznamu a je návestím vcholu Atribúty sú uložené v d alších poliach Typy atribútov 1 Syntetizované atribúty Hodnoty sa vypočítajú podl a hodnôt atribútov detí V praxi často používané 2 Dedičné atribúty Hodnoty sa vypočítajú podl a hodnôt atribútov rodičov a súrodencov Vhodné na vyjadrenie závislosti konštrukcií na kontexte, v ktorom sa nachádzajú Ak B.b := f (C 1.c 1,..., C k.c k ) hovoríme, že B.b je závislý na C 1.c 1,..., C k.c k Strom odvodenia s vypočítanými hodnotami atribútov sa nazýva anotovaný strom odvodenia Terminály majú iba syntetizované atribúty a poč. symbol gramatiky má iba dedičné atribúty
Syntaxou riadená definícia Príklad 1 - kalkulačka Pravidlo gramatiky Sémantické pravidlo L E n print(e.val) funkcia s bočným efektom E E 1 + T E.val := E 1.val + T.val E T E.val := T.val T T 1 F T.val := T 1.val F.val T F T.val := F.val F ( E ) F.val := E.val F digit F.val := digit.lexval hodnota atribútu je poslaná lexikálnym analyzátorom X.val je syntetizovaný atribút pre X {E, T, F } s celočíselnou hodnotou SRD iba so syntetizovanými atribútmi sa nazýva S-atribútová definícia a vždy sa dá vyhodnotit na strome odvodenia prechodom zdola-nahor
Syntaxou riadená definícia Príklad 2 - deklarácie Pravidlo gramatiky D T L ; T int T real L L 1, id L id Sémantické pravidlo L.in := T.type T.type := integer T.type := real L 1.in := L.in addtype(id.entry, L.in) addtype(id.entry, L.in) L.in je dedičný atribút T.type je syntetizovaný atribút Nedá sa vyhodnotit jednoducho ako S-atribútové definície
Znázorňuje závislosti medzi atribútami Graf závislostí Orientovaný graf D = (V, E) V - množina vrcholov, atribúty symbolov gramatiky E - množina hrán, X.x Y.y E ak Y.y je závislý na X.x for každý vrchol n v strome odvodenia do for každý atribút a symbolu gramatiky v n do vytvor vrchol pre a; for každý vrchol n v strome odvodenia do for každé sémantické pravidlo b := f (c 1,..., c k ) asociované s pravidlom v n do for i := 1 to k do pridaj hranu z c i do b Topologické triedenie D Usporiadanie vrcholov m 1,..., m k, také, že platí: Ak existuje hrana m i m j potom m i je pred m j. Získame platné poradie vyhodnocovania atribútov (ak D nemá cyklus)
Metódy vyhodnocovania atribútov 1 Metódy stromu odvodenia Strom odvodenia sa zostrojí explicitne, nájde sa graf závislostí a topologickým triedením sa získa poradie vyhodnocovania atribútov V čase kompilácie 2 Metódy analýzy pravidiel Poradie vyhodnocovania sa určí statickou analýzou sémantických pravidiel V čase konštrukcie kompilátora 3 "Nedbanlivé"metódy * Poradie vyhodnocovania sa určí bez ohl adu na sémantické pravidlá Ak sa preklad vykonáva počas parsovania, poradie je určené parsovacou metódou V čase konštrukcie kompilátora
Syntaktický strom Zjednodušený strom odvodenia Operátory a kl účové slová sú vnútornými vrcholmi Vetvy odvodené ret azcovými pravidlami (chain rules) sú zredukované Využíva sa ako prechodná reprezentácia kompilovaného programu alebo jeho častí Syntaxou riadený preklad môže byt založený na strome odvodenia alebo syntaktickom strome Rovnaký prístup, atribúty sú priradené k uzlom stromu a ten sa anotuje Výhody syntaktického stromu Gramatika vhodná na parsovanie nie vždy reprezentuje prirodzenú hierarchickú štruktúru vstupného programovacieho jazyka Parsovacia metóda obmedzuje poradie sprístupnenia uzlov stromu odvodenia a toto poradie nie je vždy vhodné pre preklad
Funkcie na konštrukciu vrcholov: Syntaktický strom pre výrazy 1 mknode(op, left, right) 2 mkleaf (id, entry) Vrátia smerník na 3 mkleaf (num, val) skonštruovaný vrchol Vrcholy pre operátory sú implementované ako záznamy s niekol kými poliami operátor smerník na operand 1 smerník na operand 2 Vrcholy pre identifikátory a číselné konštanty Operátor je návestím vrcholu Pri preklade sú v zázname ešte d al šie polia pre atribúty id num 4 smerník do tabuľky symbolov
Syntaktický strom pre výrazy Syntaxou riadená definícia Pravidlo gramatiky E E 1 + T E E 1 T E T T T 1 F T ( E ) T id T num Sémantické pravidlo E.nptr := mknode( +, E 1.nptr, T.nptr) E.nptr := mknode(, E 1.nptr, T.nptr) E.nptr := T.nptr T.nptr := mknode(, T 1.nptr, F.nptr) T.nptr := E.nptr T.nptr := mkleaf (id, id.entry) T.nptr := mkleaf (num, num.val) X.nptr je syntetizovaný atribút pre X {E, T, F } a obsahuje smerník na príslušný vrchol
Syntaktický strom vs. DAG Spoločné podvýrazy sú reprezentované iba jedným podstromom Pri pridávaní nového vrchola sa kontroluje, či už identický vrchol neexistuje Výraz: a + a (b c) + (b c) d + + + * + * a * - d * d a - b c a - b c b c
Implementácia SRD pri parsovaní Zostrojit automatický prekladač pre l ubovol nú SRD môže byt t ažké Máme vel ké triedy, pre ktoré to je jednoduché 1 S-atribútové definície Obsahujú iba syntetizované atribúty 2 L-atribútové definície Obsahujú syntetizované aj dedičné atribúty, ale sú tu urcčité obmedzenia pre výpočet dedičných atribútov Zahŕňajú všetky SRD, ktoré sa implementujú bez explicitnej konštrukcie stromu odvodenia S-atribútové definície L-atribútove definície Obe triedy sa dajú implementovat pri parsovaní zhora-nadol aj zdola-nahor Obmedzenia na použitú gramatiku
S-atribútová definícia Implementácia pri parsovaní zdola-nahor (1) Hodnoty atribútov sú uložené v špeciálnych poliach v zásobníku parsera a sú asociované so symbolmi gramatiky (resp. stavmi) Ak symbol nemá atribút, hodnota je nedefinovaná Zásobník s miestom pre jeden atribút: state...... Z Y X val Z.z Y.y X.x...... top Implementácia - dvojica polí 1. state obsahuje smerníky (indexy) do LR(1) parsovacej tabul ky - Symbol gramatiky je implicitne v stave, netreba si ho pamätat - Pre jednoduchost uvádzame symbol namiesto príslušného stavu 2. val obsahuje hodnoty atribútu - val[i] = hodnota atribútu pre symbol v state[i] Hodnoty syntetizovaných atribútov sú vypočítané vždy pred redukciou z atríbútov uložených v zásobníku (= atribútov symbolov z pravej strany pravidla)
S-atribútová definícia Implementácia pri parsovaní zdola nahor (2) Príklad: A XYZ, A.a = f (X.x, Y.y, Z.z) state val state val...... Z Z.z top...... Y Y.y X X.x...... výpočet A.a redukcia A -> XYZ A A.a...... top - Z.z := val[top] - Y.y := val[top 1] - X.x := val[top 2] - top := top 2 - val[top] := A.a
Pravidlo gramatiky S-atribútová definícia Implementácia pri parsovaní zdola nahor (3) Fragment kódu L E n print(val[top]) E E 1 + T val[ntop] := val[top 2] + val[top] E T T T 1 F val[ntop] := val[top 2] val[top] T F F ( E ) val[ntop] := val[top 1] F digit S redukciami v LR parseri sú asociované fragmenty kódu Získame ich zo sémantických pravidiel nahradením atribútov pozíciami v poli val Vykonajú sa tesne pred redukciou Premenné top a ntop top je aktuálny vrch zásobníka, ntop je nový vrch zásobníka Postup pri redukcii podl a pravidla A β, kde β = r 1 ntop sa nastaví na top r + 1 2 Vykoná sa fragment kódu a redukcia 3 top sa nastaví na ntop
L-atribútová definícia Syntaxou riadená definícia je L-atribútová, ak pre l ubovol né pravidlo A X 1, X 2... X n platí, že každý dedičný atribút symbolu z pravej strany X j je závislý iba na 1 atribútoch symbolov X 1, X 2,... X j 1, ktoré sú v pravidle nal avo od X j a 2 dedičných atribútoch symbolu A. SRD, ktorá nie je L-atribútová Pravidlo gramatiky: A LM A QR Sémantické pravidlo: L.i := l(a.i) M.i := m(l.s) A.s := f (M.s) R.i := r(a.i) Q.i := q(r.s) A.s := f (Q.s) Pozn.: Každá S-atribútová definícia je aj L-atribútová Nezodpovedá definícií
L-atribútová definícia Vyhodnotenie atribútov Atribúty môžu byt vyhodnotené prechádzaním stromu do hĺbky (depth-first order) procedure dfvisit(n:node); begin for každé diet a m vrcholu n zl ava doprava do begin vyhodnot dedičné atribúty vrcholu m; dfvisit(m) end; vyhodnot syntetizované atribúty vrcholu n end Prirodzený spôsob prechádzania stromu odvodenia Implementácia L-atribútovej definície pri parsovaní 1 Parsovanie zhora-nadol Všetky SRD založené na LL(1) gramatikách 2 Parsovanie zdola-nahor Všetky SRD založené na LL(1) gramatikách, vel ká čast SRD založených na LR(1) gramatikách
Prekladové schémy Ďal ší spôsob špecifikácie syntaxou riadeného prekladu Konkrétnejšia ako SRD Špecifikuje aj poradie vyhodnocovania atribútov Sémantické akcie sú uzátvorkované pomocou {} a vložené medzi symboly pravých strán pravidiel Príklad Prekladová schéma, ktorá prekladá infixové výrazy so sčítaním a odčítaním na ekvivalentné postfixové výrazy E T R R addop T {print(addop.lexeme)} R 1 ε T num {print(num.val)} addop.lexeme môže byt + alebo - Gramatika vznikla odstránením l avej rekurzie z povestnej gramatiky pre výrazy
Obmedzenia pre prekladové schémy Akcia nesmie odkazovat na nevypočítaný atribút Prekladové schémy pre S-atribútové definície Jednoduché riešenie - akcie sú umiestnené na konci pravidiel Prekladové schémy pre L-atribútové definície 1 Dedičný atribút symbolu na pravej strane pravidla musí byt vypočítaný v akcii nal avo od neho. 2 Akcia nesmie odkazovat na syntetizovaný atribút symbolu napravo. 3 Syntetizovaný atribút neterminálu na l avej strane pravidla môže byt vypočítaný až potom ako boli vypočítané všetky atribúty na ktorých je závislý. Príslušná akcia pre jeho vypočítanie je zvyčajne lokalizovaná na konci pravej strany pravidla Príklad "zlej"prekladovej schémy S A 1 A 2 {A 1.in := 1; A 2.in := 2; } A a {print(a.in)}
L-atribútová definícia Implementácia pri prediktívnom parsovaní Implementácia je možná iba pre L-atribútové definície (prekladové schémy *) založené na LL(1) gramatikách, ktoré okrem iného, nemôžu obsahovat l avú rekurziu Existuje metóda na odstránenie l avej rekurzie priamo z prekladovej schémy Rozšírenie algoritmu odstránenia l avej rekurzie z CF gramatiky Dá sa aplikovat na prekladové schémy so syntetizovanými atribútmi Ak už máme prekladovú schému založenú na LL(1) gramatike, existuje algoritmus pre konštrukciu prediktívneho syntaxou riadeného prekladača
Odstránenie l avej rekurzie z prekl. schémy Vstupná prekladová schéma: A A 1 Y {A.a := g(a 1.a, Y.y)} A X {A.a := f (X.x)} Po odstránení l avej rekurzie z CF gramatiky získame novú gramatiku: A X R R Y R ε Po prepísaní sémantických akcií získame výslednú prekl. schému: A X {R.i := f (X.x)} R {A.a := R.s} R Y {R 1.i := g(r.i, Y.y)} R 1 {R.s := R 1.s} R ε {R.s := R.i}
Odstránenie l avej rekurzie z prekl. schémy E E 1 + T {E.val := E 1.val + T.val} E E 1 T {E.val := E 1.val T.val} E T {E.val := T.val} T (E) {T.val := E.val} T num {T.val := num.val} 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 ε {R.s := R.i} T ( E ) {T.val := E.val} T num {T.val := num.val} Príklad
Konštrukcia prediktívneho prekladača Vstup. Syntaxou riadená prekladová schéma založená na gramatike vhodnej pre prediktívne parsovanie. Výstup. Kód prediktívneho syntaxou riadeného prekladača. 1 Pre každý neterminál A vytvor funkciu, ktorá má formálny parameter pre každý dedičný atribút A a vracia hodnoty syntetizovaných neterminálov A. Funkcia pre A má lokálnu premennú pre každý atribút každého symbolu, ktorý sa vyskytuje v pravidle pre A. 2 Kód pre neterminál A sa rozhoduje, ktoré pravidlo aplikovat podl a aktuálneho vstupného symbolu. 3 Kód asociovaný s každým pravidlom vykonáva nasledovné akcie. (i) Pre token X so syntetizovaným atribútom x, ulož hodnotu x do premennej deklarovanej pre X.x. Potom zavolaj procedúru match(x) a posuň sa na vstupe. (ii) Pre neteminál B, vygeneruj priradenie tvaru c := B(b 1, b 2,..., b k ), kde b 1, b 2,..., b k sú premenné pre dedičné atribúty neterminálu B, c je premenná pre syntetizovaný atribút net. B a B je volanie funkcie pre net. B. (iii) Pre akciu, kopíruj kód priamo do parsera, pričom každú referenciu na atribút nahrad asociovanou premennou.
Syntaxou riadený preklad pri parsovaní Zhrnutie 1 Implementácia S-atribútových definícii Mali sme algoritmus pri parsovaní zdola-nahor Dajú sa implementovat aj pri parsovaní zhora-nadol - Odstránenie l avej rekurzie z prekladovej schémy a zostrojenie prediktívneho prekladača 2 Implementácia L-atribútových definícií Mali sme algoritmus pri parsovaní zhora-nadol Dajú sa implementovat aj pri parsovaní zdola-nahor - Rozšírenie algoritmu pre spracovanie S-atribútových definícií V oboch prípadoch je obmedzená množina CF gramatík, na ktorej je SRP založený - Prekladač zdola-nahor je silnejší