FORDÍTÓPROGRAMOK I. Előadás Műszaki informatika szakos hallgatók számára Veszprémi Egyetem Számítástudomány Alkalmazása Tanszék 2002.
Ajánlott irodalom: Alfred V. Aho, Ravi Sethi, Jeffrey D. Ullman Compilers (Principles, Techniques, Rules) Addison Wesley, 1988 2
Fordítóprogram Forrásnyelv SOURCE LANGUAGE FORDÍTÓ Célnyelv TARGET LANGUAGE A fordító Hibaüzenet ERROR MESSAGE egy forrásnyelvről egy célnyelvre fordít közölve az esetleges hibákat Az informatikában gyakran programozási nyelvekre gondolunk Forrásnyelvű program ( pl.: C ) Cél nyelvű program ( pl.: assembly, gépikód ) 3
Azonban tetszőleges program be és kimenete is valamely nyelven meghatározott BEMENET PROGRAM KIMENET Egy program bemeneteit jól, lehetőleg formálisan definiálni kell. Egy program kimenetének értelmezhetőnek kell lennie egy másik program, vagy egy felhasználó számára. A program műveleteket adatokon végez A bemenetek és az adatszerkezetek, illetve az adatszerkezetek és a kimenet közti leképezést a fordító végzi. Tehát bárkinek, akinek nem csak egy modult, hanem teljes szoftvert kell készítenie, annak tudnia kell: a be- és kimenetet formálisan definiálni és a definiált nyelvhez fordítóprogramot készíteni. 4
A tárgy célja megmutatni: hogyan lehet nyelveket definiálni, hogyan lehet nyelveket algoritmikusan értelmezni, mely nyelveket lehet könnyen értelmezni. Példa: Egy matematikai megoldó bemenete: Aritmetikai kifejezés: 2+1*6 Szöveges feladat: A csiga egy métert tesz meg óránkén egy függőleges falon felfelé. Két méterről indulva, milyen magasan lesz hat óra múlva? Megjegyzés: A nyelvek lehetnek: Szövegesek (Pl.: XML) Grafikusak (Pl.: UML) Ebben a félévben szöveges nyelvekkel foglalkozunk, de a grafikus nyelveknek is van szöveges megfelelője. (Pl.: UML tárolása XML nyelven) 5
Fordítóprogram felépítése FORRÁSNYELV 1. LEXIKAI ELEMZO 2. SZINTAKTIKAI ELEMZO SZIMÓLUMTÁBLA KEZELO 3. SZEMANTIKAI ELEMZO 4. KÖZBÜLSO KÓD GENERÁLÓ HIBAKEZELO 5. KÓD OPTIMALIZÁLÓ 6. KÓD GENERÁLÓ CÉLNYELV Megjegyzés: Az 1-4 lépéseket vizsgáljuk szoftverfejlesztésben betöltött kiemelt szerepe alapján. 6
1. Lexikai Elemzés A forrásnyelvű szöveget elejétől a végéig karakterenként beolvassuk, és olyan szakaszokra bontjuk (ún.: tokenekre), melyekben szereplő karaktereknek együtt van értelme. Példa: position := initial + rate * 60 Tokenekre bontva: 1. position azonosító 2. := értékadás szimbólum 3. initial azonosító 4. + összeadás jel 5. rate azonosító 6. * szorzás jel 7. 60 szám Megjegyzés: Lexikai elemzés során, a tokenek közötti elválasztó karaktereket elhagyjuk. Természetes nyelvi analógia: a szöveget szavakra bontjuk. 7
2. Szintaktikai Elemzés Más néven hierarchikus elemzésnek vagy (parsing) parzolásnak nevezzük. Tokeneket szervez hierarchiába nyelvtani szabályok alapján. Példa: 1. Minden azonosító egy kifejezés 2. Minden szám is egy kifejezés 3. Ha exp1 és exp2 kifejezések, akkor exp1*exp2 is kifejezés 4. Ha id azonosító és exp egy kifejezés, akkor id := exp egy utasítás A szintaktikai elemzés eredménye a tokenek kapcsolatát leíró fa: szintaxis fa 8
Szintaxis fa: Utasítás ÁLLÍTÁS Azonosító := Kifejezés position Kifejezés + Kifejezés Azonosító Kifejezés * Kifejezés initial Azonosító Szám rate 60 Természetes nyelvi analógia: a nyelvtani mondatrészek 9
3. Szemantikai Elemzés Ellenőrzi, hogy a formailag helyes szövegrészeknek van e értelme. Tipikus feladat a típusegyeztetés 4. Közbülső kód generálás Olyan reprezentációját képezi a nyelvnek, amely könnyen felépíthető és belőle a kimenet könnyen generálható. Példa: egy dinamikusan tárolt fa := Id 1 + Id 2 * Id 3 NULL 60 Az 5. és 6. lépéseket nem tárgyaljuk 10
Szimbólumtábla kezelő Egy szöveg tartalmazhat azonosítókat Például: egy azonosító hivatkozhat: konstansra változóra függvényre Egy fordító alapvető feladata, hogy rögzítse a szövegben lévő azonosítókat, a hozzájuk tartozó adatokkal együtt. Például: mi egy azonosító: neve típusa érvényessége (a szövegen belül) hivatkozott információ helye a memóriában 11
Megjegyzés Ezen adatokat a szimbólumtábla tárolja A szemantikai elemzés során a szimbólumtáblából olvassuk az azonosítók típusát. Id 1 2 3 Név position initial rate Típus Hibakezelő A fordítás minden lépése okozhat hibákat Olyan fordító, amely megáll az első hibánál, kevésbé hasznos (minél több hibát írjon ki) 12
FORDÍTÓPROGRAMOK II. Előadás Műszaki informatika szakos hallgatók számára Veszprémi Egyetem Számítástudomány Alkalmazása Tanszék 2002. 13
Egyszerű egy lépésben fordító Bevezető gondolatok Egy nyelvet az határoz meg, hogy: hogyan néz ki : szintaxis mi a jelentése : szemantikája A szintaxis meghatározásához bevezetjük a széles körben használt környezetfüggetlen nyelvtanokat. Egy nyelv jelentésének meghatározásához nem formalizált információkat is használnunk kell. Például: nekünk kell eldöntenünk, hogy két szöveg ugyanazt jelenti-e. A környezetfüggetlen nyelvtanok segítenek a nyelv értelmezésében is. A nyelvtanorientált fordítási technikát szintaxis vezérelt ( syntax directed) fordításnak nevezzük. 14
Példaként felépítünk egy fordítót, ami infix formáról postfix formába alakít. infix: operátorok az operanduszok között Pl.: 9-5 + 2 postfix: operátorok az operanduszok után Pl.: 9 5-2 + Postfix kiértékelés berakjuk a verembe az operanduszokat ha egy operátor következik, akkor kivesszük a veremből az operanduszait, elvégezzük a műveletet és visszatesszük a verembe az eredményt. ha a postfix formában írt kifejezés végére értünk, akkor a veremben a végeredmény található. Pl.: 5-2 + 9 4 4 6 15
Első lépésként olyan fordítót építünk, mely + és - jelekkel elválasztott számjegyekből álló kifejezést fordít, majd ezt bővítjük tovább. Szintaxis vezérelt fordítás esetén a szintaktikai, szemantikai elemzés és a közbülső kód generálás egy lépésben történik. KARAKTER SOROZAT LEXIKAI ELEMZŐ TOKENEK SOROZAT SZINTAXIS VEZÉRELT ÉRTELMEZÉS KÖZBÜLSŐ REPREZENTÁCIÓ 16
Szintaxis meghatározása A környezetfüggetlen nyelvtan elemei: 1. A tokeneket tekintjük terminális szimbólumoknak (halmaz) 2. Nemterminális szimbólumok (halmaz) 3. Levezetési szabályaink (halmaz) Egy szabály: nemterminális terminálisok és nemterminálisok sorozata 4. Kiindulási szimbólum (ahonnan elkezdjük a levezetést) Példa: + és jelekből, illetve számjegyekből álló kifejezés: mint 9-5 + 2, 3-1, 7 1) List List + digit 2) List List digit 3) List digit 4) digit 0 1 2 9 17
Ha szabályokkal definiálunk egy nyelvtant, akkor a kezdő vagy kiindulási szimbólumra vonatkozó szabályokat írjuk le először. (Az előző példában List a kezdő szimbólum) A tokenek sorozata (string) nulla, vagy több tokent tartalmaz. Ha nullát, akkor üres sorozatnak nevezzük és e -vel jelöljük. Egy nyelvtanból tokenek sorozatához juthatunk: kezdőszimbólumból indulva a nemterminalisokat helyettesítve a nekik megfelelő szabályok jobb oldalain álló sorozatokkal míg csak terminálisokból, tehát tokenekből álló sorozathoz nem jutunk. 18
Példa a) A 3-mas szabály alapján 9 egy lista (list) mivel számjegy (digit) b) A 2-es szabály alapján 9 5 egy lista (list), mivel 9 egy lista és 5 egy számjegy c) Az 1-es szabály alapján 9 5 + 2 egy lista, mivel 9 5 egy lista és 2 egy számjegy Ezt a levezetést a következő fa szemlélteti, melynek minden csúcspontjában a nyelv egy szimbóluma szerepel. Az ilyen fát, levezetési fának (parse tree) nevezzük. list list - digit list list + digit list list digit list digit list digit digit 9 list digit digit 9-5 + 2 digit 2 19
Levezetési fák Egy adott kornyezetfuggetlen nyelvtan eseten a levezetesi fakra a kovetkezo tulajdonsagok teljesulnek: 1. A gyökér címkéje a kiindulási szimbólum 2. Egy levél címkéje egy token, vagy e 3. Közbülső csúcs címkéje egy nemterminális 4. Ha A egy közbülső csúcs címkéje, aminek n gyermeke van és X 1, X n a gyermekeinek cimkje: A X 1 X 2 X n egy levezetési szabály A e esetén az A címkéjű csúcsnak csak egy gyereke van Ha a leveleket balról jobbra összeolvassuk, megkapjuk a levezetett szót. Az az eljárás, mely során egy token sorozathoz meghatározzuk a levezetési fát az az elemzés vagy parzolás (parsing). 20
Egyértelműség Ha egy nyelvtan olyan, hogy valamely sorozat többféleképpen is levezethető, akkor a nyelvtan nem egyértelmű. Más szavakkal, egy nyelvtan nem egyértelmű, ha van olyan sorozat, melynek több levezetési fája is van. Példa: S S + S S S 0 1 2 9 S S S S S S S S S S 9-5 + 2 9-5 + 2 21
Nyelvtanok egyértelművé télele: Asszociativitás (9-5) + 2 ugyanaz-e mint 9 - (5 + 2) vagy 9-5 + 2? Mi a kiértékelés sorrendje? Ilyenkor kell plusz információ, amit beviszünk a nyelvtanba. Hagyományosan a + és a - műveletek illetve a * és / műveleteket balról jobbra végezzük, tehát bal asszociatívnak nevezzük őket, így a 9-5 + 2 azonos a (9-5) + 2 vel. Hagyományosan a programozási nyelvekben az értékadást jobbról balra hajtjuk végre, tehát jobb asszociatív. a = b = c azonos a = (b = c) Példa: left digit left + digit left digit right letter letter = right left right left letter = right left - digit + digit a letter = right digit 9 5 2 b letter c 22
Nyelvtanok egyértelművé télele: Operátorok kiértékelési sorrendje (precedencia) 9 + 5 * 2 lehetséges kiértékelési sorrendjei: (9 + 5) * 2 illetve 9 + (5 * 2) Mivel mind a + és mind a * balasszociatív, ez a kérdés a külön-külön kiértékelési sorrendjük alapján nem oldható fel. Több operátor esetén a relatív precedenciákat is meg kell határozni. A különböző precedencia szintekhez külön nemterminálisokat vezetünk be. Példa: expr expr + term expr term term term term * factor term / factor factor factor digit (expr) 23
Szintaxis vezérelt fordítás Példa: infix postfix átalakítás Egy E infix kifejezés postfix formára hozása Ha E egy változó vagy konstans, E postfix formája önmaga. Ha E egy E 1 op E 2 alakú kifejezés, ahol op egy tetszőleges operátor, akkor E postfix alakja E 1 E 2 op ahol E 1 és E 2 rendre E 1 és E 2 postfix alakja. Ha E egy (E 1 ) alakú kifejezés, akkor E postfix alakja E 1 postfix alakja. (tehát nincs szükség zárójelezésre) Példa: (9 5) + 2 postfix alakja 95 2 + 9 (5 + 2) postfix alakja 952 + - 24
Szintaxis vezérelt fordításhoz szintaxis vezérelt definíciókat használunk. Szintaxis vezérelt definíció esetén A bemenet szintaktikai szerkezetét egy környezetfüggetlen nyelvtan határozza meg. A szimbólumokhoz attribútumokat vagy tulajdonságokat rendelünk. A levezetési szabályokhoz szemantikai szabályokat rendelünk, amelyek megadják egy nyelvtani szabályban szereplő nemterminális szimbólumok attribútumának számítási módját. Szintetizált attribútumról beszélünk, ha értékét a kiértékelési fában hozzá tartozó csúcs gyermekeinek attribútumából számítjuk. 25
Példa: infix postfix átalakítás levezetési szabályok szemantikai szabályok konkatenáció expr expr 1 + term expr.t := expr 1.t term.t + expr expr 1 term expr.t := expr 1.t term.t -. attribútum. expr term expr.t := term.t term 0 term.t := 0 term 1 term.t := 1...... term 9 term.t := 9 26
Szintetizált attribútumok kiszámítása levezetési fa alapján: 9 5 + 2 expr.t := 95-2+ ez a kimenet expr.t := 95- term.t := 2' expr.t := 9 term.t := 5' term.t := 9-5 + 2 Végeredményül a győkér szintetizált attribútumában megkapjuk a postfix formát. 27
FORDÍTÓPROGRAMOK III. Előadás Műszaki informatika szakos hallgatók számára Veszprémi Egyetem Számítástudomány Alkalmazása Tanszék 2002. 28
Szintetizált attribútumok kiértékelése A levezetési fa minden olyan bejárása célravezető, ahol egy csúcs gyermekeit előbb értékeljük ki mint magát a csúcsot. Ennek egy könnyen megvalósítható módja a mélységi bejárás rekurzív eljárással, preorder bejárási sorrendben. procedure visit (n : node) begin for each child m of n, from left to right do visit ( m ); evaluate semantic rules at node n end end 29
Fordítási sémák A továbbiakban eljárásszerűen adjuk meg a fordítás módját. A fordítási séma egy olyan környezetfüggetlen nyelvtan, ahol a szabályok jobb oldalába programrészleteket, úgynevezett szemantikai akciókat (semantic action) ágyazunk. A fordítási séma abban különbözik a szintaxis vezérelt definíciótól, hogy a szemantikai szabályok kiértékelési sorrendje egyértelműen meghatározott. 30
A szemantikai akciókat a szabályon belül kapcsos zárójelbe tesszük. Pl.: expr expr + term { print( + ) } expr expr term { print( - ) } expr term term 0 { print( 0 ) } term 1 { print( 1 ) }...... term 9 { print( 9 ) } A szintaxis vezérelt definíció alkalmazásával ellentétben nincs mindig szükség átmeneti tárolásra. 31
Ha egy szabályban szemantikai akció szerepel, akkor a levezetési fában a szabály bal oldalán szereplő csúcshoz egy plusz gyermeket veszünk fel, szaggatott vonallal csatolva és a szemantikai akcióval címkézve. Pl.: 9 5 + 2 95 2 + expr expr term print ( + ) expr - term print ( - ) term 9 print ( 9 ) 5 print ( 5 ) 2 print ( 2 ) A bejárási sorrend kötött. 32
Levezetés (parzolás) Azt az eljárást, amely során megadjuk, hogy egy kifejezés (tokenek sorozata) hogyan vezethető le nyelvtani szabályokkal, elemzésnek vagy parzolásnak hívjuk. A elemzés egyben a levezetési fa felépítését is jelenti. Ezen eljárások többsége két csoportra osztható: top down: bottom up: gyökértő a levelek felé levelektől a gyökér felé A top down módszerek általában könnyebben végrehajthatók. A bottom up módszerek a nyelvek bővebb osztályának kezelésére alkalmasak. 33
Top Down elemzés Visszalépéses algoritmussal (back - tracking) 1. Tekintsük a token sorozat bal oldalán álló első tokent és a nyelvtan kiindulási szimbólumára vonatkozó szabályokat. 2. Vegyünk egy olyan levezetési szabályt, mely jobb oldalának bal oldalán ez a token áll. 3. A kiválasztott szabályok alapján próbáljuk levezetni a következő tokent a) a terminálisokat egyeztetjük b) a nem terminálisokból levezetjük (2. lépés rekurzív hívása) 34
Példa: Pascal hoz hasonló típusokat megadó nyelvtan type simple id array [ simple ] of type simple integer char num dotdot num array [ num dotdot num ] of integer elemzése 35
LÉPÉS ELEMZÉS BEMENET 1, type array [ num dotdot num] of integer type 2. array [ simple ] of integer array [ num dotdot num] of integer type 3. array [ simple ] of integer array [ num dotdot num] of integer type 3.1 array [ num dotdot num] of integer array [ simple ] of integer 36
LÉPÉS LEVEZETÉS BEMENET 3.2 rekurzió: 2. lépés type array [ simple ] of type array [ num dotdot num] of integer num dotdot num type 3.1 array [ num dotdot num] of integer array [ simple ] of type num dotdot num 37
LÉPÉS LEVEZETÉS BEMENET visszalépés a rekurzióban type 3.1 array [ num dotdot num] of integer array [ simple ] of type num dotdot num type 3.2 array [ num dotdot num] of integer array [ simple ] of type num dotdot num 38
LÉPÉS LEVEZETÉS BEMENET rekurzió 2. lépés type array [ simple ] of type array [ num dotdot num] of integer num dotdot num simple type array [ simple ] of type 3.2 array [ num dotdot num] of integer num dotdot num simple integer 39
Ha a 3.1 vagy 3.2 nem sikerül, akkor visszatérünk a 2. lépéshez és újabb szabályt választunk, ha ilyen nincs, akkor visszalépünk a rekurzióban. Azt a speciális esetet, amikor nincs szükség visszalépésre, előrejelző elemzésnek (predictive parsing) hívjuk. 40
Előrejelző levezetés (predictiv parsing) rekurzív eljárások egy halmaza dolgozza fel a nyelvtan minden nemterminálisához egy-egy rekurzív eljárás tartozik Előrejelző levezetés esetén a következő illesztendő token (look ahead) alapján egyértelműen eldönthető, hogy mely szabályt kell alkalmazni, illetve mely eljárást kell meghívni. procedure match (t : token) begin if lookahead = t then lookahead := next token else error end 41
procedure type begin if lookahead is in { integer, char, num } then simple else if lookahead = then begin match ( ); match ( id ) end else if lookahead = array then begin match ( array ) match ( [ ) simple match ( ] ) match ( of ); type end else error end 42
procedure simple begin if lookahead = integer then match ( integer ) else if lookahead = char then match ( char ) end else if lookahead = num then begin match ( num ) match ( dotdot ) match ( num ) end else error end 43
Az előrejelző elemzés csak akkor műkodik, ha egyértelműen eldönthető, hogy a következő token mely szabály jobb oldalából vezethető le, másképp, mi lehet az első token ami egy szabály alkalmazása során generálódik. Egy α sorozatból levezethető első tokenek halmazát FIRST(α) jelöli. Pl.: type ból levezethető szabályokról kell döntenünk type simple id array [simple] of type First ( simple ) = { integer, char, num } First ( id ) = { } First ( array ) = { array} Visszalépés nélküli elemzés lehetséges, ha minden A nemterminalis és bármely két A α és A β szabály esetén FIRST(α) FIRST(β) = (diszjunkt) 44
e szabályok kezelése A nemterminális e szabályokat akkor alkalmazzuk, ha a nemterminálisra a többi szabály nem alkalmazható (nem kell hibát jelezni, error helyett ezt alkalmazzuk) A First halmazok meghatározása Abban az esetben, ha a nyelvtan nem tartalmaz nemterminális e alakú szabályokat, akkor egy A nemterminálishoz tartozó First(A) halmaz tartalma a az A bal oldalú szabályok jobb oldalának első helyén álló terminálisok halmaza, és az A bal oldalú szabályok jobb oldalának első helyén álló nemterminálisok FIRST halmazámak uniója. Példa: A B A C A a A b FIRST(A) = {a,b} FIRST(B) FIRST(C) 45
Bal rekurzió mentesítés A Aα β A βr R αr c átalakítható: (R egy új nemterminális) ez azért fontos, mert: Bal rekurzív nyelvtanok esetén a Top - Down elemzés végtelen ciklusba eshet, mert úgy alkalmazunk szabályokat, hogy az elemzendő sorozat nem fogy. Az elemző levezető algoritmus végességét garantálja, ha a véges bemenetről a terminálisok fogynak egy szabály alkalmazásával. 46
FORDÍTÓPROGRAMOK IV. Előadás Műszaki informatika szakos hallgatók számára Veszprémi Egyetem Számítástudomány Alkalmazása Tanszék 2002. 47
Példa: Fordítási séma római arab N A 1 B 0 C 0 D 0 B 1 C 0 D 0 C 1 D 0 D 1 A 1 M { print ( 1 ) } C 1 X { print ( 1 ) } A 1 MM { print ( 2 ) } C 1 XX { print ( 2 ) } A 1 MMM { print ( 3 ) } B 1 C { print ( 1 ) } C 1 XC { print ( 9 ) } B 1 CC { print ( 2 ) } C 0 C 1 C 0 e { print ( 0 ) } B 1 CM { print ( 9 ) } B 0 B 1 B 0 e { print ( 0 ) } D 1 I { print ( 1 ) } D 1 I { print ( 2 ) } D 1 IX { print ( 9 ) } B 0 B 1 D 0 e { print ( 0 ) } 48
Példa: Fordítási séma arab római N A 1 B 0 C 0 D 0 B 1 C 0 D 0 C 1 D 0 D 1 A 1 1 { print ( M ) } C 1 1 { print ( X ) } A 1 2 { print ( MM ) } C 1 2 { print ( XX ) } A 1 3 { print ( MMM ) } B 1 1 { print ( C ) } C 1 9 { print ( XC ) } B 1 2 { print ( CC ) } C 0 C 1 C 0 0 B 1 9 { print ( CM ) } D 1 1 { print ( I ) } B 0 B 1 D 1 2 { print ( II ) } B 0 0 D 1 9 { print ( IX ) } D 0 D 1 D 0 0 49
Példa: szintaxis vezérelt definíció (arab számok) expr term1 expr.t = term1.t expr expr 1 term0 expr.t = expr 1.t * 10 + term0.t term1 1 term1.t = 1 2 = 2... 9 = 9 term0 term1 term0.t = term1.t term0 0 term0.t = 0 levezetés 360-ra: expr = 36 * 10 + 0 = 360 expr.t=3*10+6 term0.t = 0 expr.t = 3 term1.t = 3 term0.t = 6 term1.t = 6 0 3 6 50
Emlékezető A lexikai elemző feladata karakterek sorozatából tokenek sorozatát létrehozni. A szintaktikai elemző tőle kéri a tokeneket FORRÁS SZÖVEG LEXIKAI ELEMZŐ TOKEN ÚJABB TOKEN SZINTAKTIKAI ELEMZŐ SZIMBÓLUM TÁBLA A lexikai elemző tokeneket minták alapján azonosít. 51
Alapfogalmak Token: szintaktikai és szemantikai szempontból azonosan kezelt fogalom, amit a nyelvtanban egy szimbólum jelöl. Egy tokenhez tartozó mintázat: olyan karaktersorozatok, amik egyazon tokent eredményeznek. Lexéma: egy minta konkrét előfordulása a szövegben Például: TOKEN MINTÁZAT LEXÉMA OPERÁTOR + - 3 + 2 Ha egy tokenhez több minta is tartozik, akkor a tokenhez attribútumokat rendelünk. 52
Például: E = M (adott kifejezés) token attribútumai EZEK ÉPÍTIK FEL A KIFEJEZÉST <id, mutató egy szimbólumtábla bejegyzésre> <assign_op, > <id, mutató egy szimbólumtábla bejegyzésre > Minták Formális definíciója: Pl.: reguláris kifejezésekkel Felismerése Pl.: véges autómatával 53
Előfeldolgozás Ismeretlen karaktersorozatról az feltételezzük, hogy új azonosító. Ha a feldolgozás további része ezen feltételezés alapján nem lehetséges, akkor visszalépünk és próbáljuk a hibát megkeresni. Egy karaktert törlünk Egy karaktert beszúrunk Két szomszédos karaktert felcserélünk Egy karaktert kicserélünk Alapelv: Azt a megoldást keressük, ami a legkevesebb módosítással vezet értelmezhető sorozathoz. Ekkor ezen módosítások száma a hibák száma 54
Pufferelés (Buffering) Ha több karakternyi előre és visszalépésre van szükség, akkor annak érdekében, hogy a karaktereket ne kelljen odavissza mozgatni, puffereljük és indexeljük őket. KARAKTEREK LEXÉMA ELEJE ÉPPEN VIZSGÁLT KARAKTER 55
Minták megadása Alapfogalmak ábécé: szimbólumok (karakterek) véges halmaza Karaktersorozat, vagy sztring (szó): szimbólumok véges sorozata az ábécéből Konkatenáció: két szó W 1 és W 2 konkatenáltja W=W 1 W 2 a két szó egymás után írva mint sorozat Van olyan szó, ami egyetlen karaktert sem tartalmaz, ez az üres szó, amit e vel jelölünk. A nyelv szavak, vagy karaktersorozatok halmaza 56
Műveletek nyelveken Unió: w L=L 1 L 2 pontosan akkor, ha w L 1 vagy w L 2 Konkatenáció: Kleene lezárt: w L 1 L 2 pontosan akkor, ha w =w 1 w 2 ahol w 1 L 1 és w 2 L 2 w L = L 1 * pontosan akkor, ha w = w 1 w 2 w 3 w n, ahol w i L i és n N ( n = 0 értelmezése: e L 1 *) 57
Reguláris kifejezés Egy ábécé minden eleme és e reguláris kifejezés. A kifejezés által definiált nyelvek: L(δ) = {δ} bármely δ {e} Ha r és s reguláris kifejezés, akkor r s reguláris kifejezés és L(r s) = L(r) L(s) r s reguláris kifejezés és L(r s) = L(r)L(s) r* reguláris kifejezés és L(r*) = L(r)* L((r)) = L(r) (extra zárójelezés megengedett) 58
Reguláris definíció: azon 1 reguláris kifejezés az ábécé felett azon 2... azon k reguláris kifejezés az ábécé elemei és azon 1, azon 2, azon k-1 azonosítók felett. További jelölések: Előfordulások számára (r)? L(r) {e} (r)+ L(r)L(r)* Karakter osztályok [abc] L([abc]) = {a} {b} {c} ( [abc] = a b c ) [A-Z] L([A-Z]) = {A} {B} {C} {Z} ( [A-Z] = A B C Z ) 59
FORDÍTÓPROGRAMOK V. Előadás Műszaki informatika szakos hallgatók számára Veszprémi Egyetem Számítástudomány Alkalmazása Tanszék 2002. 60
Szintaktikai elemző A szintaktikai elemző helye a fordítás folyamatában TOKENEK FORRÀS SZÖVEG LEXIKAI ELEMZÕ TOKEN KERESÈS SZINTAKTIKAI ELEMZÕ LEVEZETÈSI FA Nyelvek Church tétel: általános nyelvtan által adott nyelvek és a Turing gép által elfogadott nyelvek ekvivalenciája. Cocke-Younger-Kamasi algoritmus általános nyelvtanok alapján képes nyelveket levezetni Minél szűkebb a nyelvi osztály annál hatékonyabb levezető algoritmusok tartoznak hozzá 61
Hibakezelés Alapvelvek: A hiba mibenlétét tisztán és pontosan meg kell tudnunk fogalmazni Gyorsan vissza kell tudni állítani a hibákat, hogy további hibákat detektálhassunk A hiba kezelő ( és detektáló ) nem lassíthatja le túlságosan a hibátlan nyelvek fordítását Hiba visszaállítási stratégiák ( error recovery ) pánikszerű (panic mode) egy blokkot hagy figyelmen kívül pl.: egy sort, egy begin-end pár közötti részt a hiba környezetében kifejezés szintű visszaállítás ( phrase level ) lokális javítások, ahol a levezető elakad pl.: vessző, pontosvessző csere, pontosvessző hozzáadása, pontosvessző figyelmen kívül hagyása 62
hiba előrevetítés ( error production ) tipikus hibák ismeretében olyan nyelvtan készítése, ami hibás kifejezéseket is eredményez, és ilyet levezetve pontos hibaüzenetet ad globális javítás ( global correction ) teljes szöveg legkevesebb javításával azt értelmessé tenni. Nagyon hasznos, de borzasztó költséges. CFG ( ismétlés ) levezetés levezetési fa egyértelműség nyelvek maghatározása Kérdés: reguláris kifejezésből, hogy kapok CFG-t? Válasz: reguláris kifej. NFA CFG ( reguláris nyelvtan ) Egy CFG reguláris pontosan akkor ha R ( V \ ) x * x ( ( V \ ) e ) 63
Példa: ab (a b ) a* ab a a S abq Q at bt T at e Balrekurzió eltüntetése: A Aα 1 Aα 2 Aα 3... Aα m β 1 β 2... β n helyett: A β 1 A β 2 A... β n A A α 1 A α 2 A... α m A e Balfaktorizálás: azonos előtagok eltüntetése A αβ 1 αβ 2... αβ 1n γ helyett A αa γ A β 1 β 2... β n S Q T b 64
Felülről lefelé levezetés ( top-down derivation ) Mélységi bejárással megtehető ( rekurzívan ) Előrejelző levezetés Balrekurzió eltüntetés Balfaktorizálás Egyértelműség Átvitel diagramok: minden nemterminálishoz kezdő és végállapot szükséges hozzá szabályok a kezdőből végállapotba elvezető utak éleken egy-egy szimbólummal ha az élen terminális áll, akkor beolvassuk, ha nemterminális, akkor átugrunk annak kezdő állapotába 65
Például: E T E E +T E e E: T E T E : + T E E : + e e 66
Előrejelző levezetés feltétele: átviteli diagramok determinisztikus volta, azaz ne létezzen több átvitel egy állapotból ugyanarra a bemenetre egyértelmű nyelvtant próbáljunk meghatározni ha a nemdeterminizmus nem tüntethető el, akkor előrejelző levezetés nem Megvalósítás: verem automatával Emlékeztető generál elfogad példa reguláris nyelvek reg. exp. reg. gram. véges aut. a*b* CF nyelvek CFG verem aut. a n b n általános nyelvek ált. nyelvtan R V*(V\ )V*xV* Turing gép a n b m c n d m 67
CFG veremautomata Általában a verem automata nem determinisztikus így nem megvalósítható Determinisztikus esetben rekurzió nélkül is megvalósítható: A levezetési táblázat megadja a bemenet alapján, hogy mely szabályt kell alkalmazni. E a a b b + + E T E T+ T a T b BEMENET VEREM ELÕREJELZÕ LEVEZETÕ KIMENET LEVEZETÈSI TÀBLÀZAT 68
Példa: E TE T FT T *FT e E +TE e F id ( E ) A levezetési táblázat: Nem terminális id + Bemeneti szimbólumok * ( ) $ E E TE E TE E E TE E e E e T T FT T FT T T e T *FT T e T e F F id F ( E ) 69
Ez alapján az id + id * id levezetése: verem $E $E T $E T E $E T id $E T $E $E T+ $E T bemenet id+id*id$ id+id*id$ id+id*id$ id+id*id$ +id*id$ +id*id$ +id*id$ id*id$ kimenet E TE T FT F e T e E +TE 70
FORDÍTÓPROGRAMOK VI. Előadás Műszaki informatika szakos hallgatók számára Veszprémi Egyetem Számítástudomány Alkalmazása Tanszék 2002. 71
A levezetési táblázat elkészítése FIRST és FOLLOW segédfüggvények FIRST 1. Ha x egy terminális, akkor FIRST (x) = {x} 2. Ha van x e szabály, akkor e FIRST (x) 3. Ha x egy nemterminális és x y 1 y 2...y k egy szabály, akkor: a. Minden j k-ra, ha e FIRST (y i ) minden i= 1, 2,...j-1-re akkor FIRST (y j ) \ {e} FIRST (x) b. ha e FIRST (y i ) minden i= 1, 2,... k-ra akkor e FIRST (x) FOLLOW 1. Legyen $ FOLLOW (S), ahol S a kezdőszimbólum és $ a bemenetet lezáró szimbólum 72
2. Ha létezik A αbβ szabály, akkor legyen FIRST (β) \ {e} FOLLOW (B) 3. Ha létezik A αb vagy A αbβ ahol e FIRST (β) akkor FOLLOW (A) FOLLOW (B) Algoritmus 1. A nyelvtan minden A αszabályára hajtsuk végre 2-t és 3-at 2. Minden a FIRST (α) terminálisra, legyen (A α) M (A, a) 3. Ha e FIRST (α), akkor legyen (A α) M (A, b) minden b FOLLOW (A) terminálisra vagy $-ra 4. Minden nem definiált mezőjébe M-nek írjunk hibajelzést 73
LL (1) nyelvek Ha a nyelvtan nem egyértelmű vagy balrekurzív, akkor biztosan lesz legalább egy cellája a levezetési táblázatnak, ami egynél több szabályt tartalmaz. Előrejelző levezetés csak akkor alkalmazható, ha minden cella legfeljebb egy szabályt tartalmaz. Azokat a nyelveket, melyekre a levezetési táblázat minden cellája legfeljebb egy szabályt tartalmaz, LL (1) nyelveknek hívjuk. L balról olvasva L a legbaloldalibb nem terminálist tekintve 1 egy karakter előreolvasás alapján eldönthető egyértelműen, hogy melyik szabályt kell alkalmazni 74
LL (1) nyelvek megkülönböztető tulajdonságai Ha A α β része a nyelvnek, akkor 1. α-ból és β-ból nem vezethető le ugyanolyan terminálissal kezdődő szó 2. α és β közül legfeljebb az egyikből vezethető le e 3. Ha β * e, akkor α-ból nem vezethető le olyan a terminálissal kezdődő szó, melyre a FOLLOW (A) Bemutatott eszközök alkalmazása hiba visszaállításban Pánikszerű: A kifejtésénél olyan karakterre jutunk, amire nincs szabály a táblázatban, akkor a bemeneten az első a FOLLOW (A) karakterig olvasunk ha a bemeneten lévő karakter b FIRST (B), akkor átugrunk a B nemterminálisra 75
Kifejezés szintű hibakezelés: A levezetési táblázat nemdefiniált celláiba a hibakezelő függvények címeit írjuk, amik elvégzik a karakterek lokális beillesztését vagy törlését Feladat: Készítsünk előrejelző levezetőt ( parser -t vagy más néven szintaktikai elemzőt ) a következő nyelvtanhoz bexpr bexpr or bterm bterm bterm bterm and bfactor bfactor bfactor not bfactor (bexpr) true false Mivel balrekurziót tartalmaz ezért előtte balrekurzió mentesíteni kell: bexpr bterm bexpr bexpr or bterm bexpr e bterm bfactor bterm bterm and bfactor bterm e bfactor not bfactor (bexpr) true false 76
A FIRST halmazok FIRST (bfactor) = { n, (, t, f } FIRST (bterm ) = { e, a } FIRST (bterm) = FIRST (bfactor) = { n, (, t, f } FIRST (bexpr ) = { o, e ) FIRST (bexpr) = FIRST (bterm) = { n, (, t, f } A FOLLOW halmazok 1. { $ } FOLLOW (bexpr) 2. ( ahol nem terminális van a szabály belsejében) FIRST ( ) ) = { ) } FOLLOW (bexpr) FIRST (bterm ) \ { e } FOLLOW (bfactor) FIRST (bexpr ) \ { e } FOLLOW (bterm) 77
3. e FIRST (bterm ) ebből következik, hogy FOLLOW (bterm ) FOLLOW (bfactor) FOLLOW (bterm) FOLLOW (bterm ) továbbá e FIRST (bterm ) miatt FOLLOW (bterm) FOLLOW (bfactor) e FIRST (bexpr ) FOLLOW (bexpr ) FOLLOW (bterm) FOLLOW (bexpr) FOLLOW (bexpr ) továbbá e FIRST (bexpr ) miatt FOLLOW (bexpr) FOLLOW (bterm) A fentiek alapján az alábbi gráf írható fel: {$} FOLLOW(bexpr) {)} {a} FOLLOW(bfactor) {ο} FOLLOW(bterm) FOLLOW(bterm ) FOLLOW(bexpr ) 78
A FOLLOW halmazok a gráfról leolvashatóak FOLLOW (bexpr) = { ), $ } FOLLOW (bexpr ) = { ), $ } FOLLOW (bterm) = { ), $, o } FOLLOW (bterm ) = { ), $, o } FOLLOW (bfactor) = { ), $, o, a } A levezetési táblázat n ( t f a o ) $ expr or bterm bexpr bexpr bexpr bterm bexpr bexpr bterm bterm bfactor bterm bexpr e bterm and bfactor bterm bterm bterm e bfactor not (bex) true false 79
A levezetési fa bexpr bterm bexpr' bfactor bterm' or bterm bexpr' true e bfactor ( bexpr ) bterm' e bterm bexpr' bfactor bterm' true e e 80
FORDÍTÓPROGRAMOK VII. Előadás Műszaki informatika szakos hallgatók számára Veszprémi Egyetem Számítástudomány Alkalmazása Tanszék 2002. 81
Alulról felfelé parzolás (Bottom-up) más néven: eltol-redukál (shift reduce) levezetők építés a levéltől kezdve szabályokat visszafelé alkalmazva: szövegrész cseréje nem-terminálisra = redukció mígnem a kezdő szimbólumhoz jutunk Példa S aabf A Abc b B d Nyelvtan esetén: abbcdf aabcdf aadf aabf S 82
Handle (fogódzó, kapaszkodó): az a mintázat amire visszafelé alkalmazunk egy szabályt Példa E E + E E E * E E ( E ) E id Nyelvtan esetén: Handle Redukáló szabály id 1 + id 2 * id 3 E + id 2 * id 3 E + E * id 3 E + E * E E + E id 1 id 2 id 3 E * E E + E E id E id E id E E * E E E + E E 83
Megvalósítás veremmel a bemenetet pakoljuk a verembe, amíg nem redukálható CFG: ha egy szó levezethető, akkor mindig a leginkább jobbra levő nemterminálist kifejtve is levezethető ( rightmost derivation ), így a handle mindig a verem tetején lesz Akciók 1. eltolás (bemenet verem) (shift) 2. redukálás (szabály alkalmazása visszafelé) (reduce) 3. elfogad (accept) 4. hiba (error) Dilemmák eltol / redukál dilemma: eltol vagy redukál? redukál / redukál dilemma: mely szabályt alkalmazzuk? 84
Példa (megvalósítás veremmel) Verem $ $id 1 $E $E+ $E+id 2 $E+E $E+E* $E+E*id 3 $E+E*E $E+E $E Bemenet id 1 + id 2 * id 3 $ + id 2 * id 3 $ + id 2 * id 3 $ id 2 * id 3 $ * id 3 $ * id 3 $ id 3 $ $ $ $ $ Akció eltolás redukálás E id eltolás eltolás redukálás E id eltolás eltolás redukálás E id redukálás E E*E redukálás E E+E elfogad 85
A LR(k) nyelvi osztály L balról jobbra olvassuk a bemenetet R legjobboldalabbi nemterminális cseréjét (rightmost derivation) feltételezve k k karakter hosszúságban látjuk előre a bemenetet LR (0): semmit nem látunk csak shift-tel behozunk valamit a verembe LR levezető VEREM BEMENET a 1 a 2 a n $ s m x m s m1 Kezelő program KIMENET s 0 akció lépés 86
A veremben S i egy állapot, ami korábban a verembe pakoltakról hordoz információt, meghatározása DFAval: Konfiguráció: (s 0 x 1 s 1... x m s m, a i a i+1... a n $) ( verem tartalma, be nem olvasott bemenet ) akciók: az LR levezetési táblázat alapján 1. Ha az akció [s m, a i ] = eltol s, akkor a következő konfiguráció: (s 0 x 1 s 1... x m s m a i s, a i+1 a i+2... a n $) 2. Ha [s m, a i ] = redukál A B, B = r és s = lépés[s m-r, A] akkor a következő konfiguráció: (s 0 x 1 s 1... x m-r s m-r A s, a i a i+1...a n $) 3. Ha [s m, a i ] = elfogad, akkor elfogad 4. Ha [s m, a i ] = hiba, akkor hiba-visszaállító eljárás 87
Levezető algoritmus Bemenet: a bemeneti szimbólumsorozat = w LR levezetési táblázat (akciók + lépések) Kimenet: ha w L(G), akkor levezetési fa, különben hibakezelés Módszer: - Egy s 0 kezdő állapot van a verem alján és w$ a bemeneten induláskor - A levezető programot futtatjuk míg elfogad vagy hiba üzenetet nem ad. Példa A következő nyelvtanra: 1. E E +T 2. E T 3. T T * F 4. T F 5. F (E) 6. F id 88
89 Állapot táblázat F T E $ ) ( * + id r5 r5 r5 r5 11 r3 r3 r3 r3 10 r1 r1 s7 r1 9 s11 s6 8 10 s4 s5 7 3 9 s4 s5 6 r6 r6 r6 r6 5 3 2 8 s4 s5 4 r4 r4 r4 r4 3 r2 r2 s7 r2 2 elf. s6 1 3 2 1 s4 s5 0 lépések akciók állapot
1. s i eltolás és i állapot a verembe 2. r j eltolás és j -edik szabály alkalmazásával 3. elfogad elfogad 4. üres mező hiba SLR levezetési táblázat készítése SLR = ( Simple LR ) LR(0) tételek: szabályok és a jobb oldalon egy pont A XYZ A X YZ A XY Z A XYZ Ha a pont előtti részből levezethető szimbólum sorozat van a veremben, akkor arra számítunk, hogy a pont utáni részből levezethető szimbólum sorozat van a bemeneten 90
Lezárt (closure): Legyen I egy tételhalmaz: 1. Kezdetben I lezárt (I) 2. Ha A α Bβ lezárt (I) és B σegy szabály, akkor B σ lezárt (I) 2-t addig alkalmazzuk, míg új tétel kerül a lezárt (I)-be Példa E E E E + T T T T * F F F (E) id nyelvtanra nézve: Legyen I = {E E}, ekkor (closure) lezárt (I) = { E E, E E+T, E T, T T*F, T F, F (E), F id} 91
Lépés (goto): lépés ( I, X ) olyan A αx β tételeket tartalmazó halmaz lezártja amelyekre A α X β I LR(0) tételek kanonikus kollekciója procedure procedure items( G ) begin C:={ closure ( { s s }) }; end repeat for each set of items I in C and each grammar symbol X such that goto ( I, X ) is not empty and not in C do add goto ( I, X ) to C until no more items can be added to C 92
Példa Nyelvtan: E E E E + T T... T T * F F F (E) id I 0 : I 1 : E E E E E E + T E E + T E T T F I 2 : F (E) E T F id T T * F T T*F 93
I 3 : I 7 : T F T T* F F ( E ) I 4 : F id F ( E ) E E + T I 8 : E T F ( E ) I 5 : I 9 : F id E E + T I 6 : I 10 : E E + T T T * F T T* F T F I 11 : F ( E ) 94
FORDÍTÓPROGRAMOK VIII. Előadás Műszaki informatika szakos hallgatók számára Veszprémi Egyetem Számítástudomány Alkalmazása Tanszék 2002. 95
Tekintsük a következő véges automatát: állapotai a tételek (mely szabály alkalmazásában hányadik szimbólumnál tartunk) állapotátmenetek egy szimbólum olvasásával az állapot nem egyértelmű már kezdetben sem analógiák: e e item 1 item 2... a a NFA DFA átalakítás A DFA állapotai az NFA állapotainak halmazai S = E ( S ) δ(a,σ) = U E(p) minden (q,σ,p), q A esetén Az állapotok a tételek halmazai I 0, I 1 I 0 = closure({ S S }) I 1 = goto( I 1,σ ) 96
Példa: (az előző példa folytatása) I 0 = closure ( { E E } ) = { E E, E E + T, E T, T T * F, F ( E ), F id } ) goto ( I 0, E ) = closure ( { E E, E E + T } ) = { E E, E E + T } = I 1 goto ( I 0, T ) = closure ( { E T, T T * F } ) = {E T, T T * F } = I 2 goto ( I 0, F ) = closure ( { T F } ) = { T F } = I 3 goto ( I 0, ( ) = closure ( { F ( E ) } ) = {F ( E ), E E + T, E T, T T * F, T F, F ( E ), F id}= I 4 goto ( I 0, id ) = closure ( { T id } ) = { T id } = I 5 goto ( I 1, + ) = closure ( { E E + T } ) = { E E + T, T T * F, T F, F ( E ), F id} = I 6 goto ( I 2, * ) = closure ( {T T * F } ) = {T T * F, F ( E ), F id}= I 7 97
goto ( I 4, E ) = closure ( { F ( E ), E E + T } ) = {F ( E ), E E + T } = I 8 I 1 + I 6 T I 9 E F ( + * T I 2 * I 7 I 10 F T ( I 0 I 3 ( ( F I 4 E I 8 ( I 11 id id + I 5 98
SLR levezetési táblázat generálása 1. Legyen C = { I 0, I 1,, I n } LR(0) tételek halmazának kollekciója 2. Az i. állapot megfelel a I i halmaznak. Az i. állapothoz tartozó levezetési akciók: a. Ha A α a β I i és goto (I i, a ) = I j akkor akció [ i, a ] = eltol j b. Ha A α I i, akkor akció [ i, a ] = redukál A α minden a follow ( A ) esetén. ( A nem lehet s ) c. Ha s s I i, akkor az akció [ i, $ ] = elfogad Megjegyzés: Ha az akció mátrix valamely mezőjére több szabályunk is van, akkor a nyelv nem SLR-beli. 3. Minden A nem terminálisra, ha goto ( I i, A ) = I j, akkor akció [ i, a ] = j 4. Azokhoz a mezőkhöz amiket az 1, 2, 3 lépések nem definiáltak hibaüzenetet rendelünk 5. A kezdő állapot az, amelyekhez tartozó halmaz a s s et tartalmazza 99
Példa nyelvtan: E E (1) E E + T T (2,3) T T * F F (4,5) F ( F ) id (6,7) first halmazok: first ( + ) = { + } first ( * ) = { * } first ( ( ) = { ( } first ( ) ) = { ) } first ( E ) = first ( E ) first ( E ) = first ( T ) first ( T ) = first ( F ) first ( F ) = { (, id } Megjegyzés: csak az érdekel, hogy az e ne legyen eleme egyetlen first halmaznak sem, tehát egyik nem terminális sem eltüntethető. 100
follow halmazok: $ follow ( E ) follow ( E ) follow ( E ) (1) + follow ( E ) (2) follow ( E ) follow ( T ) (2,3) * follow ( E ) (4) follow ( T ) follow ( F ) (4,5) ) follow ( E ) (6) Ebből következik, hogy: follow ( E ) = { $ } follow ( E ) = { +, ), $ } follow ( T ) = { +, *, ), $ } follow ( F ) = { +, ), $ } 101
Akciók és eltolások: Például: Például: I 0 = { E E, E E + T, E T, T T * F, F ( E ), F id} ( 2.a lépés ) akció [ 0, ( ] = eltol 4 akció [ 0, id ] = eltol 5 I 1 = { E E, E E + T } ( 2.a lépés ) ( 2.c lépés ) akció [ 1, + ] = eltol 6 akció [ 1, $ ] = elfogad 102
Például: I 2 = { E T, T T * F } ( 2.b lépés ) mivel follow ( E ) = { +, ), $ } ezért akció [ 2, $ ] = akció [ 2, + ] = akció [ 2, ) ] = = redukál E T 103
FORDÍTÓPROGRAMOK IX. Előadás Műszaki informatika szakos hallgatók számára Veszprémi Egyetem Számítástudomány Alkalmazása Tanszék 2002. 104
Nem SLR nyelvek Tekintsük a következő nyelvtant ( L left value, R right value, *R value of R ) S L = R S R L *R L id R id Kanonikus LR(0) tételek erre a nyelvtanra: I 0 = { S S, S R, L * R, L id, R id, S L = R } I 1 = { S S } I 2 = { S L = R, R L } 105
Tekintsük az I 2 halmazt S L = R akció [ 2, = ] = eltol 6 mivel = follow ( R ) R L akció [ 2, = ] = redukál R L tehát egy s / r ( eltol / redukál ) konfliktus keletkezett, mivel a levezetési táblázat egyazon cellájába két értéket akartunk beírni. Mivel a nyelvtan egyértelmű, így arra következtetünk, hogy nem SLR-beli. Kanonikus LR levezetési táblázatok SLR esetén A αredukáló lépést alkalmazunk, ha i állapotban [ A α ] I i és a follow ( A ) Előfordulhat, hogy i állapotban βα van a verem tetején úgy, hogy βa után nem következhet a a szóban. Megoldás: további információt viszünk az állapotba: egyenként pontosan megadjuk, hogy mely bemeneti karakter esetén redukálható α az A-ra. 106
LR(1) tételek [ A α β, a ] ahol A αβegy szabály és a pedig egy terminális vagy $ Megjegyzés: Az előreolvasás a [ A α β, a ] tételeket nem befolyásolja ha β e de Egy [ A α β, a ] LR(1) tétel egy γ előtagra érvényes ha ahol: 1. γ = δ α 2. a az w első szimbóluma ( terminális ), vagy w = e és a = $ A lezárt újrafogalmazása: Ha egy [ A α Bβ, a ] tétel érvényes egy γ előtagra, akkor ahol γ = δ α R G R S δaw σαβw G S δaax σαbβax R G 107
βax by Tegyük fel hogy, a, ekkor minden B ηszabály esetén Tehát [ B η, b ] érvényes a δ előtagra. b lehet az első terminális ami β-ból került levezetésre, vagy β-ból levezethető βax by e a levezetése során, ekkor b = a, másképpen b egy tetszőleges terminális a First ( βax )-ből. Mivel a terminális így First ( βax ) = First ( βa ). Az LR(1) tételek algoritmikus leszámolása: function closure ( I ) begin repeat R G R for each item [ A α Bβ, a ] I each production β δ in G and each terminal b first ( βa ) G S σbby σηby R G 108
end such that [ B η, b ] I do add [ B σ, b ] to I until no more items can be added to I return I function goto ( I, X ) begin end Let J be the set of items [ A αx β, a ] such that [ A αx β, a ] I return closure ( J ) procedure items ( G ) begin C:= { closure ( { [ s S, $]} ) } repeat for each setofitemsi inc and each granted symbol X 109
end Példák such that goto ( X, I ) is not empty in C do add goto ( X, I ) to C until no more set of items can be added to C Tekintsük a { [ S S, $ ] } halmazt Kérdés: [ S S, $ ] hogyan írható [ A α Bβ, a ] alakba Válasz: A = S B = S a = $ α = e β = e A closure eljárás szerint [ B δ, b ] alakú tételeket generálunk minden B δszabályra és b first ( βa ) terminálisra Legyen a vizsgált nyelvtan: S S S CC C cc d ekkor [ S CC, $ ] kerül a lezártba 110
Tekintsük a [ S CC, $ ] tételt: [ A α Bβ, a ] alakba írható, ha A = S, α = e, β = C, B = C, a = $ ekkor: first ( βa ) = first ( β$ ) = first ( C ) = { c, d } tehát: [ C cc, c ], [ C cc, d ], [ C d, c ], [ C d, d ] I 0 : s-el átmenve I 1 : S S, $ S S, $ S CC, $ c-vel átmenve I 2 : C CC, c / d S C C, $ C d, c / d C CC, $ és így tovább C d, $ 111
Kanonikus LR levezetési táblázat generálása 1. Készítsük el a G nyelvre az LR(1) tételek halmazainak kollekcióját 2. Az i állapota a I i halmazt reprezentálja A levezetési akciókat a következő féle képen határozzuk meg: a. Ha [ A α aβ, b ] I i és goto (I i, a ) = I j akkor akció [ i,a ] = eltol j ahol a egy terminális b. Ha [ A α, a ] I i, A S akkor az akció [ i,a ] = redukál A α c. Ha [ S S, $ ] I j akkor akció [ i,$ ] = elfogad 3. Ha goto ( I i,a ) = I j akkor goto [ i, A ] = j 4. Minden nem definiált cellába írjunk hibaüzenetet 5. Kezdő állapot az, melyhez tartozó I i halmaz elem az [ S S, $ ] tétel 112
FORDÍTÓPROGRAMOK X. Előadás Műszaki informatika szakos hallgatók számára Veszprémi Egyetem Számítástudomány Alkalmazása Tanszék 2002. 113
Szintaxisvezérelt fordítás Emlékezető: 1. Lexikai elemzés: szimbólumok azonosítása 2. Szintaktikai elemzés ( levezetés ): nyelvi szimbólumok szimbólumok nyelvtani kapcsolata 3. Szemantikai elemzés: szimbólumok kapcsolatainak jelentése Szemantikai szabályok leírására Szintaxis vezérelt definíciók Fordítási séma Szintaxis vezérelt definíció A nyelvi szimbólumokhoz attribútumokat rendeltünk a. Szintetizált attribútumok A levezetési fában a gyermekekhez rendelt attribútumokból számoljuk a szülő attribútumait Szabályban: a bal oldalon álló szimbólum attribútuma a jobb oldalon álló szimbólumok attribútumainak függvénye 114
b. Származtatott vagy örökölt attribútum A fában egy csúcshoz tartozó szimbólum attribútumait a szülők és testvérek attribútumaiból számoljuk Szabályban: a jobb oldalon álló szimbólumok attribútumait a bal és a jobb oldalon álló szimbólumok attribútumaiból számoljuk Szintetizált attribútum Példa: Nyelvi szabályok L En E E 1 + T E T T T 1 * F T F F ( E ) F digit Szemantikai szabályok print ( E.val ) E.val := E 1.val + T.val E.val := T.val T.val := T 1.val * F.val T.val := F.val F.val := E.val F.val := digit.lexval 115
Ekkor a 3*5+4n levezetése L print(19) E.val=15+4=19 n E.val=15 + T.val=4 T.val=3*5=15 F.val=4 * T.val=3 F.val=5 digit.lexval=4 F.val=3 digit.lexval=5 digit.lexval=3 Bejárási sorrend: alulról-felfelé 116
Származtatott attribútumok Gyakran átírható szintetizált attribútumokra, de néha származtatottal könnyebb megfogalmazni Példa: ( típusdefiníció ) Nyelvi szabályok D T L T int T real L L 1, id L id Szemantikai szabályok L.in := T.type T.type := integer T.type := real L 1.in := L.in addtype ( id.entry, L.in ) addtype ( id.entry, L.in ) 117
Példa: levezetés típusdefiníció alapján: real(id 1,id 2,id 3 ) D T.type=real L.in=real real, L.in=real id 3, L.in=real id 2 Függőségi gráf id 2 Csúcsok: attribútumok Élek: ha a értékéből kiszámoljuk b -t, akkor b függ a -tól, amit a b jelöl. attribútumok ettol függ ez 118
Topológiai rendezésnek nevezzük a csúcsok egy V 1, V 2,, V n sorrendjét, ha minden V i V j élre i< ja rendezés szerint A topológikus rendezés ad egy megfelelő sorrendet az attribútumok kiértékelésére Példa: szintetizált attribútumok 1 2 3 4 5 6 7 8 Lehetséges kiértékelési sorrendek: 4, 5, 6, 2, 7, 8, 3, 1 4, 7, 6, 8, 3, 5, 2, 1 119
Szintaxisvezérelt definíciók alkalmazása: szintaxisfa készítése A szintaxisfa egy dinamikus adatszerkezet, ami leírja a levezetés eredményét ( a levezetési fa tömörített formája ) Például: 3*5+4 A szintaxisfa felépítéséhez használt szintaxis vezérelt definíciók Például: Nyelvi szabályok E E 1 + T E E 1 -T E T T ( E ) T id T num Szemantikai szabályok E.nptr := mknode ( +, E 1.nptr, T.nptr) E.nptr := mknode ( -, E 1.nptr, T.nptr) E.nptr := T.nptr T.nptr := E.nptr T.nptr := mkleaf (id, id.entry) T.nptr := mkleaf (num, num.val) 120
Példa: a-4+c -hez tartozó szintaxisfa: + - id id num C címére mutató mutató to entry for a A szintetizált attribútumok kiszámítása a levezető ( parser ) vermének alkalmazásával Mivel a szintetizált attribútumokat alulról-felfelé számoljuk így alulról-felfelé ( bottom-up ) levezető kell Például: LR levezető Amikor szabályt alkalmazunk visszafelé, akkor a szintetizált attribútumokat is kiszámoljuk 121
Például: Nyelvi szabályok L E n L E 1 + T E T T T 1 * F T F F ( E ) F digit Szemantikai szabályok print ( val[ top ] ) val[ ntop ] := val[ top-2 ] + val[ top ] val[ ntop ] := val[ top-2 ] * val[ top ] val[ ntop ] := val[ top-1 ] Ha egy olyan szabályt redukálunk amelynek jobb oldalán r szimbólum van akkor: ntop := top r +1 122
L-attribútumú definíció Ha egy A X 1 X 2 X n esetén az X j attribútuma ( 1 j n ) csak a következőktől függ: Az X 1 X 2 X j-1 szimbólumok attribútumaitól és A -nak a származtatott attribútomaitól LL levezetőkkel ( pl: perdiktív parser ) és a levezetési fa mélységi bejárásával számolható Fordítási sémák ( emlékeztető ) A szabályok jobb oldalába { } közzé tett szemantikai akciókat ágyazunk A szemantikai akciók végrehajtása a levezetési fa bejárásának megfelelően Példa: infix postfix átalakítás E E + T { print ( + ) } E E - T { print ( - ) } E T E 0 { print ( 0 ) } : : E 9 { print ( 9 ) } 123
A 9-5+2 levezetési fája E {print ( 9 )} E + T {print ( + )} E - T 2 {print ( 2 )} T 5 {print ( 5 )} 9 {print ( 9 )} Felülről lefelé fordítás ( top-down translation ) A.a=g(g(f( X.x ), Y 1.y ), Y 2.y ) A.a=g(f(X.x),Y 1.y) Y 2 A.a=f(X.x) Y 1 X 124
Balrekurzív nyelvtanunk van Attribútumokat alulról-felfelé számoljuk Ezzel szemben: Előrejelző levezetőt szeretnénk használni a. Jobb rekurzív nyelvtant használunk Az attribútumokat felülről lefelé számoljuk A X R.i = f(x.x) Y 1 R.i = g(f(x.x), Y 1.y) Y 2 R.i = g(g(f(x.x), Y 1.y, Y 2.y) e 125
a. b. szintaxis fa elkészítése E E 1 + T { E.nptr := mknode ( +, E 1.nptr, T.nptr ) } E E 1 T { E.nptr := mknode (, E 1.nptr, T.nptr ) } E T { E.nptr := T.nptr } Balrekurzió mentesítés után: E T { R.i := T.nptr } R { E.nptr := R.s } R + T { R 1.i := mknode ( +, R.i, T.nptr ) } R 1 { R.s := R 1.s } R -T { R 1.i := mknode ( -, R.i, T.nptr ) } R 1 { R.s := R 1.s } R e T ( E ) { T.nptr := E.nptr } T id { T.nptr := mkleaf ( id, id.entry ) } T num { T.nptr := mkleaf (num, num.val) } 126
E T.nptr R.i id - T.nptr R.i id num + T.nptr R.s - + id e num id c Előretekintő levezetővel megvalósítható Felépítjük a szintaxisfát rögtön ki tudjuk értékelni 127
Rekurzív kiértékelés Amikor az attribútumok nem értékelhetőek ki a levezetéssel párhuzamosan Függvényekkel járjuk be a levezetési fát egy csúcs gyermekeit nem feltétlenül balról-jobbra olvasva 128
FORDÍTÓPROGRAMOK XI. Előadás Műszaki informatika szakos hallgatók számára Veszprémi Egyetem Számítástudomány Alkalmazása Tanszék 2002. 129
Megjegyzés ( szóhasználat ) Azokat a szintaxis vezérelt definíciókat, melyek csak szintetizált attribútumokat tartalmaznak S attribútumú definícióknak nevezzük Örökölt ( származtatott ) attribútumok kiértékelése alulról-felfelé Emlékeztető: Az LR levezetők a nyelvek bővebb osztályát fogadják el, mint az LL levezetők A bemutatásra kerülő eljárás L-attribútumú definíciók kiértékelésére képes Mivel LR esetén csak a szabálynak megfelelő minta végére érve tudjuk pontosan mely szabályt kell levezetni visszafelé, így a szemantikai akcióknak a szabály végén kell lennie A beágyazott akciók eltüntethetőek, új nem terminális szimbólumok úgynevezett jelzők ( markerek ) bevezetésével 130
Például: E TR R + T { print ( + ) } R -T { print ( - ) } R e T num { print ( num.val( ) )} Átalakítható: E TR R + TMR - TMR e T num { print ( num.val( ) ) } M e { print ( + ) } M e { print ( - ) } Származtatott attribútumok a veremben Fordítási séma P TL { L.in := T.type } T int { T.type := integer } T real {T.type := real } L L 1 id { L 1.in := L.in; addtype ( id entry, L.in ) } L id { addtype ( id entry, L.in ) } 131
real p,q,r levezetése D Bemenet Verem Levezetési szabály real p,q,r - T.type L.in p,q,r p,q,r real T T real real L.in, r,q,r,q,r Tp TL L id L.in, q q,r,r,r TL,q TL TL, p r TL,r TL L L,id D D TL 132
Amikor L-re redukálunk egy szabály jobb oldalát, akkor mindig T van a veremben alatta, így annak típusához közvetlenül hozzáférünk Szabály D TL T int T real L L, id L id Kódrészlet val[ ntop ] := integer val[ ntop ] := real addtype ( val[ top ], val[ top 3 ]) addtype ( val[ top ], val[ top 1 ]) Ha a származtatott attribútumok forrása nem mindig ugyan olyan távolságra van, akkor segéd szimbólumokat vezetünk be 133
Példa: Nyelvi szabályok S a A C S b A B C C c Szemantikai szabályok C.i := A.s C.i := A.s C.s := g( C.i ) Átalakítható a következő formában Nyelvi szabályok S a A C S b A B M C C c M e Szemantikai szabályok C.i := A.s M.i := A.s; C.i := M.s C.s := g( C.i ) M.s := M.i Így a C.i számításához szükséges attribútum mindig ugyan olyan messze van a verem tetejétől 134
Ugyanezt a technikát használjuk, ha a számításhoz szükséges érték nincs mindig a veremben Például: ha a következő szabályt hozzátesszük az előzőekhez: Nyelvi szabályok S a A C Szemantikai szabályok C.i := f ( A.s ) átalakítható: Nyelvi szabályok S a A N C N e Szemantikai szabályok N.i := A.s; C.i := N.s N.s := f ( N.i ) így közvetlenül c elé kerül A atribútuma 135
Típus ellenőrzés ( Type checking ) Egyszerű: Olyan nyelvekre használható, ahol az azonosítókat előre kell definiálni ( előbb definiálni mint használni ) Például: ( D deklaráció, E kifejezés, T típus, pointer ) D D ; E D D ; D id : T T char integer array[ num ] of T T E literal num id E mod E E [ E ] E Megjegyzés array[256] of char, egy 256 hosszú tömb 1-től 256-ig indexelve integer, egészre mutató pointer 136