Języki i gramatyki formalne Języki naturalne i formalne Cechy języka naturalnego - duża swoboda konstruowania zdań (brak ścisłych reguł gramatycznych), duża ilość wyjątków. Języki formalne - ścisły i jednoznaczny opis konstrukcji.
Gramatyki naturalne i formalne Gramatyki naturalne pozwalają określić zbiory reguł budowy zdań, Gramatyki formalne zajmują się pojęciami abstrakcyjnymi, powstającymi drogą uogólnienia grupy wyrazów, zadania Stanowią sposób badania i opisu zbioru reguł Języki formalne - definicje Alfabet V = {v 0,..., v n } dowolny skończony i niepusty zbiór symboli (liter), z których będą zestawiane słowa języka Słowo nad alfabetem V wszystkie skończone, uporządkowane ciągi złożone z elementów alfabetu. Słowo puste ε słowo nie mające żadnej litery
Języki formalne - definicje Język uniwersalny V* zbiór wszystkich słów nad alfabetem V Język dowolny podzbiór języka uniwersalnego V* nad V Syntaktyka (składnia) języka reguły budowy zdań w języku Semantyka języka interpretacja tych reguł, zasady stosowania składni Języki formalne - definicje Jeśli V= {a}, to V*= {ε, a, aa, aaa, } Jeśli V={a,b}, to V*={ε, a, b, aa, ab, bb, aaa, aab, } Długość słowa liczba jego liter
Przykład języka i gramatyki Gramatyka generująca słowa: aaaab, bbbb, a, b, Alfabet = { a, b }; Reguła 1: a jest poprawne (tzn. słowo złożone z a jest poprawne). Reguła 2: jeżeli a jest poprawne to ab też jest poprawne. Przykłady poprawnych słów: a - na podstawie Reguły 1. aab na podstawie Reguły 1 i Reguły 2. aaabb - na podstawie Reguły 1 i dwukrotnej Reguły 2. Typy gramatyk formalnych Gramatyka rozpoznająca dla dowolnego rozpatrywanego słowa potrafi rozstrzygnąć, czy słowo to jest poprawne czy nie, a w przypadku odpowiedzi pozytywnej potrafi podać wskazówki dotyczące budowy tego słowa Gramatyka generacyjna potrafi zbudować dowolne słowo poprawne, podając przy tym wskazówki dotyczące jego budowy oraz nie tworzy ani jednego słowa niepoprawnego
Typy gramatyk formalnych Gramatyka przetwarzająca dla dowolnie poprawnie zbudowanego słowa potrafi ona zbudować jego odwzorowania również w postaci słowa poprawnego, określając przy tym wskazówki dotyczące kolejności stosowania odwzorowań Gramatyka Noama Chomsky'ego Formalnie gramatykę określamy jako: G = < V, T, P, S > V zbiór symboli terminalnych skończony, niepusty zbiór symboli końcowych, z których budowane są słowa generowane przez gramatykę (zwany czasem alfabetem końcowym) T zbiór symboli nieterminalnych skończony, niepusty zbiór symboli pomocniczych P lista produkcji reguły gramatyki S symbol startowy (aksjomat) jest to wyróżniony symbol pomocniczy, z niego wyprowadzane są wszystkie generowane przez gramatyk G napisy.
Gramatyka Chomsky'ego - produkcje Produkcja możliwość zastąpienia symbolu pomocniczego przez słowo, w skład którego mogą wchodzić zarówno symbole pomocnicze, jak i końcowe. Proces wyprowadzania słów języka zdefiniowanego przez gramatykę odbywa się następująco: zaczynamy od symbolu S do poszczególnych symboli pomocniczych stosujemy którąś z produkcji ze zbioru P tak długo, aż wszystkie symbole pomocnicze znikną. Produkcje i wywód V* = { 1, 11, 111,... } Symbol początkowy: Produkcje: (reguły zastępowania) 1) 2) S S 1 S S 1 Wywód: 1: S 1 1 111: S 2 S 1 2 S 1 1 1 1 1 1
Produkcje cd. 1) 2) 3) 4) 5) S AB A 1 A A 1 B 0 B B 0 Wywód: 10: S 1 AB 2 1 B 4 1 0 100:? Gramatyka S AB A 1 A A 1 B 0 B B 0 Symbol początkowy
Gramatyka S AB A 1 A A 1 B 0 B B 0 Symbol początkowy Symbole nieterminalne T = {S, A, B} Gramatyka S AB A 1 A A 1 B 0 B B 0 Symbol początkowy Symbole nieterminalne T = {S, A, B} Symbole terminalne V = {0, 1}
Gramatyka S AB A 1 A A 1 B 0 B B 0 Symbol początkowy Symbole nieterminalne V = {S, A, B} Symbole terminalne T = {0, 1} Produkcje Przykłady gramatyk Gramatyka generująca wszystkie parzyste słowa złożone z samych liter (uwaga słowo puste jest słowem o parzystej długości!): G 1 =<{S}, {a}, {S ε, S aas}, S>
Przykłady gramatyk Gramatyka generująca wszystkie parzyste palindromy nad dwuelementowym alfabetem G 2 =<{S}, {a}, {S ε, S asa, S bsb}, S> Język generowany przez gramatykę To, co zostanie, czyli słowo złożone z samych symboli końcowych, nazywamy słowem wyprowadzalnym z gramatyki. Zbiór wszystkich słów wyprowadzalnych z danej gramatyki nazywa się językiem generowanym przez gramatykę.
Język generowany przez gramatykę Język generowany przez gramatykę G jest to zbiór wszystkich możliwych słów powstałych na bazie listy produkcji i wyprowadzonych z symbolu startowego języka Gdzie: L(G)={x: x V* S x} V* zbiór wszystkich możliwych słów proces wywodu słowa x z symbolu startowego S na podstawie listy produkcji P Przykład gramatyki generującej język L={a n b n c n d n, n=1, 2,..} Szukana gramatyka: G = < V, T, P, S > V = { S, B, D, E } T = { a, b, c, d} P = { r 1,, r 9 } Lista produkcji: r 1 : S abde r 2 : S abcd r 3 : B abde r 4 : B abc r 5 : bd bbc r 6 : cd Dc r 7 : ED DE r 8 : ce cdd r 9 : de dd
Przykład wywodu słowa aaabbbcccddd Wywód 3: Przykład wywodu słowa aaabbbcccddd Teraz nie osiągnęliśmy symboli końcowych. Ta gramatyka nie jest przydatna do definiowania języka programowania.
Zastosowania gramatyk Obiektem zastosowań teorii gramatyk są nie dowolne gramatyki, ale gramatyki poszczególnych typów Wyróżnienia tych typów dokonuje się na podstawie postaci reguł. Klasyfikacja Chomsky ego W teorii Chomsky ego wyróżnia się cztery typy gramatyk. Wyodrębnia się je przez nakładanie kolejno coraz silniejszych ograniczeń na układ reguł P Gramatyka klasy 0 charakteryzuje się tym, że wszystkie produkcje mają postać: u w, gdzie u V* \ { ε }, w V*
Klasyfikacja Chomsky ego Gramatyka klasy 1 (kontekstowa) charakteryzuje się tym, że wszystkie produkcje mają postać: uaw ubw, gdzie: u,w V*, A S, b V* \ { ε } Gramatyka klasy 2 (bezkontekstowa) w układzie reguł P dopuszcza się jedynie reguły postaci: A b, gdzie A S, b V* \ { ε } Klasyfikacja Chomsky ego Gramatyka klasy 3 (regularna, liniowa) w układzie reguł P dopuszcza reguły postaci: A bb, albo A Bb, gdzie A S, B S { ε }, b T* \ { ε }
Klasyfikacja Chomsky ego Każda gramatyka klasy i jest jednocześnie gramatyką klasy j dla 0 j i Każdy zbiór ciągów wywodliwych zgodnie z gramatyką klasy i jest jednocześnie zbiorem ciągów wywodliwych zgodnie z gramatyką niższych klas. Odwrotne twierdzenie nie jest prawdziwe. Im wyższa klasa gramatyki tym mniej precyzyjnie określa się rozmaitość wywodliwych ciągów. Klasyfikacja Chomsky ego Gramatyki klasy 0 Gramatyki kontekstowe Gramatyki bezkontekstowe Gramatyki liniowe
Ilustracja poszczególnych gramatyk Jako ilustrację do poszczególnych gramatyk rozpatrzymy przykład ciągów: aaa bbb ccc W skrócie będziemy je oznaczać a k b l c m Gramatyka regularna - przykład Nie nakładamy żadnych ograniczeń na wartości k, l, m Można znaleźć prawostronnie regularną gramatykę G = < V, T, P, S > generującą szukany ciąg: V = { a, b, c } T = { S, V, U} P = { r 1,, r 6 } Lista produkcji: r 1 : S as r 2 : S av r 3 : V bv r 4 : V bu r 5 : U cu r 6 : U c
Bezkontekstowa gramatyka - przykład Dla ciągów ograniczonych, gdzie k = m nie można zbudować gramatyki regularnej Ciągi można określić przez gramatykę bezkontekstową G = < V, T, P, S > : V = { a, b, c } T = { S, V} P = { r 1,, r 4 } Lista produkcji: r 1 : S asc r 3 : V Vb r 2 : S avc r 4 : V b Kontekstowa gramatyka - przykład Zdefiniowanie ciągów o jednakowej liczbie wystąpień dla każdej z liter (k = l = m) wymaga gramatyki kontekstowej lub gramatyki klasy 0, np. G = < V, T, P, S > : V = { a, b, c } T = { S, U } P = { r 1,, r 4 } Lista produkcji: r 1 : S abc r 3 : cu Uc r 2 : S asuc r 4 : bu bb
Gramatyki bezkontekstowe Gramatyka bezkontekstowa to skończony zbiór zmiennych (nazywanych symbolami niekońcowymi, pomocniczymi, kategoriami syntaktycznymi) z których każda reprezentuje pewien język Języki reprezentowane przez zmienne opisywane są za pomocą wzajemnej rekursji, z zastosowaniem symboli pierwotnych (końcowych) Reguły wiążące ze sobą zmienne nazywane są produkcjami Gramatyki bezkontekstowe Motywacją do wprowadzenia gramatyk bezkontekstowych był opis języków naturalnych. W kontekście jezyków naturalnych można zdefiniować reguły: < zdanie > < fraza rzeczownikowa >< frazaczasownikowa > < fraza rzeczownikowa > < przymiotnik >< fraza rzeczownikowa > < fraza rzeczownikowa > < rzeczownik > < rzeczownik > chopiec < przymiotnik > wysoki
Gramatyki bezkontekstowe Mają szerokie zastosowanie praktyczne: Wykorzystywane są: do definiowania języków programowania do formalizacji pojęcia analizy syntaktycznej do upraszania translacji języków programowania Gramatyki bezkontekstowe przykład 1 Definicja wyrażenia arytmetycznego z operatorami * i +, oraz argumentami reprezentowanymi przez symbol id < wyrażenie > < wyrażenie >+ < wyrażenie > < wyrażenie > < wyrażenie > < wyrażenie > < wyrażenie > ( < wyrażenie > ) < wyrażenie > id
Gramatyki bezkontekstowe przykład 2 Stosując te wyrażenia wielokrotnie możemy otrzymać bardziej złożone wyrażenia: < wyrażenie > < wyrażenie >+ < wyrażenie > < wyrażenie > < wyrażenie > < wyrażenie > < wyrażenie > < wyrażenie > id < wyrażenie > ( < wyrażenie >+ < wyrażenie > ) id < wyrażenie > ( < wyrażenie >+ id) id < wyrażenie > ( < wyrażenie > ) < wyrażenie > ( id + id) id Notacja Backusa-Naura (BNF) Umożliwia opisanie gramatyki bezkontekstowej, w sposób w sposób alternatywny do algebraicznego zapisu. Podstawowe konwencje notacji BNF: symbole nieterminalne są zamknięte w nawiasy < > "strzałka" reguły reprezentowana jest przez ::= alternatywne wyprowadzenia: rozdzielone pionową kreską opcjonalne elementy: zamknięte w nawiasy [ ] jedno- lub wielokrotne powtórzenie: { } n 1 zerowe, jedno lub wiele powtórzeń: { } n 0 połączenie : { }
Przykład notacji algebraicznej i BNF Gramatyka G = < V, T, P, S > generująca proste wyrażenia arytmetyczne : V = {a, b, d, +, *, (, )} T = {W, K, C} Semantyka powyższych symboli jest następująca: W wyrażenie; K - składnik, C czynnik; Symbol startowy S: S = W P = { r 1,, r 10 } Przykład notacji algebraicznej V = {a, b, d, +, *, (, )} T = {W, K, C} W wyrażenie; K - składnik, C czynnik, Symbol startowy S: S = W Lista produkcji: r 1 : W K r 2 : W W + K r 3 : W K + W r 4 : K C r 5 : S C * K r 6 : S K * C r 7 : C a r 8 : C b r 9 : C d r 10 : C ( W )
Przykład notacji BNF V = {a, b, d, +, *, (, )} T = {W, K, C} W wyrażenie; K - składnik, C czynnik, Symbol startowy S: S = W <W> ::= <K> <W> + <K> <K> + <W> <K> ::= <C> <C> * <K> <K> * <C> <C> ::= ( <W> ) a b d Symbole zapisane bez nawiasów < > i nie będące symbolami używanymi przez notację BNF są symbolami terminalnymi. Drzewa wyprowadzeń Historię wyprowadzeń słowa w danej gramatyce możemy zapisać za pomocą drzewa wywodu (nazywanego też drzewem rozbioru lub drzewem analizy składniowej). Wierzchołki drzewa rozbioru etykietuje się albo symbolami terminalnymi, albo kategoriami syntaktycznymi, albo symbolem ε. Liście są etykietowane jedynie symbolami terminalnymi lub symbolem ε. Wierzchołki wewnętrzne są etykietowane jedynie kategoriami syntaktycznymi.
Przykład drzewa wyprowadzeń < wyrażenie > < wyrażenie >+ < wyrażenie > < wyrażenie > < wyrażenie > < wyrażenie > < wyrażenie > ( < wyrażenie > ) < wyrażenie > id < wyrażenie > < wyrażenie > <wyrażenie> * id ( <wyrażenie> ) < wyrażenie > + < wyrażenie > id id Przykład drzewa wyprowadzeń S ::= aas a A ::= SbA SS ba S aas asbas aabas aabbas aabbaa S a A S S b A a a b a
Przykład drzewa wyprowadzeń Drzewo wyprowadzeń dla ciągu znaków 3 * (2 + 14) przy użyciu gramatyki zdefiniowanej poniżej: <Cyfra> 0 1 2 3 4 5 6 7 8 9 <Liczba> <Cyfra> <Liczba> <Liczba> <Cyfra> <Wyrażenie> <Liczba> <Wyrażenie> ( < Wyrażenie> ) <Wyrażenie> <Wyrażenie> + <Wyrażenie> <Wyrażenie> <Wyrażenie> - <Wyrażenie> <Wyrażenie> <Wyrażenie> * <Wyrażenie> <Wyrażenie> <Wyrażenie> / <Wyrażenie> < W > < W > < W > * < L > ( ) < W > 3 < W > + < W > < L > 2 < L > < L > 1 4 Etapy konstruowania drzewa wyprowadzeń 3*(2+14) (a) Konstruujemy jednowierzchołkowe drzewo dla każdego symbolu terminalnego w drzewie. Używamy produkcji <Cyfra> 0 1 2 3 4 5 6 7 8 9 1 4 2 3
Etapy konstruowania drzewa wyprowadzeń 3*(2+14) (b) Określamy że cyfry są liczbami. Używamy produkcji <Liczba> <Cyfra> < L > < L > < L > 1 2 3 Etapy konstruowania drzewa wyprowadzeń 3*(2+14) (c) Określamy że cyfr i liczba jest liczba. Wynikiem drzewa jest 14. Używamy produkcji <Liczba> <Liczba> <Cyfra> < L > < L > 4 1
Etapy konstruowania drzewa wyprowadzeń 3*(2+14) (d) Tworzymy drzewa rozbioru dla wyrażeń 3, 2, 14. Używamy produkcji: <Wyrażenie> <Liczba> < W> < L > < W> < L > < W > < L > < L > 3 2 4 1 Etapy konstruowania drzewa wyprowadzeń 3*(2+14) (e) Tworzymy drzewo dla sumy 2 + 14. Używamy produkcji <Wyrażenie> <Wyrażenie> + <Wyrażenie> < W > < W> < L > + < W > < L > < L > 2 1 4
Etapy konstruowania drzewa wyprowadzeń 3*(2+14) (f) Tworzymy drzewo dla sumy (2 + 14). Używamy produkcji: < W > ( ) < W > <Wyrażenie> ( <Wyrażenie> ) < W> + < W > < L > < L > < L > 2 1 4 Etapy konstruowania drzewa wyprowadzeń 3*(2+14) < W > < W > < W > * < L > ( ) < W > < W > + < W > 3 < L > < L > (g) Tworzymy drzewo 3* (2 + 14). Używamy produkcji: <Wyrażenie> <Wyrażenie> * (<Wyrażenie> ) 2 < L > 4 1
Drzewa wyprowadzeń i drzewa wyrażeń Mając sformułowaną gramatykę wyrażeń możemy drzewa rozbioru przekonwertować na drzewa wyrażeń, dokonując trzech transformacji: 1. Wierzchołki związane z poszczególnymi operandami niepodzielnymi są łączone w jeden wierzchołek zaetykietowany danym operandem 2. Symbol operatora (np..+), staje się etykietą wierzchołka umieszczonego nad nim, który wcześniej był zaetykietowany kategoria syntaktyczna wyrażenia. 3. Wierzchołki wewnętrzne, których etykietami wciąż są wyrażenia zostają usunięte. drzewo wyprowadzeń < W > < W > < W > * < L > ( ) < W > 3 < W > + < W > < L > < L > drzewo wyrażeń 3 * ( + ) < L > 2 14 2 1 4
Niejednoznaczność i projektowanie gramatyk Rozważmy gramatykę: G = < {S}, {a,b}, {S ::= SaS b}, S > Za pomocą tej gramatyki możemy wygenerować dowolną naprzemienną sekwencję liter a oraz b zaczynającą się i kończącą na literę b. Na ile sposobów można otrzymać słowo babab? W notacji liniowej tych sposobów jest 12, np.: S SaS SaSaS SaSab basab babab S SaS Sab SaSab Sabab babab Niejednoznaczność i projektowanie gramatyk Istnieją dwa drzewa wyprowadzeń tego słowa: S SaS SaSaS SaSab basab babab S S a S S a S b b b
Niejednoznaczność i projektowanie gramatyk Istnieją dwa drzewa wyprowadzeń tego słowa: S SaS Sab SaSab Sabab babab S S a S b S a S b b Niejednoznaczność i projektowanie gramatyk Można gramatykę tak skonstruować, żeby słowo babab, podobnie jak i każde inne generowane przez powyższą gramatykę, miało tylko jedno drzewo wywodu. Oto ta gramatyka: G = < {S}, {a,b}, {S ::= ε, S ::= bas b}, S > Taka gramatyka ma już tylko jedno drzewo wyprowadzeń dla słowa babab.
Niejednoznaczność i projektowanie gramatyk Gramatyka G jest jednoznaczna, jeśli każde słowo wyprowadzalne z G ma tylko jedno drzewo wyprowadzeń. Gramatyka w której istnieją dwa lub więcej drzewa wyprowadzeń o tym samym wyniku oraz tej samej kategorii syntaktycznej etykietującej korzeń jest nazywana gramatyką niejednoznaczną. Wystarczy żeby istniał choć jeden taki ciąg który jest niejednoznaczny. Niejednoznaczność gramatyk wyrażeń może być poważnym problemem. Niektóre drzewa wyprowadzań mogą dawać złe wartości dla wyrażeń. Dwa drzewa rozbioru dla wyrażenia: 1-2+3 <W> <W> <W> + <W> <W> - <W> <W> - <W> <L> <L> <W> + <W> <L> <L> <C> <C> <L> <L> <C> <C> 3 1 <C> <C> 1 2 Poprawne drzewo wyprowadzeń 1-2+3 = 2 2 3 Niepoprawne drzewo wyprowadzeń 1-2+3=-4
Niejednoznaczność gramatyk <W> <W> * <W> <W> + <W> <L> <L> <L> <C> <C> <C> 3 <W> <L> <C> 1 <W> + <W> <W> * <W> <L> <L> <C> <C> 1 2 2 3 Niepoprawne drzewo wyprowadzeń 1 + 2 * 3 = 9 Poprawne drzewo wyprowadzeń 1 + 2 * 3 = 7 <W> <W> + <W> <S> - <S> <Cz> <L> <C> 1 <Cz> <L> <C> 2 <S> <Cz> <L> <C> 3 Poprawne drzewo wyprowadzeń 1 2 + 3 Poprawne drzewo wyprowadzeń 1 + 2 * 3 <W> <S> <Cz> <L> <C> 1 <W> + <S> <Cz> <L> <C> 2 <S> * <Cz> <L> <C> 3
Istota niejednoznaczności Analizator składniowy który konstruuje drzewa wyprowadzeń dla programów stanowi podstawowy element kompilatora. Jeżeli gramatyka opisująca język programowania jest niejednoznaczna, kompilator nie może podjąć prawidłowej decyzji odnośnie do drzewa rozbioru dla pewnych programów, a w związku z tym nie może zdecydować, jakie działania powinien wykonać program w języku maszynowym. Kompilatory muszą korzystać ze specyfikacji które są jednoznaczne. Zadania Dana jest gramatyka G = <V,T,P,S>: V = { S, A, B } T = { a, b, c } Produkcje: B aa B Sb A cab A BaA S c S ababb Przedstawić wywód i drzewo wywodu słowa abcbacabbaa. S ababb abbaabb absbaabb abcbaabb abcbacabbb abcbacabba
Zadania S ababb abbaabb absbaabb abcbaabb abcbacabbb abcbacabba S a b A b B B a B a a S b c a b c Zadania Zdefiniować gramatykę G generującą liczby całkowite. Liczba składa się z niepustego ciągu cyfr i może zawierać znak. V = {0,1,2,3,4,5,6,7,8,9,+,-} T = { LC, L, C, Z} Produkcje: <LC> ::= <Z><L> <L> <L> ::= <C><L> <C> <C> ::= 0 1 2 3 4 5 6 7 8 9 <Z> ::= + - S = LC
Dany jest język L(G): G = <V,T,P,S> V = { S, A } T = { a, b } Produkcje: S aas a Zadania A SbA SS ba Czy słowo aabbaa należy do języka? Aby słowo należało do języka należy udowodnić, że Słowo jest wyprowadzalne z S Słowo to musi należeć do T Zadania Dany jest język L(G): G = <V,T,P,S> T = {a,b,,z,+,(,),*} V = {W,S,C} Produkcje: <W> ::= <W>+<S> <S> <S> ::= <S>*<C> <C> <C> ::= (<W>) a b c... z S = W Czy słowo: (((a+b * d) * d + a)) + a+b+d jest słowem poprawnym języka L(G)?
Zadania Dany jest język L(G): G = <V,T,P,S> T = {a,b,,z,+,(,),*} V = {W,S,C} Produkcje: <W> ::= <W>+<S> <S> <S> ::= <S>*<C> <C> <C> ::= (<W>) a b c... z S = W Czy słowo: (((a+b * d) * d + a)) + a+b+d jest słowem poprawnym języka L(G)? <W> ::= <W>+<S> <S> <S> ::= <S>*<C> <C> <C> ::= (<W>) a b c... z S = W ( ( ( a + b * d ) * d + a ) ) + a + b + d C C C C C C C C S S S S S S W S W CS SW W CSW CSW W W W S
Literatura Harel D., Rzecz o istocie informatyki - algorytmika, WNT, Warszawa 2008 http://uranos.cto.us.edu.pl/~boryczka/ http://pl.wikipedia.org