Gramatyki atrybutywne, część 1 (gramatyki S-atrybutywne Teoria kompilacji Dr inŝ. Janusz Majewski Katedra Informatyki Gramatyki atrybutywne Do przeprowadzenia poprawnego tłumaczenia, oprócz informacji na temat składni języka podlegającego tłumaczeniu, translator musi posiadać moŝliwość korzystania z wielu innych informacji dotyczących tłumaczonych konstrukcji. Informacje te mają charakter semantyczny. Dotyczą np. typu zmiennych, typu wyraŝeń, wielkości pamięci dla zmiennych, adresów odpowiednich zapisów w tablicach, wartości wyraŝeń w procesie interpretacji, itd. Informacje semantyczne mają charakter atrybutów stowarzyszonych z konstrukcjami języka podlegającego tłumaczeniu. Jednym ze sposobów formalnego określenia semantyki języka i zdefiniowania akcji podejmowanych w procesie translacji jest aparat gramatyk atrybutywnych.
Atrybutowane drzewa rozbioru Analiza semantyczna i generowanie kodu oparte są na drzewie rozbioru syntaktycznego. KaŜdy wierzchołek drzewa (symbol gramatyki jest udekorowany atrybutami opisującymi własności wierzchołka. Dla podkreślenia tego faktu takie drzewo nazywa się często atrybutowanym drzewem rozbioru syntaktycznego. Informację zgromadzoną w atrybutach wierzchołka wyprowadza się z jego otoczenia. Obliczenie atrybutów i sprawdzenie ich zgodności jest zadaniem analizy semantycznej. Optymalizację i generację kodu równieŝ moŝna opisać w podobny sposób, uŝywając atrybutów do sterowania przekształcaniem drzewa i w końcu do sterowania wyborem instrukcji maszynowych. Wykorzystanie gramatyk atrybutywnych Teoretyczny mechanizm gramatyk atrybutywnych moŝe być wykorzystany: w analizie semantycznej do skontrolowania tych wszystkich aspektów kodu źródłowego, które nie zostały zbadane przez analizator leksykalny i syntaktyczny, przy wykonywaniu tłumaczenia do kodu pośredniego, przy obliczaniu pewnych wartości związanych z drzewem rozbioru (np. konstrukcja kalkulatora software owego, do wykonywania pewnych akcji związanych z węzłami drzewa rozbioru (np. zapis lub odczyt z tablicy symboli, utworzenie lub wykorzystanie innych struktur danych, zapis lud odczyt z pliku, wydrukowanie czegoś, itp.; akcje te nie są wyliczeniem wartości atrybutów w sensie dosłownym.
Odwrotna notacja polska (notacja postfiksowa Przypomnienie: notacja nawiasowa = notacja infiksowa odwrotna notacja polska = notacja postfiksowa Niech będą dane dwa zbiory: OPERATOR zbiór operatorów binarnych OPERAND zbiór pojedynczych operandów 1. Jeśli wyraŝenie E w notacji infiksowej jest pojedynczym operandem (E OPERAND, to postać postfiksowa tego wyraŝenia to E. 2. Jeśli E 1 Θ E 2 jest wyraŝeniem w postaci infiksowej, E 1 i E 2 są wyraŝeniami w notacji infiksowej, Θ OPERATOR, to: E 1 E 2 Θ jest zapisem postfiksowym wyraŝenia E 1 Θ E 2 przy czym: E 1 i E 2 są odpowiednikami wyraŝeń E 1 i E 2 w notacji postfiksowej 3. Jeśli (E jest wyraŝeniem infiksowym, to: E jest zapisem wyraŝenia (E w notacji postfiksowej przy czym E jest odpowiednikiem wyraŝenia E w notacji infiksowej. Przykłady Notacja infiksowa: a+b*c Notacja postfiksowa: abc*+ Notacja infiksowa: a*b+c Notacja postfiksowa: ab*c+ Notacja infiksowa: (a+b*c Notacja postfiksowa: ab+c* Notacja infiksowa: a*(b+c Notacja postfiksowa: abc+*
Przykład translacja wyraŝeń do odwrotnej notacji polskiej (ONP + T E.t E 1.t T.t + E T E.t T.t T T 1 * F T.t T 1.t F.t * T F T.t F.t F (E F.t E.t F F.t name(.lexptr gdzie: - operator konkatenacji tekstów RozwaŜane słowo źródłowe: a+(b+c*d Po analizie leksykalnej: 1 +( 2 + 3 * 4.lexptr 1 2 3 4 name(.lexptr a b c d S := E + E 2 * E 2 E (E 1 E.lexptr 1 2 3 4 Przykład akcji translacja instrukcji przypisania do kodu trójadresowego S name(.lexptr gen(s := E E new_temp( gen(e := E 1 + E 2 E new_temp( gen(e := E 1 * E 2 E E 1 E name(.lexptr gdzie: - operator konkatenacji tekstów RozwaŜane słowo źródłowe: d:=a+(b+c*d Po analizie leksykalnej: 4 := 1 +( 2 + 3 * 4 name(.lexptr a b c d.lexptr=4 S := E.lexptr=1 E * E ( E S=d E=a E=b.lexptr=2 E=t 3 E=t 1 E=t 1 E=t 2 E=c.lexptr=3 E=d.lexptr=4
Przykład akcji translacja instrukcji przypisania do kodu trójadresowego S := E + E 2 * E 2 E (E 1 E S name(.lexptr gen(s := E E new_temp( gen(e := E 1 + E 2 E new_temp( gen(e := E 1 * E 2 E E 1 E name(.lexptr słowo źródłowe: d:=a+(b+c*d Tłumaczenie: t 1 := b + c.lexptr=4 S := E.lexptr=1 S=d E=a E * E ( E E=b E=t 3 E=t 1 E=t 1 E=t 2 E=c E=d.lexptr=4.lexptr=2.lexptr=3 Przykład akcji translacja instrukcji przypisania do kodu trójadresowego S := E + E 2 * E 2 E (E 1 E S name(.lexptr gen(s := E E new_temp( gen(e := E 1 + E 2 E new_temp( gen(e := E 1 * E 2 E E 1 E name(.lexptr słowo źródłowe: d:=a+(b+c*d Tłumaczenie: t 1 := b + c t 2 := t 1 * d.lexptr=4 S := E.lexptr=1 E * E ( E S=d E=a E=b.lexptr=2 E=t 3 E=t 1 E=t 1 E=t 2 E=c.lexptr=3 E=d.lexptr=4
Przykład akcji translacja instrukcji przypisania do kodu trójadresowego S := E + E 2 * E 2 E (E 1 E S name(.lexptr gen(s := E E new_temp( gen(e := E 1 + E 2 E new_temp( gen(e := E 1 * E 2 E E 1 E name(.lexptr słowo źródłowe: d:=a+(b+c*d Tłumaczenie: t 1 := b + c t 2 := t 1 * d t 3 := a + t 2.lexptr=4 S := E.lexptr=1 E * E ( E S=d E=a E=b.lexptr=2 E=t 3 E=t 1 E=t 1 E=t 2 E=c.lexptr=3 E=d.lexptr=4 Przykład akcji translacja instrukcji przypisania do kodu trójadresowego S := E + E 2 * E 2 E (E 1 E S name(.lexptr gen(s := E E new_temp( gen(e := E 1 + E 2 E new_temp( gen(e := E 1 * E 2 E E 1 E name(.lexptr słowo źródłowe: d:=a+(b+c*d Tłumaczenie: t 1 := b + c t 2 := t 1 * d t 3 := a + t 2 d := t 3.lexptr=4 S := E.lexptr=1 E * E ( E S=d E=a E=b.lexptr=2 E=t 3 E=t 1 E=t 1 E=t 2 E=c.lexptr=3 E=d.lexptr=4
Przykłady reguł semantycznych Deklaracje typu: P D ; S D D ; D D : T T char T integer T boolean T T 1 T array [num] of T 1 {addtype(.entry, T.type} {T.type char} {T.type integer} {T.type boolean} {T.type pointer(t 1.type} {T.type array(1..num.val, T 1.type} Przykłady reguł semantycznych Ustalanie typu wyraŝeń: E num E num. num E op E 2 {E.type integer} {E.type real} {E.type lookup(.lexptr} {E.type if E 1.type = integer and E 2.type = integer then integer else if E 1.type = integer and E 2.type = real then real else if E 1.type = real and E 2.type = integer then real else if E 1.type = real and E 2.type = real then real else type_error}
Przykłady reguł semantycznych Kontrola typu instrukcji: S := E S if E then S 1 S while E do S 1 S S 1 ; S 2 {S.type if lookup(.entry = E.type then vo else type_error} {S.type if E.type = boolean then S 1.type else type_error} {S.type if E.type = boolean then S 1.type else type_error} {S.type if S 1.type = vo and S 2.type = vo then vo else type_error} Gramatyka atrybutywna (1 Gramatyka atrybutywna jest oparta na gramatyce bezkontekstowej G= V, Σ, P, S. Łączy ona z kaŝdym symbolem gramatyki X ( V atrybutów A ( X. KaŜdy atrybut X. a A( X Σ zbiór reprezentuje specyficzną własność symbolu X i moŝe przyjąć którąkolwiek wartość z pewnego zbioru wartości. A X. KaŜdy wierzchołek w drzewie rozbioru syntaktycznego słowa z języka L ( G jest związany ze zbiorem wartości atrybutów dla tego symbolu X, który stanowi etykietę tego wierzchołka. Wartości atrybutów ustala się za pomocą reguł semantycznych. X.a oznacza atrybut a będący elementem zbioru (
Zbiór R ( p : Gramatyka atrybutywna (2 { } df ( = i. ( j.,..., k. R p X a f X b X c jest zbiorem reguł semantycznych dla produkcji ( p= X X X 0 i n 0 j n 0 k n 0 1... n Reguła semantyczna X i. a f ( X j. b,..., X k. c p P takiej, Ŝe: definiuje atrybut X i. a za pomocą atrybutów X. b,..., X. c symboli z tej samej produkcji. j k Gramatyka atrybutywna (3 Gramatyka atrybutywna AG jest trójką: AG = G, A, R gdzie: G= V, Σ, P, S G BK gramatyka bezkontekstowa ( V X Σ ( A= A X skończony zbiór atrybutów ( p R= R skończony zbiór reguł semantycznych p P ( ( Jeśli A X A Y to X=Y Dla kaŝdego wystąpienia X w drzewie rozbioru syntaktycznego słowa z języka L ( G, do obliczenia kaŝdego atrybutu X. a A( X moŝna zastosować co najwyŝej jedną regułę semantyczną.
Gramatyka atrybutywna (4 p= X X X P zbiorem Dla kaŝdej produkcji ( 0 1... n definiujących wystąpień atrybutów jest: AF p = X. a : X. a f... R p { i i } ( ( ( Atrybut X.a nazywamy syntetyzowanym df p= X χ P : X. a AF p ( ( Atrybut X.a nazywamy dziedziczonym df p= Y µ Xν P : X. a AF p ( ( Gramatyka atrybutywna (5 X ( V Σ zachodzi AS( X AI( X gdzie: df = { } AS( X = X. a : p= ( X χ P X. a AF( p AS ( X zbiór atrybutów syntetyzowanych dla X ( V Σ df { } AI( X = X. a : q= ( Y µ Xν P X. a AF( q AI ( X zbiór atrybutów dziedziczonych dla X ( V Σ Ponadto istnieje co najwyŝej jedna reguła. a f(... R ( p dla kaŝdego p P i X. a A( X. X w zbiorze
Gramatyka atrybutywna (6 Definicja: Gramatyka atrybutywna jest zupełna, jeśli dla wszystkich symboli X V Σ są spełnione następujące warunki: ( p= ( X χ P : AS( X AF( p q= ( Y µ Xν P : AI( X AF( q AS ( X AI( X = A( X Ponadto: AI( S = Definicja Gramatyka atrybutywna jest dobrze zdefiniowana jeśli dla kaŝdego drzewa rozbioru syntaktycznego słowa z L ( G wszystkie atrybuty są efektywnie obliczalne. Gramatyki S-atrybutywne Gramatyką atrybutywną klasy S (gramatyką S-atrybutywną nazywamy gramatykę atrybutywną zawierającą tylko i wyłącznie atrybuty syntetyzowane. Mogą one być obliczone z wykorzystaniem drzewa rozbioru syntaktycznego metodą bottom-up ( por. poprzedni przykład z translacją wyraŝeń do ONP; por. następny przykład kalkulatora.
Przykład kalkulator + T E T T T 1 * F T F F (E F num E.val E 1.val + T.val E.val T.val T.val T 1.val * F.val T.val F.val F.val E.val F.val value(num.lexptr E E.val=19 Słowo źródłowe: 4+3*5 Po skanerze: num 1 +num 2 *num 3 Tablica symboli: num.lexptr value(num.lexptr 1 4 2 3 3 5 E E.val=4 + T T F num T.val=4 F.val=4 num.lexptr=1 T F num T.val=3 F.val=3 num.lexptr=2 T.val=15 * F num F.val=5 num.lexptr=3 Translacja bottom-up dla gramatyk S-atrybutywnych
Przykład kalkulator c.d. L E$ + T E T T T 1 * F T F F ( E F num L.b print(e.val E.val E 1.val + T.val E.val T.val T.val T 1.val * F.val T.val F.val F.val E.val F.val value(num.lexptr print(attr[top-1] attr[ntop] := attr[top-2] + attr[top] attr[ntop] := attr[top-2] * attr[top] attr[ntop] := attr[top-1] attr[ntop] := value(attr[top] ZałoŜenie: po shift num na stosie attr umieszczana jest wartość num.lexptr Słowo wejściowe: num 1 * num 2 + num3$ (3*5+4 num.lexptr value(num.lexptr 1 3 2 5 3 4 Przykład kalkulator c.d. Słowo wejściowe: num 1 * num2 + num3$ (3*5+4 wejście state attr Produkcja num*num+num$ *num+num$ num 1 *num+num$ F 3 F num *num+num$ T 3 T F num+num$ T* 3 +num$ T*num 3 2 +num$ T*F 3 5 F num +num$ T 15 T T * F +num$ E 15 E T num$ E+ 15 $ E+num 15 3 $ E+F 15 4 F num $ E+T 15 4 T F $ E 19 E E+ T E$ 19 L (* (* wydrukowanie wartości =19