Tämä tehtävä on jatkoa tehtävälle Backus-Naur Form. Tässä tehtävässä harjoitellaan yhteysriippumattomien kielioppien muodostamista ja selvennetään joitakin yksityiskohtia.
Jos oikealla alhaalla olevaan isoon laatikkoon kirjoittaa kieliopin, pieneen laatikkoon kirjoittaa merkkijonon, ja painaa nappia, niin MathCheck piirtää merkkijonon jäsennyspuun tai kertoo, että merkkijono ei kuulu kieleen. Tästä voi olla hyötyä kun ratkaistessasi alla olevia tehtäviä saat palautetta, että kielioppisi tuottaa jonkin merkkijonon jota ei olisi pitänyt tuottaa.
Harjoittelemme tätä! Kopioi isoon laatikkoon ylimmälle riville A ::= 0 | 1 ja toiselle riville B ::= A | AB. Kirjoita pikkulaatikkoon 010 ja paina nappia. Mitä saat? Pitäisi tulla tämäThe string "010" is not in the language A.. Vaihda sitten isossa laatikossa ylin ja toinen rivi keskenään, ja paina nappia uudelleen. Pitäisi tulla tämäThe string "010" is in the language B. .
Tulkitse edellisen kohdan jäsennyspuu kielioppia vasten. Toisin sanoen, katso missä B on purettu auki vaihtoehdolla A ja missä vaihtoehdolla AB, ja katso missä A on purettu auki vaihtoehdolla 0 ja missä vaihtoehdolla 1.
Miksi tulos riippui rivien järjestyksestä isossa laatikossa? VastausMerkkijono 010 kuuluu kieleen B mutta ei kuulu kieleen A. Jollei muuta sanota, BNF-määritelmä kokonaisuutena tarkoittaa sitä kieltä, joka määritellään ensimmäisenä. Siksi kun B:n määritelmä on ylinnä, vastaukseksi tulee että 010 kuuluu B:hen sekä jäsennyspuu, mutta kun A:n määritelmä on ylinnä, vastaukseksi tulee että 010 ei kuulu A:han.
Miten edellä olleista kieliopeista voi päätellä, sisältääkö kieli kaikki n.y.k. jonot?
X ::= A | XA VastausA:n kieli on {0, 1}. Siksi A ei tuota ε:a. Myöskään XA ei tuota ε:a, koska jokainen XA:n tuottama merkkijono loppuu johonkin minkä A tuottaa, siis 0:aan tai 1:een. Niinpä A | XA ei tuota ε:a.
X ::= A | XC Vastaus Kuten edellä todettiin, A ei tuota ε:a. Jotta XC tuottaisi ε:n, pitää sekä X:n että C:n tuottaa ε. C tuottaa sen. X:n kohdalla syntyy muna-kana-ongelma: X tuottaa ε:n jos XC tuottaa ε:n, ja XC tuottaa ε:n jos X tuottaa ε:n. BNF:ssä vain sellainen tuottaminen merkitsee, jossa ei ole mukana jossittelua. Siksi X ei tuota ε:a. (Sama perustelu olisi kelvannut edellisessä kohdassa.) LisätietoaTämä kohta poikkeaa edellisestä sikäli, että jokainen merkkijono joka voidaan tuottaa, voidaan tuottaa äärettömän monella eri tavalla. Jos jokin merkkijono on tuotettu jollain tavalla, voidaan se tuottaa uudelleen yhtä askelta pitemmällä tavalla säännöllä X ::= A | XC valitsemalla se X:ksi ja tuottamalla C:stä ε.
X ::= C | XA VastausTyhjä merkkijono saadaan valitsemalla oikealta puolelta C ja sen tuotoksista ε. Mikä tahansa muu merkkijono saadaan rekursiivisesti. Ensin tuotetaan sen muut merkit paitsi viimeinen. Tämä tulos valitaan oikean puolen X:ksi, ja viimeinen merkki tuotetaan A:sta.
X ::= C | XC VastausEdellisen kohdan vastaus kelpaa tähän siten muutettuna, että viimeinen merkki tuotetaan XC:n C:stä.
Alla on kuvaus merkkijonojen ja kielioppien kirjoittamisesta MathCheckille. Se ei ole siinä siksi, että opiskelisit sen ulkoa, vaan siksi, että kun jäljempänä tarvitset yksityiskohtia, voit katsoa ne siitä. Se on myös esimerkki siitä, minkälaisia asioita voi tulla vastaan, kun laaditaan tarkka, eri näkökohtia huomioon ottava spesifikaatio näennäisesti yksinkertaiselle asialle.
Merkkijono voidaan kirjoittaa MathCheckille muutamalla eri tavalla:
Kielioppi esitetään MathCheckille nollalla tai useammalla välisymbolin määritelmällä, joiden perässä voi olla alkusymbolin asetus.
Matemaattisessa kirjallisuudessa on tapana esittää kukin välisymbolin määritelmä omalla rivillään tai usealla rivillä, joista muut kuin ensimmäinen on sisennetty. MathCheckissä voi tehdä niinkin, mutta ollakseen sekä itsensä että monien ohjelmointi- yms. kielten kanssa johdonmukainen, MathCheck sallii käyttää välilyöntejä ja rivinsiirtoja vapaasti kunhan tekstialkiot eivät mene sekaisin. Esimerkiksi A::=aB B ::=""|bB toimii mutta A::=aBB ::=""|bB ei toimi, koska toinen B ei tule tulkituksi kielen B määritelmän aluksi vaan osaksi kielen A määritelmän viimeistä vaihtoehtoa. Kokeile oikealla alhaalla kumpikin näistä kieliopeista merkkijonolla abb.
Kieliopin lopussa on aina ;, jotta MathCheck ei tulkitsisi seuraavan komennon alkua osaksi kielioppia. Sinun ei kuitenkaan tarvitse välittää tästä, koska opettaja on kirjoittanut sen puolestasi.
Miten MathCheckin merkkijonoon saa rivinsiirron? VastausEi mitenkään. Olisi siihenkin voitu keino kehittää, mutta se tuskin olisi tuottanut yhtä paljon pedagogista hyötyä kuin se olisi tuottanut vaivaa ja ongelmia. Olisi mm. pitänyt keksiä, miten rivinsiirto piirretään jäsennyspuun solmuun. MathCheckin saa jättämään merkkijonoon tarjotut rivinsiirrot huomiotta, mutta ei saa ottamaan niitä mukaan. Miten MathCheckille ilmaistaan ε? Vastaus Tyhjä merkkijono ilmaistaan MathCheckille joko "" tai ''. Matematiikassa tyhjää merkkijonoa merkitään symbolilla ε, mutta MathCheckiä ei ole opetettu tulkitsemaan symbolia ε tyhjäksi merkkijonoksi. Jos MathCheckin syötteessä on ε, niin MathCheck tulkitsee sen UTF-8-koodauksen mukaisesti kahden merkin mittaiseksi merkkijonoksi.
Jos kieli voidaan tuottaa millään kieliopilla, niin se voidaan tuottaa monella eri kieliopilla. Alla on muutama kielioppi, jotka kaikki tuottavat kielen {ε, a, aa, aaa, …}. Kokeile valmiiksi annetulla ja muutamalla muulla merkkijonolla, minkälainen jäsennyspuu tulee.
Kielioppi on moniselitteinen, jos ja vain jos jollakin merkkijonolla on kaksi eri jäsennyspuuta. Mikään lähellä yllä olevista kieliopeista ei ole moniselitteinen. Esimerkiksi A ::= ε | aaaA | aaA on moniselitteinen, koska se tuottaa merkkijonon aaaaaa molempien kuvien mukaisesti.
Usein pyritään välttämään moniselitteisyyttä. Sen välttäminen on kuitenkin joskus vaikeaa tai jopa mahdotonta.
Suunnittele seuraavat kieliopit. Aakkostona on {0, 1}, ja alkusymbolit on annettu valmiiksi. Voit määritellä vapaasti lisää välisymboleita. Aluksi salli moniselitteisyys. Sitten kiellä se ja paranna kielioppia kunnes MathCheck hyväksyy sen.
Miten voit tässä lähellä olevia työkaluja käyttäen helposti selvittää, voidaanko ostaa 18 munkkirinkilää ja jos kyllä niin miten voidaan? VastausKopioimalla yllä oleva kielioppi oikealle alas isoon laatikkoon, kirjoittamalla 18 m-kirjainta pieneen laatikkoon ja painamalla vastausnappia. JatkokysymysMiten voidaan helposti kirjoittaa 18 m-kirjainta niin että ei tule vahingossa 17 tai 19? VastausKirjoittamalla 6 m-kirjainta, maalaamalla ja kopioimalla se, ja pudottamalla se maalatun päälle kolmesti.
Tehtäväsi on selvittää suurin määrä munkkirinkilöitä, jota ei voi muodostaa ostamalla sopiva yhdistelmä pakkauksia. Käytettävissäsi on kaksi laatikkoa, joihin kumpaankin voit kirjoittaa kieliopin. Kun painat nappia, MathCheck vertaa kielioppien tuottamat kielet (sillä rajoituksella, että MathCheck ei selviä kovin monimutkaisista tapauksista). vihje1Kopioi edellisen tehtävän kielioppi molempiin ruutuihin. Lisää alempaan kielioppiin vaihtoehto, jolla voi ostaa kolme munkkirinkilää ja superpakkauksen. Laadi superpakkauksen kielioppi siten, että superpakkauksen koko voi olla mikä tahansa nollaa suurempi määrä munkkirinkilöitä. vihje2 Kun painat nappia, MathCheck kertoo, että superpakkauksen avulla voi ostaa viisi munkkirinkilää mutta ilman sitä ei voi. Kun kasvatat superpakkauksen kanssa ostettavien munkkirinkilöiden määrän kolmesta viiteen, MathCheck kertoo seuraavan koon, jonka voi ostaa superpakkauksen avulla mutta ei ilman sitä.
Suunnittele seuraavat kieliopit. Aakkostona on {a, b}, ja alkusymbolit on annettu valmiiksi. Kun moniselitteisyys kielletään, tehtävät eivät muutu mahdottomiksi, mutta melko vaikeiksi kylläkin. Ihan hyvä, jos saat nämä ratkaistua moniselitteisestikin, mutta jos kaipaat kunnon haastetta, niin kiellä moniselitteisyys. (Saat merkata näistä pisteet jos saat ne ratkaistua moniselitteisesti.)
Kirjoita kielioppi M MathCheckin merkkijonoille olettaen, että välilyönti, " ja ' edustavat itseään, ja m edustaa mitä tahansa muuta merkkiä joka voi tulla kyseeseen. Jotta tehtävä ei olisi liian vaikea, jätä huomiotta tekstialkioiden välinen tyhjä tila ja merkin $ erikoistehtävä.
Lopuksi muutama asia, joissa aikaisempien tenttivastausten perusteella on ollut väärinkäsityksiä.
Jokainen seuraavista kieliopeista tuottaa tyhjän kielen, koska …mistään niistä ei voi johtaa merkkijonoa, jossa ei ole välisymboleita, koska jokaisessa vaihtoehdossa on ainakin yksi välisymboli.
Jokainen merkkijono on äärellinen. Esimerkiksi a, aa ja aaa ovat merkkijonoja, mutta aaa… ei ole. On olemassa äärettömien merkkijonojen teoria, mutta BNF ei käsittele sitä eikä tämä kurssi myöskään.
Kieli on joukko merkkijonoja. Kieli voi olla äärellinen tai ääretön. Jälkimmäisessä tapauksessa kielessä on äärettömän monta merkkijonoa, mutta jokainen niistä on äärellinen. Esimerkiksi kielessä {ε, a, aa, aaa, …} on äärettömän monta merkkijonoa.
Kielioppi A ::= ε | aA ei tuota ääretöntä merkkijonoa aaa… eikä joukkoa {aaa…}. Se tuottaa äärettömän monta erilaista merkkijonoa, nimittäin merkkijonot ε, a, aa, aaa ja niin edelleen, eli se tuottaa joukon {ε, a, aa, aaa, …} eli {a0, a1, a2, a3, …}. Se ei tuota merkkijonoa an, missä n on luonnollinen luku. Se tuottaa joukon {an | n ∈ ℕ}.
Kielioppi A ::= aAb ei tuota merkkijonoa aaa…bbb, sillä A ::= aAb ei tuota sitä. Se ei edes ole merkkijono.
Kieli ei ole kaikkien merkkijonojen joukko eikä edes kaikkien aakkostosta muodostettavien merkkijonojen joukko. Kieli on joukko aakkostosta muodostettavia merkkijonoja eli kaikkien aakkostosta muodostettavien merkkijonojen joukon osajoukko.
Äärellinen kieli on kieli, jossa on vain äärellinen määrä merkkijonoja. Esimerkiksi A ::= aa | aaa määrittelee äärellisen kielen, mutta A ::= aa | aaaA määrittelee äärettömän kielen. Vaikka kieli olisi ääretön, jokainen siihen kuuluva merkkijono on äärellinen.
Hupsista, yllä oleva kuva ei ole mittakaavassa. Jotkin joukot on piirretty liian isoiksi toisiin nähden. Piirretään se uudestaan mittakaavaan, jotta joukkojen kokoerot näkyisivät oikein.
Piirtäisin mielelläni myös mittakaavassa olevan kuvan, josta kaikkien kielten joukko puuttuu mutta muut kolme ovat mukana. Valitettavasti en osaa, sillä vaikka niiden välillä vallitsevat aidot osajoukkosuhteet ovat kuten ensimmäinen kuva näyttää, ne ovat keskenään yhtäsuuria. Ääretön joukko todellakin voi olla yhtäsuuri kuin aito osajoukkonsa.
Syy näihin on ilmiöissä, joita tutkitaan tehtävässä Rationaalilukujen joukko on nollamitallinen.