Wykład 6. Gramatyki atrybutowe
Transkrypt
Wykład 6. Gramatyki atrybutowe
AGK 2008 Gramatyki atrybutowe 1 Wykład 6. Gramatyki atrybutowe1 Jak wiadomo, gramatyki bezkontekstowe nie wystarczają do zdefiniowania języków programowania, opisują one jedynie ich część składniową. Opis języka powinien zawierać równieŜ część semantyczną, opisującą znaczenie (interpretację) poszczególnych konstrukcji języka a takŜe wyraŜające pewne warunki kontekstowe języka, których spełnienie gwarantuje, Ŝe pewne programy są poprawne. W kompilatorach wykorzystuje się model opisu semantycznego sterowanego składnią. Chodzi o to, by proces konstruowania drzewa wywodu był ściśle związany z konstrukcją obiektu semantycznego przyporządkowanego temu drzewu. Mówiąc inaczej, znaczenie drzewa wywodu budowanego z produkcji gramatyki bezkontekstowej powstaje przez zastosowanie pewnych reguł semantycznych związanych z tymi produkcjami. Technika ta pochodzi od Knutha i jest podstawą praktycznych rozwiązań przy projektowaniu kompilatorów. Jej podstawą jest system złoŜony z gramatyki bezkontekstowej i atrybutowej specyfikacji semantycznej nazywany gramatyką atrybutową. Zanim wprowadzimy formalną definicje gramatyki atrybutowej ustalimy, Ŝe poniewaŜ naszych zainteresowań będą drzewa wywodu gramatyki bezkontekstowej, wygodnie będzie utoŜsamiać kaŜdą produkcję z prostym drzewem etykietowanym symbolami alfabetu gramatyki. Tak więc produkcję X0X1X2...XN będziemy utoŜsamiać z etykietowanym i uporządkowanym drzewem na poniŜszym rysunku: 1 P. Dembiński, J. Małuszyński Warszawa 1981 „Matematyczne metody definiowania języków programowania”, WNT, AGK 2008 Gramatyki atrybutowe (a) 1 X1 2 0 X0 (b) 0 X0 1ε 2 X2 N XN ....... . Drzewo produkcji przy N > 0 Drzewo produkcji przy N=0 W ten sposób kaŜde drzewo wywodu ma jednoznaczny rozkład na zbiór drzew, z których kaŜde jest izomorficzne z pewną produkcją rozpatrywanej gramatyki. Nieformalnie, gramatyka atrybutowa to system złoŜony z gramatyki bezkontekstowej oraz zbiorów tzw. reguł semantycznych, związanych z produkcjami gramatyki bezkontekstowej. Reguły semantyczne określają sposób obliczania wartości pewnych atrybutów w wierzchołkach drzew wywodu tej gramatyki. Znaczenie przypisane drzewu moŜna określić w ten sposób jako wartość pewnego atrybutu (wartości pewnych atrybutów) obliczonego (obliczonych) dla korzenia tego drzewa. Przykład. Rozpatrzmy prostą gramatykę generującą język ciągów zerojedynkowych. Za znaczenie kaŜdego takiego ciągu będziemy uwaŜać liczbę, którą on reprezentuje w notacji dwójkowej. W myśl poprzednich uwag reguły semantyczne tej gramatyki powinny wyznaczyć tę liczbę jako wartość pewnego atrybutu w korzeniu kaŜdego drzewa wywodu tej gramatyki. Odpowiednim atrybutem jest w tym przypadku L Produkcje gramatyki bezkontekstowej i odpowiadające im reguły semantyczne przedstawia poniŜszy rysunek. AGK 2008 Gramatyki atrybutowe 3 PRODUKCJE REGUŁY SEMANTYCZNE N0 L1 L(0) = L(1); W(1) = 0; L(0) = L(1)+L(2); W(1) = W(0) + 1; W(2) = W(0) L(0) = L(1); W(1) = w(0); L0 L1 C2 L0 C1 C0 0 C0 1 L(0)= 0 L(0)=2w(0) Indeksy przy symbolach nieterminalnych oznaczają wierzchołki drzewa produkcji, tzn. produkcja L LC jest zapisana jako L 0 L 1 C 2 dla oznaczenia, Ŝe L etykietuje wierzchołek 0 i 1 w produkcji, a C wierzchołek 2. Stąd reguły semantyczne moŜna odczytywać jako zapis pewnego warunku, który musi być spełniony przez wartości atrybutów w odpowiednich wierzchołkach. Głową gramatyki jest symbol N. Atrybuty: L (liczba) i W (wykładnik) mogą przyjmować wartości ze zbioru nieujemnych liczb całkowitych. Na poniŜszym rysunku znajduje się drzewo wywodu dla ciągu 101 oraz odpowiedni zbiór reguł semantycznych, wyznaczony podczas analizy syntaktycznej. L0 L1 C2 odpowiadają dwie Przykładowo w drzewie wywodu produkcji produkcje: L1 L2 C3 i L2 L4 C5 dlatego w zbiorze reguł będą reguły związane z tymi produkcjami, odpowiednio: L(1) = L(2)+L(3) i W(2) = W(1) + 1; W(3) = W(1) oraz L(2) = L(4)+L(5) i W(4) = W(2) + 1; W(5) = W(2). Obliczając wartości atrybutów L i W we wszystkich wierzchołkach drzewa, otrzymamy, Ŝe L(0) = 5, czyli wartość dziesiętną analizowanego ciągu 101. AGK 2008 Gramatyki atrybutowe 2 4 0 N L(0) = L(1) ; W(1) = 0 L(1) = L(2) + L(3); W(2) = W(1) + 1 W(3) = W(1) 1 L L(2) = L(4) + L(5) W(4) = W(2) +1 W(5) = W(2) L(3) = 2 W( 3 ) L 3 C L(4) = L(7) L(5) = 0 L(7) =2 W( 7 ) 4 L 5 C 6 W(7) = W(4) 1 L(0) = 5 7 C 9 1 8 0 L(1) = 5, L(2) = 4, L(3) = 1, L(4) = 4, L(5) = 0, L(7) = 4, W(1) = 0 W(2) = 1 W(3) = 0 W(4) = 2 W(5) = 1 W(7) = 2 Aby zdefiniować formalnie gramatyki atrybutowe wprowadzimy następujące parami rozłączne zbiory symboli: At – atrybuty Fn – symbole funkcyjne n-argumentowe, n=0,1,2, ... przy czym F0 oznacza symbole stałych W – wierzchołki. Zbiór Term określamy jako najmniejszy zbiór słów nad alfabetami At, W i Fn n=0, 1, 2, ... , taki, Ŝe (1) F0 ∈ Term (2) JeŜeli a∈At i w∈W to a(w) ∈ Term (3) JeŜeli f∈Fn , n = 0,1,2, ... oraz t1, t2,...,tn ∈Term to f(t1, t2,...,tn) ∈ Term Regułą semantyczną nazywamy parę termów, którą będziemy zapisywać w postaci równania: t1 = t2. AGK 2008 Gramatyki atrybutowe Interpretacja I 5 to odwzorowanie, które (a) dla kaŜdego a∈At przyporządkowuje dziedzinę wartości DaI oraz (b) dla kaŜdego symbolowi funkcyjnemu f∈ Fn, n=0,1,2, ... przyporządkowuje n-argumentową funkcję: f I : D1× D2×...× Dn D0 W praktyce termy zapisujemy w naturalny sposób, np. t(a przy czym termy a j (ij) 1 ( i 1 ),..., a k (ik) będą traktowane jako zmienne. Wartość termu t w interpretacji I jest zdefiniowana przez nadanie konkretnych wartości z dziedziny Da j I zmiennym a j (ij) . Niech p będzie produkcją gramatyki bezkontekstowej. Reguła semantyczna t1 = t2 jest regułą semantyczną produkcji p, jeŜeli kaŜdy wierzchołek występujący w termach t1, t2 jest wierzchołkiem p. Definicja. Gramatyką atrybutową nazywamy systemem GAT = (G, {RS(p)}p∈P, I), przy czym: G = (N, ∑, P, S) – jest gramatyka bezkontekstowa, {RS(p)} p∈P – jest zbiorem reguł semantycznych dla produkcji P I – jest interpretacją dla zbioru RS(p). ) AGK 2008 Gramatyki atrybutowe 6 Gramatyki atrybutowe w sensie Knutha. Wprowadzimy teraz definicję gramatyki atrybutowej w sensie Knutha. Niech G =(N, ∑, P, S) – będzie gramatyką bezkontekstową, At – zbiór atrybutów. KaŜdemu symbolowi nieterminalnemu X∈N przyporządkujemy skończony zbiór atrybutów At(X)⊂ At . Zbiór At(X) dzielimy na dwa rozłączne zbiory atrybutów syntezowalnych AtS (X) i atrybutów dziedziczonych AtD (X). At(x)= AtD (X) ∪ AtS (X) Mówiąc ogólnie atrybuty syntezowalne (dziedziczone) to te, których wartość w wierzchołku drzewa wywodu zaleŜy od wartości atrybutów w wierzchołkach będących następnikami (poprzednikami) danego wierzchołka. Definicja Gramatyka atrybutowa GAt = ( G, {RS(p)}p∈∈P, I ) jest gramatyką w sensie Knutha, jeŜeli dla kaŜdej produkcji p: X0 X1 ... Xnp , zbiór reguł semantycznych RS(p) składa się z reguł postaci: a0(i0) = t (a1(i1), ... ,ak(ik)), 1. dla kaŜdego j = 0,1,...,k, przy czym: Xi j jest wystąpieniem symbolu nieterminalnego po prawej stronie produkcji p (czyli 0 ≤ ij ≤ np i Xij ∈N) 2. jeśli i0 = 0, to a0 ∈ AtS (X0) oraz dla kaŜdego a ∈ AtS(X0), istnieje dokładnie jedna reguła powyŜszej postaci , dla której a = a0 i i0 = 0. 3. jeŜeli i0 ≠ 0 to a0 ∈ AtD(X0) oraz dla kaŜdego wystąpienia Xk, 1 ≤ k ≤ np, symbolu nieterminalnego X po prawej stronie produkcji p i kaŜdego atrybutu dziedzicznego, a ∈ AtD(X) istnieje dokładnie jedna reguła powyŜszej postaci taka, Ŝe a = a0 i i0 =k. Innymi słowy, w zbiorze RS(p) istnieje dokładnie jedna reguła Ŝądanej postaci dla kaŜdego syntezowanego atrybutu lewej strony produkcji i kaŜdego dziedziczonego AGK 2008 Gramatyki atrybutowe 7 atrybutu dowolnego wystąpienia symbolu nieterminalnego po prawej stronie produkcji p. RozwaŜmy teraz dowolne drzewo wywodu gramatyki G. Niech w będzie dowolnym wierzchołkiem tego drzewa etykietowanym pewnym symbolem X oraz niech a∈At (X). Przy powyŜszych załoŜeniach o gramatyce atrybutowej, w zbiorze równań (reguł) semantycznych tego drzewa istnieje dokładnie jedno równanie postaci: a(w0) = t(a1(w1), ... , ak(wk)). Powiemy, Ŝe wartość zmiennej a(w) jest określona przez układ równań i równa się v, tzn. wartość atrybutu a w wierzchołku w jest określona, jeŜeli przedtem określone są przez układ równań v1,...,vk wartości zmiennych a1(w1),...,ak(wk) i v jest wartością termu t przy interpretacji I dla v1,..., vk. Innymi słowy, po to, Ŝeby obliczyć a(w), musimy najpierw obliczyć a(w1),...,a(wk). Powiemy, Ŝe a(w) bezpośrednio zaleŜy od a(wi) Przechodnie domknięcie tej relacji daje nam relację dla i = 1,..., k. zaleŜności zmiennych występujących w układzie (równań) semantycznych związanych z drzewem wywodu. Definicja. Gramatyka atrybutowa w sensie Knutha jest poprawna (jej reguły są dobrze określone), jeŜeli dla kaŜdego drzewa wywodu, kaŜdego jego wierzchołka w i kaŜdego atrybutu a∈At(X), gdzie X etykietuje w, wartość a(w) jest określona przez układ równań tego drzewa. W terminach relacji zaleŜności znaczy to, Ŝe Ŝadna zmienna a(w) występująca w układzie równań dla drzewa wywodu nie jest zaleŜna od samej siebie. Czyli graf skierowany relacji zaleŜności dla tego układu równań nie zawiera cykli. Knuth podał algorytm, rozstrzygający poprawność gramatyk atrybutowych na podstawie reguł semantycznych gramatyki atrybutowej. Idea tego algorytmu opiera się na spostrzeŜeniu, Ŝe kaŜdy graf relacji zaleŜności zmiennych w równaniach jest złoŜony z podgrafów, które odpowiadają grafom relacji zaleŜności dla reguł semantycznych poszczególnych produkcji gramatyki. AGK 2008 Gramatyki atrybutowe PoniŜej przedstawiano 8 przykład grafu zaleŜności dla układu równań poprzedniego przykładu oraz grafy relacji zaleŜności dla reguł semantycznych produkcji przykładowej gramatyki. ZauwaŜmy na koniec, Ŝe problem dobrej określoności gramatyki atrybutowej Knutha jest istotny gdy w gramatyce tej występują atrybuty dziedziczone. Z drugiej strony wiadomo, Ŝe nie są one konieczne – teoretycznie wystarczają atrybuty syntezowane. JednakŜe, jak pokaŜą kolejne przykłady dzięki atrybutom dziedziczonym reguły semantyczne mają naturalną i prostszą postać. Dla gramatyk atrybutowych dobrze określonych w sensie Knutha i zawierających oba rodzaje atrybutów jeśli dane słowo jest akceptowane otrzymujemy drzewo wywodu, którego wierzchołki zawierają wartości atrybutów. Obliczanie wartości tych atrybutów w terminach drzew sprowadza się wykonania procedury przechodzenia w głąb od korzenia drzewa wywodu. Procedure Przech_wglab (n : node); Begin For each dziecka ‘c’ wezła ‘n’ od lego do prawego do Begin Oblicz_atrybuty_dziedziczone( wezła c); Przech_wglab ( c ); End; Oblicz_atrybuty_syntezowane( wezła n) End; AGK 2008 Gramatyki atrybutowe rys. Graf zaleŜności atrybutów dla produkcji 9 AGK 2008 Gramatyki atrybutowe 10 Zastosowanie gramatyk atrybutowych do definiowania semantyki języków programowania Przykład1. WyraŜenie warunków kontekstowych języka. W tym przykładzie rola reguł semantycznych i atrybutów sprowadza się do tego, aby kaŜdego drzewa wywodu gramatyki bezkontekstowej generującego przykładowy język programowania moŜna było zdecydować, czy programy przezeń generowane spełniają pewne warunki kontekstowe, w szczególności, czy zachodzi poprawność wyraŜeń i deklaracji oraz zgodność uŜycia zmiennych z ich deklaracjami w programach. Przed podaniem reguł semantycznych wprowadzone zostaną atrybuty i dziedziny ich wartości. Atrybuty Dziedziny wartości tekst Słowa nad alfabetem języka typ {int, boolean} Ot Funkcje przyporządkowujące zmiennym wartości ze zbioru {int, boolean} dekl, zm Zbiory zmiennych Wartością atrybutu tekst jest znak lub ciąg znaków alfabetu, który określa identyfikator w programie. Atrybut typ decyduje o poprawności wyraŜeń i ich uŜycia w programie ze względu na ‘otoczenie’, czyli wartość atrybutu Ot. Ten ostatni zostaje zdeterminowany przez deklaracje. Związek między otoczeniem i typem wyraŜenia w produkcji <wyr>0 <zm>1, opisuje reguła: typ(0) = Ot(0) (tekst(1)), która mówi, Ŝe typ wyraŜenia będącego zmienną musi być równy zadeklarowanemu typowi tej zmiennej. Podobnie reguła typ(2) = Ot(0) (tekst(1)), dla instrukcji przypisania <ins>0 <zm>1:= <wyr>2, wiąŜe typ zmiennej po lewej stronie z typem wyraŜenia po prawej stronie instrukcji przypisania. AGK 2008 Gramatyki atrybutowe 11 Atrybut typ nie dopuszcza ponadto innych wyraŜeń niŜ logiczne w instrukcjach if-then-else i while oraz eliminuje błędne uŜycie operatorów w wyraŜeniach. Atrybut dekl okresla zbiór zmiennych zadeklarowanych w programie, a atrybut zm zbiór zmiennych uŜytych. AGK 2008 Gramatyki atrybutowe 12 Reguła dekl(1) = zm(2) związana z produkcją: <prog>0 begin <dkl>1 ; <ins>2 end, wyklucza programy, w których zbiory te są róŜne. Przykład 2. Translacja języka PJP na język pośredni. Docelowym językiem programowania będzie w tym przypadku język, którego instrukcje są jednej a następujących postaci: 1. (n, if, E, m) – skocz do m pod warunkiem E 2. (n, x:= E , m) – wykonaj przypisanie i skocz do m 3. (n, skocz, m) – skocz bezwarunkowo do m 4. (n, stop) – zakończ wykonanie, gdzie: x ∈ Ident, E ∈ Exp w sensie języka PJP oraz m i n są liczbami naturalnymi. Do zbioru atrybutów dokładamy kolejne atrybuty: Atrybuty Dziedziny semantycznie tłm Zbiory instrukcji postaci 1-4 (jak wyŜej) ep, ek Liczby naturalne Nowe reguły semantyczne dla przykładowej gramatyki podaje tabela 2.2, występuje w nich takŜe wcześniej wprowadzony atrybut tekst. Znaczeniem kaŜdego programu w języku PJP będzie wartość atrybutu tłm - tłumaczenie - w korzeniu drzewa wywodu tego programu. Atrybut tekst słuŜy do „przepisywania" odpowiednich tekstów wyraŜeń i podstawień języka PJP. AGK 2008 Gramatyki atrybutowe 13 Zastosujemy reguły semantyczne z tabeli 2.2 do drzewa wywodu : (w tym przypadku jednoznacznie wyznaczonego) następującego prostego programu: begin x:integer; i:integer; x := l ; while (i > O ) do x := (2 * x); i := (i - 1); od; end; AGK 2008 Gramatyki atrybutowe 14 Zbiór reguł dla powyŜszego programu: tłm(5) = {(ep(5), x:= 1, ek(5))} ; ek(5) = ep(5) +1; tłm(6) = {(ep(6), x:= (2*x) , ek(6))} ; ek(6) = ep(6) +1; tłm(7) = {(ep(7), i:= (i-1) , ek(7))} ; ek(7) = ep(7) +1; tłm(4) = tłm(6) ∪ tłm(7); ep(6) = ep(4); ep(7) = ek(6); ek(4) =ek(7); tłm(3) = tłm(4) ∪ {(ep(3), if, i>0, ep(4)), (ep(3), if, not (i>0), ek(3)), (ek(4), skocz, ep(3)) }; tłm(2) = tłm(5) ∪ tłm(3); ek(3) = ek(4)+1; ep(4) = ep(3) +1; ep(5) = ep(2); ep(3) = ek(5); ek(2) = ek(3); tłm(1) = tłm(2) ∪ {(ek(2), stop)}; ep(2) =1; Wartość atrybutu tłm zostanie jednoznacznie wyznaczona, poniewaŜ mamy do czynienia z poprawną atrybutową gramatyką w sensie Knutha. Atrybuty syntetyczne tej gramatyki to tekst, ek, i tłm, natomiast ep - atrybut dziedziczny. Po obliczeniu atrybutów ep i ek w wierzchołkach drzewa wywodu zadanego programu otrzymamy: n ep ek 2 1 6 3 2 6 4 3 5 5 1 2 6 3 4 7 4 5 AGK 2008 Gramatyki atrybutowe 15 Zatem wartość atrybutu tłm w korzeniu drzewa wywodu będzie następującym zbiorem instrukcji języka docelowego: (1, (2, (2, (3, (4, (5, x := l, if, (i>0), if, ~(i>0), x :=(2*x), i:=(i-l), skocz, 2) 3) 6) 4) 5) 2) Patrząc na otrzymany wynik nieco inaczej, moglibyśmy traktować go jako zbiór równań semantycznych przyporządkowany programowi, gdzie poszczególne elementy składowe instrukcji oznaczają konfiguracje sterowania i obiekty bazowe dziedziny interpretacji. Z jednej strony ich niesprzeczność oznacza w tym przypadku, poprawność semantyczną przykładowego programu, z drugiej równania te są opisem semantyki przykładowego języka.