Kontekstittomien kielten jäsentäminen äydentäviä muistiinpanoja IA241 Automaatit ja kieliopit, syksy 2016 Antti-Juhani Kaijanaho 19. lokakuuta 2016 1 Yksiselitteiset operaattorikieliopit 1.1 Aritmeettiset lausekkeet ällä kurssilla on tullut tutuksi aritmeettisten lausekkeiden moniselitteinen kielioppi c + / () ässä kieliopissa on yksi prefiksioperaattori (), neljä infiksioperaattoria (+,, ja /) ja kaksi primäärilauseketta (c ja ()). Huomaa, että yksi päätemerkeistä on kaksoisroolissa: on sekä prefiksioperaattori (negaatio) että infiksioperaattori (vähennyslasku). avanomainen aritmeettisten operaattoreiden presedenssijärjestys on seuraava: korkein presedenssi on negaatiolla, seuraavaksi korkein on kerto- ja jakolaskulla, ja alin presedenssi on yhteen- ja vähennyslaskulla. Aritmetiikassa ei ole väliä, ovatko yhteen-, vähennys- ja kertolasku vasemmalle vai oikealle assosiatiivisia, mutta tavanomaista ohjelmointikielissä on julistaa ne vasemmalle assosiatiivisiksi. Jakolaskulle on luonnollista ottaa sama assosiatiivisuus kuin kertolaskulle. refiksioperaattorina negaatio on luontevimmin oikealle assosiatiivinen, jolloin 4 = (4). Lajitellaan nyt operaattorit luokkiin. Aritmeettisten lausekkeiden tapauksessa luokilla on vakiintuneet nimet: 1. Lausekeluokkaan (engl. expressions) kuuluvat yhteen- ja vähennyslaskut. 2. ermiluokkaan (engl. terms) kuuluvat kerto- ja jakolaskut. 1
3. ekijäluokkaan (engl. factors) kuuluu negaatio. Lisäksi lisätään loppuun primäärilausekkeiden luokka, johon kuuluvat vakiolausekkeet ja suljelausekkeet. Valitaan kullekin luokalle englanninkielisen nimen alkukirjain välikesymboliksi:,, ja. Noudattamalla kalvojen menetelmää edelleen saadaan seuraava yksiselitteinen kielioppi: + / c () 1.2 Säännölliset lausekkeet Säännöllisille lausekkeille voidaan kirjoittaa seuraava moniselitteinen kontekstiton kielioppi: R () c R RR R R (R) (Huomaa kieliopissa valintaa merkitsevän pystyviivan ja päätemerkin huonosti näkyvä mutta erittäin tärkeä ero.) Aluksi todetaan operaattorit. Löytyy yksi postfiksioperaattori ( ), kaksi infiksioperaattoria (ε ja ) ja neljä primäärilauseketta (, c, () ja (R)). Ne muodostavat presedenssiluokat seuraavasti: 1. 2. ε 3. Näille ei ole erityisiä nimiä, joten käytetään välikesymbolien niminä alaindeksoitua R:ää. Käsitellään kaikkia operaattoreita vasemmalle assosiatiivisina. Nyt saadaan seuraava yksiselitteinen kielioppi: R 1 R 2 R 1 R 2 R 2 R 3 R 2 R 3 R 3 R 4 R 3 R 4 c () (R 1 ) 2
2 Vasemman rekursion poisto Molemmat edellä laaditut yksiselitteiset kieliopit ovat vasenrekursiivisia. Sen poistaminen johtaa seuraavanlaisiin kielioppeihin: ε + ε / c () R 1 R 2 R 1 R 1 ε R 2 R 1 R 2 R 3 R 2 R 2 ε R 3 R 2 R 3 R 4 R 3 R 3 ε R 3 R 4 c () (R 1 ) 3 Aritmeettisten lausekkeiden ennustava jäsennys Käytetään seuraavaa kielioppia: ε + ε / c () 3
Lasketaan ensiksi NULLABL. Alustetaan: NULLABL roduktio ei sisällä yhtään päätemerkkiä mutta sen kaikki välikemerkit eivät ole merkitty, joten se ei johda merkintään. Sen sijaan ε ei sisällä yhtään päätemerkkiä ja sen kaikki välikemerkit (joita ei ole) on merkitty, joten tulee merkitä: NULLABL roduktiot + ja eivät johda merkintöihin, eikä myöskään. Sen sijaan ε aiheuttaa :n merkinnän: NULLABL Muut vielä läpikäymättömät produktiot eivät aiheuta merkintää. Aloitetaan siis alusta uudestaan. sisältää yhden ei-merkitsemättömän välikesymbolin, joten se ei aiheuta merkintää. on jo merkitty, joten sen produktioita ei tarvitse käydä läpi. sisältää yhden ei-merkitsemättömän välikesymbolin, joten sekään ei iheuta merkintään. on jo merkitty. Myöskään,, c ja () ei aiheuta merkintöjä. Kun tämä uusi iteraatio ei aiheuttanut lisämerkintöjä, NULLABL-taulukko on 4
valmis: NULLABL Laaditaan sitten IRS-taulukko. Se on luonnollista laatia NULLABLtaulukon uudeksi sarakkeeksi. Alustetaan: NULLABL IRS arkastellaan ensin produktiota. Sille k = 0, sillä ei ole NULLABL. aulukko ei muutu, koska :n kohta taulukossa on tyhjä. roduktiota ε ei voi tarkastella. arkastellaan sen sijaan produktiota +. Sille k = 0, sillä + ei ole NULLABL. Koska + on päätemerkki, se lisätään taulukkoon :n kohdalle. Sama päättely produktiolla johtaa :n lisäämiseen. NULLABL IRS +, roduktio ei johda lisäyksiin. roduktiota ε ei voi tarkastella. roduktiot ja / johtavat samalla päättelyllä kuin edellä päätemerkkien ja / lisäämiseen :n kohdalle. 5
NULLABL IRS +,, / roduktio ei johda lisäyksiin, mutta lisää :n kohdalle :n. NULLABL IRS +,, / roduktio c lisää c:n ja () lisää (:n :n kohdalle. NULLABL IRS +,, / Nyt kaikki produktiot on käyty kerran läpi. Koska lisäyksiä tuli, pitää kierros uusia. roduktiot, ε, + ja eivät aiheuta lisäyksiä. Sen sijaan produktiossa on lisättävä :n merkit :lle. NULLABL IRS +,, / 6
Myös produktio aiheuttaa kopiointitarvetta, tällä kertaa :stä :ään: NULLABL IRS +,, /, c, ( :n produktiot eivät aiheuta lisää muutoksia. Koska tämäkin kierros muutti taulukkoa, on otettava vielä yksi kierros. roduktio kopioi :n merkit :lle: NULLABL IRS +,, /, c, ( roduktio kopioi :n merkit :lle: NULLABL IRS +,, c, (, /, c, ( Muilla produktioilla ei ole vaikutusta. Mutta edelleen tarvitaan uusi kierros, jonka ainoa vaikutus on produktion mukaisesti kopioida :n merkit :lle. NULLABL IRS, c, ( +,, c, (, /, c, ( 7
Vielä yksi kierros on käytävä läpi, mutta sillä ei ole vaikutusta, joten IRS on valmis. Lasketaan vielä OLLOW. Alustuksessa :n kohdalle laitetaan. NULLABL IRS OLLOW, c, ( +,, c, (, /, c, ( ässä hankaluuksia tekee se, että jokainen produktio tulee joka kierroksella tarkastella niin monta kertaa kuin sen nuolen oikealla puolella on välikesymboleita. simerkiksi produktio tulee käsitellä kahdesti. nsimmäisellä kerralla lisätään :n kohdalle sekä IRS( ) että :n kohdalla olevat (sillä on NULLABL), toisella kerralla :n kohdalle :n kohdalla olevat. NULLABL IRS OLLOW, c, ( +,, c, ( +,,, /, c, ( roduktiota ε ei voi käsitellä. Sen sijaan + käsitellään kahdesti. nsiksi :n kohdalle lisätään sekä IRS( ) että (koska on NULLABL) :n merkit, ja toiseksi :n kohdalle kopioidaan :n kohdalla olevat merkit. Sama koskee produktiota. Nämä eivät kuitenkaan lopulta lisää taulukkoon mitään uutta. NULLABL IRS OLLOW, c, ( +,, c, ( +,,, /, c, ( Seuraavaksi tuo :n paikalle sekä IRS( ):n että (koska on NULLABL) :n kohdalla olevat merkit ja :n paikalle :n paikalla olevat 8
merkit. NULLABL IRS OLLOW, c, ( +,, c, ( +,,, / +,,, c, (, /, +,, Sitten käsitellään produktiot + ja, jotka molemmat tekevät saman asian eli (koska on NULLABL) kopioivat :n merkit :lle. ämä ei kuitenkaan muuta taulukkoa. NULLABL IRS OLLOW, c, ( +,, c, ( +,,, / +,,, c, (, /, +,, roduktio kopioi :n merkit :n paikalle. NULLABL IRS OLLOW, c, ( +,, c, ( +,,, / +,,, c, (, /, +,,, /, +,, Vielä tarkastellaan produktiota c, joka ei aiheuta muutoksia, ja produktiota (), joka lisää yhden merkin :n paikalle: NULLABL IRS OLLOW, c, ( ), +,, c, ( +,,, / +,,, c, (, /, +,,, /, +,, Koska taulukko muuttui, pitää kierros ottaa uudestaan. roduktio 9
kopioi :n merkit sekä :n että :n kohdalle: NULLABL IRS OLLOW, c, ( ), +, ),, c, ( +,, ),, / +,,, c, (, /, +,,, /, +,, roduktio kopioi :n merkit sekä :n että :n kohdalle: NULLABL IRS OLLOW, c, ( ), +, ),, c, ( +,, ),, / +,, ),, c, (, /, +,, ),, /, +,, roduktio kopioi :n merkit :lle. NULLABL IRS OLLOW, c, ( ), +, ),, c, ( +,, ),, / +,, ),, c, (, /, +,, ),, /, +,, ), Vielä yksi kierros tarvitaan, mutta se ei muuta tilannetta. Nyt voidaan laatia ennustava jäsennystaulukko: c + / ( ) + ε ε ε ε / ε ε c () 4 Vasen tekijöinti Yleisesti: A αβ 1 αβ n γ 1 γ m 10
voidaan kirjoittaa A αa γ 1 γ m A β 1 β n simerkiksi: S if then S S if then S else S voidaan kirjoittaa S if then S L L ε L else S 11