Jäsennysalgoritmeja. TIE448 Kääntäjätekniikka, syksy Antti-Juhani Kaijanaho. 29. syyskuuta 2009 TIETOTEKNIIKAN LAITOS. Jäsennysalgoritmeja

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

TIEA241 Automaatit ja kieliopit, kevät 2011 (IV) Antti-Juhani Kaijanaho. 29. huhtikuuta 2011

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

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

TIEA241 Automaatit ja kieliopit, kevät Antti-Juhani Kaijanaho. 12. kesäkuuta 2013

TIE448 Kääntäjätekniikka, syksy Antti-Juhani Kaijanaho. 29. syyskuuta 2009

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

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

LR-jäsennys. Antti-Juhani Kaijanaho. 3. lokakuuta 2016

TIEA241 Automaatit ja kieliopit, kevät Antti-Juhani Kaijanaho. 16. helmikuuta 2012

TIE448 Kääntäjätekniikka, syksy Antti-Juhani Kaijanaho. 9. marraskuuta 2009

TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 3. lokakuuta 2016

Attribuuttikieliopit

Jäsennys. TIEA341 Funktio ohjelmointi 1 Syksy 2005

Täydentäviä muistiinpanoja jäsennysalgoritmeista

TIE448 Kääntäjätekniikka, syksy Antti-Juhani Kaijanaho. 17. marraskuuta 2009

follow(a) first(α j ) x

Eloisuusanalyysi. TIE448 Kääntäjätekniikka, syksy Antti-Juhani Kaijanaho. 16. marraskuuta 2009 TIETOTEKNIIKAN LAITOS. Eloisuusanalyysi.

Kontekstittomien kielten jäsentäminen Täydentäviä muistiinpanoja TIEA241 Automaatit ja kieliopit, syksy 2016

Pinoautomaatit. TIEA241 Automaatit ja kieliopit, kesä Antti-Juhani Kaijanaho. 6. kesäkuuta 2013 TIETOTEKNIIKAN LAITOS. Pinoautomaatit.

TIE448 Kääntäjätekniikka, syksy Antti-Juhani Kaijanaho. 27. lokakuuta 2009

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

Syntaksi. TIE448 Kääntäjätekniikka, syksy Antti-Juhani Kaijanaho. 22. syyskuuta 2009 TIETOTEKNIIKAN LAITOS. Syntaksi. Aluksi.

ICS-C2000 Tietojenkäsittelyteoria Kevät 2016

ICS-C2000 Tietojenkäsittelyteoria

TIEA241 Automaatit ja kieliopit, kevät Antti-Juhani Kaijanaho. 2. helmikuuta 2012

TIE448 Kääntäjätekniikka, syksy Antti-Juhani Kaijanaho. 13. lokakuuta 2009

Täydentäviä muistiinpanoja Turingin koneiden vaihtoehdoista

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

Muita rekisteriallokaatiomenetelmiä

Pinoautomaatit. Pois kontekstittomuudesta

Yhteydettömät kieliopit [Sipser luku 2.1]

Täydentäviä muistiinpanoja kontekstittomien kielioppien jäsentämisestä

TIE448 Kääntäjätekniikka, syksy Antti-Juhani Kaijanaho. 26. lokakuuta 2009

TIEA341 Funktio-ohjelmointi 1, kevät 2008

TIEA241 Automaatit ja kieliopit, kevät Antti-Juhani Kaijanaho. 12. tammikuuta 2012

S BAB ABA A aas bba B bbs c

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

Laskennan mallit (syksy 2010) Harjoitus 8, ratkaisuja

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

Yhteydettömän kieliopin jäsennysongelma

TIEA241 Automaatit ja kieliopit, kevät Antti-Juhani Kaijanaho. 26. tammikuuta 2012

Tehtävän V.1 ratkaisuehdotus Tietorakenteet, syksy 2003

Laskennan rajoja. Sisällys. Meta. Palataan torstaihin. Ratkeavuus. Meta. Universaalikoneet. Palataan torstaihin. Ratkeavuus.

Ohjelmoinnin perusteet Y Python

Säännölliset kielet. Sisällys. Säännölliset kielet. Säännölliset operaattorit. Säännölliset kielet

TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 3. joulukuuta 2015

TIE448 Kääntäjätekniikka, syksy Antti-Juhani Kaijanaho. 7. joulukuuta 2009

TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 12. lokakuuta 2016

Esimerkki: Laskin (alkua) TIEA341 Funktio ohjelmointi 1 Syksy 2005

vaihtoehtoja TIEA241 Automaatit ja kieliopit, syksy 2016 Antti-Juhani Kaijanaho 13. lokakuuta 2016 TIETOTEKNIIKAN LAITOS

Jäsennysaiheesta lisää Täydentäviä muistiinpanoja TIEA241 Automaatit ja kieliopit, syksy 2016

Esimerkki 47. Kieli {a i b j c k : i = j tai j = k} on luonnostaan moniselitteinen.

Poikkeustenkäsittely

Silmukkaoptimoinnista

arvostelija JavaCC Petri Kärki Helsinki 15. huhtikuuta 2005 Seminaarityö HELSINGIN YLIOPISTO Tietojenkäsittelytieteen laitos

2. Yhteydettömät kielet

5.5 Jäsenninkombinaattoreista

Ohjelmoinnin perusteet, syksy 2006

Algoritmit 2. Demot Timo Männikkö

Laskennan rajoja. TIEA241 Automaatit ja kieliopit, kesä Antti-Juhani Kaijanaho. 20. kesäkuuta 2013 TIETOTEKNIIKAN LAITOS.

JOHDATUS TEKOÄLYYN TEEMU ROOS

TIEA241 Automaatit ja kieliopit, kesä Antti-Juhani Kaijanaho. 22. toukokuuta 2013

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

Hakupuut. tässä luvussa tarkastelemme puita tiedon tallennusrakenteina

Algoritmit 1. Demot Timo Männikkö

Ohjelmoinnin perusteet Y Python

TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 9. lokakuuta 2016

Algoritmit 1. Demot Timo Männikkö

TIEA241 Automaatit ja kieliopit, kevät 2011 (IV) Antti-Juhani Kaijanaho. 19. tammikuuta 2012

Pinoautomaatit. TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 6. lokakuuta 2016 TIETOTEKNIIKAN LAITOS

TIEA241 Automaatit ja kieliopit, kesä Antti-Juhani Kaijanaho. 29. toukokuuta 2013

Rajoittamattomat kieliopit

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

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

Ydin-Haskell Tiivismoniste

Turingin koneet. Sisällys. Aluksi. Turingin koneet. Turingin teesi. Aluksi. Turingin koneet. Turingin teesi

Laskennan rajoja. TIEA241 Automaatit ja kieliopit, kevät Antti-Juhani Kaijanaho. 6. maaliskuuta 2012 TIETOTEKNIIKAN LAITOS.

Esimerkki 1: Kahviautomaatti.

TIEA241 Automaatit ja kieliopit, kevät 2011 (IV) Antti-Juhani Kaijanaho. 31. maaliskuuta 2011

Laskennan rajoja. TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 10. joulukuuta 2015 TIETOTEKNIIKAN LAITOS.

TIEA341 Funktio-ohjelmointi 1, kevät 2008

5/20: Algoritmirakenteita III

ICS-C2000 Tietojenkäsittelyteoria. Tähän mennessä: säännölliset kielet. Säännöllisten kielten pumppauslemma M :=

Ohjelmointi 2 / 2008 Välikoe / Pöytätestaa seuraava ohjelma.

ICS-C2000 Tietojenkäsittelyteoria

TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 8. syyskuuta 2016

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

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

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

TIEA241 Automaatit ja kieliopit, kevät Antti-Juhani Kaijanaho. 8. maaliskuuta 2012

TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 9. lokakuuta 2016

17/20: Keittokirja IV

ITKP102 Ohjelmointi 1 (6 op)

5. HelloWorld-ohjelma 5.1

Ohjelmoinnin perusteet Y Python

14. Poikkeukset 14.1

TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 19. syyskuuta 2016

Tietotekniikan valintakoe

Algebralliset tietotyypit ym. TIEA341 Funktio ohjelmointi 1 Syksy 2005

Transkriptio:

TIE448 Kääntäjätekniikka, syksy 2009 Antti-Juhani Kaijanaho TIETOTEKNIIKAN LAITOS 29. syyskuuta 2009

Sisällys

Sisällys

Seuraava deadline Vaihe B tiistai 6.10. klo 10 selaaja ja jäsentäjä toimivat

Kääntäjän rakenne lähdeohjelma SELAAJA sanasjono JÄSENTÄJÄ VÄLIKOODIN GENEROIJA rakennepuu välikoodi KOHDEKOODIN GENEROIJA kohdeohjelma TARKASTAJA SOKERINPILKKOJA OPTIMOIJA OPTIMOIJA

Jäsentäjän tehtävät selaajan tuottaman sanasjonon muuttaminen ohjelman loogista rakennetta kuvaavaksi tietorakenteeksi ohjelmassa olevien kielioppivirheiden tunnistaminen ja diagnosointi tällä luennolla oletetaan annetuksi jäsennettävä kielioppi

Sisällys

engl. recursive descent parsing Tehdään kustakin välikesymbolista aliohjelma, joka kokeilee kutakin produktiota vuorollaan. Päätesymbolin kohdalla yritetään ottaa se selaimelta. 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.

/* <statement> ::= if ( <expression> ) <statement> if ( <expression> ) <statement> else <statement> return ; return <expression> ; */ Statement parsestatement(lexer l) throws ParserException { Lexer.State st = l.savestate(); try { l.get(lexer.if); l.get(lexer.oparen); Expression tst = parseexpression(l); l.get(lexer.cparen); Statement thn = parsestatement(l); Statement els = null; if (l.peek() == Lexer.ELSE) { l.get(); els = parsestatement(l); } return new IfStatement(tst, thn, els); } catch (ParserException e) {} l.restorestate(st); try { l.get(lexer.return); Expression e = null; Lexer.State st1 = l.savestate(); try { e = parseexception(l); } catch (ParserException e) { l.restorestate(st1); } l.get(lexer.semicolon); return new ReturnStatement(e); } catch (ParserException e) {} l.restorestate(st); throw ParserException("failed to parse a statement"); }

Pro ja contra + Erittäin helppo koodata käsin kieliopista lähtien. Jos kielioppi on vasenrekursiivinen, algoritmi kaatuu. Algoritmi tekee älyttömästi turhaa työtä kokeillessaan kaikkia vaihtoehtoja.

Vasemman rekursion poisto X α 1 X X Xγ 1...... X α m X X Xγ n = X γ 1 X X α 1...... X γ m X X α m X γ i ja α i eivät ala X:llä

A x A (E) F A F F A F F / A E F E E + F E E F = A x A (E) F AF F F AF F / AF E FE E E + FE E FE

Sama koodina Expression parseexpression(lexer l) throws ParserException { Expression e = parseterm(l); return parseexpressionprime(l, e); } Expression parseexpressionprime(lexer l, Expression e1) throws ParserException { Lexer.State st = l.savestate(); try { l.get(lexer.plus); Expression e2 = parseterm(l); return parseexpressionprime(l, new AdditionExpression(e1,e2)); } catch (ParserException e) {} l.restorestate(st); try { l.get(lexer.minus); Expression e2 = parseterm(l); return parseexpressionprime(l, new AdditionExpression(e1,e2)); } catch (ParserException e) {} l.restorestate(st); return e1; }

Poistetaan häntäkutsuja Expression parseexpression(lexer l) throws ParserException { Expression e1 = parseterm(l); while (true) { Lexer.State st = l.savestate(); try { l.get(lexer.plus); Expression e2 = parseterm(l); e1 = parseexpressionprime(l, new AdditionExpression(e1,e2)); continue; } catch (ParserException e) {} l.restorestate(st); try { l.get(lexer.minus); Expression e2 = parseterm(l); e2 = parseexpressionprime(l, new AdditionExpression(e1,e2)); continue; } catch (ParserException e) {} l.restorestate(st); return e1; } }

Ennustava jäsennys Usein on mahdollista päättää heti, onko jokin produktio mahdollinen. Esim. E + TE ei tule kyseeseen, jos seuraava token ei ole +. Tällöin kokeile-ja-peruuta on täysin älytön idea. Ideaalitilanne on, jossa peruutusta ei tarvita lainkaan. Tällöin kyse on ennustavasta jäsennyksestä (engl. predictive parsing.

Expression parseexpression(lexer l) throws ParserException { Expression e1 = parseterm(l); while (true) { switch (l.peek()) { case Lexer.PLUS: l.get(); Expression e2 = parseterm(l); e1 = parseexpressionprime(l, new AdditionExpression(e1,e2)); continue; case Lexer.MINUS: l.get(); Expression e2 = parseterm(l); e2 = parseexpressionprime(l, new AdditionExpression(e1,e2)); continue; default: return e1; } } }

Milloin tietty produktio voidaan ennustaa? NULLABLE(X) on tosi, jos X:stä voidaan johtaa tyhjä merkkijono. NULLABLE(X) = tosi NULLABLE(X) = NULLABLE(Y i ) jos on produktio X jos on produktio X Y 1 Y i Y n ja jos NULLABLE(Y 1 ) NULLABLE(Y i 1 ) FIRST(γ) on kaikkien niiden päätesymbolien (ynnä syötteen loppu) joukko, jotka voivat aloittaa γ:n. FIRST(a) = {a} FIRST(X) = FIRST(X) FIRST(Y i ) jos a on päätesymboli jos on produktio X Y 1 Y i Y n ja jos NULLABLE(Y 1 ) NULLABLE(Y i 1 ) FOLLOW(X) on kaikkien niiden päätesymbolien (ynnä syötteen loppu) joukko, jotka voivat seurata Xää. FOLLOW(Y i ) = FOLLOW(Y i ) FIRST(Y j ) jos on produktio X Y 1 Y i Y j Y n ja NULLABLE(Y i+1 ) NULLABLE(Y j 1 ) FOLLOW(Y i ) = FOLLOW(Y i ) FOLLOW(X) jos on produktio X Y 1 Y i Y n ja jos NULLABLE(Y i+1 ) NULLABLE(Y n)

Esimerkki E TE E T x E + TE T (E) E TE NULLABLE FIRST FOLLOW E ei x, ( ), eof E kyllä +, ), eof T ei x, ( +,, ), eof

Ennustava jäsennystaulukko rivi jokaiselle välikesymbolille sarake jokaiselle päätesymbolille (ynnä syötteen loppu) Merkitse produktio X γ riville X ja sarakkeeseen t jokaiselle t FIRST(γ), ja jos NULLABLE(γ), myös jokaiselle t FOLLOW(X).

Esimerkki E TE E T x E + TE T (E) E TE NULLABLE FIRST FOLLOW E ei x, ( ), eof E kyllä +, ), eof T ei x, ( +,, ), eof x + ( ) eof E E TE E TE E E +TE E TE E E T T x T (E)

Taulukon tulkinta Tee jokaiselle välikesymbolille aliohjelma. Aliohjelman alussa tee switch case kaikille päätesymboleille (ynnä syötteen päättymiselle). Jos välikesymbolin X ja päätesymbolin t risteyskohta sisältää yhden produktion, niin koodaa ko. produktio X:n aliohjelmaan t:n caseen. sisältää useamman kuin yhden produktion 1, koodaa produktiot X:n aliohjelmaan t:n caseen ja käytä peruutusta valinnan tekemiseen produktioiden välissä. on tyhjä, niin koodaa X:n aliohjelmaan t:n caseen kielioppivirheen diagnosointi. Jos taulukossa ei ole yhtään konfliktia, jäsennin on ennustava. 1 Tällöin taulukossa on konflikti.

LL(1) left-to-right parse, leftmost derivation, 1-token lookahead. Jos kieliopista johdettu ennustava taulukko on konfliktiton, ko. kielioppi on LL(1). Jos kielioppi ei ole LL(1), kannattaa kokeilla vasemman rekursion poistoa ja vasenta tekijöintiä (engl. left factoring). Monet hyödylliset kieliopit eivät ole LL(1). Moniselitteinen kielioppi ei ole koskaan LL(1). On mahdollista yleistää LL(n):ään, jolloin FIRST ja FOLLOW sisältävät n:n mittaisia sanasjonoja. Tämä laajentaa jäsennettävien kielten joukkoa.

Ylhäältä alaspäin -jäsennys LL(1)-jäsennys etenee ylhäältä alaspäin, sillä se aloittaa välikesymbolista, ennustaa tarvittavan produktion, ja jäsentää ko. produktion mukaan, ja näin rakentaa jäsennyspuun juuresta lehtiin.

Ennustava jäsennys: pro ja contra + Helppo koodata kieliopin perusteella käsin. + Tehokas ei peruutusta. Vaadittu LL(1)-kielioppi on usein varsin vaikeaselkoinen. Kieliopin muuttaminen voi johtaa vaikeaselkoisiin virheisiin, kun FIRST- ja FOLLOW-joukkojen muuttumista ei muisteta ottaa kaikkialla huomioon. Tämän poistaa LL-generaattorin käyttäminen (esim. ANTLR). Käsin kirjoitetun prediktiivisen jäsentimen muokkaaminen voi johtaa epäselvyyteen siitä, mitä kieltä se oikeasti jäsentää. Tämänkin poistaa LL-generaattorin käyttäminen (esim. ANTLR).

Sisällys

LR(k)-jäsennys left-to-right parse, rightmost derivation, k-token lookahead jäsentimessä pino ja syöte (jota luetaan k:n sanasen ikkunassa) syötejono sisältää koko syöteen ja pino on tyhjä. kaksi toimintoa: shift: Siirrä seuraava syötesananen pinoon. reduce: Valitse produktio X Y 1 Y n, poista pinosta symbolit Y 1,..., Y n ja lisää pinoon välikesymboli X. Jos jäsennys onnistui, lopussa syötejono on tyhjä ja pinossa on vain yksi symboli (kieliopin aloitussymboli).

LR(k)-jäsennysautomaatti Kuhunkin tilaan liittyy toimintaohje kullekin symbolille (ynnä syötteen loppumiselle): shift n tee shift-operaatio ja siirry tilaan n reduce n tee reduce-operaatio produktiolle n goto n siirry tilaan n koskematta pinoon ja syötteeseen accept jäsennys on valmis error jäsennys epäonnistui Goto-toiminto on mahdollinen vain välikesymbolin kohdalla, muut vain päätesymbolin kohdalla Pinoon pistetään aina symbolin seuraksi nykyinen tila; automaatin tila on aina pinon päällimmäinen tila.

LR-itemit LR(0)-item koostuu produktiosta ja indeksistä sen oikeaan puoleen. Merkitään usein niin, että indeksin paikka kirjoitetaan produktion sisään pisteenä: E F +. E LR(1)- ja LALR(1)-item sisältää lisäksi lookahead-päätesymbolin. LR(k)-item sisältää lookahead-päätesymbolijonon

Konfliktit Jos LR-automaatissa on samassa solussa useampi toimintaohje, on kyseessä konflikti. Tällöin kielioppi ei ole LR. Shift/reduce-konflikti on tilanne, jossa samassa tilassa on sekä shift- että reduce-toimintaohje. Tyypillinen esimerkki on aiemmin esitelty if-else-moniselitteisyys. Yleensä korjattavissa kielioppia muokkaamalla. Usein shift-toiminnon valitseminen tuottaa halutun tuloksen. Reduce/reduce-konflikti on tilanne, jossa samassa tilassa on kaksi eri reduce-toimintaohjetta. Tällöin joko kieliopissa on bugi tai jäsennettävä kieli ei sovellut LR-jäsennykseen. Shift/shift-konfliktia ei esiinny.

Alhaalta ylöspäin -jäsennys LR(k) jäsentää alhaalta ylöspäin, sillä se rakentaa reduce-toiminto kerrallaan jäsennyspuuta lehdistä juureen.

LR:n eri lajit Ilmaisuvoimajärjestyksessä: LR(0) ei lookaheadia SLR lookahead FIRST- ja FOLLOW-joukkojen avulla LALR(1) eli lookahead-lr LR(1)-jäsentimestä tilatehokkaampi ja hieman heikompi versio LR(1) yhden merkin lookahead, automaatti on yleensä iso LR(k), missä k > 1, ja LR(1) ovat yhtä ilmaisuvoimaiset.

LR: pro ja contra + LR(1) käsittää useampia kieliä kuin LL(k). + LR-kieliopit ovat yleensä varsin helppolukuisia. LR-jäsentimen käsin koodaaminen on lähes mahdotonta. LR-konfliktien debuggaus on hankalaa ja vaatii kokemusta.

LARL-jäsenningeneraattorit Yacc, Bison, CUP, Happy jne. Jokaiseen symboliin liittyy semanttinen arvo. Reduce-toiminnon yhteydessä mahdollista suorittaa ohjelmoijan määräämää koodia, joka voi laskea vasemman puolen välikesymbolille semanttisen arvon käyttäen oikean puolen symbolien semanttisia arvoja hyväkseen.

Sisällys

Seuraava deadline Vaihe B tiistai 6.10. klo 10 selaaja ja jäsentäjä toimivat