T-79.148 Kevät 2004 Tietojenkäittelyteorin peruteet Hrjoitu 7 Demontrtiotehtävien rtkiut 4. Tehtävä: Ooit, että yhteydettömien kielten luokk on uljettu yhdite-, ktentioj ulkeumopertioiden uhteen, o. jo kielet L 1, L 2 Σ ovt yhteydettömiä, niin moin ovt myö kielet L 1 L 2, L 1 L 2 j L 1. Vtu: Olkoon L 1 j L 2 yhteydettömiä kieliä. Tällöin on olem kieliopit G 1 = (V 1, Σ 1, R 1, S 1 ) j G 2 = (V 2, Σ 2, R 2, S 2 ), iten, että L(G 1 ) = L 1 j L(G 2 ) = L 2. Vditn liäki, että (V 1 Σ 1 ) (V 2 Σ 2 ) =, eli kieliopei ei eiinny moj välikkeitä. Kok kieliopin välikkeet voidn trvitte nimetä uudelleen, ei tämä et oleellit rjoitut. 5. Tehtävä: Unioni: Olkoon S uui välike j G = (V 1 V 2 S, Σ 1 Σ 2, R 1 R 2 S S 1 S 2, S. Nyt L(G) = L(G 1 ) L(G 2 ) = L 1 L 2. Näin on, kok S:tä voidn joht vin S 1 ti S 2, joit voidn edelleen joht vin noj jotk kuuluvt jompn kumpn iemmit kielitä (ääntöjen eknnukelt vältytään, kok välikejoukot ovt pitevierit). Ktentio: Tällä kert uui kielioppi G = (V 1 V 2 S, Σ 1 Σ 2, R 1 R 2 S S 1 S 2, S. Nyt L(G) = L 1 L 2. Kleenen tähti: Tällä kert uui kielioppi G = (V 1 S, Σ 1, R 1 S ɛ SS 1, S. Nyt L(G) = L 1 () Ooit, että eurv yhteydetön kielioppi on monielitteinen: S S ele S S. (b) Muodot ()-kohdn kieliopin kn ekvivlentti, o. mn kielen tuottv ykielitteinen kielioppi. Vtu: Yhteydetön kielioppi G on monielitteinen, mikäli on olem n w L(G) iten, että w:llä on inkin kki erilit jäennypuut. Tehtävän kieliopille ykinkertiin tällinen n on: if b then if b then ele, jok voidn jäentää khdell tp: S ele S 1
S ele S Yleenä ohjelmointikieliä hlutn ele-lue liittää lähinpään mhdollieen if-lueeeen. Ylläolevit puit enimmäinen vt tätä käytäntöä. Määritellään kielioppi eurvti: G = (V, Σ, P, S) V = S, B, U,, b, if, then, ele Σ =, b, if, then, ele P = S B U B if b then B ele B U if b then B ele U Tää välikeellä B dn johdettu vin ohjelmi, joi kikill if-lueill on ekä then- että ele-hrt. Välikkeellä U johdetn itten if-lueet, joit puuttuu elehr. 6. Tehtävä:Ldi rekuriivieti etenevä jäentäjä edelliten hrjoituten tehtävän 6 kieliopille. Vtu: All olev C-ohjelm toteutt rekuriivien jäentäjän kieliopille: C S S; C S begin C end for n time do S Tää on ykinkertitettu hiemn edellien lkuhrjoitukerrn 6. tehtävän kielioppi korvmll erilliet numerot terminlill n, jok trkoitt mitä thn numero. Tärkeimmät ohjelm eiintyvät funktiot ovt: C(), S() toteuttvt kieliopin vriniet äännöt lex() lukee yötteetä eurvn lekeemin j tllett en globliin muuttujn current tok. expect(int token) yrittää luke yötteetä lekeemin token. Mikäli lukeminen epäonnituu nnetn virheilmoitu. conume token() merkitään tämänhetkinen lekeemi käytetyki. Tämä (ti jokin muu vtv funktio) trvitn iki, että joiin tpuki täytyy yötettä luke yki lekeemi eteenpäin ennen kuin tiedetään, mitä ääntöä täytyy käyttää. Käytännöä ohjelmointikielten jäentäjät toteutetn yleenä käyttäen lex- j ycc-työkluj 1. Näitä lex muodot tilkonepohjien eljn, jok tunnit äännölliillä luekkeill määritellyt lekeemit, j ycc tekee pinoutomttipohjien jäentimen nnetulle yhteydettömälle kieliopille. 1 Ti niiden johdnnii. 2
#include <tdio.h> #include <tdlib.h> #include <ctype.h> /* Define the lphbet */ enum TOKEN DO, FOR, END, BEGIN, TIMES, OP, SC, NUMBER, ERROR ; cont chr* token[] = "do", "for", "end", "begin", "time", "", ";", "NUMBER", NULL ; /* A globl vrible holding the current token */ int current_tok = ERROR; /* Mximum length of token */ #define TOKEN_LEN 128 /* declre function correponding to nonterminl */ void S(void); void C(void); int lex(void); void conume_token(void); void error(chr *t); void expect(int token); void C(void) S(); lex(); if (current_tok == SC) C(); printf("c => S ; C\n"); ele printf("c => S\n"); void S(void) lex(); witch (current_tok) ce OP: printf("s => \n"); ce BEGIN: C(); expect(end); printf("s => begin C end\n"); ce FOR: expect(number); 3
expect(times); expect(do); S(); printf("s => for N time do S\n"); defult: error("pre error"); /* int lex(void) return the next token of the input. */ int lex(void) ttic chr token_text[token_len]; int po = 0, c, i, next_token = ERROR; /* I there n exiting token lredy? */ if (current_tok!= ERROR) return current_tok; /* kip whitepce */ do c = getchr(); while (c!= EOF && ipce(c)); if (c!= EOF) ungetc(c, tdin); /* red token */ c = getchr(); while (c!= EOF && c!= ; &&!ipce(c) && po < TOKEN_LEN) token_text[po++] = c; c = getchr(); if (c == ; ) if (po == 0) /* emicolon token */ next_token = SC; ele /* triling emicolon, leve it for future */ ungetc( ;, tdin); token_text[po] = \0 ; /* triling zero */ /* identify token */ if (idigit(token_text[0])) /* number? */ next_token = NUMBER; ele /* not number */ for (i = DO; i < NUMBER; i++) if (!trcmp(token[i], token_text)) next_token = i; current_tok = next_token; return next_token; 4
void conume_token(void) current_tok = ERROR; void error(chr *t) printf(t); exit(1); /* try to red token from input */ void expect(int token) int next_tok = lex(); if (next_tok == token) return; ele error("pre error"); int min(void) int i; C(); return 0; Liite: oikelle lineriet kieliopit Yhteydetön kielioppi G on oikelle linerinen, mikäli en kikki äännöt ovt muoto: A αb, miä α Σ j B V ε. Toiin noen, äännön oikell puolell eiintyä korkeintn yki välike, j en täytyy oll äännön lopu. Eimerkiki äännöt A bc j A ε ovt oikelle linerii, mutt A B j A bcd eivät ole. Vtvti vemmlle linerien kieliopin kikki äännöt ovt muoto A Bα. Lineriet kieliopit ovt ilmiuvoimltn mll toll kuin äärelliet utomtit, eli niillä voidn ilmit kikki äännölliet kielet. Säännöllien kielen tuottv oikelle linerinen kielioppi voidn luke uorn kielen tunnitvt utomtit. Kieliopin välikkeiki otetn utomtin tilt, j kutkin utomtin iirtymätä q i q j dn ääntö Q i Q j. Liäki kielioppiin liätään äännöt Q f ε kikille hyväkyville lopputiloille q f F. Eimerkiki utomtti: q 2 q q 1 0 b b b 5
vtv kielioppi on: Q 0 Q 1 bq 2 ε Q 1 Q 2 bq 0 Q 2 Q 0 bq 1. 6