You are on page 1of 106

Programski prevodioci 1 Uvod

Lekcija 2 – Leksička analiza

©2004-2009 Dragan Bojić 1 ©2004-2009 Dragan Bojić 2

Uloga leksičkog analizatora (skenera)


1. Isporučuje sintaksnom analizatoru
terminalne simbole (tokene)

i f ( x ==3 ) skener (IF,-) (LP,-) (ID, “x”) (EQ,-) (NUM,3) ... Deterministički konačni automati
niz znakova niz tokena
(klasa, vrednost)

2. Ignoriše neke delove ulaznog teksta


• razmake
• tabulatore
• znake za kraj linije (CR, LF)
• komentare

Programski prevodioci © 2004-2009 Dragan Bojić 3 ©2004-2009 Dragan Bojić 4

Konačni automati Konačni automati


Startno stanje Ulazni simboli Deterministički konačni automat opisan je ureĎenom petorkom (S,
označeno U, , St, P) gde:
0 1
strelicom  A D A 0 S - skup stanja automata S = {A, B, C, D, E, F};
(ako je nema, B A C 0 A je stanje
onda stanje C A F 0 odbijanja U - skup ulaznih simbola (azbuku automata), U = {0, 1};
u prvoj vrsti D B C 0 : S x U  S predstavlja funkciju prelaza; za svako stanje i
tabele E B C 1 svaki ulazni simbol definiše novo stanje u koje automat prelazi iz
F E A 1 E je stanje stanja s  S za ulazni simbol u  U; u ulaz tabele u vrsti X i
prihvatanja koloni Y upisana je vrednost (X,Y);
Stanja - funkcija prelaza St  S je startno stanje automata St = A;
(F, 1) = A •P  S skup stanja prihvatanja, P = {E, F}. Stanja iz skupa S-P
• za odreĎeno stanje i ulaz jednoznačno je odreĎeno su stanja odbijanja.
sledeće stanje => deterministički konačni automat (DKA)
Programski prevodioci © 2004-2009 Dragan Bojić 5 Programski prevodioci © 2004-2009 Dragan Bojić 6

1
Graf prelaza konačnog automata Algoritam rada DKA
•Algoritam rada automata:
0
tekuće_stanje := St; { St – startno stanje}
1
0 0 tekući_ulaz := prvi simbol ulazne sekvence;
A D B •Čvorovi: stanja while not (kraj ulazne sekvence)
•Grane: prelazi tekuće_stanje := ( tekuće_stanje, tekući ulaz );
1 0
1
1 0
tekući_ulaz := sledeći znak ulazne sekvence;
•Stanja prihvatanja: end while;
1 1 poduplano if ( tekuće_stanje  P ) {P – skup stanja prihvatanja}
F C E then ulazna sekvenca se prihvata;
0 else ulazna sekvenca se ne prihvata;
endif;

Programski prevodioci © 2004-2009 Dragan Bojić 7 Programski prevodioci © 2004-2009 Dragan Bojić 8

Jezik konačnog automata Skener u obliku DKA


Konceptualni primer: skener za tokene id, num, lp, gtr, geq
• Jezik L(K) automata K = skup svih sekvenci ulaznih simbola "" letter
koje automat prihvata. 0 letter
 1 Ulazni niz: max >= 30
Primer: id digit
 rad automata za ulaz 0110 s0 m a x s1 • Prepoznat id
0 digit 2 digit
A

0
D

1
C

1
F

0
E
1
0 0
num s0 > = s5 • Preskače beline na početku
A D B  završno stanje E je stanje ( 3 • Prolazi kroz stanje 4
prihvatanja  0110 pripada
1 jeziku L(K) automata K
lp • Prepoznat geq
1 0 1 0 > =
Probanjem:
4 5 s0 3 0 s2 • Preskače beline na početku
{1011, 0011, 011011,
gtr
... geq
F
1
C
1
E • Prepoznat num
011011011,...}  L(K)
0 {0, 00, 00111, 1, 11, 111,
1111,...}  L(K) Posle svakog prepoznatog tokena skeniranje kreće ponovo od s0 .

Programski prevodioci © 2004-2009 Dragan Bojić 9 Programski prevodioci © 2004-2009 Dragan Bojić 10

Nedeterministički konačni automati


a,b

 a b b

Nedeterministički konačni automati  S0 S1 S2 S3 S4

Specifičnosti automata:
 S0 ima prelaz za  (tzv. prazna sekvenca, automat može da
preĎe iz s0 u s1 a da pri tom ne konzumira nijedan simbol
sa ulaza)
 S1 ima dva različita prelaza za a
U pitanju je nedeterministički konačni automat (NKA)

©2004-2009 Dragan Bojić 11 Programski prevodioci © 2004-2009 Dragan Bojić 12

2
Nedeterministički konačni automat Rad datog NKA za ulaz abb
Opisan je ureĎenom petorkom (S, U, , St, P) gde: a,b

  S predstavlja skup stanja automata, za dati primer {s0,  a b b


 S0 S1 S2 S3 S4
s1,s2,s3,s4,error}
  U predstavlja skup ulaznih simbola (azbuku automata), U  a b b
S0 S1 S2 S3 S4 prihvata?
= {a, b}  a b b
  : S x (U  {})  P(S) predstavlja funkciju prelaza (P -
S0 S1 S1 S1 S1 odbija?
a b b
partitivni skup); za svako stanje i svaki ulazni simbol S0 error error error odbija?
definiše skup SN  S mogućih novih stanja u koje automat itd
može preći iz stanja s  S za ulazni simbol u  U ili za  Generalno, NKA prihvata ulaznu sekvencu x ako i
simbol prazne sekvence  samo ako za x postoji scenario promene stanja iz
  St  S je skup startnih stanja automata. St = {s0}
nekog od startnih stanja do nekog od stanja
prihvatanja
  P  S predstavlja skup stanja prihvatanja, u konkretnom
slučaju P = {s4}. Stanja iz skupa S-P nazivaju se stanjima  U ovom primeru, NKA prihvata sekvencu abb
odbijanja.
Programski prevodioci © 2004-2009 Dragan Bojić 13 Programski prevodioci © 2004-2009 Dragan Bojić 14

Algoritam rada NKA Algoritam rada NKA


•Moramo voditi evidenciju, u svakom koraku rada automata, o
Za dati NKA i datu ulaznu sekvencu na izlazu daje podatak da li se
sekvenca prihvata ili odbija. skupu svih mogućih stanja u kojima se automat može nalaziti.
Algoritam koristi funkciju -zatvaranja:
tekući_skup_stanja := St;
-closure(s) daje skup stanja dostižnih iz s po 
tekući ulaz := prvi simbol ulazne sekvence;
Napomena: s je uključeno u skup while not (kraj ulazne sekvence)
novi_skup_stanja := ;
1. S’’ = S’ = {s} for ( s  tekući_skup_stanja)
2. Za svako p iz S’ novi_skup_stanja:=novi_skup_stanja  (s,tekući_ulaz);
3. S’’ = S’’  (p, ) end for;
tekući_skup_stanja := -closure(novi_skup_stanja);
4. Ako je S’’ = S’ onda kraj, rezultat je S’’ tekući_ulaz := novi simbol ulazne sekvence;
5. S’ = S’’; end while;
6. Idi na korak 2 if (tekući_skup_stanja  P  )
then ulazna sekvenca se prihvata;
else ulazna sekvenca se ne prihvata;
end if.
Programski prevodioci © 2004-2009 Dragan Bojić 15 Programski prevodioci © 2004-2009 Dragan Bojić 16

Rad datog NKA za ulaz abb Odnos NKA i DKA


a,b

 a b b DKA je specijalan slučaj NKA


 S0 S1 S2 S3 S4
 DKA ima tačno jedno startno stanje

 DKA nema  prelaza


a b b  Funkcija prelaza DKA ima jedinstvenu vrednost
s0 s1 s1 s2 s1 s3 s1 s4 prihvata zbog s4  Uvek se može konstruisati DKA koji je ekvivalentan
(prepoznaje isti jezik) kao zadati NKA:
-closure(s0)  Svako stanje DKA je skup mogućih stanja NKA do

kojih NKA može doći u toku rada


 Moguće eksponencijalno povećanje broja
stanja

Programski prevodioci © 2004-2009 Dragan Bojić 17 Programski prevodioci © 2004-2009 Dragan Bojić 18

3
NKA DKA
Algoritam koristi istu ideju kao algoritam rada NKA, samo
što ne posmatra jednu ulaznu sekvencu, nego sistematski
odreĎuje tabelu prelaza DKA.

Konverzija NKA u DKA Algoritam:


1. Neka je s0 startno stanje NKA.
2. Odrediti S0 = -closure(s0) koje postaje startno stanje DKA
3. novo_stanje_DKA = {}
4. Za svako s iz S0,
5. Za svako  iz ulazne azbuke:
novo_stanje_DKA = novo_stanje_DKA  -closure ((s, ))
6. Označiti novo_stanje_DKA kao stanje prihvatanja, ako u svom skupu
sadrži bar jedno stanje prihvatanja NKA
7. Iterativno ponavljati tačke 3-6 za sva dobijena stanja, dok postoji
promena u skupu stanja DKA.

©2004-2009 Dragan Bojić 19 Programski prevodioci © 2004-2009 Dragan Bojić 20

NKA DKA prethodni primer NKA DKA prethodni primer (2)


b Rezultujući DKA
 q4 q5 
 q0 a
q1    b
q2 q3 q8 q9
a b c
 q6 c 
q7
 s0 s1 - - 0

s2 s1 - s2 s3 1
OdreĎivanje ekvivalentnog DKA b
a s2 - s2 s3 1
stanja stanja -zatvaranje q1  s0 s1 b c s3 - s2 s3 1
DKA NKA
a b c c Stanja s1, s2, s3 se ponašaju isto pa
 s0 q0 q 1, q 2, q 3, 0 s3
q 4, q 6, q 9 se mogu objediniti (tzv. minimizacija
s1 q 1, q 2, q 3, q 5, q 8, q 9, q 7, q 8, q 9,
q 4, q 6, q 9 q 3, q 4, q 6 q 3, q 4, q 6 1 c automata, biće obraĎena na
s2 q 5, q 8, q 9, s2 s3 1 vežbama)
q 3, q 4, q 6 b|c
s3 q 7, q 8, q 9, s2 s3 1 a
q 3, q 4, q 6  S0 S1

Samo tamo gde se u skupu stanja NKA


nalazi završno stanje q9
Programski prevodioci © 2004-2009 Dragan Bojić 21 Programski prevodioci © 2004-2009 Dragan Bojić 22

Regularni izrazi
 Alternativni formalizam za opis jezika
Regularni izrazi opisuju tačno isti skup
Regularni izrazi

jezika kao konačni automati:
 Za svaki regularni izraz može se naći
konačni automat koji opisuje isti jezik kao
taj izraz
 Za svaki konačni automat može se naći
regularni izraz koji opisuje isti jezik kao taj
automat

©2004-2009 Dragan Bojić 23 Programski prevodioci © 2004-2009 Dragan Bojić 24

4
Definicija regularnog izraza Definicija regularnog izraza (2)
 Regularni izraz s opisuje regularni skup nizova  složeniji regularni izrazi dobijaju se od regularnih izraza A i
B primenom operacija:
znakova L(s).
 Opcije A?, L(A?) = L(A)  {}
 Regularni izrazi definišu se na sledeći način:  unije A|B, L(A|B) = L(A)  L(B) = {x | x  A ili x  B}
  je regularan izraz koji opisuje prazan skup L()=.  konkatenacije (nadovezivanja) AB ili AB
L(AB)=L(A) x L(B)={xy | x  A, y  B}
  je regularan izraz koji opisuje skup {} L()={}. Konvencija:
A A
n
  ...
A A A 0  {ε}
(sekvenca dužine nula znakova, tzv. prazna sekvenca)
zvezdastog zatvaranja A*
n
 niz znakova n je regularni izraz koji opisuje skup {n} 
A*=A0|A1|A2|A3|… (beskonačan broj članova)
L(n)={n}.
 pozitivnog zatvaranja A+
A+ = A1|A2|A3|…

Programski prevodioci © 2004-2009 Dragan Bojić 25 Programski prevodioci © 2004-2009 Dragan Bojić 26

Primeri regularnih izraza


 L(abc)={abc} L(a | b | c)={a, b, c}
 L[(a | b)(c | d)]={ac, ad, bc, bd} male zagrade
su obavezne zbog prioriteta
Konstrukcija konačnog automata iz
 L(a*)={, a, aa, aaa, …} regularnog izraza
 L[(a | b)+]={a, b}  {a, b} x {a, b}  {a, b} x
{a, b} x {a, b}  …={a,b}  {aa, ab, ba, bb} 
{aaa, aab, aba, abb, baa, bab, bba, bbb} ...=
{a, b, aa, ab, ba, bb, …} = svi mogući nizove
slova a i b dužine 1 ili više
 Slovo =A | B |…| Z | a | b |…| z
Cifra = 0 | 1 |…|9
Identifikator = Slovo ( Slovo | Cifra )*

Programski prevodioci © 2004-2009 Dragan Bojić 27 ©2004-2009 Dragan Bojić 28

Tompsonov algoritam Primer primene Tompsonovog algoritma


Zadati reg. Izraz: a ( b | c )*, krećemo od osnovnih
 Za zadati reg. izraz odreĎuje nedeterministički komponenata pa kombinujemo u veće podizraze:
konačni automat a b c
1. a, b, & c S0 S1 S0 S1 S0 S1
a a  b
S0 S1 S0 S1 S3 S4
b
NKA for ab S1 S2 
NKA for 
a S0 S5
2. b | c  S3
c
S4 
a 
S1 S2
 
 a  
S0 S5 S0 S1 S3 S4
 b   b
S3 S4  S2 S3 
 
NKA for a* S0 S1 S6 S7
NKA for a | b
3. ( b | c )*  S4
c
S5 

Ken Thompson, CACM, 1968 

Programski prevodioci © 2004-2009 Dragan Bojić 29 Programski prevodioci © 2004-2009 Dragan Bojić 30

5
Primer primene Tompsonovog algoritma 2 Automatizacija konstrukcije skenera
4. a ( b | c )*  Formalna metodologija dobijanja programskog
 S4
b
S5 
koda na osnovu specifikacije jezika:
 S0
a
S1

S2

S3 S8

S9 1 Napisati RE za zadati ulazni jezik
 S6
c
S7  2 Konstruisati NKA za dati RE Tompsonovim
 alg.
3 Konstruisati DKA ekvivalentan dobijenom NKA
Posle konverzije u DKA i minimizacije broja stanja: 4 (Po potrebi) odrediti minimalan DKA
b|c
5 Implementirati DKA iz tačke 4. programom
a
 S0 S1
Generatori skenera rade po opisanom principu:
 Lex, Flex, jlex, jflex,...

Programski prevodioci © 2004-2009 Dragan Bojić 31 Programski prevodioci © 2004-2009 Dragan Bojić 32

6

Neposredno konvertovanje regularnog



izraza u DKA 5

Odredićemo DKA za regularni izraza (A | (BC)*)D─┤  D


4
Sintaksno stablo za dati izraz:
poništivi

A 
1

 D B C
2 3
 Prva pozicija za svaki čvor stabla predstavlja skup
pozicija listova koji se mogu pojaviti na prvom mestu
A  sekvence koju generiše podizraz sa korenom u datom
čvoru. Računanje prvih pozicija:

 1. prva_pozicija(ab) =
 prva _ pozicija(a), a nije poništiv

 prva _ pozicija(a)  prva _ pozicija( b), a je poništiv
B C

2. prva_pozicija(a|b) = prva_pozicija(a) 
 Pozicijama se označavaju listovi sintaksnog stabla
prva_pozicija(b)
(osim ) redom pri obilasku stabla sa leva u desno.
3. prva_pozicija(a*) = prva_pozicija(a).

 Poslednja pozicija za svaki čvor stabla predstavlja skup
pozicija listova koji se mogu pojaviti na poslednjem
 mestu sekvence koju generiše podizraz sa korenom u
5 datom čvoru. Računanje poslednjih pozicija:
1. poslednja_pozicija(ab) =
 D  poslednja _ poz.(b), b nije poništiv

 poslednja _ poz.(b)  poslednja _ poz.(a), b je poništiv
4
pozicija

A  2. poslednja_pozicija(a|b) = poslednja_pozicija(a) 
1 poslednja_pozicija(b)
 3. poslednja_pozicija(a*) = poslednja_pozicija(a).
{1,2,4}  {5}
B C
2 3 {1,2,4}  {4} {5} {5}
5
 Čvor sintaksnog stabla je poništiv ako podizraz sa
korenom u datom čvoru može generisati praznu
sekvencu. Računanje poništivosti: {1,2}  {1,3} {4} D {4}
1. Listovi nisu poništivi, osim ako su označeni sa . 4

2. Čvor konkatenacije  je poništiv ako su oba njegova poništiv


naslednika poništiva. {1} A {1} {2}  {3}
1
3. Čvor unije | je poništiv ako je bar jedan od njegovih
prva
naslednika poništiv. {2}  {3} pozicija
4. Čvor zvezdastog zatvaranja * je uvek poništiv.
poslednja
{2} B {2} {3} C {3} pozicija
2 3
 Sledeća pozicija(p) definiše se za svaku poziciju lista p
kao skup pozicija koje mogu slediti posmatranu poziciju
p u proizvoljnoj sekvenci znakova izvedenoj iz datog
regularnog izraza. Pri računanju funkcije sledeća
pozicija u sintaksnom stablu razmatraju se svi čvorovi
tipa  i * na sledeći način:
 Čvor : prva pozicija desnog naslednika je sledeća
pozicija za sve iz poslednje pozicije levog naslednika.
 Čvor *: prva pozicija naslednika je sledeća pozicija za
sve iz poslednje pozicije naslednika.
poz. sled. pozicija
1 {4}
2 {3}
3 {2,4}
4 {5}
5 /

 Stanja automata  skupovi pozicija listova sintaksnog


stabla.
 Startno stanje = prva_pozicija korena stabla
 Stanja prihvatanja su ona koja sadrže poziciju markera
kraja.
Vrsta tabele prelaza, koja je prikazana na slici, za odreĎeno
stanje popunjava se razmatrajući pojedine pozicije iz skupa
pridruženog tom stanju. Na primer, za stanje {1, 2, 4}:
 popunjavanje tabele prelaza: vrsta {1, 2, 4}, ulaz A
{1, 2 , 4}
 izdvojiti samo pozicije koje se
odnose na simbol A
{1}
 za svaku poziciju proračunati
sledeću poziciju pa unija
{4} – upisati u tabelu
prelaza
A B C D
 {1, 2, 4} {4} {3} {} {5} 0
{4} {} {} {} {5} 0
{3} {} {} {2, 4} {} 0
{} {} {} {} {} 0
{5} {} {} {} {} 1
{2, 4} {} {3} {} {5} 0
 Prepoznavači i procesori
Programski prevodioci IR4PP1  Implementacija konačnih automata

Lekcija 3 – Konačni procesori

©2006 Dragan Bojić 1 Programski prevodioci © 2006 Dragan Bojić 2

Konačni procesori Konstrukcija konačnog procesora


 Prepoznavač : binarna odluka – ulazna  Prepoznavač pretvaramo u procesor na taj način što
sekvenca se prihvata ili odbija svakom (nepraznom) ulazu u tabeli prelaza
pridružujemo AKCIJU (proizvoljnu sekvencu
 Procesor – pored prepoznavanja ulazne programskog koda).
sekvence vrši i neku dodatnu obradu kao  Ulaznu azbuku automata možemo proširiti simbolom
bočni efekat, kraja ulazne sekvence (end marker) ─┤koji se javlja
 Primeri dodatne obrade u kontekstu jednom u ulaznoj sekvenci, uvek i isključivo na
prevođenja programa: njenom kraju. Praktični razlozi.
 Praznim ulazima, po potrebi, možemo pridružiti akcije
 Izračunavanje binarne vrednosti konstante
za detekciju i oporavak od leksičkih grešaka.
 Smeštanje simbola u tabelu simbola

Programski prevodioci © 2006 Dragan Bojić 3 Programski prevodioci © 2006 Dragan Bojić 4

Primer Primer...

 Treba konstruisati deterministički  Procesor izračunava binarnu vrednost konstante


postavljajući sadržaje sledeća četiri registra:
procesor za izračunavanje vrednosti  NR (number register) sadrži binarnu vrednost celog broja
neoznačenih realnih konstanti. koji se dobija uklanjanjem decimalne tačke iz mantise;
ER (exponent register) sadrži binarnu vrednost
Primeri dozvoljenih konstanti su:

 eksponenta koji je naveden u konstanti (ne vrši se
1257,.0392, 1E + 534, 1., 1.E5, 2.0E10 normalizacija mantise);
 CR (count register) sadrži broj cifara iza decimalne tačke;
 a nedozvoljenih -21, .E3, E, E10,  SR (sign register) pamti predznak eksponenta ( +1 ili -1)
12E.  Na primer, za konstantu 12.3E4 registri će imati sledeće
vrednosti:
NR ER CR SR
123 4 1 +1
Programski prevodioci © 2006 Dragan Bojić 5 Programski prevodioci © 2006 Dragan Bojić 6

1
1. korak – Konstruisanje prepoznavača 2. korak - dodavanje akcija
 Ulazna azbuka {DIGIT, •, E, SIGN}
 prelazi razmatranjem karakterističnih primera ulaza DIGIT E • SIGN ─┤
3 8 . 7 E - 3 . 9 E 21 0 1a 7
0 1 1 2 3 4 5 6 0 7 3 4 6 6 1 1b 4a 23c YES1
DIGIT E • SIGN 23 23a 4b YES2
inicijalno stanje 0 1 7 0 4 6a 5
cifra pre opcione tačke 1 1 4 2 1 5 6b
opciona decimalna tačka 2 3 4 1 6 6c YES3
cifra nakon decimalne tačke 3 3 4 1 7 23b
slovo E 4 6 5 0
predznak eksponenta 5 6 0
cifra eksponenta 6 6 1
tačka iza koje mora ići cifra 7 3 0
Programski prevodioci © 2006 Dragan Bojić 7 Programski prevodioci © 2006 Dragan Bojić 8

Akcije imaju sledeći izgled


 Operator val(cifra) daje binarnu vrednost cifre  Prepoznavači i procesori
1a: NR := val(DIGIT) 4a: CR := 0  Implementacija konačnih automata
1b: NR := NR*10+val(DIGIT) 4b: ––––––
23a: CR := CR + 1 5: SR := val(SIGN)
NR := NR*10+val(DIGIT) 6a: SR := +1
23b: CR := 1 ER := val(DIGIT)
NR := val(DIGIT) 6b: ER := val(DIGIT)
23c: CR := 0 6c: ER := ER * 10 + val(DIGIT)
7: –––––– YES2: ER := 0
YES1: ER := 0 YES3: ––––––
CR := 0
Programski prevodioci © 2006 Dragan Bojić 9 Programski prevodioci © 2006 Dragan Bojić 10

Varijante implementacije KA Primer


 Pod implicitnom predstavom stanja  Želi se realizovati na C-u konačni
podrazumeva se da je stanje određeno automat sa slike koristeći implicitno i
mestom u programu koji se izvršava. eksplicitno predstavljanje stanja.
 U eksplicitnoj predstavi, postoji
promenljiva (tekuce) koja pamti tekuće a b ─┤
stanje pri radu automata. A B NO YES
 Objektno-orijentisana implementacija – B A B NO
projektni uzorak State.

Programski prevodioci © 2006 Dragan Bojić 11 Programski prevodioci © 2006 Dragan Bojić 12

2
Implicitno predstavljanje stanja Eksplicitno predstavljanje stanja
enum Boolean DKA(char *ulaz) {
#include<stdio.h> enum Boolean DKA(char *ulaz) { #include<stdio.h> enum Stanje {A,B,NO1,YES1};
#define ENDM '\0' /*marker kraja */ A: switch (*ulaz++) { #define ENDM '\0' /*marker kraja */ enum Stanje tabela[2][3] =
case 'a': goto B; {B,NO1,YES1,A,B,NO1};
enum Boolean {NO, YES}; enum Boolean {NO, YES};
case 'b': return NO; int znak, tekuce=A;
case ENDM: return YES; while(1) {
enum Boolean DKA(char *ulaz){…} enum Boolean DKA(char *ulaz){…}
default: return NO; switch (*ulaz++) {
} case 'a': znak=0; break;
main () { main () {
B: switch (*ulaz++) { case 'b': znak=1; break;
char s[80]; char s[80];
case 'a': goto A; case ENDM: znak=2; break;
scanf("%s",s); scanf("%s",s);
case 'b': goto B; default: return NO;
printf("%u\n",DKA(s)); printf("%u\n",DKA(s));
case ENDM: return NO; }
} }
default: return NO; tekuce=tabela[tekuce][znak];
} if(tekuce>B) return tekuce-
NO1;
}
}
}
Programski prevodioci © 2006 Dragan Bojić 13 Programski prevodioci © 2006 Dragan Bojić 14

OO implementacija KA…
Objektno-orijentisana implementacija KA

 Želimo implementirati zadati automat


koristeći projektni uzorak State iz knjige
Gama,..."Design Patterns/Elements of
Reusable Object-Oriented Programming
Style".
a b
A A B 1
B B B 0

Programski prevodioci © 2006 Dragan Bojić 15

extern class StateB: public State // class Automat implementation


Automat::Automat(): tekuciUlaz( 0 ), tekuceStanje( &stateA ) {
{ strcpy( ulazniNiz, "" );
automat.h public:
StateB(Automat& a): State(a) {}
automat.cpp }
void Automat::PostaviUlaz( char* ulNiz ) {
class Automat; #include "automat.h" strcpy( ulazniNiz, ulNiz );
class State virtual void ObradiTekuciUlaz(); #include <iostream.h> }
#include <string.h> bool Automat::KrajUlaza() {
{ virtual bool Prihvata() { return false; } Automat automat; return ulazniNiz[tekuciUlaz] == '\0';
public: } stateB; StateA stateA(automat); }
State(Automat& a): automat(a) {} StateB stateB(automat); void Automat::ObradiTekuciUlaz() {
// class StateA implementation tekuceStanje->ObradiTekuciUlaz();
virtual bool Prihvata() = 0; extern class Automat { void StateA::ObradiTekuciUlaz() tekuciUlaz++;
virtual void ObradiTekuciUlaz() = 0; public: { }
protected: Automat();
char t = automat.TekuciUlaz(); char Automat::TekuciUlaz() {
if ( t == 'a' ) return ulazniNiz[tekuciUlaz];
Automat& automat;
void PostaviUlaz( char* ulNiz ); automat.PromeniStanje(stateA); }
}; else if ( t == 'b' ) void Automat::PromeniStanje( State& novoStanje ) {
bool KrajUlaza(); automat.PromeniStanje(stateB); tekuceStanje = &novoStanje;
extern class StateA: public State void ObradiTekuciUlaz(); } }
{ char TekuciUlaz(); // class StateB implementation State* Automat::TekuceStanje() {
void StateB::ObradiTekuciUlaz() return tekuceStanje;
public: State* TekuceStanje(); { }
StateA(Automat& a): State(a) {} void PromeniStanje(State& novoStanje); char t = automat.TekuciUlaz(); void main() {
if ( t == 'a' ) char ulazniNiz[100];
virtual void ObradiTekuciUlaz(); protected: automat.PromeniStanje(stateB); cin >> ulazniNiz;
virtual bool Prihvata() { return true; } char ulazniNiz[100]; else if ( t == 'b' ) automat.PostaviUlaz(ulazniNiz);
automat.PromeniStanje(stateA); while ( !automat.KrajUlaza() ) {
int tekuciUlaz; } automat.ObradiTekuciUlaz();
} stateA;
State* tekuceStanje; }
} automat; cout << automat.TekuceStanje()->Prihvata();
}

3
 Uloga sintaksno/semantičke analize
Programski prevodioci IR4PP1  Gramatike
 Višeznačnost gramatika
 Gramatike i regularni izrazi
Lekcija – Sintaksna analiza  Klasifikacija gramatika

©2006 Dragan Bojić 1 Programski prevodioci © 2006 Dragan Bojić 2

Uloga sintaksno-semantičke analize


Parsiranje,
Provera statičke semantike,
sintaksna & Generisanje interne reprezentacije  Uloga sintaksno/semantičke analize
sem. analiza Detekcija i oporavak od grešaka
 Gramatike
skener generator koda
 Višeznačnost gramatika
izdvaja tokene iz generiše mašinski kod
 Gramatike i regularni izrazi
tabela simbola
izvornog koda
 Klasifikacija gramatika
održava informacije o
deklarisanim imenima i tipovima

Poziva: sintaksno upravljano prevođenje


tok podataka

Programski prevodioci © 2006 Dragan Bojić 3 Programski prevodioci © 2006 Dragan Bojić 4

Bezkontekstna gramatika BNF Notacija


terminalni simboli pišu se bez zagrada (ident, +, -)
Bezkontektsna gramatika G opisana je uređenom neterminalni simboli pišu se u zagradama (<Expr>, <Term>)
četvorkom (VN, VT, P, <S>) gde: strane smene razdvajaju se sa ::= ili 
BNF gramatika za aritmetičke izraze
•VN predstavlja skup neterminalnih simbola, npr. VN = <Expr> ::= <Sign> <Term>
• Alternative su transformisane
{<S>, <A>, <B>}. <Expr> ::= <Expr> <Addop> <Term>
u posebne smene
<Sign> ::= +
•VT predstavlja skup terminalnih simbola, npr. <Sign> ::= - • Ponavljanje se mora izraziti
rekurzijom
VT = {a, b, c, d}. V = VT  VN predstavlja skup <Sign> ::=

gramatičkih simbola. <Addop> ::= +


<Addop> ::= - Prednosti
• manje meta simbola
•P predstavlja skup smena (produkcija) oblika <Term>
<Term>
::= <Factor>
::= <Term> <Mulop> <Factor> (bez |, (), [], {})
<X> , gde <X>  VN a  na predstavlja proizvoljan <Mulop> ::= * • Lakše napraviti sint. stablo
niz od nula ili više gramatičkih simbola. <Mulop> ::= / Mane
<Factor> ::= ident • više smena
•<S>  VN predstavlja startni neterminal. <Factor> ::= number
<Factor> ::= ( <Expr> )
Programski prevodioci © 2006 Dragan Bojić 5 Programski prevodioci © 2006 Dragan Bojić 6

1
EBNF Notacija Primer: Gramatika za aritmetičke izraze
Extended Backus-Naur form John Backus: razvio prvi Fortran compiler Smene
Peter Naur: editovao Algol60 speficikaciju
(BNF + reg. izrazi) Expr = [ "+" | "-" ] Term { ( "+" | "-" ) Term }.
simbol značenje primeri Term = Factor { ( "*" | "/" ) Factor }. Expr
Factor = ident | number | "(" Expr ")".
string Predstavlja “sam sebe” "=", "while"
ime predstavlja T ili NT simbol ident, Statement Terminalni simboli
= razdvaja strane smene A= b c d . Obični TS: "+", "-", "*", "/", "(", ")" Term
. završava smenu (samo 1 instanca)
| Razdvaja alternative a | b | c značenje a or b or c
klase TS: ident, number
(...) grupiše alternative a ( b | c ) značenje ab | ac
(više instanci) Factor
[...] opcioni deo [a]b značenje ab | b
{...} { a } b značenje b | ab | aab | aaab | ... Neterminalni simboli
ponavljajući deo
Expr, Term, Factor
Konvencije
Startni simbol
• Terminalni simboli počinju malim slovom (npr. ident)
Expr
• Neterminalni simboli počinju velikim slovima (npr. Statement)
Programski prevodioci © 2006 Dragan Bojić 7 Programski prevodioci © 2006 Dragan Bojić 8

Terminologija Terminologija (nastavak)


 Alfabet posmatrane gramatike – skup terminala VT
 + izvođenje u jednom ili više koraka
 Sentencijalna forma – proizvoljan niz gramatičkih
simbola     ...  
 oznaka , ,.... ili ABCD, XYZ, ...  * naziva se izvođenje u nula ili više koraka.
 Sentenca – sekvenca terminalnih simbola opisanih  Redukcija – obrnuto od izvođenja, zamena desne
gramatikom strane smene levom u nekoj sent. formi
 Oznaka uvw, ...
 Jezik opisan gramatikom G, u oznaci L(G) predstavlja
 Gramatičko izvođenje, u oznaci skup svih sentenci koje se mogu izvesti iz startnog
 <X>      neterminala <S> u nula ili više koraka izvođenja:
predstavlja primenu neke gramatičke smene <X>   da bi se u
nekom nizu gramatičkih simbola (takozvanoj sentencijalnoj formi) L(G) = {x | <S> * x, x  VT*}
 <X>  zamenilo pojavljivanje leve strane smene odgovarajućom
desnom stranom.

Programski prevodioci © 2006 Dragan Bojić 9 Programski prevodioci © 2006 Dragan Bojić 10

Primer Terminologija (nastavak)


Gramatika G1:  levo izvođenje (engl. leftmost derivation) - u svakom
1. <S>  a <A> c <B> koraku izvođenja zamenjivan prvi neterminal s leve
2. <S>  <B> d <S> strane
Izvođenje:
3. <B>  a <S> c <A> <S> lm a <A> c <B> lm a a c <B> lm a a c b
4. <B>  c <A> <B> S  a A c B  a a c B  a a c b  desno izvođenje (engl. rightmost derivation) - u
  
5. <A>  <B> a <B> svakom koraku izvođenja zamenjuje se krajnje desni
1 7 8
6. <A>  a <B> c neterminal u sentencijalnoj formi
7. <A>  a
aacb  L(G1) <S> rm a <A> c <B> rm a <A> c b rm a a c b
8. <B>  b
 Parser je procedura koja na osnovu date gramatike
utvrđuje, za zadatu sekvencu, pripadnost sekvence
jeziku opisanom datom gramatikom i njeno izvođenje
iz startnog neterminala
Programski prevodioci © 2006 Dragan Bojić 11 Programski prevodioci © 2006 Dragan Bojić 12

2
Terminologija (nastavak)
 Stablo izvođenja je Uloga sintaksno/semantičke analize
grafička predstava S  a A c B  a a c B  a a c b 
  
izvođenja 1 7 8  Gramatike
 Izvođenje <X>  Y Z
<S>  Višeznačnost gramatika
V se u stablu izvođenja  Gramatike i regularni izrazi
predstavlja na taj način <A> c <B>
što čvor <X> ima a  Klasifikacija gramatika
čvorove naslednike Y,
Z i V navedenim a b
redosledom..

Programski prevodioci © 2006 Dragan Bojić 13 Programski prevodioci © 2006 Dragan Bojić 14

Višeznačnost gramatike Otklanjanje višeznačnosti


Ako je gramatika višeznačna, za jednu sentencu moguće je odrediti Primer
više različitih stabala izvođenja
<T>  <F> | <T> * <T>
Primer
<F>  id
<T>  <F> | <T> * <T> sentenca: id * id * id Jezik nije dvosmislen, samo gramatika
<F>  id
Gramatika se može transformisati u
Za ovu sentencu moguće je konstruisati dva sintaksna stabla: Tako da <Т> ima veći prioritet od <F>
<T>  <F> | <T> * <F>
<T> <T> <F>  id Sada postoji samo jedno sintaksno stablo
<T> <T> <T>
<T> <T> <T> <T> <T> <T> <T>
<F> <F> <F> <F> <F> <F> <T>
id * id * id id * id * id
<F> <F> <F>
id * id * id
Ovo je nepoželjno svojstvo pri prevođenju.

Programski prevodioci © 2006 Dragan Bojić 15 Programski prevodioci © 2006 Dragan Bojić 16

Dvosmislenost u prog. jezicima Dvosmislenost u prog. jezicima (2)

Primer: Dangling Else (viseće Else) Primer: Dvosmislenost kao posledica preklapanja identifikatora
<Stmt>  if <Expr> then <Stmt> a = f(17)
| if <Expr> then <Stmt> else <Stmt>
| other Stmts Da li je f funkcija, ili vektor (u npr. Algolu)?
Razmotrimo sentencu: Da bi se ova dvosmislenost razrešila,
If E1 then if E2 then S1 else S2 neophodan je semantički kontekst:
Ova sentenca ima dva stabla izvođenja.
• potrebno je poznavati tip simbola f
Moguće rešenje (else se pridružuje najbližem neuparenom then)
<Stmt>  <Matched>
| <Unmatched>
<Matched>  if <Expr> then <Matched> else <Matched>
| other Stmts
<Unmatched>  if <Expr> then <Stmt>
| if <Expr> then <Matched> else <Unmatched>
Programski prevodioci © 2006 Dragan Bojić 17 Programski prevodioci © 2006 Dragan Bojić 18

3
Ograničenja regularnih jezika

 Uloga sintaksno/semantičke analize  Nisu svi formalni jezici regularni


 Gramatike  Na primer, ne mogu se konstruisati KA za
 Višeznačnost gramatika jezike:
 Gramatike i regularni izrazi  L = {pkqk}, k>0
 L = {wcwr | w* }
 Klasifikacija gramatika
 (ovo nisu reg. izrazi. KA ne može da odbrojava)

Programski prevodioci © 2006 Dragan Bojić 19 Programski prevodioci © 2006 Dragan Bojić 20

Regularne gramatike Regularne gramatike i KA


 Za svaki regularni izraz r može se naći  Algoritam transformacije KA u regularnu gramatiku:
bezkontekstna gramatika g, tako da  Terminalnim simbolima odgovaraju ulazni simboli

L(r) = L(g) automata.


 Obrnuto ne važi, osim za:  Neterminalnim simbolima odgovaraju stanja

 Gramatike koje opisuju regularne jezike automata. Startnom neterminalu odgovara startno
nazivaju se regularnim gramatikama. stanje automata.
 Proizvoljnom prelazu automata iz stanja A u stanje
 Definicija:
B pod ulazom x, odgovara smena <A>  x<B>.
 Svaka smena regularne gramatike ima jedan
 Proizvoljno stanje prihvatanja A indukuje
od sledeća dva oblika: dodavanje smene: <A>  .
 1. <A>  b <C>
 2. <A>    - prazna sekvenca
Programski prevodioci © 2006 Dragan Bojić 21 Programski prevodioci © 2006 Dragan Bojić 22

Primer: KA => regularna gramatika Desno-linearne gramatike


0 1  Takođe opisuju regularne jezike
A A, B E 0 1. <A>  0<A> 9. <C>  1<C>
B E C 1 2. <A>  0<B> 10. <D>   svaka smena desno-linearne gramatike
3. <A>  1<E> 0<E>
C C B, C 0 4. <B>  0<E> 11. <D>  je oblika:
D E C, D 1 5. <B>  1<C> 1<C>
6. <B>   12. <D> 
 <A>  w<B> ili
E E E 0
7. <C>  0<C> 1<D>  <A>  w
8. <C>  1<B> 13. <D>  
14. <E>  0 gde je w proizvoljna sekvenca od nula
<E>
• Postupak reg. gramatika => KA analogno
15. <E>  1 ili više terminala.
<E>

Programski prevodioci © 2006 Dragan Bojić 23 Programski prevodioci © 2006 Dragan Bojić 24

4
Transformacija desno-linearne u
regularnu gramatiku Primer transformacije
 Primenom tri pravila: <A>  <B>
<B>  1 <A>  1 1. <A>  ab<B> 4. <B>  <A>
1. <A>  ab<B>
<A>  w zameniti sa <A>  w<> <B>  2 zameniti sa <A>  2 2. <A>  ac<> 5. <B>  
w – terminali <>   ... ... 2. <A>  ac
<> je novo uvedeni neterminal <B>  n <A>  n 3. <B>  <A> 3. <>  

prethodno ukloniti smenu <B> 


4. <B>  
1. <A> a <bB> 5. <>  
<B> ako eventualno postoji.
2. <bB> b <B> 6. <B>  <A>
<A>  a1 <a2...anB> 3. <A> a <C>
<a2...anB>  a2 <a3...anB> 7. <B>  
4. <C> c <>
<A>  a1a2...an <B> zameniti sa ...
n>1 <an-1anB>  an-1 <anB>
<anB>  an <B>
1. <A> a <bB> 5. <>  
2. <bB> b <B> 6. <B>  a <bB>
<a2...anB>, <a3...anB>, ..., <an-1anB>, <anB> 3. <A> a <C> 7. <B>  a <C>
– novouvedeni neterminali.
4. <C> c <> 8. <B>  
Programski prevodioci © 2006 Dragan Bojić 25 Programski prevodioci © 2006 Dragan Bojić 26

Klasifikacija gramatika
Noam Chomsky (1956)

 Uloga sintaksno/semantičke analize Gramatike su skupovi smena opšteg oblika   .


klasa 0 Neograničene gramatike ( i  proizvoljni)
 Gramatike npr: <A>  a <A> b | <B> c <B>
a<B>c  d <A>  a<A>b  a<B>c<B>b  d<B>b  bbb
 Višeznačnost gramatika d<B>  bb
Prepoznaju se Tjuringovim mašinama
 Gramatike i regularni izrazi klasa 1 Kontekstne gramatike (||  ||)
npr: a <A>  a b c
 Klasifikacija gramatika Prepoznaju se linearno ograničenim automatima
klasa 2 Context-free grammars ( = NT)
npr: <A>  a b c.
Prepoznaju se potisnim automatima Samo ove dve klase
su relevantne za
klasa 3 Regularne gramatike ( = NT,  =  | T NT) konstrukciju
npr: <A>   | b <B>. prevodilaca
Prepoznaju se konačnim automatima
Programski prevodioci © 2006 Dragan Bojić 27 Programski prevodioci © 2006 Dragan Bojić 28

5
 Uvod
Programski prevodioci 1  BU parser u vidu potisnog automata
 SHIFT-REDUCE Parsiranje
 Konstrukcija LR(0) parsera
Lekcija – Parsiranje od dna ka  Konflikti u SHIFT-REDUCE parsiranju
vrhu, prvi deo

©2006 Dragan Bojić 1 Programski prevodioci © 2006 Dragan Bojić 2

Pojam parsera Strategije parsiranja

 Parser: algoritam koji utvrđuje, za  Od vrha ka dnu (engl. top-down):


zadatu ulaznu sekvencu, da li pripada parser konstruiše stablo izvođenja
jeziku zadate gramatike. počev od korena ka listovima
 Ako pripada, parser određuje izvođenje  Od dna ka vrhu (engl. bottom-up):
posmatrane ulazne sekvence iz startnog parser konstruiše stablo izvođenja
neterminala gramatike. počev od listova ka korenu

Programski prevodioci © 2006 Dragan Bojić 3 Programski prevodioci © 2006 Dragan Bojić 4

Potisni automat (pushdown automaton)

 Uvod  Neformalno: potisni automat = konačni


 BU parser u vidu potisnog automata automat + stek
 SHIFT-REDUCE Parsiranje  PA su jednako "jak" formalizam za opis
 Konstrukcija LR(0) parsera jezika kao bezkontekstne gramatike
 Konflikti u SHIFT-REDUCE parsiranju

Programski prevodioci © 2006 Dragan Bojić 5 Programski prevodioci © 2006 Dragan Bojić 6

1
Primer Rad potisnog automata
1. <S> <S> <S> a  Automat startuje sa definisanom startnom
2. <S>  <S> b konfiguracijom steka ().
3. <S>  <S> <S> <S> c
 Automat skenira sekvencu koja se sastoji od ulaznih
4. <S> d simbola a,b,c,d,-| s leva na desno, znak po znak.
a b c d -|  U svakom koraku rada, akcija automata se određuje
 SHIFT ACCEPT čitanjem kontrolne tabele (reprezentuje kontrolnu
<S> SHIFT SHIFT SHIFT funkciju), za tekući vrh steka i tekući ulazni simbol (i
tekuće stanje, u slučaju da ima više stanja).
a REDUCE(1) REDUCE(1) REDUCE(1) REDUCE(1) REDUCE(1)  Akcija se sastoji od ažuriranja ulaza, steka i stanja.
b REDUCE(2) REDUCE(2) REDUCE(2) REDUCE(2) REDUCE(2)
c REDUCE(3) REDUCE(3) REDUCE(3) REDUCE(3) REDUCE(3)
d REDUCE(4) REDUCE(4) REDUCE(4) REDUCE(4) REDUCE(4)

Programski prevodioci © 2006 Dragan Bojić 7 Programski prevodioci © 2006 Dragan Bojić 8

Formalna definicija potisnog Formalna definicija potisnog


automata automata (nastavak)
 Potisni automat definisan je uređenom šestorkom (U,  c: (U  {─┤})  Y  S  O predstavlja
Y, Ys, S, St, c) gde:
 U – skup ulaznih simbola. Primer: U = {a, b,c,d,-|}. kontrolnu funkciju koja za svaki ulazni
 Y – skup simbola steka. Npr. Y = {<S>,a,b,c,d,}. simbol (kojima se, iz praktičnih razloga,
 Ys – početna konfiguracija steka i definisana je dodaje marker kraja ulazne sekvence
sekvencom simbola steka koja počinje simbolom .
Simbol  naziva se dnom steka. ─┤), svaki simbol steka i svako stanje
 S – skup stanja potisnog automata. Primer: S = {S0}. definiše određeni element skupa svih
Napomena: nas interesuju isključivo potisni mogućih operacija potisnog automata
automati sa jednim stanjem.
 St  S – startno stanje automata. O = Oy  S  Ou  {ACCEPT, REJECT},

Programski prevodioci © 2006 Dragan Bojić 9 Programski prevodioci © 2006 Dragan Bojić 10

Operacije potisnog automata Operacije potisnog automata


Nad stekom:  Nad ulaznom sekvencom:
 Oy = {POP, PUSH(x), nepromenjen  Ou = {ADVANCE, RETAIN}
stek} je skup mogućih operacija nad
stekom:  ADVANCE označava prelaz na sledeći
ulazni simbol
 POP označava skidanje jednog simbola
sa steka  RETAIN označava da se tekući simbol
 PUSH(x) označava stavljanje simbola
ulaza ne menja
steka x na vrh steka

Programski prevodioci © 2006 Dragan Bojić 11 Programski prevodioci © 2006 Dragan Bojić 12

2
Operacije potisnog automata Operacije potisnog automata

 Za završetak rada: Prema tome, svaka operacija automata sastoji se iz:

 ACCEPT – kraj rada automata pri čemu  određene operacije nad stekom
se ulazna sekvenca prihvata (ili ACCEPT/REJECT),
 REJECT – kraj rada pri čemu se ulazna  promene stanja u određeno stanje s  S i
sekvenca odbija  određene operacije nad ulazom.

Programski prevodioci © 2006 Dragan Bojić 13 Programski prevodioci © 2006 Dragan Bojić 14

Algoritam rada potisnog automata Akcije u kontrolnoj tabeli BU parsera


tekuće_stanje := St;
Samo sledeće kombinacije se pojavljuju:
tekući_ulaz := prvi simbol ulazne sekvence;  ACCEPT - uspešan završetak parsiranja;
tekući_stek := Ys;
loop  REJECT - neuspešan završetak parsiranja.
if c( tekući_ulaz, tekući_stek, tekuće_stanje ) = ACCEPT  SHIFT:
then kraj rada uz prihvatanje ulazne sekvence;
else if c( tekući_ulaz, tekući_stek, tekuće_stanje ) = REJECT  PUSH(tekući_ulaz)
then kraj rada uz odbijanje ulazne sekvence  ADVANCE
else
c(tekući_ulaz, tekući_stek, tekuće_stanje) je oblika (y,s,u);
 REDUCE(p)
primeniti na tekući_stek operaciju y;  POP x dužina desne strane p
tekuće_stanje := s;  PUSH(leva strana p)
primeniti na tekući_ulaz operaciju u;  RETAIN
end if
end loop; Stanje se ne menja.
Programski prevodioci © 2006 Dragan Bojić 15 Programski prevodioci © 2006 Dragan Bojić 16

Primer rada potisnog BU parsera Primer rada…


Stanje steka: Preostali ulaz: Akcija Stanje steka: Preostali ulaz: Akcija
1.  dddaddacb-| SHIFT 11.  <S> <S> <S> dacb-| SHIFT
2.  d ddaddacb -| REDUCE(4) 12.  <S> <S> <S> d acb -| REDUCE(4)
3.  <S> ddaddacb -| SHIFT 13.  <S> <S> <S> <S> acb -| SHIFT
4.  <S> d daddacb -| REDUCE(4)
14.  <S> <S> <S> <S> a cb -| REDUCE(1)
5.  <S> <S> daddacb -| SHIFT
6.  <S> <S> d addacb -| REDUCE(4) 15.  <S> <S> <S> cb -| SHIFT
7.  <S> <S> <S> addacb -| SHIFT 16.  <S> <S> <S> c b -| REDUCE(3)
8.  <S> <S> <S> a ddacb -| REDUCE(1) 17.  <S> b -| SHIFT
9.  <S> <S> ddacb -| SHIFT 18.  <S> b -| REDUCE(2)
10.  <S> <S> d dacb -| REDUCE(4) 19.  <S> -| ACCEPT

Programski prevodioci © 2006 Dragan Bojić 17 Programski prevodioci © 2006 Dragan Bojić 18

3
Rad potisnog BU parsera Parsiranje od dna ka vrhu (BU)
 u svakom koraku važi: Koncept BU parsiranja
stek + ulaz = sentencijalna forma u  Kod pristupa 'odozdo-nagore' parser otkriva
strukturu stabla izvođenja počev od listova
krajnje desnom izvođenju ulaza iz <S> stabla nagore, određujući čvorove roditelja
 parser potiskuje (akcija SHIFT) simbole prepoznavanjem leve strane smena na
sa ulaza na stek dok ne kompletira osnovu poznate desne strane.
ručku
 redosled smena koje parser prepoznaje
 SHIFT ≡ PUSH(tekući ulazni simbol), tokom rada obrnut od redosleda pri krajnje
ADVANCE desnom izvođenju date sentence
 tada se ručka zamenjuje levom stranom
smene (akcija REDUCE)
Programski prevodioci © 2006 Dragan Bojić 19 Programski prevodioci © 2006 Dragan Bojić 20

Primer... Pojam ručke (handle)


<S> rm <S>b rm <S><S><S>cb  rm  Ručka sentencijalne forme  je pojava, u toj
   sentencijalnoj formi, desne strane produkcije
2 3 1 koja je poslednja primenjena u krajnje
 rm<S><S><S><S>acb  rm <S><S><S> dacb  rm desnom izvođenju .
 
4 4
 rm <S><S>ddacb rm <S><S><S>addacb rm  Produkcija ručke je poslednja produkcija
  primenjena u krajnje desnom izvođenju
1 4 sentencijalne forme.
 rm <S><S>daddacb  rm <S>ddaddacb rm
 
4 4  u prethodnom primeru, ručka za finalnu sentencu
rm dddaddacb je početno slovo d, a produkcija ručke je 4.

Programski prevodioci © 2006 Dragan Bojić 21 Programski prevodioci © 2006 Dragan Bojić 22

BU parsiranje po principu potiskivanja


i sažimanja (shift-reduce)

 Uvod  Parser po principu potiskivanja i sažimanja


(engl. shift-reduce) predstavlja potisni
 BU parser u vidu potisnog automata
automat, koji je definisan:
 SHIFT-REDUCE Parsiranje  skupom ulaznih simbola
 Konstrukcija LR(0) parsera  skupom simbola steka
 Konflikti u SHIFT-REDUCE parsiranju  početnim stekom i
 potisnom tabelom i kontrolnom tabelom.

Programski prevodioci © 2006 Dragan Bojić 23 Programski prevodioci © 2006 Dragan Bojić 24

4
Primer SHIFT-REDUCE parsera Elementi SR parsera
1.<S> <A><A><S>  Skup ulaznih simbola parsera sastoji se
2.<S>  od skupa terminalnih simbola zadate
<S> <A> a a -|
3.<S> a
 <S> <A>11 ax  SHIFT REDUCE(2) gramatike proširenog simbolom -|.
4.<A> a
<S> <S> REJECT ACCEPT
<A>
11 <A>12 a4 <A>
11
SHIFT REJECT
ax a x REDUCE(4)REDUCE(3)
<A>12 <S> <A>
11 ax <A>12
SHIFT REDUCE(2)
a4 a4 REDUCE(4) REDUCE(4)
<S> <S> REJECT REDUCE(1)
(a)potisna tabela (b) kontrolna tabela
Programski prevodioci © 2006 Dragan Bojić 25 Programski prevodioci © 2006 Dragan Bojić 26

Elementi SR parsera(...) Elementi SR parsera(...)


 Simboli parserskog steka obeležavaju vrste  Potisna tabela određuje koji simbol
potisne i kontrolne tabele. steka se u određenom trenutku
 svaki simbol steka odgovara nekom gramatičkom potiskuje na stek.
simbolu.
 simboli steka kodiraju i dodatne informacije, o  Redovi potisne tabele označeni su
kojima će biti reči pri razmatranju konstrukcije simbolima steka a kolone gramatičkim
parsera. Ove informacije su potrebne radi simbolima.
jednoznačnog određivanja parserskih aktivnosti;  U svakom ulazu tabele nalazi se najviše
 zbog postojanja ovih dodatnih informacija, više jedan stek simbol (prazni ulazi označavaju
različitih simbola steka odgovara jednom istom
gramatičkom simbolu.
grešku)

Programski prevodioci © 2006 Dragan Bojić 27 Programski prevodioci © 2006 Dragan Bojić 28

Primer rada <S> <A> a a -|

Elementi SR parsera(...)
 <S> <A>11 ax  SHIFT REDUCE(2)

SR parsera <S>
<A> <A>
<S> REJECT
SHIFT
ACCEPT
REJECT
11 12 a4 <A>
11

 Kontrolna tabela određuje akciju parsera na ax a x REDUCE(4)REDUCE(3)

osnovu tekućeg simbola na vrhu steka i <A>


12 <S> <A>
11 ax <A>
12
SHIFT REDUCE(2)
a4 a4 REDUCE(4) REDUCE(4)
tekućeg ulaznog simbola. <S> <S> REJECT REDUCE(1)
 Postoji četiri tipa parserskih akcija: sadržaj steka preost. ulaz akcija parsera
 ACCEPT - uspešan završetak parsiranja;
 REJECT - neuspešan završetak parsiranja. 1.  aa-| SHIFT
 SHIFT (potiskivanje): 2. ax a-| REDUCE(4)
 PUSH(potisna_tabela[vrh_steka, tekući_ulaz]) 3. <A>11 a-| SHIFT
ADVANCE
<A>11a4

4. -| REDUCE(4)
 REDUCE(p)
 POP x dužina desne strane p 5. <A>11<A>12 -| REDUCE(2)
 PUSH(potisna_tabela[vrh_steka, leva strana p]) 6. <A>11<A>12<S>1 -| REDUCE(1)
RETAIN

7. <S>0 -| ACCEPT
Programski prevodioci © 2006 Dragan Bojić 29

5
Konstrukcija SR parsera za LR(0)
gramatike

 Uvod  strategija odlučivanja se zasniva


 BU parser u vidu potisnog automata isključivo na sadržaju steka.
 Ulazni simboli ne uzimaju se u obzir pri
 SHIFT-REDUCE Parsiranje odlučivanju.
 Konstrukcija LR(0) parsera  Značenje LR(0):
 Konflikti u SHIFT-REDUCE parsiranju  ulaz se čita s Leva na desno;
 nalazi se desno (Rightmost) izvođenje
 gleda se 0 simbola na ulazu

Programski prevodioci © 2006 Dragan Bojić 31 Programski prevodioci © 2006 Dragan Bojić 32

Pojam LR(0) konfiguracije


(engl. configuration ili item) Primer

 LR(0) konfiguracija predstavlja  za gramatiku:


gramatičku smenu sa dodatom tačkom 1. <S>  a
negde na desnoj strani 2. <S> ( <S> <R>
 A X1...Xi  Xi+1....Xn 3. <R> , <S> <R>
4. <R> )

Programski prevodioci © 2006 Dragan Bojić 33 Programski prevodioci © 2006 Dragan Bojić 34

Primer Primer
LR(0) konfiguracije 2. smene  za praznu smenu <X>   jedna
 konfiguracija zatvaranja (tačka na početku)
konfiguracija, u oznaci
<S>   ( <S> <R>
<X>    ili <X>  
 bazične konfiguracije (tačka nije na početku):
<S>  (  <S> <R>  proširenje gramatike (uniformiše pravila
<S>  ( <S>  <R> konstrukcije parsera)
<S>  ( <S> <R>  0. <S’>  <S> ─┤
 druga oznaka za poslednju konfiguraciju
<R>3

Programski prevodioci © 2006 Dragan Bojić 35 Programski prevodioci © 2006 Dragan Bojić 36

6
Konstrukcija karakterističnog LR(0) Konstrukcija karakterističnog LR(0)
automata – detektora ručki automata – detektora ručki

 Stanja automata su skupovi  Operacija Closure0 nad skupom


konfiguracija konfiguracija s:
 Iterativna konstrukcija grafa prelaza  Closure0(s) = s{<B> |
koristeći operacije Closure0 i Goto0 <A><B>Closure0(s)}

<A>  <B> iterativno <A>   <B>...


<B>   1 <B>   <C>...
dodaje
se
.
. <C>   ...
<B>   i

Programski prevodioci © 2006 Dragan Bojić 37 Programski prevodioci © 2006 Dragan Bojić 38

Konstrukcija karakterističnog LR(0) Algoritam konstrukcije


automata – detektora ručki karakterističnog LR(0) automata

 Operacija Goto0 nad stanjem s i  Startno stanje detektora ručki se dobija kao
Closure0({<S’>  <S> ─┤}).
ulaznim simbolom X:
 Stanje S' u koje se prelazi iz nekog stanja S
 Goto0(s,X)=Closure0({<A> X | pod ulazom X, dobija se kao rezultat
<A> Xs} procedure GoTo0(S,X).
 Polazeći od startnog stanja, sistematski se
određuju prelazi za svaki ulazni simbol, što
... generiše nova stanja.
X
<A>    X  <A>   X   Ova stanja se procesiraju na isti način kao
... startno, sve dok postoji neko neobrađeno
stanje.

Programski prevodioci © 2006 Dragan Bojić 39 Programski prevodioci © 2006 Dragan Bojić 40

Karakteristični automat za Karakteristični automat za


gramatiku iz primera gramatiku iz primera
<S’> –>  <S> --| <S’> –>  <S> --|
<S> –> a
<S> –> (<S> <R>

Closure0

Programski prevodioci © 2006 Dragan Bojić 41 Programski prevodioci © 2006 Dragan Bojić 42

7
Karakteristični automat za Karakteristični automat za
gramatiku iz primera gramatiku iz primera
<S>0 <S>0
<S’> –>  <S> --| <S> <S’> –>  <S> --| <S>
<S’> –> <S> --| <S’> –> <S> --|
<S> –> a <S> –> a
startno <S> –> (<S> <R> a a1 startno <S> –> (<S> <R> a a1
stanje stanje
<S>–> a  <S>–> a 
(
(
(2

GOTO0 na
(2
<S> –> ( <S> <R>
<S> –> ( <S> <R>
<S> –>  a
<S> –>  (<S> <R>
CLOSURE0 na nova stanja

Programski prevodioci © 2006 Dragan Bojić 43 Programski prevodioci © 2006 Dragan Bojić 44

Karakteristični automat za Karakteristični automat za


gramatiku iz primera gramatiku iz primera
<S>0 --|0 <S>0 --|0
<S’> –>  <S> --| <S> --| <S’> –>  <S> --| <S> --|
<S’> –> <S> --| <S’> –> <S> --| <S’> –> <S> --| <S’> –> <S> --|
<S> –> a <S> –> a
startno <S> –> (<S> <R> a a1 startno <S> –> (<S> <R> a a1
stanje stanje
<S>–> a  <S>–> a 

( a ( a

(2 <S>2 (2 <S>2 <R>2


<S> –> ( <S> <R> <S> <S> –> (<S>  <R> <S> –> ( <S> <R> <S> <S> –> (<S>  <R> <R> <S> –> ( <S> <R>
<S> –>  a <R> –>  , <S> <R> <S> –>  a <R> –>  , <S> <R>
<S> –>  (<S> <R> <R> –>  ) <S> –>  (<S> <R> a <R> –>  ) ) )
4
( <R> –> ) 
(
,3 , <S>3 )
<S>
GOTO0 na nova stanja
( <R> –> ,  <S> <R> <R> –> , <S> <R>
<S> –>  a , <R> –>  ,<S><R>
<S> –>  (<S> <R> <R>–>  )
karakteristični automat
ujedno predstavlja <R>3 <R>
<R> –> , <S> <R> 
potisnu tabelu parsera
Programski prevodioci © 2006 Dragan Bojić 45 Programski prevodioci © 2006 Dragan Bojić 46

Popunjavanje LR(0) kontrolne tabele


na osnovu karakterističnog automata Primer
<S> <R> ( , ) a ─┤
(razmatra se ulaz u vrsti V, kojoj odgovara skup  <S>0 (2 a1 SHIFT
konfiguracija S): <S>0 ─┤0 SHIFT
 Ako S sadrži konfiguraciju oblika <X>    x , ulaz ─┤0 ACCEPT
treba popuniti akcijom SHIFT.
a1 REDUCE(1)
 Ako S sadrži konfiguraciju oblika <Y>   , odnosno
(2 <S>2 (2 a1 SHIFT
tačka se nalazi na kraju desne strane, ulaz treba
popuniti akcijom REDUCE(<Y>  ). Izuzetno, ako se <S>2 <R>2 ,3 )4 SHIFT
radi o nultoj smeni, akcija je ACCEPT. <R>2 REDUCE(2)
 Vrste koje nisu pokrivene ni 1. ni 2. pravilom treba da , 3 <S>3 (2 a1 SHIFT
sadrže akciju REJECT. <S>3 <R>3 ,3 )4 SHIFT
 Ukoliko gornja pravila na jednoznačan način određuju <R>3 REDUCE(3)
akciju za svaki ulaz kontrolne tabele, gramatika pripada )4 REDUCE(4)
klasi LR(0). 144444444442444444444444443 14442444443
potisna tabela kontrolna tabela
Programski prevodioci © 2006 Dragan Bojić 47 Programski prevodioci © 2006 Dragan Bojić 48

8
Konflikti u SR parsiranju

 Uvod  pri konstrukciji tabele mogu se pojaviti


konflikti:
 BU parser u vidu potisnog automata
 SHIFT/REDUCE, na primer, ako stanje sadrži
 SHIFT-REDUCE Parsiranje <X>  a 
<Y> a  b
 Konstrukcija LR(0) parsera
 REDUCE/REDUCE, na primer, ako stanje sadrži
 Konflikti u SHIFT-REDUCE parsiranju <X>  c 
<Y> d 

Programski prevodioci © 2006 Dragan Bojić 49 Programski prevodioci © 2006 Dragan Bojić 50

Konflikti u SR parsiranju Konflikti u SR parsiranju

 prazne smene uvek izazivaju konflikt  tada gramatika nije LR(0) i (teorijski)
=> LR(0) ne dozvoljava prazne smene nije moguće napraviti LR(0) parser;
 <S’>   <S> ─┤  u praksi (yacc):
 <S>   a  S/R konflikt uvek razrešava u korist S, osim
ako se %prec direktivom eksplicitno ne
 <S>  
zada drugačije
 R/R konflikt (ozbiljniji problem) prema
redosledu navođenja smena

Programski prevodioci © 2006 Dragan Bojić 51 Programski prevodioci © 2006 Dragan Bojić 52

9
Parsiranje od dna ka vrhu

(Nastavak)

Konstrukcija SR parsera za SLR(1) gramatike

 SLR(1) = Simple LR(1)

 ideja je da parser gleda tekući ulazni simbol pri radu

 time se smanjuje broj potencijalnih konflikata u kontrolnoj tabeli

 REDUCE(<X>  ) biće izvršeno samo ako je tekući ulaz iz skupa FOLLOW(<X>)

Follow skupovi neterminala


 FOLLOW skup posmatranog neterminala <X> je skup terminala koji se mogu pojaviti neposredno
iza <X> u bilo kojoj sentencijalnoj formi izvedenoj iz <S>─┤(marker kraja je dodat jer se svaki
ulazni niz njime završava).
FOLLOW(<X>) = {t | t  Vt {─┤}
 <S>─┤,* <X>t }

Računanje FOLLOW skupova

 Pojmovi na kojima se zasniva računanje FOLLOW skupova su poništivost neterminala i FIRST


skupovi neterminala.

Poništivost neterminala
 Neterminal <X> je poništiv ako i samo ako se iz njega može izvesti prazna sekvenca:
<X> ,* 
 Sekvenca gramatičkih simbola je poništiva ako i samo ako se sastoji od nula ili više poništivih
neterminala.
 Skup poništivih neterminala P formiramo na sledeći način:
1. U skup P staviti sve neterminale koji se pojavljuju na levoj strani neke prazne smene.
2. Razmatrati redom smene čije se desne strane sastoje isključivo od neterminala, a leva strana se ne
nalazi u skupu P. Ako se svi neterminali desne strane pojavljuju u skupu P, dodati levu stranu smene
u P.
3. Sve dok postoji promena u skupu P ponavljati korak 2, u suprotnom završiti postupak.

First skupovi
 Skup FIRST(<X>) za proizvoljan neterminal <X> predstavlja skup svih terminalnih simbola kojima
može početi sentencijalna forma izvedena iz <X>:
FIRST(<X>) = { t | t  Vt    V*  <X> * t }
 Moguće je definisati FIRST skupove sentencijalnih formi: Neka je  = A1A2...AiAi+1...An proizvoljna
sentencijalna forma u kojoj prvih i simbola predstavlja poništive neterminale. Tada skup FIRST()
predstavlja uniju FIRST skupova svih simbola sa levog kraja sekvence zaključno sa prvim koji nije
poništiv:
FIRST()=FIRST(A1)  FIRST(A2) ...  FIRST(Ai+1)
 Ukoliko je simbol A terminal, onda je FIRST(A) = {A}.

Iterativno računanje FIRST skupova neterminala:


1. Inicijalno, FIRST skupovi svih neterminala su prazni.
2. Razmatramo redom svaki neterminal <X>
3. Razmatramo redom sve smene sa levom stranom <X>.
4. Neka je jedna takva smena <X>  . Tada računamo:
a. FIRST(<X>) = FIRST(<X>)  FIRST()
5. Tačke 2-4 algoritma ponavljamo sve dok ima promene u FIRST skupovima.

Računanje FOLLOW skupova

 FOLLOW skupove računamo prema sledećim pravilima:


1. Skup FOLLOW startnog neterminala sadrži marker kraja ulaza ─┤.
2. Za određivanje FOLLOW skupa neterminala <X> posmatramo sve gramatičke smene na čijoj se
desnoj strani nalazi <X>. Neka je <Y>   <X>  jedna od tih smena. Tada:
FOLLOW(<X>)  FIRST(), ako  nije poništivo, ili
FOLLOW(<X>)FIRST()FOLLOW(<Y>),ako je  poništivo.

Računanje FOLLOW skupova (nastavak)

 U opštem slučaju, na osnovu datih pravila formira se sistem skupovnih jednakosti koji se rešava
iterativno:
1. Inicijalno se usvoji da su svi FOLLOW skupovi prazni.
2. Usvojene vrednosti se uvrste u jednakosti čime se dobijaju nove vrednosti FOLLOW skupova.
3. Korak 2. ponavlja se sve dok postoji promena bar u jednom skupu. Krajnje vrednosti predstavljaju
konačno rešenje.

Primer računanja FOLLOW skupova:

Za sledeću gramatiku sa startnim simbolom <A>:


1. <A>  a <B> <C>
2. <A>  b <B>
3. <A>  
4. <B>  a <B> b
5. <B>  
6. <C>  b <C>
7. <C>  c
Odrediti FOLLOW skupove za svaki neterminal.

Rešenje
Odredimo prvo poništive neterminale u datoj gramatici, zatim FIRST, a potom i FOLLOW skupove.
1.<A>a<B><C> Pon = { <A>, <B>}
2. <A>  b<B> FIRST(<A>)=a, b
3. <A>   FIRSTB>)=a
4. <B>  a<B>b
FIRSTC>)=b, c
5. <B>  
6. <C>  b<C> FOLLOWA> = ─┤
7. <C>  c FOLLOW(<B>)  FIRST(<C>)
FOLLOW(<B>)  FIRST()  FOLLOW(<A>)
FOLLOW(<B>)  {b}
FOLLOW(<B>)=FIRST(<C>)FOLLOW(<A>){b}
= {b, c, ─┤}
FOLLOW(<C>)  FIRST()  FOLLOW(<C>)
FOLLOW(<C>) FIRST()FOLLOW(<A>)=─┤

Konstrukcija SLR(1) parsera

 Karakteristični automat i potisna tabela SLR(1) parsera identični su karakterističnom automatu i potisnoj
tabeli LR(0) parsera.

Popunjavanje kontrolne SLR(1) tabele


 (razmatra se ulaz u vrsti V, kojoj odgovara skup konfiguracija S i koloni x):
1. Ako S sadrži konfiguraciju oblika <X>    x , odnosno tačka se nalazi ispred terminalnog
simbola x, ulaz treba popuniti akcijom SHIFT.
2. Ako S sadrži konfiguraciju oblika <Y>   , odnosno tačka se nalazi na kraju desne strane, a važi
da je x  FOLLOW(<Y>), tada ulaz treba popuniti akcijom REDUCE(<Y>  ). Izuzetno, ako se
radi o nultoj smeni, akcija je ACCEPT.
3. Vrste koje nisu pokrivene ni 1. ni 2. pravilom treba da sadrže akciju REJECT.
Ukoliko gornja pravila na jednoznačan način određuju akciju za svaki ulaz kontrolne tabele, gramatika
pripada klasi SLR(1).

SLR(1) - Primer za ranije datu gramatiku


0. <S’>  <S> ─┤
1. <S>  a
2. <S> ( <S> <R>
3. <R> , <S> <R>
4. <R> )
FOLLOW (<S’>) = { ─┤}
FOLLOW (<S>) = { , ) ─┤ } FOLLOW (<R>) = { , ) ─┤ }
( , ) a ─┤
 SHIFT SHIFT
<S>0 SHIFT
─┤0 ACCEPT
a1 REDUCE(1) REDUCE(1) REDUCE(1)
(2 SHIFT SHIFT
<S>2 SHIFT SHIFT
<R>2 REDUCE(2) REDUCE(2) REDUCE(2)
,3 SHIFT SHIFT
<S>3 SHIFT SHIFT
<R>3 REDUCE(3) REDUCE(3) REDUCE(3)
)4 REDUCE(4) REDUCE(4) REDUCE(4)

LALR(1) parsiranje

Nedostatak SLR(1) metoda


 Gramatika
0. <S’> <S> ─┤
1. <S>  <A> a
2. <S>  b c <A> c
3. <A>  b
nije SLR(1) jer se u kontrolnoj tabeli pojavljuje S/R konflikt u stanju bx i koloni c jer je
FOLLOW(<A>)={a,c}:

 bx
<S’>   <S> ─┤ <S>  b  c <A>c
<S>   <A> a b
<A>  b 
<S>   b c <A> c
<A>   b

 konflikta ne bi bilo kada bi se uočilo da


REDUCE(<A>  b) ne treba raditi u koloni c, pošto <A> „dolazi” iz smene 2, tako da R treba raditi
samo u koloni a, a SHIFT u koloni c
 problem je što SLR(1) parser pri redukciji koristi FOLLOW skup, koji uzima u obzir i <A> u drugoj
smeni (tj. u FOLLOWu se računaju sve pojave odjednom)
 dakle, neki konflikti mogu se izbeći ako se uzmu precizniji skupovi od FOLLOW pri popunjavanju
kontrolne tabele
 ovo je ostvareno kod LALR(1) gramatika

Pojam LR(1) konfiguracije

 LR(1) konfiguracija predstavlja LR(0) konfiguraciju sa dodatim predikcionim simbolom


A X1...Xi  Xi+1....Xn, p p VT  {}
( se koristi kao predikcija samo kod konfiguracija smene 0.)
Primer
0.<S'>  <S>-| Neke LR(1) konfiguracije:
1.<S> <A><A><S> <S'>  <S> -|, 
2.<S>   <S> a, -|
<A> a, a
3.<S> a
4.<A> a
<A> -> *a, -| <A> -> *a, a <A> -> *a, {a,-|}

Pravilne LR(1) konfiguracije

 u okviru simbola steka LALR(1) parsera može se pojaviti samo podskup LR(1) konfiguracija koje
nazivamo pravilnim.

 LR(1) konfiguraciju <X>  , t nazivamo pravilnom LR(1) konfiguracijom ako i samo ako je:

1. t  FOLLOW(<X>), ili

2. reč o smeni 0 i t=.


Iterativni metod konstrukcije LALR(1) parsera

1) konstruisanje karakterističnog LR(0) automata i


2) određivanje predikcionih skupova (engl. lookahead sets) LA metodom prosleđivanja predikcionih
simbola (engl. lookahead propagation).

Metod prosleđivanja predikcionih simbola:


1) Odrediti skupove spontanih predikcionih simbola za sve konfiguracije zatvaranja u svakom od
stanja LR(0) detektora ručki:
o SLA skup za proizvoljnu LR(0) konfiguraciju zatvaranja <A>   u stanju S računa se
tako što se:
a) nađu sve konfiguracije oblika
<B>  <A> u stanju S i
b) u skup SLA(<A>  ) uključe svi terminali
tFIRST().
2) Između LR(0) konfiguracija u stanjima LR(0) automata definišu se veze prosleđivanja prema slici:
1. sluèaj
<A> X  <A> X  
 
X

2. sluèaj <B> <A> 


 je poništivo

<A> 

prelaz izmeðu stanja

veza prosleðivanja

Predikcioni (LA) skupovi računaju se sledećim iterativnim algoritmom:

 Inicijalno su LA skupovi konfiguracija zatvaranja u svakom od stanja jednaki SLA skupovima


odgovarajućih konfiguracija, dok su LA skupovi ostalih konfiguracija prazni.

 Predikcioni simboli prosleđuju se među LA skupovima konfiguracija koje su povezane vezama


prosleđivanja sve dok postoji promena u LA skupovima.

Primer

Za gramatiku:
1. <S> <A><S>
2. <S> 
3. <A> <B>b<B>c
4. <A> <C>c<B>
5. <B> a<D>
6. <C> a<D>
7. <D> 

Sledeća slika prikazuje stanje početno stanje pri računanju predikcionih simbola za ovu gramatiku.
 LR(0) konfiguracijama u svakom stanju LR(0) detektora ručki dodati su SLA skupovi predikcija.
 Isprekidane linije predstavljaju veze prosleđivanja.
state  state <S> state 
0 0
<S>
<S'>  <S>  {} <S'> <S>   {} <S'> <S>  {}

<S>  <A><S> {}
state <A>
<S>   {} 1 state <S>
1
<A>  <B>b<B>c{a} <A> <S> <A> <S> {} <S>
<S> <A><S> {}
<A>  <C>c<B>{a}
<B>  a<D>{b} <S>  <A><S> {}
<S>   {}
<C>  a<D>{c} state <D>
<A>  <B>b<B>c{a} <A> x
<A>  <C>c<B>{a} <B> a<D> {}
a
<C> <B>  a<D>{b} <C> a<D> {}
ax <C>   a<D> 
{ c}
<B> <D>
<C> <B> <C> a state a
4 x
<B> a <D> {}
state <B> state <C> <C> a <D> {}
31 4
<A> <B> b<B>c{} <A> <C> c<B>{} <D>    {}
b
c
state b state c
3 4 state <B>
4
<A> <B>b <B>c{} <A> <C>c <B>{}
<A> <C>c<B> {}
<B>  a<D>{c} <B>  a<D>{} <B>
<B> a a
state <B> state a
33 5
<A> <B>b<B> c{} <B> a <D>{}
<D>   {}
c
state c <D>
3
state <D>
<A> <B>b<B>c {} 5
<B> a<D> {}

 Računanjem LA skupova određen je LALR(1) detektor ručki (ili karakteristični automat):


state  state <S> state 
0 0
<S> 
<S'>  <S>   <S'> <S>    <S'> <S>   
<S>  <A><S>  
<S>     state <A> state <S>
1 1
<A>  <B>b<B>c{a } <A> <S>
<S> <A> <S>   <S> <A><S>  
<A>  <C>c<B>{a }
<S>  <A><S>  
<B>  a<D> b
<S>    
<C>  a<D> c state <D>
<A>  <B>b<B>c{a } <A> x
<A>  <C>c<B>{a } <B> a<D>  b
a
<C> <B>  a<D> b <C> a<D>  c
state a <C>  a<D> c
x
<B>
state <C> <B> a
4 <D>
<C>
state a
x
state <B> state <C>
31 4 <B> a <D> b
<A> <B> b<B>c{a } <A> <C> c<B>{a } <C> a <D> c
<D>    {b c}
b c
state b state c
3 4 state <B>
4
<A> <B>b <B>c{a } <A> <C>c <B>{a } <B>
<A> <C>c<B> {a }
<B>  a<D> c <B>  a<D> {a }
a
<B> a
state <B> state a
33 5
<A> <B>b<B> c{a } <B> a <D>{ac }
<D>   {ac }
c
state c
3 <D>
state <D>
<A> <B>b<B>c {a } 5
<B> a<D> {ac }

 karakteristični automat ujedno predstavlja potisnu tabelu

Konstrukcija kontrolne LALR(1) tabele


(razmatra se ulaz u vrsti X i koloni y):

 neprazna potisna tabela za u vrsti X i koloni y => SHIFT

 Ako <W> , y  X => REDUCE(<W> )

 REDUCE nulte smene => ACCEPT

 Svi ulazi tabele koji nisu obuhvaćeni gornjim pravilima sadrže REJECT akciju.

 Ako svaki ulaz u kontrolnoj tabeli, posle njihovog popunjavanja prema navedenim pravilima, sadrži
jedinstvenu akciju zadata gramatika pripada klasi LALR(1) gramatika i konstrukcija parsera je
okončana.
 U suprotnom slučaju, zadata gramatika ne pripada klasi LALR(1) gramatika, pa se za nju ne može
konstruisati LALR(1) parser.

Odnos među LR klasama bezkontekstnih gramatika

 od svih LR metoda LALR(1) parsiranje ima za praksu najveći značaj.


LL(1)

LR(0)
SLR(1)
LALR(1)
LR(1)
Sve bezkontekstne gramatike

 Parseri generisani alatima yacc i cup su LALR(1) parseri


Oporavak od grešaka kod parsera

 prevođenje se obično ne zaustavlja na prvoj greški u ulaznom programu


 Prihvatljivi odgovori prevodioca pri nailasku na grešku:
 detekcija greške (izdavanje odgovarajuće izlazne poruke)
 oporavak od greške – prevodilac pokušava da određenim akcijama učini moguć nastavak
sintaksno-semantičke analize programa, da bi se detektovale i druge potencijalne greške.
Ne vrši se generisanje izlaznog programa. Akcije obuhvataju modifikaciju parserskog
steka i/ili preostalog ulaza.
 popravak greške – prevodilac pokušava da korisnikov ulaz sa greškom popravi u validan
program, uz generisanje prevedenog koda. Naravno, nije garantovano otklanjanje greške u
smislu da se postigne tačno ono što je programer želeo. Popravljeni program može
nekorektno da se ponaša pri izvršavanju.
 Neprihvatljivi odgovori:
 prevodilac ne detektuje postojeću grešku u programu
 prevodilac otkazuje (greška u izvršavanju)
 prevodilac počinje da se vrti u mrtvoj petlji, stalno prijavljujući istu grešku
Svojstvo prefiksa
 Simbol povrede predstavlja onaj simbol ulaznog niza na kome je otkrivena greška.
prefiks

Ulazna . . . . . . . . . . . . . . . . . . . .
sekvenca

simbol povrede

 Parser ima svojstvo ispravnog prefiksa ako za sve neispravne ulazne sekvence niz simbola pre
simbola povrede predstavlja prefiks nekog prihvatljivog ulaznog niza.
 Kod takvih parsera možemo modifikacijom preostalog ulaza učiniti ceo ulayni niz prihvatljivim
 Parseri konstruisani metodima koje proučavamo na kursu imaju ovo svojstvo
 Poruka o grešci najčešće se formuliše na osnovu vršnog simbola steka i tekućeg ulaznog simbola, uz
navođenje linije i pozicije na liniji koda na kojoj je nastupila greška.
 Potom se vrši oporavak parsera od greške, koji potencijalno može da prouzrokuje nove nepostojeće
greške. Kvalitet oporavka ceni se po tome koliko malo nepostojećih grešaka se prijavljuje.

Oporavak od grešaka u SR parsiranju

 izložićemo osnovne (i najčešće primenjivane) varijante "paničnog" oporavka. Ideja je da pri pojavi
greške, parser pokušava da izađe iz jezičkog konstrukta u kome je nastala greška, tražeći siguran
ulazni simbol (kao što je terminator naredbe ili početna ključna reč sledeće naredbe i slično) od koga
može da nastavi normalno parsiranje.

 kompleksniji metodi oporavka i popravka greške (i za LL i za LR tehnike) mogu se naći u knjizi


Fisher-a, LeBlanc-a

Jednostavan "panic mode" algoritam:

 Definišemo skup tzv. sigurnih simbola (kao što su terminatori iskaza i konstrukcija ; end --| itd.)
 (1) Kada parser detektuje grešku, sa ulaza se redom uklanjaju simboli dok se ne naiđe na neki od
sigurnih simbola.

 (2) Tada se sa steka parsera skidaju simboli sve dok se ne naiđe na neki koji može da potisne sigurni
simbol na ulazu na stek.

 (3) Parsiranje se posle toga nastavlja na uobičajen način.

Ovaj algoritam najbolje funkcioniše kod nestrukturiranih jezika, kakvi su Basic ili Fortran; ideja je da se
parser izvuče iz pogrešnog konstrukta tako što detektuje njegov kraj i posle normalno nastavi parsiranje.
Poboljšanje za strukturirane jezike je da se pored skupa sigurnih simbola definiše i skup simbola zaglavlja
(header), kao što su begin, then i slično.

Poboljšani "panic mode" algoritam:

 (1) Kada parser detektuje grešku, sa ulaza se redom uklanjaju simboli dok se ne naiđe na neki od
sigurnih simbola ili simbola zaglavlja.

 (2a) Ako je naišao siguran simbol, tada se sa steka parsera skidaju simboli sve dok se ne naiđe na neki
koji može da potisne sigurni simbol na ulazu na stek.

 (2b) Ako je naišao simbol zaglavlja, tada se on potiskuje na stek i posebno markira.

 (3) Parsiranje se posle toga nastavlja na uobičajen način. Kada se redukcijom neke smene ukloni
markirani simbol sa steka, prelazi se ponovo na korak (1).

Oporavak od grešaka u yacc/cup parserima


Prijava greške

 pri nastanku sintaksne greške u izgenerisanom parseru, poziva se funkcija yyerror() kojoj se
prosleđuje opis greške u stringu

 Po povratku iz yyerror(), parser može izvršiti oporavak od greške ako u gramatici postoje
odgovarajuća pravila. U suprotnom, yyparse() završava rad i vraća nenultu vrednost (neusprešan
kraj).

Oporavak od greške

 oporavak od grešaka je pod kontrolom korisnika: postoji poseban gramatički simbol error.

 Simbol error tretira se kao specijalan neterminal, čija se zamena ne definiše smenama, već se
razmatra se jedino u slučaju da parser detektuje grešku.

 Tada parser pokušava da odgovarajuću pojavu error u gramatici upari sa pogrešnim delom ulazne
sekvence i potom nastavi parsiranje.

Primer gramatike sa error smenom


stmt : expr ';'
| while_stmt ';'
| if_stmt ';'
| ...
| error ';'
;
if_stmt : if '(' expr ')' stmt

 Smena sa error znači da ako ulazni niz ne odgovara ni jednoj od “normalnih” smena za stmt, parser
prelazi u režim oporavka “gutajući” pogrešne ulazne simbole (tj. uparujući ih sa error) sve dok ne
naiđe na “;”.

 Parser izlazi iz režima oporavka ako može da nastavi o dove tačke normalno parsiranje (SHIFT-uje
bar tri tokena na uobičajen način).

YACC Algoritam oporavka od greške

 Po detektovanju greške, parser skida sa steka stanja dok ne dođe do stanja koje ima neposredan
oporavak od greške ( konfiguraciju X…error…).

 Tada parser počinje “preskakanje” ulaznih tokena do trenutka kada dođe neki koji očekuje.

 Tada nastavlja parsiranje ali bez izvršavanja semantičkih akcija. Ako uspešno procesira bar tri tokena
sa ulaza, ulaz se resetuje na stanje kada je prestalo preskakanje tokena i parsiranje se ponavlja
normalno, ovaj put izvršavajući sve akcije.

 Ako parser nije uspeo uspešno da isprocesira tri tokena, parser odbacuje sledeći token sa ulaza i
pokušava da nastavi parsiranje.

 Ako se u pokušajima oporavka dođe do kraja ulaza ili isprazni parserski stek (na primer nije bilo
odgovarajućeg stanja koje ima oporavak) parser neuspešno završava rad.

Gde dodati pravila za oporavak od greške u gramatiku?

 Jednostavna i efikasna strategija oporavka je da se preskoči ostatak tekuće linije programa (ili ostatak
tekućeg iskaza):
stmnt: error ';' /* on error, skip
until ';' is read */

 Takođe je korisno upariti zatvorenu zagradu za već parsiranu otvorenu zagradu (ili neki sličan par
delimitera). U suprotnom, zatvorena zagrada bi izgledala neuparena i generisala dodatnu suvišnu
prijavu greške:
primary: '(' expr ')'
| '(' error ')'
...
;

 Da bi suzbio suvišne prijave grešaka, parser ne prijavljuje sintaksne greške neposredno posle prve
prijave. Tek posle tri ispravno procesirana ulazna tokena, ponovo se omogućava prijavljivanje
grešaka.

 Ako se u semantičkoj akcija pravila za oporavak od greške upotrebi yyerrok, parser će odmah
omogućiti prijavu novih grešaka (neće čekati da prođu tri uspešna tokena), na primer:
primary: '(' error ')' { yyerrok; }

 Primetiti da pravila za oporavak od greške mogu sadržati akcije, kao i obična pravila.
 Translacione gramatike
Programski prevodioci 1  Atributivno-translacione gramatike
 Sintaksno-upravljano prevođenje od
dna ka vrhu
Lekcija – Sintaksno upravljano prevođenje

©2007 Dragan Bojić 1 Programski prevodioci © 2007 Dragan Bojić 2

Translacione gramatike Translaciona gramatika


Kod translacionih gramatika skup terminalnih simbola delimo na

ulazne i akcione simbole (pišu se u vitičastim zagradama).  definiše prevođenje ulazne sekvence (sastoji
se od ulaznih simbola) u akcionu sekvencu.
 Primer
1. <E> <E> + <T> {+}  Data gramatika definiše prevođenje infiksnog
2. <E> <T> aritmetičkog izraza u postfiksni
3. <T> <T> * <P> {*}
4. <T> <P>  na primer
5. <P> ( <E> ) (a+b)*c
6. <P> a {a}
7. <P> b {b} prevodi se u
8. <P> c {c} {a} {b} {+} {c} {*}

Programski prevodioci © 2007 Dragan Bojić 3 Programski prevodioci © 2007 Dragan Bojić 4

Translaciono stablo izvođenja Sekvenca aktivnosti


 za datu ulaznu sekvencu određuje se na uobičajeni  Dobija se obilaskom stabla s leva na desno i
beleženjem simbola u listovima:
način, pri čemu se u stablo unose i akcioni simboli. a {a} + b {b} * c {c} {*} * ( b {b} + a {a} {+} ) {*}
<E>
* ( c {c} + a {a} {+} ) {*} {+}
<T> +
+
<E> <T> * *  Ukoliko iz sekvence aktivnosti uklonimo akcione
simbole, preostali simboli čine zadatu ulaznu
<T> * <P> <P>
sekvencu:
<P> <T> ( <E> ) * ( <E> ) a+b*c*(b+a)*(c+a)
a a <T> * <P> * <E> + <T> +

C <T> +


 Ukoliko iz sekvence aktivnosti uklonimo ulazne
<P> C <E> + <T> <P>
simbole, preostali simboli čine zadatu akcionu
b b <T> <P> <P> a a sekvencu, odnosno prevod date ulazne sekvence:
<P> a a C C {a} {b} {c} {*} {b} {a} {+} {*} {c} {a} {+} {*} {+}
b b
Programski prevodioci © 2007 Dragan Bojić 5 Programski prevodioci © 2007 Dragan Bojić 6

1
Atributivno-translacione
gramatike (ATG)

 Translacione gramatike  Atributi – mehanizam prosleđivanja


informacija između pojedinih gramatičkih
 Atributivno-translacione gramatike simbola i smena.
 Sintaksno-upravljano prevođenje od  Atributi se pridružuju pojedinim gramatičkim
dna ka vrhu simbolima. (pišu se u indeksu uz simbol).
 Dve vrste atributa:
 sintetizovani – prenose informacije od
listova stabla ka korenu (odozdo na gore)
 nasleđeni – obrnuto, od korena ka listovima.

Programski prevodioci © 2007 Dragan Bojić 7 Programski prevodioci © 2007 Dragan Bojić 8

Primer ATG Atributivno translacione gramatike


1. <S>p4,q1  a p1 <S> t1,p2 bs1 {c}q2,p3 <A> r1,q3 {d r2,s2,t2 }  atributi ulaznih simbola tretiraju se UVEK kao
(p2, p3, p4)  p1 ( q2, q3 )  q1 s2  s1 t2  t1 r2  r1
2. <S> p2,p1  e sintetizovani
p2  p1  njihove vrednosti obezbeđuje leksički analizator
3. <A> p3,t1  <S> p1,t2 b q1 <A> r1,q2 <A> s1,q3 {f r2,s2,p2 } kroz vrednosni deo ulaznog tokena.
(p2, p3)  p1 (q2, q3)  q1 r2  r1 s2  s1 t2  t1  Svakoj smeni pridružuju se pravila
4. <A> p2,q1  {e q2} cp1 izračunavanja vrednosti za atribute simbola
p2  p1 q2  q1 koji se pojavljuju u toj smeni (ne mogu se
Za gramatiku iz primera: koristiti niti računati atributi simbola iz drugih
<S>p,q sintetizovano p, nasleđeno q smena)
<A>p,q sintetizovano p, nasleđeno q
Atributi akcionih simbola su nasleđeni
Programski prevodioci © 2007 Dragan Bojić 9 Programski prevodioci © 2007 Dragan Bojić 10

Osnovna pravila konzistencije Osnovna pravila konzistencije


atributivne gramatike atributivne gramatike (nastavak)

(ako se naruše, gramatika nema smisla) 3. Za svaki nasleđeni atribut koji se pojavljuje
1. Atributi se moraju slagati po broju i tipu za na desnoj strani smene mora postojati
pravilo za izračunavanje
sve pojave istog simbola X (ne moraju i po
 može zavisiti od nasleđenih sa leve strane i od
imenu). bilo kog sa desne strane.
2. Za svaki sintetizovani atribut koji se 4. Vrednost nasleđenih atributa startnog
pojavljuje na levoj strani smene mora neterminala (na levoj strani) mora biti
postojati pravilo za izračunavanje unapred zadata.
 može zavisiti od nasleđenih atributa sa leve 5. Vrednosti atributa ulaznih simbola se ne
strane i od bilo kog sa desne strane. računaju, nego moraju biti unapred zadate.

Programski prevodioci © 2007 Dragan Bojić 11 Programski prevodioci © 2007 Dragan Bojić 12

2
Računanje vrednosti atributa Računanje vrednosti atributa...

 Za naš primer, uzećemo ulaznu 1. Prvo konstruišemo stablo izvođenja


sekvencu bez atributa. <S>

a1 b2 a3 b4 c5 b2 c6 c7.
(indeksi predstavljaju vrednosti atributa A <S> b  C <A>  d

ulaznih simbola) i da startni simbol ima  b <A> <A> +


nasl. atribut = 1. <S>  e c  e c

a <S> b  c <A>  d

  e c

Programski prevodioci © 2007 Dragan Bojić 13 Programski prevodioci © 2007 Dragan Bojić 14

Računanje vrednosti atributa... Računanje vrednosti atributa...


2. Naznačimo sve što inicijalno znamo (atribute 3. Redom posmatramo deo po deo stabla koji
terminala koji su zadati ulaznom sekvencom i odgovara primeni određene smene, gledamo u
nasleđeni atribut u korenu stabla). pravila šta se može izračunati.
<S> ,1
1. <S>p4,q1  ap1 <S>t1,p2 bs1 {c}q2,p3 <A>r1,q3 {dr2,s2,t2}
(p2, p3, p4)  p1 ( q2, q3 )  q1 s2  s1 t2  t1 r2  r1
a1 <S> b2 C <A> d

 b2 <A> <A> + <S>1 ,1

<S> e c6 e c7


a1 <S> b2 C <A> d

a3 <S> b4 c <A> d Na osnovu pravila p4  p1 iz smene 1.

 e c5
Programski prevodioci © 2007 Dragan Bojić 15 Programski prevodioci © 2007 Dragan Bojić 16

Računanje vrednosti atributa... Računanje vrednosti atributa...


4. Ceo postupak ponavljamo iterativno prolazeći  Sekvenca aktivnosti (listovi stabla):
više puta po potrebi kroz stablo dok sve ne a1 b2 c1,1 a3 b4 c1,3 e1 c5 d5,4,3 b2 e2
izračunamo, ili dok dalje računanje nije moguće.
<S> 1,1 c6 e2 c7 d6,7,3 d3,2,1

a1 <S> 1,1 b2 C1,1 <A> 3,1 d3,2,1  Ulaznu sekvencu (izostavimo akcione simbole):
a1 b2 a3 b4 c5 b2 c6 c7
 b2 <A> 6,2 <A> 7,2 +6,7,3

<S> 3,1 e2 C6 e2 C7  Ako iz sekvence aktivnosti izostavimo ulazne


simbole, dobijamo izlaznu sekvencu koja
predstavlja prevod date ulazne sekvence:
a3 <S> 3,3 b4 c1,3 <A> 5,1 d5,4,3
c1,1 c1,3 e1 d5,4,3 e2 e2 d6,7,3 d3,2,1
 e1 C5
Programski prevodioci © 2007 Dragan Bojić 17 Programski prevodioci © 2007 Dragan Bojić 18

3
Drugi primer ATG Prvo rešenje
 Dodeliti atribute sledećoj gramatici:  samo sintetizovani atributi
1. <integer> digit <more digits> 1. <integer>value digitval <more digits>v, b
2. <more digits>  digit <more digits> value  val * 10b + v
3. <more digits>  e 2. <more digits>v, b  digitval <more digits> v1, b1
 tako da neterminalni simbol <integer> ima v  val * 10b1 + v1 b  b1 + 1
sintetizovani atribut jednak vrednosti celog 3. <more digits> v, b  e
broja koji ovaj simbol generiše. v0 b0
 Pretpostaviti da ulazni simbol digit ima
atribut jednak vrednosti odgovarajuće cifre.

Programski prevodioci © 2007 Dragan Bojić 19 Programski prevodioci © 2007 Dragan Bojić 20

Drugo rešenje
 nasleđeni i sintetizovani, izbegava se  Translacione gramatike
stepenovanje
1. <integer>value  digitval <more digits>i,s  Atributivno-translacione gramatike
value  s i  val  Sintaksno-upravljano prevođenje od
Napomena: i nasleđen, s sintetizovan
dna ka vrhu
2. <more digits>i,s  digitval <more digits>i1,s1
i1  10i + val s  s1

3. <more digits>i,s  e si

Programski prevodioci © 2007 Dragan Bojić 21 Programski prevodioci © 2007 Dragan Bojić 22

Uslovi parsiranja atributivne gramatike Poljska translaciona gramatika

 Poljska translaciona gramatika  akcioni simboli su na samom kraju


& desne strane smene
 S-atributivna gramatika  Primeri:
<X>  a {T} {V} OK
<Y>  {R} OK
<Z>  {T} y NIJE OK

Programski prevodioci © 2007 Dragan Bojić 23 Programski prevodioci © 2007 Dragan Bojić 24

4
Poljska translaciona gramatika S-atributivna gramatika
 Ukoliko gramatika nije poljska, možemo je  Gramatika je S - atributivna, ako:
transformisati:
 Svi atributi neterminalnih simbola su
1. <X>  A {y} B
sintetizovani.
transformišemo u:
 Nijedan sintetizovani atribut ne može da zavisi
<X>  <N> B
od drugog sintetizovanog atributa iste pojave
<N>  A {y} simbola u gramatici.
 Druga varijanta:
 Nasleđeni atributi akcionih simbola smeju da
1. <X>  A <M> B zavise samo od atributa onih simbola produkcije
transformišemo u: koji su levo od tog akcionog simbola.
<M>  {y}

Programski prevodioci © 2007 Dragan Bojić 25 Programski prevodioci © 2007 Dragan Bojić 26

Primer Primer
1. <E>p  ( <E>q + <E>r )  ADD s1,s2,s3  Data S-atributivna poljska translaciona
s1  q, s2  r, p,s3  NEWT gramatika prevodi izraz u niz sastavljen od
atoma ADDp,q,r i MULTp,q,r gde su p, q i r
respektivno ukazatelji na levi operand, desni
2. <E>p  ( <E>q * <E>r )  MULT s1,s2,s3 operand i rezultat operacije u tabeli simbola
s2  q, s2  r, p,s3  NEWT (ekvivalent asemblerskom kodu).
 Novi ulaz u tabelu generišemo pozivom
funkcije NEWT.
3. <E>p  Ir  Atribut tokena I je ukazatalj na tabelu
simbola, na simbol koji odgovara tokenu I.
pr

Programski prevodioci © 2007 Dragan Bojić 27 Programski prevodioci © 2007 Dragan Bojić 28

Primer Konstrukcija potisnog BU procesora


 Za ulaz:
(1+(a*2))  prvo konstruišemo potisni prepoznavač
 Leksička analiza daje sledeću sekvencu terminala: (nekom od SR tehnika) za ulaznu gramatiku
( I1 + ( I2 * I3 ) ) -|  prepoznavač proširujemo u procesor:
 Indeksi uz I su brojevi ulaza u tabeli simbola (leks.  stek simboli sadrže i polja za atribute;
analizator je stavio konstante i promenljive u tab.  vrednosti svih atributa poznate su u trenutku
simbola). stavljanja na stek
Tabela simbola:  akciju REDUCE za svaku smenu proširujemo
Redni broj Naziv Tip računanjem svih atributivnih pravila te smene i
emitovanjem akcionih simbola navedenih u toj
1 1 C smeni na izlaz.
2 a V
3 2 C
Programski prevodioci © 2007 Dragan Bojić 29 Programski prevodioci © 2007 Dragan Bojić 30

5
Proširene REDUCE akcije za tekući primer
REDUCE(1): REDUCE(3) : Primer rada potisnog procesora za tekući primer
BEFORE AFTER BEFORE AFTER
 Stek Tek.ul Akc. Izlaz
) <E> I <E> 1.  ( I1 + ( I2 * I3 ) ) -| SHIFT
2. ( I1 + ( I2 * I3 ) ) -| SHIFT
3.  ( I1 + ( I2 * I3 ) ) -| REDUCE(3)
<E> NEWT vredn. r vredn. r 4.  ( <E>1 + ( I2 * I3 ) ) -| SHIFT
5.  ( <E>1 + ( I2 * I3 ) ) -| SHIFT
vredn. r .... ... ... 6.  ( <E>1 + ( I2 * I3 ) ) -| SHIFT
7.  ( <E>1 + ( I2 * I3 ) ) -| REDUCE(3)
+    8.  ( <E>1 + ( <E>2 * I3 ) ) -| SHIFT
9.  ( <E>1 + ( <E>2 * I3 ) ) -| SHIFT
<E> 10.  ( <E>1 + ( <E>2 * I3 ) ) -| REDUCE(3)
11.  ( <E>1 + ( <E>2 * <E>3 ) ) -| SHIFT
vredn. q REDUCE(2) je kao i REDUCE(1) samo 12.  ( <E>1 + ( <E>2 * <E>3) ) -| REDUCE(2) {MUL2,3,4}
 ( <E>1 + <E>4 ) -| SHIFT
umesto "+" stoji "*", a akcija je
13.

( 14.  ( <E>1 + <E>4 ) -| REDUCE(1) {ADD1,4,5}


OUTPUTMULTq,r,NEWT. 15.  <E>5 -| ACCEPT
...
OUTPUTADDq,r,NEWT
Programski prevodioci © 2007 Dragan Bojić 32

Primer rada potisnog procesora za tekući primer

 Konačni izlaz:
{MULT 2,3, 4}
{ADD 1,4, 5}
Konačna tabela simbola:
RB Naziv Tip
1 1 C
2 a V
3 2 C
4 t1 T
5 t2 T
Programski prevodioci © 2007 Dragan Bojić 33

6
 Uvod
Programski prevodioci 1  Konstrukcija parsera od vrha ka dnu
 Selekcioni skupovi i LL(1) gramatike
 Transformacije gramatika u LL(1)
Lekcija – Parsiranje od vrha ka  Sintaksno-upravljano prevođenje od
dnu (Top Down) vrha ka dnu

©2006 Dragan Bojić 1 Programski prevodioci © 2006 Dragan Bojić 2

Koncept parsiranja od vrha ka dnu Koncept parsiranja od vrha ka dnu


parser u svakom koraku rada pokušava da upari
 parser na ulazu ima kompletnu ulaznu 
tekući simbol iz sentencijalne forme koju trenutno
sekvencu (i poznatu gramatiku) razmatra, sa delom preostalog ulaza
 ako je tekući simbol terminal, onda mora biti isti terminal na
 potrebno je da parser rekonstruiše ulazu. Tada se samo prelazi na razmatranje sledećeg
simbola iz tekuće sentencijalne forme i sledećeg ulaznog
celokupno levo izvođenje ulazne simbola.
 ako je tekući simbol neterminal, bira se jedna od smena
sekvence, počev od startnog kojom se taj neterminal zamenjuje i na taj način dobija nova
sentencijalna forma za razmatranje. Izbor smene: tekući
neterminala ulaz mora biti u selekcionom skupu izabrane smene.
 procedura se ponavlja sve dok se ne rekonstruiše
celokupno levo izvođenje (ukoliko je zadata ulazna
sekvenca u jeziku razmatrane gramatike).

Programski prevodioci © 2006 Dragan Bojić 3 Programski prevodioci © 2006 Dragan Bojić 4

Primer Primer

1. <S>  a <A> <B>  parser počinje rad razmatranjem


2. <S>  b startnog neterminala i prvog znaka
3. <A>  c <B> ulazne sekvence
<S> => ? => acdd
4. <B>  d
  tekući ulaz
tekući neterminal
<S> => ? => acdd

Programski prevodioci © 2006 Dragan Bojić 5 Programski prevodioci © 2006 Dragan Bojić 6

1
Primer Primer
 Parser primenjuje izabranu smenu u prvom
 na parser bira smenu za <S> na koraku levog izvođenja:
osnovu tekućeg ulaza. U primeru, to je <S> =>lm a <A><B>=> ? => acdd
smena 1.  Novo stanje:
<S> =>lm a <A><B>=> ? => acdd
 U opštem slučaju, smena se bira ako je  
tekući ulaz neki terminalni simbol iz tekući simbol tekući ulaz
selekcionog skupa te smene.  Sada vidimo da se a u sentencijalnoj formi i a u
završnoj sentenci uparuju, pa tekući postaju:
<S> => lm a <A><B>=> ? => acdd
 
tekući simbol tekući ulaz
Programski prevodioci © 2006 Dragan Bojić 7 Programski prevodioci © 2006 Dragan Bojić 8

Primer Primer
 biramo smenu 3. za zamenu <A>:  uparivanje tekućeg terminala i tekućeg ulaza:
<S> =>lm a <A><B>=>lm a c <B> <B> => ? => acdd <S> =>lm a <A><B>=>lm a c <B> <B> =>lm a c d <B> => ? => acdd
   
tekući simbol tekući ulaz tekući simbol tekući ulaz
 Uparivanje tekućeg terminala i tekućeg ulaza:
<S> =>lm a <A><B>=>lm a c <B> <B> => ? => acdd  sada biramo smenu 4:
  <S> =>lm a <A><B>=>lm a c <B> <B> =>lm a c d d => ? => acdd
tekući simbol tekući ulaz  
 biramo smenu 4 na osnovu tekućeg ulaznog tekući simbol tekući ulaz
simbola:
 uparivanjem tekućeg terminala i tekućeg ulaza
<S> =>lm a <A><B>=>lm a c <B> <B> =>lm a c d <B> => ? => acdd
konstatujemo da je rekonstrukcija levog
  izvođenja uspešno okončana
tekući simbol tekući ulaz
Programski prevodioci © 2006 Dragan Bojić 9 Programski prevodioci © 2006 Dragan Bojić 10

Metodi konstrukcije TD parsera

 Uvod  metod rekurzivnog spusta


 Konstrukcija parsera od vrha ka dnu  tabelarni (u vidu potisnog automata)
 Selekcioni skupovi i LL(1) gramatike
 Transformacije gramatika u LL(1)
 Sintaksno-upravljano prevođenje od
vrha ka dnu

Programski prevodioci © 2006 Dragan Bojić 11 Programski prevodioci © 2006 Dragan Bojić 12

2
Metod rekurzivnog spusta Principi konstrukcije
 Primer gramatike za koju želimo da konstruišemo  Programsko rešenje čini glavni program i niz
parser: uzajamno rekurzivnih potprograma. Za svaki
1. <E> <T> <E_list> neterminal gramatike obezbeđuje se jedan
2. <E_List>  + <T> <E_List> potprogram (u konkretnom slučaju imaćemo
3. <E_list>  
potprograme PROCE, PROCE_LIST, PROCT,
PROCT_LIST i PROCP).
4. <T>  <P> <T_list>
 Potprogram za određeni neterminal ima ulogu
5. <T_List>  * <P> <T_List> da prepozna primenu neke od smena sa
6. <T_list>   datim neterminalom na levoj strani i upari
7. <P>  ( <E> ) neterminal sa ulazom u skladu sa
8. <P>  I prepoznatom smenom.

Programski prevodioci © 2006 Dragan Bojić 13 Programski prevodioci © 2006 Dragan Bojić 14

globalna promenljiva IN
Primer predstavlja tekući ulazni Kod za prepoznavanje smene
znak
procedure PROCP:  generalno, segmenti koda odgovaraju
case IN of pojedinim gramatičkim simbolima desne
‘I’ : goto P8; strane smene
‘(’ : goto P7;  neterminalu odgovara poziv odgovarajućeg
potprogrma, npr. za <E> je PROCE
‘+’, ‘*’, ‘)’, ‘─┤’: REJECT;  terminalu generalno odgovara sekvenca u
end case; kojoj se uparuje terminal u smeni sa tekućim
P8: kod za prepoznavanje 8. smene ulazom:
P7: kod za prepoznavanje 7. smene  ispituje da li je tekući ulaz jednak neterminalu,
end procedure;  ako jeste, procedurom NEXTCHAR se čita sledeći
primena pojedinih znak sa ulaza ()
smena prepoznaje se  ako nije, akcijom REJECT se odbija ulazna
koristeći njihove sekvenca
selekcione skupove
Programski prevodioci © 2006 Dragan Bojić 15 Programski prevodioci © 2006 Dragan Bojić 16

Primer za 7. <P>  (<E>) : Glavni program


P7:  inicijalizuje promenljivu IN da sadrži prvi
IN = NEXTCHAR(); ulazni znak.
call PROCE;  poziva potprograma za startni neterminal
if ( IN = ‘)’ ) čime inicira uparivanje ulazne sekvence
then IN = NEXTCHAR();  potom ispituje se da li je procesiran ceo ulaz
što označava da se ulazna sekvenca prihvata.
return;
 U suprotnom, ako tekući znak nije marker
else REJECT; kraja, sekvenca se odbija.
end if

Programski prevodioci © 2006 Dragan Bojić 17 Programski prevodioci © 2006 Dragan Bojić 18

3
procedure PROCE_LIST:
case IN of
Kompletan primer ‘+’ : goto P2;
‘)’, ‘ ─┤’ : goto P3;
procedure PROCP: ‘I’, ‘(’, ‘*’ : REJECT;
case IN of end case;
Glavni program:
‘I’ : goto P8;
IN = NEXTCHAR();
call PROCE;
‘(’ : goto P7;
P2: IN = NEXTCHAR();
call PROCT;
 Uvod
‘+’,‘*’,‘)’,‘─┤’:REJECT;
if (IN = ‘─┤’)
then ACCEPT;
end case;
call PROCE_LIST;
return;;  Konstrukcija parsera od vrha ka dnu
P8: IN = NEXTCHAR();
Selekcioni skupovi i LL(1) gramatike
else REJECT; P3: return;
return; 
end if; end procedure;
P7: IN = NEXTCHAR();
Transformacije gramatika u LL(1)
end; call PROCE;
if ( IN = ‘)’)
procedure PROCT_LIST: 
procedure PROCE: case IN of
Sintaksno-upravljano prevođenje od
then IN=NEXTCHAR();
case IN of ‘*’ : goto P5; 
procedure PROCT:
‘I’, ‘(’: goto P1; ‘+’, ‘)’, ‘ ─┤’ : goto P6;
‘+’,‘*’,‘)’,‘─┤’:REJECT;
case IN of
‘I’, ‘(’: goto P4;
‘I’, ‘(’ : REJECT; vrha ka dnu
end case; end case;
‘+’,‘*’,‘)’,‘─┤’: REJECT;
P1: call PROCT; P5: IN = NEXTCHAR();
end case;
call PROCE_LIST; call PROCP;
P4:call PROCP; call PROCT_LIST;
return;
call PROCT_LIST; return;
end procedure;
return; P6: return;
end procedure; end procedure;
Programski prevodioci © 2006 Dragan Bojić 19 Programski prevodioci © 2006 Dragan Bojić 20

Selekcioni skupovi LL(1) gramatike


 Da bi parser jednoznačno prepoznao smenu,
 Skup ulaznih simbola koji mogu selekcioni skupovi smena sa istom levom
predstavljati tekući ulaz u trenutku stranom moraju biti disjunktni:
SELECT(<X>  )  SELECT(<X> ) = ,
prepoznavanja smene <X>   od

,: 
strane potisnog automata, naziva se  Gramatike kod kojih je ovo ispunjeno nazivaju
selekcioni skup smene, u oznaci se LL(1) gramatike
SELECT(<X>  )  Značenje skraćenice: LL(1)
 parsira se sa (L)eva na desno
 nalazi se (L)evo izvođenje ulazne sekvence
 koristi se po (1) simbol sa ulaza unapred (enlg.
lookahead symbol)

Programski prevodioci © 2006 Dragan Bojić 21 Programski prevodioci © 2006 Dragan Bojić 22

Računanje selekcionih skupova Primer

 Za proizvoljnu produkciju <A>  ,  Za sledeću gramatiku sa startnim simbolom <A>:


1. <A> a <B> <C>
važi da je 2. <A>  b <B>
SELECT(<A>  ) = FIRST(), 3. <A>  
4. <B>  a <B> b
ako  nije poništiva sekvenca, ili
5. <B>  
SELECT(<A>)=FIRST()  6. <C>  b <C>
FOLLOW(<A>), 7. <C>  c
Odrediti SELECT skupove za svaku smenu i ispitati da
u suprotnom.

li se radi o LL(1) gramatici.

Programski prevodioci © 2006 Dragan Bojić 23 Programski prevodioci © 2006 Dragan Bojić 24

4
Primer Primer
 Moramo odrediti poništive neterminale, FIRST i SELECT(1)={a}
FOLLOW skupove: SELECT(2)={b}
1. <A> a<B><C> Pon = { <A>, <B>}
 b<B> SELECT(3)=FOLLOW(<A>)={─┤}
2. <A> FIRST(<A>)= {a, b }
3. <A>  FIRST (<B>)={a} SELECT(4)={a}
4. <B>  a<B>b SELECT(5)=FOLLOW(<B={ b, c, ─┤}
FIRST (<C>)= {b, c }
5. <B> 
 b<C> FOLLOW (<A>)= {─┤} SELECT(6)={b}
6. <C>
FOLLOW(<B>)=
7. <C> c SELECT(7)={c}
FIRST(<C>) FOLLOW(<A>) {b}= {b, c, ─┤}
FOLLOW(<C>) = Ovo jeste LL(1) gramatika jer ispunjava uslov da smene
FIRST( )FOLLOW(<A>)= {─┤} koje imaju identične leve strane, imaju disjunktne
selekcione skupove.
Programski prevodioci © 2006 Dragan Bojić 25 Programski prevodioci © 2006 Dragan Bojić 26

Primer
 Provera za smene 1. , 2. i 3. :  Uvod
SELECT(1)  SELECT(2) =   Konstrukcija parsera od vrha ka dnu
SELECT(1)  SELECT(3) =   Selekcioni skupovi i LL(1) gramatike
SELECT(2)  SELECT(3) =   Transformacije gramatika u LL(1)
 Provera za smene 4. i 5. :
 Sintaksno-upravljano prevođenje od
SELECT(4)  SELECT(5)=  vrha ka dnu
 Provera za smene 6. i 7. :
SELECT(6)  SELECT(7)= 

Programski prevodioci © 2006 Dragan Bojić 27 Programski prevodioci © 2006 Dragan Bojić 28

Transformacije gramatika za
dovođenje u LL(1) oblik Uklanjanje direktne leve rekurzije

 Uklanjanje direktne leve rekurzije <X>  <X> 


 Uklanjanje indirektne leve rekurzije <X>  
 Ideja transformacije: <X> opisuje sekvencu
 Leva faktorizacija
koja počinje jednim od  simbola, a nastavlja
se nizom  simbola.
 Ovaj niz  simbola posle početnog ,

možemo opisati uvođenjem novog


neterminala <Y> i korišćenjem desno
rekurzivnih smena

Programski prevodioci © 2006 Dragan Bojić 29 Programski prevodioci © 2006 Dragan Bojić 30

5
Uklanjanje indirektne leve
Uklanjanje direktne leve rekurzije rekurzije

<X>  <X> 1 <X>  1 <Y>  Primer indirektne leve rekurzije:


.... ....
<X>  <X> n transformiše se u: <X>  n <Y>
<X>  <Y> a
<X>  1 <Y>  1 <Y> <Y> <X> b
..... .... <Y> c
<X>  n <Y>  n <Y>
<Y>  

Programski prevodioci © 2006 Dragan Bojić 31 Programski prevodioci © 2006 Dragan Bojić 32

Uklanjanje indirektne leve rekurzije


Primer
 Algoritam:
Poređati neterminale u nekom redosledu A1, A2, …, An
for i  1 to n Ukloniti levu rekurziju iz sledeće
for j  1 to i – 1 gramatike:
zameniti svaku smenu oblika
<A>i  <A>j <S>  <E>
sa <E>  <E> + <T>
<A>i  1 | 2 |…| k,
gde su <A>j  1| 2|…| k sve aktuelne smene za <A>j <E>  <T>
end_for <T>  <E> - <T>
eliminisati direktno levo rekurzivne smene za <A>i
novodobijene neterminale dodati na kraj <T>  id
end_for
 pretpostavka algoritma je da inicijalna gramatika ne sadrži
cikluse (<A>i + <A>i )
Programski prevodioci © 2006 Dragan Bojić 33 Programski prevodioci © 2006 Dragan Bojić 34

Primer Primer
 usvajamo redosled <S>, <E>, <T>  i=3, j=1, <A>i = <T>, <A>j = <S>, nema
 prva iteracija, i=1, <A>i = <S>, ne ulazi se u unutrašnju petlju, promene
nema direktne leve rekurzije po <S>, nema promene gramatike
 i=2, j=1, <A>i = <E>, <A>j = <S>, u unutrašnjoj petlji nema  i=3, j=2, <A>i = <T>, <A>j = <E>, menja
promena, u spoljašnjoj eliminacija dir. rekurzije po <E>: se 5. smena
<S>  <E>
<E>  <T> <E'> <S>  <E>
<E'>  + <T> <E'> <E>  <T> <E'>
<E'> 
<T>  <E> - <T>
<E'>  + <T> <E'>
<T>  id <E'> 
<T>  <T> <E'> - <T>
<T>  id

Programski prevodioci © 2006 Dragan Bojić 35 Programski prevodioci © 2006 Dragan Bojić 36

6
Primer Primer
 i=3, <A>i = <T>, eliminacija direktne leve  i=4, <A>i = <E'>, za j=1, 2, 3 nema promene
rekurzije po <T>:  i=5, <A>i = <T'>, za j=1, 2, 3 nema promene, za
<S>  <E> j=4, <A>j = <E'>:
<S>  <E>
<E>  <T> <E'> <E>  <T> <E'>
<E'>  + <T> <E'> <E'>  + <T> <E'>
<E'>  <E'> 
<T>  id <T'> <T>  id <T'>
<T'> <E'> - <T> <T'> <T'> +<T> - <T> <T'>
<T'>   <T'> - <T> <T'>
<T'>  

Programski prevodioci © 2006 Dragan Bojić 37 Programski prevodioci © 2006 Dragan Bojić 38

Leva faktorizacija

 Pravilo leve faktorizacije glasi (uvodi se  Da li ove transformacije garantuju


novi neterminal <S'>): dovođenje u LL(1) oblik bilo koje
<S   1 <S   <S bezkontekstne gramatike?
....  <S  1  ne, problem transformacije u LL(1) je
neodlučiv.
<S   n ....
<S  n

Programski prevodioci © 2006 Dragan Bojić 39 Programski prevodioci © 2006 Dragan Bojić 40

 primer jezika koji se ne može opisati LL(1)


gramatikom:
{ an0bn | n  1 }  { an1b2n | n  1 }  Uvod
 gramatika za ovaj jezik – nije LL(1):  Konstrukcija parsera od vrha ka dnu
<S>  <S'>
<S>  <S''>  Selekcioni skupovi i LL(1) gramatike
<S'>  a0b  Transformacije gramatika u LL(1)
<S'> a<S'>b
<S''>  a1bb  Sintaksno-upravljano prevođenje od
<S''> a<S''>bb vrha ka dnu
 0 i 1 ne mogu biti u istoj smeni
 sa ulaza se moraju pročitati svi a simboli, kojih ima
proizvoljan broj, da bi se odredilo izvođenje

Programski prevodioci © 2006 Dragan Bojić 41 Programski prevodioci © 2006 Dragan Bojić 42

7
Sintaksno-upravljano prevođenje od Sintaksno-upravljano prevođenje od
vrha ka dnu vrha ka dnu
 Kojim redom rekurz. parser pri prepoznavanju
 Kojim redom rekurz. parser pri prepoznavanju smene <A>  <B><C> određuje atribute?
smene <A>  <B><C> određuje atribute? 5. posle uparivanja sa ulazom <C> saznajemo
 nasleđeni atributi X su ulazni parametri za PROCX sintetizovane atribute od <C>
 sintetizovani atr. X su izlazni parametri za PROCX 6. kad uparimo celu desnu stranu izračunavamo
1. nasleđeni atributi od <A> su već poznati (prosleđuje sintetizovane atribute od <A>
pozivalac). 7. vraćanje kontrole pozivaocu sa sint. atr. <A>
2. nasleđeni atributi od <B> zavise od nasleđenih od  moraju se uvesti ograničenja u pravila
<A> i oni se izračunavaju izračunavanja atributa, da bi parser paralelno sa
3. posle uparivanja <B> sa ulazom saznaćemo konstrukcijom stabla izvođenja (od vrha ka dnu)
sintetizovane atribute <B> računao vrednosti svih atributa).
4. nasleđeni atributi od <C> zavise od nasleđenih od  Gramatike koje zadovoljavaju ova pravila nazivaju
<A> i bilo kog atributa <B> se L-atributivne gramatike

Programski prevodioci © 2006 Dragan Bojić 43 Programski prevodioci © 2006 Dragan Bojić 44

Uslovi L-atributivnosti gramatike Primer


 Nasleđeni atributi simbola sa desne strane  Sledeće smene su deo neke atributivne
smene mogu da zavise od nasleđenog atributa
simbola sa leve strane i bilo kog atributa bilo kog gramatike. U svakoj od njih, p, q i r su
simbola koji je na desnoj strani ispred posmatranog nasleđeni atributi, a s i t sintetizovani. Za
simbola. svaku od smena pronaći od kojih sve atributa
 Sintetizovani atribut simbola sa leve strane mogu da zavise atributi p i r da bi smena bila
smene može da zavisi od nasleđenih atributa tog
simbola i od bilo kog atributa bilo kog simbola sa L-atributivna.
desne strane. a) <S>s,q  au <S>t,p <A>r
Sintetizovani atribut akcionog simbola sme da

zavisi isključivo od nasleđenog atributa istog b) <S>s,q  {cp} bu <S>t,r
akcionog simbola. c) <S>s,q  cu <A>r <S>t,p

Programski prevodioci © 2006 Dragan Bojić 45 Programski prevodioci © 2006 Dragan Bojić 46

Konstrukcija sintaksno-upravljanog procesora za


Rešenje L-atributivne LL(1) translacione gramatike

a) <S>s,q at,r<S>t,p<A>r  Osnovne ideje


p = f1(q, u), r = f2(q, u, t, p)  Nasleđeni atributi se prenose po vrednosti,
sintetizovani atributi se prenose po adresi
s=f3(q, u, t, p,r)  Svi atributi koji su sa desne strane postaju
lokalne promenljive.
b) <S>s,q  {cp} bu <S>t,r  Svi atributi istog simbola sa leve strane
p = f1(q), moraju imati isto ime (formalni parametri)
r = f2(q, p, u) u - sintetizovan.  Pravilo x  y može se eliminisati tako da se x
preimenuje u y ili obrnuto (pri tome se ne
c) <S>s,q  cu <A>r <S>t,p smeju menjati imena atributa sa leve strane)
p = f1(q, u, r)
r = f2(q, u)
Programski prevodioci © 2006 Dragan Bojić 47 Programski prevodioci © 2006 Dragan Bojić 48

8
Primer Preuređena gramatika
1. <S>q  ax1 <A>x,y,z <S>q1 {bw} 1. <S>q  ax <A>x,y,z <S>q {bw}
(x1 postalo x, q1 postalo q)
w  y * z + q1 x  x1 q  q1 wy*z+q
2. <S>r1  b ay {cw} <A>u,r,x {bv}  <S>q  b ay {cw} <A>u,r,x {bv}
(r1 postalo q, r postalo q)
wy+3 r1  r vr*x-w u wy+3 vq*x-w uw+2
w+2  <A>x,y,z1  aq {cv} <A>x,z1,u1 <A>u,t,y
3. <A>x,y,z1  aq {cv} <A>x1,z,u1 <A>u,t,y1 (x1 postalo x, z postalo z1, y1 postalo y)
vx-q u3
vx-q x1  x y  y1 z1  z  <A>x,y,z1  b aq {bx} as2
u3 (t i t1 postali x, s postalo y, s1 postalo z1)
(y,z1)  s2
4. <A>t,s,s1  b aq {bt1} as2
t1  t (s,s1)  s2

Programski prevodioci © 2006 Dragan Bojić 49 Programski prevodioci © 2006 Dragan Bojić 50

Implementacija parsera (pseudokod) Implementacija parsera (pseudokod)


Program Parser; procedure S (var q :integer)
type ulaz = record of var x,y,z,w,u,v :integer;
ime:char; begin
atrib: integer; case u.ime of
end; 'a': x := u.atrib;
var q: integer;
ADVANCE;
A(x,y,z);
u: ulaz; S(q);
procedure ADVANCE; w := y * z + q;
begin out (b,w);
u.ime = sledeći ulazni simbol; 'b': ADVANCE;
u.atrib = njegov atribut; if u.ime <> 'a' then REJECT;
end; y := u.atrib;
procedure ACCEPT; ADVANCE;
begin w := y + 3;
kraj rada sa prihvatanjem ulaza out ('c', w);
u := w + 2;
end; A(u,q,x);
procedure REJECT; v := q * x - w;
begin out ('b', v);
kraj rada sa neprihvatanjem ulaza default: REJECT;
end; end; {od "case"}
end; {od "begin"}
Programski prevodioci © 2006 Dragan Bojić 51 Programski prevodioci © 2006 Dragan Bojić 52

Implementacija parsera (pseudokod) Implementacija parsera (pseudokod)


procedure A(x:integer,var y,z1:integer) begin {main}
var q,v,u,u1,s2, t:integer; ADVANCE;
begin S(q);
case u.ime of if u.ime=ENDMARKER then ACCEPT
'a': q:=u.atrib; else REJECT;
ADVANCE; end.
v:=x-q;
u:=3;
out ('c', v);
A(x,z1,u1);
A(u,t,y);
'b': ADVANCE;
if u.ime <> 'a' then REJECT;
q:=u.atrib;
ADVANCE;
out ('b', x);
if u.ime <>'a' then REJECT;
s2:=u.atrib;
ADVANCE;
y:=s2;
z1:=s2;
default: REJECT;
end;
end;
Programski prevodioci © 2006 Dragan Bojić 53 Programski prevodioci © 2006 Dragan Bojić 54

9
 Uvod
Programski prevodioci 1  Organizacija tabele simbola
 Predstavljanje informacija o objektima
 Predstavljanje informacija o opsezima
Lekcija – Konstrukcija tabele imena
simbola  Operacije nad tabelom simbola

©2006 Dragan Bojić 1 Programski prevodioci © 2006 Dragan Bojić 2

Uloga tabele simbola u kompajleru Preliminarni interfejs tabele simbola

 Pamćenje informacija o svim  Prema drugim delovima kompajlera


deklarisanim objektima:
 Ime, tip, vrednost (za konstante), adresa class Table {
(za promenljive i metode), parametri (za
metode), itd static Object insert(String name,…);
 Nalaženje informacija o korišćenim static Object find(String name,…);
objektima }
 Mapiranje imena  tip, vrednost, adresa,…

Programski prevodioci © 2006 Dragan Bojić 3 Programski prevodioci © 2006 Dragan Bojić 4

Interna organizacija tabele simbola

 Uvod  Dinamička struktura podataka: skup objektnih


i strukturnih zapisa
 Organizacija tabele simbola
 Objektni zapisi (instance klase Object)
 Predstavljanje informacija o objektima čuvaju informaciju o deklarisanim imenima
 Predstavljanje informacija o opsezima  Strukturni zapisi (instance klase Struct)
imena čuvaju informacije o tipovima u programu (na
 Operacije nad tabelom simbola njih ukazuju objektni zapisi)

Programski prevodioci © 2006 Dragan Bojić 5 Programski prevodioci © 2006 Dragan Bojić 6

1
Organizacija tabele simbola: moguće
strukture podataka TS u vidu jednostruko ulančane liste
 Primer deklaracija mikroJave:
 Jednostruko ulančana (neuređena) lista final int n=10;
class T {…}
 Binarno leksički uređeno stablo int a, b, c;
 Heš tabela void m(){…}

 Prednosti: jednostavnost, zapamćen redosled deklarisanja


 Nedostatak: sporost pretrage ako kada ima mnogo imena
 (u nastavku predavanja o TS biće usvojena ova
realizacija)

Programski prevodioci © 2006 Dragan Bojić 7 Programski prevodioci © 2006 Dragan Bojić 8

TS u vidu binarnog stabla TS u vidu heš tabele


final int n=10; final int n=10;
class T {…} class T {…}
int a, b, c;
int a, b, c; void m(){…}
void m(){…}

 Prednosti: brža pretraga (log n)


Nedostaci: veća potrošnja prostora

 Prednost: brzina
i vremena pri ažuriranju (isplati se
samo ako ima mnogo deklaracija)  Nedostaci: komplikovanije u odnosu na listu,
 Originalni redosled deklaracija je izgubljen redosled deklaracija se gubi

Programski prevodioci © 2006 Dragan Bojić 9 Programski prevodioci © 2006 Dragan Bojić 10

Zapisi o objektima

 Uvod  Svako deklarisano ime se pamti se u


 Organizacija tabele simbola jednom objektnom zapisu
 Vrste objekata:
 Predstavljanje informacija o objektima static final int
 Predstavljanje informacija o opsezima Con = 0, // constants
imena Var = 1, // variables, parameters
Typ = 2, // types
 Operacije nad tabelom simbola Meth = 3, // methods
Fld = 4; // fields

Programski prevodioci © 2006 Dragan Bojić 11 Programski prevodioci © 2006 Dragan Bojić 12

2
Informacije o objektu Informacije o objektu: adrese
 Globalnih promenljivih
 Za sve vrste objekata:
 ime, vrsta, tip, sledeći zapis  U mjVM se čuvaju u oblasti globalnih podataka:
 Dodatne specifične informacije:
 Za konstante: vrednost
 Za promenljive: adresa, nivo deklarisanosti
(lokalne, globalne)
 Za polja klase: pomeraj  Svaka mJ promenljiva zauzima po 1 memorijsku reč
 Za metode: adresa, broj parametara, lista  Adrese promenljivih su relativne u odnosu na početak
formalnih parametara i lokalnih objekata oblasti globalnih podataka
 Adrese se dodeljuju sukcesivno

Programski prevodioci © 2006 Dragan Bojić 13 Programski prevodioci © 2006 Dragan Bojić 14

Struktura podataka za predstavljanje


Informacije o objektu: adrese objekata
 Lokalnih promenljivih
 U mjVM se čuvaju na steku poziva (metoda), u aktivacionom zapisu  Pravolinijsko rešenje u duhu OO:
(okviru) metoda:

 Kada se pristupa atributima podklasa


zahteva eksplicitnu konverziju (nešto
Svaka mJ promenljiva zauzima po 1 memorijsku reč
komplikovaniji kod)

 Adrese promenljivih su relativne u odnosu na pokazivač okvira


(frame pointer)
 Adrese se dodeljuju sukcesivno
Programski prevodioci © 2006 Dragan Bojić 15 Programski prevodioci © 2006 Dragan Bojić 16

Struktura podataka za predstavljanje


objekata Primer
 Za naše potrebe, usvojićemo “ravnu” implementaciju: svi final int n = 10;
atributi će biti deklarisani u istoj klasi Object class T {…}
class Object { int a, b, c;
static final int Con = 0, Var = 1, Typ = 2, Fld = 3, void m (int x) {…}
Meth = 4;
int kind; // Con, Var, Typ, Fld, Meth
String name;
Struct typ;
Obj next;
int adr; // Con: value; Var, Fld, Meth: address
intlevel; // Var: declaration level; Meth: no.of.
parameters
Obj locals; // Meth: local objects
}
Programski prevodioci © 2006 Dragan Bojić 17 Programski prevodioci © 2006 Dragan Bojić 18

3
Struktura podataka za
Preddeklarisana imena preddeklarisana imena
 Posebna lista objekata:

 Šta se unapred deklariše u TS (na


početku prevođenja):
 Standardni tipovi: int, char
 Standardni metodi: ord(ch), chr(i), len(arr)
 Standardne konstante: null

 Druga, lošija varijanta: posebne ključne reči


 Zahteva posebne terminale u gramatici
 Komplikovanije, niz specijalnih slučajeva pri pretrazi i ažuriranju TS
Programski prevodioci © 2006 Dragan Bojić 19 Programski prevodioci © 2006 Dragan Bojić 20

Predstavljanje opsega važenja imena


u TS

 Uvod  Hijerarhija opsega imena u programu:


 Organizacija tabele simbola  Opseg preddeklarisanih imena “universe”
 Opseg globalnih imena u celom programu
 Predstavljanje informacija o objektima  Opseg klase (polja i metodi određene
 Predstavljanje informacija o opsezima klase)
imena  Opseg metoda (parametri i lokalna imena)
 Operacije nad tabelom simbola  Svaki opseg je posebna kolekcija (lista)
objekata

Programski prevodioci © 2006 Dragan Bojić 21 Programski prevodioci © 2006 Dragan Bojić 22

Predstavljanje opsega važenja imena


u TS Primer
 Za predstavljanje opsega uvodimo zapis Scope:
class Scope {
Scope outer; // to outer scope
Obj locals; // to the objects of this scope program scope
int nVars; // number of variables in this scope (for
addr.
allocation)
}
Scope topScope; // this is an attribute of class Tab

 Kolekcija tipa steka pamti trenutno aktivne


opsege u programu

Programski prevodioci © 2006 Dragan Bojić 23 Programski prevodioci © 2006 Dragan Bojić 24

4
Pretraga imena u TS

 Uvod  Prilikom svakog korišćenja nekog


 Organizacija tabele simbola simbola poziva se find
 Predstavljanje informacija o objektima obj = tab.find(name);

 Predstavljanje informacija o opsezima  Pretraga počinje u listi topScope


imena  Ako se ne nađe tamo, pretraga se
 Operacije nad tabelom simbola nastavlja u sledećem okružujućem
opsegu (sledeći na steku ispod)

Programski prevodioci © 2006 Dragan Bojić 25 Programski prevodioci © 2006 Dragan Bojić 26

Pretraga imena u TS Pretraga imena u TS


 Algoritam:  Ako se ime nigde ne nađe vraća se noObj
static Object find (String name) {  Radi se o posebnom preddeklarisanom objektu
for (Scope s = topScope; s != null; s = s.outer)
for (Object p = s.locals; p != null; p = p.next)
if (p.name.equals(name)) return p;
error(name + " not found");
return noObj;
}
 Ovako se rezultat find lakše koristi, nego da je
vraćena null vrednost
Programski prevodioci © 2006 Dragan Bojić 27 Programski prevodioci © 2006 Dragan Bojić 28

Ubacivanje imena u TS Gde se poziva insert()?


 Za svaku deklaraciju pozivamo insert:
obj = Tab.insert(kind, name, typ);
 U parseru, unutar smena za deklaracije.
 Aktivnosti unutar insert():
 Proverava da li već postoji objekat istog imena (samo) u
topScope, ako ima => greška
 U suprotnom, kreira novi Object(kind, name, type)  Primer: deklaracija promenljive
 Dodeljuje mu adresu (prvu slobodnu) VarDecl = Typetyp identname (: Tab.insert(Obj.Var, name, typ) :)
 Dodeljuje nivo deklaracije (global=0, local=1) { "," identname (: Tab.insert(Obj.Var, name, typ) :) }.
 Dodaje objekat na kraj liste topScope

Programski prevodioci © 2006 Dragan Bojić 29 Programski prevodioci © 2006 Dragan Bojić 30

5
Obrada opsega Obrada opsega
 Dva nova metoda u interfejsu tabele simbola:  Za zatvaranje opsega:
za otvaranje i zatvaranje opsega
static void closeScope() {
topScope = topScope.outer;
 Za otvaranje opsega:
}
static void openScope() {
Scope s = new Scope();  Poziva se kada parser naiđe na kraj opsega
s.outer = topScope; topScope = s; (kraj programa, } od klase ili metoda)
}
 Sa vrha steka opsega skida tekući opseg
 Poziva se kada parser naiđe na početak
opsega (početak programa, iza imena klase,
ili metoda)
 Na vrh steka opsega stavlja novi opseg
Programski prevodioci © 2006 Dragan Bojić 31 Programski prevodioci © 2006 Dragan Bojić 32

Primer upotrebe Primer upotrebe


MethodDecl
= Typetyp
identname (: meth=Tab.insert(Obj.Meth, name, typ);
Tab.openScope() :)

"}" (: meth.locals = Tab.topScope.locals;
Tab.closeScope(); :).

 Napomena: atribut typ je tipa Struct, name tipa String, meth


tipa Object

Programski prevodioci © 2006 Dragan Bojić 33 Programski prevodioci © 2006 Dragan Bojić 34

Primer upotrebe Primer upotrebe

Programski prevodioci © 2006 Dragan Bojić 35 Programski prevodioci © 2006 Dragan Bojić 36

6
Primer upotrebe Interfejs tabele simbola (finalno)
class Tab {
static Scope topScope; // current top scope
static int level; // nesting level of current scope
static Struct intTyp; // predeclared types
static Struct charTyp;
static Struct nullTyp;
static Struct noTyp;
static Obj chrObj; // predeclared objects
static Obj ordObj;
static Obj lenObj;
static Obj noObj;
static Obj insert (int kind, String name, Struct typ);
static Obj find (String name);
static void openScope();
static void closeScope();
}

Programski prevodioci © 2006 Dragan Bojić 37 Programski prevodioci © 2006 Dragan Bojić 38

7
Semantička analiza – Tipovi podataka

 Svaki programski konstrukt (deklaracija, izraz, iskaz) ima svoj tip


 Vrste tipova:
o osnovni (u Mikrojavi int, char)
o izvedeni. U mikrojavi:
 nizovi
 klase
 Tipovi imaju strukturu, tj. osobine:
o memorijsko zauzeće
o za izvedene (tipovi elemenata, definicije članova, …)

Predstavljanje tipova

 Tipove možemo predstavljati tzv. izrazima tipa (engl. type expressions).


- osnovni tip predstavlja izraz tipa
- ime tipa predstavlja izraz tipa
- izvedeni tipovi se dobijaju primenom tzv. konstruktora izvedenog tipa na neki izraz
tipa.
 Pogodan metod za predstavljanje izraza tipa su grafovi. U slučaju Mikrojave, grafovi tipova sadržaće
Struct čvorove i po potrebi Obj čvorove (npr. za imena članova klasa).

Predstavljanje tipova grafom

 Izgled Struct čvora (instanca istoimene klase):

class Struct {
static final int // kinds of types
None = 0, Int = 1, Char = 2, Arr = 3; Class = 4;
int kind; // None, Int, Char, Arr, Class
Struct elemTyp; // Arr: element type
int n; // Class: number of fields
Obj fields; // Class: list of fields
}

Grafovi osnovnih tipova


Predstavljanje tipa niza

Predstavljanje tipa klase

Preddefinisana imena i njihovi tipovi u tabeli simbola


Sistem tipova
 Sistem tipova je skup pravila kako se dodeljuju tipovi različitim delovima programa (deklaracijama,
izrazima, iskazima).
 Za mikrojavu sistem tipova definisan je sekcijama A.3 Semantics i A.4 Context Conditions
specifikacije.
 Proverom tipa implementira se određeni sistem tipova. Provera može biti:
 statička, ako je vrši kompajler, ili
 dinamička, ako se izvodi u vreme izvršavanja programa (pod uslovom da objekti u programu
nose informaciju o tipu u vreme izvršavanja).
 Primer: C++ RTTI – Run time type information, typeid i dynamic_cast operatori
 Jezik se naziva strogo tipiziranim (engl. strongly typed) ako uspešna statička provera tipova
garantuje da u izvršavanju programa neće doći do greške.

Ekvivalentost izraza tipova


 kada se za dva izraza tipa može reći da predstavljaju međusobno zamenljive tipove?
 dve vrste ekvivalencije tipova:
 po imenu
 strukturna.
Ekvivalentost tipova po imenu

 dva tipa su ekvivalentna ako su reprezentovana istim čvorom tipa u grafu (tj. imaju isto ime).
 a i b imaju isti tip.
 u Mikrojavi ekvivalentnost tipova je po imenu, sa izuzetkom nizova: dva niza su ekvivalentna
ako su im tipovi elemenata ekvivalentni.

Ekvivalentost tipova po strukturi


 dva tipa su ekvivalentna ako imaju istu strukturu (topologiju grafa)
 Primer: tipovi promenljivih v i w su ekv. po strukt (ali to definicija mikrojave ne dopušta). U C-u
se svuda primenjuje ekv. po imenu, osim kod zapisa gde se gleda struktura.

Provera tipova u mikrojavi

class Struct {
...
// checks, if two types are compatible (e.g. in comparisons)
public bool CompatibleWith (Struct other) {
return this.Equals(other) ||
this == Tab.nullType && other.IsRefType() ||
other == Tab.nullType && this.isRefType();
}
// checks, if this can be assigned to dest
public bool AssignableTo (Struct dest) {
return this.Equals(dest) ||
this == Tab.nullType && dest.IsRefType() ||
kind == Kinds.Arr && dest.kind == Kinds.Arr && // for len()
dest.elemType == Tab.noType;
}
// checks, if two types are equal (structural equivalence for array,
// name equivalence otherwise)
public bool Equals (Struct other) {
if (kind == Kinds.Arr)
return other.kind == Kinds.Arr && elemType.Equals(other.elemType);
return other == this;
}
public bool IsRefType() { return kind == Kinds.Class || kind = Kinds.Arr; }
}

Ostale stvari u vezi tipova (nema ih u Mikrojavi):


 konverzije tipova: na primer, u izrazima gde se koriste operandi različitih tipova, kao što je
sabiranje celobrojne vrednosti sa realnom, mora se operand konvertovati u drugi tip (ceo broj u
realni).
o Ako konverziju eksplicitno navodi programer, radi se o eksplicitnoj konverziji (npr. operator
cast u Cu (int)x).
o Ako konverziju ne navodi programer, nego je automatski uradi kompajler, reč je o
implicitnoj konverziji (engl. coercion)
 preklapanje funkcija i operatora (engl. overloading): kada isto ime ima različita značenja u
zavisnosti od konteksta. Na primer, u C++u:
o int fja( int x ) { x = 1; }
o int fja ( T& t ) { t.end = true; }
su dve funkcije istog imena.
 polimorfmne funkcije dozvoljavaju izvršavanje sa argumentima različitih tipova. Tipičan primer je
funkcija koja prima referencu na baznu klasu, koja može biti pozvana sa objektom izvedene klase u
objektno-orijentisanim jezicima.
TABELE SIMBOLA

Tekući opseg važenja imena i pravila vidljivosti

Bilo koja linija koda sadrži se unutar jedne programske jedinice ili više programskih jedinica koje
definišu opseg važenja imena. Većina savremenih jezika je blokovski strukturirana - dozvoljava
da opseg važenja imena bude ugnježden.

otvoreni teku}i opseg


opsezi va`enja
va`enja zatvoren
opseg
va`enja

linija koda

Tekući opseg važenja je opseg važenja imena definisan trenutnim najdubljim ugnježdenjem.
Otvoreni opsezi su tekući opseg važenja i svi opsezi koji okružuju tekuću liniju koda.
Zatvoreni opsezi su opsezi važenja imena definisani bilo kojom programskom jedinicom koja ne
okružuje posmatranu liniju izvornog koda.
Tekući opseg važenja nije fiksan već s menja dinamički zavisno od tumačenja.

Skup statičkih pravila vidljivosti:


1. U bilo kojoj tački izvršnog programa pristupačna su samo imena deklarisana u tekućem opsegu
važenja i u otvorenim opsezima važenja koji sadrže tekući opseg važenja
2. Ako je ime deklarisano u više od jednog opsega važenja, za interpretaciju tog imena koristi se
deklaracija čija je dubina najveća i najbliža tački obraćanja.
3. Nove deklaracije se dozvoljavaju samo u tekućem opsegu važenja.
Očigledna posledica ovih pravila je da pri zatvaranju nekog opsega, sve deklaracije zadate u
njemu postaju nepristupačne.
Primer:

Na mestu tekuća pozicija u programu vidljiva su sledeća imena:


A,C,M:character
H,L,:integer
Nisu vidljivi X i Y jer je njihov blok zatvoren, dok se vidi A iz treće deklaracije a ne iz prve zbog
drugog pravila vidljivosti.

Realizacija tabele simbola

U zavisnosti od opsega važenja postoje dva pristupa realizaciji tabele simbola:


1. pojedinačna tabela simbola za svaki opseg važenja
2. jedinstvena tabela za sve opsege važenja

Pojedinačne tabele za svaki opseg važenja

Kod pojedinačnih tabela simbola za svaki opseg važenja stek mehanizam je pogodan za
realizaciju. Pri otvaranju novog opsega stavlja se tabela simbola na stek, a po zatvaranju opsega
skida se sa steka. Umesto cele tabele može se koristiti i samo ukazatelj na tabelu.
Nedostaci ovog pristupa su:
i) Ako želimo da pristupimo nekom nelokalnom imenu moramo pristupati većem broju tabela
simbola, pogotovo ako želimo da pristupimo nekom globalnom imenu.
ii) Ako su tabele realizovane kao heš tabele, za svaki opseg važenja se rezerviše memorijski
prostor za tabelu simbola. Na duboko ugnježdenim nivoima gde ima malo imena gubitak prostora
je najveći (nije veliki problem danas kada računari imaju puno memorije). Ovaj problem se ne
javlja ako su tabele organizovane u obliku binarnog stabla.

Jedinstvena tabela simbola za sve opsege

Sva imena koja se pojave u toku prevodjenja se smeštaju u jedinstvenu tabelu simbola. Pošto se
može desiti da u različitim opsezima važenja imamo ista imena, svakom imenu se pridruži opseg
važenja za koji je to ime definisano. (Posebna globalna promenljiva „broji” trenutno otvorene
opsege, inkrementira se pri otvaranju opsega, dekrementira pri zatvaranju).

Primer:
{ int M, A, L;

{float X, Y;

}
{char A, C, M;

/* trenutna pozicija*/
}
}
Jedinstvena tabela se može realizovati kao heš tabela
A(2 ) L(1) A(1)

C(2 ) M(1)

M(2)

heš tabela
Prednosti heš tabele simbola su:
i) Brži je pristup simbolu jer se pretražuje samo jedna tabela, i obično su ti traženi simboli na
početku lanaca.
ii) Memorijski prostor je efikasnije iskorišćen jer imamo samo jedno zaglavlje tabele, ali je taj
dobitak umanjen zato što se uz svako ime dodaje prostor za opseg važenja.
Realizacija jedinstvene tabele simbola korišćenjem binarnog, leksikografski
uređenog, stabla

Kod ovog načina realizacije tabele simbola, svi simboli formiraju stablo. Ubacivanje novih simbola
pri otvaranju novog opsega važenja i izbacivanje simbola pri zatvaranju opsega važenja zahteva
pretraživanje stabla do listova, što nije baš efikasno pa se ne preporučuje ova struktura podataka
ukoliko imamo jednu tabelu za sve opsege važenja. Binarno stablo se može koristiti kada imamo
pojedinačne tabele za sve opsege važenja.
Primer:
{ int M, A, L;

{float X, Y;

}
{char A, C, M;

/* trenutna pozicija*/
}
}
M(1)

A(1) L(1)

A(2) L(2) M(2)

Realizacija jedinstvene tabele u vidu steka.

U tom slučaju na vrhu steka se nalaze simboli iz tekućeg opsega važenja, i razdvojeni su od
simbola iz predhodnog opsega važenja sa markerom. Kada se opseg zatvara sve što se nalazi na
steku iznad markera se skida sa steka. Ovakva tabela je korišćena u ranim verzijama prevodilaca.

markeri
Izvršno okruženje

Uvod

 Definiše se kao podrška pri izvršavanju programa na višem programskom jeziku.


 Obuhvata sledeća razmatranja:
o Izvršna organizacija memorije -- kako se predstavljaju različiti tipovi podataka i kako se
dodeljuje memorija promenljivama različitih memorijskih klasa u programu? Kako se
pristupa ovim promenljivama?
o Pravila vidljivosti -- Kako upotreba određene promenljive uparuje sa odgovarajućom
deklaracijom? Kako se iz određene procedure pristupa promenljivoj koja nije definisana u toj
proceduri (nelokalnoj promenljivoj)?
o Poziv procedura – Kako se generiše kod za poziv i povratak iz potprograma? Kako se pri
pozivu procedura prenose stvarni parametri? Kako se realizuju rekurzivne procedure?
o Itd (podrška obradi izuzetaka, podrška simboličkom debagovanju, podrška dinamičkom
povezivanju...)

Izvršna organizacija memorije

 Jedna moguća podela operativne memorije u vreme izvršavanja programa:


najviša
adresa
oblast steka
} nepopunjena
oblast
oblast dinamičkih
podataka
 granice poznate u
oblast statičkih
podataka  vreme prevođenja


oblast programskog
koda
0
Slika 1

 Za oblast steka najčešće se koristi procesorski stek (mada nije obavezno, na primer kada stek
procesora nije u operativnoj memoriji).

 S obzirom da se veličine steka i oblasti dinamičkih podataka menjaju u toku izvršavanja programa,
nije određena fiksna granica između ove dve oblasti već se svaka od njih može proširivati po potrebi
do trenutka njihovog eventualnog međusobnog susreta.

 U ovom kontekstu termin statički generalno se koristi za veličine koje su poznate u vreme
prevođenja programa (pre njegovog izvršavanja), dok se termin dinamički odnosi na veličine koje
nisu poznate u vreme prevođenja, to jest, menjaju se tokom izvršavanja programa.
Memorijske klase promenljivih

 Vrednost neke promenljive u toku izvršavanja programa može se čuvati na različitim mestima:
o u procesorskom registru (takozvane registarske promenljive);
o u oblasti statičkih podataka (takozvane statičke promenljive);
o u oblasti steka (takozvane automatske promenljive) ili
o u oblasti dinamičkih podataka (takozvane dinamičke promenljive).
 Drugim rečima, promenljive poseduju različite memorijske klase (engl. storage class).

Memorijske klase promenljivih u nekim programskim jezicima

 U Pascal-u, na primer, promenljive deklarisane u glavnom programu smeštaju se statički, lokalne


promenljive procedura (uključujući i parametre) smeštaju se najčešće na steku dok programer može
eksplicitno alocirati (zauzeti) deo memorije iz dinamičke oblasti korišćenjem standardne funkcije
new.
 U C-u se globalne promenljive (deklarisane izvan procedura) smeštaju statički, dok se lokalne
promenljive procedura (i njihovi parametri) smeštaju na steku, a standardnom funkcijom malloc
programer može eksplicitno alocirati deo memorije iz dinamičke oblasti. Programer može uticati na
smeštanje promenljive navođenjem, u deklaraciji promenljive, takozvanog specifikatora memorijske
klase (register, static ili auto).

Način pristupa skalarnoj (na primer, celobrojnoj) promenljivoj

 zavisi od njene memorijske klase:


o Registarskim promenljivama se pristupa registarskim direktnim adresiranjem.
o Statičkim promenljivama se pristupa memorijskim direktnim adresiranjem s obzirom da
su veličina i početna adresa smeštanja promenljive u memoriji poznati u vreme prevođenja
programa.
o Automatskim promenljivama se pristupa baznim adresiranjem, što će detaljnije biti
objašnjeno u nastavku.
o Dinamičkim promenljivama se pristupa nekom vrstom indirektnog adresiranja. Adrese
ovih promenljivih ne mogu biti ugrađene u programski kod s obzirom da nisu poznate u
vreme prevođenja

Studija slučaja: Arhitektura procesora Intel 80x86

Kod mikroprocesora Intel 8086 za rad sa stekom koriste se 16-bitni registri SP (Stack Pointer) i BP (Base
Pointer) i instrukcije navedene u tabeli 1
Tabela 1
Instrukcija Objašnjenje
PUSH r/m stavlja vrednost operanda na stek
POP r/m skida vrednost sa vrha steka i dodeljuje je operandu
CALL r/m stavlja tekuću vrednost brojača naredbi IP na stek i vrši skok na adresu
specificiranu operandom
RET [c] SP uvećava za vrednost specificiranu operandom c; skida vrednost sa vrha steka i
dodeljuje brojaču naredbi IP
ADD dst, src Sabira vrednost operanda src sa operandom dst i rezultat smešta u dst
SUB dst, src Oduzima vrednost operanda src sa operandom dst i rezultat smešta u dst
MOV dst, src Dodeljuje operandu dst vrednost operanda src

Oznake korišćene za operande imaju sledeće značenje:


 r/m označava registarsko direktno ili memorijsko direktno adresiranje
 [c] označava da je operand opcioni. Ako je naveden, zadat je neposrednim adresiranjem; ako nije
naveden, podrazumeva se vrednost 0.
 src kod MOV naredbe označava proizvoljan način adresiranja, a kod ADD i SUB naredbi registarsko
direktno, memorijsko direktno ili neposredno adresiranje
 dst kod MOV označava proizvoljan načina adresiranja osim neposrednog, a kod ADD i SUB naredbi
registarsko direktno ili memorijsko direktno adresiranje. Ako je jedan od operanada MOV, ADD i SUB
naredbi u memoriji, drugi mora biti u registru.

Načini adresiranja kod 8086

Načini adresiranja koje koristi 8086 mikroprocesor navedeni su u tabeli 2. Stek raste prema nižim
memorijskim lokacijama i registar SP ukazuje na poslednju popunjenu lokaciju. Adresiranje je bajtovsko, a
na steku se čuvaju isključivo 16-bitne veličine. Mikroprocesor 8086 poseduje i 16-bitne registre opšte
namene AX, BX, CX i DX i 16-bitne indeksne registre SI i DI.
Tabela 2
Primeri sintakse Objašnjenje Naziv
100 vrednost operanda je neposredno
100
labela adresa operanda je memorijsko direktno
[100] zadata vrednost
AX vrednost operanda je registarsko direktno
BP sadržaj registra
[BP] adresa operanda je registarsko indirektno
[SI] sadržaj nekog od
[DI] registara BP, SI, DI.
[BP+4] adresa operanda je bazno ili indeksno
[DI-100] sadržaj registra 
[SI-20] konstanta

Primer

 U nekoj C proceduri promenljive r, s, a i d deklarisane su na sledeći način:


register int r; /* registarska celobrojna promenljiva */
static int s; /* statička celobrojna promenljiva */
auto int a; /* automatska celobrojna promenljiva */
static int *d; /* statička promenjiva tipa pokazivača na ceo broj. */

 Pod pretpostavkom da je dužina celobrojnog podatka 16-bita i da se pokazivač d inicijalizuje


pozivom d=(int *)malloc(sizeof(int)), koji asemblerski kod odgovara naredbama
dodele:
r=s;
a=*d; ?

Rešenje
r=s
 Pretpostavimo da je promenljivoj r dodeljen procesorski registar SI, da je adresa promenljive s u
statičkoj oblasti (određena u vreme prevođenja programa) jednaka 200. Prevodilac za naredbu
dodele
r = s;
generiše sledeći asemblerski kod:
MOV SI,[0200]
Izvorišni (desni) operand zadat je memorijskim direktnim, a odredišni registarskim adresiranjem.

a=*d;
 Pod pretpostavkom da je a jedina automatska (lokalna) promenljiva u posmatranoj proceduri, njen
pomeraj u odnosu na registar BP će biti -2 i biće poznat u vreme prevođenja programa
 Takođe možemo pretpostaviti da je adresa promenljive d u statičkoj oblasti podataka jednaka 202.
 U vreme izvršavanja, pozivom funkcije malloc, dodeljuje se memorija u dinamičkoj oblasti podataka
neimenovanoj dinamičkoj celobrojnoj promenljivoj i adresa te promenljive upisuje u promenljivu d.
 Posle toga neimenovanoj dinamičkoj promenljivoj može se pristupati preko ukazivača d (u C
programu se piše *d što označava vrednost promenljive na koju ukazuje d).
 Prema tome, naredba
a = *d;
kopira sadržaj neimenovane promenljive u promenljivu a. Ovoj naredbi odgovara sledeći asemblerski
kod:
MOV BX,[0202] ; u BX ide sadržaj promenljive d
MOV AX,[BX] ; u AX ide sadržaj *d
MOV [BP-02],AX ; a:=*d
Korišćenje registra AX pri ovom transferu je bilo neophodno, jer ne postoji instrukcija transfera iz
memorije u memoriju (na primer MOV [BP-02], [BX]).

Pozivanje i povratak iz potprograma

 Pri svakom pozivu procedure u toku izvršavanja programa, na vrh steka se stavlja blok podataka koje
koristi pozvana procedura u svom radu. Ovaj blok zove se aktivacioni zapis procedure ili okvir
(engl. frame).
 AZ na steku ostaje sve dok pozvana procedura ne vrati kontrolu pozivaocu, kada se AZ pozvane
procedure skida sa vrha steka.

Primer

 Ukoliko, na primer iz procedure X usledi poziv procedure Y, a iz ove procedure poziv procedure Z,
na vrhu steka će biti aktivacioni zapis za Z, ispod njega aktivacioni zapis za Y, a ispod njega
aktivacioni zapis za X (slika 2).

procedura X Stablo aktivacije STEK


...
aktivacioni zapis
CALL Y procedure X

aktivacioni zapis
procedura Y procedure Y
...
aktivacioni zapis
CALL Z procedure Z
SP
procedura Z

Slika 2
Kada usledi povratak iz procedure Z sa steka se skida vršni aktivacioni zapis, po povratku iz Y drugi, a po
povratku iz X u glavni program i treći aktivacioni zapis.

Struktura aktivacionog zapisa

 pogodna za C procedure prikazana je na slici 3.

viže 
memorijske 
adrese 
kontrolna veza  aktivacioni zapis
 pozivaoca





stvarni parametri 



povratna adresa 
 aktivacioni zapis
kontrolna veza  pozvane procedure
BP 



lokalne promenljive
niže 
memorijske 
adrese 
SP
Slika 3

 Registar SP u svakom trenutku ukazuje na vrh steka. Registar BP ukazuje na polje kontrolne (ili
dinamičke) veze i služi za pristup stvarnim parametrima i lokalnim promenljivama procedure.
 Stvarnim parametrima pristupa se baznim adresiranjem [BP+pomeraj] gde je vrednost pomeraja za
svaki od parametara poznata u vreme prevođenja.
 Lokalnim promenljivama pristupa se baznim adresiranjem [BP-pomeraj] gde je vrednost pomeraja
takođe poznata u vreme prevođenja.
 U polju kontrolne veze čuva se adresa istoimenog polja u aktivacionom zapisu pozivaoca (drugim
rečima, to je ukazivač na istoimeno polje u aktivacionom zapisu pozivaoca). Radi se, u stvari, o
staroj vrednosti koju je registar BP imao pre poziva, i koja će biti vraćena u ovaj registar po povratku
iz pozvane procedure. Kontrolne veze svih aktivacionih zapisa koji se u određenom trenutku nalaze
na steku čine lanac kontrolnih veza.

Sekvenca pozivanja

 Niz aktivnosti koje pri pozivu neke procedure izvršavaju pozivalac i pozvana procedura da bi uspostavili
aktivacioni zapis pozvane procedure naziva se sekvenca pozivanja.
 Aktivnosti započinje procedura-pozivalac:
 Na stek se redom stavljaju stvarni parametri za pozvanu proceduru.
 Izvršava se CALL naredba koja na stek stavlja povratnu adresu i prenosi kontrolu pozvanoj proceduri
 Pozvana procedura:
 Na stek stavlja sadržaj registra BP (radi se o polju kontrolne veze).
 Sadržaj registra SP, koji u tom trenutku ukazuje na kontrolnu vezu, kopira u BP.
 Od sadržaja registra SP oduzima broj N koji je poznat u vreme prevođenja. Radi se o broju memorijskih
lokacija potrebnih za smeštaj lokalnih promenljivih. Na ovaj način se na steku alocira potreban prostor
za lokalne promenljive.
 Nakon završetka sekvence pozivanja, izvršava se kod pozvane procedure za inicijalizaciju lokalnih
promenljivih itd.

Sekvenca povratka

 Prilikom povratka iz pozvane u pozivajuću proceduru izvršava se sekvenca povratka.


 Pozvana procedura:
 Sadržaj registra BP kopira se u registar SP čime se sa steka oslobađa prostor za lokalne promenljive i one
efektivno prestaju da postoje.
 Sa vrha steka (koji u tom trenutku ukazuje na polje kontrolne veze pozvane procedure) skida se vrednost
kontrolne veze i smešta u registar BP. Time je ovaj registar postao spreman za upotrebu u proceduri-
pozivaocu.
 Naredba RET skida sa vrha steka povratnu adresu i smešta u brojač naredbi IP. Time se kontrola predaje
pozivaocu.
 Procedura - pozivalac:
 Dodavanjem odgovarajuće vrednosti na SP sa steka uklanja stvarne parametre i normalno nastavlja rad.

Primer

Napisati 80x86 asemblerski potprogram ekvivalentan datom programu na C-u. Koja sekvenca asemblerskog
koda odgovara pozivu primer(10,20) u glavnom programu?
void primer(int a,b) {
int c;
c=a;
}

Rešenje
Poziv primer(10,20) prevodi se sa:
; smeštanje drugog parametra na stek
MOV AX,20
PUSH AX
; smeštanje prvog parametra na stek
MOV AX,10
PUSH AX
; poziv procedure primer
CALL primer
; skidanje parametara sa steka
; alternativa navedenim je operacija ADD SP,4
POP CX
POP CX
; kraj poziva
Napomene:
1. Ukazivač steka SP se pri svakom skidanju podatka sa steka uvećava za dva, a pri svakom smeštanju na
stek umanjuje za 2, jer su na steku 16-bitne veličine, a adresa je bajtovska.
2. Glavni program u C-u je funkcija main kojoj takođe odgovara na steku aktivacioni zapis.
Kod za proceduru primer je:
; smeštanje sadržaja BP u polje kontrolne veze
PUSH BP
; nova vrednost BP treba da ukazuje na kontrolnu vezu
MOV BP,SP
; alociranje prostora za lokalnu promenljivu c
;
SUB SP,2
; u AX ide vrednost stvarnog parametra a
MOV AX,[BP+04]
; u lokalnu promenljivu c ide vrednost iz AX
MOV [BP-02],AX
; oslobađanje prostora dodeljenog promenljivoj c
MOV SP,BP
; restauracija vrednosti BP iz kontrolne veze
POP BP
; povratak u pozivajuću proceduru
RET

Na slici 4 prikazan je izgled aktivacionog zapisa procedure primer.

adresa sadržaj
[BP+6] 20 (vrednost parametra b)
[BP+4] 10 (vrednost parametra a)
[BP+2] adresa instrukcije POP CX
[BP+0] vrednost BP pozivaoca
n=2 BP
[BP-2] vrednost parametra c
SP
Slika 4

Diskusija

1. U prethodnom primeru redosled smeštanja na stek stvarnih parametara je takav da na stek prvo ide krajnje
desni parametar. Ova konvencija odgovara C programima kod kojih se procedura može pozivati sa
promenljivim brojem parametara. Ovaj redosled obezbeđuje da se uvek zna da je pomeraj za prvi
parametar (pod pretpostavkom da je celobrojni) +2, za drugi +4 itd.
2. Postavlja se pitanje da li je registar BP neophodan za pristup parametrima i lokalnim promenljivama
procedure. Drugim rečima, da li se za pristup može koristiti bazno adresiranje sa registrom SP i
odgovarajućim pomerajem (koji bi u ovom slučaju bio uvek pozitivan) i time izbeći rezervacija
posebnog registra?
Poseban registar je ipak neophodan iz sledećeg razloga: vrednost baznog registra ne sme se menjati
tokom izvršavanja procedure da bi se za pristup određenoj promenljivoj mogla koristiti uvek ista
vrednost pomeraja, izračunata još u vreme prevođenja. Registar SP ne zadovoljava ovaj zahtev u šta se
možemo uveriti na jednostavnom primeru. Neka u proceduri A postoji poziv primer(X,1) gde je X
lokalna promenljiva procedure A. Tokom sekvence pozivanja, na stek će biti smeštena prvo vrednost
desnog parametra - konstanta 1. Potom treba da usledi smeštanje prvog parametra što znači da treba
pristupiti promenljivoj X koristeći vrednost pomeraja izračunatu u toku prevođenja. Međutim,
smeštanjem konstante 1 na stek vrednost SP je umanjena za 2, i time je promenjena vrednost potrebnog
pomeraja za X. Na vrh steka se, takođe, smeštaju međurezultati izračunavanja složenijih aritmetičkih
izraza jer oni imaju privremen karakter - samo dok se ne izračuna krajnji rezultat.
3. Postavlja se takođe pitanje: zašto se lokalne promenljive alociraju na steku umesto da se koristi statička
oblast memorije? Programski jezici koji ne dozvoljavaju rekurzivne procedure (primer je FORTRAN)
zaista mogu statički alocirati lokalne promenljive a stek koristiti samo za čuvanje povratnih adresa pri
pozivu procedura. Međutim, C i Pascal koji dozvoljavaju rekurziju moraju obezbediti način da u
određenom trenutku izvršavanja programa jednoj istoj proceduri odgovara veći broj različitih
aktivacionih zapisa u memoriji.

Rekurzija: primer

Data je C funkcija proba. Pratiti tok izvršavanja poziva fakt(3) i odrediti izgled procesorskog steka u
trenutku neposredno pre prvog povratka iz funkcije.
int fakt(int n) {
return (n>0)?(n * fakt(n-1)):1;
}

Rešenje
Razmotrimo aktivnosti koje se odvijaju tokom izvršavanja poziva fakt(3):
 Iz glavnog programa poziva se funkcija fakt sa parametrom n = 3. Pri ovome se na steku formira
aktivacioni zapis funkcije fakt. Prenos parametra je po vrednosti, pa pozivalac pre naredbe CALL na
stek stavlja vrednost 3.
 U funkciji fakt, pre nego što se izvrši return naredba mora se izračunati vrednosti izraza navedenog
u okviru te naredbe. Radi se o uslovnom izrazu. S obzirom da je n >0 potrebno je izračunati proizvod n
* fakt(n-1). Da bi se odredio drugi faktor proizvoda, poziva se funkcija fakt, ovaj put sa vrednošću
parametra n - 1 = 2. Ovaj poziv se realizuje kao i svaki drugi poziv funkcije, formiranjem novog
aktivacionog zapisa na steku. Ovaj aktivacioni zapis uključuje i parametar, vrednost 2 tako da za novu
aktivaciju funkcije fakt važi da je n =2.
 Kontrola izvršavanja se ponovo prenosi na početak funkcije fakt. Pre povratka iz funkcije, ponovo se
mora izračunati vrednost drugog faktora proizvoda navedenog u naredbi return. Stoga ponovo sledi
poziv funkcije fakt, ovaj put sa vrednošću parametra 1. Formira se novi aktivacioni zapis na vrhu steka
koji u polju parametra ima vrednost 1, tako da za novu aktivaciju funkcije važi n = 1.
 Izvršavajući ponovo funkciju fakt od početne naredbe, ustanovljava se da je n >0 te stoga opet treba
izračunati drugi faktor proizvoda n * fakt(n-1). Zato sledi poziv fakt(0) pri čemu se na vrhu
steka formira novi aktivacioni zapis.
 U novoj aktivaciji važi da je n =0 pa nije ispunjen uslov n>0. Zato je vrednost uslovnog izraza jednaka 1.
U trenutku neposredno pred povratak iz ove aktivacije funkcije fakt, na steku se još uvek nalaze sva
četiri aktivaciona zapisa funkcije fakt (slika 5). Po izvršenju naredbe return, sa vrha steka skida se
poslednji stavljeni aktivacioni zapis. Funkcija fakt može da prosledi rezultat pozivaocu u nekom
procesorskom registru, ili alternativno preko steka. U ovom drugom slučaju u okviru polja parametara
potrebno je rezervisati lokaciju za smeštaj rezultata (na slici 5 je prikazan slučaj kada se rezultat vraća u
registru).
 Po povratku iz četvrte u treću aktivaciju funkcije fakt računa se proizvod vrednosti parametra n=1 i
vraćenog rezultata fakt(0) = 1 i dobijeni rezultat 1 vraća pozivaocu, pri čemu se uklanja aktivacioni
zapis sa vrha steka.
 Na isti način, druga aktivacija računa proizvod parametra n=2 i vraćenog rezultata fakt(1)=1 i rezultat
2 vraća pozivaocu, pri čemu se skida naredni aktivacioni zapis sa vrha steka.
 Prva aktivacija računa konačni rezultat 3 * 2 = 6 i vraća ga glavnom programu, pri čemu se sa steka
skida i poslednji aktivacioni zapis funkcije fakt. Time je u potpunosti obrađen poziv fakt(3).


 Aktivacioni zapis za main


n=3 

povratna adresa  Aktivacioni zapis za fakt(3)


n=2 

povratna adresa  Aktivacioni zapis za fakt(2)


n=1 

povratna adresa  Aktivacioni zapis za fakt(1)


n=0 

povratna adresa  Aktivacioni zapis za fakt(0)

BP,SP 
Slika 5

Statičko okruženje za nelokalne promenljive realizovano pristupnim vezama

 U Pascal-u je, za razliku od C-a, dozvoljeno ugneždavanje deklaracija procedura.


 Prema pravilu leksičkog opsega važenja deklaracije promenljivih, u nekoj Pascal-skoj proceduri, pored
lokalnih promenljivih, vidljive su i sve promenljive deklarisane u okružujućim procedurama ako nemaju
isto ime kao lokalne promenljive.
 Izgled aktivacionog zapisa pogodnog za Pascal procedure dat je na slici 6. U odnosu na aktivacioni zapis
za C procedure, definisan u zadatku 1, razlika je u polju pristupne veze. Polje pristupne veze potrebno
je da bi se realizovao pristup nelokalnim promenljivama koje su deklarisane u drugim procedurama.

Aktivacioni zapis sa pristupnom vezom

 Polje pristupne veze neke procedure ukazuje na AZ (preciznije, na polje kontrolne veze toga zapisa)
neposredno okružujuće procedure (u listingu programa). Ova procedura, u opštem slučaju, razlikuje
se od procedure pozivaoca.
viže 
memorijske  aktivacioni zapis
adrese  procedure u kojoj
 je deklarisana

 pozvana procedura

. . .


 aktivacioni zapis
 pozivaoca



stvarni parametri 


pristupna veza 

povratna adresa 
 aktivacioni zapis
 pozvane procedure
kontrolna veza 
BP 


niže
lokalne promenljive 
memorijske 
adrese 
SP
Slika 6

Algoritam formiranja pristupne veze

 Razmotrimo tri moguća slučaja kada Pascal-ska procedura A poziva proceduru B:


i) Deklaracija B je ugneždena u deklaraciji A; kaže se da je B deklarisana na (za jedan)
višem leksičkom nivou ugneždavanja od A.
procedure A;
procedure B; begin...end;
begin B end.
U ovom slučaju, pristupna veza procedure B ukazivaće na AZ(A).

ii) Deklaracija B je ugneždena u istoj proceduri X (ili u glavnom programu) kao i deklaracija
A; tada važi da su A i B na istom leksičkom nivou ugneždavanja.
procedure X;
procedure B; begin...end;
procedure A; begin B end;
begin ... end.
U ovom slučaju, pristupna veza A kopira se u polje pristupne veze B, tako da obe ukazuju
na AZ(X).

iii) Leksički nivo ugneždavanja A je veći od nivoa B. Razlika leksičkih nivoa A i B označena
sa N može da bude veća od jedan;
procedure X
procedure B;
procedure Y
procedure A; begin B end;
begin A; end;
begin Y; end;
begin B; end;
u ovom slučaju potrebno je slediti lanac od pristupnih veza počev od pristupne veze A i u
polje pristupne veze za B iskopirati sadržaj N-tog polja u lancu. (Za N=1 to je polje na
koje ukazuje polje pristupne veze za A, itd.)

Sekvenca pozivanja

 Različite obaveze u odnosu na C procedure:


 Pri pozivu, procedura pozivalac radi sledeće:
 na stek redom stavlja stvarne parametre (uobičajeno za Pascal je da kranje levi parametar ide prvi)
 na stek stavlja vrednost koja definiše sadržaj polja pristupne veze pozvane procedure prema gore
navedenim pravilima (na primer, u slučaju i, na stek se stavlja sadržaj registra BP)
 Izvršava se CALL naredba koja na stek stavlja povratnu adresu i prenosi kontrolu pozvanoj proceduri
 Pozvana procedura:
 Na stek stavlja sadržaj registra BP (radi se o polju kontrolne veze).
 Sadržaj registra SP, koji u tom trenutku ukazuje na kontrolnu vezu, kopira u BP.
 Od sadržaja registra SP oduzima broj N koji je poznat u vreme prevođenja. Radi se o broju memorijskih
lokacija potrebnih za smeštaj lokalnih promenljivih. Na ovaj način se na steku alocira potreban prostor
za lokalne promenljive.
 Nakon završetka sekvence pozivanja, izvršava se kod pozvane procedure.

Sekvenca povratka

 Prilikom povratka iz pozvane u pozivajuću proceduru izvršava se sekvenca povratka, koju u


potpunosti realizuje pozvana procedura:
 Sadržaj registra BP kopira se u registar SP čime se sa steka oslobađa prostor za lokalne promenljive i one
efektivno prestaju da postoje.
 Sa vrha steka (koji u tom trenutku ukazuje na polje kontrolne veze pozvane procedure) skida se vrednost
kontrolne veze i smešta u registar BP. Time je ovaj registar postao spreman za upotrebu u proceduri-
pozivaocu.
 Naredba RET n skida sa vrha steka povratnu adresu i smešta u brojač naredbi IP. Ova naredba zatim
uvećava registar SP za vrednost n čime se sa steka skidaju stvarni parametri i pristupna veza. Nakon toga
se kontrola predaje pozivaocu.

Primer

Odrediti 80x86 asemblerski ekvivalent datog Pascal programa . Kako izgleda procesorski stek u trenutku
neposredno pre prvog povratka iz procedure?
program glavni;
procedure jedan
var local1: integer;
procedure tri; forward;
procedure dva;
begin {dva}
tri {II slučaj kod formiranja pristupne veze}
end; {dva}
procedure tri;
begin {tri}
local1:=10;
end; {tri}
begin {jedan}
dva {I slučaj kod formiranja pristupne veze}
end; {jedan}
begin {glavni}
jedan

end. {glavni}

Rešenje

procedura dva
; sadržaj registra BP definise sadržaj polja kopntrolne veze
PUSH BP
; BP ukazuje na polje kontrolne veze
MOV BP,SP
; počinje sekvenca poziva procedure tri
; uspostavlja se sadržaj polja kontrolne veze u aktivacionom
zapisu
; procedure tri,
; kopiranjem sadržaja polja kontrolne veze u akt. zapisu procedure
dva
; (ii slučaj algoritma)
PUSH [BP+04]
; poziv procedure tri
CALL tri
; sekvenca povratka iz procedure dva
; dealocira se deo aktivacionog zapisa iza polja kontrolne veze
MOV SP,BP
; restaurira se sadržaj registra BP potreban pozivaocu i dealocira
; polje kontrolne veze sa steka
POP BP
; povratak pozivaocu uz dealociranje polja pristupne veze
RET 0002

procedura tri
; definisanje polja kontrolne veze
PUSH BP
; BP ukazuje na polje kontrolne veze
MOV BP,SP
; prevod naredbe local1 := 10
MOV DI,[BP+04]
MOV [DI-02],10*
; sekvenca povratka
MOV SP,BP
POP BP
RET 0002

procedura jedan
; definisanje polja kontrolne veze
PUSH BP
; BP ukazuje na polje kontrolne veze
MOV BP,SP
; alociranje prostora za promenljivu local1
SUB SP,+02

*
Na 8086 asembleru sintaksa ove instrukcije glasi MOV SS:WORD PTR [DI-2],10
SS: označava da se pristupa segmentu steka (podrazumevana vrednost za registar DI je segment podataka DS),
WORD PTR označava da se prenosti jedna reč, a ne jedan bajt.
; definisanja pristupne veze za proceduru dva (slučaj i)
PUSH BP
; poziv procedure dva
CALL dva
; sekvenca povratka
MOV SP,BP
POP BP
RET
glavni program - sekvenca poziva
; polje pristupne veze nije potrebno proceduri jedan pošto su
; promenljive glavnog programa statički alocirane
CALL jedan
U vreme izvršavanja procedure tri, izgled procesorskog steka je prikazan na slici 7. Pristupna veza u
aktivacionom zapisu procedura dva i tri ukazuje na početak aktivacionog zapisa procedure jedan.
Promenljivoj local1 prostor je dodeljen na steku u aktivacionom zapisu procedure jedan. Glavni program ne
poseduje aktivacioni zapis jer se promenljive glavnog programa alociraju statički, pa zbog toga ni procedura
jedan ne poseduje pristupnu vezu. Deo programa koji upisuje vrednost 10 u promenljivu local1 u proceduri
tri ima sledeći izgled:
MOV DI,[BP+4]
MOV [DI-2], 10*
Prva naredba dodeljuje registru DI sadržaj polja pristupne veze, odnosno adresu polja kontrolne veze u
aktivacionom zapisu procedure jedan. Sada se u drugoj naredbi promenljivoj local1 pristupa indeksnim
adresiranjem uz korišćenje registra DI i pomeraja poznatog u vreme prevođenja programa.
viže
memorijske
adrese
povratna adresa 

 aktivacioni zapis
kontrolna veza  procedure jedan


local1 

pristupna veza 

aktivacioni zapis
povratna adresa  procedure dva


kontrolna veza 


pristupna veza 
niže 
aktivacioni zapis
memorijske povratna adresa  procedure tri
adrese 

kontrolna veza 
BP, SP 
Slika 7

Diskusija
1. Kod C-a se problem pristupa nelokalnim promenljivama ne javlja, jer su sve promenljive kojima se
pristupa u proceduri ili lokalne (kada im se pristupa baznim adresiranjem uz korišenje registra BP) ili su
globalne, statički alocirane (pa su ima adrese poznate u vreme prevođenja programa).
2. Da li je pristupna veza neophodna ili se za pristup nelokalnim promenljivama mogu koristiti kontrolne
veze? U cilju nalaženja odgovora osmatrajmo opet program iz tačke a). U slučaju korišćenja kontrolnih
veza, naredba dodele u proceduri tri mogla bi se realizovati na sledeći način:
; u DI ide sadržaj polja kontrolne veze aktivacionog zapisa
procedure tri
MOV DI,[BP]
; u DI ide sadržaj polja kontrolne veze aktivacionog zapisa
procedure dva
MOV DI,[DI]
; DI ukazuje na kontrolnu vezu procedure jedan pa se uz poznati
; pomeraj pristupa promenljivoj local1
MOV [DI-2],10
Razmotrimo, međutim slučaj koji bi nastao da procedura jedan pozove proceduru tri posle završetka
procedure dva. Pošto je procedura dva završena, sa steka su uklonjeni aktivacioni zapisi procedura jedan i tri
pa je na steku ostao samo aktivacioni zapis procedure jedan. Pri ponovnom pozivu procedure tri, na vrh
steka se stavlja aktivacioni zapis za ovu novu aktivaciju procedure tri. Sada bi naredba dodele morala biti
realizovana na sledeći način uz korišćenje kontrolnih veza:
; u DI ide sadržaj polja kontrolne veze procedure tri
MOV DI,[BP]
; DI ukazuje na kontrolnu vezu procedure jedan pa se uz
; poznati pomeraj pristupa promenljivoj local1
MOV [DI-2],10
Prema tome, potreban je jedan nivo indirekcije manje jer se aktivacioni zapis procedure jedan sada nalazi na
steku neposredno ispod aktivacionog zapisa procedure tri. Drugim rečima, naredba dodele u proceduri tri se
različito prevodi u zavisnosti sa kog mesta je pozvana procedura tri što je nedopustivo. Pristupna veza je, u
skladu sa tim, neophodna.

Statičko okruženje realizovano displejima

 U opštem slučaju, ako se promenljivoj deklarisanoj na leksičkom nivou M pristupa iz procedure


deklarisane na nivou N kao nelokalnoj promenljivoj (te je N > M), potrebno je slediti lanac od N-M
pristupnih veza da bi se došlo do aktivacionog zapisa u kome se nalazi promenljiva.
 Efikasniji pristup nelokalnim promenljivama realizuje se korišćenjem displeja. Za svaki leksički
nivo na kome se može nalaziti nelokalna promenljiva čuva se poseban pokazivač na aktivacioni zapis
odgovarajuće procedure deklarisane na tom nivou; niz tih pokazivača naziva se displej.
 Za pristup nelokalnoj promenljivoj putem displeja uvek su dovoljne dve naredbe, bez obzira na
kojem se leksičkom nivou nalazi neloklana promenljiva:
 Pva naredba u registar dovodi sadržaj odgovarajueg pokazivača koji predstavlja adresu
aktivacionog zapisa u kome se nalazi nelokalna promenljiva.
 Druga naredba vrši pristup koristeći bazno indeksiranje sa poznatim pomerajem.

 Pokazivači displeja mogu se čuvati u registrima procesora, u statičkoj zoni memorije ili u
aktivacionom zapisu procedure.

Primer

program glavni;
procedure jedan;
var local1: integer;
procedure dva;
procedure tri;
begin {tri}
local1:=10
end; {tri}
begin {dva}
tri
end; {dva}
begin {jedan}
dva
end; {jedan}
begin {glavni}
jedan
end. {glavni}

 procedura tri iz tačke b) postavke koja se nalazi na leksičkom nivou tri (glavni program je na nivou
nula), imala bi tri1 pokazivača u displeju kako je prikazano na slici 8.
STEK

Aktivacioni zapis
procedure jedan

Aktivacioni zapis
Display1
Display2 procedure dva
Display3 BP
Aktivacioni zapis
Displej za proceduru tri procedure tri

Slika 8
 Pod pretpostavkom da su pokazivači statički alocirani, naredbi local1:=10 bi odgovarao sledeći
segment asemblerskog koda:
MOV DI, Display1 ; u SI ide adresa aktivacionog zapisa procedure
jedan
MOV [DI-4], 10 ; u promenljivu local1 se upisuje 10
; (pomeraj se zna u vreme prevođenja)
 Prednost displeja u odnosu na lanac pristupnih veza je u efikasnijem pristupu nelokalnim
promenljivama; nedostatak je u povećanoj režiji u sekvenci pozivanja procedure, kada je potrebno
definisati sadržaj displeja.

Algoritam za postavljanje displeja

 Pri svakom pozivu i povratku ažuriraju se registri displeja da odgovaraju trenutno aktivnoj proceduri
(onoj čiji je AZ na vrhu steka).
 Procedura na nivou ugneždavanja N koristi N registara displeja.
 U svakoj situaciji dovoljno je ažurirati jedan registar displeja (to je onaj koji odgovara nivou
ugeždavanja N na kome se nalazi pozvana procedura P):
o pri pozivu, stari sadržaj displej registra N čuva se u akt. zapisu procedure P
o u displej registar N stavlja se pokazivač na upravo formirani AZ(P)
o pri povratku iz P, sačuvana vrednost displej registra N restaurira se.

1
Dovoljna su i dva pokazivača jer se lokalnim promenljivama može pristupiti koristeći registar BP. Treći pokazivač
koristi se pri uspostavljanju displeja prilikom sekvence pozivanja.
Poređenje sa pristupnim vezama na datom primeru

 Izgled steka u trenutku kada se izvršava procedura tri dat je na slici 9.


viže
memorijske
adrese
povratna adresa 

 aktivacioni zapis
kontrolna veza  procedure jedan


local1 

pristupna veza 

aktivacioni zapis
povratna adresa  procedure dva


kontrolna veza 


pristupna veza 
niže 
aktivacioni zapis
memorijske povratna adresa  procedure tri
adrese 

kontrolna veza 
BP, SP 
Slika 9

 Sekvenca asemblerskih instrukcija koja odgovara naredbi local1:=10:


; u DI ide sadržaj polja pristupne veze procedure tri
MOV DI,[BP+4]
; u DI ide sadržaj polja pristupne veze procedure dva
MOV DI,[DI+4]
; DI ukazuje na kontrolnu vezu procedure jedan pa se uz poznati
; pomeraj pristupa promenljivoj local1
MOV [DI-2],10
 S obzirom da je razlika leksičkih nivoa procedura jedan (u kojoj je promenljiva local1 deklarisana) i
procedure tri (u kojoj se pristupa promenljivoj local1) jednaka 2, bilo je potrebno pratiti lanac od dve
pristupne veze da bi se stiglo da aktivacionog zapisa procedure jedan.
 U slučaju da je razlika leksičkih nivoa veća od 2, u gornju sekvencu bio bi dodat odgovarajući broj
instrukcija MOV DI,[DI+4].

Procesorska podrška višim programskim jezicima

Naslednici procesora 8086 imaju dve mašinske instrukcije za podršku izvršnoj organizaciji memorije kod
viših programskih jezika:
 ENTER Size, Level
 LEAVE
Struktura aktivacionog zapisa za ENTER i LEAVE

Na slici * prikazan je izgled aktivacionog zapisa koji odgovara ovim naredbama. Za pristup nelokalnim
promenljivama koristi se displej alociran u aktivacionom zapisu procedure.
više 
memorijske 
adrese  aktivacioni zapis
 pozivaoca



stvarni parametri 


povratna adresa 

kontrolna veza 
BP 

aktivacioni zapis
 pozvane procedure
displej 





niže lokalne promenljive 
memorijske 
adrese SP 

Naredba ENTER Size, Level

 Naredba ENTER realizuje deo sekvence pozivanja koji izvršava pozvana procedura.
 Ova naredba ima dva operanda.
o Size (16-bitna veličina) definiše koliko memorije treba alocirati u aktivacionom zapisu za
lokalne promenljive.
o Level (8-bitna veličina) predstavlja leksički nivo pozvane procedure.
 Ova naredba izvršava se kao prva naredba pozvane procedure na sledeći način:
1. Sadržaj registra BP ide na stek (čime se definiše polje kontrolne veze)
2. U registar BP upisuje se sadržaj registra SP (čime je BP postavljen da ukazuje na polje kontrolne
veze).
3. Ako je Level = 0 preskače se sledeći korak (Level = 0 važi za procedure u C-u kod koga se ne javlja
problem pristupa nelokalnim promenljivim).
4. Označimo vrednost Level -1 sa N, a sadržaj polja kontrolne veze sa A. Na stek se smešta N reči koje
se kopiraju redom počev od lokacije A-2 ka nižim memorijskim lokacijama. Potom se na stek smešta
adresa polja kontrolne veze. Ovime je uspostavljen displej pozvane procedure.
5. Registar SP umanjuje se za vrednost operanda Size čime se alocira prostor za lokalne promenljive
pozvane procedure.
Naredba LEAVE

 Naredba LEAVE realizuje deo sekvence povratka koji izvršava pozvana procedura.
 Ova naredba neposredno prethodi naredbi RET i izvršava se na sledeći način:
1. Sadržaj registra BP kopira se u registar SP. Ovime se dealocira sa steka deo aktivacionog zapisa
pozivaoca ispod kontrolne veze.
2. Sa steka se skida sadržaj polja kontrolne veze i smešta u registar BP. Time je BP namešten za
pozivaoca, a polje kontrolne veze pozvane procedure je uklonjeno sa steka.

Primer

Odrediti asemblerski ekvivalent datog Pascal programa koristeći predložene instrukcije.


program glavni;
procedure jedan;
var local1: integer;
procedure dva;
procedure tri;
begin {tri}
local1:=10
end; {tri}
begin {dva}
tri
end; {dva}
begin {jedan}
dva
end; {jedan}
begin {glavni}
jedan
end. {glavni}

Asemberski kod koji odgovara datom Pascal programu bez korišćenja naredbi ENTER i LEAVE dat je u
ranijem primeru. Za dati Pascal program, asemblerski ekvivalent uz korišćenje naredbi ENTER i LEAVE bi
imao sledeći izgled:
procedura dva
; nema lokalnih promenljivih a leksički nivo je jednak 2
ENTER 0,2
; poziv procedure tri
CALL tri
; sekvenca povratka iz procedure dva
; dealocira se deo aktivacionog zapisa iza polja kontrolne veze
LEAVE
; povratak pozivaocu uz dealociranje polja pristupne veze
; nema stvarnih parametara za dealociranje pa je upotrebljena
; naredba RET bez argumenta
RET

procedura tri
; nema lokalnih promenljivih a leksički nivo je jednak 3
ENTER 0,3
; prevod naredbe local1 := 10
; u DI se kopira pokazivač koji odgovara leksičkom nivou 1
MOV DI,[BP-02]
; u kativacionom zapisu procedure jedan displej ima samo jedan
pokazivač
; promenljiva local1 nalazi se odmah ispod toga pokazivača
MOV [DI-04],10*
; sekvenca povratka
LEAVE
RET

procedura jedan
; rezervišu se dva bajta za promenljivu local1
; leksički nivo je jednak 1
ENTER 2,1
; poziv procedure dva
CALL dva
; sekvenca povratka
LEAVE
RET

glavni program - sekvenca poziva


CALL jedan

*
Na 8086 asembleru sintaksa ove instrukcije glasi MOV SS:WORD PTR [DI-2],10
SS: označava da se pristupa segmentu steka (podrazumevana vrednost za registar DI je segment podataka DS),
WORD PTR označava da se prenosti jedna reč, a ne jedan bajt.
Generisanje međukoda

Prednosti upotrebe međukoda nad direktnim generisanjem mašinskog koda iz izvornog programa:
 prednji kraj kompajlera (sintaksno-semantički analizator i generator međukoda) su mašinski nezavisni.
Kompajler se lako prilagođava novoj mašini izmenom zadnjeg kraja kompajlera (generatora mašinskog
koda iz međukoda).
 ako prednji krajevi kompajlera za različite jezike generišu isti međukod, moguće je za ciljnu mašinu
napraviti samo jedan generator koda za sve jezike.
 optimizaciju je moguće sprovoditi na međukodu, čime se pravi mašinski nezavistan optimizator.

Načini predstavljanja međukoda

 sintaksno stablo ili aciklički graf (u grafu se eliminišu ponavljanja usled zajedničkih podizraza)
 postfiksna notacija
 troadresni kod
 graf toka kontrole na nivou bazičnih blokova
 SSA – Static Single Assignment Form

Predstavljanje međukoda putem sintaksnog stabla ili acikličkog grafa


(direct acyclic graph)
Primer
Stablo, odnosno graf za iskaz: a:= b * -c + b * -c

Atributivno-translaciona gramatika za iskaz dodele koja konstruiše sintaksno stablo:


1. <S>s  idn {MKLEAF}x,y,z := <E>s1 {MKNODE}a,b,c,d
x  "id" yn a  "assign" b  z c  s1 s  d
2. <E>s  <E>s1 + <E>s2 {MKNODE}a,b,c,d
a  "+" b  s1 c  s2 sd
3. <E>s  <E>s1 * <E>s2 {MKNODE}a,b,c,d
a  "*" b  s1 c  s2 sd
4. <E>s  – <E>s1 {MKNODE}a,b,c,d
a  "uminus" b  s1 c  NULL sd
5. <E>s  ( <E>s1 )
s  s1
6. <E>s  idn {MKLEAF}x,y,z
x  "id" yn sz

Akcija {MKLEAF}x,y, z konstruiše čvor – list sintaksnog stabla, pri čemu x (nasl. atribut) označava tip čvora,
a y (nasleđ. atribut) ime promenljive koja je predstavljena tim čvorom (ili pointer u tabelu simbola gde se
nalazi ta promenljiva). Sintetizovani atribut z je pokazivač na konstruisani čvor.
Akcija {MKNODE}a,b,c,d konstruiše unutrašnji čvor sintaksnog stabla, a (nasl. atr.) označava operator, a b i c
(nasl. atr.) pokazivače na čvorove naslednike. Sintetizovani atribut d je pokazivač na konstruisani čvor.
Neterminal <E> ima sintetizovani atr. koji predstavlja pokazivač na deo sintaksnog stabla koji odgovara
izrazu koji <E> uparuje.
Neterminal <S> ima sint. atr. koji predstavlja pokazivač na kompletno sint. stablo koje odgovara iskazu
dodele.
Terminal id ima atribut koji predstavlja ime promenljive (ili pokazivač na tabelu simbola gde se nalazi ta
promenljiva).
Aciklički graf će biti konstruisan istom ovom gramatikom, pod uslovom da akcije {MKLEAF} i
{MKNODE} za iste ulazne parametre vraćaju uvek isti čvor, a ne da prave u svakom pozivu novi čvor.

Implementacija sintaksnog stabla (grafa)


 putem stabla zapisa ili vektora zapisa kao na slici:

stablo zapisa vektor zapisa

Predstavljanje međukoda putem postfiksne notacije

Primer
Postfiksna notacija za iskaz: a:= b * -c + b * -c
a b c uminus * b c uminus * + assign
Forma postfiksne notacije pogodna je za izvršavanje na stek mašini (npr. mikrojava virtuelna mašina).
Atributivno-translaciona gramatika koja prevodi iskaz dodele u postfiksnu notaciju
(na izlaz ide ono što je unutar vitičastih zagrada):
1. <S>  <ID> := <E> {assign}
2. <E>  <E> + <E> {+}
3. <E>  <E> * <E> {*}
4. <E>  – <E> {uminus}
5. <E>  ( <E> )
6. <E>  <ID>
7. <ID>  a {a}
8. <ID>  b {b}
9. <ID>  c {c}
(Ova forma može se dobiti i postorder obilaskom sintaksnog stabla – kod njega se prvo ispišu levi i desni
naslednik svakog čvora, pa onda sam čvor).
Ovo je koncept, a jedna konkretna realizacija ovog koncepta je mikrojava bajtkod.

Predstavljanje međukoda putem troadresnog koda

 niz iskaza osnovnog oblika: x := y op z


 drugi mogući tipovi:
 za ranije dato sintaksno stablo i graf možemo napisati sledeće sekvence troadresnog koda (uvedene su
privremene promenljive ti za međurezultate koji odgovaraju unutrašnjim čvorovima stabla):

 gramatika za iskaz dodele koja generiše troadresni kod:


1. <S>  idn := <E>s {GEN3}a,b,c
a  n b  ":=" cs
2. <E>s  <E>s1 + <E>s2 {GEN1}a,b,c,d,e
(s, a)  newtemp b  ":=" c  s1 d  "+" e  s2
3. <E>s  <E>s1 * <E>s2 {GEN1}a,b,c,d,e
(s, a)  newtemp b  ":=" c  s1 d  "*" e  s2
4. <E>s  – <E>s1 {GEN2}a,b,c,d
(s, a)  newtemp b  ":=" c  "uminus" d  s1
5. <E>s  ( <E>s1 )
s  s1
6. <E>s  idn
sn
Terminal id ima atribut koji predstavlja naziv odgovarajuće promenljive. Neterminal <E> ima sintetizovani
atribut koji predstavlja naziv privremene promenljive koja sadrži međurezultat za deo izraza uparen sa <E>.
Svaki poziv funkcije newtemp rezerviše novu privremenu promenljivu.
Akcija {GEN} od svojih argumenata sastavlja jednu troadresnu naredbu (ima promenljiv broj nasleđenih
atributa).
 gramatika za iskaz while koja generiše troadresni kod prema slici:

Neterminal <E> predstavlja uslovni izraz, a <S> iskaz tela petlje.


<S>  while {GENL}l1 <E>t {GEN5}a,b,c,d <S> {GEN4}g,h {GENL}l2
(l1,h)  newlabel (d,l2)  newlabel
a  "if" b  t c  "= 0 goto" g  "goto"

GENL – generiše definiciju labele u međukodu


GENC – generiše izvršne naredbe međukoda

Implementacija troadresnih naredbi


 četvorke - zapis sa četiri polja, operandi se predstavljaju pointerima na tabelu simbola.
 trojke - nema polja za rezultat, nego se redni broj naredbe navodi kada se koristi međurezultat koji ta
naredba izračunava
 indirektne trojke - ne koriste se redni brojevi trojki, nego umesto njih pokazivači na mem. adresu gde je
smeštena trojka čiji se rezultat koristi na mestu operanda. Uvodi se još dodatan vektor pokazivača koji
definiše redosled trojki, omogućujući jednostavnu izmenu redosleda - samo se ažurira vektor, a sadržaj u
trojkama ostaje neizmenjen.
Primer
Troadresnom međukodu:

odgovaraju sledeće četvorke, trojke i indirektne trojke, respektivno.


indirektne trojke

Predstavljanje međukoda grafom toka kontrole programa na nivou osnovnih blokova

Osnovni blok je skup iskaza međukoda koji se izvršavaju u sekvenci (bez grananja) izuzev krajnjeg iskaza u
bloku koji može biti uslovni ili bezuslovni skok.
Dekompozicija programa na osnovne blokove:
 Odrediti vođe (prve iskaze) osnovnih blokova: prvi iskaz u programu, iskazi koji predstavalju odredišta
uslovnih ili bezuslovnih skokova i iskazi koji neposredno slede bezuslovne ili uslovne skokove.
 Svakom vođi pridružiti iskaze koji ga slede do prvog sledećeg vođe (isključujući taj iskaz) ili do kraja
programa.

U grafu toka kontrole, osnovni blokovi predstavljaju čvorove grafa. Od bloka B1 postoji orijetisana grana
ka bloku B2, ako B2 neposredno sledi B1 u nekoj izvršnoj sekvenci, odnosno ako:
 postoji uslovan ili bezuslovan skok od poslednjeg iskaza B1 ka vođi B2, ili
 B2 neposredno sledi B1 u međukodu, a B1 nema na kraju bezuslovni skok.

Primer
Programskom fragmentu:
prod = 0; i = 1;
do {
prod = prod + a[i] * b[i];
i = i + 1;
} while ( i <= 20 );
odgovara sledeći međukod i graf toka kontrole:
1. prod = 0
2. i = 1 prod = 0
3. t1 = 4 * i i=1
4. t2 = a[t1]
5. t3 = 4 * i
6. t4 = b[t3] t1 = 4 * i
7. t5 = t2 * t4 t2 = a[t1]
t3 = 4 * i
8. t6 = prod + t5 t4 = b[t3]
9. prod = t6 t5 = t2 * t4
10. t7 = i + 1 t6 = prod + t5
11. i = t7 prod = t6
12. if i <= 20 goto 3 t7 = i + 1
i = t7
if i <= 20 goto 3

Predstavljanje međukoda statičkom formom jedinstvene dodele (engl. Static Single Assignment form
– SSA)

U programu koji je u SSA formi:


 Svakoj dodeli promenljive daje se jedinstveno ime
 Sve upotrebe te promenljive koje koriste vrednost te dodele se preimenuju da reflektuju dodeljeno
ime:

Najlakše u kodu bez grananja:


V=V+4 V0 = 4
X = V + 5 posle preimenovanja X = V0 + 5
V=6 V1 = 6
Y = V *7 Y = V1 *7

Kako izvršiti preimenovanje kada u kodu postoji granjanje?

Ovo se rešava uvođenjem takozvanih -funkcija.

Vrednost ove -funkcija je jednaka X0 ako kontrola u poslednji bazični blok ulazi iz then dela IFa, odnosno
X1 ako kontrola ulazi kroz else deo.

U opštem slučaju, vrednost funkcije (V1, V2, …, VN) u osnovnom bloku B sa N blokova prethodnika u
grafu kontrole toka na nivou bloka, P1, P2, .. , PN, iznosi Vj ako tok izvršavanja prenosi kontrolu programa sa
Pj na blok B.

-funkcija Ima tačno toliko argumenata koliko posmatrani blok ima ulaznih grana.


Formalno, program je u obliku SSA ako:


1. Svaka promenljiva poseduje tačno jednu dodelu vrednosti.
2. Dodela promenljivoj dominira svim upotrebama te promenljive. Drugim rečima, u grafu toka kontrole na
nivou iskaza ne može se od ulaznog čvora doći do čvora upotrebe promenljive, a da se ne prođe kroz čvor
dodele toj promenljivoj.

Iz SSA forme i -funkcija nikada se direktno ne generiše kod, nego se neka druga međuforma (npr.
troadresne naredbe) privremeno transformiše u SSA da bi se olakšala optimizacija koda na nivou SSA, a
zatim se iz SSA konvertuje natrag u polaznu međuformu.

"Vraćanje" iz SSA forme nazad u običan međukod

U najjednostavnijoj varijanti, -funkciju sa N argumenata u bloku B treba zameniti sa N običnih dodela, po


jednom na kraju svakog bloka prethodnika bloku X u grafu. Ovim se nekada dobija neefikasan kod sa
suvišnim dodelama, ali se on može poboljšati dodatnim optimizacijama koje nisu predmet našeg
razmatranja.
Primer sa osnovnim blokovima

Izvorni kod
for (v=g1; g3; v+=g2 )
a[i]=2;
međukod (četvorke)
v=g1
t2=g2
t3=g3
L1: if v > t3 goto L2
t4 = &a
t5 = 4*i
t6=t4+t5
*t6=2
v=v+t2
goto L1
L2:
međukod (SSA forma)

v1=g1
B1 t2=g2
t3=g3

B2 v2=(v1,v3)
v2>t3
T F
t4=&a
t5=4*i
B3 t6=t4+t5
*t6=2
v3=v2+t2

Pogodnosti za korišćenje SSA forme su u eksplicitnoj predstavi informacija vezanih za tok podataka što
olakšava optimizacije koje su zasnovane na analizi toka podataka. Mane SSA forme su u tome što je
ograničena na skalarne vrednosti (ceo niz se mora tretirati kao veliki scalar) i uvođenje suvišnih dodela
vrednosti kada se konvertuje iz SSA u običan međukod.
Generisanje koda

Ulaz u generator koda je međukod programa, izlaz je mašinski kod za ciljnu mašinu.
(moguće varijante: apsolutizovani mašinski kod, objektni kod obrađivan u predmetu sistemski
softver/programiranje, asemblerski izvorni kod-ako izlaz ide potom u asembler).

Ciljna mašina za ovu lekciju: podskup x86 asemblera

 Dvoadresna mašina, asemblerske naredbe oblika: OP destination, source


ima značenje destination := destination OP source
 Ograničenje: ne mogu istovremeno i source i destination biti memorijske lokacije (jedan mora biti u
registru)
 OP će nam biti ADD, MOV, SUB, MUL, DIV.
o MUL src ima značenje: (DX:AX)  AX * src
o DIV src ima značenje: AX  (DX:AX) div SRC
DX  (DX:AX) mod SRC
 Ima registare opšte namene AX, BX, CX, DX i indeksne SI, DI, BP.
 Adresiranje na nivou bajta, memorijska reč od 2 bajta. U našim primerima svi operandi i rezultati
operacija će biti 16bitni.
 Načini adresiranja:
Način adr. Sintaksa Objašnjenje
Apsolutno M Simbolička mem. adresa M
Registarsko R Registar R
Indeksno (r.relat) [Rc] Konstanta c  sadržaj reg. R
Indirektno reg. [R] Sadržaj registra R
Neposredno c Konstanta c

Napomena: kod reg. indirektnog mogu se samo koristiti registri BX, SI, DI. Kod indeksnog samo registri
BX, BP, SI, DI.

Funkcije generatora koda

1) Izbor naredbi (instruction selection)


 Mapiranje IR u mašinski kod
 Podrazumeva se fiksirano mapiranje promenljivih u memoriju i neograničen broj registara
 Problem izbora operacija, načina adresiranja

2) Raspoređivanje naredbi (instruction scheduling)


 Promena redosleda naredbi da se smanje kašnjenja, upotreba registara i slično
 Podrazumeva se fiksirani program, tj. skup instrukcija

3) Dodela registara (register allocation)


 Odlučivanje koje promenljive veličine idu u registre, generalnije, o mapiranju promenljivih u
memoriju i registre procesora
 Menja mapiranje promenljivih u memoriju, moguće je (privremeno) deljenje iste lokacije od strane
više promenljivih
Ove 3 funkcije su tesno povezane, što usložnjava posao generisanja koda.

Neki problemi generisanja koda

 neefikasan kod ako se pojedini iskazi posmatraju odvojeno:


Primer
Generisati mašinski kod za naredbe:
a=b+c
d=a+e
Generisani kod:
MOV AX, b
ADD AX, c
MOV a, AX } nepotrebno
MOV AX, a
ADD AX, e
MOV d, AX

 problem izbora naredbi.


Primer
Izraz a = a +1
može se prevesti na (bar) dva načina:
INC a MOV AX, a
ADD AX, 1
MOV a, AX
 problem dodele registara promenljivim, odnosno izbora skupa promenljivih koje će biti u registrima u
datoj tački izvršavanja programa, što ima neposredan odraz na efikasnost koda, odnosno broj pristupa
memoriji. Problem je NP kompletan (tj. alg. eksponencijalno zavisi od broja prom.)

Jednostavan algoritam generisanja koda za jedan bazični blok


Prema knjizi: Aho, Sethi, Ullman „Compilers/Principles, Techniques, and Tools”.

 u prvom koraku određuju se informacije o životu i sledećem korišćenju za svaku pojavu promenljivih u
bazičnom bloku.
Promenljiva x je živa u iskazu i programa ako postoji putanja do nekog iskaza j po kojoj se x ne menja, a u
iskazu j promenljiva x se koristi kao operand. Tada iskaz j predstavlja sledeće korišćenje promenjive x. U
suprotnom, za promenljivu x se kaže da je mrtva.

Postupak izračunavanja (unutar bazičnog bloka):


1. Ako se ne vrši globalna analiza, konzervativna pretpostavka je da su na izlazu iz bazičnog bloka sve
korisničke promenljive žive, a privremene mrtve (postoje izuzeci). Ove informacije sačuvamo u tabeli
simbola (T.S) za svaku promenljivu.
2. Iskazi u bazičnom bloku obrađuju se redosledom od poslednjeg ka prvom. Kada naiđemo na i-tu
četvorku
i. x := y op z ;
iz T.S. pokupimo informacije o x, y, z i prikačimo i-toj četvorci.
u T.S. ažuriramo x = (m , -), to jest, x je mrtvo i nema sledeće korišćenje
u T.S. ažuriramo: y, z = (ž , i), to jest, y i z su živi a iskaz i predstavlja sled. kor.

Primer
Generisati mašinski kod za sledeću instrukciju :
d := (a – b) + (a – c) + (a – c).

Međukod : 1. t := a – b t = (ž , 3) a = (ž , 2) b = (ž , -)
2. u := a – c u = (ž , 3) a = (ž , -) c = (ž , -)
3. v := t + u v = (ž , 4) t = (m , -) u = (ž , 4)
4. d := v + u d = (ž , -) v = (m , -) u = (m , -)

Tabela simbola
a b c d t u v
(ž , -) (ž , -) (ž , -) (ž , -) (m , -) (m , -) (m , -)
(ž , 2) (ž , 1) (ž , 2) (m , -) (ž , 3) (ž , 4) (ž , 4)
(ž , 1) (m , -) (ž , 3) (m , -)
(m , -)
 Generator koda koristi desktriptor registra za svaki registar i desktriptor adresa za svaku promenljivu.
Deskriptor registara sadrži spisak imena promenljivih čije vrednosti se nalaze u pojedinim registrima
(na početku bloka prazan).
Primer : AX : a, b, c
Deskriptor adresa pokazuje u kojim se sve registrima i memorijskim lokacijama nalazi vrednost neke
promenljive (na početku bloka sve korisničke prom. su u memoriji)
Primer : a : AX, BX, a’

Algoritam generisanja koda za i) x := y op z

1. Poziva se potprogram getreg da bi se dobila lokacija L u koji će biti smešten rezultat x. Obično funkcija
vraća registar, a ređe fizičku lokaciju operativne memorije
2. Ako y nije u L onda se generiše mašinska instrukcija:
MOV L, y’
gde je y' tekuća lokacija za y (najbolje ako je neki registar).
3. Generiše se mašinska instrukcija
op L, z’
gde je z' tekuća lokacija za z (najbolje ako je neki registar).
Dodati L u adresni deskriptor za x. Ako je L registar, dodati x u reg. deskriptor za L.
4. Ako y i z nisu živi u i-toj četvorci, udaljiti ih iz deskriptora registara u kojima se trenutno nalaze.
5. Posle procesiranja svih četvorki, na kraju bazičnog bloka, generisati instrukciju:
MOV m, R
za sve promenljive koje su žive, a nalaze se isključivo u nekom od registara R.

Getreg (četvorka x:=y OP z , fleg da li je neophodan registar):izlaz: registar R ili mem. lokacija za y
1. Ako je y jedina promenljiva u nekom registru R i y je mrtvo u posmatranoj četvorci, izbaciti R iz adr.
deskriptora za y i vratiti R
2. Ako (1) ne uspe, vratiti prazan registar (ako ima takav).
3. Ako (2) ne uspe, i ako x ima sledeću upotrebu u tom bloku ili ako je op operator koji obavezno zahteva
registar (npr. indeksiranje) pronaći neki zauzeti registar. Sa MOV upisati u memoriju vrednosti svih
promenljivih iz R koje nisu u mem., izbaciti R iz adr. deskriptora tih promenljivih i vratiti R.
4. Ako tačka (3) ne uspe, vratiti memorijsku lokaciju za x.

- Za raniji primer :

četvorke mašinski kod Deskriptori registara Adresni deskriptori


registri prazni a, b, c i d u memoriji
t := a - b MOV AX, a’
SUB AX, b’ AX sadrži t t u AX, a, b, c u memoriji
u := a - c MOV BX, a’ AX sadrži t t u AX, a, b, c u memoriji
SUB BX, c’ BX sadrži u u u BX
v := t + u ADD AX, BX AX sadrži v u u BX, a, b, c u memoriji
BX sadrži u v u AX
d := v + u ADD AX, BX AX sadrži d d u AX, a, b, c u memoriji
MOV d’, AX registri prazni za a, b, c u memoriji
novi bazični blok

Pravila generisanje koda za pristup elementima niza:


Naredba i je u registru R i je u memoriji M i je na steku, pomeraj di
Kod Cena Kod Cena Kod Cena
a:=b[i] MOV R’, [b+R] 2 MOV R, M 4 MOV R, [BP+di] 4
MOV R, [R+b] MOV R, [R+b]
a[i]:=b MOV [a+R], b 3 MOV R, M 5 MOV R, [BP+di] 5
MOV [R+a], b MOV [R+a], b

Pravila generisanja koda pri upotrebi pokazivača:


Naredba p je u registru R p je u memoriji M p je na steku,pomeraj dp
Kod Cena Kod Cena Kod Cena
a:=*p MOV a, [R] 2 MOV R, M 3 MOV R, [BP+dp] 3
MOV R, [R] MOV R, [R]
*p:=a MOV [R], a 2 MOV R, M 4 MOV R, [BP+dp] 4
MOV [R], a MOV [R], a

You might also like