3.3 KILIOPPIN JÄSNNYSONGLMA Rtkistv tehtävä: Annettu yhteydetön kielioppi G j merkkijono x. Onko x L(G)? Rtkisumenetelmä = jäsennyslgoritmi. Useit vihtoehtoisi menetelmiä, erityisesti kun G on jotin rjoitettu (käytännössä esiintyvää) muoto. Johdot j jäsennyspuut Olkoon γ V kieliopin G = (V, Σ, P, S) lusejohdos. Lähtösymbolist S merkkijonoon γ johtv suorien johtojen jono S = γ 0 γ 1 γ n = γ snotn γ:n johdoksi G:ssä. Johdon pituus on siihen kuuluvien suorien johtojen määrä (edellä n). simerkki: luseen johtoj kieliopiss G expr : (i) T T T F T T F (ii) T F T F F F F (iii) T F T F. Johto γ γ on vsen johto, merkitään γ γ, jos kusskin johtoskeless on produktiot sovellettu merkkijonon vsemmnpuoleisimpn välikkeeseen (edellä johto (i)). Vstvsti määritellään oike johto (edellä (iii)), jot merkitään γ Suori vsempi j oikeit johtoskeli merkitään γ γ j γ γ. γ Olkoon G = (V, Σ, P, S) yhteydetön kielioppi. Kieliopin G mukinen jäsennyspuu on järjestetty puu, joll on seurvt ominisuudet: (i) puun solmut on nimetty joukon V ε lkioill siten, että sisäsolmujen nimet ovt välikkeitä (so. joukost N = V Σ) j juurisolmun nimenä on lähtösymboli S; (ii) jos A on puun jonkin sisäsolmun nimi, j X 1,...,X k ovt sen jälkeläisten nimet järjestyksessä, niin A X 1... X k on G:n produktio. Jäsennyspuun τ tuotos on merkkijono, jok sdn liittämällä yhteen sen lehtisolmujen nimet esijärjestyksessä ( vsemmlt oikelle ).
simerkki. Luseen jäsennyspuu kieliopiss G expr : Luseen johto: T F T T T F T T F T F Johto S = γ 0 γ 1 γ n = γ vstvn jäsennyspuun muodostminen: (i) puun juuren nimeksi tulee S; jos n = 0, niin puuss ei ole muit solmuj; muuten (ii) jos ensimmäisessä johtoskeless on sovellettu produktiot S X 1 X 2... X k, niin juurelle tulee k jälkeläissolmu, joiden nimet vsemmlt oikelle ovt X 1, X 2,...,X k ; (iii) jos seurvss skeless on sovellettu produktiot X i Y 1 Y 2... Y l, niin juuren i:nnelle jälkeläissolmulle tulee l jälkeläistä, joiden nimet vsemmlt oikelle ovt Y 1, Y 2,...,Y l ; j niin edelleen. Konstruktiost huomtn, että jos τ on jotkin johto S γ vstv jäsennyspuu, niin τ:n tuotos on γ. Olkoon τ kieliopin G mukinen jäsennyspuu, jonk tuotos on päätemerkkijono x. Tällöin τ:st sdn vsen johto x:lle käymällä puun solmut läpi esijärjestyksessä ( ylhäältä ls, vsemmlt oikelle ) j lventmll vstn tulevt välikkeet järjestyksessä puun osoittmll tvll. Oike johto sdn käymällä puu läpi käänteisessä esijärjestyksessä ( ylhäältä ls, oikelt vsemmlle ). Muodostmll nnetust vsemmst johdost S x ensin jäsennyspuu edellä esitetyllä tvll, j sitten jäsennyspuust vsen johto, sdn tkisin lkuperäinen johto; vstv tulos pätee myös oikeille johdoille. simerkki. Luseen vsemmn johdon muodostminen jäsennyspuust. 1 2 T 1 T 2 F 2 F 1 2 1 2 T 2 F 1 1 T 1 F 2 2 T T T F T T F 1
Luse 3.3 Olkoon G = (V, Σ, P, S) yhteydetön kielioppi. Tällöin: (i) jokisell G:n lusejohdoksell γ on G:n mukinen jäsennyspuu τ, jonk tuotos on γ; (ii) jokist G:n mukist jäsennyspuut τ, jonk tuotos on päätemerkkijono x, vstvt yksikäsitteiset vsen j oike johto S x j S x. Seurus 3.4 Jokisell G:n luseell on vsen j oike johto. Siis: yhteydettömän kieliopin tuottmien luseiden jäsennyspuut, vsemmt j oiket johdot vstvt yksikäsitteisesti toisin. Jäsennysongelmn rtkisuun ktsotn usein kuuluvn pelkän päätösongelmn Onko x L(G)? rtkisemisen lisäksi jonkin näistä jäsennysesityksistä tuottminen. Kieliopin moniselitteisyys Luseell voi oll kieliopiss useit jäsennyksiä. simerkki. Trkstelln yksinkertisten ritmeettisten lusekkeiden kielioppi: G expr =,,, (). Luseell on tässä kieliopiss kksi jäsennystä: Yhteydetön kielioppi G on moniselitteinen, jos jollkin G:n luseell x on kksi erilist G:n mukist jäsennyspuut. Muuten kielioppi on yksiselitteinen. Moniselitteisyys on tietojenkäsittelysovelluksiss yleensä ei-toivottu ominisuus, kosk se merkitsee että nnetull luseell on kksi vihtoehtoist tulkint. Yhteydetön kieli, jonk tuottvt kieliopit ovt kikki moniselitteisiä, on luonnostn moniselitteinen. simerkiksi kielioppi G expr on moniselitteinen, kieliopit G expr j G mtch yksiselitteisiä. Kieli L expr = L(G expr) ei ole luonnostn moniselitteinen, kosk sillä on myös yksiselitteinen kielioppi G expr. Luonnostn moniselitteinen on esimerkiksi kieli (Todistus sivuutetn.) i b j c k i = j ti j = k. 3.4 Osittv jäsentäminen Yksi (yleisessä muodoss tehoton!) tp etsiä vsent johto (jäsennyspuut) nnetun kieliopin G mukiselle luseelle x on loitt G:n lähtösymbolist j generoid systemttisesti kikki mhdolliset vsemmt johdot (jäsennyspuut), smll sovitten muodostetun lusejohdoksen päätemerkkejä (puun lehtiä) x:n merkkeihin. i-yhteensopivuuden ilmetessä peruutetn viimeksi tehty produktiovlint j kokeilln järjestyksessä seurv vihtoehto. Tällist luseenjäsennystp snotn osittvksi, kosk siinä trksteltu luse yritetään joht kieliopin lähtösymbolist osittmll se vlittujen produktioiden mukisiin rkenneosiin j yrittämällä näin, trvittess toistuvsti edelleen osittmll, sovitt kieliopin tuottm rkennett yhteen luseen rkenteen knss.
sim. Trkstelln kielioppi G: T T T T (). Luseen osittv jäsennys G:n suhteen: T T [ristiriit; peruutetn] () T [ristiriit; peruutetn] T T [ristiriit; peruutetn] T T () [ristiriit; peruutetn] T [ristiriit; peruutetn] T () [ristiriit; peruutetn] T [OK!] m. osittv jäsennystekniikk sdn huomttvsti tehokkmmksi, jos kieliopill on sellinen ominisuus, että jäsennyksen jok viheess määrää tvoitteen olevn luseen seurv merkki yksikäsitteisesti sen, mikä lvennettvn olevn välikkeeseen liittyvä produktio on vlittv. Kielioppi, joll on tämä ominisuus, snotn LL(1)-tyyppiseksi. Muoktn G:stä välikkeen produktiot tekijöimällä ekvivlentti kielioppi G : T ε T (). simerkiksi luseen jäsentäminen G :n suhteen (kulloisenkin produktiovlinnn määräävä syötemerkki on tässä merkitty vstvn johtonuolen päälle): T T ε. LL(1)-tyyppiselle kieliopille on helppo kirjoitt jäsennysohjelm suorn rekursiivisin proseduurein. simerkiksi kieliopin G pohjlt voidn muodost seurv C-kielinen funktiokokoelm, jok syötejonon jäsennyksen yhteydessä tulost sen tuottvn vsemmn johdon produktiot järjestyksessä. #include <stdio.h> int next; void (void); void prime(void); void T(void); void (void) printf(" -> T \n"); T(); prime(); void prime(void) if (next == ) printf(" -> \n"); next = getchr(); (); else if (next == - ) printf(" -> -\n"); next = getchr(); (); else printf(" -> \n");
void T(void) if (next == ) printf("t -> \n"); next = getchr(); else if (next == ( ) printf("t -> ()\n"); next = getchr(); (); if (next!= ) ) RROR(") expected."); next = getchr(); else RROR("T cnnot strt with this."); void RROR(chr *msg) printf("%s\n",msg); exit(1); int min(void) next = getchr(); (); exit(0); simerkiksi syötejono -() käsitellessään ohjelm tulost seurvt rivit: T T - T T () T T T T Tulostus vst vsent johto: T T () (T ) ( ) ( ) ( T ) ( ) ( ) ( ).