• Nem Talált Eredményt

Nyelvtanok átalakítása

In document Formális nyelvek (Pldal 86-95)

3. Környezetfüggetlen nyelvek

3.2. Nyelvtanok átalakítása

Jelölje B az ily módon kapott legnagyobb számosságú halmazt.

Amennyiben kiindulásul a terminális szimbólumok halmazát választjuk, B0 = Σ

akkor a B halmaz a terminális szimbólumokon kívül azokat és csakis azokat a nemterminális szimbólumokat fogja tartalmazni, amelyekből kiindulva a helyettesítési szabályok alkalmazásával egy pusztán terminális szimbólumokból álló jelsorozat állítható elő.

Ezzel mintegy alulról felfelé bottom-up – innen adódik a B jelölés – fésüljük végig a grammatika szabályait, és csakis azokat a szimbólumokat vesszük be a halmazunkba, amelyekre nézve van remény, hogy nem feleslegesek.

Vegyünk ismét egy halmazsorozatot, de válasszunk most más képzési szabályt.

Ti+1 = Ti ∪ { X  A → αXβ, A ∈ Ti } (3.7.) Új halmaz képzésekor tehát az eredeti halmazhoz hozzá kell venni azon helyettesítési szabályok jobboldalán található terminális és nemterminális szimbólumokat, amely szabályok baloldala az eredeti halmazhoz tartozó nemterminális szimbólum.

A halmazsorozat számossága itt is monotonon növekszik, és itt is akkor áll meg a növekedés, ha egy lépésben nem tudunk az eredeti halmazhoz egy szimbólumot sem hozzáfűzni.

Jelölje itt a legnagyobb elemszámú halmazt T. Legyen a kiindulásként választott halmaz egyedül a mondatszimbólumot tartalmazó halmaz:

T0 = { S }

akkor a T halmaz azokat és csakis azokat a terminális és nemterminális szimbólumokat tartalmazza majd, amelyek egy, a mondatszimbólumból kiinduló levezetés mondatszerű formáiban szerepelhetnek.

Ezzel az algoritmussal felülről lefelé top down – innen a T jelölés – fésüljük meg a grammatika szabályait.

Lássunk egy példát. Legyen a grammatika:

S → a S → B B → BC C → b

A nyelvtant alulról felfelé megfésülve a következő halmazsorozatot kapjuk:

B0 = { a,b } B1 = B = { a,b,S,C }

A halmaz számossága tovább nem növelhető. Mint látható a B nemtermi-nális szimbólum nem került bele a halmazba, így feleslegesnek bizonyult. Ezt a szimbólumot tehát, és minden olyan helyettesítési szabályt, amelyben ez a szim-bólum szerepel, kihagyhatunk a nyelvtanból. Ez most így megkurtítva mindössze egy tartalmaz:

S → a C → b

Ezt a nyelvtant felülről lefelé fésülve a következő halmazsorozatot kapjuk:

T0 = { S } T1 = T = { S,a }

Végeredményben tehát a nyelvtan egyetlen helyettesítési szabályt tartal-maz, S → a és egyetlen mondatot generál.

Amennyiben a fésülést fordított sorrendben végeztük volna el, vagyis először alkalmaztuk volna a top down és utána a bottom-up vizsgálatot, akkor az előbbitől eltérő eredményt kaptunk volna. A nyelvtannak helytelenül két szabálya, nevezetesen S → a és C → b is megmaradt volna. Így tehát a kígyó a fejétől a farkáig nem ugyanolyan hosszú, mint a farkától a fejéig.

Ennek a látszólagos ellentmondásnak a forrását azok a nemterminális szimbólumok képezik, amelyekből nem vezethető le terminális jelsorozat. Ilyen példánkban a B nemterminális. Ha egyszer ilyen nemterminálisok bekerülnek egy mondatszerű formába, akkor azokat onnan hosszabb távon sem lehet kiebrudalni, az ilyen nemterminálisokat nem lehet agyonütni.

Az ilyen agyonüthetetlen nemterminálisok természetesen felesleges szimbólumok, hiszen belőlük nem vezethető le csupa terminálisból álló jelsoro-zat. Ezeket a szimbólumokat az alulról felfelé történő fésüléskor felismerjük, de nem detektáljuk felesleges voltukat, ha lefelé fésülünk.

Vizsgáljuk meg, miért nem lehet ezeket a nemterminálisokat, ha egyszer belekerültek a mondatszerű formába, onnan kiirtani.

Ha valamely szimbólumhoz nem tartozik olyan levezetési szabály, amelynek éppen a szimbólum lenne a baloldala, akkor triviális, hogy ez a szim-bólum onnan el nem távolítható, örökre benne marad a mondatszerű formában.

A B szimbólum esetében nem ez a helyzet, mégsem tudunk megszaba-dulni tőle, nem kaphatunk belőle terminális jelsorozatot. Ennek jobb megértésére célszerű megismerkednünk a rekurzivitás fogalmával.

Egy nemterminális szimbólumot rekurzívnak mondunk, ha származtat-ható belőle olyan jelsorozat, amely az eredeti szimbólumot tartalmazza.

*

A ⇒ αAβ (3.8.)

Egy nyelvtan akkor rekurzív, ha tartalmaz rekurzív nemterminálist.

Nem rekurzív nyelvtanok csak véges mondatot generálnak. Minden véges nyelv reguláris nyelvtannal generálható. Ezek igazolását az olvasóra bízom.

A fentiekből következik, hogy minden végtelen sok mondatot generáló nyelvtan rekurzív.

Természetesen a rekurzív nyelvtanoknál mindig kell találnunk egy egérutat, egy olyan levezetési lehetőséget, amikor a rekurzivitást előidéző nemterminális szimbólum többet nem fordul elő. Pontosan ugyanúgy, ahogy egy rekurzív eljáráshívást alkalmazó program esetében, itt is kötelező egy olyan alternatíva, amikor az eljárást nem hívjuk meg rekurzív módon.

Így például az alábbi formálisan helyes, a szintakszis szabályait kielégítő ALGOL 60 nyelven írt programfragmens nem rekurzív eljárást tartalmaz, hanem egyszerűen badarság.

integer procedure FACT (N);

value N, integer N;

FACT := N * FACT(N-1);

Nyilvánvaló, ha egyszer meghívtuk ezt az eljárást, akkor az – elvben – soha az életben nem hagyja abba a számolást.

Nevezzük ezt az ostobaságot álrekurzivitásnak.

Mielőtt továbbmennénk, mutassuk meg az előbbi, a faktoriális kiszámítá-sára hivatott program helyes változatát:

integer procedure FACT (N);

value N, integer N;

FACT := if N=0 then 1 else N * FACT(N-1);

Mint látható az N=0 esetre van egérutunk.

Itt persze feltételeztük, hogy az eljárást csak nem negatív számokkal mint aktuális paraméterekkel hívjuk meg. Ha ez a feltétel nem biztosítható, akkor valamilyen ellenőrzést, védelmet kell a programba beépítenünk.

Az álrekurzió ugyanúgy fenyeget minket nyelvtanok esetében. Itt is előfordulhat, hogy egy alkalmas nemterminális szimbólum, ha egyszer bekerült a mondatszerű formába, ott is ragad, nem tudunk tőle szabadulni. Pontosan ez a helyzet a B szimbólummal. Minthogy ez álrekurziót okoz nincsen olyan mondat, amelynek levezetésében a B szerepelhetne, így természetesen felesleges szimbólum.

Példánkban a rekurzivitás közvetlen volt, a levezetési szabály baloldalán található szimbólum szerepelt ugyanazon szabály jobboldalán is. Ez persze nem szükségszerű. Lehetséges, hogy a szimbólum csak több levezetési lépés után tér vissza. Ebben az esetben álrekurzióról akkor beszélünk, ha ebből az ördögi körből nem tudunk kilépni, az egyszer már előfordult nemterminális újabb felbukkanása elkerülhetetlen.

Vegyük észre, hogy az álrekurzióval szemben a két fésülés, a felülről lefelé és az alulról felfelé történő, másképpen viselkedik. Alulról fésülve az ilyen szimbólumok átcsúsznak a fésű fogain, és feleslegesnek minősülnek. Felülről lefelé azonban az álrekurzió ténye nem detektálható, az ilyen szimbólumok benne maradnak a nyelvtanban.

Amennyiben a fésülést az álrekurziót kiszűrő módon alulról kezdjük, akkor két fésüléssel valóban minden felesleges szimbólumtól megszabadulunk.

Ezt beláthatjuk, ha meggondoljuk, hogy a bottom-up fésülés eltünteti mindazokat a nemterminálisokat, amelyekből nem vezethető le terminális jelsorozat. Így a (3.5.) összefüggésben az A nemterminális nyilván nem ilyen szimbólum, ha egyszer fennakadt a fésűn.

A második top down fésülésnél viszont csak azok a szimbólumok marad-nak meg, amelyek elérhetőek az S mondatszimbólumból. Amennyiben az A nem-terminális túlélte mindkét fésülést, akkor az

* *

S ⇒ α A β ⇒ w *

alakú (3.5.) összefüggésben mind az első, mind a második ⇒operátorral jelzett levezetése helytálló, ugyanis a fenti gondolatmenet nem csak az A nemtermi-nálisra, hanem az α és β jelsorozatokban esetleg található nemterminálisokra is alkalmazható.

A következőkben az A → ε alakú úgynevezett ε-szabályok kiküszöbölé-séről szólunk.

Már említettük, hogy a környezetfüggő, vagyis 1-es osztályú nyelveket nem csökkentő nyelvtanok generálják. Az ε-szabályok, ahol a baloldal hossza 1, a jobboldalé viszont 0 természetesen csökkentő szabályok. Minthogy a reguláris és környezetfüggetlen nyelvek a környezetfüggő nyelvek részhalmazai, hogyan engedhető meg ε-szabályok alkalmazása ezekben a nyelvosztályokban?

Az a helyzet, hogy majd finomítanunk kell a nyelvosztályok definícióján, de előbb vizsgáljuk meg az ε-szabályok kiküszöbölési lehetőségeit.

Fésüljük most meg ismét alulról az eredeti nyelvtant, válasszuk azonban most induló halmaznak az üres jelsorozatot!

B0 = { ε }

Nyilvánvaló, hogy most a záróhalmazban azok a nemterminális szimbólu-mok találhatóak, amelyek elenyészhetnek, vagyis amelyek az ε-szabályok alkalmazása révén közvetlenül vagy közvetve utód és nyom nélkül eltűnhetnek a mondatszerű formából.

Itt különbséget kell tennünk két eset között, eleme-e ennek a halmaznak a mondatszimbólum vagy sem? Amennyiben a mondatszimbólum benne van ebben a halmazban, akkor a mondatszimbólum is elenyészhet, belőle kiindulva le tudjuk vezetni az üres jelsorozatot, az ε eleme a nyelvnek.

Ellenkező esetben, tehát amikor a mondatszimbólum nem eleme a halmaznak, a mondatszimbólum nem enyészhet el, az üres jelsorozat nem eleme a nyelvnek.

Az első esetben, amikor a nyelv tartalmazza az üres jelsorozatot, állítsuk elő a nyelvet két nyelv uniójaként. Az első komponensnek egyetlen eleme lesz, az üres jelsorozat, míg a másodiknak mondatai az üres jelsorozat kivételével megegyeznek az eredeti nyelv mondataival.

Jelölje, mint eddig, Le azt a nyelvet, amelynek egyetlen mondata az üres jelsorozat. Az L nyelvet tehát, amely feltételezésünk szerint tartalmazza az üres jelsorozatot, a következőképpen állítjuk elő

L = (L – Le) ∪ Le (3.9.) Az L Le formalizmus az üres jelsorozattól megfosztott eredeti nyelvet jelenti. Az Le nyelvtana csak egyetlen szabályt tartalmaz:

Q → ε

ahol itt azért jelöltük a mondatszimbólumot Q betűvel, mert feltételezésünk szerint S már le van foglalva az eredeti nyelv mondatszimbólumának. A (3.9.) nyelv mondatszimbólumát jelöljük P betűvel, akkor az eredeti nyelv szabályait a következő szabályokkal kell kiegészítenünk:

P → Q Q → ε P → S

Ha most újra elvégezzük az eredeti nyelvtan vizsgálatát, akkor ugyanazt az eredményt másképpen kell interpretálnunk. A régi mondatszimbólum, amely beke-rült az elenyésző nemterminálisok közé, mondatszimbólum rangját elvesztette, így ennek az új nyelvnek nem eleme az üres jelsorozat, ugyanakkor valamennyi ettől eltérő mondat legenerálható. Ez megfelel a fentebb vázolt koncepciónknak.

Hogyan lehet egy nyelvtanból, amely nem generálja az üres jelsorozatot, az ε-szabályokat eltávolítani?

Hagyjuk el az összes ε-szabályt, de ugyanakkor az olyan levezetési szabályoknál, ahol a jobboldalon szerepelnek elenyésző nemterminálisok, az összes lehetséges konfigurációban hagyjuk el ezeket a nemterminálisokat. Az elhagyottakról feltételezzük, hogy elenyésznek, a megmaradt többiről éppen ellenkezőleg azt tesszük fel, hogy belőlük nem üres jelsorozatok származnak.

Azzal modellezzük tehát az ε-szabályokat, hogy amennyiben feltételezésünk szerint egy nemterminális elenyészik, akkor azt be sem írjuk a levezetési szabályba.

Persze ez nagyon megnövelheti a nyelvtant, így ha egy levezetési szabály jobboldalán k elenyésző szimbólum van, akkor ebből az egyetlen helyettesítési szabályból 2k új szabály származhat.

Visszatérve a nem csökkentő nyelvtanok problémájára definiáljuk újra az első nyelvosztály nyelveit. Minden olyan nyelvet 1-es osztálybelinek tekintünk, amely, ha nem tartalmazza az üres jelsorozatot, akkor előállítható nem csökkentő nyelvtan segítségével, ha tartalmazza, akkor viszont előállítható két nyelv uniója-ként, ahol az első nyelvnek egyetlen mondata van, az üres jelsorozat, a második pedig az eredeti nyelv valamennyi az üres jelsorozattól eltérő mondatát tartamaz-za, és nem csökkentő nyelvtannal generálható.

Ez az új felfogás feloldja az ortodox értelmezés miatt jelentkező ellent-mondásokat.

Ezek szerint, ha van egy olyan környezetfüggetlen nyelvtanunk, amelyben vannak ε-szabályok, akkor a fentiek szellemében át kell a nyelvtant alakítanunk, hogy a nyelv a környezetfüggő, tehát nem csökkentő nyelvek részhalmazába tartozzék? Szó sincs róla. Az osztályba sorolás nyelveket és nem nyelvtanokat

említ. Ha meggyőződtünk róla, hogy a nyelvnek van a csökkentés tekintetében enyhített kritériumokat kielégítő nyelvtana, akkor ebben megnyugodhatunk, és rajtunk áll, hogy eltávolítjuk-e az ε-szabályokat vagy sem.

Lássunk egy példát az ε-szabályok kiküszöbölésére. Legyen a nyelvtan:

S → SaSb ε

A nyelvtan, mint arról könnyen meggyőződhetünk, olyan azonos számú a és b karakterekből álló jelsorozatokat generál, ahol a mondatok bármely prefixu-mában legalább annyi a karakter van, mint b karakter. Elemezzük ezt a nyelvtant.

A fésülés során keletkezett halmazsorozat:

B0 = { ε } B1 = B = { ε, S }

A mondatszimbólum benne van a záróhalmazban, minthogy a nyelvnek ε eleme. Az ismertetett módon új mondatszimbólumot, legyen ez Ŝ, és új levezetési szabályokat kell bevezetnünk

Ŝ → ε Ŝ → S

Az eredeti nyelvtanból az ε-szabályt elhagyva mindössze egy szabályunk marad. Ennek jobboldala viszont két elenyésző szimbólumot tartalmaz. Így helyette 22 = 4 új szabályt kell bevezetnünk:

S → SaSb S → aSb S → Sab S → ab A teljes nyelvtan:

Ŝ → ε Ŝ → S S → SaSb S → aSb S → Sab S → ab Minthogy az eredeti nyelv tartalmazta az üres jelsorozatot, az átalakítás eredményeképpen két nyelv unióját kaptuk. Az első nyelvnek csak egyetlen eleme van, az üres jelsorozat, a másik nyelv nyelvtana nem tartalmaz ε-szabályt, és generálja az eredeti nyelv minden mondatát az ε kivételével.

Míg az eredeti nyelvtan alapján nem túl nagy fáradtsággal a nyelv felismerhető volt, a módosított nyelvtanról már ez kevésbé állítható. Ezzel az átalakítással az áttekinthetőséget feláldoztuk az ortodoxia oltárán.

Általában gyakori, hogy egy nyelvtan világosabb és áttekinthetőbb, mint ε-szabályokat nem tartalmazó egyenértékese. Ez is egyik oka annak, hogy az irodalom meglehetősen nagyvonalú ezen a területen. Meghagyja a régi nyelvtant és megelégszik azzal a megnyugtató tudattal, hogy ki lehetne küszöbölni az ε-szabályokat.

A nyelvtanok csinosságának növelésére szolgáló következő lépés az úgynevezett egyszeres szabályok kiküszöbölése lesz.

Mint már említettük egyszereseknek nevezzük az

A → B (3.10.)

alakú szabályokat. Rögtön felmerül a kérdés, miért nem szeretjük ezeket a szabá-lyokat, miért zavarnak minket?

Valójában az egyszeres szabályok léte csak akkor zavaró, ha ciklicitás van bennük, mint például az

A → B B → C C → A szabályok esetében.

Általában egy mondat levezetésére korlátos számú véges lépés szükséges. Amennyiben azonban ciklicitás van az egyszeres szabályok között, akkor levezetési lépésekkel vissza tudunk térni ugyanahhoz a mondatszerű formához, más szóval lesznek olyan mondatok, amelyeket nem korlátos számú lépésben is le lehet vezetni. Ez valóban nem szimpatikus jelenség.

Persze egyszeres szabályok jelenléte még nem jelent szükségszerűen ciklicitást, ennek veszélyét viszont legegyszerűbben és legdrasztikusabban az egyszeres szabályok kiirtása útján lehet elhárítani. Ha nincs egyszeres szabály, akkor bizonyosan nincs ciklicitás.

Kiküszöbölésük algoritmusa a következő lehet.

Emeljük ki a nyelvtanból az egyszeres szabályokat, és a továbbiakban azt a nyelvtant vizsgáljuk, amely csak ezekből az egyszeres szabályokból áll.

Megnézzük, hogy ebben a nyelvtanban, tehát az egyszeres szabályokban hány nemterminális szimbólum van. Ez után alkalmazzuk a felülről lefelé való fésülést olymódon, hogy kiinduló halmazként rendre egy-egy ilyen nemterminá-list választunk.

Az egyes fésülések eredményként kapott záróhalmaz nyilván azokat a nemterminálisokat tartalmazza, amelyek a kiindulásul választott nemterminális szimbólumból az egyszeres szabályok útján elérhetőek.

Az egyszeres szabályok elhagyásakor ennek megfelelően a nyelvtant új szabályokkal kell kiegészíteni. Ezen szabályok baloldala a kiindulásul választott nemterminális szimbólum lesz, jobboldala pedig megegyezik azon szabályok jobboldalával, amelyeknek baloldala a záróhalmazban található valamelyik nemter-minális. Így állíthatjuk elő egyetlen lépésben azt a mondatszerű formát, amelyet az egyszeres szabályok esetleges alkalmazásának befejezése után kapunk.

Állításaink nyilvánvalóak, így további magyarázatra nincsen szükség.

Lássunk erre is egy példát. Legyen a nyelvtan a jól ismert aritmetikai kifejezéseket generáló nyelvtan:

E → E+T E → T T → T∗F T → F F → (E) F → a

Az egyszeres szabályok létét kiemelendő itt most nem éltünk az azonos baloldalak nyújtotta egyszerűsítő jelöléssel.

Nyelvtanunk két egyszeres szabályt tartalmaz:

E → T T → F

Az egyszeres szabályok három nemterminális szimbólumot tartal-maznak. Ennek megfelelően a felülről való fésülést három ízben, az E, T és F szimbólumokból kiindulva kell elvégezni. Megállapodás szerint minden szimbó-lumból saját maga mindig elérhető, ha másképp nem, az egyszeres szabályok nullaszor való alkalmazásával.

A három vizsgálat záróhalmazait úgy különböztetjük meg, hogy indexként a kiinduló nemterminálisokat használjuk.

TE = { E, T, F } TT = { T, F } TF ={ F }

Ennek megfelelően az egyszeres szabályok elhagyásával egyidejűen a következő új szabályokat kell bevezetni:

E → T∗F E → (E) E → a T → (E) T → a Így az új, egyszeres szabályokat most már nem tartalmazó nyelvtan:

E → E+T  T∗F  (E)  a T → T+F  (E)  a F → (E)  a

Ezzel megkaptuk az ismert nyelvtanunkkal egyenértékű, de egyszeres szabályt nem tartalmazó nyelvtant. Őszintén szólva, az egyszeres szabályok kiirtása nem emelte az áttekinthetőséget. Ráadásul ez a nyelvtan „ártatlan” volt, amennyiben itt az egyszeres szabályokban nem volt ciklicitás. Éppen ezért nem kell feltétlenül ragaszkodnunk az egyszeres szabályok eltávolításához.

Az angol irodalom az olyan nyelvtant, amely mentes a felesleges szimbólumoktól, nem, vagy csak az ismert korlátozással tartalmaz ε-szabályt, végül nincsen benne egyszeres szabály, proper grammar névvel illeti.

Ennek a szóhasználatnak a magyar nyelven nincsen pontos egyen-értékese, talán igazándi vagy tisztességes nyelvtan elnevezés volna megfelelő. Engedtessék meg, hogy javaslatot tegyek a jólfésült nyelvtan megnevezés bevezetésére.

Az eddigiekből következik, hogy minden környezetfüggetlen nyelvtan-nak, bármilyen összegubancolódott legyen is, mindig van jólfésült egyenértékese.

In document Formális nyelvek (Pldal 86-95)