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.
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.
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 MathCheckia 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.
Sama kieli voidaan aina 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.
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.
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). VihjeKopioi 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ä. Vihje 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.
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.
Kieli on (äärellinen tai ääretön) joukko merkkijonoja, joista jokainen on äärellinen. 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ä eikä se 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.