TIEA241 Automaatit ja kieliopit, syksy 2015 Antti-Juhani Kaijanaho TIETOTEKNIIKAN LAITOS 26. marraskuuta 2015
Sisällys
Tunnistamis- ja jäsennysongelma Olkoon G = (N, Σ, P, S) kontekstiton kielioppi ja w Σ sen merkkijono. Tunnistamisongelmassa tehtävänä on selvittää, päteekö w L(G). Jäsennysongelma on tunnistamisongelman yleistys: tehtävänä on selvittää kaikki w:n jäsennyspuut. Jäsennysongelmalle on runsaasti laajassa käytössä olevia algoritmisia ratkaisuja. Useimmat eivät toimi kaikilla kieliopeilla. Tällä luennolla tarkastellaan a ja ennustavaa jäsennystä. Lisämateriaalissa lisäksi LR-jäsennys.
1 Määritelmä Olkoon G = (V, Σ, P, S) CFG. Se on operaattorikielioppi välikesymbolien E V (operaattorivälikesymbolit) suhteen, jos kaikki operaattorivälikesymbolien produktiot ovat jotain seuraavista muodoista: A B ( on prefiksioperattori) A B ( on postfiksioperaattori) A B C A BC ( on infiksioperaattori) (ε on infiksioperaattori) A ( on primäärilauseke) A B missä A, B, C E ja sekä alkaa että päättyy päätesymboliin. 1 Tämä määritelmä ei ole yleisesti käytössä.
Esimerkkejä operaattoreista Tavanomaisten operaattoreiden (+, jne) lisäksi: C:n typecast (tyyppi) on prefiksioperaattori. Funktiokutsu (arg1,...,argn) on postfiksioperaattori. Mixfix-operaattorit kuten C:n?lauseke: ovat tämän analyysin kannalta infiksioperaattoreita.
Presedenssi ja assosiatiivisuus Miten on lauseke a b c tulkittava? 2 Operaattorien välille on tapana määritellä osittaisjärjestys nimeltä presedenssi: Jos :llä on korkeampi presedenssi kuin :lla, niin tuo lauseke tulkitaan (a b) c. Jos :llä on korkeampi presedenssi kuin :lla, niin tuo lauseke tulkitaan a (b c). Lisäksi on kullekin operaattorille tapana määritellä ominaisuus nimeltä assosiatiivisuus: Jos kummallakaan ei ole toista korkeampi presedenssi mutta molemmat assosioivat vasemmalle, tuo lauseke tulkitaan (a b) c. Jos kummallakaan ei ole toista korkeampi presedenssi mutta molemmat assosioivat oikealle, tuo lauseke tulkitaan a (b c). Muissa tapauksissa tuo lauseke on kielioppivirhe. 2 Tässä tai tai molemmat voivat toki olla prefiksi- tai postfiksioperaattoreita, jolloin a, b ja c voivat olla tyhjiä.
C-kielen infiksioperaattoritaulukko 3 infiksioperaattorit (E on lausekkeiden välikesymboli) assosioivat * / % vasemmalle + - vasemmalle << >> vasemmalle < <= > >= vasemmalle ==!= vasemmalle & vasemmalle ^ vasemmalle vasemmalle && vasemmalle vasemmalle?e: vasemmalle = *= /= %= += -= <<= >>= &= ^= = oikealle, vasemmalle 3 Kullakin operaattorilla on korkeampi presedenssi kuin kaikilla sen alapuoleisilla riveillä olevilla operaattoreilla.
Yksiselitteisen operaattorikieliopin laatiminen I Lajitellaan operaattorit eri luokkiin siten, että samassa luokassa olevista operaattoreista millään ei ole suurempi presedenssi kuin muilla. 4 Järjestetään luokat jonoon siten, että luokka A tulee luokan B:n jälkeen, jos A:n operaattoreilla on suurempi presedenssi kuin B:n operaattoreilla. Lisätään jonon loppuun vielä yksi luokka primäärilausekkeita varten. Valitaan kullekin luokalle oma uniikki välikesymboli. 4 Oletetaan yksinkertaisuuden vuoksi, että kaikilla samaan luokkaan kuuluvilla operaattoreilla on sama assosiatiivisuus.
Yksiselitteisen operaattorikieliopin laatiminen II Kullekin operaattoreiden luokalle, jonka välikesymboli on A ja jota seuraavan luokan välikesymboli on B, tehdään seuraavat produktiot: A B A A B jokaiselle A-luokan vasemmalle assosioivalle infiksioperaattorille. A B A jokaiselle A-luokan oikealle assosioivalle infiksioperaattorille. A A jokaiselle A-luokan prefiksioperaattorille. A A jokaiselle A-luokan postfiksioperaattorille. Primäärilausekkeiden luokalle tehdään tarvittavat produktiot. Kaikki alkuperäisen kieliopin operaattorivälikesymbolien produktiot poistetaan ja kaikki viittaukset näihin symboleihin muutetaan viittamaan ensimmäisen luokan välikesymboliin.
Jay Earley: An Efficient Context-Free Parsing Algorithm. Communications of the ACM, 13 (2), pp. 94 102, 1970. Syötteenä CFG G ja merkkijono w, tulosteena tieto, päteekö w L(G). CFG:stä laaditun PDA:n muunnelma
Asetelmat Algoritmi pitää kirjaa kolmesta asiasta: produktio, jota ollaan soveltamassa kuinka pitkälle produktion oikealla puolella ollaan päästy mistä kohtaa syötemerkkijonoa produktion käsittely alkoi Tällaisia kirjauksia kutsutaan asetelmiksi (engl. item) Asetelma, jossa sovelletaan produktiota A α 1... α n, jossa on jo käsitelty k ensimmäistä oikean puolen merkkiä ja jonka produktion käsittely alkoi syötemerkistä numero l, esitetään muodossa 5 A α 1... α k α k+1... α n, l 5 Huomaa piste!
Lähtökohdat Algoritmi olettaa: kieliopin alkusymbolilla on täsmälleen yksi produktio alkusymboli ei esiinny minkään produktion oikealla puolella Merkitään syötemerkkijonoa w = c 0... c n 1. Tarvitaan apujoukkoja yksi enemmän kuin syötemerkkijonossa on merkkejä. Merkitään niitä S 0,..., S n. Kukin apujoukko sisältää asetelmia.
Earleyn tunnistin 1. Alustetaan: 6 S 0 = {(S ω S, 0)} i {1,..., n} : S i = 2. Kaikilla i = 0,..., n (tässä järjestyksessä) ja jokaisella s S i tehdään yksi seuraavista: Ennustus Jos s on muotoa A ω Bω, f : Jokaiselle produktiolle B ω B P lisää S i :hin B ω B, i. Täydennys Jos s on muotoa A ω, f : Jokaiselle (B ω B Aω B, f ) S f lisää S i :hin B ω B A ω B, f. Selaus Jos s on muotoa A ω cω, f ja c = c i : Lisää S i+1 :een A ωc ω, f. 3. Palauta, päteekö (S ω S, 0) S n. 6 Olkoon S ω S kieliopin alkusymbolin ainoa produktio.
Esimerkki taululla E E + E E E c w = c + c c
Pro ja contra + Yleinen jäsennysalgoritmi, toimii kaikilla CFG:illä. Aika- ja tilavaativuus on (hyvin koodattuna) O(n 3 ), missä n on syötemerkkijonon pituus. Algoritmi ei ole aivan triviaali koodattava.
engl. recursive descent parsing Tehdään kustakin välikesymbolista aliohjelma, joka kokeilee kutakin produktiota vuorollaan. Päätesymbolin kohdalla katsotaan onko se seuraavana merkkijonossa. Välikesymbolin kohdalla kutsutaan sitä vastaavaa aliohjelmaa. Jos jäsennys ei onnistu, peruutetaan (backtrack) lähimpään tehtyyn valintaan, jossa ei ole vielä kaikki vaihtoehdot käyty läpi.
Välittömän vasemman rekursion poisto ei selviä vasenrekursiivisista produktioista: Esim. A Ab a kääntyisi aliohjelmaksi, joka ensi töikseen kutsuu itseään. Tuollainen produktio voidaan korvata kahdella uudella produktiolla A aa ja A ε ba, missä A on uusi välikesymboli. Yleisesti mikä tahansa produktiojoukko A Aα 1 Aα n β 1 β m voidaan kirjoittaa muotoon A β 1 A β m A A ε α 1 A α n A missä α i ja β i ovat välike- ja päätesymbolien jonoja, jotka eivät ala A:lla, ja A on uusi välikesymboli. Epäsuora vasen rekursio pitää poistaa toisella menetelmällä, joka sivuutetaan tässä.