815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

Samankaltaiset tiedostot
ICS-C2000 Tietojenkäsittelyteoria Kevät 2016

ITKP102 Ohjelmointi 1 (6 op)

11.4. Context-free kielet 1 / 17

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

815338A Ohjelmointikielten periaatteet

FORMAALI SYSTEEMI (in Nutshell): aakkosto: alkeismerkkien joukko kieliopin määräämä syntaksi: sallittujen merkkijonojen rakenne, formaali kuvaus

Laskennan mallit (syksy 2010) Harjoitus 8, ratkaisuja

815338A Ohjelmointikielten periaatteet Harjoitus 7 Vastaukset

Java-kielen perusteet

Ohjelmoinnin perusteet Y Python

Se mistä tilasta aloitetaan, merkitään tyhjästä tulevalla nuolella. Yllä olevassa esimerkissä aloitustila on A.

815338A Ohjelmointikielten periaatteet Harjoitus 6 Vastaukset

Luonnolliset vs. muodolliset kielet

M =(K, Σ, Γ,, s, F ) Σ ={a, b} Γ ={c, d} = {( (s, a, e), (s, cd) ), ( (s, e, e), (f, e) ), (f, e, d), (f, e)

ITKP102 Ohjelmointi 1 (6 op)

Metodien tekeminen Javalla

Tietorakenteet (syksy 2013)

ITKP102 Ohjelmointi 1 (6 op)

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

Ohjelmassa henkilön etunimi ja sukunimi luetaan kahteen muuttujaan seuraavasti:

(0 1) 010(0 1) Koska kieli on yksinkertainen, muodostetaan sen tunnistava epädeterministinen q 0 q 1 q 2 q3

Tietueet. Tietueiden määrittely

Attribuuttikieliopit

Osoitin ja viittaus C++:ssa

Algoritmit 2. Demot Timo Männikkö

T Syksy 2002 Tietojenkäsittelyteorian perusteet Harjoitus 8 Demonstraatiotehtävien ratkaisut

tään painetussa ja käsin kirjoitetussa materiaalissa usein pienillä kreikkalaisilla

Harjoitustyö: virtuaalikone

Ohjelmoinnin perusteet Y Python

Metodit. Metodien määrittely. Metodin parametrit ja paluuarvo. Metodien suorittaminen eli kutsuminen. Metodien kuormittaminen

TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 30. marraskuuta 2015

11. Javan valintarakenteet 11.1

Harjoitus 6 (viikko 42)

Tehtävä 2: Säännölliset lausekkeet

Koottu lause; { ja } -merkkien väliin kirjoitetut lauseet muodostavat lohkon, jonka sisällä lauseet suoritetaan peräkkäin.

Pythonin Kertaus. Cse-a1130. Tietotekniikka Sovelluksissa. Versio 0.01b

Kielioppia: toisin kuin Javassa

S BAB ABA A aas bba B bbs c

Harjoitus 3 (viikko 39)

Operaattoreiden ylikuormitus. Operaattoreiden kuormitus. Operaattoreiden kuormitus. Operaattoreista. Kuormituksesta

System.out.printf("%d / %d = %.2f%n", ekaluku, tokaluku, osamaara);

Tietotekniikan valintakoe

Ohjelmassa muuttujalla on nimi ja arvo. Kääntäjä ja linkkeri varaavat muistilohkon, jonne muuttujan arvo talletetaan.

// Tulostetaan double-tyyppiseen muuttujaan "hinta" tallennettu // kertalipun hinta ja vaihdetaan riviä. System.out.printf("%.1f euros.

Harjoitus 6. Käytä String-luokasta vain charat- ja length-operaatioita.

Täydentäviä muistiinpanoja jäsennysalgoritmeista

811120P Diskreetit rakenteet

Taulukot. Jukka Harju, Jukka Juslin

Ohjelmointikielten syntaksista ja semantiikasta

System.out.printf("%d / %d = %.2f%n", ekaluku, tokaluku, osamaara);

Ohjelmointiharjoituksia Arduino-ympäristössä

811120P Diskreetit rakenteet

811312A Tietorakenteet ja algoritmit , Harjoitus 2 ratkaisu

TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 16. marraskuuta 2015

ITKP102 Ohjelmointi 1 (6 op)

jäsentämisestä TIEA241 Automaatit ja kieliopit, syksy 2015 Antti-Juhani Kaijanaho 27. marraskuuta 2015 TIETOTEKNIIKAN LAITOS

8. Näppäimistöltä lukeminen 8.1

KESKI-SUOMEN MAAKUNNAN JA LÄHIKUNTIEN LUKIOIDEN TIETOTEKNIIKAN II KILPAILU

Kirjoita, tallenna, käännä ja suorita alla esitelty ohjelma, joka tervehtii käyttäjäänsä.

Ohjelmoinnin perusteet Y Python

Luento 4 Aliohjelmien toteutus

// Tulostetaan double-tyyppiseen muuttujaan "hinta" tallennettu // kertalipun hinta ja vaihdetaan riviä. System.out.printf("%.1f euros.

Kerta 2. Kerta 2 Kerta 3 Kerta 4 Kerta Toteuta Pythonilla seuraava ohjelma:

Ohjelmoinnin perusteet, 1. välikoe

2. Lisää Java-ohjelmoinnin alkeita. Muuttuja ja viittausmuuttuja (1/4) Muuttuja ja viittausmuuttuja (2/4)

Tietorakenteet ja algoritmit syksy Laskuharjoitus 1

Harjoitus Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti:

CODEONLINE. Monni Oo- ja Java-harjoituksia. Version 1.0

815338A Ohjelmointikielten periaatteet Harjoitus 4 vastaukset

Muodolliset kieliopit

uv n, v 1, ja uv i w A kaikilla

jäsennyksestä TIEA241 Automaatit ja kieliopit, syksy 2016 Antti-Juhani Kaijanaho 29. syyskuuta 2016 TIETOTEKNIIKAN LAITOS Kontekstittomien kielioppien

Javan perusteet. Ohjelman tehtävät: tietojen syöttö, lukeminen prosessointi, halutun informaation tulostaminen tulostus tiedon varastointi

TIEA241 Automaatit ja kieliopit, kesä Antti-Juhani Kaijanaho. 10. kesäkuuta 2013

Perusteet. Pasi Sarolahti Aalto University School of Electrical Engineering. C-ohjelmointi Kevät Pasi Sarolahti

Jäsennys. TIEA341 Funktio ohjelmointi 1 Syksy 2005

Johdatus lukuteoriaan Harjoitus 11 syksy 2008 Eemeli Blåsten. Ratkaisuehdotelma

T Syksy 2006 Tietojenkäsittelyteorian perusteet T Harjoitus 7 Demonstraatiotehtävien ratkaisut

Java-kielen perusteita

Vasen johto S AB ab ab esittää jäsennyspuun kasvattamista vasemmalta alkaen:

Java-kielen perusteet

Java-kielen perusteet

Demo 7 ( ) Antti-Juhani Kaijanaho. 9. joulukuuta 2005

Ohjelmoinnin perusteet, syksy 2006

Sisällys. 12. Näppäimistöltä lukeminen. Yleistä. Yleistä

Ohjelmoinnin peruskurssien laaja oppimäärä

Loppukurssin järjestelyt

Perusteet. Pasi Sarolahti Aalto University School of Electrical Engineering. C-ohjelmointi Kevät Pasi Sarolahti

Ohjelmoinnin perusteet Y Python

Alkuarvot ja tyyppimuunnokset (1/5) Alkuarvot ja tyyppimuunnokset (2/5) Alkuarvot ja tyyppimuunnokset (3/5)

Loppukurssin järjestelyt C:n edistyneet piirteet

811120P Diskreetit rakenteet

Java-kielen perusteita

Todistus: Aiemmin esitetyn mukaan jos A ja A ovat rekursiivisesti lueteltavia, niin A on rekursiivinen.

Rekursiiviset palautukset [HMU 9.3.1]

on rekursiivisesti numeroituva, mutta ei rekursiivinen.

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

811120P Diskreetit rakenteet

8. Kieliopit ja kielet

Transkriptio:

815338A Ohjelmointikielten periaatteet 2015-2016. Harjoitus 2 vastaukset Harjoituksen aiheena on BNF-merkinnän käyttö ja yhteys rekursiivisesti etenevään jäsentäjään. Tehtävä 1. Mitkä ilmaukset seuraava kielioppi määrittelee? <sana> ::= <X><Y> <X> ::= a <X>a <Y> ::= b b<y> Vastaus. Tutkitaan ensin välisymboleita <X> ja <Y>. Luonnollisesti X:stä voidaan johtaa a. Kun a on johdettu, rekursiivisen määrittelyn (X:n säännön toinen mahdollisuus) perusteella voidaan johtaa aa, tämän jälkeen aaa jne. Välisymbolin <X> paikalle voidaan siis johtaa merkkijono aa a, missä a-kirjaimia on vähintään yksi kappale. Vastaavalla tavalla huomataan, että välisymbolin <Y> paikalle voidaan johtaa merkkijono bb...b, missä b-kirjaimia on vähintään yksi kappale. Koska <sana>-välisymboliksi voidaan johtaa ilmaus, jossa <X> ja <Y> korvataan millä tahansa kyseisistä välisymboleista johdettavalla lausekkeella, niin kieliopin <sana> -välisymbolin tilalle voidaan johtaa muotoa aa abb..b olevat merkkijonot, joissa a ja b-kirjaimia on kumpaakin ainakin yksi kappale. Tehtävä 2. Määritellään kielioppi seuraavasti <lauseke> ::= <A>a<B>b <A> ::= b <A>b <B> ::= a a<b> Mitkä seuraavista lausekkeista kuuluvat em. kielioppiin a) bbaabb, b) bbaba, c) bbbaaab, d) bbaaabb? Vastaus. Kuten tehtävässä 1, huomataan, että välisymbolin <A> paikalle voidaan johtaa merkkijono bb...b, missä b-kirjaimia on vähintään yksi kappale. Välisymbolin <B> paikalle voidaan johtaa merkkijono aa a, missä a-kirjaimia on vähintään yksi kappale. Koska lausekkeessa välisymbolien <A> ja <B> välissä on kirjain a ja lausekkeen lopussa on kirjain b, niin voidaan todeta että lauseke on muotoa bb...ba..ab, missä alussa b- kirjaimia on vähintään yksi ja a-kirjaimia vähintään kaksi. Lauseke loppuu siis aina kirjaimiin ab. Näin ollen kohtien a), b) ja d) merkkijonoja ei voi johtaa kielioppisäännöillä. Sen sijaan kohdan c) merkkijono bbbaaab voidaan johtaa (konstruoi johto!), joten se sisältyy määriteltyyn kieleen.

Tehtävä 3. Määrittele BNF (tai EBNF) -notaatiolla seuraavat kielen vakioita ilmaisevat välisymbolit (nonterminaalit), joiden määrittely on annettu sanallisesti. <binääriluku> on yhdestä tai useammasta peräkkäisestä numerosta koostuva merkkijono, missä kukin numero voi olla 0 tai 1. <kokonaisluku> on joko etumerkitön tai etumerkillä + tai - varustettu yhdestä tai useammasta peräkkäisestä numerosta koostuva merkkijono, missä kukin numero voi olla 0,..., 9. <desimaaliluku> on merkkijono, joka koostuu joko 1. kokonaisluvusta, 2. desimaaliosasta tai 3. kokonaisluvusta ja sitä seuraavasta desimaaliosasta. Desimaaliosa alkaa pisteellä (.), jota seuraa etumerkitön kokonaisluku. Ohje: Käytä tarvittaessa muita välisymboleja, joille määritellään erikseen sääntö. Vastaus. Tyypit voidaan määritellä seuraavasti (muutkin tavat mahdollisia): Binääriluvussa on siis ainakin yksi numero, joka voi olla 0 tai 1. Määritellään binääriselle numerolle välisymboli, jonka nimeksi valitaan bitti. Jos luvussa on useampia bittejä, niin loppuosa ensimmäisen bitin jälkeen on aina binääriluku. Näin saadaan rekursiivinen määritelmä: <binääriluku> ::= <bitti> <bitti><binääriluku> <bitti> ::= 0 1 Kokonaisluku voidaan rakentaa alhaaltapäin: ensin numerot, sitten etumerkittömät luvut ja lopuksi luvut joissa voi olla etumerkki. Esitetään välisymbolien määritelmät ylhäältä lähtien: <kokonaisluku> ::= [+ -] <etumerkitön> <etumerkitön> ::= <numero> <numero><etumerkitön> <numero> ::= 0 1 2 3 4 5 6 7 8 9 Desimaaliluku voidaan esittää ylläolevia määritelmiä käyttämällä ja määrittelemällä lisäksi desimaaliosa: <desimaaliluku> ::= <kokonaisluku> <desimaaliosa> <kokonaisluku><desimaaliosa> <desimaaliosa> ::=.<etumerkitön>

Tehtävä 4. C -kielen if-lauseen syntaksi on seuraava: <if_lause> ::= if(<lauseke>) <lause> [else <lause>] Näytä, että näin tulee määriteltyä monikäsitteinen kielioppi, kun otetaan huomioon, että if-lause on lauseen erikoistapaus, joten if-lause voi esiintyä säännön oikealla puolella. Ohje: Näytä, että if-lauseella if(ehto1) if(ehto2) lause2 else lause3 on kaksi erilaista johtopuuta, ts. syntaksista ei voi päätellä kumpaan if -lauseeseen else kuuluu. Tätä sanotaan roikkuvan elsen ongelmaksi (dangling else problem). Miten C - kielessä tulkitaan ylläoleva koodi? Vastaus. Lauseelle if(ehto1) if(ehto2) lause2 else lause3 saadaan kaksi erilaista johtoa, kun otetaan huomioon, että välisymboli <lause> voidaan korvata välisymbolilla <if-lause>: <if_lause> -> if(<lauseke>) <lause> -> if(<lauseke>) <if_lause> -> if(ehto1) <if_lause> -> if(ehto1) if(<lauseke>) <lause> else <lause> -> if(ehto1) if(ehto2) <lause> else <lause> -> if(ehto1) if(ehto2) lause2 else <lause> -> if(ehto1) if(ehto2) lause2 else lause3 ja <if_lause> -> if(<lauseke>) <lause> else <lause> -> if(ehto1) <lause> else <lause> -> if(ehto1) <if_lause> else <lause> -> if(ehto1) if(<lauseke>) <lause> else <lause> -> if(ehto1) if(ehto2) <lause> else <lause> -> if(ehto1) if(ehto2) lause2 else <lause> -> if(ehto1) if(ehto2) lause2 else lause3 Näillä johdoilla on erilaiset johtopuut (piirrä ne!). C:ssä (kuten yleisesti muissakin kielissä, joissa on tämä ominaisuus) lause tulkitaan niin, että else viittaa lähimpään iflauseeseen, ts. esimerkiksi

int x = 0; if(x == 0) if( x!= 0) x = 1; else x = 2; sijoittaa muuttujaan x arvon 2 (jäisi nollaksi jos else viittaisi ylempään lauseeseen). Tehtävä 5. Seuraava kielioppi määrittelee joukon symboleja a, b ja c käyttäviä yksinkertaisia yhteen- vähennys- ja kertolaskua sisältäviä aritmeettisia lausekkeita. <lauseke> ::= <termi> <termi> + <termi> <termi> - <termi> <termi> ::= <tekijä> <tekijä> * <termi> <tekijä> ::= a b c Kirjoita C-kielellä (tai jollain muulla valitsemallasi kielellä) kieliopille rekursiivisesti laskeutuva jäsentäjä, jolle jäsennettävä lauseke syötetään komentoriviltä ohjelman alussa ennen jäsennystä. Ohjelma tulostaa virheilmoituksen, jos lauseke ei ollut syntaksiltaan kieliopin hyväksymää muotoa ja ilmoituksen "Lauseke oikeaa muotoa", mikäli kielioppi hyväksyy sen. Virheestä ilmoittaminen on helpointa tehdä kutsumalla virhetilanteen sattuessa tätä varten kirjoitettua funktiota error(), jolle voi antaa virheilmoituksen parametrina. Ohjelman voi myös lopettaa funktiossa. Huomaa, että nyt kaikki lekseemit ovat yhden merkin mittaisia, joten funktio gettoken() voidaan kirjoittaa niin, että se hakee syötteenä saadusta merkkijonosta aina seuraavan merkin. Vastaus. Luennoilla esitettyyn tapaan ohjelma voidaan kirjoittaa niin, että jokaista välisymbolia kohti kirjoitetaan oma (rekursiivinen) metodi, joka jäsentää kyseisen välisymbolin. Lekseemi haetaan globaaliin muuttujaan sym metodissa gettoken(). Tässä tapauksessa lekseemi on aina yhden merkin mittainen, joten funktiosta tulee yksinkertainen. Kun havaitaan virhe, kutsutaan virhefunktiota error, joka päättää ohjelman. Tällöin ohjelman runko olisi seuraava:

// Globaali muuttuja lekseemille char sym; // Globaali muuttuja: missä kohdassa jäsennettävää merkkijonoa ollaan int curpos = 0; // Globaali muuttuja jossa on jäsennettävä merkkijono char orig_expr[max_len_expr]; // Lekseemin tyyppi eli sananen. Voi olla aluksi 0/1 = loppu/kesken int token; // Hakee seuraavan lekseemin int gettoken() { // Lue seuraava merkki jonosta orig_expr muuttujaan sym // ja kasvata osoitinta curpos // Palauta 0 jos jonon lopussa // Virhefunktio tulostaa ilmoituksen ja lopettaa ohjelman. void error(char *msg) { printf("virhe: %s",msg); exit(1); // Jäsentää tekijän void tekija(){ token = gettoken(); // Jos jono loppu niin virhe switch(sym) { // a,b tai c: OK break; // Muu -> virhe // Jäsentää termin void termi() { // Termissä aina tekijä ensimmäisenä tekija(); // Tekijä OK, jatketaan token = GetToken(); // Jos jono loppu, OK switch(sym) { // * : termi jatkuu termi(); // + - OK break; // Muu -> virhe

// Jäsentää lausekkeen void lauseke() { // Lausekkeessa aina termi ensimmäisenä. termi(); // Jos ei loppu niin termi hakenut lekseemin switch(sym) { // + tai tulee uusi termi termi(); // Muu virhe // Tarkistetaan että lauseke loppu, muuten virhe int main(int args, char** argv) { // Luetaan jäsennettävä lauseke merkkijonoon orig_expr printf("anna jasennettava lauseke > "); scanf("%s",orig_expr); // Jäsennetään lauseke lauseke(); // Jos menee läpi tulostetaan että lauseke oikea printf("lauseke OK."); return 0; Harjoituksen yhteyteen on linkitetty kaksi versiota ohjelmasta, joille kummallekin syötetään jäsennettävä lauseke komentoriviltä. Lausekkeessa ei voi olla välilyöntejä ja sen maksimipituus on 99 merkkiä. Ensimmäinen versio ei luokittele lekseemejä, vaan gettoken palauttaa arvon 1 jos lauseketta ei ole luettu loppuun ja arvon 0, jos ollaan lopussa. Jäsentäminen käyttää lekseemin sisältävää muuttujaa sym. Toisessa versiossa lekseemien tyypeille on määritelty lueteltu tyyppi. Tällöin jäsentämisessä voidaan käyttää haetun lekseemin tyyppiä, jolloin virheen raportointi saadaan tarkemmaksi.