Emlékszünk, volt a Chomsky-normálforma, amiről már ranteltem egyet, hogy hogy kéne csinálni rendesen. Csak azt nem meséltem el, hogy mire jó, vagy miért.
A felállás most az, hogy szeretnénk CF nyelvet parsolni, vagyis ha van egy CF nyelvtanunk, és egy input stringünk, akkor egy derivációs fát akarunk építeni, aminek a határa épp ez az input string. Ezt pl. ha a nyelvtan Chomsky-normálformában van, akkor a Cocke-Younger-Kasami algoritmussal, avagy CYK, meg lehet tenni. Ha a nyelvtanunkban R a szabályok halmaza és n hosszú az input string, mondjuk w=a1a2…an, akkor mindezt O(|R|n3) időben elvégzi, mégpedig dinamikus programozással:
- kitölt egy T[i][j] táblázatot, ahol 1≤i≤j≤n;
- a táblázat egy cellába a nemterminálisok V halmazának részhalmazai kerülnek;
- az A nemterminális pontosan akkor kerül T[i][j]-be, ha A⇒∗aiai+1…aj.
- alapeset: T[i][i]={A∈V: A→ai∈R}, tehát ha az i. betű a, akkor minden A→a szabály bal oldalát felvesszük.
- indukció: T[i][j]-be akkor kerül be A, ha i<j, ha van olyan i≤k≤j index és A→BC szabály, melyre B∈T[i][k] és C∈T[k+1][j]. Ehhez végig kell pörgetni a lehetséges k-kat és R-eket, tehát egy cella kitöltése (j−i)|R|, ezt szummázva az összes cellára kapunk egy O(|R|n3) időigényt.
Remek, mondhatnánk, van egy elemző algoritmusunk, polinomidejű, mi kell még
hát például használható időigény
mert a köbös az nem az, bárki bármit mond.
Miről van szó, mikor akarunk elemezni? Mondjuk ha van egy fordítóprogramunk, akkor az benyeli a forráskódot tartalmazó file-t mint egy stringet és izzításképp felépíti belőle a kódhoz tartozó AST-t. De azért gondoljuk már végig, hogy ha pl a gcc köbös időben menne, egy ~10kbyte-os forrásfile-nál is cca 1012 ideig kéne várnunk, mire végez? Ez testvérek közt (egy ciklusban egy lépés, pár gigahertzes gépen) félóra minimum. File-onként. Indítasz egy buildet, másnapig be se jössz, vagy hogy? :D
Szóval, hatékonyabb elemzési módszer kell.
Ha visszagondolunk a rantemre a Chomsky normálformáról, akkor ott láttuk, hogy a balettlépések közül a darabolás és az ezUTÁN elvégzett ε-mentesítés lineáris időben, konstansszor nagyobb nyelvtant ad vissza, a szűk keresztmetszet a láncszabály-mentesítés volt, ami négyzetes.
öm...
de mégis kit zavarnak a láncszabályok?
csak jól kéne velük bánni.
Nézzünk már magunkba, ezzel a láncszabály-mentesítéssel csinálunk egy tök redundáns nagy nyelvtant. Kb annyi értelme, mint NFA-t ε-mentesíteni. Ott is csak az ε-lezárton kéne operálni on-the-fly, legalábbis az esetek túlnyomó részében, cachelve az elérhetőséget, még úgy is kevesebb tárat eszünk, mintha végrehajtanánk az ε-mentesítő algoritmust..
Tehát ha a nyelvtanunkban csak a hosszú jobboldalakat tördeljük, majd ε-mentesítünk, de a láncszabályokat békén hagyjuk (ha vannak esetleg nem használható nemterminálisok, azokat persze még az elején eldobjuk, amiből meg csak ε vezethető le, azokat töröljük a jobb oldalakról), akkor kapunk egy ekvivalens nyelvtant, amiben lesznek A→BC, A→B és A→a alakú szabályok. Erre az értelemszerűen módosított CYK:
- T[i][i]-hez: ciklusban menjünk végig a nemterminálisokon. Ha A→ai∈R, akkor vegyük be A-t T[i][i]-be és az összes olyan B-t is, melyre B-ből A levezethető láncszabályokkal;
- T[i][j], i<j meghatározásához ciklusban menjünk végig a nemterminálisokon. Ha A még nem került bele T[i][j]-be, keressünk egy A→BC szabályt és i≤k≤j indexet, amire B∈T[i][k] és C∈T[k+1][j]. Ha ilyen van, akkor tegyük bele A-t T[i][j]-be, és az összes olyan B-t is, melyre B-ből A levezethető láncszabályokkal.
és akkor jó ez a módosított CYK, ami láncszabályt is támogat, csók a családnak.
Miután ezt így kigondoltam, persze találtam egy 2009-es papírt, megjelent az Informatica Didactica c lapban (jé, van ilyen is), akik szintén. Ők ezt 2NF-nek hívják. ez egy ilyen szakma, az ember gondolkodik, aztán ha rájön bármire, rákeres és nahát, mások már megcsinálták :P Aztán rákerestem megint és más is implementálta ezt 2004-ben. Bizonyos dolgokat többször is elfogadnak tudományos helyeken. Nem kéne. Na mindegy..
örülünk, Vincent?
dehogy
hát ez ettől még köbös.
Legközelebb shift-reduce parserekről írok. Azok lineárisak, tehát gyorsak, de "persze" nem minden nyelvtanhoz van ilyen.
No comments:
Post a Comment