Kifejezések kiértékelése * Lengyel-forma Szlávi Péter ELTE Informatika Szakmódszertani Csoport szlavi@ludens.elte.hu http://izzo.inf.elte.hu/~szlavi/ Copyright, 1999 © Szlávi Péter
Tartalomjegyzék 0 Bevezetés (célok, fogalmak) 1 Lexikális analízis 2 Aritmetikai kifejezések 2.1 Rutishauser módszere 2.2 A lengyel-formák, a lényeg 3 Kifejezések feldolgozása postfix lengyel-forma alapján 3.1 Lengyel-formára hozás 3.2 Kiértékelés lengyel-forma alapján Programozási módszertan 2018.12.10.
0 Bevezetés (célok, fogalmak) Kifejezések általános fogalma végrehajtás leírása (akár egy programé): kiértékelési fával amelynek pontjai operációk, operációk paraméterei (amelyek szintén lehetnek kiértékelési fák – rekurzió). művelet1 par1 par2 … művelet2 par1 … parn parn Programozási módszertan 2018.12.10.
0 Bevezetés (célok, fogalmak) Előzetes példa – egy végrehajtható program: Program Próba: Változó a,b,c:Egész Be: a,b c:=sin(a+b^2) Ki: c Program vége. Program Próba Változó Egész a b c Be: := Ki: sin + ^ 2 … és vannak pusztán (fekete) szintaktikai elemek … Programozási módszertan 2018.12.10.
0 Bevezetés (célok, fogalmak) Előzetes példa – és a program „végrehajtása”: Program Próba: Változó a,b,c:Egész Be: a,b c:=sin(a+b^2) Ki: c Program vége. Program Próba Változó Egész a b c Be: := Ki: sin + ^ 2 A „deklaráció” nélkül… Programozási módszertan 2018.12.10.
0 Bevezetés (célok, fogalmak) Ez előző lapon pirossal jelzett elemek operációk aritmetikai műveletek relációk függvények (szabad szintaxisú) operátorok paraméterek konstansok változók kifejezések (itt a rekurzió) Ez előző lapon kékkel jelzett elemek Programozási módszertan 2018.12.10.
0 Bevezetés (folytatás) + a * 2 b Problémák: a+2*b2*b+ab*2+a nem egyértelműség (a+2)*b zárójelezés x:=(a+2)*b nem kommutatív bináris operátor * b + a 2 * b + a 2 := x Programozási módszertan 2018.12.10.
0 Bevezetés (folytatás) sin(b(i)+a*x) „szabad szintaxisú” operátor (indexelés) prefix operátor (sin) + * Ind b i Sin a x Programozási módszertan 2018.12.10.
0 Bevezetés (folytatás) Lexikális egységek fogalma Típus Miféle=(Adat,Művelet) LexEgys=Rekord(fajta:Miféle azon:Szöveg) Finomítás: Adat(Konstans, Változó) Művelet(BinOp, …) Kifejezéskiértékelés folyamata: Lexikális egységekre bontás (lexikális analízis) Kiértékelési fa felépítése Kiértékelési fa lebontása (kódgenerálás, végrehajtás) Praktikus elkülönítés, mert a változók értékét először még meg kell tudakolni. Fordítás esetén Értelmezés esetén Programozási módszertan 2018.12.10.
0 Bevezetés (folytatás) Lexikális analízis: Input: Szöveg vagy karaktersorozat (File) Output: LexEgys-sorozat (AbsztraktSorozat, File,Sor) Pl.: sin(k*+)<x (Művelet,’sin’)(Művelet,’(’)(Adat,’k’) (Művelet,’*’)(Adat,’’)(Művelet,’+’) (Adat,’’)(Művelet,’)’)(Művelet,’<’) (Adat,’x’) Programozási módszertan 2018.12.10.
0 Bevezetés (folytatás) Kiértékelési fa felépítése: Input: LexEgys-sorozat (AbsztraktSorozat,File,Sor) Output: LexEgys-fa Pl.: (Művelet,’sin’)(Művelet,’(’)(Adat,’k’) (Művelet,’*’)(Adat,’’)(Művelet,’+’) (Adat,’’)(Művelet,’)’)(Művelet,’<’) (Adat,’x’) Demo Programozási módszertan 2018.12.10.
0 Bevezetés (folytatás) Kiértékelési fa lebontása: Input: LexEgys-fa Output: kód (fordítás) vagy érték (értelmezés) Pl.: Programozási módszertan 2018.12.10.
0 Bevezetés (folytatás) Kiértékelési fa lebontása (folytatás): Programozási módszertan 2018.12.10.
1 Lexikális analízis Input: Szöveg vagy karaktersorozat (File) Output: LexEgys-sorozat (AbsztraktSorozat,File,Sor) Típus Kif=Szöveg LexKif=AbsztraktSorozat(LexEgys) Függvény LexikálisAnalízis(Konstans k:Kif):LexKif Változó lk:LexKif opHol:AbsztraktSorozat ( Rekord(tól,ig:Egész) ) ik,io:Egész opHol:=OperátorTólIg(k) [opHol(i):=i. operátor helye] Hf. Programozási módszertan 2018.12.10.
1 Lexikális analízis (folytatás) ik:=1; [k akt.ind.] io:=1; [oper. akt.ind.] lk:=Üres; Ciklus amíg ikHossz(k) Ha ik=opHol(io).tól akkor [operátornál tartunk] lk:+LexEgys(Művelet,Rész(k,opHol(io).tól, opHol(io).ig)) ik:=opHol(io).ig+1; io:+1 különben [adatnál tartunk] lk:+LexEgys(Adat,Rész(k,ik,opHol(io).tól-1)) ik:=opHol(io).tól Elágazás vége Ciklus vége LexikálisAnalízis:=lk Függvény vége. Programozási módszertan 2018.12.10.
2 Aritmetikai kifejezések Csak „hagyományos” aritmetikai műveleteket tartalmazó szintaktikusan helyes kifejezések (legfeljebb relációk és logikai műveletek). Az adatok csak konstansok lehetnek. Két módszer: Rutishauser (a „naív”) módszer lengyel-formára épülő (Lukasievitž) Kiindulópont: lexikális egységekre bontott kifejezés Programozási módszertan 2018.12.10.
2 Aritmetikai kifejezések 2.1 Rutishauser módszere @:TípusAzonosítóAzonosítóTípus; azonosítóhoz adott típusú érték rendelése Feltételezések: csak bináris, infix műveleteket tartalmaz Például -5 helyett 0-5, -x helyett 0-Valós©x teljesen zárójelezett Például (0-x) helyett (0-(Valós©x)) Lényeg: fafölépítés szintszám lexikális egység falebontás legmagasabb szintszámú, legbaloldalibb részkifejezés kiértékelése és értékének visszahelyettesítése; amíg csak (egy) értéket nem kapunk. Programozási módszertan 2018.12.10.
2 Aritmetikai kifejezések 2.1 Rutishauser módszere (folytatás) Szintszám-hozzárendelés: kezdetben 0 (azaz az 1. elemhez 0) ‘(’ és a műveleti jelek növelik (azaz a következő elemé eggyel nagyobb) ‘)’ és az operandusok eggyel csökkentik (azaz a következő elemé eggyel nagyobb) Pl.: (((7+2)*3)/(5-2)) 01232321210121210 ((9*3)/(5-2)) (27/(5-2)) 0121210121210 01 0121210 (27/3) 9 01 010 0 Programozási módszertan 2018.12.10.
2 Aritmetikai kifejezések 2.1 Rutishauser módszere (folytatás) Algoritmus: Típus LexKif = AbsztraktSorozat(LexEgys) Szintek = AbsztraktSorozat(Egész) Operátor= ('(',')','+','-',...) Függvény Kiértékel(Változó lk: LexKif): Valós Változó sz:Szintek op1,op2,műv:LexEgys eredmény:Valós hol,rkszint:Egész [részkifejezés szintszám] SzintSzámozás(lk,sz) Programozási módszertan 2018.12.10.
2 Aritmetikai kifejezések 2.1 Rutishauser módszere (folytatás) Ciklus amíg Hossz(lk)>1 [még nem csak az eredmény] hol:=MaxSzintű(sz); op1:=ElemÉrték(lk,hol) op2:=ElemÉrték(lk,hol+2); műv:=ElemÉrték(lk,hol+1) rkszint:=ElemÉrték(sz,hol+1) eredmény:=Kiszámol(op1.azonosító, műv.azonosító,op2.azonosító) lk:=Bal(lk,hol-2)+LexEgys(Adat,eredmény)+ Jobb(lk,hol+4)) sz:=Bal(sz,hol-2)+rkszint+ Jobb(sz,hol+4)) Ciklus vége Kiértékel:=eredmény Függvény vége. (((7+2)*3)/(5-2)) 01232321210121210 ((9*3)/(5-2)) (27/(5-2)) 0121210121210 01 0121210 (27/3) 9 01 010 0 Programozási módszertan 2018.12.10.
2 Aritmetikai kifejezések 2.1 Rutishauser módszere (folytatás) Meggondolandó eljárások, függvények: Eljárás SzintSzámozás(Konstans lk: LexKif, Változó sz: Szintek) [sz:=az lk-beli lexikális kifejezések szintszám-sorozata] Függvény MaxSzintű(Konstans sz: Szintek): Egész [az sz-beli szintszámok közüli első max. indexe] Függvény Kiszámol(Konstans o1: Szöveg, m: Operátor, o2: Szöveg): Valós [az m művelet értéke o1 és o2 paraméterekkel] Programozási módszertan 2018.12.10.
2 Aritmetikai kifejezések 2.2 A lengyel-formák, a lényeg Lényeg: az operátor megelőzi (prefix) vagy követi (postfix, suffix) az operandusait. Pl.: Hagyományos Lengyel-forma infix prefix postfix a+2*b + a * 2 b a 2 b * + (a+2)*b * + a 2 b a 2 + b * x:=a+2*b := x + a * 2 b x a 2 b * + := sin(a*x+b(i)) sin + * a x b i a x * b i + sin : Indexelés operátor Programozási módszertan 2018.12.10.
3 Kifejezések feldolgozása postfix lengyel-forma alapján 3 3 Kifejezések feldolgozása postfix lengyel-forma alapján 3.1 Lengyel-formára hozás Input: Sor(LexEgys) [infix] Output: Sor(LexEgys) [postfix] Lényeg: verembe a műveleti jelek. Feltétel (csak most!): csak bináris műveletek. Pl.: Input Verem Output 3^2/(5+3) ^2/(5+3) 3 Programozási módszertan 2018.12.10.
3 Kifejezések feldolgozása postfix lengyel-forma alapján 3 3 Kifejezések feldolgozása postfix lengyel-forma alapján 3.1 Lengyel-formára hozás (folytatás) Input Verem Output 2/(5+3) ^ 3 /(5+3) ^ 3 2 (5+3) / 3 2 ^ 5+3) / ( 3 2 ^ +3) / ( 3 2 ^ 5 3) / ( + 3 2 ^ 5 ) / ( + 3 2 ^ 5 3 / 3 2 ^ 5 3 + 3 2 ^ 5 3 + / Programozási módszertan 2018.12.10.
3 Kifejezések feldolgozása postfix lengyel-forma alapján 3 3 Kifejezések feldolgozása postfix lengyel-forma alapján 3.1 Lengyel-formára hozás (folytatás) Típus Operátor =('(',...,'+','-',...) Infix =Sor(LexEgys) PostFix =Sor(LexEgys) Műveletek=Verem(Operátor) Konstans prec:Tömb(Operátor: Egész) (0,...,8,8,...) [precedenciák] Eljárás PostFixForma(Változó if:Infix, pf:Postfix): Változó le: LexEgys v : Műveletek Programozási módszertan 2018.12.10.
3 Kifejezések feldolgozása postfix lengyel-forma alapján 3 3 Kifejezések feldolgozása postfix lengyel-forma alapján 3.1 Lengyel-formára hozás (folytatás) Üres(v); Üres(pf) Ciklus amíg nem Üres?(if) Sorból(if,le) Elágazás le.fajta=Adat esetén Sorba(pf,le) le.azonosító='(' esetén Verembe(v,le.azonosító) le.azonosító=')' esetén NyK(v,pf) egyéb esetben NKK(le.azonosító, v,pf) Verembe(v,le.azonosító) Elágazás vége Ciklus vége VeremÜrítés(v,pf) Eljárás vége. Nyitóig kivesz Nem kisebbet kivesz Programozási módszertan 2018.12.10.
3 Kifejezések feldolgozása postfix lengyel-forma alapján 3 3 Kifejezések feldolgozása postfix lengyel-forma alapján 3.1 Lengyel-formára hozás (folytatás) NyitóigKivesz: Eljárás NyK(Változó v:Műveletek, pf:PostFix): Változó op:Operátor Ciklus amíg Tető(v)'(' Veremből(v,op); Sorba(pf,LexEgys(Művelet,op)) Ciklus vége Veremből(v,op) Eljárás vége. Programozási módszertan 2018.12.10.
3 Kifejezések feldolgozása postfix lengyel-forma alapján 3 3 Kifejezések feldolgozása postfix lengyel-forma alapján 3.1 Lengyel-formára hozás (folytatás) NemKisebbeketKivesz: Eljárás NKK(Konstans műv:Operátor, Változó v:Műveletek, pf:PostFix): Változó op:Operátor Ciklus amíg nem Üres?(v) és Prec(műv)Prec(Tető(v)) Veremből(v,op) Sorba(pf,LexEgys(Művelet,op)) Ciklus vége Eljárás vége. Programozási módszertan 2018.12.10.
3 Kifejezések feldolgozása postfix lengyel-forma alapján 3 3 Kifejezések feldolgozása postfix lengyel-forma alapján 3.1 Lengyel-formára hozás (folytatás) Eljárás VeremÜrítés(Változó v:Műveletek, pf:PostFix): Változó op:Operátor Ciklus amíg nem Üres?(v) Veremből(v,op) Sorba(pf,LexEgys(Művelet,op)) Ciklus vége Eljárás vége. Programozási módszertan 2018.12.10.
3 Kifejezések feldolgozása postfix lengyel-forma alapján 3 3 Kifejezések feldolgozása postfix lengyel-forma alapján 3.2 Kiértékelés lengyel-forma alapján Input: Sor(LexEgys) [postfix] Output: érték Lényeg: verembe az operandusok (részeredmények) Pl.: (Jelölés: Verembe; Veremből) Input Verem Tevékenység 7 2 + 3 * 5 2 - / (7) 2 + 3 * 5 2 - / 7 (2) Programozási módszertan 2018.12.10.
3 Kifejezések feldolgozása postfix lengyel-forma alapján 3 3 Kifejezések feldolgozása postfix lengyel-forma alapján 3.2 Kiértékelés lengyel-forma alapján (folytatás) Input Verem Tevékenység + 3 * 5 2 - / 7 2 (+) 3* 5 2 - / 9 (3) * 5 2 - / 9 3 (*) 5 2 - / 27 (5) 2 - / 27 5 (2) - / 27 5 2 (-) / 27 3 (/) 9 Programozási módszertan 2018.12.10.
3 Kifejezések feldolgozása postfix lengyel-forma alapján 3 3 Kifejezések feldolgozása postfix lengyel-forma alapján 3.2 Kiértékelés lengyel-forma alapján (folytatás) Típus PostFix =Sor(LexEgys) RészEred=Verem(Valós) Függvény PostFixKiért(Változó kif:PostFix):Valós Változó le:LexEgys v :RészEred ért,op1,op2:Valós Üres(v) Ciklus amíg nem Üres?(kif) Sorból(kif,le) Programozási módszertan 2018.12.10.
hozzárendelés, konstans esetén maga az érték. 3 Kifejezések feldolgozása postfix lengyel-forma alapján 3.2 Kiértékelés lengyel-forma alapján (folytatás) Elágazás le.fajta=Adat esetén Verembe(v, Érték(le.azonosító)) le.fajta=Művelet esetén Veremből(v,op2); Veremből(v,op1) ért:=Kiszámol(le.azonosító,op1,op2) Verembe(v,ért) Elágazás vége Ciklus vége Változó esetén érték hozzárendelés, konstans esetén maga az érték. Programozási módszertan 2018.12.10.
3 Kifejezések feldolgozása postfix lengyel-forma alapján 3 3 Kifejezések feldolgozása postfix lengyel-forma alapján 3.2 Kiértékelés lengyel-forma alapján (folytatás) Veremből(v,ért); PostFixKiért:=ért Függvény vége. Függvény Kiszámol(Konstans műv:Szöveg, op1,op2:Valós):Valós Elágazás műv='+' esetén Kiszámol:=op1+op2 műv='-' esetén Kiszámol:=op1-op2 ... ... Elágazás vége Függvény vége. Demo Programozási módszertan 2018.12.10.