1.1.5 Wybrane elementy teorii analizy tekstów Poprzednie
Transkrypt
1.1.5 Wybrane elementy teorii analizy tekstów Poprzednie
1.1.5 Wybrane elementy teorii analizy tekstów Poprzednie podrozdziały przedstawiły dwie podstawowe metody formalizacji: formalizację języka danej dziedziny wiedzy oraz formalizację dziedziny wiedzy opisanej matematycznie jako wielosortowa struktura relacyjna. Pokazane przykłady formalizacji ujawniły nam jednak, Ŝe formalizacja dokonywana jest z wykorzystaniem innej wiedzy niŜ wiedza, którą reprezentujemy – wykorzystujemy dodatkowo wiedzę o tym jak rozumieć formalnie (logicznie) opisywane reprezentacje wiedzy z danej dziedziny (obrazy, napisy, tabele decyzyjne itp.). ZauwaŜmy, Ŝe w kaŜdym obiekcie reprezentującym wiedzę W moŜe być reprezentowana takŜe wiedza o odniesieniach do wiedzy W, jak i wiedza o tworzeniu (produkcji, konstruowaniu, budowie) tych reprezentacji; ta dodatkowa wiedza jest niezbędna do tego, aby człowiek (agent) dysponując konkretną reprezentacją wiedzy W mógł wiedzę W pozyskać i zrozumieć (ogólnie, przetwarzać tę wiedzę) . JeŜeli jakiś konkretny obiekt słuŜący do reprezentacji wiedzy obejmuje wszystkie wyŜej opisane reprezentacje wiedzy: reprezentacje danej wiedzy, reprezentacje wiedzy na jaką wskazują te reprezentacje oraz reprezentacje o budowaniu reprezentacji wiedzy, to te reprezentacje będziemy nazywali tekstami (obiekty zawierające wszystkie z wymienionych typów reprezentacji nazywamy znakami). Przykładami obiektów zawierających czy udostępniających teksty są konkretne ksiąŜki, teksty dowodów twierdzeń czy wyszukiwarki internetowe. W ramach nauki logika, systemy wiedzy o tekstach (znakach) reprezentujących wiedzę i odnoszących się do wiedzy z danej dziedziny wiedzy nazywane są systemami tekstowymi (systemami znakowymi) lub systemami semiotycznymi w dziedzinie logiki zwanej semiotyką. Np. systemami tekstowymi są: wcześniej określana w systemie multimedialnym dowolna rzeczywistość wirtualna, a takŜe system znaków drogowych ustawionych na ulicach miasta, system tekstów mowy pisanej, reprezentującej słownictwo oraz zasady pisowni i zasady gramatyki, system określający język w lingwistyce matematycznej czy teorii automatów, system tekstów definiujących język programowania, systemy notacji języka formalnego – sieci semantyczne, systemy BNF, drzew wyprowadzeń oraz drzew struktur budowy formuł. W 1981 r. została wydana ksiąŜka Witolda Marciszewskiego „Metody analizy tekstu naukowego”. ChociaŜ praca ta była przygotowana dla wydawnictwa jako poradnik, czy przewodnik po wskazanej w tytule ksiąŜki dziedzinie wiedzy, poradnik przeznaczony dla nauczycieli akademickich i studentów, to prezentowała ona takŜe nowatorskie idee oraz wytyczała nowe kierunki badań. Zwłaszcza prekursorskie było zaproponowanie, jako głównego celu logicznej analizy tekstu, badania logicznego związku pomiędzy tematem (tekstem lub symbolem nieterminalnym) a rematem (tekstem lub symbolem terminalnym), tj. pomiędzy tymi fragmentami tekstu, które reprezentują wiedzę potrzebną do wyznaczenia i reprezentowania innej wiedzy, a tymi fragmentami tekstu, które reprezentują wiedzę wyznaczoną na podstawie tematu (symbolu nieterminalnego). W tym ujęciu, istotą logicznej poprawności jednostki tekstu jest występowanie logicznego stosunku pomiędzy tematem (symbolem nieterminalnym) i rematem (symbolem terminalnym). Ten związek logiczny ustala się dokonując formalnego opisu relacji określających zwartość tematyczną tekstów z danej dziedziny wiedzy, do której analizowany tekst naleŜy. Analizowane relacje zwane są relacjami nawiązywania. Na podstawie tych relacji jedne teksty są wyprowadzane z drugich, adekwatnie do wyznaczania jednej wiedzy przez drugą. W sensie wyprowadzalności tekstów, w dowolnym wyprowadzeniu jedne teksty są następnikami innych, w tym teksty wyprowadzane (rematy) są następnikami tekstów (tematów), z którymi pozostają w relacji nawiązywania. Relacja bycia następnikiem ustala pewien porządek tekstów, umoŜliwiający wykorzystanie do badania struktury tematycznej tekstu aparatu pojęciowego teorii krat. Ze względu na znaczenie pojęć tematu i rematu dla analizy tekstu, postuluje się utworzenie teorii, którą Autor omawianej pracy proponuje nazwać logiczną teorią tekstu. Standardowe procedury logicznej analizy tekstu mogły być rozpoznane dzięki określaniu języków programowania i zastosowaniom tych języków do implementacji algorytmów rozwiązujących zadania informatyczne, np. w programowaniu logicznym języka Prolog, czy bardziej dojrzałej postaci tego języka - języka Turbo Prolog1. Języki programowania określa się uŜywając symboli nieterminalnych (tematów) oznaczających operacje tworzące słowa języka z symboli terminalnych (rematów). Działanie wyszukiwarki internetowej wiąŜe podany prze uŜytkownika temat poszukiwań z z rematem – wynikiem tych poszukiwań. Definicja tekstu w edytorze TEX jest tematem edycji, a rematem jest wynik kompilacji tej definicji przez stosowny program edytora. W informatyce sformułowanie zadania (problemu) zawiera: dane wejściowe, stanowiące temat zadania oraz dane wyjściowe, stanowiące jego remat. W zapisie programu, tematy są zaimplementowane jako ciągi instrukcji przetwarzających dane wejściowe w dane wyjściowe, rematy są określone przez instrukcji określające, które z uzyskanych danych są wyjściowe oraz instrukcje ustalające zatrzymanie realizacji programu (instrukcje „stop”). Istotą programowania logicznego jest, jak się zazwyczaj postuluje: 1) taka formalizacja tekstu zadania, wyraŜonego w języku jakiejś dziedziny wiedzy, która reprezentuje (wyraŜa, przedstawia) wiedzę logiczną o danych i faktach, do których odwołuje się (nawiązuje) tekst zadania, a więc reprezentacja tego co jest dla tego tekstu i dla danej dziedziny wiedzy 1 Przystępne wprowadzenie do programowania w języku Turbo Prolog moŜna znaleźć w: J. Szajna, M. Adamski, T. Kozłowski, Programowanie w języku logiki, Warszawa 1991. tematem, utoŜsamianym w programowaniu logicznym z siecią semantyczną, 2) formalizacja relacji nawiązywania, ustalających sekwencje operacji prowadzących od danych i faktów do innych danych i faktów lub do nowych danych (szukanych) i ustaleń (tj. do rematu); w programowaniu logicznym sekwencjom tych operacji odpowiada przestrzeń rozwiązań, a zbiorowi relacji nawiązywania - baza wiedzy, 3) formalizacja wszystkich faktów określonych przez relacje nawiązywania występujące w tekście zadania; w programowaniu logicznym reprezentacji tych faktów odpowiada dynamiczna baza danych, 4) formalizacja zbioru danych, niekoniecznie występujących w tekście zadania, do których trzeba się odwołać, aby uzyskać to co jest szukane; w programowaniu logicznym odpowiada temu zewnętrzna baza danych, formalizacja zapytań, określających to co szukane i co ma być ustalone, a więc reprezentacja tego co jest dla danego tekstu zadania rematem. Podsumowując rozwaŜania dotyczące formalizacji naszkicujemy aparat pojęciowy umoŜliwiający sformułowanie logicznej teorii tekstu, podając stosowne postulaty znaczeniowe w języku teorii mnogości. Przez wiedzę będziemy rozumieć, jak poprzednio, informację przetwarzaną w umyśle człowieka, a przez reprezentację wiedzy, przedstawianie (kodowanie) wiedzy za pomocą róŜnorakich środków w ramach systemów komunikacji międzyludzkiej. Reprezentacje wiedzy są więc tekstami. Zrelatywizowanie reprezentacji wiedzy do dziedzin wiedzy prowadzi do wyodrębnienia tekstowych dziedzin wiedzy, a wyraŜanie tych tekstów w jakimś języku, do wyodrębnienia języka dziedziny wiedzy. Gdy wszystkie równokształtne teksty reprezentują tę samą wiedzę (w szczególności są pusto spełnione), a równokształtność jest kongruencją w tekstowej dziedzinie wiedzy, to tekstową dziedzinę wiedzy nazywamy systemem reprezentacji wiedzy. 1.1.5.1 Analiza tekstu w tekstowej dziedzinie wiedzy Strukturę relacyjną < U, U0, ε, R> nazywamy tekstową dziedziną wiedzy, gdy U jest niepustym zbiorem wszystkich tekstów reprezentujących wiedzę z pewnej dziedziny, U0 – wyróŜnionym niepustym podzbiorem zbioru U zwanym bazą tekstową, ε jest relacją częściowego porządku określoną na zbiorze U zwaną relacją bycia częścią tekstów, a R jest ustalonym zbiorem relacji określonych w U zwanych relacjami nawiązywania tekstów. Niech TDW = < U, U0, ε, R> jest tekstową dziedziną wiedzy. (a) Dwa teksty α,β∈U są równokształtne, gdy dwie struktury relacyjne powstałe przez ograniczenie uniwersum struktury TDW odpowiednio do zbiorów {t∈U : t ε α}, {t∈U : t ε β}, są izomorficzne oraz części tekstu α pozostają w tych samych relacjach w strukturze TDW co ich obrazy izomorficzne będące częściami tekstu β. (b) Tekst α jest wyprowadzalny ze zbioru tekstów X⊆U, co zapisujemy X |- R α, gdy istnieje taki tekst β, zwany wyprowadzeniem tekstu α ze zbiory X, i istnieje taki ciąg tekstów α1, α2, ..., αn ∈ U, Ŝe spełnione są warunki (1) teksty α1, α2, ..., αn zawarte są w tekście β, (2) αn = α, (3) dla dowolnych i≤n: bądź αi ∈ X, bądź istnieją takie i1, i2, ..., ik < i oraz istnieje taka relacja r ∈ R, Ŝe <αi1, αi2, ..., αik,, αi> ∈ r (4) β jest najmniejszym tekstem w <U, ε > spełniającym warunki (1)-(3). (c) Ramą zbioru tekstów X⊆U jest zbiór Fr(X) = {α∈U : X |- R α } (d) Poprawnie zbudowanymi są teksty naleŜące do zbioru Fr(U0). (e) Dla dowolnych tekstów α, β ∈U, α ≥ β wttw istnieje taki zbiór X tekstów, Ŝe β ∈ X i X |- R α i nieprawdą jest X\{β} |- R α, napis „α ≥ β” czytamy: α nawiązuje do β, lub α jest następnikiem β, (f) Dla dowolnego tekstu α∈U, zbiór Parts(α) = {t∈U : t ε α} zwany jest budową tekstu α. (g) Tekst β jest rematem tekstu α wttw β ∈ Fr(U0), α ≠ β, β ∈ Parts(α) oraz nie istnieje taki tekst t∈ Parts(α), Ŝe t≥β; innymi słowy: tekst β jest rematem tekstu α, gdy jest wyprowadzalny z tekstów bazowych (nawiązuje do tych tekstów), jest częścią właściwą tekstu α oraz Ŝadna część tekstu α nie jest jego następnikiem; intuicyjnie, remat danego tekstu jest tą jego częścią, która nie słuŜy do zrozumienia innych części tego tekstu, a jedynie sama moŜe być zrozumiana dzięki nawiązaniu do wcześniejszych tekstów, (h) Tekst t jest tematem tekstu α wttw t ∈ Fr(U0), α ≠ t, t ∈ Parts(α) oraz kaŜdy następnik t naleŜący do Parts(α) jest rematem α; innymi słowy: tekst t jest tematem tekstu α, gdy jest jego częścią właściwą, której kaŜdy następnik będący częścią α jest rematem; intuicyjnie, tematem danego tekstu jest kaŜda jego właściwa część, która słuŜy do zrozumienia rematu tego tekstu, tak więc, aby zrozumieć remat nawiązujemy najpierw do tematów, a następnie do tekstów, z których tematy są wyprowadzone, (i) Dowolny tekst jest jednostką tekstu, gdy posiada w swojej budowie rematy i tematy oraz gdy ze zbioru wszystkich tematów tego tekstu wyprowadzalny jest kaŜdy z rematów. ZauwaŜmy, Ŝe dowolne wyprowadzenie tekstu poprawnie zbudowanego jest jednostką tekstu. 1.1.5.2 Definicja systemu reprezentacji wiedzy WaŜne jest takŜe stwierdzenie, Ŝe dla dowolnej tekstowej dziedziny wiedzy TDW, w której wszystkie równokształtne teksty reprezentują tę samą wiedzę, jeŜeli relacja „~” równokształtności tekstów jest kongruencją w TDW (tj. zachodzenie relacji pomiędzy danymi tekstami przechodzi na zachodzenie tych samych relacji pomiędzy tekstami równokształtnymi do odpowiednich danych tekstów, np. jeśli relacja(tekst1, tekst2) i tekst1~tekst1’ oraz tekst2~tekst2’, to relacja(tekst1’, tekst2’)), to struktura ilorazowa TDW/~ jest takŜe tekstową dziedziną wiedzy. Uzasadnione jest więc sformułowanie następującej definicji: Niech w tekstowej dziedzinie wiedzy TDW wszystkie równokształtne teksty reprezentują tę samą wiedzę, a relacja „~” równokształtności tekstów jest kongruencją w TDW. Wtedy strukturę ilorazową TDW/~ nazywamy systemem reprezentacji wiedzy, relacje nawiązywania nazywamy relacjami konkatenacji, a o wyprowadzeniu danego tekstu mówimy, Ŝe jest konkatenacją pewnego ciągu tekstów określonego przez definicję wyprowadzenia tekstu. Tekstami są typy, tj. zbiory wszystkich tekstów równokształtnych w TDW. 1.1.5.3 Definicja języka sformalizowanego Przyjmijmy dalej, Ŝe wiedza logiczna jest informacją przetwarzaną w umyśle identyfikującą ogólną budowę, cechy i przyporządkowania wszelkich obiektów odnoszących się do danej dziedziny wiedzy oraz identyfikującą relacje pomiędzy tymi obiektami. Język, w którym przedstawiamy schematycznie, za pomocą schematów, tj. formuł, wzorów, planów, diagramów itp., wiedzę logiczną nazywamy językiem sformalizowanym. Język ten jest określony przez cztery zbiory symboli < Al, Tr, Fm, W>, Al jest alfabetem, Tr – zbiorem termów, Fm – zbiorem formuł, a W jest rodziną zbiorów formuł takich, Ŝe do kaŜdego z tych zbiorów naleŜą formuły reprezentujące wiedzę o tej samej wartości logicznej. Alfabet składa się ze stałych i zmiennych indywiduowych, będących zarazem termami, symboli funkcyjnych – wiąŜących stałe i zmienne w termy, predykatów – wiąŜących stałe i zmienne w formuły, spójników – wiąŜących formuły w inne formuły, kwantyfikatorów – wiąŜących zmienne i formuły w inne formuły oraz symboli pomocniczych (np. nawiasów, ramek, kropek, linii, strzałek itd.). Przykładem języka sformalizowanego jest język będący wynikiem formalizacji (schematyzacji) języka dowolnej dziedziny wiedzy. 1.1.5.4 Definicja systemu reprezentacji wiedzy Systemem reprezentacji wiedzy logicznej nazywamy system reprezentacji wiedzy, w którym zbiorem tekstów bazowych jest zbiór wszystkich symboli języka sformalizowanego, a zbiór relacji konkatenacji pozwala 1) wyróŜnić wszystkie składniki języka sformalizowanego, 2) wyprowadzić formuły poprawnie zbudowane, 3) tworzyć teksty wywodów prowadzących od formuł o określonej wartości logicznej do formuł o określonej wartości logicznej (niezmienniczość wartości logicznych względem wywodów). Systemy reprezentacji wiedzy logicznej są niekiedy nazywane logikami. W podrozdziale 1.2 określimy system zwany logiką pierwszego rzędu. 1.1.6 Pojęcie języka w lingwistyce matematycznej Najprostszymi przykładami systemów tekstowych w lingwistyce matematycznej lub teorii automatów skończonych albo teorii obliczeń (takŜe teorii algorytmów) są systemy dla których określamy pewne języki sformalizowane zwane językami abstrakcyjnymi, krótko językami. Niech V jest dającym się określić zbiorem, zwanym alfabetem, którego elementy nazywane są literami, dowolne ciągi liter słowami. KaŜdą literę moŜna utoŜsamiać ze słowem. Alfabet jest tak określony, Ŝe moŜna w nim wyróŜnić jedną literę oznaczaną symbolem Λ. Słowo zbudowane tylko z litery Λ nazywa się słowem pustym. Liczbę liter w słowie określa się jako liczbę liter l(x) w ciągu x, ale dla słowa pustego przyjmuje się: l(Λ)=0. Dalej, określa się relację dwuargumentową zwaną konkatenacją w taki sposób, Ŝe dla dwu dowolnych słów x, y konkatenacją jest słowo będące sklejeniem tych słów oznaczane xy lub x•y. Przyjmuje się dla dowolnego słowa x, Ŝe Λx = xΛ = x. Posługując się słowem pustym moŜna w sposób prosty zdefiniować zawieranie się słowa x w słowie y: x zawiera się w y wtedy i tylko wtedy, gdy istnieją takie słowa w1, w2, Ŝe y=w1xw2. Zbiór V* zwany zbiorem słów nad alfabetem V moŜemy określić takŜe rekurencyjnie: S1. Λ∈V*, S2. s∈V* ∧ x∈V ⇒ xs, S3. nic innego nie jest słowem. Podobnie, długość l(x) słowa x moŜna określić rekurencyjnie: L1. l(Λ) = 0, L2. x∈V ∧ s∈V* ⇒ l(xs) = 1+l(s). Dowolny podzbiór L zbioru słów V* nazywamy językiem abstrakcyjnym lub krótko językiem. Niech zbiór T⊆V jest zbiorem liter zwanych literami terminalnymi. Litery, które nie są terminalne będziemy nazywać nieterminalnymi. WyróŜnijmy jedno słowo nieterminalne S. Słowo to nazywamy wyjściowym. Określmy funkcję częściową π przyporządkowującą pewnym słowom pewne litery nieterminalne. Funkcję π nazywamy operacją przypisania słów literom nieterminalnym. Przypisanie słowa s literze nieterminalnej M, jako słowu, nazywamy regułą produkcji i oznaczamy: M::=s lub M→s. Wprowadzamy następującą operację wyprowadzalności: słowo s2 jest wyprowadzane ze słowa s1 wtedy i tylko wtedy, gdy dla pewnej reguły produkcji M::=s jeśli M jest literą naleŜąca do słowa s1 i zastąpimy ją w kaŜdym miejscu, gdzie występuje w słowie s1 przez słowo s, to w wyniku tego postawienia otrzymamy słowo s2. JeŜeli dla słowa s1Ms2 zastosujemy regułę M::=s, to otrzymamy słowo s1ss2. Układ G = <V, T, S, π> nazywamy gramatyką bezkontekstową. PoniewaŜ, dla operacji przypisania, kaŜdemu słowu naleŜącemu do dziedziny tej operacji, odpowiada litera nieterminalna, która moŜe teŜ być słowem naleŜącym do dziedziny operacji przypisania, więc moŜna iterować (wielokrotnie stosować) operację przypisania do danego słowa. Gdy po tych iteracjach operacji przypisania, dla danego słowa przypisanego słowu wyjściowemu S, moŜna przekształć to słowo w słowo będące konkatenacją tyko symboli terminalnych, to takie słowo nazywać będziemy akceptowalnym lub generowanym przez gramatykę G. Zbiór słów w tym sensie akceptowalnych określa język bezkontekstowy L(G). Przykład 1.1.6.1 Zbiór V = {Λ, S, A, B, 0, 1} , gdzie T = {0, 1} z regułami produkcji: S::= SAB, S::= Λ A::= 0, B::= 1 określa gramatykę bezkontekstową języka bezkontekstowego L⊆V*. PokaŜemy, Ŝe słowo 0101 jest generowane przez tę gramatykę (akceptowalne). 1. 2. S SAB słowo wyjściowe, Reg. S::= SAB, 3. 4. 5. 6. 7. 8. S0B S01 SAB01 S0B01 S0101 Λ0101 0101 Reg. A::= 0, Reg. B::= 0, Reg. S::= SAB, Reg. A::= 0, Reg. B::= 0, Reg. S::= Λ z Λ0101=0101 na podstawie własności konkatenacji. Przykład 1.1.6.2 Implementacja powyŜszego przykładu w języku Turbo Prolog PREDICATES /*deklaracje predykatów */ litera_alfabetu(string) /*predykat uznający litery w jednoelementowych łańcuchach za litery budowanego języka */ litera_terminalna(string) /*predykat ustalajacy, Ŝe litera w jednoelementowym łańcuchu jest literą terminalną */ słowo(string) /* predykat ustalający, Ŝe łańcuch liter jest słowem */ CLAUSES /*deklaracja formuł – klauzul – faktów i reguł */ /* deklaracja liter alfabetu */ litera_alfabetu(""). /* "" - słowo puste */ litera_alfabetu("S"). litera_alfabetu("A"). litera_alfabetu("B"). litera_alfabetu("0"). litera_alfabetu("1"). /* deklaracja liter terminalnych */ litera_terminalna("0"). litera_terminalna("1"). /* deklaracja słów */ słowo(X) :- litera_alfabetu(X). słowo(Z) :- słowo(X), słowo(Y), concat(X,Y,Z). /* concat(X,Y,Z) jest standardowym zapisem tworzącym dla łańcuchów słów X, Y ich konkatenację Z=XY lub dla X,Z znajdujący Y, lub dla Y,Z znajdujący X */ Przykład 1.1.6.3 Relacje i operacje na tekstach (łańcuchach znaków, słowach języka) PREDICATES zawieranie(string,string) /* zawieranie(T1,T2) – tekst T1 zawarty jest w tekście T2, np. tekst „bc” zawarty jest w tekście „aabcd” */ podstawienie(string,string,string,string) /* podstawienie(T1,T2,T3,T4) – tekst T4 jest wynikiem podstawienia tekstu T1 za tekst T2 w tekście T3 na pierwszym miejscu, na którym tekst T2 występuje w tekście T3. Np. tekst „aabbc” jest wynikiem podstawienie tekstu „a” za tekst „b” na pierwszym miejscu w tekście „abbbc” , gdzie tekst „b” występuje */ poczatek(string,string,string) /* poczatek(T1,T2,P) – tekst P jest częścią tekstu T2 poprzedzającą występowanie w nim tekstu T1 */ koniec(string,string,string) /* koniec(T1,T2,P) – tekst P jest częścią tekstu T2 następującą po występowaniu w nim tekstu T1 */ podstawienie_globalne(string,string,string,string) /* podstawienie_globalne(T1,T2,T3,T4) – tekst T4 jest wynikiem podstawienia tekstu T1 za tekst T2 w tekście T3 w kaŜdym miejscu, na którym tekst T2 występuje w tekście T3. Np. tekst „aaaac” jest wynikiem podstawienie tekstu „a” za tekst „b” w kaŜdym miejscu w tekście „abbbc” , gdzie tekst „b” występuje */ cyfra(string) /* predykat cyfra(T)rozpoznaje wśród łańcuchów znaków cyfry: „0”, „1”, ...”9” */ ciag_cyfr(string) /* predykat ciag_cyfr(T)rozpoznaje wśród łańcuchów znaków ciągi cyfr: np. „019” */ ciag_cyfr_w_tekscie(string,string,string) /* ciag_cyfr_w_tekscie(T,L,R) – L jest ciągiem cyfr na początku tekstu T, a R jest pozostałą częścią tekstu T */ napis_liczby(string) /* predykat napis_liczby(T) rozpoznaje wśród ciągów cyfr napisy liczb, tj. ciągi cyfr nie zaczynające się od cyfry „0” */ napis_liczby_w_tekscie(string,string,string) /* - predykat rozpoznaje na początku tekstu napis liczby oraz wyróŜnia pozostałą część takstu */ CLAUSES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ZAWIERANIE TEKSTÓW % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% zawieranie("",""). zawieranie(T1,T2):T2<>"",concat(T1,_,T2); T2<>"",frontStr(1,T2,_,N_T2), zawieranie(T1,N_T2). /* występowanie w argumencie formuły atomowej symbolu „_“ oznacza, Ŝe istnieje jakaś wartość tego argumentu przy której formuła ta zachodzi; wyraŜenie postaci frontStr(1,T2,_,N_T2)oznacza, Ŝe z tekstu T2 została pobrana pierwsza litera i reszta po pobraniu tej litery jest tekstem N_T2; zawieranie tekstów zostało określone rekurencyjnie: 1) tekst pusty zawiera się w tekście pustym, 2) zawieranie tekstu T1 w tekście T2 zachodzi, gdy istnieje jakiś tekst taki, Ŝe konkatenacja T1 z tym tekstem daje tekst T2, jeśli tak nie jest, to sprawdzamy ten warunek po popraniu a tekstu T2 pierwszej litery, a pobieranie liter powtarzamy do momentu uzyskania zawierania, lub do momentu otrzymania tekstu pustego, a wtedy zawieranie nie zachodzi */ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% koniec(T1,T2,K):T2<>"",concat(T1,K,T2),!; T2<>"",frontStr(1,T2,_,N_T2), koniec(T1,N_T2,K). /* prosimy o wyjaśnienie powyŜszej reguły: określenie tekstu K, który przy zawieraniu tekstu T1 w tekście T2 jest pozostałą częścią tekstu T2 występującą po pierwszym zakończeniu tekstu T1 (tekst T1 moŜe wystąpić w róŜnych miejscach tekstu T2) */ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% poczatek(T1,T2,P):koniec(T1,T2,K),concat(T,K,T2),concat(P,T1,T). /* poczatek(T1,T2,P)- zachodzi przy zawieraniu tekstu T1 w tekście T2; jeśli za pomocą predykatu konkatenacji i predykatu koniec pomniejszymy T2 o koniec K, a tekst który pozostanie pomniejszymy o tekst T1, to otrzymamy szukany początek P występujący w tekście T2 przed tekstem T1; P moŜe być tekstem pustym */ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % PODSTAWIANIE TEKSTU ZA TEKST W TEKŚCIE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% podstawienie(T1,T2,T3,T4):T1<>T2, T3<>"", poczatek(T2,T3,P),koniec(T2,T3,K),!, concat(P,T1,T),concat(T,K,T4). /* podstawienie(T1,T2,T3,T4) – pierwsze, jednokrotne, podstawienie tekstu T1 za tekst T2 w tekście T3, w wyniku czego otrzymujemy tekst T4; prosimy o wyjaśnienie podanej reguły */ podstawienie_globalne(T1,T2,T3,T4):podstawienie(T1,T2,T3,N_T3),!, podstawienie_globalne(T1,T2,N_T3,T4); T4=T3,!. /* podstawienie_globalne(T1,T2,T3,T4) – kolejne podstawienia tekstu T1 za tekst T2 w tekście T3 wszędzie tam gdzie tekst T2 występuje przy pierwszym i po następnych podstawieniach, w wyniku czego otrzymujemy tekst T4; prosimy o wyjaśnienie podanej reguły */ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % NAPIS LICZBY % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% cyfra("0"). cyfra("1"). cyfra("2"). cyfra("3"). cyfra("4"). cyfra("5"). cyfra("6"). cyfra("7"). cyfra("8"). cyfra("9"). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Rozpoznawanie napisu jako ciągu cyfr %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ciag_cyfr(X):X<>"", cyfra(X),!; X<>"", cyfra(C), concat(C,N_X,X),cyfra(N_X),!; X<>"", cyfra(C), concat(C,N_X,X),!, ciag_cyfr(N_X). napis_liczby(X):X=”0”,!; ciag_cyfr(X),frontStr(1,X,C,_),C<>"0",!. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Rozpoznawanie ciągu cyfr na początku napisu %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ciag_cyfr_w_tekscie("","",""). ciag_cyfr_w_tekscie(T,L,R):T<>"",ciag_cyfr(T),L=T,R="",!; T<>"", frontStr(1,T,L,R),cyfra(L), frontStr(2,T,L1,_),not(ciag_cyfr(L1)); T<>"", frontStr(1,T,C,N_T), cyfra(C), ciag_cyfr_w_tekscie(N_T,N_L,R), concat(C,N_L,L). napis_liczby_w_tekscie(T,L,R):ciag_cyfr_w_tekscie(T,L,R), frontStr(1,L,C,_),C<>"0",!. Problem 1.1.7.1 Wykorzystując podane implementacje dokonać implementacji definicji języka niekontekstowego w języku Turbo Prolog. 1.1.7 Notacja Backusa-Naura (BNF) KaŜdy język programowania trzeba poprawnie zdefiniować i opisać reguły produkcji (tworzenia) napisów poprawnych i dopuszczalnych w tym języku. Trzeba to uczynić nie tylko dla uczących się tego języka programistów, lecz takŜe na uŜytek translatorów (kompilatorów), których przecieŜ podstawowym zadaniem jest rozstrzyganie, czy dany ciąg symboli źródłowych jest programem. Aby opis języka programowania był formalny, trzeba do tego celu uŜywać pewnego „nadjęzyka”, czyli metajęzyka. Takim metajęzykiem jest właśnie notacja zaproponowana pierwszy raz przez Backusa, a zastosowana na szeroką skalę przez duńskiego informatyka Naura. Wprowadzona notacja jest wynikiem prowadzenia specyficznej metody budowy języków bezkontekstowych, w których symbole nieterminalne są pisanymi w nawiasach <,> symbolami reprezentującymi nazwy składników metajęzyka słuŜącego do opisu budowy języka formalnego, w tym najczęściej języka programowania. Do opisu ciągu reguł produkcji słów uznanych za poprawnie zbudowane, ciągu postaci: N→x1, N→x2, N→x3, N→x4,…, N→xk, stosuje się bardzo uŜyteczną umowę notacyjną, ciąg tych reguł zapisuje się w postaci: N::= x1| x2| x3| x4| ... | xk . W notacji Backusa-Naura występują zmienne metajęzykowe (reprezentujące nazwy składników języka formalnego) oznaczone przy pomocy dowolnych napisów ujętych w nawiasy kątowe <, >, symbol ::= oraz kreska pionowa | (rozumiana jako „albo”). Symbol ::= ma znaczenie „z definicji równa się”. Przykładowo podamy określenie cyfry, litery i identyfikatora w języku Pascal: <cyfra> ::= 0|1|2|3|4|5|6|7|8|9, co czytamy – cyfrą w Pascalu z definicji jest 0 albo 1, albo 2, itd. <litera> ::= a|b|c|...|x|y|z|A|B|C|...|X|Y|Z, <identyfikator> ::= <litera>|<identyfikator><litera>|<identyfikator><cyfra>. Tę ostatnią definicję czytamy – identyfikator jest literą albo ciągiem identyfikatora i litery (ich konkatenacją, np. Aa), albo ciągiem identyfikatora i cyfry (ich konkatenacją, np. A1). Przykład 1.1.7.1 Rozpatrzmy język wyraŜeń algebraicznych. Symbolami nieterminalnymi są: <zmienna>, <operacja>, <wyraŜenie>, zaś terminalnymi symbole liter: A, B, …, Z, i symbole działań: +, -, ×, /, a ponadto symbole nawiasów: (,) oraz symolbol równości: =. Symbolem wyjściowym (początkowym) jest <wyraŜenie>. Określmy reguły produkcji języka wyraŜeń algebraicznych następująco: <zmienna>::= A| B| … | Z <operacja>::= +| -| ×| /| ^| √ <relacja>::= <| ≤| =| ≠| ≥| > <nawiasy>::= <nawias lewy>| <nawias prawy> <nawias lewy>::= ( <nawias prawy>::= ) <wyraŜenie>::=<zmienna> |<nawias lewy><wyraŜenie><operacja><wyraŜenie><nawias prawy> | <nawias lewy>-<wyraŜenie><nawias prawy>| <nawias lewy> +<wyraŜenie><nawias prawy>| √<wyraŜenie>| <wyraŜenie><relacja><wyraŜenie> . Stosując zapis strzałkowy dla reguł produkcji moŜemy wywód wyraŜenia „(A(B×((A+C))/D))” napisać w postaci: <wyraŜenie>→ <nawias lewy><wyraŜenie><operacja><wyraŜenie><nawias prawy>→ (A-<nawias lewy><wyraŜenie><operacja><wyraŜenie><nawias prawy>)→ (A-(B×<nawias lewy><wyraŜenie><operacja><wyraŜenie><nawias prawy>))→ (A-(B×(<wyraŜenie>/D)))→ (A-(B×(<nawias lewy><wyraŜenie><operacja><wyraŜenie> <nawias prawy>/D)))→ (A-(B×((A+C)/D))) JeŜeli zbiór reguł produkcji tekstu rozszerzymy o operacje pozwalające podstawiać za dowolnie wybrane zmienne <wyraŜenie>, co np. dla zmiennej A zapisujemy w skrócie A := <wyraŜenie>, zamiast zapisu reguły produkcji <wyraŜenie>::= A:= <wyraŜenie>, to tak określoną regułę produkcji będziemy nazywać regułą przypisania. Reguła przypisania najczęściej jest uŜywana w językach programowania do implementacji obliczeń liczbowych lub przetwarzania tekstów. Przykład 1.1.7.2 Operacja przypisania dla wyraŜeń algebraicznych. Niech w zaproponowanym języku wyraŜeń algebraicznych określone jest takŜe tworzenie napisów liczbowych w notacji dziesiętnej dla symbolu nieterminalnego <napis liczby>. Wykorzystując zaproponowaną notację reguły przypisania zapisać tekst obliczenia wyraŜenia: 2 − 3,145 , wykorzystując w zapisie wyniku kaŜdej operacji tylko jedną zmienną X (tak wykorzystywane zmienne reprezentują rejestry pamięci komputera; minimalna ilość wykorzystanych zmiennych oznacza wykorzystanie minimalnego obszaru pamięci komputera). Obliczenie: 1. X:=2 2. X:=√X 3. X:=(X – 3,415) 4. X:=√X