Atributovaý překlad Typy atributů, implemetace Šárka Vavrečková Ústav iformatiky, FPF SU Opava sarka.vavreckova@fpf.slu.cz Posledí aktualizace: 5. prosice 008
Typy atributů Defiice (Sytetizovaé a dědičé atributy) Sytetizovaý atribut je atribut, jehož hodota závisí a hodotách atributů uzlů jeho vlastího podstromu v derivačím stromě. Slouží k posíláí údajů v derivačím stromě směrem zdola ahoru. Dědičý atribut je atribut, jehož hodota závisí a hodotách atributů adřízeého uzlu ebo uzlů a stejé úrovi derivačího stromu vlevo od tohoto symbolu. Žádý atribut emůže být zároveň sytetizovaý a dědičý. A BCD A.val = B.val + D.val, C.des = (A.m + B.val) 10 +.lex A.val je sytetizovaý, závisí a atributech symbolů-potomků C.des je dědičý, závisí a atributech předka a bratrů vlevo
Iicializace atributů Každý atribut musí být ěkde v derivačím stromě iicializová: dědičé atributy obvykle iicializujeme v kořei stromu (obecě a horím levém začátku cesty toku hodoty atributu derivačím stromem), sytetizovaé atributy jsou většiou iicializováy v listech stromu (tj. v termiálích pravidlech), často lexikálím aalyzátorem (pokud e, musíme iicializaci provést sami v příslušém pravidle).
Příklad Gramatika geeruje výraz ve tvaru hledej (; L) v hledej je klíčové slovo určující příkaz pro hledáí čísla v sezamu, je číslo, které má být hledáo, L geeruje sezam čísel, v je výstupí termiál, do jeho atributu uložíme výsledek Sytaktická pravidla v překladové gramatice: S hledej (; L) v L A A, L ε
S hledej (; L) v L A A, L ε Zpracováí výrazu hledej (; 9, ) S poz = 0 cis = hledej ( 1 hledaé číslo iicializujeme a, pozice a 0 (dědičé atributy) posíláme dolů hledaou hodotu a pozici 1 (zvýšili jsme o 1) 3 do ižšího patra přepošleme dědičé atributy posíláme dolů hledaou hodotu a pozici 5 iicializace sytetizovaého atributu a 0 (zatím ealeze) ; L 6 aleze, místo 0 pošleme pozici (idex) prvku 7 přeeseme do výstupího atributu ) v A, L A ε
S hledej (; L) v L A A, L ε Zpracováí výrazu hledej (; 9, ) S poz = 0 cis = hledej ( 1 hledaé číslo iicializujeme a, pozice a 0 (dědičé atributy) posíláme dolů hledaou hodotu a pozici 1 (zvýšili jsme o 1) 3 do ižšího patra přepošleme dědičé atributy posíláme dolů hledaou hodotu a pozici 5 iicializace sytetizovaého atributu a 0 (zatím ealeze) 9 ; L 6 aleze, místo 0 pošleme pozici (idex) prvku 7 přeeseme do výstupího atributu 1 ) v A, L A ε
S hledej (; L) v L A A, L ε Zpracováí výrazu hledej (; 9, ) S poz = 0 cis = hledej ( 1 hledaé číslo iicializujeme a, pozice a 0 (dědičé atributy) posíláme dolů hledaou hodotu a pozici 1 (zvýšili jsme o 1) 3 do ižšího patra přepošleme dědičé atributy posíláme dolů hledaou hodotu a pozici 5 iicializace sytetizovaého atributu a 0 (zatím ealeze) 9 ; L 6 aleze, místo 0 pošleme pozici (idex) prvku 7 přeeseme do výstupího atributu 1 ) v A 1, L A ε
S hledej (; L) v L A A, L ε Zpracováí výrazu hledej (; 9, ) S poz = 0 cis = hledej ( 1 hledaé číslo iicializujeme a, pozice a 0 (dědičé atributy) posíláme dolů hledaou hodotu a pozici 1 (zvýšili jsme o 1) 3 do ižšího patra přepošleme dědičé atributy posíláme dolů hledaou hodotu a pozici 5 iicializace sytetizovaého atributu a 0 (zatím ealeze) 9 ; L 6 aleze, místo 0 pošleme pozici (idex) prvku 7 přeeseme do výstupího atributu 1 ) v A 1, L A ε
S hledej (; L) v L A A, L ε Zpracováí výrazu hledej (; 9, ) S poz = 0 cis = hledej ( 1 hledaé číslo iicializujeme a, pozice a 0 (dědičé atributy) posíláme dolů hledaou hodotu a pozici 1 (zvýšili jsme o 1) 3 do ižšího patra přepošleme dědičé atributy posíláme dolů hledaou hodotu a pozici 5 iicializace sytetizovaého atributu a 0 (zatím ealeze) 9 ; L 6 aleze, místo 0 pošleme pozici (idex) prvku 7 přeeseme do výstupího atributu 1 ) v A 1, L 0 A alez = 0 ε
S hledej (; L) v L A A, L ε Zpracováí výrazu hledej (; 9, ) S poz = 0 cis = hledej ( 1 hledaé číslo iicializujeme a, pozice a 0 (dědičé atributy) posíláme dolů hledaou hodotu a pozici 1 (zvýšili jsme o 1) 3 do ižšího patra přepošleme dědičé atributy posíláme dolů hledaou hodotu a pozici 5 iicializace sytetizovaého atributu a 0 (zatím ealeze) 9 ; L 6 aleze, místo 0 pošleme pozici (idex) prvku 7 přeeseme do výstupího atributu 1 ) v A 1, L 0 A alez = 0 ε
S hledej (; L) v L A A, L ε Zpracováí výrazu hledej (; 9, ) S poz = 0 cis = hledej ( 1 hledaé číslo iicializujeme a, pozice a 0 (dědičé atributy) posíláme dolů hledaou hodotu a pozici 1 (zvýšili jsme o 1) 3 do ižšího patra přepošleme dědičé atributy posíláme dolů hledaou hodotu a pozici 5 iicializace sytetizovaého atributu a 0 (zatím ealeze) 9 ; L 6 aleze, místo 0 pošleme pozici (idex) prvku 7 přeeseme do výstupího atributu 1 ) v A 1, L 0 A alez = 0 ε
S hledej (; L) v L A A, L ε Atributová gramatika Použijeme atributy [lex], L[poz, cis, alez], A[poz, cis, alez], v[vysl] dědičé: poz, cis, vysl sytetizovaé: lex, alez hledej ( 9 S poz = 0 cis = ; L 1 ) v A 1, L S hledej (; {L.poz = 0, L.cis =.lex} L) v {v.vysl = L.alez} L {A.poz = L.poz + 1, A.cis = L.cis} A {if.lex = A.cis the L.alez = A.poz else L.alez = A.alez} A, {L.poz = A.poz, L.cis = A.cis} L {A.alez = L.alez} A ε {A.alez = 0} 0 A alez = 0 ε
S hledej (; L) v L A A, L ε Atributová gramatika Použijeme atributy [lex], L[poz, cis, alez], A[poz, cis, alez], v[vysl] dědičé: poz, cis, vysl sytetizovaé: lex, alez hledej ( 9 S poz = 0 cis = ; L 1 ) v A 1, L S hledej (; {L.poz = 0, L.cis =.lex} L) v {v.vysl = L.alez} L {A.poz = L.poz + 1, A.cis = L.cis} A {if.lex = A.cis the L.alez = A.poz else L.alez = A.alez} A, {L.poz = A.poz, L.cis = A.cis} L {A.alez = L.alez} A ε {A.alez = 0} 0 A alez = 0 ε
Determiistický překlad výrazů při iterpretaci Požadavky a gramatiku gramatika typu LL(1), silá LR(1) ebo jiá, kterou lze použít pro determiistický překlad často eí třeba použít výstupí termiály zachováváme prioritu operátorů
S i = A A BC C +BC C BC C ε B DE E DE E /DE E ε D D i D (A) Příklad LL(1) gramatika
Příklad LL(1) gramatika S i = A {Uloz(i.azev, A.val)} A B {C.m = B.val} C {A.val = C.val} C +B {C 1.m = C 0.m + B.val} C {C 0.val = C 1.val} C B {C 1.m = C 0.m B.val} C {C 0.val = C 1.val} C ε {C.val = C.m} B D {E.m = D.val} E {B.val = E.val} E D {E 1.m = E 0.m D.val} E {E 0.val = E 1.val} E /D {E 1.m = E 0.m/D.val} E {E 0.val = E 1.val} E ε {E.val = E.m} D {D.val =.lex} D i {D.val = ZjistiHodotu(i.azev)} D (A) {D.val = A.val}
S i = A S i = A {Uloz(i.azev, A.val)} A B {C.m = B.val} C {A.val = C.val} C +B {C 1.m = C 0.m + B.val} C {C 0.val = C 1.val} C B {C 1.m = C 0.m B.val} C {C 0.val = C 1.val} C ε {C.val = C.m} B D {E.m = D.val} E {B.val = E.val} E D {E 1.m = E 0.m D.val} E {E 0.val = E 1.val} E /D {E 1.m = E 0.m/D.val} E {E 0.val = E 1.val} E ε {E.val = E.m} D {D.val =.lex} D i {D.val = ZjistiHodotu(i.azev)} D (A) {D.val = A.val} B C D E B C D E D E + B C i D E ε D E ε ε i ε
S i = A S i = A {Uloz(i.azev, A.val)} A B {C.m = B.val} C {A.val = C.val} C +B {C 1.m = C 0.m + B.val} C {C 0.val = C 1.val} C B {C 1.m = C 0.m B.val} C {C 0.val = C 1.val} C ε {C.val = C.m} B D {E.m = D.val} E {B.val = E.val} E D {E 1.m = E 0.m D.val} E {E 0.val = E 1.val} E /D {E 1.m = E 0.m/D.val} E {E 0.val = E 1.val} E ε {E.val = E.m} D {D.val =.lex} D i {D.val = ZjistiHodotu(i.azev)} D (A) {D.val = A.val} B C D E B C 3 D 6 E D E + B C i 3 D E ε D E ε ε i ε
S i = A S i = A {Uloz(i.azev, A.val)} A B {C.m = B.val} C {A.val = C.val} C +B {C 1.m = C 0.m + B.val} C {C 0.val = C 1.val} C B {C 1.m = C 0.m B.val} C {C 0.val = C 1.val} C ε {C.val = C.m} B D {E.m = D.val} E {B.val = E.val} E D {E 1.m = E 0.m D.val} E {E 0.val = E 1.val} E /D {E 1.m = E 0.m/D.val} E {E 0.val = E 1.val} E ε {E.val = E.m} D {D.val =.lex} D i {D.val = ZjistiHodotu(i.azev)} D (A) {D.val = A.val} B C D E B C 3 D 6 E D E + B C i 3 5 30 D E ε D E ε 5 ε i ε
S i = A B 30 C S i = A {Uloz(i.azev, A.val)} A B {C.m = B.val} C {A.val = C.val} C +B {C 1.m = C 0.m + B.val} C {C 0.val = C 1.val} C B {C 1.m = C 0.m B.val} C {C 0.val = C 1.val} C ε {C.val = C.m} B D {E.m = D.val} E {B.val = E.val} E D {E 1.m = E 0.m D.val} E {E 0.val = E 1.val} E /D {E 1.m = E 0.m/D.val} E {E 0.val = E 1.val} E ε {E.val = E.m} D {D.val =.lex} D i {D.val = ZjistiHodotu(i.azev)} D (A) {D.val = A.val} D E 30 B C 3 D 6 30 E D E + B C i 3 5 30 D E 30 ε D E ε 5 val = m ε = 30 i ε
S i = A B 30 C S i = A {Uloz(i.azev, A.val)} A B {C.m = B.val} C {A.val = C.val} C +B {C 1.m = C 0.m + B.val} C {C 0.val = C 1.val} C B {C 1.m = C 0.m B.val} C {C 0.val = C 1.val} C ε {C.val = C.m} B D {E.m = D.val} E {B.val = E.val} E D {E 1.m = E 0.m D.val} E {E 0.val = E 1.val} E /D {E 1.m = E 0.m/D.val} E {E 0.val = E 1.val} E ε {E.val = E.m} D {D.val =.lex} D i {D.val = ZjistiHodotu(i.azev)} D (A) {D.val = A.val} D E 30 B C 3 D 6 30 E 8 D 8 E + B C i 3 5 30 D E 30 8 ε D E ε 5 val = m ε = 30 i ε
S i = A B 30 C S i = A {Uloz(i.azev, A.val)} A B {C.m = B.val} C {A.val = C.val} C +B {C 1.m = C 0.m + B.val} C {C 0.val = C 1.val} C B {C 1.m = C 0.m B.val} C {C 0.val = C 1.val} C ε {C.val = C.m} B D {E.m = D.val} E {B.val = E.val} E D {E 1.m = E 0.m D.val} E {E 0.val = E 1.val} E /D {E 1.m = E 0.m/D.val} E {E 0.val = E 1.val} E ε {E.val = E.m} D {D.val =.lex} D i {D.val = ZjistiHodotu(i.azev)} D (A) {D.val = A.val} D E 30 B 8 C 3 D 6 30 E 8 D 8 8 E + B C i 3 5 30 D E 30 8 val = m = 8 ε D E ε 5 val = m ε = 30 i ε
S i = A B 30 C S i = A {Uloz(i.azev, A.val)} A B {C.m = B.val} C {A.val = C.val} C +B {C 1.m = C 0.m + B.val} C {C 0.val = C 1.val} C B {C 1.m = C 0.m B.val} C {C 0.val = C 1.val} C ε {C.val = C.m} B D {E.m = D.val} E {B.val = E.val} E D {E 1.m = E 0.m D.val} E {E 0.val = E 1.val} E /D {E 1.m = E 0.m/D.val} E {E 0.val = E 1.val} E ε {E.val = E.m} D {D.val =.lex} D i {D.val = ZjistiHodotu(i.azev)} D (A) {D.val = A.val} D E 30 B 8 C 3 D i 3 6 30 E 5 30 D E 30 8 D 8 8 8 E val = m = 8 ε + B C 15 D E ε 5 val = m 15 ε = 30 i ε
S i = A B 30 C S i = A {Uloz(i.azev, A.val)} A B {C.m = B.val} C {A.val = C.val} C +B {C 1.m = C 0.m + B.val} C {C 0.val = C 1.val} C B {C 1.m = C 0.m B.val} C {C 0.val = C 1.val} C ε {C.val = C.m} B D {E.m = D.val} E {B.val = E.val} E D {E 1.m = E 0.m D.val} E {E 0.val = E 1.val} E /D {E 1.m = E 0.m/D.val} E {E 0.val = E 1.val} E ε {E.val = E.m} D {D.val =.lex} D i {D.val = ZjistiHodotu(i.azev)} D (A) {D.val = A.val} D E 30 B 8 C 3 D 6 30 E 8 D 8 8 E 15 + B C i 3 5 30 D E 30 8 val = m = 8 ε 15 D 15 15 E ε 5 val = m 15 ε = 30 i val = m ε = 15
S 37 i = A B 30 37 C S i = A {Uloz(i.azev, A.val)} A B {C.m = B.val} C {A.val = C.val} C +B {C 1.m = C 0.m + B.val} C {C 0.val = C 1.val} C B {C 1.m = C 0.m B.val} C {C 0.val = C 1.val} C ε {C.val = C.m} B D {E.m = D.val} E {B.val = E.val} E D {E 1.m = E 0.m D.val} E {E 0.val = E 1.val} E /D {E 1.m = E 0.m/D.val} E {E 0.val = E 1.val} E ε {E.val = E.m} D {D.val =.lex} D i {D.val = ZjistiHodotu(i.azev)} D (A) {D.val = A.val} D E 30 37 B 8 C 3 D 6 30 E 8 D 8 8 E 15 37 + B C 37 i 3 5 30 D E 30 8 val = m = 8 ε 15 D 15 15 E val = m ε = 37 5 val = m 15 ε = 30 i val = m ε = 15
Oproti sytaxi rozšíříme: Implemetace LL(1) překladu aprogramujeme všechy použité sématické fukce (včetě práce s tabulkou symbolů) do fukcí aprogramovaých pro sytaxi přidáme sématiku voláí sématických fukcí a vyhodocováí sématických pravidel určíme způsob předáváí atributů mezi symboly a pravidly Použijeme metodu rekurzivího sestupu. Termiály vstupí zpracovávají se stejě jako u sytaxe (fukce expect i) výstupí aprogramujeme fukci expect out ošetřující výstupí termiály
Atributy přeášíme Růzé typy atributů posíláme uvitř pravidla lokálími proměými, mezi pravidly (předek potomek) budeme zpracovávat takto: sytetizovaé atributy etermiálů posíláme rekurzí směrem ahoru, pro ě použijeme parametry volaé odkazem, aby bylo možé v adřízeé fukci zjistit hodotu vypočteou ve volaé podřízeé fukci, dědičé atributy etermiálů posíláme rekurzí směrem dolů, pro ě použijeme parametry volaé hodotou, sytetizovaé atributy vstupích termiálů ukládáme do globálí proměé (jsou součástí proměé typu TSymbol), obvykle je zde ukládá lexikálí aalyzátor, dědičé atributy výstupích termiálů buď přímo vypisujeme, ebo ukládáme do vhodé globálí proměé (dyamického sezamu, souboru).
S Av {v.vysl = A.val, VypisText(v.vysl)} A B {C.m = B.val} C {A.val = C.val} C +B {C 1.m = C 0.m + B.val} C {C 0.val = C 1.val} C B {C 1.m = C 0.m B.val} C {C 0.val = C 1.val} C ε {C.val = C.m} B D {E.m = D.val} E {B.val = E.val} E D {E 1.m = E 0.m D.val} E {E 0.val = E 1.val} E /D {E 1.m = E 0.m/D.val} E {E 0.val = E 1.val} E ε {E.val = E.m} D {D.val =.lex} D i {D.val = ZjistiHodotu(i.azev)} D (A) {D.val = A.val}
Datové typy a proměé type TTypSymbolu = (S_ID, S_NUM, S_PLUS, S_MINUS, S_MUL, S_DIV, S_LZAV, S_RZAV, S_VYSTUP, S_ENDOFFILE); TSymbol = record typ: TTypSymbolu; atribcislo: iteger; // celé číslo (S_NUM) atribstr: ^TObjekt; // ázev proměé (S_ID) var symbol: TSymbol;... // další proměé a datové typy
Ošetřeí chyb a pomocé fukce pro výstup procedure error(cost hlaska: strig); begi Koec := true; writel( Chyba při sytaktické aalýze a řádku,zak.cislo,, sloupci,zak.pozice, :,hlaska); Pomocé fukce pro výpis VypisTyp(typ: TTypSymbolu) převede datový typ a řetězec VypisHod(sym: TSymbol) převede symbol a řetězec
Vstupí a výstupí termiály procedure expect_i(vstupi_term: TTypSymbolu); // vstupí symboly begi if vstupi_term = symbol.typ the Lex else error( symbol,vypishod(symbol), eí očekávaého typu, VypisTyp(vstupi_term)); procedure expect_out(vystupi_term: TSymbol); begi if vystupi_term.typ = S_VYSTUP the VypisText(vystupi_term.atribcislo); // chyba se epředpokládá // výstupí symboly
Pravidla S Av {v.vysl = A.val, VypisText(v.vysl)} procedure S; var pom_sym: TSymbol; begi if symbol.typ i [S_NUM,S_ID,S_LZAV] the begi A(pom_sym); pom_sym := S_VYSTUP; // výstupí termiál v expect_out(pom_sym); ed else error( symbol,vypishod(symbol), eí očekávaého typu, VypisTyp(S_NUM),,,VypisTyp(S_ID), ebo,vypistyp(s_lzav));
Pravidla A B {C.m = B.val} C {A.val = C.val} procedure A(var val: iteger); var pomval: iteger; begi if symbol.typ i [S_NUM,S_ID,S_LZAV] the begi B(pomval); C(pomval,val); ed else error( symbol,vypishod(symbol), eí očekávaého typu, VypisTyp(S_NUM),,,VypisTyp(S_ID), ebo,vypistyp(s_lzav));
Pravidla C +B {C 1.m = C 0.m + B.val} C {C 0.val = C 1.val} C B {C 1.m = C 0.m B.val} C {C 0.val = C 1.val} C ε {C.val = C.m} procedure C(m: iteger; var val: iteger); var pomval: iteger; begi case symbol.typ of S_PLUS: begi expect_i(s_plus); B(pomval); C(m + pomval,val) S_MINUS: begi expect_i(s_minus); B(pomval); C(m - pomval,val)...
Pravidla C +B {C 1.m = C 0.m + B.val} C {C 0.val = C 1.val} C B {C 1.m = C 0.m B.val} C {C 0.val = C 1.val} C ε {C.val = C.m}... S_RZAV,S_ENDOFFILE: val := m; else error( symbol,vypishod(symbol), eí očekávaého typu, VypisTyp(S_PLUS),,,VypisTyp(S_MINUS),,,VypisTyp(S_RZAV), ebo koec vstupu )
Pravidla B D {E.m = D.val} E {B.val = E.val} procedure B(var val: iteger); var pomval: iteger; begi if symbol.typ i [S_NUM,S_ID,S_LZAV] the begi D(pomval); E(pomval,val); ed else error(...);
Pravidla E D {E 1.m = E 0.m D.val} E {E 0.val = E 1.val} E /D {E 1.m = E 0.m/D.val} E {E 0.val = E 1.val} E ε {E.val = E.m} procedure E(m: iteger; var val: iteger); var pomval: iteger; begi case symbol.typ of S_MUL: begi expect_i(s_mul); D(pomval); E(m * pomval,val) S_DIV: begi expect_i(s_div); D(pomval); if pomval = 0 the error( děleí ulou ) else E(m/pomval,val)...
Pravidla E D {E 1.m = E 0.m D.val} E {E 0.val = E 1.val} E /D {E 1.m = E 0.m/D.val} E {E 0.val = E 1.val} E ε {E.val = E.m}... S_PLUS,S_MINUS,S_RZAV,S_ENDOFFILE: val := m; else error(...)
Pravidla D {D.val =.lex} D i {D.val = ZjistiHodotu(i.azev)} D (A) {D.val = A.val} procedure D(var val: iteger); begi case symbol.typ of S_NUM: begi val := symbol.atribcis; expect_i(s_num) S_ID: begi val := symbol.atribstr^.hodota.i; expect_i(s_id)... // musíme zachytit předem, pak bude // přepsáo lexikálím aalyzátorem // z tabulky symbolů
Pravidla D {D.val =.lex} D i {D.val = ZjistiHodotu(i.azev)} D (A) {D.val = A.val}... S_LZAV: begi expect_i(lzav); A(val); expect_i(rzav) else error(...)
Hlaví fukce procedure Preklad; begi iit; // iicializace překladu včetě lexikálího aalyzátoru Lex; // předačteme jede symbol S; // spustíme rekurziví voláí doe; // ukočeí překladu, úklid paměti apod.
S i = V V AM A V + A V A ε M BF B M B M/ B ε F F i F (V ) Příklad silá LR(1) gramatika
Příklad silá LR(1) gramatika S i = V {Uloz(i.azev, V.val)} V AM {if A.op = S PLUS the V.val = A.val + M.val else V.val = A.val M.val} A V + {A.val = V.val, A.op = S PLUS} A V {A.val = V.val, A.op = S MINUS} A ε {A.val = 0, A.op = S PLUS} M BF {if B.op = S MUL the M.val = B.val F.val else M.val = B.val/F.val} B M {B.val = M.val, B.op = S MUL} B M / {B.val = M.val, B.op = S DIV} B ε {B.val = 1, B.op = S MUL} F {F.val =.lex} F i {F.val = ZjistiHodotu(i.azev)} F (V ) {F.val = V.val}
S 33 i = V A 13, + 0 M 13 V, + B F 5 0, A 7 M M 5 0 1, 7 1, V B F B F 0, + A 0 ε 1, B 1 ε M 0 1 ε 0 F 0 7 i 1 ε i S i = V {Uloz(i.azev, V.val)} V AM {if A.op = S PLUS the V.val = A.val+M.val else V.val = A.val M.val} A V + {A.val = V.val, A.op = S PLUS} A V {A.val = V.val, A.op = S MINUS} A ε {A.val = 0, A.op = S PLUS} M BF {if B.op = S MUL the M.val = B.val F.val else M.val = B.val/F.val} B M {B.val = M.val, B.op = S MUL} B M / {B.val = M.val, B.op = S DIV} B ε {B.val = 1, B.op = S MUL} F {F.val =.lex} F i {F.val = ZjistiHodotu(i.azev)} F (V ) {F.val = V.val}
Postup použijeme metodu přepisu rozkladové tabulky se zásobíkem do zásobíku ukládáme celé symboly včetě atributů atributy jsou je sytetizovaé
S #S 0 S i = V {Uloz(i.azev, V.val)} 1 V AM {if A.op = S PLUS the V.val = A.val + M.val else V.val = A.val M.val} A V + {A.val = V.val, A.op = S PLUS} 3 A V {A.val = V.val, A.op = S MINUS} A ε {A.val = 0, A.op = S PLUS} 5 M BF {if B.op = S MUL the M.val = B.val F.val 6 else M.val = B.val/F.val} B M {B.val = M.val, B.op = S MUL} 7 B M / {B.val = M.val, B.op = S DIV} 8 B ε {B.val = 1, B.op = S MUL} 9 F {F.val =.lex} 10 F i {F.val = ZjistiHodotu(i.azev)} 11 F (V ) {F.val = V.val} 1
Datové typy type TTypSymbolu = (S_ID, S_NUM, S_ROVNASE, S_PLUS, S_MINUS,// termiály S_MUL, S_DIV, S_LPAR, S_RPAR, S_ENDOFFILE, S_NS, S_NSC, S_NV, S_NA, S_NM, S_NB, S_NF, S_HASH); // etermiály TSymbol = record typ: TTypSymbolu; atribcislo: iteger; atribstr: ^TObjekt; TSymbolZasob = record typ: TTypSymbolu; atribcislo: iteger; // atributy val a lex atribstr: ^TObjekt; // atribut azev atribop: TTypSymbolu; // pro S_PLUS, S_MINUS, S_MUL, S_DIV
Proměé var koec: boolea; // idikátor ukočeí výpočtu symbol: TSymbol; // aktuálí symbol ze vstupu vrchol_zas: TSymbolZasob; // symbol a vrcholu zásobíku zasobik: TZasobik; // prvky jsou typu TSymbolZasob... // další používaé datové typy a proměé
Pravidla procedure reduce(cislo_prav: iteger); var SymbolZas: TSymbolZas; val: iteger; begi case cislo_prav of 0:... 1:... atd. doplíme podle pravidel
Pravidla S #S 0 0: begi Vyjmi_ze_zasobiku(vrchol_zas); // S Vyjmi_ze_zasobiku(vrchol_zas); // # SymbolZas.typ := S_NSC; Pridej_do_zasobiku(SymbolZas);
Pravidla S i = V {Uloz(i.azev, V.val)} 1 1: begi Vyjmi_ze_zasobiku(vrchol_zas); // V val := vrchol_zas.atribcislo; Vyjmi_ze_zasobiku(vrchol_zas); // = Vyjmi_ze_zasobiku(vrchol_zas); // i // uložíme vypočteou hodotu do tabulky symbolů: vrchol_zas.atribstr^.hodota.i := val; SymbolZas.typ := S_NS; Pridej_do_zasobiku(SymbolZas);
Pravidla V AM {if A.op = S PLUS the V.val = A.val + M.val else V.val = A.val M.val} : begi Vyjmi_ze_zasobiku(vrchol_zas); // M val := vrchol_zas.atribcislo; Vyjmi_ze_zasobiku(vrchol_zas); // A SymbolZas.typ := S_NV; if vrchol_zas.atribop = S_PLUS the SymbolZas.atribcislo := vrchol_zas.atribcislo + val else if vrchol_zas.atribop = S_MINUS the SymbolZas.atribcislo := vrchol_zas.atribcislo - val else error( chyba v sytaxi aritmetického výrazu, ealeze žádý ze symbolů, VypisTyp(S_PLUS), ebo,vypistyp(s_minus)); Pridej_do_zasobiku(SymbolZas);
Pravidla A V + {A.val = V.val, A.op = S PLUS} 3 3: begi Vyjmi_ze_zasobiku(vrchol_zas); // + Vyjmi_ze_zasobiku(vrchol_zas); // V SymbolZas.typ := S_NA; SymbolZas.atribop := S_PLUS; SymbolZas.atribcislo := vrchol_zas.atribcislo; Pridej_do_zasobiku(SymbolZas);
Pravidla A V {A.val = V.val, A.op = S MINUS} : begi Vyjmi_ze_zasobiku(vrchol_zas); // - Vyjmi_ze_zasobiku(vrchol_zas); // V SymbolZas.typ := S_NA; SymbolZas.atribop := S_MINUS; SymbolZas.atribcislo := vrchol_zas.atribcislo; Pridej_do_zasobiku(SymbolZas);
Pravidla A ε {A.val = 0, A.op = S PLUS} 5 5: begi SymbolZas.typ := S_NA; SymbolZas.atribop := S_PLUS; SymbolZas.atribcislo := 0; Pridej_do_zasobiku(SymbolZas);... // pro symboly M a B to bude podobé jako pro V a A, // ale esmíme zapomeout ošetřit děleí ulou
Pravidla F {F.val =.lex} 10 10: begi Vyjmi_ze_zasobiku(vrchol_zas); // SymbolZas.typ := S_NF; SymbolZas.atribcislo := vrchol_zas.atribcislo; Pridej_do_zasobiku(SymbolZas);
Pravidla F i {F.val = ZjistiHodotu(i.azev)} 11 11: begi Vyjmi_ze_zasobiku(vrchol_zas); // i with SymbolZas do begi typ := S_NF; atribcislo := vrchol_zas.atribstr^.hodota.i; Pridej_do_zasobiku(SymbolZas);
Pravidla F (V ) {F.val = V.val} 1 1: begi Vyjmi_ze_zasobiku(vrchol_zas); // ( Vyjmi_ze_zasobiku(vrchol_zas); // V with SymbolZas do begi typ := S_NF; atribcislo := vrchol_zas.atribcislo; Vyjmi_ze_zasobiku(vrchol_zas); // ) Pridej_do_zasobiku(SymbolZas);
Rozhodováí mezi pravidly podle tabulky i = + / ( ) $ S acc S r0 V push push push r1 A r9 r9 r9 M r r push push r r B push push push F r6 r6 r6 r6 r6 r6 r10 r10 r10 r10 r10 r10 i push r11 r11 r11 r11 r11 r11 = r5 r5 r5 + r3 r3 r3 r r r r7 r7 r7 / r8 r8 r8 ( r5 r5 r5 ) r1 r1 r1 r1 r1 r1 # push
Rozhodováí mezi pravidly podle tabulky S S i = + / ( ) $ acc r0 procedure Akce; begi case vrchol_zas of S_NSC: if symbol.typ = S_ENDOFFILE the accept else error( očekává koec souboru ); S_NS: if symbol.typ = S_ENDOFFILE the reduce(0) else error( očekává koec souboru );
Rozhodováí mezi pravidly podle tabulky i = + / ( ) $ V push push push r1 S_NV: case symbol.typ of S_PLUS,S_MINUS,S_RZAV: push; S_ENDOFFILE: reduce(1); else error( symbol,vypishod(symbol), eí očekávaého typu, VypisTyp(S_PLUS),,,VypisTyp(S_MINUS),,, VypisTyp(S_RZAV), ebo koec souboru );... // atd. pro všechy etermiály
Pravidla i = + / ( ) $ r10 r10 r10 r10 r10 r10 i push r11 r11 r11 r11 r11 r11 S_NUM: if symbol.typ i [S_PLUS,S_MINUS,S_MUL,S_DIV,S_RZAV, S_ENDOFFILE] the reduce(10) else error(...); S_ID: case symbol.typ of S_PLUS,S_MINUS,S_MUL,S_DIV,S_RZAV,S_ENDOFFILE: reduce(11); S_ROVNASE: push; else error(...);... // atd. pro všechy termiály
Ošetřeí chyb a akceptováí procedure error(cost hlaska: strig); begi Koec := true; writel( Chyba při sytaktické aalýze a řádku,zak.cislo,, sloupci,zak.pozice, :,hlaska); procedure accept; begi Koec := true;
Práce se vstupem procedure push; var SymbolZas: TSymbolZas; begi with SymbolZas do begi typ := symbol.typ; atribcislo := symbol.atribcislo; atribstr := symbol.atribstr; Pridej_do_zasobiku(SymbolZas); Lex; // lexikálí aalyzátor ačte další symbol
Iicializace a ukočeí procedure Iit; var SymbolZas: TSymbolZas; begi... // iicializace vstupu a výstupu Vytvor_zasobik; SymbolZas.typ := S_HASH; Pridej_do_zasobiku(SymbolZas); Lex; Koec := false; procedure Doe; begi Zlikviduj_zasobik; // uvolí paměť zabraou zásobíkem... // uzavřeí vstupu a výstupu
Řízeí překladu procedure Preklad; begi Iit; while (ot Koec) do Akce; Doe;