Professional Documents
Culture Documents
Arhitektura LR parsera
ulaznog bafera
steka koji čuva stanja
tabele prelazaka (goto table) koja nam govori koje je novo stanje
tabele akcija (action table) koj nam govori koju kaciju treba uraditi za dato tekuće stanje i
dati terminalni simbol na ulazu
Algoritam parsiranja
LR parser čita ulaz slijeva udesno ali treba da napravi desnu derivaciju, pa zbog toga koristi
redukciju umjesto derivacije. Algoritam kreira "leftmost redukciju" ulaznog niza, pa je krajnji
rezultat obrnuta desna derivacija.
Algoritam:
1. Stek se inicijalizuje sa stanjem [0]. Tekuće stanje je uvijek ono koje je na vrhu steka.
2. Za dato tekuće stanje i dati ulazni simbol provjeravamo tabelu akcija. Postoje 4 mogućnosti:
o shift sn:
tekući simbol se uklanja iz ulaznog niza
stanje n se stavlja na stek (operacija push) i postaje tekuće stanje
o reduce rm:
broj m se upisuje u izlazni tok (ovo je samo radi evidencije)
za svaki simbol sa desne strane pravila m gramatike uklanjamo po jedan
simbol sa steka (operacija pop)
za stanje koje je na vrhu steka i lijevu stranu pravila m gramatike pogledamo
odgovarajuće polje u tabeli prelazaka i stanje iz tog polja upišemo na stek
o acc - string je prihvaćen (accepted)
o nema akcija (prazno polje) - prijavljujemo sintaksnu grešku
3. Ponavljamo korak 2 sve dok string ne bude prihvaćen ili dok se prijavi greška
Primjer
(1) E → E * B
(2) E → E + B
(3) E → B
(4) B → 0
(5) B → 1
1+1
action goto
state * + 0 1 $ E B
0 s1 s2 3 4
1 r4 r4 r4 r4 r4
2 r5 r5 r5 r5 r5
3 s5 s6 acc
4 r3 r3 r3 r3 r3
5 s1 s2 7
6 s1 s2 8
7 r1 r1 r1 r1 r1
8 r2 r2 r2 r2 r2
Redovi tabela označeni su stanjima parsera. Kolone tabele akcija terminalni simboli (uključujući
specijalni simbol $ koji označava kraj ulaznog niza). Akcije u toj tabeli mogu biti:
Kolone tabele prelazaka su neterminalni simboli gramatike a polja te tabele sadrže stanja parsera.
Stanje u toj tabeli znači da je ono sljedeće stanje parsera kada se prepozna određeni netreminalni
simbol.
Procedura parsiranja
Parser počinje rad sa stekom koji sadrži samo početno stanje ('0'):
[0]
Prvi simbol u ulaznom nizu je '1'. U polju Action[0,1] () je tekuće stanje a 1 je tekući simbol) stoji
s2, tj. akcija je shift 2, p se stanje 2 stavlja na stek i prelazimo na sljedeći ulazni simbol (tj. +).
Rezultujući stek je
[0 '1' 2]
gdje je 2 na vrhu steka. Zbog lakšeg praćenja postupka pokazujemo i simbol (npr. '1', B) koji je
uzrok prelaska u sljedeće stanje, iako formalno on nije dio steka.
Posmatramo polje Action[2,+] u kome je r5, tj. redukcija pravila 5. Intuitivno, to yna;I da je parser
prepoynao desnu stranu produkcije 5, što se zaista i desilo. Upisujemo 5 u izlazni niz, uklanjamo
jedno stanje sa steka (jer sa desne strane pravila 5 imamo samo jedan simbol). Sada je satnje 0 na
vrhu steka pa provjeravamo polje Goto[0,B], jer je B desna strana pravila 5. Kako u polju Goto[0,B]
upisano 4, na stek stavljamo stanje 4. Rezultujući stek je:
[0 B 4]
Sada provjeravamo polje Action[4,+], u kome piše r3. Upisujemo 3 u izlazni niz i uklanjamo jedno
stanje sa steka (jer desna strana pravila 5 ima jedan simbol). Sada je na vrhu steka stanje 0, pa
provjeravamo polje Goto[0,E], jer je E desna strana pravila 3. U tom polju je stanje 3, pa to stanje
stavljamo na stek i ono postaje novo tekuće stanje.
[0 E 3]
Provjeravamo polje Action[3,’+’] u kojem je s6, pa stavljamo stanje 6 na stek. Stek ima sljedeći
izgled:
[0 E 3 '+' 6]
Primjetite da ovako napisan stek možete posmatrati kao istorijat rada konačnog automata koji je
“pročitao” neterminal E a zatim terminal ‘+’. Tabela prelazaka tog automata definisina je shift-
akcijama tabele akcija i goto-akcijama tabele prelazaka.
Sljedeći simbol na ulazu je '1', pa posmatramo polje Action[6,’1’]=s2, što znači da vršimo shift tj.
stanje 2 stavljamo na vrh steka i prelazimo na sljedeći simbol u ulaznom nizu:
[0 E 3 '+' 6 '1' 2]
Kako je Action[2,$]=r5, vršimo redukcija pravila 5 tj. uklanjamo 2 sa steka, Goto[6,B]=8,a
postavljamo 8 na vrh steka i dobijamo:
[0 E 3 '+' 6 B 8]
U stanju 8 uvijek vršimo redukciju (Action[8,$]=r2). Kako desna strana produkcije 2 ima tri
simbola (dva neterminalna i jedan treminalni), sa steka uklanjamo tri stanja tj. 8, 6 i 3. Sda je na
vrhu steka 0, pa posmatramo polje Goto[0,E] jer je E lijeva strana pravila 2. Kako je Goto[0,E]=3,
na stek stavljamo stanje 3, pa sada stek ima izgled:
[0 E 3]
Kona;no, čitamo '$' iz ulaznog niza a koako je Action[3,$]=acc, ulazni string se prihvata. Izlazni
string nam pokazuje redosljed primjene pravila gramatike obrnut desnoj derivaciji ulaznog stringa.
E→•E+B
E→E•+B
E→E+•B
E→E+B•
Pravila oblika A → ε imaju samo jedan ajtem A → •. Ovi ajtemi označavaju stanja parsera. Npr.
ajtem E → E • + B, označava da je parser prepoznao string koji odgovara neterminalnom simbolu E
i očekuje da pročita simbol '+' a zatim i ostatak stringa koji bi trebalo da odgovara neterminalnom
simbolu B.
Skupovi ajtema
Najčešće nije moguće opisati stanje parsera samo jednim ajtemom jer nije moguće unaprijed znati
koje će pravilo biti primjenjeno za redukciju. Npr. ako postoji i pravilo E → E * B, tada oba ajtema
E → E • + B i E → E • * B mogu biti primjenjena pošto se pročita string koji odgovara neterminalu
E. Zbog toga će ova dva ajtema biti u istom stanju tj. skupu { E → E • + B, E → E • * B }.
Ako u skup ajtema postoji ajtem oblika A → v • Bw i ako u gramatici postoji pravilo oblika B → w'
tada i ajtem B → • w' treba dodati u skup ajtema. Dodavanje ajtema nastaviti sve dok je to moguće.
Na taj način dobija se zatvorenje skupa ajtema (slično tranzitivnom zatvorenju grafa).
Proširena gramatika
Prije nego što počnemo da određujemo skupove ajteme (tj. stanja parsera), u gramatiku dodajemo
novo pravilo
(0) S → E
(0) S → E
(1) E → E * B
(2) E → E + B
(3) E → B
(4) B → 0
(5) B → 1
Konstrukcija tabele
U skup S0 dodajemo ajtem S → • E i tražimo njegovo zatvorenje:
S0 : S → • E
S0 : S → • E
E→•E*B
E→•E+B
E → • B,
B→•0
B→•1
Počevši sa stanjem S0, odredićemo skup prelasaka iz ovog stanja u druga stanja. Posmatramo sve
simbole (terminalne i neterminalne) koji se nalaze desno od simbola •. Procedura za prelaske je
sljedeća:
Za terminal '0' odredimo Prelazak(S0, ‘0’) B → 0 • (simbol • nalazi se samo ispred simbola 0 u
petom ajtemu u skupu S0). Zatim odredimo zatvorenje ajtema B → 0 • , što daje skup S1:
S1
B→0•
S2
B→1•
S3
S→E•
E→E•*B
E→E•+B
S4
E→B•
Primjetite da u ovom slučaju zatvorenje nije dodalo nove ajteme. Nastavaljamo ovak postupak sve
dok moženo dodavati nove skupove ajtema. Z skupove S1, S2 i S4 nema prelaza, jer se simbol •
nalazi na kraju (krajnji desni simbol). Za skup S3 moguće je napraviti prelaske na simbole '*' i '+'.
Tako za simbol '*' dobijamo:
S5
E→E*•B
B → • 0 /* dodato zbog E → E * • B */
B → • 1 /* dodato zbog E → E * • B */
S6
E→E+•B
B → • 0 /* dodato zbog E → E + • B */
B → • 1 /* dodato zbog E → E + • B */
Iz skupa S5 možemo preći na terminale '0' i '1' i na neterminal B. Lako se vidi da je Prelazak(S5,
'0' ) = S1 i Prelazak(S5, '1' ) = S2. Za neterminal B imamo Prelazak(S5, B):
S7
E→E*B•
Iz skupa S6 možemo preći na terminale '0' i '1' i na neterminal B. Lako se vidi da je Prelazak(S6,
'0')=S1 i Prelazak(S6, '1' ) = S2. Za neterminal B imamo Prelazak(S6, B):
S8
E→E+B•
Skup * + 0 1 E B
0 1 2 3 4
3 5 6
5 1 2 7
6 1 2 8
Konflikti
Moguća su dva tipa konflikata: shift-reduce conflict i reduce-reduce conflict. Ako se to dogodi
kažemo da grmatika nije LR(0) gramatika.
(1) E → 1 E
(2) E → 1
S1
E→1•E
E→1•
E→•1E
E→•1
(1) E → A 1
(2) E → B 2
(3) A → 1
(4) B → 1
S1
A→1•
B→1•
LR(0) primjer
Primjer gramatike (u Bison notaciji):
0) S: stmt
1) stmt: ID ':=' expr
2) expr: expr '+' ID
3) expr: expr '-' ID
4) expr: ID
Stanje 1
1) stmt: ID • ':=' expr
SHIFT 3 on ':='
Stanje 2
0) S: stmt •
SHIFT 4 on
Stanje 3
1) stmt: ID ':=' • expr
2) expr: • expr '+' ID
3) expr: • expr '-' ID
4) expr: • ID
GOTO 6 on expr
SHIFT 5 on ID
Stanje 4
0) $S: stmt •
Stanje 5
4) expr: ID •
Stanje 6
1) stmt: ID ':=' expr •
2) expr: expr • '+' ID
3) expr: expr • '-' ID
SHIFT 7 on '+'
SHIFT 8 on '-'
Stanje 7
2) expr: expr '+' • ID
SHIFT 9 on ID
Stanje 8
3) expr: expr '-' • ID
SHIFT 10 on ID
Stanje 9
2) expr: expr '+' ID •
Stanje 10
3) expr: expr '-' ID •
Tabele parsera
Tabele parsera
Akcije Prelasci
ID ':=' '+' '-' <EOF> stmt expr
0 s1 g2
1 s3
2 s4
3 s5 g6
4 acc acc acc acc acc
5 r4 r4 r4 r4 r4
6 r1 r1 s7 s8 r1
7 s9
8 s10
9 r2 r2 r2 r2 r2
10 r3 r3 r3 r3 r3
(0) S → E
(1) E → 1 E
(2) E → 1
S0
S→•E
E→•1E
E→•1
S1
E→1•E
E→1•
E→•1E
E→•1
S2
S→E•
S3
E→1E•
action goto
stanje 1 $ E
0 s1 2
1 s1/r2 r2 3
2 acc
3 r1 r1
action goto
state 1 $ E
0 s1 2
1 s1 r2 3
2 acc
3 r1